Files
explore/lib/api/useHeadBlock.ts
zeekayandHanzo Dev f434a701dc dex: show the AMM trades that are actually landing, next to an honest CLOB
The AMM subgraph has been indexed and at chain head the whole time; nothing
read it. /dex queried only the native CLOB at 0x9999, which has genuinely
never emitted an event, so the page reported MARKETS 0 / VOLUME 0 while ~1
swap per block was landing in the WLUX/LZOO pool.

Wire the amm subgraph in as a SECOND venue rather than folding it into the
first. The two are different exchanges and their figures are never summed —
each section reports only its own state, so "live" can never be borrowed by
the venue that is not trading.

Swaps were rendering as anonymous EVM traffic; they now read as trades:
pool-signed amounts resolved into sold/bought, scaled by each token's own
decimals, with symbols, pair, fee tier and links to sender, block and txn.

Status uses the words already in use elsewhere (useNetworkValidators,
useFeeSplit) — live/idle/empty/unavailable/unknown — defined once in
lib/api/venueStatus. There is deliberately no 'stale': separating a stalled
indexer from a quiet venue needs an indexer head this API does not serve.

Also decomplected while here: one fetcher for both subgraphs, and an
unreachable endpoint is no longer flattened into "empty" — an outage and a
venue that has never traded are different facts and now render differently.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-07 08:03:30 -07:00

41 lines
1.0 KiB
TypeScript

import { useQuery } from '@tanstack/react-query';
import { getApiBase } from 'lib/api/subgraph';
const STATS_PATH = '/v1/stats';
const POLL_INTERVAL_MS = 30_000;
// The chain head, read straight off the API host the same way the subgraphs
// are, so it resolves identically in dev and in production. `null` means we
// could not read it, and callers must report that rather than guess a height.
async function fetchHeadBlock(): Promise<number | null> {
const base = getApiBase();
if (!base) {
return null;
}
try {
const res = await fetch(base + STATS_PATH);
if (!res.ok) {
return null;
}
const json = await res.json() as { head_block?: number } | null;
return typeof json?.head_block === 'number' ? json.head_block : null;
} catch {
return null;
}
}
export function useHeadBlock(): number | null {
const { data } = useQuery({
queryKey: [ 'headBlock', getApiBase() ],
queryFn: fetchHeadBlock,
refetchInterval: POLL_INTERVAL_MS,
});
return data ?? null;
}