Skip to content

Fix editorial leftovers from the Serialized onboarding (follow-up to #2269) - #2300

Closed
angelinosan wants to merge 3505 commits into
ChainBench:devfrom
angelinosan:fix/serialized-editorial
Closed

Fix editorial leftovers from the Serialized onboarding (follow-up to #2269)#2300
angelinosan wants to merge 3505 commits into
ChainBench:devfrom
angelinosan:fix/serialized-editorial

Conversation

@angelinosan

Copy link
Copy Markdown

Follow-up to #2269, review pass on the Serialized onboarding. Bench 001 ended up half-migrated to four providers: methodology and cardinality were updated, but the title, seo_description, subtitle, seo_intro, two findings and one FAQ answer still list three providers, and two findings now contradict the live tables ("Mobula leads on three of four chains", "Codex leads on Base").

Minimal text-only diff (7 files, +28/-24):

  • bench 001: Serialized added to title / subtitle / seo_description / seo_intro / FAQ; the two stale findings reworded around templated values ({{p50:codex}}); {{p99:serialized}} added to the p99 finding.
  • metadata-coverage (004): Serialized added to the title.
  • answers/which-crypto-price-api-is-the-fastest: Serialized and Robinhood Chain added to every static provider/chain list; 27 -> 48 active series; the Base-floor and preconfirmed-events limitations aligned with the new flashblock reference (a sub-second Base p50 is no longer "impossible", it is on the live page).
  • answers/which-crypto-data-api-covers-the-most-blockchains: Serialized (/v1/meta/chains) added to intro and methodology.
  • benchmarks/README: wallet-labels-coverage removed from the prod-holds list since Promote dev to main: Serialized onboarding, bench scoring fixes, 001 node reference #2269 publishes it.
  • harness aggregator-head-lag: SERIALIZED_API_KEY documented (README env table + .env.example); tracked-aggregators and supported-chains lines brought up to date with the pool table.

No query, schema or code changes; CI (pnpm validate / typecheck / build) should stay green.

🤖 Generated with Claude Code

Chainstack + Alchemy probed from 3 regions; Railway env vars pushed.
QuickNode endpoint pending (supported per docs, key not yet provisioned).
…inhood

feat: bench 069 (rpc-keyed-latency) live + Robinhood Chain tab
…inhood

fix: bench 069 spec validation (em dash + cohort length)
…inhood

feat: 7 per-chain keyed RPC benches + drop Optimism
* fix: Gains USDC collateral array index (2 not 3)

* feat: fallback Gains funding estimate when API returns zero
* fix: Gains USDC collateral array index (2 not 3)

* feat: fallback Gains funding estimate when API returns zero

* fix: gains funding precision 1e21 not 1e18 (1000x correction)
fix: raise maxDuration to 300s, extend sitemap JS timeout to 240s
ship: dev to main (aug 27)
…Bench#2121)

* feat: fee-compare tool — Hyperliquid vs Gains wallet analysis (ChainBench#2054)

* feat: HL vs Gains wallet fee comparison tool

* feat: HL vs Gains wallet fee comparison

* fix: fetch Gains fee rates live, drop hardcoded 0.12%

* fix: fetch Gains fee rates live, drop hardcoded rates

* feat: HL vs Gains wallet fee comparison tool

* fix: fetch Gains fee rates live, drop hardcoded 0.12%

* feat: per-trade table, live Gains rates per coin, PnL column

* fix: remove duplicate gainsFeeCache declaration

* feat: fee-compare per-trade breakdown + live Gains rates

* feat: HL vs Gains wallet fee comparison tool

* fix: fetch Gains fee rates live, drop hardcoded 0.12%

* feat: per-trade table, live Gains rates per coin, PnL column

* fix: remove duplicate gainsFeeCache declaration

* redesign: fee-compare UI — logos, VS card, trade table, per-fill savings (ChainBench#2046)

* perf: reduce Vercel invocations - live-prices 1s->5s CDN TTL, alternatives+perp ISR 300s

* fix: double-counted notional in HL vs Gains comparison (ChainBench#2048)

* redesign: fee-compare UI — logos, VS card, trade table, per-fill savings

* fix: double-counted notional in HL vs Gains comparison — use per-side rate

* fix: rename Gains.trade -> Gains, HL -> Hyperliquid in UI (ChainBench#2049)

* feat: always show Gains simulated, bold winner, pro design (ChainBench#2051)

* fix: mobile responsive — stack VS card vertically, hide overflow columns (ChainBench#2052)

* fix: symmetric HL/Gains display + winner logic for single-platform wallets (ChainBench#2053)

* fix: mobile table Gains fee column always visible, symmetric panels (ChainBench#2057)

* fix: revalidate hl-cohort + hl-history on aggregate purge (ChainBench#2069)

* fix(app-store-ratings): last_over_time[31m] on reviews panel for 7d+ staleness (ChainBench#2073)

* fix: sitemap 90s timeout — maxDuration=60 + tighten internal deadline to 20s

* fix: suppress orphaned buildFullSitemap rejection + guard unhandled getProvider throws

* feat(rpc): add Dogecoin bench ChainBench#235 (Tatum, dRPC, BlockCypher)

* fix(dogecoin-rpc): remove em-dash from seo_intro

* fix(dogecoin-rpc): em-dash in seo_intro

* fix: sitemap aggregate timeout + CDN caching (ChainBench#2090) (ChainBench#2092)

* feat: shareable wallet URLs + HL fee/funding breakdown

- /fee-compare/[venueA]/[venueB]/[wallet] dynamic route auto-submits on load
- pushState updates URL after analyze so any comparison is shareable
- FeeCompareClient accepts initialVenueA/B/Wallet/Days props
- HL wallet side: replace 2-cell grid with inline fee/funding/net breakdown

* fix: remove 'No activity found' text from crossSim projection side

* fix: sitemap aggregate timeout + CDN caching (s-maxage stripped by dynamic route)

* fix: raise maxDuration to 300s and extend sitemap JS timeout to 240s

SIGKILL (signal 9) was killing the function at 60s. The aggregate blob
(4.25MB) exceeds Next.js Data Cache's 2MB cap, so unstable_cache never
caches it and every request re-fetches from /api/aggregate (FETCH_TIMEOUT_MS
= 65s > maxDuration = 60s). SIGKILL discards the buffered response -> 500.

- maxDuration 60 -> 300: gives full build time on cold starts
- JS timeout 55s -> 240s: allows aggregate fetch + HL-builder Prometheus
  sweeps to finish before falling back to the static sitemap

* feat(zcash): add bench ChainBench#236 with Tatum zcashd, Tatum Zebra, Blockchair

* fix: include pre-window HL positions in carry projection
…ast (ChainBench#2120)

* feat(robinhood): add QuickNode to keyed-rpc-robinhood bench (ChainBench#243)

* fix(keyed-rpc-robinhood): update findings — Alchemy leads overall, Chainstack wins us-east
…ms, Chainstack 139ms (ChainBench#2122)

* feat(robinhood): add QuickNode to keyed-rpc-robinhood bench (ChainBench#243)

* fix(keyed-rpc-robinhood): update findings — Alchemy leads overall, Chainstack wins us-east

* fix(ws-head-latency-robinhood): update findings — QuickNode leads at 0.27ms, Alchemy 40ms, Chainstack 139ms
Flotapponnier and others added 26 commits September 5, 2026 20:28
…ups (ChainBench#2264)

v1.0 claimed bench 001 references archive nodes and was therefore
unaffected by provider clock disagreement. That repeated the spec
instead of reading the harness: there is no archive-node reference in
aggregator-head-lag at all, and the leaderboard gauge is computed from
each provider's own timestamp. The spec says the opposite in three
places.

Also records the now-conclusive bench 067 result (verified 5 of 19
chains), probe-confirmed negative capabilities, and a verified 5.2x
BONK mispricing traced to pool discovery missing the main market.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…en-security feasibility (ChainBench#2265)

The v1.1 text said the deep Orca pool was absent from their pool list.
It is present, ranked second. The real defect is that the ranking
compares liquidityNative across different quote assets without
converting to USD, so a $4,347 USDC-quoted pool outranks a $75,679
SOL-quoted one because 4,346 > 728. Seven of eight pools agree on the
price; rank 1 is the lone outlier and the token is priced from it.

Adds section 17: token-security bench feasibility, including the
provider cohort, a latency table where Mobula is last by 17x, three
measured design traps, a retrospective backtest and its limits, and
which fields actually carry signal.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…#2266)

Both benches score a proxy for the thing they claim to measure.

Bench 004 scores the logo field as "non-empty string", which any
provider wins by construction by rewriting logos onto its own CDN at a
deterministic path. The current beneficiary is Mobula, at 100% logo on
every chain against 22.9/37.8/78.9 for a provider returning upstream
URLs. Adds logo_resolved: HEAD the URL, fall back to a ranged GET on
403/405, cache 6h so we do not hammer third-party CDNs.

Bench 008 scores a hit as "any non-generic name", which cannot tell a
curated entity from a personal name-service record. Measured: 25% of
Serialized's hits and 25.4% of Mobula's named something other than the
curated entity. The anchor list already carries a Hint for every
address and the scoring path ignored it. Adds
wallet_labels_accurate_total scored against that Hint.

Both land as SEPARATE series, not as redefinitions, so the published
leaderboards and their history stay intact while the stricter numbers
build up alongside.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… clock (ChainBench#2267)

The spec promises "Reference: archive nodes per chain, validated against
block hashes" in three places. The harness never did that: both provider
paths compute receiveTime minus the timestamp the provider itself sent.
grep for archive/getBlockByNumber/blockTimestamp over the harness returns
nothing.

Measured consequence: on the same transaction hash, Serialized and Mobula
disagree about when it happened by 707 ms on Solana and 1,000 ms on Base,
so the leaderboard partly ranks where each vendor puts its clock.

Adds one WebSocket subscription per monitored pool straight to a node,
timestamping every swap on receipt, matched to provider emissions by
transaction hash. Published as head_lag_ref_seconds beside the legacy
series so the old one keeps its history while the two are compared.

Validated before shipping at a 100% hash match rate on Base and Solana.
That validation also surfaced the binding constraint: against public
endpoints the reference node is SLOWER than the providers, so the series
carries the node's own latency as an offset and must be read as a
relative comparison until REF_WS_URL_<CHAIN> points at a paid node. All
of this is documented at the call site.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Their trades stream is keyed by token with an optional pools filter,
while the bench is keyed by pool. Subscribing by the pool's native side
(SOL, WETH, WBNB) acknowledges and delivers nothing; subscribing by the
side their own /v1/pool reports as `token` (USDC, BUSD, USDG) with
pools=<bench pool> delivers exactly that market. Verified on all four
bench pools before shipping (events with txHash: solana 4, base 10,
bnb 2, robinhood 79).

One connection per process, four pools multiplexed: their key allows 5
concurrent connections and this harness runs in three regions.

Records both series: head_lag_seconds from their own `at`, same
treatment as the incumbents, and head_lag_ref_seconds against the node
reference clock matched by txHash.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…he 2025-01-01 floor (ChainBench#2271)

keyed-rpc-robinhood (live since 2026-08-27) and every bench added
since the last regeneration emitted datePublished 2025-01-01 in
JSON-LD, the FLOOR_PUBLISHED fallback in src/lib/seo/bench-dates.ts.
A datePublished a year before the site existed, next to a
dateModified that moves hourly, is exactly the freshness signal the
file header warns about.

Regenerated with scripts/generate-bench-published.mjs as documented.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…Asia-Pacific claim (ChainBench#2273)

Same rescoping as the main hotfix, applied to the two-region dev
version: the headline still cites Singapore, the region tabs stay,
every chain-wide superlative and the unsourced Asia-Pacific
justification are gone.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…product URLs (dev twin) (ChainBench#2275)

Same two changes as the main hotfix. On dev, keyed-rpc-robinhood declares
its region tabs so the payload guard is a no-op there; the sitemap filter
is identical.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…ditorial (dev twin) (ChainBench#2277)

Same change as the main hotfix. On dev, keyed-rpc-robinhood declares its
region tabs so it is returned untouched; the page-level guard from the
previous twin is removed.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Reverts ChainBench#2268 before it reaches main. Measured 2026-09-08: their `at` is
the block timestamp exactly, so the ruler matches, but on Base every
sampled trade arrives before its own block exists (11/11 received while
the node head was still target-1, median 1.04 s ahead of publication).

They stream sequencer preconfirmations; Mobula, Codex and GeckoTerminal
read sealed blocks. That is a latency/finality trade-off, not a speed
gap, and one ranking would present it as superiority. RecordHeadLag also
drops negatives, so on the legacy series they would read as no data on
Base while being the fastest.

Audit §18.1 records the measurements, the two open questions for them
(preconfirmed=false on all lead events, 0 Robinhood events in 240 s) and
the conditions to reopen. Serialized stays on benches 004, 005, 008, 090.

Claude-Session: https://claude.ai/code/session_01LtBjM1FhTKxiZhwzb3Y61c

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nominator (ChainBench#2279)

Two problems on /products/[slug], both visible on Serialized.

rankPerChainForBench only holds one real per-chain fact: the leader, from
bestPerChain. For every other provider it reused the unfiltered aggregate
order shifted by one slot, so a chip reading "ChainBench#3 on Solana" was the global
rank with a chain label on it, repeated identically across every chain of
the bench. That reads as a measurement and is not one. Non-leader chips
are gone: a chip now means "leads this chain", and its absence means
"does not lead", not "ranks lower".

The chips also hid how many providers were measured on the chain. "ChainBench#1 on
Solana" was ChainBench#1 of 2 on bench 008 while sitting next to "ChainBench#3 of 8" for the
aggregate. They now read "ChainBench#1 of 4 on Ethereum", with the denominator taken
from providersPerChain and omitted when that set is unknown rather than
substituting the global count.

Wins accounting is unchanged: it already counted rank === 1 entries only.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…he mix (ChainBench#2280)

On a bench with chain dimensions the cross-chain aggregate is a mix, not a
comparison. Ranking on it alone let a provider measured on one chain that
nobody else reported finish above a provider that led several contested
ones. Five live benches shipped that way:

  rpc-capabilities        Binance 1st on 1 chain, PublicNode led 6
  wallet-labels-coverage  XRPScan 1st on 1 chain, Serialized led 4
  token-quote-coverage    Jupiter 1st on 1 chain, Mobula led 2
  bridge-fee              Squid Router 1st on 1 chain
  perp-liq-rate           Lighter 1st on 1 chain

rankedCandidates now sorts by contested-chain wins first and uses the
aggregate value only to break ties. A chain counts only when at least two
providers reported on it, so an uncontested chain awards nothing: you do
not win a race you ran alone.

Guarded by the per-chain stashes, which materialize/load.ts populates only
on the unfiltered view. A chain-filtered variant has none, so ?chain=bnb
keeps ranking by value as before.

providers.ts reuses the same ordering. The two surfaces disagreeing is what
put "ChainBench#3 of 8" next to five chain-leadership chips on the same bench row.

Known and accepted: a provider with one contested win now ranks above one
with none and a higher aggregate figure (TonAPI over XRPScan on 008). That
is what ranking on head-to-head record means; the win count is on the row.

Rule documented in methodology, section II.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…hainBench#2281)

Replaces the global chain-wins sort from ChainBench#2280, which fixed the ordering but
broke the reading of it. Ranking on a key the reader cannot see in the column
produced tables that no longer descend: 79.88% at rank 4 on 008, and a 74 ms
leader at rank 3 on rpc-capabilities where lower is better.

The defect was never the sort key. It is that the aggregate includes chains
where a provider had no competitor, so the fix belongs on the value: with
`score_scope: contested_chains` a bench is scored only on chains carrying at
least two measured providers, and a provider with none of those leaves the
ranked field (still visible on its own chain tab). One quantity on screen,
ordering follows from it.

Opt-in per bench and named for the property, not the bench, so any bench
whose chain set contains uncontested chains is a candidate and the rule is
readable in the public YAML. Enabled on wallet-labels-coverage only:
stellar, xrp and bitcoin carry one measured provider each there.

load.ts already fetched every provider's per-chain value inside its per-chain
loop and discarded all but the leader; it now keeps them.

Four other live benches qualify and are deliberately left untouched pending
review: rpc-capabilities, token-quote-coverage, bridge-fee, perp-liq-rate.

Residual limitation documented in methodology: providers are still averaged
over the different subsets of contested chains they cover.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…chain scope (ChainBench#2282)

ChainBench#2281 changes the provider values on wallet-labels-coverage, but the cached
v62 entries still carry the old cross-chain aggregate, so staging kept
serving StellarExpert first. Both keys bumped in lockstep as usual.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
NOWNodes exposes keyless public endpoints on a handful of chains. Tested
apples-to-apples from the VPS with the harness's own eth_getBlockByNumber
probe: public-eth.nownodes.io p50 38ms / head lag 0 blocks vs publicnode,
public-bsc.nownodes.io p50 100ms / head lag 0 blocks. Both fresh, both
under the 5 RPS free limit at the harness's 3-req/min cadence.

Their other public endpoints don't fit an existing bench: Coreum returns
501 on the Tendermint /status our cosmos probe uses (only the gRPC-gateway
REST works), and LUKSO/Bitcoin have no bench. A full scan of
public-<ticker>.nownodes.io across every RPC bench chain confirmed only
eth, bsc, coreum and lukso answer keyless.

Adds nownodes to the harness config for those two chains, the provider
block in both specs, and enriches the registry entry.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…inBench#2285)

The manifest pointed at a generated green "NN" placeholder. Swap it for
a clean square SVG in the NOWNodes brand purple (#A52CE7, sampled from
their wordmark) with a white "N", legible in the 24px leaderboard chip
and the 56px product-page header alike. A 3:1 wordmark would squish in
those square/circular slots; their official CDN icon SVG ships with
empty paths so it can't be used.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…h#2286)

Every headline value on /products/[slug] carried a hardcoded "p50 · 24h",
including the count benches. "19 DEX-indexed chains, p50 over 24h" claims a
distribution that was never computed: those provider blocks repeat one
instant expression across p50, p90 and p99.

The spec already says which is which. A bench whose p50/p90/p99 are three
different expressions computes a real percentile (metadata-coverage takes
quantile_over_time(0.50) over hourly rates); one that repeats a single
expression has one measurement (wallet-labels-coverage is a plain
sum(increase)/sum(increase) ratio). hasDistribution is derived from that in
spec.ts, overlaid from the live YAML like dimensions and expectedN, so a
spec edit lands without waiting on a worker rewrite.

The badge then reads "p50 · 24h" only when a percentile exists, "24h avg"
for rolling ratios (pct, bps) and the bare window otherwise.

18 of the 218 live benches change: 12 to "24h" and 6 to "24h avg". The 166
latency benches are untouched, which is the point — p50 is right there.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nch#2287)

Three additions, all driven by NOWNodes' keyless public endpoints and
tested apples-to-apples from the VPS:

- bitcoin-rpc (ChainBench#259, new): Bitcoin Core getblockcount probe (new "bitcoin"
  Kind reusing callNeoBlockCount). 3 no-key providers: publicnode 35ms,
  drpc 103ms, nownodes 171ms, all at the same tip.
- lukso-rpc (ChainBench#260, new): EVM eth_getBlockByNumber. 3 no-key providers:
  lukso-official 94ms, nownodes 169ms, thirdweb 743ms.
- coreum-rpc: NOWNodes added. Their public Coreum endpoint answers 501 on
  Tendermint /status, so the cosmos probe now falls back to the
  gRPC-gateway REST (/cosmos/base/tendermint/v1beta1/blocks/latest) when
  /status returns http_err — general fix for any REST-only cosmos node.

Adds the two chains + coreum provider to the harness config, the bitcoin
probe case and the REST fallback to probe.go, both specs, and a
lukso-official registry entry.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…list (ChainBench#2289)

NOWNodes now has keyless latency data on five chains (Ethereum, BNB,
Bitcoin, LUKSO, Coreum), so it qualifies for the cross-chain
rpc-capabilities aggregate. This is the exact page/list a NOWNodes
contact asked to appear on. No new data needed; the aggregate
ocb:rpc_latency_milliseconds:p50_24h{provider="nownodes"} already spans
its chains.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Was @NOWNodes_io; their actual account is x.com/NOWNodes.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…hainBench#2291)

The lukso chain and the lukso-official provider had no logo, so the
lukso-rpc leaderboard and chain surfaces showed a placeholder "LU" chip.
Adds LUKSO's official symbol (brand pink #FE005B, from docs.lukso.tech)
and maps both `lukso` and `lukso-official` to it.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…hainBench#2292)

bitcoin-rpc and lukso-rpc are new benches whose chains were absent from
CHAINS, so every chain-name surface (the NOWNodes product page's
"RPC performance by chain" table, chain badges) fell back to the raw
slug and rendered "bitcoin" / "lukso" lowercase next to "Ethereum",
"BNB Chain", "Coreum". Adds both with proper labels (Bitcoin, LUKSO),
native symbols and websites.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…hainBench#2294)

* bridge-monitor: 3/30 tiers, 5-route conserving loop, HL withdraw, proactive equalizer

* bridge-monitor: use api.mobula.io (was demo-api), configurable via MOBULA_API_BASE

* bridge-monitor: keep quote-loop notionals at 5/50/300 (execution tiers 3/30 are separate)

* bench 002: scope region tabs to EU-West while us-east/sgp probes are paused

* bench 001 bridge-fee: scope region tabs to EU-West while us-east/sgp probes are paused

* bench 001/002: display EU-West only (single region) + methodology copy while us/sgp paused
…alized (ChainBench#2297)

Base was the only chain whose zero point was wrong, and measurably so: a
block becomes queryable ~0.36 s after the timestamp it carries (median over
25 consecutive blocks) while the sequencer publishes flashblock
preconfirmations every 200 ms inside the 2 s interval. Measuring against the
block timestamp therefore described the chain's stamping convention, not the
provider's pipeline, and charged anything reading preconfirmations with a
negative lag: 99% of Serialized's Base emissions, 140 of 147.

base_flashblock_ref.go feeds the existing reference clock from that stream.
The clock already keeps the first observation, so the preconfirmation wins
over the sealed-block logs subscription without further change. The endpoint
is public and anycast: 1.1 ms RTT from both the Paris and Singapore boxes,
the same distance as the provider endpoints, so no region is handicapped
against the feeds it measures.

headlineLag applies the substitution in one place, so it lands on all four
providers at once. Re-basing one provider and leaving the others on the old
ruler is the asymmetry this change exists to remove. A Base emission with no
flashblock match is dropped, not measured against a different ruler: a dead
reference must show up as missing data, never as quietly different numbers.

Verified from two vantage points before shipping. Serialized on Base moves
from -1.016 to +0.239 (Paris) and -1.081 to +0.244 (laptop), stable, with 4
negatives out of 125 left as network jitter. Mobula's old-reference figure
from Paris (+1.070) matches production (0.951), which is what makes the
vantage trustworthy.

Only Base changes. Solana, BNB and Robinhood carry no preconfirmation layer
a provider consumes and their chain-supplied timestamps sit within ~60 ms of
the observable moment, so they keep the on-chain timestamp.

Serialized is re-added with the pinned Robinhood token address corrected:
the old value acked and delivered nothing, which is what produced the "they
publish nothing on Robinhood" report. With the address /v1/pool returns,
they deliver 98 events in 5 minutes at p50 +0.596 s.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bench 001 was half-migrated: methodology and cardinality mention four
aggregators but the title, seo_description, subtitle, seo_intro, two
findings and one FAQ answer still list three. The stale findings also
contradict the live tables ('Mobula leads on three of four chains',
'Codex leads on Base').

- bench 001: add Serialized to title/subtitle/seo/intro/FAQ, reword the
  two stale findings around the templated values, add {{p99:serialized}}
- metadata-coverage (004): add Serialized to the title
- answers/which-crypto-price-api-is-the-fastest: add Serialized and
  Robinhood Chain to every static list, 27->48 series, align the Base
  floor and preconfirmed-events limitations with the flashblock reference
- answers/which-crypto-data-api-covers-the-most-blockchains: add
  Serialized (/v1/meta/chains) to the intro and methodology
- benchmarks/README: drop wallet-labels-coverage from the prod-holds
  list since this release publishes it
- harness aggregator-head-lag: document SERIALIZED_API_KEY (README table
  + .env.example), fix tracked aggregators and supported chains lists

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Flotapponnier

Copy link
Copy Markdown
Collaborator

Reviewed — solid editorial cleanup and correct for dev. Two things to flag given the branch state moved since this was opened:

1. Needs a rebase on current dev. dev advanced quite a bit (a main→dev sync plus follow-up merges) and several of those touch benchmarks/aggregator-head-lag.yml, which this PR also edits — so it conflicts as-is (GitHub currently reports mergeable=unknown). Please rebase on latest dev before merge.

2. Serialized is now deliberately dev-only in prod. We just removed Serialized from the production bench 001 (provider block + all copy) as a product decision — it stays full on dev/staging, so completing the Serialized copy on dev (this PR) is exactly right. Heads-up for whoever promotes dev→main next: Serialized is a provider, so there is no automatic held-out gate for it (REMOVED_BENCH_SLUGS is bench-level) — it will silently re-appear on the prod aggregator-head-lag leaderboard + answer pages unless the promotion consciously drops it.

3. wallet-labels-coverage removed from the held-out list — confirmed intended (cleared for prod). Just make sure its spec actually ships to main in that promotion.

Minor: bench 004 (metadata-coverage) gets "Serialized" in title only; seo_description / subtitle still list the old set — worth aligning while you are in here.

Otherwise clean — specs validate, copy is consistent (cardinality 27→48, the stale "leads three of four chains" and "Codex leads Base" claims correctly reworded). Good to merge once rebased.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants