From abe595319b06edab26bfe7be45fec343edf288f8 Mon Sep 17 00:00:00 2001 From: Flotapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Fri, 21 Aug 2026 18:10:39 +0200 Subject: [PATCH 1/4] fix: bench number 208->232 (208 taken by perp-liq-rate) (#2031) --- benchmarks/trading-platform-wallets.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/trading-platform-wallets.yml b/benchmarks/trading-platform-wallets.yml index 1055594b..16077544 100644 --- a/benchmarks/trading-platform-wallets.yml +++ b/benchmarks/trading-platform-wallets.yml @@ -1,7 +1,7 @@ # OpenChainBench. Bench 208 slug: trading-platform-wallets -number: "208" +number: "232" title: "Daily active wallets per trading platform: GMGN vs Axiom vs Fomo vs pump.fun, live" seo_title: "Daily active wallets by trading platform 2026: GMGN vs Axiom vs Fomo vs pump.fun" seo_description: "{{best_name}} leads trading platforms with {{best_p50}} unique active wallets in 24h. GMGN vs Axiom vs Fomo vs Trojan vs BasedBot ranked by real user count, live from Dune community datasets." From 9f56168b0da2df2cc441082fa65c55368988748a Mon Sep 17 00:00:00 2001 From: Flotapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Fri, 21 Aug 2026 21:05:18 +0200 Subject: [PATCH 2/4] fix(audit): 4 bugs + stablecoin/bridge leads, answers cadence, citation direction, bench 233 * fix(audit): answer leads semantics, freshness copy, null bench cards, OI label * fix(audit): stablecoin/bridge leads semantics, drop hardcoded refresh cadence on answers page * fix: perp-amm-volume-share duplicate bench number 043 -> 233 * fix(citation): direction-aware headlineSentence for lower-is-better metrics --- answers/best-rpc-for-indexer.yml | 6 +++--- .../how-much-does-it-cost-to-bridge-usdc-to-arbitrum.yml | 2 +- answers/which-bridge-has-the-fastest-quote-api.yml | 2 +- answers/which-evm-aggregator-has-the-fastest-quote.yml | 2 +- answers/which-gas-oracle-is-the-most-accurate.yml | 6 +++--- answers/which-l2-has-the-fastest-block-time.yml | 4 ++-- answers/which-stablecoin-is-the-most-stable.yml | 2 +- benchmarks/perp-amm-volume-share.yml | 4 ++-- src/app/alternatives/[slug]/page.tsx | 4 ++-- src/app/answers/[slug]/page.tsx | 2 +- src/app/products/[slug]/page.tsx | 2 +- src/lib/citation.ts | 3 ++- src/lib/perp-venue-external.ts | 8 ++++---- 13 files changed, 24 insertions(+), 23 deletions(-) diff --git a/answers/best-rpc-for-indexer.yml b/answers/best-rpc-for-indexer.yml index 740198c6..829d0bf1 100644 --- a/answers/best-rpc-for-indexer.yml +++ b/answers/best-rpc-for-indexer.yml @@ -1,7 +1,7 @@ slug: best-rpc-for-indexer question: "Which RPC is best for indexers and high-throughput read workloads in 2026?" short_answer: | - {{best_name}} currently leads the free-tier keyed RPC leaderboard at {{best_p50}} p50 latency (24h avg) on eth_getBlockByNumber probes, and pairs it with archive-depth support across a wide chain footprint, measured live by OpenChainBench from three regions. + {{best_name}} currently ranks first on the free-tier keyed RPC leaderboard at {{best_p50}} p50 latency (24h avg) on eth_getBlockByNumber probes, and pairs it with archive-depth support across a wide chain footprint, measured live by OpenChainBench from three regions. benchmark: rpc-capabilities @@ -19,7 +19,7 @@ limitations: faq: - q: "Which RPC provider is best for a subgraph or custom indexer?" - a: "{{best_name}} leads the head-latency leaderboard at {{best_p50}} p50 (24h). For indexers the ranking that matters is the intersection of the latency leaderboard and the archive-depth matrix: a provider that wins latency but fails at 5M depth is not indexer-viable. The bench page surfaces both, and the head-to-head leader among indexer-viable providers is the answer." + a: "{{best_name}} ranks first on the head-latency leaderboard at {{best_p50}} p50 (24h). For indexers the ranking that matters is the intersection of the latency leaderboard and the archive-depth matrix: a provider that wins latency but fails at 5M depth is not indexer-viable. The bench page surfaces both, and the fastest among indexer-viable providers is the answer." - q: "Why does eth_getBlockByNumber matter for indexers when the real workload is eth_getLogs?" a: "Because eth_getBlockByNumber measures the head-of-chain read path that every provider must implement, it is the fair cross-vendor probe. Providers that misbehave on head reads reliably misbehave on eth_getLogs at higher magnitude. Providers that keep head reads tight and consistent tend to keep eth_getLogs tight and consistent too. The latency leaderboard is a lower bound on indexer-workload latency, and a provider that fails the lower bound is not worth benchmarking on the harder workload." - q: "Which provider supports full archive access without a paid plan?" @@ -37,5 +37,5 @@ related: - which-crypto-price-api-is-the-fastest seo_title: "Best RPC for indexers 2026 live rankings" -seo_description: "{{best_name}} leads at {{best_p50}} p50 latency (24h avg) on the OpenChainBench keyed and no-key RPC leaderboards, ranked live from three regions with archive-depth matrix." +seo_description: "{{best_name}} ranks first at {{best_p50}} p50 latency (24h avg) on the OpenChainBench keyed and no-key RPC leaderboards, ranked live from three regions with archive-depth matrix." status: live diff --git a/answers/how-much-does-it-cost-to-bridge-usdc-to-arbitrum.yml b/answers/how-much-does-it-cost-to-bridge-usdc-to-arbitrum.yml index e81f5320..cfbbe2de 100644 --- a/answers/how-much-does-it-cost-to-bridge-usdc-to-arbitrum.yml +++ b/answers/how-much-does-it-cost-to-bridge-usdc-to-arbitrum.yml @@ -20,7 +20,7 @@ limitations: faq: - q: "What is the cheapest way to bridge USDC to Arbitrum?" - a: "At $300 notional, {{best_name}} currently leads the measured cohort at {{best_p50}} all in (p50, 24h, averaged across the corridors it quotes). Intent layers usually top this table at retail sizes because they compress fee, spread and destination gas into one solver quote, while direct protocols carry a fixed fee floor that hits hardest on small trades. The leaderboard refreshes every five minutes, and the corridor level leader can differ from the aggregate, so treat this as the live starting point rather than a permanent answer." + a: "At $300 notional, {{best_name}} currently offers the cheapest route at {{best_p50}} all in (p50, 24h, averaged across the corridors it quotes). Intent layers usually top this table at retail sizes because they compress fee, spread and destination gas into one solver quote, while direct protocols carry a fixed fee floor that hits hardest on small trades. The leaderboard refreshes every five minutes, and the corridor level leader can differ from the aggregate, so treat this as the live starting point rather than a permanent answer." - q: "Why is bridging a small amount of USDC so expensive in percentage terms?" a: "Because part of the cost is fixed. Destination gas and base protocol fees cost roughly the same whether you move $300 or $10,000, so at $300 they are the dominant share of the percentage, while at $10,000 they dilute to noise. This is why published comparisons quoting $10,000 rack rates understate what retail users pay: the current measured spread at $300 runs from {{best_p50}} to {{worst_p50}} across {{count}} providers, a gap driven mostly by how much fixed cost each architecture front loads rather than by spread efficiency." - q: "Do I need ETH on Arbitrum to receive bridged USDC?" diff --git a/answers/which-bridge-has-the-fastest-quote-api.yml b/answers/which-bridge-has-the-fastest-quote-api.yml index 3f34c012..b6da7842 100644 --- a/answers/which-bridge-has-the-fastest-quote-api.yml +++ b/answers/which-bridge-has-the-fastest-quote-api.yml @@ -20,7 +20,7 @@ limitations: faq: - q: "Which cross-chain bridge has the lowest API latency right now?" - a: "{{best_name}} currently leads at {{best_p50}} (p50, 24h) across {{count}} measured bridges, averaged over the 4 USDC routes and 3 notional sizes the harness sweeps. The leaderboard refreshes every 5 minutes against fresh Prometheus samples; the 24h window smooths a single fast cold start so the ranking reflects sustained API performance." + a: "{{best_name}} currently returns quotes the fastest at {{best_p50}} (p50, 24h) across {{count}} measured bridges, averaged over the 4 USDC routes and 3 notional sizes the harness sweeps. The leaderboard refreshes every 5 minutes against fresh Prometheus samples; the 24h window smooths a single fast cold start so the ranking reflects sustained API performance." - q: "What is the difference between quote latency and bridge fill time?" a: "Quote latency is the wall clock time the bridge API takes to return a price. Fill time is the wall clock time the funds take to land on the destination chain after the user signs. They are decoupled: a bridge can quote in 100 ms and take 30 seconds to settle, or quote in 2 seconds and settle in 5 seconds. This benchmark measures the quote half because that is the part a wallet, an aggregator or an embedded swap UI feels first and tunes its UX around." - q: "Why does bridge quote latency matter for builders?" diff --git a/answers/which-evm-aggregator-has-the-fastest-quote.yml b/answers/which-evm-aggregator-has-the-fastest-quote.yml index b1d85c8b..0e79becb 100644 --- a/answers/which-evm-aggregator-has-the-fastest-quote.yml +++ b/answers/which-evm-aggregator-has-the-fastest-quote.yml @@ -20,7 +20,7 @@ limitations: faq: - q: "Which EVM swap quote API has the lowest latency right now?" - a: "{{best_name}} currently leads at {{best_p50}} (p50 over the last 24 hours) on the active tab, across {{count}} measured providers. The leaderboard re-sorts every minute on fresh Prometheus samples, so the answer reflects measured latency on the live basket, not a marketing claim. Per chain leaders can differ from the cross chain aggregate; the chain tabs at the top of the bench page show each ranking separately." + a: "{{best_name}} currently returns quotes the fastest at {{best_p50}} (p50 over the last 24 hours) on the active tab, across {{count}} measured providers. The leaderboard re-sorts every minute on fresh Prometheus samples, so the answer reflects measured latency on the live basket, not a marketing claim. Per chain leaders can differ from the cross chain aggregate; the chain tabs at the top of the bench page show each ranking separately." - q: "Does this measure quote quality or just speed?" a: "Speed only. Latency is wall clock round trip from request to last byte, recorded only on a successful parseable response. Output amount in USD is not scored on this bench because providers measure it differently (Bebop is net of fees on a gasless RFQ, others are gross), and converting all outputs to a comparable USD value introduces an oracle bias the leaderboard does not want to bake into a latency comparison." - q: "Why are some providers not on every chain?" diff --git a/answers/which-gas-oracle-is-the-most-accurate.yml b/answers/which-gas-oracle-is-the-most-accurate.yml index 018731e0..074d4f4d 100644 --- a/answers/which-gas-oracle-is-the-most-accurate.yml +++ b/answers/which-gas-oracle-is-the-most-accurate.yml @@ -20,7 +20,7 @@ limitations: faq: - q: "Which gas oracle is the most accurate right now?" - a: "{{best_name}} currently leads at {{best_p50}} gwei (p99 absolute gap, 24h) on the active chain tab across 3 measured oracles. The leaderboard refreshes every minute against fresh Prometheus samples; per chain leaders can differ from the cross chain headline so the chain tabs at the top of the bench page expose each ranking separately. Read the gap alongside the covered rate column for the full picture, inclusion confidence oracles trade a wider gap for higher coverage." + a: "{{best_name}} currently posts the tightest estimate at {{best_p50}} gwei (p99 absolute gap, 24h) on the active chain tab across 3 measured oracles. The leaderboard refreshes every minute against fresh Prometheus samples; per chain leaders can differ from the cross chain headline so the chain tabs at the top of the bench page expose each ranking separately. Read the gap alongside the covered rate column for the full picture, inclusion confidence oracles trade a wider gap for higher coverage." - q: "Why rank on p99 instead of p50?" a: "At current fee levels the typical minute p50 gaps are fractions of a micro gwei apart across oracles. On a 100k gas transaction a 0.001 gwei error is about a thousandth of a cent, so a p50 ranking orders economically indistinguishable noise. The p99 captures the volatile minutes (mempool spikes, NFT mints, MEV bursts) where predictions actually diverge and a wrong number either overpays or misses the block. The typical p50 and p90 gaps remain visible as secondary columns." - q: "How does Etherscan compare to PublicNode feeHistory or Owlracle?" @@ -30,7 +30,7 @@ faq: - q: "Why is Avalanche C-Chain excluded?" a: "Avalanche C-Chain's auto tuning fee market drives the priority fee toward zero by design, which collapses the prediction error metric to zero across every oracle and makes the comparison non informative. BNB Chain is excluded for a different reason (it is not EIP-1559, effective fee is gasPrice only). Adding either chain would silently produce flat numbers that pollute the comparison; surfacing zero scores on a leaderboard is misleading." - q: "Which oracle should I integrate for my wallet?" - a: "Read the p99 gap (does it blow out during spikes?) together with the covered rate (does it err on the side of inclusion or under bid?) for the chain your product runs on. {{best_name}} currently leads the active tab at {{best_p50}} gwei but the right choice depends on whether your UX tolerates over pay (then prefer high covered) or optimises for tail behaviour (then prefer low p99 gap), and whether the oracle's free quota fits your call volume. The bench gives you the live numbers, it cannot tell you which trade off your product wants." + a: "Read the p99 gap (does it blow out during spikes?) together with the covered rate (does it err on the side of inclusion or under bid?) for the chain your product runs on. {{best_name}} currently posts the smallest p99 gap on the active tab at {{best_p50}} gwei but the right choice depends on whether your UX tolerates over pay (then prefer high covered) or optimises for tail behaviour (then prefer low p99 gap), and whether the oracle's free quota fits your call volume. The bench gives you the live numbers, it cannot tell you which trade off your product wants." - q: "How often is the leaderboard refreshed?" a: "Per oracle polling runs continuously (12 s for PublicNode feeHistory, 15 s for Etherscan with the 6 s global gate, 60 s for Owlracle). The page reads a rolling 24 h p50, p90 and p99 every minute. A single misprediction during a gas spike cannot move the headline because the p99 window absorbs it across thousands of blocks." @@ -40,7 +40,7 @@ related: - which-evm-aggregator-has-the-fastest-quote seo_title: "Which Ethereum gas oracle is the most accurate in 2026?" -seo_description: "{{best_name}} leads at {{best_p50}} gwei (p99 absolute gap, 24h) across PublicNode feeHistory, Owlracle and Etherscan on Ethereum and Polygon, measured per block by OpenChainBench." +seo_description: "{{best_name}} posts the smallest p99 gap at {{best_p50}} gwei (p99 absolute gap, 24h) across PublicNode feeHistory, Owlracle and Etherscan on Ethereum and Polygon, measured per block by OpenChainBench." status: live expert_take: | diff --git a/answers/which-l2-has-the-fastest-block-time.yml b/answers/which-l2-has-the-fastest-block-time.yml index 2065abf3..ff485880 100644 --- a/answers/which-l2-has-the-fastest-block-time.yml +++ b/answers/which-l2-has-the-fastest-block-time.yml @@ -20,7 +20,7 @@ limitations: faq: - q: "Which L2 has the fastest block time right now?" - a: "{{best_name}} currently leads at {{best_p50}} (p50, 24h) across 9 measured L2s. The leaderboard reads a fresh p50 every minute from the Prometheus quantile over the 24 hour window, so the headline is sustained, not a single lucky head. Arbitrum One's Nitro stack runs a 250 ms sequencer interval by default, which is roughly 8x faster than the OP Stack 2 s convention used by Optimism, Base, Blast and Mantle." + a: "{{best_name}} currently posts the fastest block time at {{best_p50}} (p50, 24h) across 9 measured L2s. The leaderboard reads a fresh p50 every minute from the Prometheus quantile over the 24 hour window, so the headline is sustained, not a single lucky head. Arbitrum One's Nitro stack runs a 250 ms sequencer interval by default, which is roughly 8x faster than the OP Stack 2 s convention used by Optimism, Base, Blast and Mantle." - q: "Why are Base and Optimism block times nearly identical?" a: "Both run the OP Stack with the same default sequencer cadence (2 s). Blast and Mantle are also OP Stack forks and cluster at the same number; this is by design because OP Stack is a turnkey rollup framework where the sequencer interval is a configuration constant, not a chain specific design choice. The leaderboard makes the architectural family visible at a glance." - q: "Is zkSync Era really slower than Arbitrum?" @@ -40,5 +40,5 @@ related: - which-gas-oracle-is-the-most-accurate seo_title: "Which Ethereum L2 has the fastest block time in 2026?" -seo_description: "{{best_name}} leads at {{best_p50}} (p50, 24h) across Arbitrum, Optimism, Base, Blast, Mantle, zkSync, Linea, Scroll and Taiko, measured live via `newHeads` WebSocket by OpenChainBench." +seo_description: "{{best_name}} posts the fastest block time at {{best_p50}} (p50, 24h) across Arbitrum, Optimism, Base, Blast, Mantle, zkSync, Linea, Scroll and Taiko, measured live via `newHeads` WebSocket by OpenChainBench." status: live diff --git a/answers/which-stablecoin-is-the-most-stable.yml b/answers/which-stablecoin-is-the-most-stable.yml index d7a54f0a..bbf51585 100644 --- a/answers/which-stablecoin-is-the-most-stable.yml +++ b/answers/which-stablecoin-is-the-most-stable.yml @@ -20,7 +20,7 @@ limitations: faq: - q: "Which stablecoin is the most stable right now?" - a: "{{best_name}} currently leads the leaderboard at {{best_p50}} (median per minute worst deviation, 24h) across {{count}} measured stablecoins on USD quoted venues. The leaderboard refreshes every minute against fresh Prometheus samples; the 24h window smooths a single off market tick so the headline reflects sustained peg stability." + a: "{{best_name}} currently holds its peg tightest at {{best_p50}} (median per minute worst deviation, 24h) across {{count}} measured stablecoins on USD quoted venues. The leaderboard refreshes every minute against fresh Prometheus samples; the 24h window smooths a single off market tick so the headline reflects sustained peg stability." - q: "What is stablecoin peg deviation in basis points?" a: "Peg deviation is the absolute distance between a stablecoin's price and $1.00, expressed in basis points where 1 bp equals 0.01%. A stablecoin at $0.9978 has 22 bps of deviation; at $1.0050 it has 50 bps. Tens of bps is normal noise, hundreds of bps is stress, thousands of bps is a depeg event. The bench records both per minute deviation and the worst 1% tail (p99) over 24h, the integration grade number for any product holding inventory in the stable." - q: "How does USDC compare to USDT on stability?" diff --git a/benchmarks/perp-amm-volume-share.yml b/benchmarks/perp-amm-volume-share.yml index 520fba97..685203f6 100644 --- a/benchmarks/perp-amm-volume-share.yml +++ b/benchmarks/perp-amm-volume-share.yml @@ -1,7 +1,7 @@ -# OpenChainBench. Bench № 043 +# OpenChainBench. Bench № 233 slug: perp-amm-volume-share -number: "043" +number: "233" title: Perp AMM volume share, live 24h notional ranked seo_title: "Perp DEX AMM volume 24h ranking 2026" seo_description: "Live 24h volume in USD for AMM-style perp DEX venues: GMX V2, Gains Network, Ostium, Pacifica, SynFutures and KiloEx. Refreshed every 5 minutes. Compares pool-counterparty and synthetic models." diff --git a/src/app/alternatives/[slug]/page.tsx b/src/app/alternatives/[slug]/page.tsx index 05dfd25f..a70beb05 100644 --- a/src/app/alternatives/[slug]/page.tsx +++ b/src/app/alternatives/[slug]/page.tsx @@ -281,11 +281,11 @@ export default async function AlternativePage({

)} - {perpBenchRows.length > 0 && ( + {perpBenchRows.filter((r) => r.value !== null && r.rank !== null).length > 0 && (
{alt.target_product} across benchmarks
- + r.value !== null && r.rank !== null)} />
)} diff --git a/src/app/answers/[slug]/page.tsx b/src/app/answers/[slug]/page.tsx index cdd7fe68..fb686c88 100644 --- a/src/app/answers/[slug]/page.tsx +++ b/src/app/answers/[slug]/page.tsx @@ -375,7 +375,7 @@ export default async function AnswerPage({ /benchmarks/{bench.slug} - , refreshed every minute. + .

)} diff --git a/src/app/products/[slug]/page.tsx b/src/app/products/[slug]/page.tsx index d46b0089..c403473f 100644 --- a/src/app/products/[slug]/page.tsx +++ b/src/app/products/[slug]/page.tsx @@ -110,7 +110,7 @@ export async function generateMetadata({ const benchWord = benchCount === 1 ? "benchmark" : "benchmarks"; const winWord = p.wins === 1 ? "first-place finish" : "first-place finishes"; const winSuffix = p.wins > 0 ? `, ${p.wins} ${winWord}` : ""; - const fallbackDescription = `${p.name} reviewed across ${benchCount} live OpenChainBench ${benchWord}${winSuffix}. Reproducible measurements, open methodology, refreshed every minute.`; + const fallbackDescription = `${p.name} reviewed across ${benchCount} live OpenChainBench ${benchWord}${winSuffix}.`; // Registry descriptions use markdown-flavour backticks for host names // and code snippets (rendered as in the product page body). // Those leak into meta description and social previews as raw backticks diff --git a/src/lib/citation.ts b/src/lib/citation.ts index 09062a88..672811f9 100644 --- a/src/lib/citation.ts +++ b/src/lib/citation.ts @@ -113,7 +113,8 @@ export function headlineSentence(b: Benchmark): string { const top = leader(b); if (!top) return `${b.title}. Awaiting first run.`; const value = fmtUnit(top.value, b.unit); - return `${top.name} leads ${b.metric.toLowerCase()} at ${value} ${windowSuffix(b.unit)} on ${b.title}.`; + const verb = b.higherIsBetter ? "leads" : "posts the lowest"; + return `${top.name} ${verb} ${b.metric.toLowerCase()} at ${value} ${windowSuffix(b.unit)} on ${b.title}.`; } /** Pasteable attribution string. Standard convention: " Source: OpenChainBench (url)". */ diff --git a/src/lib/perp-venue-external.ts b/src/lib/perp-venue-external.ts index 1350acb8..34a4014f 100644 --- a/src/lib/perp-venue-external.ts +++ b/src/lib/perp-venue-external.ts @@ -271,7 +271,7 @@ async function fetchHyperliquidStats(): Promise { const vol24h = ctxs.reduce((s, c) => s + (parseFloat(c.dayNtlVlm ?? "0") || 0), 0); const totalOI = ctxs.reduce((s, c) => s + (parseFloat(c.openInterest ?? "0") || 0), 0); if (vol24h > 0) extraKpis.push({ label: "Volume 24h", value: fmtUsdShort(vol24h) }); - if (totalOI > 0) extraKpis.push({ label: "Open Interest", value: fmtUsdShort(totalOI) }); + if (totalOI > 0) extraKpis.push({ label: "OI (all markets)", value: fmtUsdShort(totalOI) }); extraKpis.push({ label: "Listed assets", value: String(meta.universe?.length ?? ctxs.length) }); } @@ -330,7 +330,7 @@ async function fetchDydxStats(): Promise { const extraKpis: { label: string; value: string }[] = []; if (vol24h > 0) extraKpis.push({ label: "Volume 24h", value: fmtUsdShort(vol24h) }); - if (oi > 0) extraKpis.push({ label: "Open Interest", value: fmtUsdShort(oi) }); + if (oi > 0) extraKpis.push({ label: "OI (all markets)", value: fmtUsdShort(oi) }); if (trades24h > 0) extraKpis.push({ label: "Trades 24h", value: fmtCount(trades24h) }); if (markets) @@ -457,7 +457,7 @@ async function fetchExtendedStats(): Promise { const extraKpis: { label: string; value: string }[] = []; if (vol24h > 0) extraKpis.push({ label: "Volume 24h", value: fmtUsdShort(vol24h) }); - if (oi > 0) extraKpis.push({ label: "Open Interest", value: fmtUsdShort(oi) }); + if (oi > 0) extraKpis.push({ label: "OI (all markets)", value: fmtUsdShort(oi) }); if (perp.length > 0) extraKpis.push({ label: "Perp markets", value: String(perp.length) }); @@ -532,7 +532,7 @@ async function fetchPolymarketStats(): Promise { const extraKpis: { label: string; value: string }[] = []; if (vol24h > 0) extraKpis.push({ label: "Volume 24h", value: fmtUsdShort(vol24h) }); - if (oi > 0) extraKpis.push({ label: "Open Interest", value: fmtUsdShort(oi) }); + if (oi > 0) extraKpis.push({ label: "OI (all markets)", value: fmtUsdShort(oi) }); if (events.length > 0) extraKpis.push({ label: "Active markets", value: String(events.length) }); From 28fe90daf43df9bdea530b377738b7b741739f96 Mon Sep 17 00:00:00 2001 From: Flotapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Sun, 23 Aug 2026 00:34:22 +0200 Subject: [PATCH 3/4] fix: bump aggregate-blob cache key to v2 (flush stale ISR) (#2034) --- src/lib/aggregate-blob.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/aggregate-blob.ts b/src/lib/aggregate-blob.ts index 13eb46fe..ace33ba6 100644 --- a/src/lib/aggregate-blob.ts +++ b/src/lib/aggregate-blob.ts @@ -107,6 +107,6 @@ async function fetchAndProject(): Promise { */ export const loadAggregateFromBlob = unstable_cache( fetchAndProject, - ["aggregate-blob-v1"], + ["aggregate-blob-v2"], { revalidate: 60, tags: ["bench-aggregate", "benchmarks"] }, ); From 26888f28bf512d067fc773d462fd72a2ae13e934 Mon Sep 17 00:00:00 2001 From: Florent Tapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Sun, 23 Aug 2026 00:35:54 +0200 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20/perp-tokens=20hub=20=E2=80=94=20P/?= =?UTF-8?q?E,=20FDV,=20revenue=20for=20Hyperliquid,=20GMX,=20GNS,=20dYdX,?= =?UTF-8?q?=20Drift,=20Ostium?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/logos/drift-perp.webp | Bin 0 -> 8662 bytes public/logos/dydx-perp.svg | 21 ++ public/logos/gains-network-perp.webp | Bin 0 -> 6098 bytes public/logos/gmx-perp.webp | Bin 0 -> 5530 bytes public/logos/hyperliquid-perp.webp | Bin 0 -> 5936 bytes public/logos/ostium-perp.webp | Bin 0 -> 7058 bytes public/logos/synthetix-perp.webp | Bin 0 -> 9162 bytes src/app/perp-tokens/page.tsx | 365 +++++++++++++++++++++++++++ 8 files changed, 386 insertions(+) create mode 100644 public/logos/drift-perp.webp create mode 100644 public/logos/dydx-perp.svg create mode 100644 public/logos/gains-network-perp.webp create mode 100644 public/logos/gmx-perp.webp create mode 100644 public/logos/hyperliquid-perp.webp create mode 100644 public/logos/ostium-perp.webp create mode 100644 public/logos/synthetix-perp.webp create mode 100644 src/app/perp-tokens/page.tsx diff --git a/public/logos/drift-perp.webp b/public/logos/drift-perp.webp new file mode 100644 index 0000000000000000000000000000000000000000..959fbf7eb89b896efb4adc8cc9a0a0b6e5f02619 GIT binary patch literal 8662 zcmV;{At~NcNk&G_ApihZMM6+kP&iD&Apig`f50CAO(d3jA-A{*=7`}RzxQtqLVc0uYTPrQ zA&!iSJwj91nhF1Oq5Xj|niD?P|Cyaj=18=2O7z?KutNi)sGn+kwb%b#y*theOJe&` ze7O4y|0p=BP=zXv3NEY{32H&|aTF+65xO())Q@6(U@UmV7=U=tqWK-=7{$h;P55{U zB4lOM6$l$}gbbr_XA~B({^q;>A>UaU1qf}S{mxsAo(&4)x;mZ|`Ueok002O_utl27 z2PmjF6trz4x#iFL{zDKE6W}zr?T1!2b!rvbVwD879HL~KY?Ezm*)Y^@XiIkeYgya2 zwUM0n`+mt(*wx)L%^YTCW~QT|!^pwR34}SzVW#G8+f}mu|9cn1 z&M@POYZVw~aF}W?T!k4L{7AN~+O}<5IhRsfZ7^W*>T@$QGc&WkwWV#4m@yDL8Y>7} z-Z3C`F|PrAwAOm9rDRW%WUIDq+m?GNrPhYMk1^U@%)GL&*5UlX5NF^?2Rgvm;l?(wmEX#{C|(Ku0{8MtozV)B%A$z2P2aPYA)dO(ZXE?l(X55 zarIeUi-m5&JYFKe8Ks~kz^OhR%aNsc6WWcKWF{yNo9rc;K!X1l^AHeuhnSd@F3>Kw$WwRseSDv_ zrVJ@*2O-fRb9Z954!FBy7Y>((^HQG_Cyeg>&Mn}ADWxz?XvHJ@sp#g17M^x zPQCUhLE2p4ZDcLS^R>SmT{c=J<>g<=ZpQcyIpNwrPd)6>YxBH5rSES-SATD}Ppu!V zzVcPP{~5gRPx_2cMk4r4FBRid0y)SsMo`c_(DWR;JewvR`a)t#LXj~P2f{LPh{)%$ zTo~_kvUex#IMdUU9pEv>(rS>NTowZ318G)S*+G3wI6twO?n=T+n^y^`mB~bzbgKj% zkD*euQ{nvrLZ||lPSdN^LKi?5+i{EZvc27R*PKDoVDqBy$7mq)_+=?Sk7 zI@h7Fi#anhI_H!jSQ%5{*z4GUydXdYF-&U3T+f*3Hhsx@QkJ@?e)Qy>|*GN{7 zF)p$akP?Id9rw{oe;e>7_(=85RYMwT@38++A74uN`WP-Ehk|Y|^vMyguFxu3y=E6{ z2o_z`=DOc-_Iz^aSG~@bU9>6G`o+eBL*Swo>BR^*Oa$tZ9_4Y;_s$Q?&!%JUiy2Lu zTQq(^D}^ArWbdH#V#YT~-LwU&dyf;_jwAbiqfy(TSy#%`iJO+L#_{^-{QBy{&78wc z=l9y~_kpCKmCzU8yP

)ywsqar)8)Sjxl> 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 literal 0 HcmV?d00001 diff --git a/public/logos/dydx-perp.svg b/public/logos/dydx-perp.svg new file mode 100644 index 00000000..f142b1ec --- /dev/null +++ b/public/logos/dydx-perp.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/public/logos/gains-network-perp.webp b/public/logos/gains-network-perp.webp new file mode 100644 index 0000000000000000000000000000000000000000..fed47676a06210efedd28bc3db26e89358470b72 GIT binary patch literal 6098 zcmV;@7cJ;gNk&G>7XScPMM6+kP&iDz7XSb+f50CA2?lK=IZ|f7&+;dH{hmNX|0jUI zK7iDc={tez#5Ge@Hq>zAxClaSmA6Ka(%BIy$?CWe4-u`c7j7d-QlyNN?s=Y>(SNH> zT=5M!w!m#9Ns5%m%=e7`TlO-e;Ka6Vr#bX?|L02}ng4j6j=BgL8o(vH zoRH)UeQ$KL-~+%Ly-POvwW_r#vsf4d1-L``CVn1#3lXLy5_nnziOT?=(&<7$03hCQ z#pOR;uC<&$0KtWzlDPEq&EWn?yoO6ucT79(U)!K19l5M-TZKd@w=3Hy%ZF~(&0 zTfElSQfH~LY$>$_U@4fHnb)AcW^b+4l5R0{4iJu1Qq}&EGwrv6ta-iB7@u@0fx|>#1dto`m{-#Q%g4;IkVVrYscJW z*4-B!DG8S7Kc#^EJfT%x+1S{32mzKAY-xqY)=uc`#tV;mk?KLZzcA0u zM>{;Vy4m%&>--A(vGSk1tBs~W*=gH`?cmOUh%t`IUTa&q&9?gRul(|j_jNy&}3c9q??rk5gBk_^JNjd7h2ef7-cG zJ;8V#hcpvM| zcwE#?DTf?_JXNLQFeFxK@4fr=?(_EU&|CkZPJPPL>q11Ra8SbMg~DM0KuHpf^Oj3G zIs757INydHKmr(eYRlohpJz87PygcjI`1E1yYJgAw}&O$jD7HQ32e#e4b%ZH0H{zH z*YoujsGR*oagTe|-BEI=Jdu$w28}{Q#(mB1k5AY7XyvJgIC}KfxBf({bxt9`k_@(J$(~HO_u*Fd0uv zZ34l701)E}M|r3N2t+tA(-)O%YxBL9+q5)Nj5TLH%YY>S5L!12_0Ie213u?>x!?3I zXRp=Y&WzGh zzgr*t$K3nadOg-S*WTh#1s+%;D|KK61Go&>Vh9~EV1rYr2%b!t7@Nd&6o3=+FaQw1 zMjv+%{=K)}_4jvA_!AcIA8to&yl$J@nq6*(*FGHDRL{0+-kA1H>0lJt0sunjz(WpT zR0ur)6B82(OAY~xJcdfuB#>3%n2^ep@0{V;!jq)%C=-td-mY+OZW{=dmipyXY zdhOUe@16JbbMV|l2oTvPhK3=;9M8s+N7VjwK6i1xzudj-WGEqH5>iepnXXBV_9=VW zgJyfP>(``wQ1CHU!wXZ2)9$&~HdnR0qeLWhj$c0%DUbxooy)kI7)1E*qi%tOzdi@Ql) z%`43486>`xb1t&BB>b$Q)o&ul%ABj zrb9Prx|HFLJe}6q>`o+N6kWll{P>ss)SXw`vx4n3zg`f!H~y68;V3El3ZL)mF}O=LHX#B31JQ|Nxj z@pwJkXXoo`J_A3z45$Hw))FoD`r+;N_J4etx)maJR9e0uYj#tkmNDbw`q1^`AN}qZ zp3xXaEq1Fmlf?2ZQKmZT(j<43QjbYbT4^QfP-v1Tse=*)ikS^Ut`i%tdgA&1&maEP z{n6tui!laN350w{Dm!M;Vgxs@X3Q`Q+AZDl+HdQ;);_sw$IH`}oT;>Bf|4EElvUw6 zl%+%|_hMW$#bl|QsnkoO-BHOY_vWhjsA=^)x$xm(PRA@tl_|=WEn9)@27zM95(O;5 z%@M7Txvh2VTCWP;yWAf7R(osDpR@TJSIpSGOz)w2&28psM@L5_wT5~%_Rvh zc4Ax4t@Ww%dO|M_=3*!BZjNVHtSg+?tFK$z!;8s0(wRzEQc_PqmTZG;0wkb^V7>Wp z_VK<>UMibUOseQFWVFM?H_#nJI}7&pIzRcY^(Nyo^ixcihz(|EIDLU1O$|^a0p>k zhDndDjP_fr-sm~kKe}6cINIW4E%21y+ph~H*g2e0F1h5=)LH_d>#ir+r=zx>yqfvA zI~;H^RG>wh>_^{q*VoIdc=aN^s;a+xefvM!ySs6;*K5V$zAIZX&dtb7nF3=2fMt{s zhk*((M#dNmV@i(nE{iy33|C(l_3*&<`uzTSF;vU!=vEm`YZwd5B}>^=V+%OiIj4jb z5V?a9RgtbvZfoOB4++1ZUC+Pi%I(RHyDcN{f!$ZB3KxSBSTaL9G8tTjHYnKlrz{m_%Aq=QIj;+7|07aE#VF{)JN-8B} zr;(oh&++0fcz(4#ce{|TH9jid>N#1uj08J{d!wu>8P9>ZR4`6k7-L-BO`IOS@^^=R zeR=kY$K%a6EoaeHpVn{WP=H=}@s_Vux^^p(5q<)vk2(Dy%bh<_;8=+k3tI z%RHBl@7|HdG*F6V+$X%Y!}bIn;C=J;3$*wsQ z5_K{=vwAP?J*2(%pQL|M$KSdmdT6e2C4d+T011HEZ!eG?Y^z+sG6e|%3I-_4j{bcP zbB0fDfY4z=EwwRMRIfPlsbEETp~ zauGauifxUo+Z($#4i0s;*XMtF{nlUJeth}oFV`=7*rjEVpuh;etFsuh$HOVGkMdNO z(U5y6w7lv*U-YN`TwGC(kfZ<^Swa%V4qF(f3ff?*DOxzv?n3hy?U%n-zqqnIpEcIg zK0M}zmKXp);JX}$DA@!gB4m)%wzRcyTP)z?f2IqU*;@#?7KedRjzloVCFPO|YgogX z$@Ed(4`=^f|MRaOKm3RIt5y%bpO%7Cs1QhC01WY+%;I|19)K)}xHMQEOA$TwuoI#? zG+5m9l<)EM-zD!NncdtTahe2hhlym^F%aNu zO~lnZ`-x)&DjQNn$IiOGPulm7Ut2r7>=sd|oL$mBk$-)A@<{Y;JmA8#@Nw%YssFPAk$H#HFr;+7l`Y7|l z=KH;aV_dE-p!(Ab?-n=~d7fyT!{pUGDBi6=?q8ioZ;A;mVl~hGRF$W@4ah_PR za94*2nkNG7zW>gB8pjW!q*Qg~d1eo_^my@~DBnhYt##2`6#K?3Y)z?f3NMLQ$v~p(aCYC5^s;3F{!5*XLSkzizD%eJUv(ztSera$cwXt?~XO<&waWhC$ zvVgDs)ECyhW3HYx)&wLlBwk)Vw%XYdWA5-_py^Io$4@%_|`+0-k6iMOIlME zz}J5t=WTx0PkUNGs&qV>SPr$*t2?$V`vBrLvLsb^M>%kbP}2;l02c`08?#h39ttHQ zB$0Es%X*!E?$=X;J7WP+geA)oLCQ{9lK4j8j7r(58cKq_iimTUcY1ua*RGv`+zDaH zAq0Stk--prBLJN4q{>hTRbg8!FJoDT^N2fHvJ{4r1OONjSONqqNP{EQki)(3GavHq2@>ZUX=S761SM0$5e%&VXW$n94+{c_dYn844Rq z(g^nBdVYMqw>j^>_o=;}Q$*zcLJer=!}r=(xvu-=^ZCiSyVKWns1`IqXsWT7y#y6Q zM((B_Xv-z`dtXYai3(Z>3|duHb$H;l3-`&VLbZnueaMp^?>~(9>!#^__aw71vat3e zP8Zdw$~_$=ny*F~>=K*m&gXaQc{Ck!)l;TAHh(^k+UHd#9nbGM{0X2iql6IFK1qKU*glI82S!}uYmN)L}nby{^kGDOYja6^%pFj8h zs0W1Iak7GV?4tA7T`@}+k{}VGrK9celmQF?k2A<&*)u-+EXPZdE62QH{L<=jH$N@%q`@|IV9L5+_s=wBC%`SnFHYdmiQq9Q1(G)IQs;UT^ct z=3Ab0x_dL%hkaP1o-TE?*)YbI!^W~eATYp+B-guhUmbDTc8p6&fe}F9!$Zmv9)Z*t z-_NW(SjSs5PZn`xd{`A!)#8w`QIImlNHPE`#~<&{Ij4ibFisybkZ^$FHc*cM5xjjZ z#ct@XN4@pFUbb^scZ*{dmkO)hXL{Q3rWs2`f)v;Te3cwaBXJNAhl(pg9CEq0y)8Ur zaI=5@_}}4!7fY}2bC2WLJ>+>K?=@4A%EUI6<#gd9%?6M#0>nx{$%Zvw9T6WtJ^&K;{9g9q<4D{bPUs{@?f4!((pUk8OrX$FcYQlQedGGC*RS6G%e{0zOf410zkdA;)n`xDZfDhM z>S4c9l!FM?CGEUqh1d{8@KpgJV_{<%31tr#1_2rK~#4+sjkxBlFpzI^tt zG@jl98H50A0GRU86m^3F-`vQeune|hWMq^u7ep*sF)7Lf1RRV=F|Z)EFaPnsAM-0Q z90oevLZU!0bu`yf+$=}nzDAfJlk0nd^P!R;`)QFj}5pdH{eT z#H8);ulV(*t#_L(Z7o#I2;4BT1yoZ51(DCFeb6|@xL`~Q839H`sp30qM%3I<>1Pg8dI|NQi*+RfO2je${@NcH() zu4=^4QoW;zhI0_=5geszJRyDS`-f-#GoPQA`KMUFM6`v3r9+y;j_NRruaGXXF6ZAa zf8_USabekt6%IQ{ghrFn5s}N6hwFKZF6Y3IJb<7z%~g|-AE!O%p5}a19DCMA1X7NL zW#n`<6#xUQKFDp?IpxQb^J#5c>8@h83ILb`0zeLAKI4q)sBL5mT{Md&&Uqxgy(<;9LQru6~_A>Oy$(+sGQ5 zeK;p-VPIl_U44TY^l~Yl`*`#I_nAhwX=jPsz+)n6k<+ba4*#*dv6y+Dxc6z_i12!j zWNdpmhl(AZ-xx2{M%7jjD-gqj*X91?TDw2oKf;$`dl>dt*`H7cRxOAHs}^kMe0q$2 zWTM9|wG0vr9+VgaMUz_2e6Fo_++X{XnFpMYb9r}U+uXg~&L8^MFW=(d1Hp|_QL9wn z~@1%3%pUPLsp;m#H{6;2_0PNfwqYm7I=P z8Ecx3Yi*sjd+dI|nAwZ}ApA4G_{!Q+Oc6s3Xa)2&)xCDV5Rbnf^;^2^onLLuy^oY0 z#I5o!Mg}IHx%uqtK1*ubLyX2gPymOB0T51Vp^d??Kn=%rbf$LTnfW?gXa}k-yP}%X z3d^u9C`ZMS<;VDgOMlVMe+01gfhVE_OC literal 0 HcmV?d00001 diff --git a/public/logos/gmx-perp.webp b/public/logos/gmx-perp.webp new file mode 100644 index 0000000000000000000000000000000000000000..20a9ed2ed53d58d348fd249fbf3cf784e19d01b7 GIT binary patch literal 5530 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 cL6k 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 literal 0 HcmV?d00001 diff --git a/public/logos/ostium-perp.webp b/public/logos/ostium-perp.webp new file mode 100644 index 0000000000000000000000000000000000000000..29731961f97851d88312a52b0b5c26bc45c8a886 GIT binary patch literal 7058 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 literal 0 HcmV?d00001 diff --git a/public/logos/synthetix-perp.webp b/public/logos/synthetix-perp.webp new file mode 100644 index 0000000000000000000000000000000000000000..8c430bd73ef0c6e6766fd313da3717fd612ea6dc GIT binary patch literal 9162 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'q5=GV8-ldNwHcwupI(FNWjU}=cjcll`; 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 U^q0$5ygdS-S33;kCO3>S0K%-+y#N3J literal 0 HcmV?d00001 diff --git a/src/app/perp-tokens/page.tsx b/src/app/perp-tokens/page.tsx new file mode 100644 index 00000000..8ce2f358 --- /dev/null +++ b/src/app/perp-tokens/page.tsx @@ -0,0 +1,365 @@ +import Link from "next/link"; +import Image from "next/image"; +import { pageMetadata } from "@/lib/page-metadata"; +import { safeJsonLd, buildBreadcrumbJsonLd } from "@/lib/jsonld"; +import { SITE } from "@/data/site"; + +const DESCRIPTION = + "Perp DEX token valuation: FDV, protocol revenue, and P/E ratio for Hyperliquid, GMX, dYdX, Gains Network and more. Live from DeFiLlama, updated hourly."; + +export const metadata: import("next").Metadata = pageMetadata({ + path: "/perp-tokens", + title: "Perp DEX token P/E ratios 2026: Hyperliquid, GMX, dYdX, GNS", + description: DESCRIPTION, +}); + +export const revalidate = 3600; + +const PROTOCOLS: { + slug: string; + name: string; + token: string; + llamaSlug: string; + cgId: string | null; + logo: string; + chains: string[]; +}[] = [ + { + slug: "hyperliquid", + name: "Hyperliquid", + token: "HYPE", + llamaSlug: "hyperliquid", + cgId: "hyperliquid", + logo: "/logos/hyperliquid-perp.webp", + chains: ["Hyperliquid L1"], + }, + { + slug: "gmx", + name: "GMX", + token: "GMX", + llamaSlug: "gmx", + cgId: "gmx", + logo: "/logos/gmx-perp.webp", + chains: ["Arbitrum", "Avalanche"], + }, + { + slug: "gains-network", + name: "Gains Network", + token: "GNS", + llamaSlug: "gains-network", + cgId: "gains-network", + logo: "/logos/gains-network-perp.webp", + chains: ["Arbitrum", "Polygon", "Base"], + }, + { + slug: "dydx", + name: "dYdX", + token: "DYDX", + llamaSlug: "dydx", + cgId: "dydx", + logo: "/logos/dydx-perp.svg", + chains: ["dYdX Chain", "Ethereum"], + }, + { + slug: "drift", + name: "Drift Protocol", + token: "DRIFT", + llamaSlug: "drift-protocol", + cgId: "drift-protocol", + logo: "/logos/drift-perp.webp", + chains: ["Solana"], + }, + { + slug: "ostium", + name: "Ostium", + token: "OST", + llamaSlug: "ostium", + cgId: null, + logo: "/logos/ostium-perp.webp", + chains: ["Arbitrum"], + }, +]; + +type ProtocolRow = { + slug: string; + name: string; + token: string; + logo: string; + chains: string[]; + llamaSlug: string; + fdv: number | null; + rev30dAvgDay: number | null; + annualRev: number | null; + pe: number | null; + rev24h: number | null; +}; + +async function fetchLlamaRevenue( + slug: string +): Promise<{ rev24h: number | null; avg30d: number | null }> { + try { + const res = await fetch( + `https://api.llama.fi/summary/fees/${slug}?dataType=dailyRevenue`, + { next: { revalidate: 3600 } } + ); + if (!res.ok) return { rev24h: null, avg30d: null }; + const d = await res.json(); + const rev24h: number | null = d.total24h ?? null; + const chart: [number, number][] = d.totalDataChart ?? []; + const last30 = chart.slice(-30).map(([, v]) => v).filter(Boolean); + const avg30d = + last30.length > 0 + ? last30.reduce((a, b) => a + b, 0) / last30.length + : null; + return { rev24h, avg30d }; + } catch { + return { rev24h: null, avg30d: null }; + } +} + +async function fetchCGFdv(cgId: string): Promise { + try { + const res = await fetch( + `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=${cgId}&per_page=1&sparkline=false`, + { next: { revalidate: 3600 } } + ); + if (!res.ok) return null; + const d = await res.json(); + const coin = d[0]; + if (!coin) return null; + return coin.fully_diluted_valuation ?? coin.market_cap ?? null; + } catch { + return null; + } +} + +function fmtB(v: number | null): string { + if (v === null) return "—"; + if (v >= 1e9) return `$${(v / 1e9).toFixed(1)}B`; + if (v >= 1e6) return `$${(v / 1e6).toFixed(0)}M`; + return `$${(v / 1e3).toFixed(0)}K`; +} + +function fmtPE(v: number | null): string { + if (v === null) return "—"; + return `${v.toFixed(1)}x`; +} + +export default async function PerpTokensPage() { + const rows: ProtocolRow[] = await Promise.all( + PROTOCOLS.map(async (p) => { + const [{ rev24h, avg30d }, fdv] = await Promise.all([ + fetchLlamaRevenue(p.llamaSlug), + p.cgId ? fetchCGFdv(p.cgId) : Promise.resolve(null), + ]); + const annualRev = avg30d ? avg30d * 365 : null; + const pe = + fdv && annualRev && annualRev > 0 ? fdv / annualRev : null; + return { + ...p, + fdv, + rev30dAvgDay: avg30d, + annualRev, + pe, + rev24h, + }; + }) + ); + + const sorted = [...rows].sort( + (a, b) => (b.annualRev ?? -1) - (a.annualRev ?? -1) + ); + + const breadcrumbLd = { + "@context": "https://schema.org", + ...buildBreadcrumbJsonLd([ + { name: "Home", item: SITE.url }, + { name: "Perp DEX tokens", item: `${SITE.url}/perp-tokens` }, + ]), + }; + + return ( +
+