Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
9689cf0
solana cohort: solana-official logo alias, leorpc logo + light chip, …
Jul 12, 2026
b493572
Merge pull request #1135 from ChainBench/chore/solana-cohort-pages
Flotapponnier Jul 12, 2026
d80b67d
nft harness: keyless OpenSea mode, empty x-api-key header caused 401s…
Flotapponnier Jul 13, 2026
7c6f4f1
nft harness: delist rarible, free tier is 100 requests per month (#1137)
Flotapponnier Jul 13, 2026
a98ae7a
robinhood chain: chains hub entry, chain-kpis, l2-block-time (HTTP po…
Jul 13, 2026
dda42b6
Merge pull request #1138 from ChainBench/feat/robinhood-chain-hub
Flotapponnier Jul 13, 2026
be49b75
bridge-monitor: on-chain balance fallback + degraded flag
Jul 13, 2026
90658e0
bridge-monitor: self-healing metrics + slack notifiers
Jul 13, 2026
2283c97
bridge-monitor: auto-rebalancer, corrective transfer via cheapest bridge
Jul 13, 2026
ca1efe8
bridge-monitor: tier downgrade ladder + rebalancer wiring in pre-flight
Jul 13, 2026
91656a9
bridge-monitor: stuck-fund reaper, hourly stranded gauge + corrective…
Jul 13, 2026
bc7e169
bridge-monitor: gas auto-top-up via LiFi same-chain swap, gated by de…
Jul 13, 2026
9626ac4
bridge-monitor: unit tests for refill route, ladder, stranded hours; …
Jul 13, 2026
3b55ed3
bridge-monitor: keyless dry-run support for reaper + RunDryRun
Jul 13, 2026
ed084d8
bridge-monitor: comment style cleanup in pre-flight docs
Jul 13, 2026
d2c3d00
bridge-monitor: daily spend tracker keyed by UTC date, persisted; exe…
Jul 13, 2026
b7b3b08
bridge-monitor: fix double-send on in-flight rebalance, slot-wide bud…
Jul 13, 2026
19357b4
bridge-monitor: SIMULATE_BALANCES only honored in dry-run mode
Jul 13, 2026
1b68417
tx executor: preserve hash on ambiguous send errors, split dry-run sp…
Jul 13, 2026
ded0e81
Merge pull request #1140 from ChainBench/feat/bridge-self-healing-fixes
Flotapponnier Jul 13, 2026
cbe1eb8
executor: add missing chain label, first real single-test panicked po…
Flotapponnier Jul 13, 2026
548d109
bridge-monitor: point Mobula calls at demo-api.mobula.io (#1142)
Flotapponnier Jul 13, 2026
1a19724
tokenized-stock-peg: bench 076, onchain tokenized equities vs Nasdaq …
Jul 13, 2026
22bd7fc
Merge pull request #1143 from ChainBench/feat/tokenized-stock-peg
Flotapponnier Jul 13, 2026
84d61a3
spec: missing store blob for a live bench throws instead of caching t…
Flotapponnier Jul 13, 2026
31d40ea
tsp: parse the flat spark shape (close/timestamp arrays), log empty p…
Jul 13, 2026
6397da4
Merge pull request #1145 from ChainBench/fix/tsp-spark-parser
Flotapponnier Jul 13, 2026
3002075
tsp: drop invalid rank_matrix_query, 1m reference candles, fee-band +…
Jul 13, 2026
734aac9
Merge pull request #1146 from ChainBench/fix/tsp-spec-validation
Flotapponnier Jul 13, 2026
88991bb
rwa: new category, tokenized-stock-peg moves in, 11 equity logos + re…
Jul 13, 2026
1ccad7c
Merge pull request #1147 from ChainBench/feat/rwa-category-stock-pages
Flotapponnier Jul 13, 2026
a3128eb
rwa: xstocks-peg (077) + usdy-nav-basis (078), issuer label on the ts…
Jul 13, 2026
b0e1392
Merge pull request #1148 from ChainBench/feat/xstocks-usdy-benches
Flotapponnier Jul 13, 2026
8d06d98
rwa: complete product pages, hood/qqq/coin/orca/pyth logos + dual-iss…
Jul 13, 2026
16c7f12
Merge pull request #1149 from ChainBench/chore/rwa-product-pages-comp…
Flotapponnier Jul 13, 2026
5bca1b3
registry: googl links to google.com, abc.xyz 403s aggressively
Jul 13, 2026
f71c744
Merge pull request #1150 from ChainBench/fix/googl-url
Flotapponnier Jul 13, 2026
ed3678f
cardano: cache koios epoch params 1h (public tier was exhausted); ste…
Jul 13, 2026
1928867
Merge pull request #1151 from ChainBench/fix/koios-cadence-stellar-re…
Flotapponnier Jul 13, 2026
29a4594
fix(store+bridge-monitor): fail-fast on missing blob + sub-50ms histo…
Flotapponnier Jul 13, 2026
e1dc0ee
fix: 3 machine-readable surface bugs (citable unit scaling, stat filt…
Flotapponnier Jul 13, 2026
47f0f6c
feat: /api/compare/{a}/{b} + openapi.json coverage (Wave 1 P0/P1) (#1…
Flotapponnier Jul 13, 2026
bae07d0
feat: Wave 1 P2 batch — cite MIME, sparkline SVG, Dataset PropertyVal…
Flotapponnier Jul 13, 2026
6b57a7f
bridge-monitor: Mobula EIP-712 signature-confirm flow (fixes stuck de…
Flotapponnier Jul 13, 2026
ac908f1
robinhood chain vague 1: weekend drift (079) + arb latency (080) + su…
Jul 14, 2026
d8eda8d
Merge pull request #1161 from ChainBench/feat/robinhood-vague1
Flotapponnier Jul 14, 2026
04c12af
subsidy is a chain KPI, not a bench: kill standalone spec, add 3 card…
Jul 14, 2026
47c7e79
Merge pull request #1163 from ChainBench/fix/subsidy-not-a-bench
Flotapponnier Jul 14, 2026
72311c9
pm-api-latency: add Predexon (bench 6th provider), fresh key deployed…
Jul 14, 2026
d3f709e
Merge pull request #1166 from ChainBench/feat/predexon-pm-provider
Flotapponnier Jul 14, 2026
604a64b
usdy: 3-retry on Orca RPC to fix 40% success rate (#1168)
Flotapponnier Jul 14, 2026
a0cf8f4
bench vague 2: ship 081-085 (ws latency, oracle freshness, rpc reliab…
Flotapponnier Jul 14, 2026
aa68026
hyperliquid frontend page: add ProviderLogo in the hero next to the name
Jul 14, 2026
0cd090b
Merge pull request #1171 from ChainBench/fix/hyperliquid-frontend-logo
Flotapponnier Jul 14, 2026
349b786
hl frontends: add slash, topdog, markets-mobile logos + registry entr…
Jul 14, 2026
6269bdf
Merge pull request #1173 from ChainBench/chore/hl-frontend-logos-3
Flotapponnier Jul 14, 2026
7f54aa5
idx-latency: swap Alchemy for Mobula in the cohort (paid-plan key, be…
Flotapponnier Jul 14, 2026
a7a0206
fix(bench): sample-size PromQL + leader reliability floor (#1175)
Flotapponnier Jul 15, 2026
d73812e
fix(registry): remove duplicate topdog entry (#1177)
Flotapponnier Jul 15, 2026
fba5e8e
vague2 QA: unit sec for true-seconds benches (fixes 0.0s heros), soft…
Flotapponnier Jul 15, 2026
5f699b0
add bench 086 polkadot-rpc: first Substrate chain in the RPC cluster …
Flotapponnier Jul 15, 2026
5280a4c
product pages: 9 block-builder registry entries + verified logos, ora…
Flotapponnier Jul 15, 2026
5fff7bf
085: add bobthebuilder provider row (real share, was metrics-only) (#…
Flotapponnier Jul 15, 2026
e809f1d
polkadot-rpc bench 086 + /chains/polkadot + Parity product (#1184)
Flotapponnier Jul 15, 2026
99e7c49
fix: dedup onfinality key in logo-manifest (already declared line 49)…
Flotapponnier Jul 15, 2026
5e3ac15
store: last-known-good snapshot fallback (no more awaiting after firs…
Flotapponnier Jul 15, 2026
c65d1c7
chain-kpis: add polkadot to registry (DOT native, stables via Asset H…
Flotapponnier Jul 16, 2026
1e62b2e
live-feed status: Feed down pill + banner on aggregator-head-lag (#1193)
Flotapponnier Jul 16, 2026
d332a3e
series gaps: null the chart line when a feed goes silent (unless chan…
Flotapponnier Jul 16, 2026
ea73d01
add bench 087 ws-head-latency-base + 088 ws-head-latency-solana (#1196)
Flotapponnier Jul 16, 2026
25a495a
ws-head-latency: multi-region (harness region label + spec region tab…
Flotapponnier Jul 16, 2026
c57a528
ws-head-latency: align region env var with rpc-capabilities (REGION n…
Flotapponnier Jul 16, 2026
361f321
chart: red band overlay for null-bucket downtime windows (#1203)
Flotapponnier Jul 16, 2026
a8f3d71
rename ws-head-latency -> ws-head-latency-ethereum for sibling slug p…
Flotapponnier Jul 16, 2026
d295f71
network-coverage: drop coinstats (free tier credits exhausted) (#1206)
Flotapponnier Jul 16, 2026
eafec54
Revert "network-coverage: drop coinstats (free tier credits exhausted…
Flotapponnier Jul 16, 2026
7dea9b2
downtime bands: provider-colored tint + name/silent label + edge mark…
Flotapponnier Jul 16, 2026
60748a5
downtime bands: pill labels + vertical stacking on overlap (#1211)
Flotapponnier Jul 16, 2026
8e2f1ab
tsp-arb-latency: lower trigger 50 -> 25 bps + credit sub-poll closure…
Flotapponnier Jul 16, 2026
3f9308f
downtime pill: drop the leading dot indicator, center the label (#1213)
Flotapponnier Jul 16, 2026
726945e
downtime pill: 'DATA MISSING' wording + skip leading gaps (#1215)
Flotapponnier Jul 16, 2026
509fa32
drop bench 084 indexer-latency (harness pruned, spec deleted) (#1218)
Flotapponnier Jul 16, 2026
3ed6c2d
video/render: strict Zod body schema before upstream forward (#1216)
Flotapponnier Jul 16, 2026
b7ca6eb
mcp: allowlist perp_funding_*, perp_venue_*, perp_execution_* prefixe…
Flotapponnier Jul 16, 2026
b46aa74
aggregator-head-lag: drop 'unless changes==0' from series queries (#1…
Flotapponnier Jul 16, 2026
a29e354
seo: 200 placeholders + sitemap threshold buffer (#1222)
Flotapponnier Jul 16, 2026
a18a8dc
aggregator-head-lag: restore outage detection with backfill-safe guar…
Flotapponnier Jul 16, 2026
04ba908
ws-head-latency: sub-ms histogram floor + keyed slots for base/solana…
Flotapponnier Jul 16, 2026
72bbd16
ship: ungate bench 085 evm-block-builders on prod (#1227)
Flotapponnier Jul 16, 2026
540c4b7
loader: propagate 24h series null-runs to 7d/30d (#1229)
Flotapponnier Jul 16, 2026
e176f0f
propagateNullsToCoarser: use absolute time-ago instead of window frac…
Flotapponnier Jul 16, 2026
83aa310
tsp-arb-latency: drop 5 illiquid tickers (TSLA GOOGL AMZN MSFT SPY) (…
Flotapponnier Jul 16, 2026
0d6e84b
perp-fees harness: fix Paradex depth-skip, gains SOL slot, dYdX walk …
Flotapponnier Jul 16, 2026
d2efd22
downtime bands: opt-in via live_activity, skip on other benches (#1235)
Flotapponnier Jul 16, 2026
ff4dd28
batch 2: MEV chips + rpc copy + Aster/edgeX + Cardano/Sui/Cosmos/Avax…
Flotapponnier Jul 16, 2026
981926a
rpc-capabilities: add 4 keyless providers (ThirdWeb Blast Gateway.fm …
Flotapponnier Jul 16, 2026
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
49 changes: 37 additions & 12 deletions benchmarks/aggregator-head-lag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ source: https://github.com/ChainBench/OpenChainBench/tree/main/harnesses/aggrega

prometheus:
window: 24h
# Live-feed sanity gate. Sums event-arrival changes across every
# aggregator series in the last 15min. If this is 0, ALL our probes
# are silent (harness crash / Prom scrape failing / config drift) and
# the per-provider "Feed down" badges would be misleading, so the UI
# suppresses them. If > 0, at least one provider is actively receiving
# events from us, which means a provider showing 0 changes on its own
# is genuinely silent from Codex/Mobula/Gecko upstream.
probe_ok: sum(changes(head_lag_seconds[15m]))

faq:
- q: "Which crypto data API has the lowest latency right now?"
Expand Down Expand Up @@ -153,17 +161,32 @@ providers:
mean: avg_over_time(head_lag_seconds{aggregator="mobula"}[24h]) * 1000
success: clamp_max(count_over_time(head_lag_seconds{aggregator="mobula"}[24h]) / 5760, 1)
sample_size: sum(count_over_time(head_lag_seconds{aggregator="mobula"}[24h]))
series: avg_over_time(head_lag_seconds{aggregator="mobula"}[1h]) * 1000
# Hybrid `unless` guard: drop the sample when the gauge saw no
# fresh event in the last 15 min AND we have enough scrapes in
# that window to trust the changes() reading (>5 samples). The
# count_over_time gate skips false-drops on backfilled data
# that Prom compacted to ~1 sample per hour — on that vintage
# changes([15m]) reads 0 by construction, without the gate the
# 30D view lost its first ~8 days to a fake wall-to-wall gap.
# Modern data at 15s cadence carries ~60 samples per 15 min so
# the guard still fires the moment a WS goes silent.
series: avg_over_time(head_lag_seconds{aggregator="mobula"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="mobula"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="mobula"}[15m]) > 5)
# Total gauge-value changes on this aggregator across chains and
# regions in the last 15min. Non-zero = fresh events arrived; 0 =
# every subscription has been silent for 15+ minutes (the gauge is
# frozen at its last value). Threshold is > 0 rather than a rate
# so quiet chains at night don't false-flag the aggregate view.
live_activity: sum(changes(head_lag_seconds{aggregator="mobula"}[15m]))
regions:
- region: us-east
p50: quantile_over_time(0.50, head_lag_seconds{aggregator="mobula", region="us-east"}[24h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="mobula", region="us-east"}[1h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="mobula", region="us-east"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="mobula", region="us-east"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="mobula", region="us-east"}[15m]) > 5)
- region: eu-west
p50: quantile_over_time(0.50, head_lag_seconds{aggregator="mobula", region="eu-west"}[24h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="mobula", region="eu-west"}[1h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="mobula", region="eu-west"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="mobula", region="eu-west"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="mobula", region="eu-west"}[15m]) > 5)
- region: ap-southeast
p50: quantile_over_time(0.50, head_lag_seconds{aggregator="mobula", region="sgp"}[24h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="mobula", region="sgp"}[1h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="mobula", region="sgp"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="mobula", region="sgp"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="mobula", region="sgp"}[15m]) > 5)

- slug: codex
name: Codex
Expand All @@ -176,17 +199,18 @@ providers:
mean: avg_over_time(head_lag_seconds{aggregator="codex"}[24h]) * 1000
success: clamp_max(count_over_time(head_lag_seconds{aggregator="codex"}[24h]) / 5760, 1)
sample_size: sum(count_over_time(head_lag_seconds{aggregator="codex"}[24h]))
series: avg_over_time(head_lag_seconds{aggregator="codex"}[1h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="codex"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="codex"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="codex"}[15m]) > 5)
live_activity: sum(changes(head_lag_seconds{aggregator="codex"}[15m]))
regions:
- region: us-east
p50: quantile_over_time(0.50, head_lag_seconds{aggregator="codex", region="us-east"}[24h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="codex", region="us-east"}[1h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="codex", region="us-east"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="codex", region="us-east"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="codex", region="us-east"}[15m]) > 5)
- region: eu-west
p50: quantile_over_time(0.50, head_lag_seconds{aggregator="codex", region="eu-west"}[24h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="codex", region="eu-west"}[1h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="codex", region="eu-west"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="codex", region="eu-west"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="codex", region="eu-west"}[15m]) > 5)
- region: ap-southeast
p50: quantile_over_time(0.50, head_lag_seconds{aggregator="codex", region="sgp"}[24h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="codex", region="sgp"}[1h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="codex", region="sgp"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="codex", region="sgp"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="codex", region="sgp"}[15m]) > 5)

- slug: geckoterminal
name: GeckoTerminal
Expand All @@ -199,15 +223,16 @@ providers:
mean: avg_over_time(head_lag_seconds{aggregator="geckoterminal"}[24h]) * 1000
success: clamp_max(count_over_time(head_lag_seconds{aggregator="geckoterminal"}[24h]) / 5760, 1)
sample_size: sum(count_over_time(head_lag_seconds{aggregator="geckoterminal"}[24h]))
series: avg_over_time(head_lag_seconds{aggregator="geckoterminal"}[1h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="geckoterminal"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="geckoterminal"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="geckoterminal"}[15m]) > 5)
live_activity: sum(changes(head_lag_seconds{aggregator="geckoterminal"}[15m]))
regions:
- region: us-east
p50: quantile_over_time(0.50, head_lag_seconds{aggregator="geckoterminal", region="us-east"}[24h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="geckoterminal", region="us-east"}[1h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="geckoterminal", region="us-east"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="geckoterminal", region="us-east"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="geckoterminal", region="us-east"}[15m]) > 5)
- region: eu-west
p50: quantile_over_time(0.50, head_lag_seconds{aggregator="geckoterminal", region="eu-west"}[24h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="geckoterminal", region="eu-west"}[1h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="geckoterminal", region="eu-west"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="geckoterminal", region="eu-west"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="geckoterminal", region="eu-west"}[15m]) > 5)
- region: ap-southeast
p50: quantile_over_time(0.50, head_lag_seconds{aggregator="geckoterminal", region="sgp"}[24h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="geckoterminal", region="sgp"}[1h]) * 1000
series: avg_over_time(head_lag_seconds{aggregator="geckoterminal", region="sgp"}[1h]) * 1000 unless (changes(head_lag_seconds{aggregator="geckoterminal", region="sgp"}[15m]) == 0 and count_over_time(head_lag_seconds{aggregator="geckoterminal", region="sgp"}[15m]) > 5)

4 changes: 2 additions & 2 deletions benchmarks/bridge-quote-latency.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ methodology:
- "Notional sizes: $5, $50, $300 per quote."
- "Cadence: full sweep (4 routes × 3 amounts × N bridges) every 5 minutes for 24 hours."
- "Region: eu-west. Single point of measurement; multi-region requires running additional monitor instances."
- "Histogram buckets: 50, 100, 200, 500, 1000, 2000, 5000, 10000 ms."
- "Histogram buckets: 10, 25, 50, 100, 200, 500, 1000, 2000, 5000, 10000 ms. Sub-50ms buckets added 2026-07-13 so solver-cached fast paths (Near Intents on HyperCore in particular) surface their true p50 instead of being floored at the interpolation of the (0, 50] bucket."
- "Failures (quote_failed, execution_failed, unsupported route) excluded from latency aggregates and counted toward success rate."

# Per-corridor leader rewrite deferred: this YAML does not yet declare
Expand Down Expand Up @@ -89,7 +89,7 @@ faq:
- q: "Are intent and relay bridges always faster than aggregators?"
a: "On a single-route query, usually. Intent layers like Relay quote against a pool of pre-positioned solvers, so the API is a thin price-discovery call. Aggregators like LI.FI run a route-search graph over N underlying bridges per request, which adds 100 to 400 ms of irreducible work. On multi-hop or rare-corridor queries the aggregator advantage in coverage matters more than the latency gap, and the comparison flips."
- q: "How does OpenChainBench measure bridge quote latency?"
a: "The harness issues identical quote requests against every bridge for the same route and notional, every five minutes, from a single eu-west origin. Each request times wall-clock duration from send to last byte received, then publishes a Prometheus histogram (50, 100, 200, 500, 1000, 2000, 5000, 10000 ms buckets). p50, p90 and p99 are derived via `histogram_quantile` over a rolling 24-hour window. Errored quotes (quote_failed, unsupported route, timeout) are excluded from the latency aggregate and counted toward success rate so a fast-but-broken bridge cannot game the headline."
a: "The harness issues identical quote requests against every bridge for the same route and notional, every five minutes, from a single eu-west origin. Each request times wall-clock duration from send to last byte received, then publishes a Prometheus histogram (10, 25, 50, 100, 200, 500, 1000, 2000, 5000, 10000 ms buckets). p50, p90 and p99 are derived via `histogram_quantile` over a rolling 24-hour window. Errored quotes (quote_failed, unsupported route, timeout) are excluded from the latency aggregate and counted toward success rate so a fast-but-broken bridge cannot game the headline."
- q: "Does quote latency affect the price the user gets?"
a: "Indirectly, yes. A slower quote API leaves a larger window between the moment the price is quoted and the moment the user signs. On volatile corridors the underlying spot can drift in that window, which surfaces as a quoted-vs-realized gap. Intent layers compensate by re-quoting at signing time; aggregators usually pass through a slippage parameter. The fee benchmark on this site (`/benchmarks/bridge-fee`) measures the realized cost; this page measures the latency half of the same flow."

Expand Down
Loading
Loading