mirror of
https://github.com/luxfi/explore.git
synced 2026-10-30 16:57:53 +00:00
luxd serves no P-Chain JSON-RPC, so every platform.* read the explorer sent
answered 404 and the validators, chains and heights widgets were empty on Lux
and Zoo. Each read is now GET /v1/chain/P/ops/{validators,blockchains,height},
coded against the node's OpenAPI 3.1 document, through GET
/v1/node/p-chain?op=<op>. The proxy's fixed table allows those three ops and one
NodeID parameter; a POST there answers 405.
ChainEntry.pChain is where the P-Chain that secures a chain is read: Lux reads
its own; Zoo, an L2 carried by Lux's validator set, reads Lux's and never its
own node's; Hanzo, on its own committee until hanzod joins as an L2, has none.
P-Chain UI names whose it is ("Lux primary network validators securing Zoo
Network") and prices stake in LUX. The cross-network validator sum is gone: it
counted Lux's validators again under Zoo.
The top bar shows a link only where its page has content: Chains, Bridge and
DEX on the Lux C-Chain host (their pages now 404 elsewhere), Validators where a
P-Chain secures the chain, Stats where there is a P-Chain panel or a stats
service. A P-Chain at genesis renders height #0 rather than nothing. The chain
page's uptime is no longer multiplied by 100.
Claude-Session: https://claude.ai/code/session_011Ge9UnfkEK37Lapx5nfPQK
68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
// Live heads of the P-Chain and the C-Chain. A head that could not be read is
|
|
// undefined, never 0: a P-Chain at genesis answers height "0", and that is a
|
|
// fact about the chain, not a failed read.
|
|
|
|
import { useQuery } from '@tanstack/react-query';
|
|
|
|
import type { GetHeightResponse } from './types';
|
|
|
|
import { getPChain } from 'configs/app/chainRegistry';
|
|
import { getEnvValue } from 'configs/app/utils';
|
|
|
|
import { read } from './read';
|
|
|
|
const HEIGHTS_STALE_TIME_MS = 15_000;
|
|
const HEIGHTS_QUERY_KEY = 'pchain:chainHeights' as const;
|
|
|
|
async function fetchChainHeights(): Promise<{ pChain?: number; cChain?: number }> {
|
|
// NEXT_PUBLIC_NETWORK_RPC_URL IS the C-chain EVM RPC endpoint (canonical
|
|
// `/v1/chain/C/rpc` on the gateway). Dial it directly — no path rewriting — so
|
|
// the C-chain height works regardless of the gateway path scheme.
|
|
const cChainRpcUrl = getEnvValue('NEXT_PUBLIC_NETWORK_RPC_URL') ?? '';
|
|
|
|
const [ pRes, cRes ] = await Promise.allSettled([
|
|
read<GetHeightResponse>('height'),
|
|
fetch(cChainRpcUrl, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ jsonrpc: '2.0', method: 'eth_blockNumber', params: [], id: 2 }),
|
|
}),
|
|
]);
|
|
|
|
let pChain: number | undefined;
|
|
let cChain: number | undefined;
|
|
|
|
if (pRes.status === 'fulfilled' && /^\d+$/.test(pRes.value.height ?? '')) {
|
|
pChain = Number(pRes.value.height);
|
|
}
|
|
|
|
if (cRes.status === 'fulfilled' && cRes.value.ok) {
|
|
const data = await cRes.value.json() as { result?: string };
|
|
cChain = data.result ? parseInt(data.result, 16) : undefined;
|
|
}
|
|
|
|
return { pChain, cChain };
|
|
}
|
|
|
|
export interface UseChainHeightsResult {
|
|
readonly pChainHeight: number | undefined;
|
|
readonly cChainHeight: number | undefined;
|
|
readonly isLoading: boolean;
|
|
}
|
|
|
|
export function useChainHeights(): UseChainHeightsResult {
|
|
const query = useQuery({
|
|
queryKey: [ HEIGHTS_QUERY_KEY ],
|
|
queryFn: fetchChainHeights,
|
|
staleTime: HEIGHTS_STALE_TIME_MS,
|
|
refetchInterval: HEIGHTS_STALE_TIME_MS,
|
|
enabled: Boolean(getPChain()),
|
|
});
|
|
|
|
return {
|
|
pChainHeight: query.data?.pChain,
|
|
cChainHeight: query.data?.cChain,
|
|
isLoading: query.isLoading,
|
|
};
|
|
}
|