Files
zeekay 87aa0fa367 chains: read each chain from that chain, and list the ones this network runs
/chains showed fifteen rows on every network, from a hardcoded table. Four of
them — T, R, I, O — are registered on no network at all; the node answers
"there is no ID with alias: T". A fifth, M, runs on devnet alone. And every
/chains/<slug> page printed the same four numbers: the primary network's
validator count, its total stake, its chain count, its threshold. Nothing on
Q-Chain's page was about Q-Chain. Fifteen pages, one set of facts.

The network already knows its own answer. platform.getBlockchains is the chain
list, and it is per-network for free: mainnet and testnet report nine chains,
devnet reports ten including M. That is what /chains lists now, joined with
configs/app/primaryChains.ts for presentation only — a chain the network
reports and we have no metadata for still gets a row, because the network is
the source of truth and our table is not.

Three facts per chain, each read from that chain:

  * the blockchain ID, from the registry — the thing that actually tells one
    chain from another, and it was already on screen while the numbers above
    it were not
  * whether the node has bootstrapped it, from info.isBootstrapped, which the
    gateway routes for every chain. This is how Q-Chain's page now says
    Syncing where the other nine say Bootstrapped: Q has not come up on any of
    the three networks and is the sole reason all three report healthy:false
  * its head, in its own dialect — eth_blockNumber for C, platform.getHeight
    for P, xvm.getHeight for X. Not avm: that service is gone from this build,
    and asking it returns "can't find service" rather than a height

Validators are the P-Chain's model, so they render on the P-Chain and nowhere
else. The head is labelled for the model it comes from — the X-Chain's is an
accepted height, not a block height.

Where a chain has no head to read, it says so. The gateway routes exactly P, X
and C on all three networks; D, A, B, Z, G, K and Q are registered and
bootstrapped on the node but their RPC 404s from a browser. Proof it is the
route and not the chain: C-Chain's own blockchain ID, /v1/bc/25td8att…/rpc,
404s while /v1/bc/C/rpc returns a height — same chain, same node. Those pages
read "No public RPC" and say plainly that the chain is registered and running
but not published. A zero there would have read as a measurement.

One proxy replaces the P-only one. /v1/pchain hardcoded /v1/bc/P; /v1/node/
<endpoint> resolves the endpoint against the primary-chain table and never
treats it as a URL. A chain the gateway does not route comes back 200 carrying
a JSON-RPC error rather than 502 — nothing is broken, and 502 put a red failed
request in the console of eight of the ten chain pages.

Deleted: CHAIN_INDEXER_URLS and the hook that read it — fifteen hostnames of
the shape api-indexer-<x>chain.lux.network, none of which resolve. Fifteen of
fifteen NXDOMAIN. It fetched them on every chain page and rendered the null.

Measured on mainnet, 1440x900 and 390x844, fresh context per URL: 20 of 20
chain/screen rows agree with RPC on both status and head — C-Chain 1,107,826
against a live head bracketed at 1,107,822..1,107,829, P and X at 0, seven
reading No public RPC, Q Syncing while the rest are Bootstrapped. /chains
lists the same ten chains the P-Chain reports, and 10 of 10 row links reach a
real page. Zero 4xx or 5xx from our own origin.
2026-08-08 07:32:01 -07:00

116 lines
5.7 KiB
TypeScript

/* eslint-disable max-len */
import type { Route } from 'nextjs-routes';
// equal og:description
const DEFAULT_TEMPLATE = '%network_name% Explorer - Search transactions, verify smart contracts, analyze addresses, and track network activity. Complete blockchain data and APIs for the %network_title% network.';
// FIXME all page descriptions will be updated later
const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/': DEFAULT_TEMPLATE,
'/ai': 'Explore AI models, compute providers, inference results, and attestations on the %network_name% A-Chain.',
'/txs': DEFAULT_TEMPLATE,
'/internal-txs': DEFAULT_TEMPLATE,
'/txs/kettle/[hash]': DEFAULT_TEMPLATE,
'/tx/[hash]': 'View transaction %hash% on %network_title%',
'/blocks': DEFAULT_TEMPLATE,
'/block/[height_or_hash]': 'View the transactions, token transfers, and uncles for block %height_or_hash%',
'/chains': 'Explore all blockchains on %network_name% including primary chains and sovereign L1/L2/L3 networks.',
'/chains/[slug]': 'View chain details, validators, and network information for %slug% on %network_name%.',
'/bridge': 'Track cross-chain transfers between %network_name% chains. View bridge routes, transfer status, and connected chains.',
'/block/countdown': DEFAULT_TEMPLATE,
'/block/countdown/[height]': DEFAULT_TEMPLATE,
'/accounts': DEFAULT_TEMPLATE,
'/accounts/label/[slug]': DEFAULT_TEMPLATE,
'/address/[hash]': 'View the account balance, transactions, and other data for %hash% on the %network_title%',
'/verified-contracts': DEFAULT_TEMPLATE,
'/contract-verification': DEFAULT_TEMPLATE,
'/address/[hash]/contract-verification': 'View the account balance, transactions, and other data for %hash% on the %network_title%',
'/tokens': DEFAULT_TEMPLATE,
'/token/[hash]': '%hash%, balances and analytics on the %network_title%',
'/token/[hash]/instance/[id]': '%hash%, balances and analytics on the %network_title%',
'/apps': DEFAULT_TEMPLATE,
'/apps/[id]': DEFAULT_TEMPLATE,
'/essential-dapps/[id]': DEFAULT_TEMPLATE,
'/stats': DEFAULT_TEMPLATE,
'/stats/[id]': DEFAULT_TEMPLATE,
'/uptime': DEFAULT_TEMPLATE,
'/hot-contracts': DEFAULT_TEMPLATE,
'/api-docs': DEFAULT_TEMPLATE,
'/search-results': DEFAULT_TEMPLATE,
'/auth/callback': DEFAULT_TEMPLATE,
'/account/merits': DEFAULT_TEMPLATE,
'/account/watchlist': DEFAULT_TEMPLATE,
'/account/api-key': DEFAULT_TEMPLATE,
'/account/custom-abi': DEFAULT_TEMPLATE,
'/account/tag-address': DEFAULT_TEMPLATE,
'/account/verified-addresses': DEFAULT_TEMPLATE,
'/public-tags/submit': 'Propose a new public tag for your address, contract or set of contracts for your dApp. Our team will review and approve your submission. Public tags are incredible tool which helps users identify contracts and addresses.',
'/withdrawals': DEFAULT_TEMPLATE,
'/txn-withdrawals': DEFAULT_TEMPLATE,
'/visualize/sol2uml': DEFAULT_TEMPLATE,
'/csv-export': DEFAULT_TEMPLATE,
'/dex': 'Explore the D-Chain decentralized exchange on %network_name%. View orderbook, trade history, liquidity pools, and market data.',
'/deposits': DEFAULT_TEMPLATE,
'/output-roots': DEFAULT_TEMPLATE,
'/dispute-games': DEFAULT_TEMPLATE,
'/batches': DEFAULT_TEMPLATE,
'/batches/[number]': DEFAULT_TEMPLATE,
'/batches/celestia/[height]/[commitment]': DEFAULT_TEMPLATE,
'/blobs/[hash]': DEFAULT_TEMPLATE,
'/ops': DEFAULT_TEMPLATE,
'/op/[hash]': DEFAULT_TEMPLATE,
'/404': DEFAULT_TEMPLATE,
'/name-services': DEFAULT_TEMPLATE,
'/name-services/domains/[name]': DEFAULT_TEMPLATE,
'/name-services/clusters/[name]': DEFAULT_TEMPLATE,
'/validators': DEFAULT_TEMPLATE,
'/validators/[id]': DEFAULT_TEMPLATE,
'/epochs': DEFAULT_TEMPLATE,
'/epochs/[number]': DEFAULT_TEMPLATE,
'/gas-tracker': 'Explore real-time %network_title% gas fees with %network_name%\'s advanced gas fee tracker. Get accurate %network_gwei% estimates and track transaction costs live.',
'/mud-worlds': DEFAULT_TEMPLATE,
'/token-transfers': DEFAULT_TEMPLATE,
'/advanced-filter': DEFAULT_TEMPLATE,
'/pools': DEFAULT_TEMPLATE,
'/pools/[hash]': DEFAULT_TEMPLATE,
'/interop-messages': DEFAULT_TEMPLATE,
'/operations': DEFAULT_TEMPLATE,
'/operation/[id]': DEFAULT_TEMPLATE,
'/cc/tx/[hash]': DEFAULT_TEMPLATE,
'/cross-chain-tx/[id]': DEFAULT_TEMPLATE,
// multichain routes
'/chain/[chain_slug]/accounts/label/[slug]': DEFAULT_TEMPLATE,
'/chain/[chain_slug]/advanced-filter': DEFAULT_TEMPLATE,
'/chain/[chain_slug]/block/[height_or_hash]': DEFAULT_TEMPLATE,
'/chain/[chain_slug]/block/countdown': DEFAULT_TEMPLATE,
'/chain/[chain_slug]/block/countdown/[height]': DEFAULT_TEMPLATE,
'/chain/[chain_slug]/csv-export': DEFAULT_TEMPLATE,
'/chain/[chain_slug]/op/[hash]': DEFAULT_TEMPLATE,
'/chain/[chain_slug]/token/[hash]': DEFAULT_TEMPLATE,
'/chain/[chain_slug]/token/[hash]/instance/[id]': DEFAULT_TEMPLATE,
'/chain/[chain_slug]/tx/[hash]': DEFAULT_TEMPLATE,
'/chain/[chain_slug]/visualize/sol2uml': DEFAULT_TEMPLATE,
'/ecosystems': DEFAULT_TEMPLATE,
// service routes, added only to make typescript happy
'/sprite': DEFAULT_TEMPLATE,
'/v1/metrics': DEFAULT_TEMPLATE,
'/v1/monitoring/invalid-api-schema': DEFAULT_TEMPLATE,
'/v1/log': DEFAULT_TEMPLATE,
'/v1/tokens/[hash]/instances/[id]/media-type': DEFAULT_TEMPLATE,
'/v1/proxy': DEFAULT_TEMPLATE,
'/v1/csrf': DEFAULT_TEMPLATE,
'/v1/healthz': DEFAULT_TEMPLATE,
'/v1/config': DEFAULT_TEMPLATE,
'/v1/node/[endpoint]': DEFAULT_TEMPLATE,
};
const TEMPLATE_MAP_ENHANCED: Partial<Record<Route['pathname'], string>> = {
'/stats/[id]': '%description%',
};
export function make(pathname: Route['pathname'], isEnriched = false) {
return (isEnriched ? TEMPLATE_MAP_ENHANCED[pathname] : undefined) ?? TEMPLATE_MAP[pathname] ?? '';
}