mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
/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.
123 lines
7.0 KiB
TypeScript
123 lines
7.0 KiB
TypeScript
import { getFeaturePayload } from 'configs/app/features/types';
|
|
|
|
import type { Route } from 'nextjs-routes';
|
|
|
|
import config from 'configs/app';
|
|
import { layerLabels } from 'lib/rollups/utils';
|
|
|
|
const dappEntityName = (getFeaturePayload(config.features.marketplace)?.titles.entity_name ?? '').toLowerCase();
|
|
|
|
const TEMPLATE_MAP: Record<Route['pathname'], string> = {
|
|
'/': '%network_name% blockchain explorer - View %network_name% stats',
|
|
'/ai': '%network_name% AI compute - models, providers and attestations',
|
|
'/txs': '%network_name% transactions - %network_name% explorer',
|
|
'/internal-txs': '%network_name% internal transactions - %network_name% explorer',
|
|
'/txs/kettle/[hash]': '%network_name% kettle %hash% transactions',
|
|
'/tx/[hash]': '%network_name% transaction %hash%',
|
|
'/blocks': '%network_name% blocks',
|
|
'/block/[height_or_hash]': '%network_name% block %height_or_hash%',
|
|
'/chains': '%network_name% chains - all blockchains on the network',
|
|
'/chains/[slug]': '%network_name% %slug% chain details',
|
|
'/bridge': '%network_name% bridge - cross-chain transfers',
|
|
'/block/countdown': '%network_name% block countdown index',
|
|
'/block/countdown/[height]': '%network_name% block %height% countdown',
|
|
'/accounts': '%network_name% top accounts',
|
|
'/accounts/label/[slug]': '%network_name% addresses search by label',
|
|
'/address/[hash]': '%network_name% address details for %hash%',
|
|
'/verified-contracts': 'Verified %network_name% contracts lookup - %network_name% explorer',
|
|
'/contract-verification': '%network_name% verify contract',
|
|
'/address/[hash]/contract-verification': '%network_name% contract verification for %hash%',
|
|
'/tokens': 'Tokens list - %network_name% explorer',
|
|
'/token/[hash]': '%network_name% token details',
|
|
'/token/[hash]/instance/[id]': '%network_name% NFT instance',
|
|
'/apps': `%network_name% ${ dappEntityName }s - Explore top ${ dappEntityName }s`,
|
|
'/apps/[id]': `%network_name% marketplace ${ dappEntityName }`,
|
|
'/essential-dapps/[id]': '%id_cap%',
|
|
'/stats': '%network_name% stats - %network_name% network insights',
|
|
'/stats/[id]': '%network_name% stats - %id% chart',
|
|
'/uptime': '%network_name% uptime',
|
|
'/hot-contracts': '%network_name% hot contracts',
|
|
'/api-docs': '%network_name% API docs - %network_name% developer tools',
|
|
'/search-results': '%network_name% search result for %q%',
|
|
'/auth/callback': '%network_name% - authentication',
|
|
'/account/merits': '%network_name% - Merits',
|
|
'/account/watchlist': '%network_name% - watchlist',
|
|
'/account/api-key': '%network_name% - API keys',
|
|
'/account/custom-abi': '%network_name% - custom ABI',
|
|
'/account/tag-address': '%network_name% - private tags',
|
|
'/account/verified-addresses': '%network_name% - my verified addresses',
|
|
'/public-tags/submit': '%network_name% - public tag requests',
|
|
'/withdrawals': '%network_name% withdrawals - track on %network_name% explorer',
|
|
'/txn-withdrawals': `${ layerLabels.current } to ${ layerLabels.parent } message relayer`,
|
|
'/visualize/sol2uml': '%network_name% Solidity UML diagram',
|
|
'/csv-export': '%network_name% export data to CSV',
|
|
'/dex': '%network_name% DEX - D-Chain orderbook and market data',
|
|
'/deposits': '%network_name% deposits - track on %network_name% explorer',
|
|
'/output-roots': '%network_name% output roots',
|
|
'/dispute-games': '%network_name% dispute games',
|
|
'/batches': '%network_name% txn batches',
|
|
'/batches/[number]': `%network_name% ${ layerLabels.current } txn batch %number%`,
|
|
'/batches/celestia/[height]/[commitment]': `%network_name% ${ layerLabels.current } txn batch %height% %commitment%`,
|
|
'/blobs/[hash]': '%network_name% blob %hash% details',
|
|
'/ops': 'User operations on %network_name% - %network_name% explorer',
|
|
'/op/[hash]': '%network_name% user operation %hash%',
|
|
'/404': '%network_name% error - page not found',
|
|
'/name-services': '%network_name% name services - %network_name% explorer',
|
|
'/name-services/domains/[name]': '%network_name% %name% domain details',
|
|
'/name-services/clusters/[name]': '%network_name% %name% cluster details',
|
|
'/validators': '%network_name% validators list',
|
|
'/validators/[id]': '%network_name% validator %id% details',
|
|
'/epochs': '%network_name% epochs',
|
|
'/epochs/[number]': '%network_name% epoch %number% details',
|
|
'/gas-tracker': 'Track %network_name% gas fees in %network_gwei%',
|
|
'/mud-worlds': '%network_name% MUD worlds list',
|
|
'/token-transfers': '%network_name% token transfers',
|
|
'/advanced-filter': '%network_name% advanced filter',
|
|
'/pools': '%network_name% DEX pools',
|
|
'/pools/[hash]': '%network_name% pool details',
|
|
'/interop-messages': '%network_name% interop messages',
|
|
'/operations': '%network_name% operations',
|
|
'/operation/[id]': '%network_name% operation %id%',
|
|
'/cc/tx/[hash]': '%network_name% cross-chain transaction %hash% details',
|
|
'/cross-chain-tx/[id]': '%network_name% cross-chain transaction %id% details',
|
|
|
|
// multichain routes
|
|
'/chain/[chain_slug]/accounts/label/[slug]': '%network_name% addresses search by label',
|
|
'/chain/[chain_slug]/advanced-filter': '%network_name% advanced filter',
|
|
'/chain/[chain_slug]/block/[height_or_hash]': '%network_name% block %height_or_hash% details',
|
|
'/chain/[chain_slug]/block/countdown': '%network_name% block countdown index',
|
|
'/chain/[chain_slug]/block/countdown/[height]': '%network_name% block %height% countdown',
|
|
'/chain/[chain_slug]/csv-export': '%network_name% export data to CSV',
|
|
'/chain/[chain_slug]/op/[hash]': '%network_name% user operation %hash% details',
|
|
'/chain/[chain_slug]/token/[hash]': '%network_name% token details',
|
|
'/chain/[chain_slug]/token/[hash]/instance/[id]': '%network_name% token NFT instance',
|
|
'/chain/[chain_slug]/tx/[hash]': '%network_name% transaction %hash% details',
|
|
'/chain/[chain_slug]/visualize/sol2uml': '%network_name% Solidity UML diagram',
|
|
'/ecosystems': '%network_name% ecosystems',
|
|
|
|
// service routes, added only to make typescript happy
|
|
'/sprite': '%network_name% SVG sprite',
|
|
'/v1/metrics': '%network_name% node API prometheus metrics',
|
|
'/v1/monitoring/invalid-api-schema': '%network_name% node API prometheus metrics',
|
|
'/v1/log': '%network_name% node API request log',
|
|
'/v1/tokens/[hash]/instances/[id]/media-type': '%network_name% node API token instance media type',
|
|
'/v1/proxy': '%network_name% node API proxy',
|
|
'/v1/csrf': '%network_name% node API CSRF token',
|
|
'/v1/healthz': '%network_name% node API health check',
|
|
'/v1/config': '%network_name% node API app config',
|
|
'/v1/node/[endpoint]': '%network_name% node API JSON-RPC proxy',
|
|
};
|
|
|
|
const TEMPLATE_MAP_ENHANCED: Partial<Record<Route['pathname'], string>> = {
|
|
'/token/[hash]': '%network_name% %symbol_or_name% token details',
|
|
'/token/[hash]/instance/[id]': '%network_name% token instance for %symbol_or_name%',
|
|
'/apps/[id]': '%network_name% - %app_name%',
|
|
'/address/[hash]': '%network_name% address details for %domain_name%',
|
|
'/stats/[id]': '%title% chart on %network_name%',
|
|
};
|
|
|
|
export function make(pathname: Route['pathname'], isEnriched = false) {
|
|
const template = (isEnriched ? TEMPLATE_MAP_ENHANCED[pathname] : undefined) ?? TEMPLATE_MAP[pathname];
|
|
return template.trim();
|
|
}
|