Files
explore/pages/api/pchain.ts
T
Antje Worring ffc3902264 fix(explore): real validators + honest-empty stats/DEX + dropdown clip
Investor-grade data, no fabricated placeholders:

- pages/api/pchain.ts: derive node origin via new URL().origin instead of a
  regex that only stripped /ext/bc/C/rpc. Non-C-chain brands (hanzo:
  /ext/bc/hanzo/rpc) built a wrong URL -> HTML 404 -> JSON parse crash, so
  Validators/Total Stake/Connected/Uptime all showed 0/-. Now the P-chain
  proxy resolves correctly and the real validator set + stake render. Parse
  upstream defensively with a clear error instead of an opaque message.

- lib/api/dchain/useDexData.ts: delete all hardcoded DEMO_* markets/orders/
  trades/pools/overview. Return only real D-Chain (DexVM) data or honest-empty.
- ui/dex/DexPage.tsx: honest empty/error states per tab (no fake rows).

- stubs/stats.ts: neutralize STATS_COUNTER (title empty, value 0) so the
  'Placeholder Counter 9.074M' stub can never surface as real data.
- ui/pages/Stats.tsx: gate indexer-backed counters/charts on
  config.features.stats.isEnabled; always show the live chain-sourced Network
  Overview, with an honest 'being indexed' note when no stats microservice.

- ui/snippets/navigation/horizontal/NavLinkGroup.tsx: popover Content defaulted
  to overflow-hidden + tight py, clipping the last nav item (Verified
  Contracts). Override to overflow-visible with padding; bottom-start placement.
2026-06-23 21:06:19 -07:00

72 lines
2.2 KiB
TypeScript

// Server-side proxy for P-chain JSON-RPC calls.
// Bypasses CORS issues with the KrakenD gateway which returns 404 on OPTIONS preflight for /ext/bc/P.
import type { NextApiRequest, NextApiResponse } from 'next';
import { getEnvValue } from 'configs/app/utils';
const TIMEOUT_MS = 10_000;
// Derive the node's API origin from the chain RPC URL. The RPC URL points at a
// specific EVM chain (e.g. `…/ext/bc/C/rpc` or `…/ext/bc/hanzo/rpc`); the P-chain
// lives at `<origin>/ext/bc/P`, so we must reduce to the scheme+host origin and
// never naively concatenate onto the full RPC path (which produced a malformed
// URL → HTML 404 → "Unexpected non-whitespace character after JSON" for every
// non-C-chain brand).
function getApiBase(): string {
const rpcUrl = getEnvValue('NEXT_PUBLIC_NETWORK_RPC_URL') ?? '';
if (!rpcUrl) {
return '';
}
try {
return new URL(rpcUrl).origin;
} catch {
return '';
}
}
const handler = async(req: NextApiRequest, res: NextApiResponse): Promise<void> => {
if (req.method !== 'POST') {
res.status(405).json({ error: 'Method not allowed' });
return;
}
const base = getApiBase();
if (!base) {
res.status(500).json({ error: 'NEXT_PUBLIC_NETWORK_RPC_URL not configured' });
return;
}
try {
const response = await fetch(`${ base }/ext/bc/P`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(req.body),
signal: AbortSignal.timeout(TIMEOUT_MS),
});
// The node returns JSON for valid P-chain RPC; a wrong URL or gateway
// error yields HTML. Read as text and parse defensively so the client gets a
// clear error rather than an opaque "non-whitespace character" parse crash.
const raw = await response.text();
let data: unknown;
try {
data = JSON.parse(raw);
} catch {
res.status(502).json({
error: 'P-chain request failed',
message: `Upstream returned non-JSON (HTTP ${ response.status }) from ${ base }/ext/bc/P`,
});
return;
}
res.status(200).json(data);
} catch (error) {
res.status(502).json({
error: 'P-chain request failed',
message: error instanceof Error ? error.message : 'Unknown error',
});
}
};
export default handler;