Skip to content
Merged
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions apps/explorer/src/comps/DataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as React from 'react'
import { Pagination } from '#comps/Pagination'
import { Sections } from '#comps/Sections'
import { cx } from '#lib/css'
import { useNewLiveRows } from '#lib/use-new-live-rows'
import ChevronDownIcon from '~icons/lucide/chevron-down'

export function DataGrid(props: DataGrid.Props) {
Expand Down Expand Up @@ -56,6 +57,10 @@ export function DataGrid(props: DataGrid.Props) {
}),
}))
: items(mode)
const newLiveRows = useNewLiveRows(
activeItems.map((item) => item.key),
effectiveLoading ? undefined : props.liveScope,
)
const pages = pagesProp ?? Math.ceil(totalItems / itemsPerPage)
const isSimpleSinglePage =
pagination === 'simple' &&
Expand Down Expand Up @@ -145,6 +150,9 @@ export function DataGrid(props: DataGrid.Props) {
'hover:bg-surface-hover transition-colors duration-100',
item.expanded && 'border-l-distinct',
item.className,
item.key !== undefined &&
newLiveRows.has(item.key) &&
'block-row-shimmer',
)}
>
{item.link && (
Expand Down Expand Up @@ -278,6 +286,8 @@ export namespace DataGrid {
}

export interface Props {
/** Enables new-row highlights, resetting when the feed scope changes. */
liveScope?: string | undefined
columns: {
stacked: Column[]
tabs: Column[]
Expand Down
9 changes: 9 additions & 0 deletions apps/explorer/src/lib/live-feed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function liveFeedSecondsLeft(
session: { scope: string; deadline: number } | null,
scope: string,
eligible: boolean,
now: number,
): number {
if (!eligible || !session || session.scope !== scope) return 0
return Math.max(0, Math.ceil((session.deadline - now) / 1_000))
}
48 changes: 48 additions & 0 deletions apps/explorer/src/lib/live-query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as z from 'zod/mini'
import { zAddress } from './zod'

export const liveQuerySchema = z.object({
address: zAddress({ lowercase: true }),
kind: z.enum(['token-transfers', 'account-transfers', 'transactions']),
limit: z.prefault(z.coerce.number().check(z.int(), z.gte(1), z.lte(200)), 10),
account: z.optional(zAddress({ lowercase: true })),
direction: z.optional(z.enum(['in', 'out'])),
include: z.prefault(z.enum(['all', 'sent', 'received']), 'all'),
status: z.optional(z.enum(['success', 'reverted'])),
after: z.optional(
z.coerce.number().check(z.int(), z.gte(0), z.lte(253402300799)),
),
hideSubmitBatches: z.optional(z.enum(['true', 'false'])),
})
export type LiveQuery = z.infer<typeof liveQuerySchema>
export function buildLiveQueries(options: LiveQuery): string[] {
const { address, kind, limit } = options
if (kind === 'transactions') {
const sides =
options.include === 'sent'
? ['from']
: options.include === 'received'
? ['to']
: ['from', 'to']
return sides.map(
(side) =>
`SELECT hash, block_num, idx FROM txs WHERE "${side}" = '${address}'${options.after ? ` AND block_timestamp >= '${new Date(options.after * 1000).toISOString()}'` : ''} ORDER BY block_num DESC, idx DESC LIMIT ${Math.min(limit, 10)}`,
)
}
const account = kind === 'account-transfers' ? address : options.account
const filters = [
"topic0 = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'",
]
if (kind === 'token-transfers') filters.push(`address = '${address}'`)
const sides = !account
? [undefined]
: options.direction === 'in'
? ['topic2']
: options.direction === 'out'
? ['topic1']
: ['topic1', 'topic2']
return sides.map(
(side) =>
`SELECT address, block_num, tx_hash, log_idx, block_timestamp, topic0, topic1, topic2, data FROM logs WHERE ${[...filters, ...(side && account ? [`${side} = '0x${account.slice(2).padStart(64, '0')}'`] : [])].join(' AND ')} ORDER BY block_num DESC, log_idx DESC LIMIT ${limit}`,
)
}
6 changes: 4 additions & 2 deletions apps/explorer/src/lib/server/address-history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ import { isZonePortalAddress } from '#lib/domain/zones'
export const [MAX_LIMIT, DEFAULT_LIMIT] = [10, 10]
const HISTORY_TOTAL_CACHE_TTL = 60_000
const HISTORY_TOTAL_CACHE_MAX_ENTRIES = 50
const SUBMIT_BATCH_SELECTOR = toFunctionSelector(
export const SUBMIT_BATCH_SELECTOR = toFunctionSelector(
getAbiItem({ abi: zonePortalAbi, name: 'submitBatch' }),
)

export type EnrichedTransaction = {
hash: `0x${string}`
blockNumber: string
transactionIndex?: number | undefined
timestamp: number
from: `0x${string}`
to: `0x${string}` | null
Expand Down Expand Up @@ -312,7 +313,7 @@ async function fetchFilteredHistoryPage(
* Resolves TIP-20 metadata for every token referenced by the page's event
* logs (symbol/decimals for the known-event summaries).
*/
async function buildTokenMetadataLookup(
export async function buildTokenMetadataLookup(
rows: readonly TransactionRow[],
): Promise<(address: Address.Address) => Metadata | undefined> {
const config = getWagmiConfig()
Expand Down Expand Up @@ -394,6 +395,7 @@ export function toEnrichedTransaction(
return {
hash: row.hash,
blockNumber: toHexQuantity(row.blockNumber),
transactionIndex: row.transactionIndex ?? undefined,
timestamp: parseTimestamp(row.timestamp) ?? 0,
from: Address.checksum(row.sender),
to,
Expand Down
Loading
Loading