From 373cb9ecb5d38e4eefd4446e58b3bfe6933c5776 Mon Sep 17 00:00:00 2001 From: Florent Tapponnier Date: Wed, 24 Jun 2026 15:14:37 +0200 Subject: [PATCH] feat(perps): cherry-pick perp cluster sprint 1+2 to prod Brings the full /perps hub from dev to main: - /perps hub page with cohort summary, leaderboard, By asset tab, age badge - 3 new bench specs (perp-volume-share #041, perp-open-interest #042, perp-funding-stability #043) - Per-product PerpVenueSection wired into /products/ for 16 perp DEX venues - 9 new perp DEX registry entries (drift, vertex, edgex, extended, aevo, pacifica, variational, ostium, grvt) - 13 logo assets, SVG-first - Footer + sitemap entries for /perps - Hub pill on per-product pages Backed by perp-cohort-stats harness on Railway (volume, OI, fees, active markets, funding via Mobula aggregator across 12 venues). --- benchmarks/perp-funding-stability.yml | 207 ++++++++++ benchmarks/perp-open-interest.yml | 119 ++++++ benchmarks/perp-volume-share.yml | 120 ++++++ public/logos/aevo.svg | 11 + public/logos/aster.svg | 25 ++ public/logos/drift.svg | 5 + public/logos/edgex.jpg | Bin 0 -> 2979 bytes public/logos/extended.svg | 1 + public/logos/gains.svg | 1 + public/logos/grvt.jpg | Bin 0 -> 5682 bytes public/logos/hyperliquid.png | Bin 4768 -> 7469 bytes public/logos/ostium.png | Bin 0 -> 11350 bytes public/logos/pacifica.svg | 8 + public/logos/paradex.svg | 17 + public/logos/variational.png | Bin 0 -> 5172 bytes public/logos/vertex.png | Bin 0 -> 11282 bytes src/app/perps/page.tsx | 330 ++++++++++++++++ src/app/products/[slug]/page.tsx | 33 ++ src/app/sitemap.ts | 1 + src/components/perp-by-asset-table.tsx | 261 +++++++++++++ src/components/perp-hub-tabs.tsx | 96 +++++ src/components/perp-venue-bench-cards.tsx | 98 +++++ src/components/perp-venue-kpi-strip.tsx | 128 ++++++ src/components/perp-venue-section.tsx | 161 ++++++++ src/components/perp-venues-leaderboard.tsx | 429 +++++++++++++++++++++ src/components/site-footer.tsx | 1 + src/data/provider-registry.ts | 56 +++ src/lib/logo-manifest.ts | 17 +- src/lib/perp-stats.ts | 391 +++++++++++++++++++ src/lib/perp-venue-context.ts | 158 ++++++++ src/lib/perp-venue-data.ts | 123 ++++++ 31 files changed, 2794 insertions(+), 3 deletions(-) create mode 100644 benchmarks/perp-funding-stability.yml create mode 100644 benchmarks/perp-open-interest.yml create mode 100644 benchmarks/perp-volume-share.yml create mode 100644 public/logos/aevo.svg create mode 100644 public/logos/aster.svg create mode 100644 public/logos/drift.svg create mode 100644 public/logos/edgex.jpg create mode 100644 public/logos/extended.svg create mode 100644 public/logos/gains.svg create mode 100644 public/logos/grvt.jpg create mode 100644 public/logos/ostium.png create mode 100644 public/logos/pacifica.svg create mode 100644 public/logos/paradex.svg create mode 100644 public/logos/variational.png create mode 100644 public/logos/vertex.png create mode 100644 src/app/perps/page.tsx create mode 100644 src/components/perp-by-asset-table.tsx create mode 100644 src/components/perp-hub-tabs.tsx create mode 100644 src/components/perp-venue-bench-cards.tsx create mode 100644 src/components/perp-venue-kpi-strip.tsx create mode 100644 src/components/perp-venue-section.tsx create mode 100644 src/components/perp-venues-leaderboard.tsx create mode 100644 src/lib/perp-stats.ts create mode 100644 src/lib/perp-venue-context.ts create mode 100644 src/lib/perp-venue-data.ts diff --git a/benchmarks/perp-funding-stability.yml b/benchmarks/perp-funding-stability.yml new file mode 100644 index 00000000..56a537bc --- /dev/null +++ b/benchmarks/perp-funding-stability.yml @@ -0,0 +1,207 @@ +# OpenChainBench. Bench № 043 + +slug: perp-funding-stability +number: "043" +title: Perp DEX funding stability, 7-day stddev of ETH funding ranked +seo_title: "Perp DEX funding stability 2026: ETH funding stddev across 12 venues ranked" +seo_description: "Live 7-day standard deviation of ETH perpetual futures funding rate in bps across 12 major venues. Lower means more stable funding for carry traders." +subtitle: 7-day standard deviation of ETH funding rate, in basis points per 24h, across the Mobula funding cohort. Lower means funding stays in a tight band, the carry trader's preferred signal. +category: Trading +status: live +metric: 7d ETH funding stddev +unit: bps +higher_is_better: false + +disclaimer: | + Stability is not directionality. A venue with persistently positive but tight-banded funding ranks better here than one that flips between positive and negative every settlement, even if the second venue offers better average carry. Read alongside perp-funding for direction and average level. + +seo_intro: | + This benchmark ranks perp venues by how tightly their ETH funding + rate clusters over the trailing 7 days. Average funding tells you + which side gets paid; stability tells you how reliably. A venue + whose 24h hold cost wanders 15 bps in a week is harder to carry + trade than one that holds within 3 bps even if both average the + same number. The bench reads the same normalized series as + perp-funding (per-venue hold cost in bps per 24h) and exposes + stddev_over_time of that series on a 7 day window for ETH. The + Mobula funding cohort is 12 venues: Hyperliquid, Binance, Bybit, + OKX, dYdX v4, Paradex, Aster, Drift, Vertex, EdgeX, Extended and + Aevo. Lower is better. + +abstract: | + The bench reuses the normalized 24h ETH funding series from + perp-funding and adds a 12-venue cohort: Hyperliquid, Binance, + Bybit, OKX, dYdX v4, Paradex, Aster, Drift, Vertex, EdgeX, Extended + and Aevo. For each venue it publishes the 7 day rolling standard + deviation of the ETH hold-24h gauge, in bps. Sign is preserved on + the underlying series; the ranking metric is the magnitude of the + swing, not its direction. Lower means the venue's funding stayed in + a tight band, the cleanest signal for funding-rate arbitrage and + basis trades. Cadence and freshness inherit from the upstream + funding scrape (60 second poll, 30 second Prom scrape). + +methodology: + - "Source. Same upstream as perp-funding: each venue's public funding endpoint polled every 60 seconds, normalized to bps per hour and per 24h hold, sign preserved." + - "Metric. stddev_over_time(perp_venue_funding_24h_bps{asset=\"ETH\"}[7d]) per venue. The 7d window smooths intraday noise but reacts to regime shifts within a week." + - "Sign handling. The underlying series is signed (positive means longs pay). Stability measures the swing, so the ranking uses the unsigned stddev. Average direction and level are the perp-funding bench." + - "Cohort. 12 venues: Hyperliquid, Binance, Bybit, OKX, dYdX v4, Paradex, Aster on the CEX-plus-orderbook side; Drift, Vertex, EdgeX, Extended and Aevo on the onchain-perp side. All quote ETH funding with documented intervals." + - "Cadence. The upstream funding harness polls every 60 seconds; Prometheus scrapes every 30 seconds. The 7 day stddev refreshes on every scrape." + - "Failures. A venue whose upstream funding feed errors keeps its last gauge value; the perp_venue_health gauge drops to 0 and the leaderboard tags the row stale." + - "Reproducibility. The harness emits perp_venue_funding_24h_bps with labels venue and asset; the bench query is the stddev over 7d on that series with asset=ETH pinned." + +findings: + - "{{best_name}} currently has the tightest ETH funding band at {{best_p50}} stddev (7d)." + - "{{name:hyperliquid}} sits at {{p50:hyperliquid}} stddev (7d) on ETH. Hourly settlement means rapid reaction to skew but tight clustering once the book is calm." + - "{{name:binance}} sits at {{p50:binance}} stddev (7d). Deepest book in the field anchors the rate." + - "Outliers on this bench are the venues to watch for funding arbitrage: a wider band means larger spreads to harvest against the cohort median." + +source: https://github.com/ChainBench/OpenChainBench/tree/main/benchmarks/perp-funding-stability.yml + +prometheus: + window: 24h + expected_freshness_seconds: 3600 + +faq: + - q: "What does this benchmark measure?" + a: "How tightly each venue's ETH funding rate clusters over the trailing 7 days. The ranking metric is the standard deviation of the normalized 24h hold cost in bps. Lower is better." + - q: "Why stddev instead of average?" + a: "Average funding is the perp-funding bench. This one ranks stability: a venue whose hold cost swings 20 bps in a week is harder to carry trade than one that holds within 3 bps. Both views matter." + - q: "Why 7d window?" + a: "Long enough to capture a full funding cycle (typically 8h settlements across 21 cycles), short enough to react to regime shifts within a week. 30d would smooth too much and hide stress windows." + - q: "Why only ETH?" + a: "ETH is the deepest perp pair on every venue in the cohort. BTC and SOL have noisier feeds on some smaller venues, which would contaminate the cross-venue ranking. BTC and SOL stability are companion panels rather than the headline." + - q: "Is a low stddev always good?" + a: "Low stddev means predictable funding, which is what most carry traders want. But a stable rate of 0 bps is less useful than a stable rate of negative 10 bps; combine this view with perp-funding to size the actual opportunity." + +providers: + - slug: hyperliquid + name: Hyperliquid + tag: HyperBFT L1 perp DEX, hourly funding + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"hyperliquid\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="hyperliquid",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="hyperliquid",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="hyperliquid"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="hyperliquid",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="hyperliquid",asset="ETH"}[7d]) + + - slug: binance + name: Binance + tag: Largest CEX perp book, 8h funding + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"binance\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="binance",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="binance",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="binance"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="binance",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="binance",asset="ETH"}[7d]) + + - slug: bybit + name: Bybit + tag: USDT linear perps, interval per instrument + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"bybit\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="bybit",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="bybit",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="bybit"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="bybit",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="bybit",asset="ETH"}[7d]) + + - slug: okx + name: OKX + tag: USDT swaps, 8h funding + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"okx\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="okx",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="okx",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="okx"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="okx",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="okx",asset="ETH"}[7d]) + + - slug: dydx + name: dYdX v4 + tag: Appchain order book perps, hourly funding + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"dydx\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="dydx",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="dydx",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="dydx"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="dydx",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="dydx",asset="ETH"}[7d]) + + - slug: paradex + name: Paradex + tag: Starknet L2 perps, 8h funding + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"paradex\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="paradex",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="paradex",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="paradex"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="paradex",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="paradex",asset="ETH"}[7d]) + + - slug: aster + name: Aster + tag: BNB Chain perps, Binance compatible API + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"aster\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="aster",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="aster",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="aster"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="aster",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="aster",asset="ETH"}[7d]) + + - slug: drift + name: Drift + tag: Solana perp DEX, hybrid AMM and orderbook + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"drift\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="drift",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="drift",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="drift"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="drift",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="drift",asset="ETH"}[7d]) + + - slug: vertex + name: Vertex + tag: Arbitrum perp and spot orderbook + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"vertex\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="vertex",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="vertex",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="vertex"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="vertex",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="vertex",asset="ETH"}[7d]) + + - slug: edgex + name: EdgeX + tag: zkSync perp DEX + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"edgex\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="edgex",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="edgex",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="edgex"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="edgex",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="edgex",asset="ETH"}[7d]) + + - slug: extended + name: Extended + tag: Starknet perp DEX (formerly X10) + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"extended\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="extended",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="extended",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="extended"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="extended",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="extended",asset="ETH"}[7d]) + + - slug: aevo + name: Aevo + tag: OP Stack perp DEX with options + formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"aevo\",asset=\"ETH\"} over a 7d window." + queries: + p50: stddev_over_time(perp_venue_funding_24h_bps{venue="aevo",asset="ETH"}[7d]) + mean: stddev_over_time(perp_venue_funding_24h_bps{venue="aevo",asset="ETH"}[7d]) + success: avg_over_time(perp_venue_health{venue="aevo"}[24h]) + sample_size: count_over_time(perp_venue_funding_24h_bps{venue="aevo",asset="ETH"}[24h]) + series: stddev_over_time(perp_venue_funding_24h_bps{venue="aevo",asset="ETH"}[7d]) diff --git a/benchmarks/perp-open-interest.yml b/benchmarks/perp-open-interest.yml new file mode 100644 index 00000000..47b24f0d --- /dev/null +++ b/benchmarks/perp-open-interest.yml @@ -0,0 +1,119 @@ +# OpenChainBench. Bench № 042 + +slug: perp-open-interest +number: "042" +title: Perp DEX open interest, live USD notional ranked +seo_title: "Perp DEX open interest 2026: Hyperliquid, Lighter, GMX, gains.trade ranked" +seo_description: "Live perpetual futures open interest in USD across Hyperliquid, Lighter, GMX v2 and gains.trade. Public API sourced, refreshed every 5 minutes." +subtitle: Live aggregate open interest in USD across major decentralized perpetual futures venues. Higher means more notional sits open. Read live from each venue's public API. +category: Trading +status: live +metric: Open interest +unit: usd +higher_is_better: true + +seo_intro: | + This benchmark ranks the major onchain perp venues by aggregate open + interest, in USD. Open interest is the canonical depth-of-market + number for perpetual futures: it tells you how much notional sits + open right now, on every market, on a given venue. We poll each + venue's public API every 5 minutes, sum open interest across all + listed perps, and publish one gauge per venue. Hyperliquid, Lighter, + GMX v2 and gains.trade are the cohort. Headline number is the 24h + average of the live OI gauge so a single noisy print does not move + the ranking. + +abstract: | + The bench polls four perp DEX venues every 5 minutes for live open + interest and exposes a USD-aggregated gauge per venue. Sources: + Hyperliquid info metaAndAssetCtxs (openInterest per asset, summed in + USD), Lighter orderBookDetails (open interest per market), GMX + Subsquid synthetics-arbitrum (openInterest by market), gains.trade + onchain reads aggregated by indexer. Each value carries a freshness + timestamp and a health gauge so a stale or errored venue does not + poison the leaderboard. Higher is better. + +methodology: + - "Cadence: every 5 minutes per venue in parallel, 10 second timeout per request." + - "Hyperliquid: info metaAndAssetCtxs, openInterest summed across all assets and priced in USD using the venue's own mark price." + - "Lighter: orderBookDetails per market, open interest summed across markets in USD." + - "GMX v2: synthetics-arbitrum subgraph, openInterestUSD summed across markets." + - "gains.trade: onchain indexer over Gains v8 contracts on Base, open interest summed across pairs in USD." + - "Headline. avg_over_time of the live OI gauge over the last 24 hours, so a one-print spike does not move the ranking. The Series tab plots the raw gauge." + - "Failures. A venue that errors or times out keeps its last gauge value and its perp_venue_health gauge drops to 0; the leaderboard tags it as stale." + +findings: + - "{{best_name}} currently leads the cohort at {{best_p50}} of open interest (24h average)." + - "{{name:hyperliquid}} sits at {{p50:hyperliquid}} of open interest. HyperBFT orderbook is the deepest decentralized perp venue." + - "{{name:lighter}} clocks {{p50:lighter}} of open interest. Fully onchain orderbook on zkSync." + - "{{name:gmx}} sits at {{p50:gmx}} of open interest. Pool-based execution on Arbitrum and Avalanche." + - "{{name:gains}} sits at {{p50:gains}} of open interest. Synthetic perps on Base." + +source: https://github.com/ChainBench/OpenChainBench/tree/main/benchmarks/perp-open-interest.yml + +prometheus: + window: 24h + expected_freshness_seconds: 1800 + +faq: + - q: "What does this benchmark measure?" + a: "The live aggregate open interest of major perp DEX venues in USD. Headline is the 24h average of the live OI gauge so single prints do not skew the ranking." + - q: "How is open interest different from volume?" + a: "Volume counts every trade that crosses the book during a window. Open interest counts notional that currently sits open, regardless of when it was opened. A high-volume venue with high turnover can carry lower OI than a slower venue with sticky positions." + - q: "Why these four venues?" + a: "Hyperliquid, Lighter, GMX v2 and gains.trade are the cohort whose public APIs expose open interest cleanly enough to compare without backfilling. Other venues join as their endpoints document the same series." + - q: "Is OI a good proxy for venue health?" + a: "It is one of the cleanest. A venue can spike volume with wash trading or incentive programs, but real OI is harder to fake because it ties up margin. Compared against perp-volume-share, persistent OI dominance signals real position-holding flow rather than turnover." + +providers: + - slug: hyperliquid + name: Hyperliquid + tag: HyperBFT L1 perp DEX + formula: "Open interest from Hyperliquid info metaAndAssetCtxs, summed across all assets and priced in USD using the venue's mark price; headline is the 24h time average." + queries: + p50: avg_over_time(perp_venue_oi_usd{venue="hyperliquid"}[24h]) + p90: quantile_over_time(0.90, perp_venue_oi_usd{venue="hyperliquid"}[24h]) + p99: quantile_over_time(0.99, perp_venue_oi_usd{venue="hyperliquid"}[24h]) + mean: avg_over_time(perp_venue_oi_usd{venue="hyperliquid"}[24h]) + success: avg_over_time(perp_venue_health{venue="hyperliquid"}[24h]) + sample_size: count_over_time(perp_venue_oi_usd{venue="hyperliquid"}[24h]) + series: perp_venue_oi_usd{venue="hyperliquid"} + + - slug: lighter + name: Lighter + tag: zk-rollup, zero taker fee + formula: "Open interest from Lighter orderBookDetails per market, summed across markets in USD; headline is the 24h time average." + queries: + p50: avg_over_time(perp_venue_oi_usd{venue="lighter"}[24h]) + p90: quantile_over_time(0.90, perp_venue_oi_usd{venue="lighter"}[24h]) + p99: quantile_over_time(0.99, perp_venue_oi_usd{venue="lighter"}[24h]) + mean: avg_over_time(perp_venue_oi_usd{venue="lighter"}[24h]) + success: avg_over_time(perp_venue_health{venue="lighter"}[24h]) + sample_size: count_over_time(perp_venue_oi_usd{venue="lighter"}[24h]) + series: perp_venue_oi_usd{venue="lighter"} + + - slug: gmx + name: GMX v2 + tag: Synthetics on Arbitrum, oracle-priced + formula: "openInterestUSD from the GMX synthetics-arbitrum subgraph summed across markets; headline is the 24h time average." + queries: + p50: avg_over_time(perp_venue_oi_usd{venue="gmx"}[24h]) + p90: quantile_over_time(0.90, perp_venue_oi_usd{venue="gmx"}[24h]) + p99: quantile_over_time(0.99, perp_venue_oi_usd{venue="gmx"}[24h]) + mean: avg_over_time(perp_venue_oi_usd{venue="gmx"}[24h]) + success: avg_over_time(perp_venue_health{venue="gmx"}[24h]) + sample_size: count_over_time(perp_venue_oi_usd{venue="gmx"}[24h]) + series: perp_venue_oi_usd{venue="gmx"} + + - slug: gains + name: gains.trade + tag: Synthetic perps on Base + formula: "Open interest across Gains v8 pairs on Base, read onchain and summed in USD; headline is the 24h time average." + queries: + p50: avg_over_time(perp_venue_oi_usd{venue="gains"}[24h]) + p90: quantile_over_time(0.90, perp_venue_oi_usd{venue="gains"}[24h]) + p99: quantile_over_time(0.99, perp_venue_oi_usd{venue="gains"}[24h]) + mean: avg_over_time(perp_venue_oi_usd{venue="gains"}[24h]) + success: avg_over_time(perp_venue_health{venue="gains"}[24h]) + sample_size: count_over_time(perp_venue_oi_usd{venue="gains"}[24h]) + series: perp_venue_oi_usd{venue="gains"} diff --git a/benchmarks/perp-volume-share.yml b/benchmarks/perp-volume-share.yml new file mode 100644 index 00000000..752115bb --- /dev/null +++ b/benchmarks/perp-volume-share.yml @@ -0,0 +1,120 @@ +# OpenChainBench. Bench № 041 + +slug: perp-volume-share +number: "041" +title: Perp DEX volume share, live 30-day rolling notional ranked +seo_title: "Perp DEX volume 2026: Hyperliquid, Lighter, GMX, gains.trade ranked by 30d notional" +seo_description: "Live 30-day rolling perp DEX volume across Hyperliquid, Lighter, GMX v2 and gains.trade in USD notional. Public API sourced, refreshed every 5 minutes." +subtitle: 30-day rolling perpetual futures notional volume in USD across major decentralized venues. Higher means more flow. Read live from each venue's public API. +category: Trading +status: live +metric: 30d perp volume +unit: usd +higher_is_better: true + +seo_intro: | + This benchmark ranks the major onchain perp venues by 30-day rolling + notional volume, in USD. Volume is the cleanest single-number proxy + for where perpetual futures flow actually lives today. We poll each + venue's public API every 5 minutes, sum the trailing 30 days of taker + notional in USD, and publish a single gauge per venue. Hyperliquid, + Lighter, GMX v2 and gains.trade are the cohort. Headline number is + the 24h average of the 30d rolling sum, so a single noisy print does + not move the ranking. The companion benches price the cost side + (perp-fees for opening, perp-funding for holding); this one prices + flow. + +abstract: | + The bench polls four perp DEX venues every 5 minutes for cumulative + taker notional and exposes a rolling 30 day USD sum per venue. + Sources: Hyperliquid info dayNtlVlm (per-asset day notional, summed + and rolled into 30d), Lighter public stats endpoint (24h volume per + market, rolled), GMX Subsquid synthetics-arbitrum (positionVolume by + day), gains.trade onchain reads aggregated by indexer. Each value + carries a freshness timestamp and a health gauge so a stale or + errored venue does not poison the leaderboard. Higher is better. + +methodology: + - "Cadence: every 5 minutes per venue in parallel, 10 second timeout per request." + - "Hyperliquid: info dayNtlVlm summed across all assets, rolled into a 30 day window via Prometheus sum_over_time on the daily gauge." + - "Lighter: public stats endpoint, 24h volume per market, summed across markets and rolled into 30 days the same way." + - "GMX v2: synthetics-arbitrum subgraph, positionVolume aggregated per day across all markets, rolled into 30 days." + - "gains.trade: onchain indexer over Gains v8 contracts on Base, taker notional summed per day and rolled." + - "Headline. avg_over_time of the rolling 30 day sum over the last 24 hours, so a one-print spike does not move the ranking. The Series tab plots the raw rolling sum." + - "Failures. A venue that errors or times out keeps its last gauge value and its perp_venue_health gauge drops to 0; the leaderboard tags it as stale." + +findings: + - "{{best_name}} currently leads the cohort at {{best_p50}} of 30d notional (24h average)." + - "{{name:hyperliquid}} sits at {{p50:hyperliquid}} of 30d notional, the deepest decentralized perp book in the field." + - "{{name:lighter}} clocks {{p50:lighter}} of 30d notional. Zero taker fee plus a fully onchain orderbook on zkSync." + - "{{name:gmx}} sits at {{p50:gmx}} of 30d notional. Pool-based execution on Arbitrum and Avalanche." + - "{{name:gains}} sits at {{p50:gains}} of 30d notional. Synthetic perps on Base with onchain fee reads." + +source: https://github.com/ChainBench/OpenChainBench/tree/main/benchmarks/perp-volume-share.yml + +prometheus: + window: 24h + expected_freshness_seconds: 1800 + +faq: + - q: "What does this benchmark measure?" + a: "The 30 day rolling notional volume of major perp DEX venues in USD. Headline is the 24h average of the rolling 30d sum so single prints do not skew the ranking." + - q: "Why 30 day rolling instead of daily?" + a: "Daily perp volume is too noisy for ranking, a single thin Sunday can flip positions. The 30 day window smooths the cycle and matches the cadence at which serious flow makers compare venues." + - q: "Why these four venues?" + a: "Hyperliquid, Lighter, GMX v2 and gains.trade are the cohort whose public APIs expose taker notional cleanly enough to compare without backfilling. Other venues join as their endpoints document the same series." + - q: "Is this the same as DeFiLlama volume?" + a: "Methodology is similar in spirit but each venue is queried directly here, not via an aggregator. Numbers should sit close to DeFiLlama on most days, divergences usually mean a downstream feed lagged." + +providers: + - slug: hyperliquid + name: Hyperliquid + tag: HyperBFT L1 perp DEX + formula: "Sum across all assets of Hyperliquid info dayNtlVlm, rolled into a 30 day window, headline is the 24h average." + queries: + p50: avg_over_time(perp_venue_volume_30d_usd{venue="hyperliquid"}[24h]) + p90: quantile_over_time(0.90, perp_venue_volume_30d_usd{venue="hyperliquid"}[24h]) + p99: quantile_over_time(0.99, perp_venue_volume_30d_usd{venue="hyperliquid"}[24h]) + mean: avg_over_time(perp_venue_volume_30d_usd{venue="hyperliquid"}[24h]) + success: avg_over_time(perp_venue_health{venue="hyperliquid"}[24h]) + sample_size: count_over_time(perp_venue_volume_30d_usd{venue="hyperliquid"}[24h]) + series: perp_venue_volume_30d_usd{venue="hyperliquid"} + + - slug: lighter + name: Lighter + tag: zk-rollup, zero taker fee + formula: "Sum of 24h volume per market from the Lighter public stats endpoint, rolled into a 30 day window, headline is the 24h average." + queries: + p50: avg_over_time(perp_venue_volume_30d_usd{venue="lighter"}[24h]) + p90: quantile_over_time(0.90, perp_venue_volume_30d_usd{venue="lighter"}[24h]) + p99: quantile_over_time(0.99, perp_venue_volume_30d_usd{venue="lighter"}[24h]) + mean: avg_over_time(perp_venue_volume_30d_usd{venue="lighter"}[24h]) + success: avg_over_time(perp_venue_health{venue="lighter"}[24h]) + sample_size: count_over_time(perp_venue_volume_30d_usd{venue="lighter"}[24h]) + series: perp_venue_volume_30d_usd{venue="lighter"} + + - slug: gmx + name: GMX v2 + tag: Synthetics on Arbitrum, oracle-priced + formula: "positionVolume aggregated per day from the GMX synthetics-arbitrum subgraph, rolled into a 30 day window, headline is the 24h average." + queries: + p50: avg_over_time(perp_venue_volume_30d_usd{venue="gmx"}[24h]) + p90: quantile_over_time(0.90, perp_venue_volume_30d_usd{venue="gmx"}[24h]) + p99: quantile_over_time(0.99, perp_venue_volume_30d_usd{venue="gmx"}[24h]) + mean: avg_over_time(perp_venue_volume_30d_usd{venue="gmx"}[24h]) + success: avg_over_time(perp_venue_health{venue="gmx"}[24h]) + sample_size: count_over_time(perp_venue_volume_30d_usd{venue="gmx"}[24h]) + series: perp_venue_volume_30d_usd{venue="gmx"} + + - slug: gains + name: gains.trade + tag: Synthetic perps on Base + formula: "Taker notional aggregated per day from the Gains v8 onchain indexer, rolled into a 30 day window, headline is the 24h average." + queries: + p50: avg_over_time(perp_venue_volume_30d_usd{venue="gains"}[24h]) + p90: quantile_over_time(0.90, perp_venue_volume_30d_usd{venue="gains"}[24h]) + p99: quantile_over_time(0.99, perp_venue_volume_30d_usd{venue="gains"}[24h]) + mean: avg_over_time(perp_venue_volume_30d_usd{venue="gains"}[24h]) + success: avg_over_time(perp_venue_health{venue="gains"}[24h]) + sample_size: count_over_time(perp_venue_volume_30d_usd{venue="gains"}[24h]) + series: perp_venue_volume_30d_usd{venue="gains"} diff --git a/public/logos/aevo.svg b/public/logos/aevo.svg new file mode 100644 index 00000000..09e01ae0 --- /dev/null +++ b/public/logos/aevo.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/logos/aster.svg b/public/logos/aster.svg new file mode 100644 index 00000000..6559bc7b --- /dev/null +++ b/public/logos/aster.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/logos/drift.svg b/public/logos/drift.svg new file mode 100644 index 00000000..959ac3c9 --- /dev/null +++ b/public/logos/drift.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/logos/edgex.jpg b/public/logos/edgex.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0ecd0f19738a513e806cb06637ea2033110a41af GIT binary patch literal 2979 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 pTgiNr?q}>g!CEis#vf;cJXE^F^j{1+Gv)e8Us literal 0 HcmV?d00001 diff --git a/public/logos/extended.svg b/public/logos/extended.svg new file mode 100644 index 00000000..9035442b --- /dev/null +++ b/public/logos/extended.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/logos/gains.svg b/public/logos/gains.svg new file mode 100644 index 00000000..0473bedb --- /dev/null +++ b/public/logos/gains.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/logos/grvt.jpg b/public/logos/grvt.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3ab8f1abd41c2314265bed124e60939224512182 GIT binary patch literal 5682 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 z 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 + + + + + + + diff --git a/public/logos/paradex.svg b/public/logos/paradex.svg new file mode 100644 index 00000000..4b4e0218 --- /dev/null +++ b/public/logos/paradex.svg @@ -0,0 +1,17 @@ + + + paradex-white + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/logos/variational.png b/public/logos/variational.png new file mode 100644 index 0000000000000000000000000000000000000000..d473f3c8407a17141dc428e2f3557326b71e19eb GIT binary patch literal 5172 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 literal 0 HcmV?d00001 diff --git a/public/logos/vertex.png b/public/logos/vertex.png new file mode 100644 index 0000000000000000000000000000000000000000..38d253d16fc438d16ef6796adb08b2aae5263b8c GIT binary patch literal 11282 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 R>-7bwKYO84u4EeY{{R7JUH||9 literal 0 HcmV?d00001 diff --git a/src/app/perps/page.tsx b/src/app/perps/page.tsx new file mode 100644 index 00000000..0a095b27 --- /dev/null +++ b/src/app/perps/page.tsx @@ -0,0 +1,330 @@ +import Link from "next/link"; +import { fetchPerpByAssetMatrix, fetchPerpCohort } from "@/lib/perp-stats"; +import { PerpHubTabs } from "@/components/perp-hub-tabs"; +import { pageMetadata } from "@/lib/page-metadata"; +import { safeJsonLd, buildBreadcrumbJsonLd } from "@/lib/jsonld"; +import { SITE } from "@/data/site"; + +/** + * Hub landing page for the perpetual DEX cohort. SSR'd against the + * `perp_venue_*` gauges exposed by the cross-venue perp cohort harness + * plus the existing perp bench gauges (perp-fees, perp-funding). One + * server fetch, one client tab swap between DEX venues and by-asset. + * + * The page positions OCB as the neutral cross-venue measurement layer + * for perp DEXes. Volume and open interest sit alongside the measured + * execution-quality benches OCB already runs, on the same timeline and + * with the same methodology. Per-venue pages live on /products/ + * (PerpVenueSection mirrors the PM venue treatment). + * + * The hub renders gracefully before the harness goes live: every + * numeric field is independently nullable, the leaderboard shows a row + * of dots for missing data, and the JSON-LD ItemList stays valid + * because it lists venue identities, not metric values. + */ + +const DESCRIPTION = + "Live volume, open interest, fees, all-in cost and funding rate across 15 perpetual DEXes. Reproducible methodology, refreshed every minute, sources public."; + +export const metadata: import("next").Metadata = pageMetadata({ + path: "/perps", + title: + "Perpetual DEX leaderboard: Hyperliquid, Lighter, GMX, dYdX, live cross-venue ranking", + description: DESCRIPTION, +}); + +export const revalidate = 60; + +export default async function PerpsHubPage() { + // Fetch cohort + per-asset matrix in parallel so the by-asset tab is + // hydrated on first paint, no second round-trip when the user flips + // the pill. Both helpers are wrapped in unstable_cache so concurrent + // requests collapse onto the same Prom roundtrip. + const [cohort, byAsset] = await Promise.all([ + fetchPerpCohort(), + fetchPerpByAssetMatrix(), + ]); + + const breadcrumbLd = { + "@context": "https://schema.org", + ...buildBreadcrumbJsonLd([ + { name: "Home", item: SITE.url }, + { name: "Perpetuals", item: `${SITE.url}/perps` }, + ]), + }; + + // ItemList JSON-LD points at the /products/ page for each + // venue. The GMX cohort row keys as gmx-v2 (matching the bench + // harness label), but the product page lives at /products/gmx, so + // map it here. Keeping this list stable means the SERP card does + // not churn if the harness drops a series momentarily. + const top15 = cohort ? cohort.venues.slice(0, 15) : []; + const itemListLd = cohort + ? { + "@context": "https://schema.org", + "@type": "ItemList", + name: "Perpetual DEXes tracked by OpenChainBench", + description: + "Perpetual DEX venues tracked by OpenChainBench, with cross-venue measurements of volume, open interest, fees, all-in cost and funding rate.", + numberOfItems: top15.length, + itemListElement: top15.map((r, i) => ({ + "@type": "ListItem", + position: i + 1, + name: r.name, + url: + r.slug === "gmx-v2" + ? `${SITE.url}/products/gmx` + : `${SITE.url}/products/${r.slug}`, + })), + } + : null; + + return ( +
+