Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions benchmarks/mev-protect-rpc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ methodology:
- "Headline: median latency across the methods the provider served that tick, aggregated over 24h with quantile_over_time. A rejected method does not poison the latency; it lowers the coverage panel instead."
- "Coverage: mev_rpc_methods_supported counts the wallet methods served on the last tick (max 7). Flashbots rejects eth_call on the public endpoint; Blink blocks full-node reads like eth_getBlockByNumber, which keeps it off the general RPC benches but not off this one."
- "Out of scope, disclosed: inclusion rate, refund economics and sandwich protection efficacy are the write path and require funded transactions. See the arXiv study Private MEV Protection RPCs (2505.19708) for a one-off execution-quality comparison."
- "Failures (timeouts, 403, 429) increment mev_rpc_call_total{result} and count against the success rate; the gauge keeps its last value so the chart shows the outage in the success column rather than a fake zero."
- "Success rate counts transport failures only (timeouts, throttling, network); a method a gateway refuses by policy is a coverage gap shown in the coverage panel, not an outage. Failures increment mev_rpc_call_total{result}; the gauge keeps its last value so the chart shows the outage in the success column rather than a fake zero."

findings:
- "{{best_name}} leads at {{best_p50}} (p50, 24h) on the cross-region wallet call median over {{count}} measured gateways."
Expand Down Expand Up @@ -84,7 +84,7 @@ dimensions:
metric_panels:
- id: coverage
label: Method coverage
metric: avg(mev_rpc_methods_supported)
metric: avg(mev_rpc_methods_supported{benchmark="mev-protect-rpc"})
label_key: provider
unit: count
higher_is_better: true
Expand All @@ -100,7 +100,7 @@ providers:
p90: quantile_over_time(0.90, mev_rpc_wallet_latency_milliseconds{provider="flashbots"}[24h])
p99: quantile_over_time(0.99, mev_rpc_wallet_latency_milliseconds{provider="flashbots"}[24h])
mean: avg_over_time(mev_rpc_wallet_latency_milliseconds{provider="flashbots"}[24h])
success: sum(increase(mev_rpc_call_total{provider="flashbots",result="ok"}[24h])) / clamp_min(sum(increase(mev_rpc_call_total{provider="flashbots"}[24h])), 1)
success: sum(increase(mev_rpc_call_total{provider="flashbots",result="ok"}[24h])) / clamp_min(sum(increase(mev_rpc_call_total{provider="flashbots",result!~"blocked|method_not_found"}[24h])), 1)
sample_size: sum(increase(mev_rpc_call_total{provider="flashbots"}[24h]))
series: avg(avg_over_time(mev_rpc_wallet_latency_milliseconds{provider="flashbots"}[1h]))
regions:
Expand All @@ -123,7 +123,7 @@ providers:
p90: quantile_over_time(0.90, mev_rpc_wallet_latency_milliseconds{provider="mevblocker"}[24h])
p99: quantile_over_time(0.99, mev_rpc_wallet_latency_milliseconds{provider="mevblocker"}[24h])
mean: avg_over_time(mev_rpc_wallet_latency_milliseconds{provider="mevblocker"}[24h])
success: sum(increase(mev_rpc_call_total{provider="mevblocker",result="ok"}[24h])) / clamp_min(sum(increase(mev_rpc_call_total{provider="mevblocker"}[24h])), 1)
success: sum(increase(mev_rpc_call_total{provider="mevblocker",result="ok"}[24h])) / clamp_min(sum(increase(mev_rpc_call_total{provider="mevblocker",result!~"blocked|method_not_found"}[24h])), 1)
sample_size: sum(increase(mev_rpc_call_total{provider="mevblocker"}[24h]))
series: avg(avg_over_time(mev_rpc_wallet_latency_milliseconds{provider="mevblocker"}[1h]))
regions:
Expand All @@ -146,7 +146,7 @@ providers:
p90: quantile_over_time(0.90, mev_rpc_wallet_latency_milliseconds{provider="blinklabs"}[24h])
p99: quantile_over_time(0.99, mev_rpc_wallet_latency_milliseconds{provider="blinklabs"}[24h])
mean: avg_over_time(mev_rpc_wallet_latency_milliseconds{provider="blinklabs"}[24h])
success: sum(increase(mev_rpc_call_total{provider="blinklabs",result="ok"}[24h])) / clamp_min(sum(increase(mev_rpc_call_total{provider="blinklabs"}[24h])), 1)
success: sum(increase(mev_rpc_call_total{provider="blinklabs",result="ok"}[24h])) / clamp_min(sum(increase(mev_rpc_call_total{provider="blinklabs",result!~"blocked|method_not_found"}[24h])), 1)
sample_size: sum(increase(mev_rpc_call_total{provider="blinklabs"}[24h]))
series: avg(avg_over_time(mev_rpc_wallet_latency_milliseconds{provider="blinklabs"}[1h]))
regions:
Expand Down
1 change: 1 addition & 0 deletions benchmarks/perp-open-interest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ abstract: |
Higher is better.

methodology:
- "Convention: open interest counts each contract once (one side), the standard used by CME, Binance and Coinglass, and the only convention comparable across venues. Aggregators can differ: DefiLlama doubles Lighter and Ostium (long plus short), folds 1,682 options markets into Paradex, and adds HIP-3 sub-dex OI to Hyperliquid. Where our number is about half of theirs, that is the convention gap, not missing data; five venues where conventions align match DefiLlama within 2 percent."
- "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."
- "Aster: fapi openInterest endpoint per instrument, summed across all listed USDT perps."
Expand Down
1 change: 1 addition & 0 deletions benchmarks/pm-data-freshness.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ abstract: |
yet cover Kalshi venue data).

methodology:
- "Anchor rows: on each venue tab the venue itself (Polymarket, Kalshi) is the canonical T0, so its row reads as the harness network round trip, near zero by construction. It is kept on the board to document the reference point, not as a competing feed; the comparison rows are the data providers measured against it."
- "Polymarket T0. `wss://ws-subscriptions-clob.polymarket.com/ws/market` is public, no auth, sub 50ms gateway publish latency from EU West. Cross correlation uses (conditionId, priceUSD rounded to 3 decimals, sizeUSD micros, 5s time bucket)."
- "Kalshi T0. `https://api.elections.kalshi.com/v1/social/trades` (REST), polled every 5s with cursor pagination. Every trade carries `create_date` at microsecond precision; that timestamp is the canonical T0. Poll cadence affects only correlation timing, not the freshness number. The official Kalshi WebSocket needs RSA PSS signed headers from a US KYC account and 403s from non US IPs, not viable for a public benchmark."
- "Mobula PM WebSocket. `wss://pm-api-prod-eu.mobula.io`. Auth via API key in the subscribe payload. Cloudflare on the gateway requires a browser User Agent on the upgrade request, default Go HTTP UA is silently filtered. Covers Polymarket today, Kalshi coverage is not yet shipped."
Expand Down
10 changes: 5 additions & 5 deletions benchmarks/polymarket-resolution-delay.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ providers:
p50: 1000 * histogram_quantile(0.50, sum by (le) (pmres_resolution_delay_seconds_bucket))
p90: 1000 * histogram_quantile(0.90, sum by (le) (pmres_resolution_delay_seconds_bucket))
p99: 1000 * histogram_quantile(0.99, sum by (le) (pmres_resolution_delay_seconds_bucket))
mean: sum(pmres_resolution_delay_seconds_sum) / sum(pmres_resolution_delay_seconds_count)
mean: 1000 * sum(pmres_resolution_delay_seconds_sum) / sum(pmres_resolution_delay_seconds_count)
success: clamp_max(sum(pmres_resolution_delay_seconds_bucket{le="7200"}) / sum(pmres_resolution_delay_seconds_count), 1)
sample_size: sum(pmres_resolutions_total)
series: 1000 * histogram_quantile(0.50, sum by (le) (pmres_resolution_delay_seconds_bucket))
Expand All @@ -145,7 +145,7 @@ providers:
p50: 1000 * histogram_quantile(0.50, sum by (le) (pmres_resolution_delay_seconds_bucket{category="sports"}))
p90: 1000 * histogram_quantile(0.90, sum by (le) (pmres_resolution_delay_seconds_bucket{category="sports"}))
p99: 1000 * histogram_quantile(0.99, sum by (le) (pmres_resolution_delay_seconds_bucket{category="sports"}))
mean: sum(pmres_resolution_delay_seconds_sum{category="sports"}) / sum(pmres_resolution_delay_seconds_count{category="sports"})
mean: 1000 * sum(pmres_resolution_delay_seconds_sum{category="sports"}) / sum(pmres_resolution_delay_seconds_count{category="sports"})
success: clamp_max(sum(pmres_resolution_delay_seconds_bucket{le="7200",category="sports"}) / sum(pmres_resolution_delay_seconds_count{category="sports"}), 1)
sample_size: sum(pmres_resolutions_total{category="sports"})
series: 1000 * histogram_quantile(0.50, sum by (le) (pmres_resolution_delay_seconds_bucket{category="sports"}))
Expand All @@ -158,7 +158,7 @@ providers:
p50: 1000 * histogram_quantile(0.50, sum by (le) (pmres_resolution_delay_seconds_bucket{category="crypto"}))
p90: 1000 * histogram_quantile(0.90, sum by (le) (pmres_resolution_delay_seconds_bucket{category="crypto"}))
p99: 1000 * histogram_quantile(0.99, sum by (le) (pmres_resolution_delay_seconds_bucket{category="crypto"}))
mean: sum(pmres_resolution_delay_seconds_sum{category="crypto"}) / sum(pmres_resolution_delay_seconds_count{category="crypto"})
mean: 1000 * sum(pmres_resolution_delay_seconds_sum{category="crypto"}) / sum(pmres_resolution_delay_seconds_count{category="crypto"})
success: clamp_max(sum(pmres_resolution_delay_seconds_bucket{le="7200",category="crypto"}) / sum(pmres_resolution_delay_seconds_count{category="crypto"}), 1)
sample_size: sum(pmres_resolutions_total{category="crypto"})
series: 1000 * histogram_quantile(0.50, sum by (le) (pmres_resolution_delay_seconds_bucket{category="crypto"}))
Expand All @@ -171,7 +171,7 @@ providers:
p50: 1000 * histogram_quantile(0.50, sum by (le) (pmres_resolution_delay_seconds_bucket{category="politics"}))
p90: 1000 * histogram_quantile(0.90, sum by (le) (pmres_resolution_delay_seconds_bucket{category="politics"}))
p99: 1000 * histogram_quantile(0.99, sum by (le) (pmres_resolution_delay_seconds_bucket{category="politics"}))
mean: sum(pmres_resolution_delay_seconds_sum{category="politics"}) / sum(pmres_resolution_delay_seconds_count{category="politics"})
mean: 1000 * sum(pmres_resolution_delay_seconds_sum{category="politics"}) / sum(pmres_resolution_delay_seconds_count{category="politics"})
success: clamp_max(sum(pmres_resolution_delay_seconds_bucket{le="7200",category="politics"}) / sum(pmres_resolution_delay_seconds_count{category="politics"}), 1)
sample_size: sum(pmres_resolutions_total{category="politics"})
series: 1000 * histogram_quantile(0.50, sum by (le) (pmres_resolution_delay_seconds_bucket{category="politics"}))
Expand All @@ -184,7 +184,7 @@ providers:
p50: 1000 * histogram_quantile(0.50, sum by (le) (pmres_resolution_delay_seconds_bucket{category="other"}))
p90: 1000 * histogram_quantile(0.90, sum by (le) (pmres_resolution_delay_seconds_bucket{category="other"}))
p99: 1000 * histogram_quantile(0.99, sum by (le) (pmres_resolution_delay_seconds_bucket{category="other"}))
mean: sum(pmres_resolution_delay_seconds_sum{category="other"}) / sum(pmres_resolution_delay_seconds_count{category="other"})
mean: 1000 * sum(pmres_resolution_delay_seconds_sum{category="other"}) / sum(pmres_resolution_delay_seconds_count{category="other"})
success: clamp_max(sum(pmres_resolution_delay_seconds_bucket{le="7200",category="other"}) / sum(pmres_resolution_delay_seconds_count{category="other"}), 1)
sample_size: sum(pmres_resolutions_total{category="other"})
series: 1000 * histogram_quantile(0.50, sum by (le) (pmres_resolution_delay_seconds_bucket{category="other"}))
15 changes: 9 additions & 6 deletions src/app/benchmarks/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -463,12 +463,15 @@ export default async function BenchmarkPage({
{benchmark.subtitle}
</p>

{/* Wikipedia-style infobox. Floats right on desktop next to the
TL;DR and the intro copy, stacks above on mobile. Table markup
+ microdata make the key/value pairs extractable by LLM
crawlers verbatim (Perplexity, Gemini, ChatGPT-with-web all
hoist this format from Wikipedia pages when composing answers)
while giving readers a two second scan of the headline facts. */}
{/* Compact "At a glance" card. Rendered as a native <details>
element so it collapses to a one line summary on click while
still shipping the full microdata + key/value pairs inside the
collapsed body (LLM crawlers see the content whatever the
visual state). Sits between the subtitle and the TL;DR
grounding trace so a reader has: headline claim (H1) → context
(subtitle) → at-a-glance facts (this card) → canonical
grounding sentence (TL;DR) before entering the leaderboard
body. */}
<BenchInfobox benchmark={benchmark} />

{/* Visible grounding-trace TL;DR. Renders the same canonical line
Expand Down
8 changes: 4 additions & 4 deletions src/app/products/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ export async function generateMetadata({
// crawlers that peek at the response before the 308 fires still see the
// right canonical target.
// Merkle rebranded to Blink Labs and went keyed-only; the provider was
// fully delisted 2026-07-10 from the keyless RPC benches. 308 to the
// Blink Labs product page (bench 074 lists them under the new name) so
// the old URL's link equity lands on the successor.
// fully delisted 2026-07-10 so this page has no data left. 308 to the
// capabilities bench for now; flip to /products/blinklabs in the same PR
// that removes mev-protect-rpc from REMOVED_BENCH_SLUGS.
if (slug === "merkle") {
permanentRedirect("/products/blinklabs");
permanentRedirect("/benchmarks/rpc-capabilities");
}
if (await isHlBuilderWithHistory(slug)) {
const canonicalUrl = `${SITE.url}/hyperliquid/${slug}`;
Expand Down
Loading
Loading