mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
Brand explorers show only their own chain on validators and DEX
On a Zoo, Hanzo, Pars, SPC or Osage host the validators page listed every L1 in the registry, and /dex rendered the Lux D-Chain markets. The network total now sums every L1 only on the Lux primary-network explorer, and /dex answers 404 anywhere else. isPrimaryNetworkHost() is the same predicate as isPrimaryNetworkExplorer(), taking the host from the request. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -413,7 +413,13 @@ export function isPrimaryNetworkExplorer(): boolean {
|
||||
// primary network's chains or the cross-L1 list. Gating purely on vm==='EVM'
|
||||
// wrongly promoted unregistered hosts (buildWhiteLabelChain defaults to
|
||||
// vm:'EVM') to primary, leaking the parent network's chains.
|
||||
return !isWhiteLabelMode() && getCurrentChain().vm === 'EVM';
|
||||
return isPrimaryNetworkHost(getHostname());
|
||||
}
|
||||
|
||||
/** isPrimaryNetworkExplorer() for an explicit host, e.g. a request's Host header. */
|
||||
export function isPrimaryNetworkHost(hostname: string): boolean {
|
||||
const chain = CHAINS.find((c) => c.hostnames.includes(hostname));
|
||||
return chain !== undefined && chain.vm === 'EVM';
|
||||
}
|
||||
|
||||
export function getCurrentNetwork(): NetworkEntry {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Validator counts across every network in the registry, not just the one this
|
||||
// explorer is pointed at.
|
||||
// Validator counts. The Lux primary-network explorer sums every L1 in the
|
||||
// registry; a brand explorer (Zoo, Hanzo, Pars, SPC, Osage) counts only its own
|
||||
// chain and never names another network.
|
||||
//
|
||||
// Lux, Hanzo, Zoo and Pars are each a sovereign L1 with its OWN P-Chain and its
|
||||
// own validator set, so "how many validators" is a sum over chains and there is
|
||||
@@ -15,7 +16,7 @@ import React from 'react';
|
||||
|
||||
import type { PChainValidator } from './types';
|
||||
|
||||
import { CHAINS, getCurrentChain } from 'configs/app/chainRegistry';
|
||||
import { CHAINS, getCurrentChain, isPrimaryNetworkExplorer } from 'configs/app/chainRegistry';
|
||||
|
||||
const STALE_TIME_MS = 60_000;
|
||||
const PRIMARY_NETWORK_ID = '11111111111111111111111111111111LpoYY';
|
||||
@@ -65,8 +66,10 @@ export function useNetworkValidators() {
|
||||
// Same network as this deployment: a mainnet explorer must not count testnet
|
||||
// validators.
|
||||
const { all, readable } = React.useMemo(() => {
|
||||
const { network } = getCurrentChain();
|
||||
const chains = CHAINS.filter((c) => c.network === network);
|
||||
const current = getCurrentChain();
|
||||
const chains = isPrimaryNetworkExplorer() ?
|
||||
CHAINS.filter((c) => c.network === current.network) :
|
||||
CHAINS.filter((c) => c.network === current.network && c.name === current.name);
|
||||
return { all: chains, readable: chains.filter((c) => c.nodeApiUrl) };
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { Route } from 'nextjs-routes';
|
||||
import type { Props } from 'nextjs/getServerSideProps/handlers';
|
||||
|
||||
import config from 'configs/app';
|
||||
import { isPrimaryNetworkHost } from 'configs/app/chainRegistry';
|
||||
|
||||
export type Guard = (chainConfig: typeof config) => <Pathname extends Route['pathname'] = never>(context: GetServerSidePropsContext) =>
|
||||
Promise<GetServerSidePropsResult<Props<Pathname>> | undefined>;
|
||||
@@ -342,3 +343,16 @@ export const megaEth: Guard = () => async() => {
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Pages that read the Lux primary network (the D-Chain DEX) exist only on the
|
||||
// Lux C-Chain explorer. A brand explorer answers 404 for them rather than
|
||||
// rendering another network's markets under its own name.
|
||||
export const primaryNetwork: Guard = () => async(context: GetServerSidePropsContext) => {
|
||||
const header = context.req.headers['x-forwarded-host'] ?? context.req.headers.host ?? '';
|
||||
const host = String(Array.isArray(header) ? header[0] : header).split(',')[0].trim().replace(/:\d+$/, '');
|
||||
if (!isPrimaryNetworkHost(host)) {
|
||||
return {
|
||||
notFound: true,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,6 +31,7 @@ export const pools = factory([ guards.pools ]);
|
||||
export const megaEth = factory([ guards.megaEth ]);
|
||||
export const zetaChainCCTX = factory([ guards.zetaChainCCTX ]);
|
||||
export const crossChainTxs = factory([ guards.notMultichain, guards.crossChainTxs ]);
|
||||
export const dex = factory([ guards.primaryNetwork ]);
|
||||
|
||||
// ROLLUPS
|
||||
export const rollup = factory([ guards.rollup ]);
|
||||
|
||||
+1
-1
@@ -15,4 +15,4 @@ const Page: NextPage = () => {
|
||||
|
||||
export default Page;
|
||||
|
||||
export { base as getServerSideProps } from 'nextjs/getServerSideProps/main';
|
||||
export { dex as getServerSideProps } from 'nextjs/getServerSideProps/main';
|
||||
|
||||
@@ -32,9 +32,10 @@ const PERCENTAGE_SCALE = 100;
|
||||
// that shows one network's share is answering a narrower question than the one
|
||||
// being asked.
|
||||
//
|
||||
// Every network is listed, including ones that did not answer. A chain dropped
|
||||
// from the list would read as a chain with no validators, and the total says
|
||||
// how many answered so a partial sum is never mistaken for the whole.
|
||||
// On the Lux primary-network explorer every network is listed, including ones
|
||||
// that did not answer: a chain dropped from the list would read as a chain with
|
||||
// no validators, and the total says how many answered. A brand explorer has
|
||||
// only its own chain, so the block does not render there.
|
||||
const NetworkValidators = () => {
|
||||
const { networks, total, isKnown, isLoading, answeredCount, queriedCount } = useNetworkValidators();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user