Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/explorer/src/comps/DataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function DataGrid(props: DataGrid.Props) {
loading = false,
countLoading = false,
disableLastPage = false,
hasMore,
itemsLabel = 'items',
itemsPerPage = 10,
pagination = 'default',
Expand Down Expand Up @@ -157,10 +158,11 @@ export function DataGrid(props: DataGrid.Props) {
<div className="flex flex-col items-center sm:flex-row sm:justify-between gap-[12px] border-t border-dashed border-card-border px-[16px] py-[12px] text-[12px] text-tertiary">
<Pagination.Simple
page={page}
totalPages={totalPages}
totalPages={displayCount === Infinity ? 0 : totalPages}
fetching={fetching && !loading}
countLoading={countLoading}
disableLastPage={disableLastPage}
hasMore={hasMore}
/>
{/* Show transaction count - loading state shown while fetching */}
<Pagination.Count
Expand Down Expand Up @@ -226,5 +228,6 @@ export namespace DataGrid {
pagination?: 'default' | 'simple'
emptyState?: React.ReactNode
flexible?: boolean
hasMore?: boolean
}
}
33 changes: 22 additions & 11 deletions apps/explorer/src/comps/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,15 @@ export namespace Pagination {
}

export function Simple(props: Simple.Props) {
const { page, totalPages, fetching, countLoading, disableLastPage } = props
const {
page,
totalPages,
fetching,
countLoading,
disableLastPage,
hasMore,
} = props
const canGoNext = totalPages > 0 ? page < totalPages : hasMore
return (
<div className="flex items-center justify-center sm:justify-start gap-[6px]">
<Link
Expand Down Expand Up @@ -267,13 +275,13 @@ export namespace Pagination {
Page{' '}
<span className={fetching ? 'opacity-50' : undefined}>
{Pagination.numFormat.format(page)}
</span>{' '}
of{' '}
{countLoading
? '…'
: totalPages > 0
? Pagination.numFormat.format(totalPages)
: '…'}
</span>
{totalPages > 0 && (
<>
{' '}
of {countLoading ? '…' : Pagination.numFormat.format(totalPages)}
</>
)}
</span>
<Link
to="."
Expand All @@ -283,7 +291,7 @@ export namespace Pagination {
page: (prev?.page ?? 1) + 1,
live: false,
})}
disabled={page >= totalPages}
disabled={!canGoNext}
className={cx(
'rounded-full border border-base-border hover:bg-alt flex items-center justify-center cursor-pointer active:translate-y-[0.5px] aria-disabled:cursor-not-allowed aria-disabled:opacity-50 size-[24px] text-primary',
)}
Expand All @@ -295,7 +303,7 @@ export namespace Pagination {
to="."
resetScroll={false}
search={(prev) => ({ ...prev, page: totalPages, live: false })}
disabled={page >= totalPages || disableLastPage}
disabled={page >= totalPages || disableLastPage || totalPages === 0}
className={cx(
'rounded-full border border-base-border hover:bg-alt flex items-center justify-center cursor-pointer active:translate-y-[0.5px] aria-disabled:cursor-not-allowed aria-disabled:opacity-50 size-[24px] text-primary',
)}
Expand All @@ -315,12 +323,15 @@ export namespace Pagination {
countLoading?: boolean
/** Disable "Last page" button when we can't reliably navigate there */
disableLastPage?: boolean
hasMore?: boolean
}
}

export function Count(props: Count.Props) {
const { page, totalPages, totalItems, itemsLabel, loading, className } =
props
const displayCount =
totalItems > 1000 ? '1000+' : Pagination.numFormat.format(totalItems)
return (
<div
className={cx(
Expand All @@ -338,7 +349,7 @@ export namespace Pagination {
</>
)}
<span className="text-primary tabular-nums">
{loading ? '…' : Pagination.numFormat.format(totalItems)}
{loading ? '…' : displayCount}
</span>
<span className="text-tertiary">{itemsLabel}</span>
</div>
Expand Down
82 changes: 82 additions & 0 deletions apps/explorer/src/lib/queries/address-events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { keepPreviousData, queryOptions } from '@tanstack/react-query'
import type { Address, Hex } from 'ox'

export type AddressEventData = {
txHash: Hex.Hex
blockNumber: Hex.Hex
blockTimestamp: number | null
logIndex: number
contractAddress: Address.Address
topics: Hex.Hex[]
data: Hex.Hex
}

export type AddressEventsApiResponse = {
events: AddressEventData[]
total: number
offset: number
limit: number
hasMore: boolean
error: null | string
}

type AddressEventsRequestParameters = {
offset: number
limit: number
}

export function addressEventsQueryOptions(
params: {
page: number
address: Address.Address
} & AddressEventsRequestParameters,
) {
const searchParams = new URLSearchParams({
limit: params.limit.toString(),
offset: params.offset.toString(),
})
return queryOptions({
queryKey: [
'account-events',
params.address,
params.page,
params.limit,
params.offset,
],
queryFn: async (): Promise<AddressEventsApiResponse> => {
const response = await fetch(
`${__BASE_URL__}/api/address/events/${params.address}?${searchParams}`,
)
const data = await response.json()
return data as AddressEventsApiResponse
},
staleTime: 10_000,
refetchInterval: false,
refetchOnWindowFocus: false,
placeholderData: keepPreviousData,
})
}

export type AddressEventsData = Awaited<
ReturnType<NonNullable<ReturnType<typeof addressEventsQueryOptions>['queryFn']>>
>

export type AddressEventsCountResponse = {
data: number | null
isExact: boolean
error: string | null
}

export function addressEventsCountQueryOptions(address: Address.Address) {
return queryOptions({
queryKey: ['address-events-count', address],
queryFn: async (): Promise<AddressEventsCountResponse> => {
const response = await fetch(
`${__BASE_URL__}/api/address/events-count/${address}`,
)
return response.json() as Promise<AddressEventsCountResponse>
},
staleTime: 60_000,
retry: false,
})
}
43 changes: 43 additions & 0 deletions apps/explorer/src/routeTree.gen.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading