From 9301a4edb4f3c16afb1769f02cf8c3bc96069564 Mon Sep 17 00:00:00 2001 From: "Tanishq Sharma (Tani)" Date: Tue, 27 Jan 2026 15:20:32 -0500 Subject: [PATCH 1/5] feat(explorer): add homepage network stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add /api/stats endpoint for network metrics - Add NetworkStats component below spotlight pills - Shows txns/24h, tokens count, accounts/24h - Uses block_num filtering (24h ≈ 172,800 blocks at 0.5s/block) Amp-Thread-ID: https://ampcode.com/threads/T-019c00e5-b80d-7485-872a-c46d5bb31aeb Co-authored-by: Amp --- apps/explorer/src/comps/NetworkStats.tsx | 80 ++++++++++++++++ apps/explorer/src/routeTree.gen.ts | 21 +++++ apps/explorer/src/routes/_layout/index.tsx | 2 + apps/explorer/src/routes/api/stats.ts | 103 +++++++++++++++++++++ 4 files changed, 206 insertions(+) create mode 100644 apps/explorer/src/comps/NetworkStats.tsx create mode 100644 apps/explorer/src/routes/api/stats.ts diff --git a/apps/explorer/src/comps/NetworkStats.tsx b/apps/explorer/src/comps/NetworkStats.tsx new file mode 100644 index 00000000..b8264a18 --- /dev/null +++ b/apps/explorer/src/comps/NetworkStats.tsx @@ -0,0 +1,80 @@ +import { useQuery } from '@tanstack/react-query' +import { getApiUrl } from '#lib/env' +import { TOKEN_COUNT_MAX } from '#lib/constants' +import type { StatsApiResponse } from '#routes/api/stats' + +async function fetchStats(): Promise { + const response = await fetch(getApiUrl('/api/stats'), { + credentials: 'same-origin', + }) + if (!response.ok) throw new Error('Failed to fetch stats') + const json: StatsApiResponse = await response.json() + if (json.error) throw new Error(json.error) + return json.data +} + +function formatNumber(num: number, max?: number): string { + if (max && num >= max) return `${(max / 1000).toFixed(0)}K+` + if (num >= 1_000_000) return `${(num / 1_000_000).toFixed(1)}M` + if (num >= 1_000) return `${(num / 1_000).toFixed(1)}K` + return num.toLocaleString() +} + +export function NetworkStats() { + const { data, isLoading } = useQuery({ + queryKey: ['network-stats'], + queryFn: fetchStats, + staleTime: 60 * 1000, + refetchInterval: 60 * 1000, + }) + + if (isLoading || !data) { + return ( +
+ Loading... +
+ ) + } + + const hasAnyData = + data.transactions24h > 0 || data.tokens > 0 || data.accounts24h > 0 + + if (!hasAnyData) return null + + return ( +
+
+
+ {data.transactions24h > 0 && ( + + )} + {data.tokens > 0 && ( + + )} + {data.accounts24h > 0 && ( + + )} +
+
+ ) +} + +function StatItem(props: { value: string; label: string }) { + return ( +
+ + {props.value} + + {props.label} +
+ ) +} diff --git a/apps/explorer/src/routeTree.gen.ts b/apps/explorer/src/routeTree.gen.ts index b11e86b7..95a566c4 100644 --- a/apps/explorer/src/routeTree.gen.ts +++ b/apps/explorer/src/routeTree.gen.ts @@ -11,6 +11,7 @@ import { Route as rootRouteImport } from './routes/__root' import { Route as LayoutRouteImport } from './routes/_layout' import { Route as LayoutIndexRouteImport } from './routes/_layout/index' +import { Route as ApiStatsRouteImport } from './routes/api/stats' import { Route as ApiSearchRouteImport } from './routes/api/search' import { Route as ApiHealthRouteImport } from './routes/api/health' import { Route as ApiCodeRouteImport } from './routes/api/code' @@ -46,6 +47,11 @@ const LayoutIndexRoute = LayoutIndexRouteImport.update({ path: '/', getParentRoute: () => LayoutRoute, } as any) +const ApiStatsRoute = ApiStatsRouteImport.update({ + id: '/api/stats', + path: '/api/stats', + getParentRoute: () => rootRouteImport, +} as any) const ApiSearchRoute = ApiSearchRouteImport.update({ id: '/api/search', path: '/api/search', @@ -184,6 +190,7 @@ export interface FileRoutesByFullPath { '/api/code': typeof ApiCodeRoute '/api/health': typeof ApiHealthRoute '/api/search': typeof ApiSearchRoute + '/api/stats': typeof ApiStatsRoute '/address/$address': typeof LayoutAddressAddressRoute '/block/$id': typeof LayoutBlockIdRoute '/demo/address': typeof LayoutDemoAddressRoute @@ -211,6 +218,7 @@ export interface FileRoutesByTo { '/api/code': typeof ApiCodeRoute '/api/health': typeof ApiHealthRoute '/api/search': typeof ApiSearchRoute + '/api/stats': typeof ApiStatsRoute '/': typeof LayoutIndexRoute '/address/$address': typeof LayoutAddressAddressRoute '/block/$id': typeof LayoutBlockIdRoute @@ -241,6 +249,7 @@ export interface FileRoutesById { '/api/code': typeof ApiCodeRoute '/api/health': typeof ApiHealthRoute '/api/search': typeof ApiSearchRoute + '/api/stats': typeof ApiStatsRoute '/_layout/': typeof LayoutIndexRoute '/_layout/address/$address': typeof LayoutAddressAddressRoute '/_layout/block/$id': typeof LayoutBlockIdRoute @@ -272,6 +281,7 @@ export interface FileRouteTypes { | '/api/code' | '/api/health' | '/api/search' + | '/api/stats' | '/address/$address' | '/block/$id' | '/demo/address' @@ -299,6 +309,7 @@ export interface FileRouteTypes { | '/api/code' | '/api/health' | '/api/search' + | '/api/stats' | '/' | '/address/$address' | '/block/$id' @@ -328,6 +339,7 @@ export interface FileRouteTypes { | '/api/code' | '/api/health' | '/api/search' + | '/api/stats' | '/_layout/' | '/_layout/address/$address' | '/_layout/block/$id' @@ -355,6 +367,7 @@ export interface RootRouteChildren { ApiCodeRoute: typeof ApiCodeRoute ApiHealthRoute: typeof ApiHealthRoute ApiSearchRoute: typeof ApiSearchRoute + ApiStatsRoute: typeof ApiStatsRoute ApiAbiBatchRoute: typeof ApiAbiBatchRoute ApiAddressAddressRoute: typeof ApiAddressAddressRoute ApiTokensCountRoute: typeof ApiTokensCountRoute @@ -381,6 +394,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof LayoutIndexRouteImport parentRoute: typeof LayoutRoute } + '/api/stats': { + id: '/api/stats' + path: '/api/stats' + fullPath: '/api/stats' + preLoaderRoute: typeof ApiStatsRouteImport + parentRoute: typeof rootRouteImport + } '/api/search': { id: '/api/search' path: '/api/search' @@ -603,6 +623,7 @@ const rootRouteChildren: RootRouteChildren = { ApiCodeRoute: ApiCodeRoute, ApiHealthRoute: ApiHealthRoute, ApiSearchRoute: ApiSearchRoute, + ApiStatsRoute: ApiStatsRoute, ApiAbiBatchRoute: ApiAbiBatchRoute, ApiAddressAddressRoute: ApiAddressAddressRoute, ApiTokensCountRoute: ApiTokensCountRoute, diff --git a/apps/explorer/src/routes/_layout/index.tsx b/apps/explorer/src/routes/_layout/index.tsx index 3726ad21..78ed8b8d 100644 --- a/apps/explorer/src/routes/_layout/index.tsx +++ b/apps/explorer/src/routes/_layout/index.tsx @@ -9,6 +9,7 @@ import { waapi, stagger } from 'animejs' import type { Address, Hex } from 'ox' import * as React from 'react' import { ExploreInput } from '#comps/ExploreInput' +import { NetworkStats } from '#comps/NetworkStats' import { cx } from '#lib/css' import { springInstant, springBouncy, springSmooth } from '#lib/animation' import { Intro, type IntroPhase, useIntroSeen } from '#comps/Intro' @@ -158,6 +159,7 @@ function Component() { /> + ) diff --git a/apps/explorer/src/routes/api/stats.ts b/apps/explorer/src/routes/api/stats.ts new file mode 100644 index 00000000..848aea65 --- /dev/null +++ b/apps/explorer/src/routes/api/stats.ts @@ -0,0 +1,103 @@ +import { createFileRoute } from '@tanstack/react-router' +import * as IDX from 'idxs' +import { getChainId } from 'wagmi/actions' +import * as ABIS from '#lib/abis' +import { TOKEN_COUNT_MAX } from '#lib/constants' +import { getWagmiConfig } from '#wagmi.config.ts' + +const IS = IDX.IndexSupply.create({ + apiKey: process.env.INDEXER_API_KEY, +}) + +const QB = IDX.QueryBuilder.from(IS) + +// Average block time on Tempo is 0.5 seconds +const AVERAGE_BLOCK_TIME_SECONDS = 0.5 +const BLOCKS_PER_DAY = Math.floor((24 * 60 * 60) / AVERAGE_BLOCK_TIME_SECONDS) + +export type StatsApiResponse = { + data: { + transactions24h: number + tokens: number + accounts24h: number + } | null + error: string | null +} + +export const Route = createFileRoute('/api/stats')({ + server: { + handlers: { + GET: async () => { + try { + const config = getWagmiConfig() + const chainId = getChainId(config) + const tokenCreatedSignature = ABIS.getTokenCreatedEvent(chainId) + + // Get latest block number to calculate 24h ago + const latestBlockResult = await QB.selectFrom('blocks') + .select('num') + .where('chain', '=', chainId) + .orderBy('num', 'desc') + .limit(1) + .executeTakeFirst() + + const latestBlock = BigInt(latestBlockResult?.num ?? 0) + const block24hAgo = latestBlock - BigInt(BLOCKS_PER_DAY) + const block24hAgoSafe = block24hAgo < 0n ? 0n : block24hAgo + + // Run queries in parallel + const [tokensCountResult, txCount24hResult, accounts24hResult] = + await Promise.all([ + // Total tokens (capped) + QB.selectFrom( + QB.withSignatures([tokenCreatedSignature]) + .selectFrom('tokencreated') + .select((eb) => eb.lit(1).as('x')) + .where('chain', '=', chainId as never) + .limit(TOKEN_COUNT_MAX) + .as('subquery'), + ) + .select((eb) => eb.fn.count('x').as('count')) + .executeTakeFirst(), + + // Transactions in last 24h (by block number) + QB.selectFrom('txs') + .select((eb) => eb.fn.count('hash').as('count')) + .where('chain', '=', chainId) + .where('block_num', '>=', block24hAgoSafe) + .executeTakeFirst(), + + // Active accounts: sample recent txs and count unique senders + QB.selectFrom('txs') + .select(['from']) + .where('chain', '=', chainId) + .where('block_num', '>=', block24hAgoSafe) + .limit(50000) + .execute(), + ]) + + const uniqueAccounts = new Set( + accounts24hResult?.map((tx) => tx.from) ?? [], + ) + + return Response.json({ + data: { + transactions24h: Number(txCount24hResult?.count ?? 0), + tokens: Number(tokensCountResult?.count ?? 0), + accounts24h: uniqueAccounts.size, + }, + error: null, + } satisfies StatsApiResponse) + } catch (error) { + console.error('Failed to fetch stats:', error) + const errorMessage = + error instanceof Error ? error.message : 'Unknown error' + return Response.json( + { data: null, error: errorMessage } satisfies StatsApiResponse, + { status: 500 }, + ) + } + }, + }, + }, +}) From 162a6fbbccc3e35c511ef52191f51068242a2ec6 Mon Sep 17 00:00:00 2001 From: "Tanishq Sharma (Tani)" Date: Tue, 27 Jan 2026 15:50:47 -0500 Subject: [PATCH 2/5] feat(explorer): add network stats to homepage - Add /api/stats endpoint with 24h transactions, token count, and active accounts - Add NetworkStats component with loading and error states - Implement 60s server-side caching to avoid IndexSupply rate limits - Add thundering herd prevention and stale-while-error resilience Amp-Thread-ID: https://ampcode.com/threads/T-019c0131-d03f-7478-b89f-0afd1cf0725a Co-authored-by: Amp --- apps/explorer/src/comps/NetworkStats.tsx | 31 +++-- apps/explorer/src/routes/api/stats.ts | 168 +++++++++++++++-------- 2 files changed, 127 insertions(+), 72 deletions(-) diff --git a/apps/explorer/src/comps/NetworkStats.tsx b/apps/explorer/src/comps/NetworkStats.tsx index b8264a18..183f7390 100644 --- a/apps/explorer/src/comps/NetworkStats.tsx +++ b/apps/explorer/src/comps/NetworkStats.tsx @@ -4,9 +4,7 @@ import { TOKEN_COUNT_MAX } from '#lib/constants' import type { StatsApiResponse } from '#routes/api/stats' async function fetchStats(): Promise { - const response = await fetch(getApiUrl('/api/stats'), { - credentials: 'same-origin', - }) + const response = await fetch(getApiUrl('/api/stats')) if (!response.ok) throw new Error('Failed to fetch stats') const json: StatsApiResponse = await response.json() if (json.error) throw new Error(json.error) @@ -20,22 +18,29 @@ function formatNumber(num: number, max?: number): string { return num.toLocaleString() } -export function NetworkStats() { - const { data, isLoading } = useQuery({ +export function NetworkStats(): React.JSX.Element | null { + const { data, isLoading, isError } = useQuery({ queryKey: ['network-stats'], queryFn: fetchStats, - staleTime: 60 * 1000, - refetchInterval: 60 * 1000, + staleTime: 60_000, + gcTime: 5 * 60_000, + refetchInterval: 60_000, + retry: 2, }) - if (isLoading || !data) { + if (isLoading) { return ( -
- Loading... -
+
+
+
+ Loading stats... +
+
) } + if (isError || !data) return null + const hasAnyData = data.transactions24h > 0 || data.tokens > 0 || data.accounts24h > 0 @@ -68,9 +73,9 @@ export function NetworkStats() { ) } -function StatItem(props: { value: string; label: string }) { +function StatItem(props: { value: string; label: string }): React.JSX.Element { return ( -
+
{props.value} diff --git a/apps/explorer/src/routes/api/stats.ts b/apps/explorer/src/routes/api/stats.ts index 848aea65..7ad20543 100644 --- a/apps/explorer/src/routes/api/stats.ts +++ b/apps/explorer/src/routes/api/stats.ts @@ -15,6 +15,12 @@ const QB = IDX.QueryBuilder.from(IS) const AVERAGE_BLOCK_TIME_SECONDS = 0.5 const BLOCKS_PER_DAY = Math.floor((24 * 60 * 60) / AVERAGE_BLOCK_TIME_SECONDS) +// Cache stats for 60 seconds to avoid rate limiting +const CACHE_TTL_MS = 60_000 +let cachedStats: StatsApiResponse['data'] | null = null +let cacheTimestamp = 0 +let fetchInProgress: Promise | null = null + export type StatsApiResponse = { data: { transactions24h: number @@ -24,72 +30,116 @@ export type StatsApiResponse = { error: string | null } +async function fetchStatsFromIndexer(): Promise { + const config = getWagmiConfig() + const chainId = getChainId(config) + const tokenCreatedSignature = ABIS.getTokenCreatedEvent(chainId) + + // Get latest block number to calculate 24h window + const latestBlockResult = await QB.selectFrom('blocks') + .select('num') + .where('chain', '=', chainId) + .orderBy('num', 'desc') + .limit(1) + .executeTakeFirst() + + const latestBlock = BigInt(latestBlockResult?.num ?? 0) + const block24hAgo = latestBlock - BigInt(BLOCKS_PER_DAY) + const block24hAgoSafe = block24hAgo < 0n ? 0n : block24hAgo + + // Get token count + const tokensCountResult = await QB.selectFrom( + QB.withSignatures([tokenCreatedSignature]) + .selectFrom('tokencreated') + .select((eb) => eb.lit(1).as('x')) + .where('chain', '=', chainId as never) + .limit(TOKEN_COUNT_MAX) + .as('subquery'), + ) + .select((eb) => eb.fn.count('x').as('count')) + .executeTakeFirst() + + // Get transaction count (24h) + const txCount24hResult = await QB.selectFrom('txs') + .select((eb) => eb.fn.count('hash').as('count')) + .where('chain', '=', chainId) + .where('block_num', '>=', block24hAgoSafe) + .executeTakeFirst() + + // Get active accounts (sample recent txs and count unique senders) + const accounts24hResult = await QB.selectFrom('txs') + .select(['from']) + .where('chain', '=', chainId) + .where('block_num', '>=', block24hAgoSafe) + .limit(50_000) + .execute() + + const uniqueAccounts = new Set(accounts24hResult?.map((tx) => tx.from) ?? []) + + return { + transactions24h: Number(txCount24hResult?.count ?? 0), + tokens: Number(tokensCountResult?.count ?? 0), + accounts24h: uniqueAccounts.size, + } +} + export const Route = createFileRoute('/api/stats')({ server: { handlers: { GET: async () => { - try { - const config = getWagmiConfig() - const chainId = getChainId(config) - const tokenCreatedSignature = ABIS.getTokenCreatedEvent(chainId) - - // Get latest block number to calculate 24h ago - const latestBlockResult = await QB.selectFrom('blocks') - .select('num') - .where('chain', '=', chainId) - .orderBy('num', 'desc') - .limit(1) - .executeTakeFirst() - - const latestBlock = BigInt(latestBlockResult?.num ?? 0) - const block24hAgo = latestBlock - BigInt(BLOCKS_PER_DAY) - const block24hAgoSafe = block24hAgo < 0n ? 0n : block24hAgo - - // Run queries in parallel - const [tokensCountResult, txCount24hResult, accounts24hResult] = - await Promise.all([ - // Total tokens (capped) - QB.selectFrom( - QB.withSignatures([tokenCreatedSignature]) - .selectFrom('tokencreated') - .select((eb) => eb.lit(1).as('x')) - .where('chain', '=', chainId as never) - .limit(TOKEN_COUNT_MAX) - .as('subquery'), - ) - .select((eb) => eb.fn.count('x').as('count')) - .executeTakeFirst(), - - // Transactions in last 24h (by block number) - QB.selectFrom('txs') - .select((eb) => eb.fn.count('hash').as('count')) - .where('chain', '=', chainId) - .where('block_num', '>=', block24hAgoSafe) - .executeTakeFirst(), - - // Active accounts: sample recent txs and count unique senders - QB.selectFrom('txs') - .select(['from']) - .where('chain', '=', chainId) - .where('block_num', '>=', block24hAgoSafe) - .limit(50000) - .execute(), - ]) - - const uniqueAccounts = new Set( - accounts24hResult?.map((tx) => tx.from) ?? [], + const now = Date.now() + const cacheAge = now - cacheTimestamp + const isCacheValid = cachedStats && cacheAge < CACHE_TTL_MS + + // Return cached data if still valid + if (isCacheValid) { + const remainingTtl = Math.max( + 1, + Math.floor((CACHE_TTL_MS - cacheAge) / 1000), ) + return Response.json( + { data: cachedStats, error: null } satisfies StatsApiResponse, + { headers: { 'Cache-Control': `public, max-age=${remainingTtl}` } }, + ) + } + + // If a fetch is already in progress, wait for it (prevents thundering herd) + if (fetchInProgress) { + try { + const data = await fetchInProgress + return Response.json( + { data, error: null } satisfies StatsApiResponse, + { headers: { 'Cache-Control': 'public, max-age=60' } }, + ) + } catch { + // Fall through to try fresh fetch + } + } + + try { + fetchInProgress = fetchStatsFromIndexer() + const data = await fetchInProgress + + cachedStats = data + cacheTimestamp = now + fetchInProgress = null - return Response.json({ - data: { - transactions24h: Number(txCount24hResult?.count ?? 0), - tokens: Number(tokensCountResult?.count ?? 0), - accounts24h: uniqueAccounts.size, - }, - error: null, - } satisfies StatsApiResponse) + return Response.json( + { data, error: null } satisfies StatsApiResponse, + { headers: { 'Cache-Control': 'public, max-age=60' } }, + ) } catch (error) { - console.error('Failed to fetch stats:', error) + fetchInProgress = null + console.error('[stats] Failed to fetch stats:', error) + + // Return stale cache if available (stale-while-error pattern) + if (cachedStats) { + return Response.json( + { data: cachedStats, error: null } satisfies StatsApiResponse, + { headers: { 'Cache-Control': 'public, max-age=10' } }, + ) + } + const errorMessage = error instanceof Error ? error.message : 'Unknown error' return Response.json( From 8a5857e9ba7f48064e1f3f42d0df77a3737b01e7 Mon Sep 17 00:00:00 2001 From: "Tanishq Sharma (Tani)" Date: Tue, 27 Jan 2026 15:52:18 -0500 Subject: [PATCH 3/5] refactor: hide loading state for network stats Amp-Thread-ID: https://ampcode.com/threads/T-019c0131-d03f-7478-b89f-0afd1cf0725a Co-authored-by: Amp --- apps/explorer/src/comps/NetworkStats.tsx | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/apps/explorer/src/comps/NetworkStats.tsx b/apps/explorer/src/comps/NetworkStats.tsx index 183f7390..877f04f4 100644 --- a/apps/explorer/src/comps/NetworkStats.tsx +++ b/apps/explorer/src/comps/NetworkStats.tsx @@ -28,18 +28,7 @@ export function NetworkStats(): React.JSX.Element | null { retry: 2, }) - if (isLoading) { - return ( -
-
-
- Loading stats... -
-
- ) - } - - if (isError || !data) return null + if (isLoading || isError || !data) return null const hasAnyData = data.transactions24h > 0 || data.tokens > 0 || data.accounts24h > 0 From 2fa51ece5d940855e277d3e17866b315f2a35d7f Mon Sep 17 00:00:00 2001 From: "Tanishq Sharma (Tani)" Date: Tue, 27 Jan 2026 15:59:37 -0500 Subject: [PATCH 4/5] style: add vertical dividers between stats and increase number font size Amp-Thread-ID: https://ampcode.com/threads/T-019c0131-d03f-7478-b89f-0afd1cf0725a Co-authored-by: Amp --- apps/explorer/src/comps/NetworkStats.tsx | 45 +++++++++++++----------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/apps/explorer/src/comps/NetworkStats.tsx b/apps/explorer/src/comps/NetworkStats.tsx index 877f04f4..210b30c4 100644 --- a/apps/explorer/src/comps/NetworkStats.tsx +++ b/apps/explorer/src/comps/NetworkStats.tsx @@ -1,4 +1,5 @@ import { useQuery } from '@tanstack/react-query' +import * as React from 'react' import { getApiUrl } from '#lib/env' import { TOKEN_COUNT_MAX } from '#lib/constants' import type { StatsApiResponse } from '#routes/api/stats' @@ -35,28 +36,30 @@ export function NetworkStats(): React.JSX.Element | null { if (!hasAnyData) return null + const stats = [ + data.transactions24h > 0 && { + value: formatNumber(data.transactions24h), + label: 'txns / 24h', + }, + data.tokens > 0 && { + value: formatNumber(data.tokens, TOKEN_COUNT_MAX), + label: 'tokens', + }, + data.accounts24h > 0 && { + value: `+${formatNumber(data.accounts24h)}`, + label: 'accounts / 24h', + }, + ].filter(Boolean) as Array<{ value: string; label: string }> + return (
-
-
- {data.transactions24h > 0 && ( - - )} - {data.tokens > 0 && ( - - )} - {data.accounts24h > 0 && ( - - )} +
+ {stats.map((stat, i) => ( + + {i > 0 &&
} + + + ))}
) @@ -65,7 +68,7 @@ export function NetworkStats(): React.JSX.Element | null { function StatItem(props: { value: string; label: string }): React.JSX.Element { return (
- + {props.value} {props.label} From 8d9425d2fe8b7fd9ec2447deebb178936e8170bf Mon Sep 17 00:00:00 2001 From: "Tanishq Sharma (Tani)" Date: Tue, 27 Jan 2026 16:01:42 -0500 Subject: [PATCH 5/5] chore: increase token count cap from 100K to 1M Amp-Thread-ID: https://ampcode.com/threads/T-019c0131-d03f-7478-b89f-0afd1cf0725a Co-authored-by: Amp --- apps/explorer/src/lib/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/explorer/src/lib/constants.ts b/apps/explorer/src/lib/constants.ts index 00c59b8f..eaf41903 100644 --- a/apps/explorer/src/lib/constants.ts +++ b/apps/explorer/src/lib/constants.ts @@ -2,4 +2,4 @@ * Maximum number of rows to count in expensive count queries. * This prevents performance issues when counting very large datasets. */ -export const TOKEN_COUNT_MAX = 100_000 +export const TOKEN_COUNT_MAX = 1_000_000