mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
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]>
41 lines
1.0 KiB
TypeScript
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;
|
|
}
|