Skip to content

Promote dev to main: Serialized onboarding, bench scoring fixes, 001 node reference - #2269

Open
Flotapponnier wants to merge 175 commits into
mainfrom
dev
Open

Flotapponnier wants to merge 175 commits into
mainfrom
dev

Conversation

@Flotapponnier

Copy link
Copy Markdown
Collaborator

Staging state on dev since 2026-09-05, reviewed at https://staging-openchainbench.vercel.app.

What this promotes

Serialized (serialized.xyz) as a provider

Bench integrity fixes, all as separate series so history is preserved

Audit doc docs/methodology/serialized-onboarding-audit.md v1.3 (#2264, #2265): every number, every correction, two methodology defects in our own benches, a verified 5.2x BONK mispricing traced to a pool-ranking unit bug on their side.

What merging to main does beyond the site

The three Railway head-lag services (Aggregator east usa, Agg eu west, agg sgp) build from main, root harnesses/aggregator-head-lag. After this merge, trigger a fresh git build on each (serviceInstanceDeployV2); SERIALIZED_API_KEY is already set on all three. Agg eu west has three failed snapshot-upload deploys since 2026-09-05 14:32 (lstat …/harnesses: no such file or directory), a railway up from a directory without the harness path; a git build replaces it.

Known state at promotion time

  • 004: Serialized is producing (p50 53.3% on the spec query) but the leaderboard still shows the pre-outage snapshot because Mobula/Codex/Jupiter quantiles are NaN while the dead hours (webshare proxy quota, 429) remain in the 24h window; quorum fails 1/4 and the worker keeps the previous render. Self-heals once those hours roll out.
  • 008: Serialized 3rd at 76.75% (n=1,188). 005: last at 19. 090: 4th of 5 at 19 (Sim by Dune is dead: api.sim.dune.com no longer resolves).

🤖 Generated with Claude Code

https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

…2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.
* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection
…2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease
* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease
* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column in top markets to fit xyz:NVDA
* feat(rpc): add Shentu bench #254 and MANTRA Chain bench #255

* fix: remove accidental dev-portal submodule
* merge: dev → main (Gains carry fix + vault fee split) (#2191)

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* feat(rpc): Union bench #253 (#2195)

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: Gains carry projection (v6 action names + still-open positions)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column for long tickers (xyz:NVDA)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column in top markets to fit xyz:NVDA

* feat(rpc): add Union bench #253 (Nodes.Guru, Stake And Relax, High Stakes) (#2194)

* fix(union-rpc): remove em dashes from YAML

* feat(union): add provider SVG logos and brand colors

* feat: Shentu #254 + MANTRA Chain #255 benches

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: Gains carry projection (v6 action names + still-open positions)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column for long tickers (xyz:NVDA)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column in top markets to fit xyz:NVDA

* feat(rpc): add Union bench #253 (Nodes.Guru, Stake And Relax, High Stakes) (#2194)

* fix(union-rpc): remove em dashes from YAML (#2196)

* feat(rpc): Shentu #254 + MANTRA Chain #255 (#2199)

* feat(rpc): add Shentu bench #254 and MANTRA Chain bench #255

* fix: remove accidental dev-portal submodule

* fix: bench-blob revalidate 300s to fix perp ISR conflict
…2207)

* fix(fee-compare): rename Volume→Position size + clearer vault fee label

* fix(fee-compare): show total position value + inline vault fee explanation
…#2208)

* fix(fee-compare): rename Volume→Position size + clearer vault fee label

* fix(fee-compare): show total position value + inline vault fee explanation
* merge: dev → main (Gains carry fix + vault fee split) (#2191)

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* feat(rpc): Union bench #253 (#2195)

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: Gains carry projection (v6 action names + still-open positions)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column for long tickers (xyz:NVDA)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column in top markets to fit xyz:NVDA

* feat(rpc): add Union bench #253 (Nodes.Guru, Stake And Relax, High Stakes) (#2194)

* fix(union-rpc): remove em dashes from YAML

* feat(union): add provider SVG logos and brand colors

* feat: Shentu #254 + MANTRA Chain #255 benches

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: Gains carry projection (v6 action names + still-open positions)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column for long tickers (xyz:NVDA)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column in top markets to fit xyz:NVDA

* feat(rpc): add Union bench #253 (Nodes.Guru, Stake And Relax, High Stakes) (#2194)

* fix(union-rpc): remove em dashes from YAML (#2196)

* feat(rpc): Shentu #254 + MANTRA Chain #255 (#2199)

* feat(rpc): add Shentu bench #254 and MANTRA Chain bench #255

* fix: remove accidental dev-portal submodule

* feat: Band Protocol #256 + cheqd #257 benches

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: Gains carry projection (v6 action names + still-open positions)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column for long tickers (xyz:NVDA)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column in top markets to fit xyz:NVDA

* feat(rpc): add Union bench #253 (Nodes.Guru, Stake And Relax, High Stakes) (#2194)

* fix(union-rpc): remove em dashes from YAML (#2196)

* feat(rpc): Shentu #254 + MANTRA Chain #255 (#2199)

* feat(rpc): add Shentu bench #254 and MANTRA Chain bench #255

* fix: remove accidental dev-portal submodule

* feat: Band Protocol #256 + cheqd #257 benches

* fix: bench-blob revalidate 300s to fix perp ISR conflict (#2206)

* merge: dev → main (Gains carry fix + vault fee split) (#2191)

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* feat(rpc): Union bench #253 (#2195)

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: Gains carry projection (v6 action names + still-open positions)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column for long tickers (xyz:NVDA)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column in top markets to fit xyz:NVDA

* feat(rpc): add Union bench #253 (Nodes.Guru, Stake And Relax, High Stakes) (#2194)

* fix(union-rpc): remove em dashes from YAML

* feat(union): add provider SVG logos and brand colors

* feat: Shentu #254 + MANTRA Chain #255 benches

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: Gains carry projection (v6 action names + still-open positions)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column for long tickers (xyz:NVDA)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column in top markets to fit xyz:NVDA

* feat(rpc): add Union bench #253 (Nodes.Guru, Stake And Relax, High Stakes) (#2194)

* fix(union-rpc): remove em dashes from YAML (#2196)

* feat(rpc): Shentu #254 + MANTRA Chain #255 (#2199)

* feat(rpc): add Shentu bench #254 and MANTRA Chain bench #255

* fix: remove accidental dev-portal submodule

* fix: bench-blob revalidate 300s to fix perp ISR conflict

* fix(fee-compare): total position value + inline vault fee explanation

* fix(fee-compare): remove vault fee — carry fees settled per-action, not OI surcharge (#2209)

* feat(rpc): ICON bench #258 — new icon probe kind, 3 keyless providers
* fix: include long-running Gains positions in HL funding projection

* fix: use earliest POSSIZEINCREASE as anchor for positions opened before fetch window
* fix: include long-running Gains positions in HL funding projection

* fix: use earliest POSSIZEINCREASE as anchor for positions opened before fetch window

* fix: fetch 1yr Gains history for position reconstruction to find true open timestamps
* fix: include long-running Gains positions in HL funding projection

* fix: use earliest POSSIZEINCREASE as anchor for positions opened before fetch window

* fix: fetch 1yr Gains history for position reconstruction to find true open timestamps

* feat: grey out Gains-exclusive pairs in comparison, exclude from HL fee calc

* fix: hide equivFee for Gains-exclusive pairs (coin not on HL)
* fix: signed HL funding projection, filter exclusive coins, increase coin limit to 20

* fix: sort Gains trades oldest-first for correct size tracking; fix equivFee uses HL rate not Gains rate
* merge: dev → main (Gains carry fix + vault fee split) (#2191)

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* feat(rpc): Union bench #253 (#2195)

* fix(harnesses): cap LZ/CCIP/Axelar cardinality to bench-tracked chains only (#2187)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit (#2188)

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection (#2189)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains action names v5→v6, handle position size increases (#2190)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: Gains carry projection (v6 action names + still-open positions)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column for long tickers (xyz:NVDA)

* fix(cache): strip heavy fields from aggregate blob to pass 2MB limit

Hub pages only need card data. Drop seriesByRegion24h, metricPanels,
editorial text (seoIntro/faq/findings/methodology/disclaimer/abstract/
perChainExplainer) from the blob aggregate slim. Cuts serialized size
from ~4.3 MB to under 2 MB so unstable_cache actually persists the
entry instead of silently dropping it on every render.

* fix: include still-open Gains positions in carry projection

* fix: update Gains open action names to v6 API, handle TradePosSizeIncrease

* fix: widen coin name column in top markets to fit xyz:NVDA

* feat(rpc): add Union bench #253 (Nodes.Guru, Stake And Relax, High Stakes) (#2194)

* fix(union-rpc): remove em dashes from YAML

* feat(union): add provider SVG logos and brand colors

* fix(citation): allow negative p50 for deviation benches
…ns, comparable notional (#2217)

F1: paginate fetchHlFundingHistory (up to 5 pages × 500) to cover 180d+ windows
F4: multi-slice reconstructGainsPositions — one PositionSlice per size-change period
    so pre-increase periods use smaller notional (more accurate HL equiv funding)
F5: track comparableNotionalUsdc (HL-listed coins only) and use it in walletStats
    so the HL taker-equiv fee isn't inflated by PONS/Gains-exclusive notional
report: Best Robinhood Chain RPC (median-scoped)
Flotapponnier and others added 30 commits September 14, 2026 21:50
…nsfers enabled, rate inverted) (#2352)

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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
MoonPay, Meld and Onramper were black-on-transparent (invisible on the
dark theme) and Ramp's R was white (invisible on light); Mercuryo was a
480x68 wordmark. Now: MoonPay disc + triangle from their app icon;
Ramp sign and Onramper three-circle mark from their own CDNs, Meld's
hexagon and Mercuryo's official favicon, each on a white rounded tile
so they read on both themes.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
#2354)

The directory appeared in the working tree while the logo change was
being committed with git add -A. It is not part of that change and is
not ready; files stay on disk untracked for whoever is working on it.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…a spot volume no longer shown as perp volume (#2355)

/perp/gains showed $30B days: the chart is the day-over-day delta of
Gains' cumulative leveraged_volume, and that counter jumped +$29B on
2026-09-03 and +$27B on 2026-09-07 (history re-indexes on Gains' side)
while real days are $30-500M. deltaBarsFromCumulative now drops deltas
above 8x the median (unit-tested on the real series).

GMX, Hyperliquid, edgeX, Drift, SynFutures, KiloEx, Orderly and
Backpack fed "Daily volume" and "Total volume" from DeFiLlama's free
/summary/dexs/<slug>, which is SPOT swap volume: GMX ~$1M/day vs ~$50M
of perps, Hyperliquid ~$85M vs ~$14B. Perp volume history is on
DeFiLlama's paid tier (402); bench 266 (perp-volume-history harness,
in progress) will rebuild it per venue. Until then those pages omit
the volume chart and card rather than show spot numbers; fees charts
and native 24h volume KPIs stay.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… and Paradex ranked (#2358)

Tom asked for the pre-TGE venues on the P/F bench. New spec field
provider.unranked ("Pre-TGE"): the loader stamps unrankedLabel on the
row and keeps ms at zero, so every ranking helper (liveResults, leader,
field stats) still skips it, and the ledger renders an unranked block
under the field with the row's companion-panel values (fees 30d, OI)
and a neutral badge, sorted by fees. Ostium, Pacifica, Extended plus
two new venues, Nado (Ink) and Decibel (Aptos), use it.

edgeX (EDGE, CoinGecko rank 167) and Paradex (DIME) turned out to have
listed tokens: they get cgIDs in the harness and enter the ranking
(edgeX at ~3.6x). DeFiLlama's fee adapter reports very low fees for
Paradex; noted in the tag and methodology.

Verified end to end: harness built from this tree (20 protocols, one
live poll), scraped by a local Prometheus, materialized with the
worker's loader, rendered by next dev: 14 ranked rows, 5 pre-TGE rows
with fees, no UNRESPONSIVE badges. bun 261/261, typecheck, validate.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…s vs GMX compare hero (#2357)

* bench 266: daily perp DEX volume on closed UTC days, backfilled; Gains vs GMX compare hero

New harness perp-volume-history: one perp notional figure per venue per
UTC day for 10 venues (Hyperliquid, GMX V2, Gains, Aster, Lighter, dYdX,
Paradex, Extended, Orderly, Aevo), read from the upstream each DeFiLlama
adapter reads (DeFiLlama's derivatives API is paid). 400 day backfill on
first boot, hourly re-read of the last three closed days, JSON history
mirrored to /data/state/aggregate/perp-volume so Caddy serves it on the
existing kv aggregate path. Gains reads the backend volume-mix trade
notional, or the Dune view DeFiLlama reads when DUNE_API_KEY is set;
DEFILLAMA_API_KEY switches every venue to the Pro API.

Site: bench spec with 1d headline, 7d/30d window toggle, cohort share
and history depth; /compare hero (daily bars, lead ribbon, 7d/30d lead,
days led, current streak) for any pair of cohort venues, curated
gains-vs-gmx; /perp/<venue> volume charts now read this series instead
of DeFiLlama's dexs summary, which is spot swap volume for GMX and
Hyperliquid. gmx-v2 aliases to gmx so bench 041 lands on the same
product and compare pages.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

* perp-volume-history: flush after every source; Dune view at most every 12h (free-tier credits)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

* perp venue page: comment reflects #2355

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

* bench 266: Hyperliquid split into main dex and HIP-3 rows; Lighter adds the Robinhood deployment

Checked every row against DeFiLlama on 2026-09-13. GMX, Extended,
Orderly, Aevo, Paradex match to the digit; Aster and dYdX within 1%.
Lighter read 23% under DeFiLlama's page because its parent also sums
the Robinhood chain deployment (api.rh.lighter.xyz): both are summed
now (1.159B vs 1.161B). Hyperliquid read 8% over on the day and 26%
over on the week: the candle reconstruction matches the exchange's own
dayNtlVlm (3.361B vs 3.359B) and DeFiLlama's single line covers HIP-3
dexs only partially, so the main dex and the builder-deployed HIP-3
dexs are now two rows instead of one blended figure.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

* compare hero: weekly A / B volume ratio chart, venue logos; curated aster-vs-hyperliquid, aster-vs-lighter, dydx-vs-gmx

Seven-day windows ending on the last closed day, tiled back 16 weeks,
median dashed, latest window shaded, tooltip decomposes the ratio into
both volumes and the distance to the median. Same window as the 7d tile
so the two never disagree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

---------

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…eaches quorum during the first backfill (#2360)

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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… volume source replaced (upstream dead since 09-10) (#2359)

Venue pages now draw the daily volume chart from the perp-volume-share
bench blob (perp_venue_volume_24h_usd, our harness reading each venue's
native API): one bar per finished UTC day from the 12 h ring, last
sample of the day (dailyBarsFromRing, unit-tested). Venues with an exact
native daily history (Gains, Lighter) keep it; the chart title says
which source it is. This restores the chart on GMX, Hyperliquid, Aster,
dYdX, Extended, Pacifica, Paradex, Aevo, Orderly, Backpack, Vertex, GRVT
that #2355 had emptied.

While checking the cohort series, Gains was frozen at $44M since 09-10:
stats.gains.trade answers Cloudflare 1016 (origin DNS error) and the
DeFiLlama fallback is paid-only. The cohort harness now derives Gains'
24h volume from backend-global.gains.trade/api/stats daily snapshots
(Arbitrum, Base, Polygon, MegaETH), scaled to 24 h, with a re-index guard
(delta > 40x the median of recent deltas is a history backfill, not
trading; Gains had +$29B and +$27B jumps this month). Live run: $533M.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e-mix auto + direct), same definition as bench 266 (#2361)

The 24h gauge read leveraged_volume deltas from /api/stats since #2359.
That counter is Gains' own perimeter: resizes at full notional plus an
"other" bucket, up to 3x what DefiLlama and bench 266 show on busy days
(2026-09-14: $482M vs $152M). The daily chart on /perp/gains and the 24h
figure on /perps disagreed on what "Gains volume" is.

Now /api/volume-mix?from=D&to=D per UTC day, autoVolumeUsd +
directVolumeUsd (opens and closes at notional, resizes at traded delta),
the same field bench 266 stores. Rolling 24h = today so far + yesterday
x (24 - h) / 24. Yesterday missing -> today alone only after 20:00 UTC,
else nothing (gauge keeps its last value). Two calls per tick, upstream
allows 30/min.

Bench 041 and 234 methodology text updated (was still describing the
dead stats.gains.trade endpoint and Arbitrum+Polygon only).


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ange (#2362)

Prom only holds perp_daily_volume_usd since tonight's first scrape, so
the bench chart showed a point at "now" and nothing on 7d/30d/90d/1y
while the harness already holds 400 days per venue. A small registry
(src/lib/series-history.ts) lets /api/series build the dense grid from
the harness JSON for registered benches; panels stay on Prom.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…quid candles stop ~340 days back and were re-walked every sweep) (#2363)

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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…bel) for daily-cadence benches (#2364)

perp-daily-volume moves once per UTC day, so 1h/6h/24h drew one point at
"now" and the ledger said "(24h)" for a closed-day figure. The chart now
hides ranges below min_range, opens on default_range and the ledger's
base window reads "last closed day".


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…displayed (#2365)

The compare hero, provider profile and every title built from the
providers blob still said "gains.trade": the perp-asset-breadth blob was
last materialized on 2026-08-17 (before the 08-25 YAML rename) and its
result name is the first appearance the profile builder sees. An
editorial CANONICAL_NAMES override for `gains` now wins over any stale
appearance, the way Helius/PublicNode/dRPC already do.

Remaining "Gains Network" copy renamed in bench 266's spec (venue name,
description, methodology, FAQ) and the P/F bench tag, plus the display
strings and brand mentions in the perp harnesses (perp-volume-history
JSON venue name, cohort/fees/longevity registries, apps API name,
permissions-scan metric help, comments). API hosts (*.gains.trade) and
DeFiLlama match strings untouched.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ange (bench 266 opened on 24h with no pill selected) (#2366)

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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ive view's definition as a caption (#2367)

The View pills above the chart (P/F ratio, FDV / fees, P/S, ...) only
had the Prom gauge name as a native title. Each pill now shows the
panel's spec `description` on hover and keyboard focus, and the active
view's description is repeated under the row so the definition is
readable on touch screens.

The headline tab reads a new optional `panel_main_description` spec
field (schema, type, loader); bench 265 sets it to the P/F definition.
Panels without a description render as before.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…drops the duplicate logo row (#2368)

Each compare card now carries the 7d/30d/90d history behind its two
headline numbers, read from /api/series filtered to the pair, fetched
when the card scrolls into view. The perp volume hero already sits
under the provider header cards, so its own logo row went.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
#2369)

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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…chart (#2370)

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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…laims matched to live floats and multiples (#2371)

- seo_description and two findings appended a literal "x" after
  {{best_p50}} / {{worst_p50}}, which already carry the unit: the meta,
  OG and Twitter descriptions read "GNS trades at 1.559xx". Description
  also rewritten to fit the 158 char cap instead of being cut with an
  ellipsis.
- seo_intro: HYPE/LIT/ASTER float is 23/25/35%, so "a quarter to a
  third of supply"; the expensive end is dYdX and Aster, with Paradex's
  multiple flagged as an adapter artifact (Derive sits mid-table now).
- SynFutures row labelled "F (SynFutures)": the bare ticker made
  compare links read "GNS vs F".


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…and a proper axis (#2372)

Each card now carries the history behind its two numbers: view tabs
mirroring the bench page (headline metric plus every metric panel with a
tab), 7d / 30d / 90d range, y axis with nice ticks, area fills, latest
or hovered values in the legend. Fetched on scroll-in from /api/series
filtered to the pair, cached per view and range.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… side has no data, isolated points drawn (#2373)

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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ives up early (#2374)

The dYdX indexer rate-limited the VPS IP mid-backfill and the source
spent an hour walking every market through the retry ladder while the
four venues behind it waited. Sources now run in parallel (one goroutine
each, flush + publish as each lands), 429s honour Retry-After, and the
dYdX walk stops after a run of rate-limited calls at one request a
second.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…emits it (shipped to prod in #2375) (#2376)

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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ilures (the retired Ethereum deployment answers 504) (#2378)

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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… OI (Float stays a chart tab; six columns max) (#2379)

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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…el, DeFiLlama check in the intro (#2381)

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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ort and product cards (#2382)

The OG / Twitter card body was one italic sentence; nothing in it caught
the eye in a feed. The claim now sits on its own line under an orange
marker (#ffb257), with the qualifier in the usual muted italic:

- bench cards (OG, Twitter, per-chain OG): "GNS posts the lowest p/f
  ratio at 1.559x" highlighted, then "(p50, 24h)". The title is no
  longer repeated under the claim.
- report cards: the hero finding's first clause (split at the first
  ", " / ". " / "; " / " - " between 24 and 84 chars) highlighted, the
  remainder within the previous ~140 character budget.
- product cards: "#1 on 11 of 13 benchmarks" (or "N benchmarks
  measured" when no win) highlighted.

headlineSentence() is unchanged in output; it is now built from the new
headlineParts() so the cards and the citation string stay in lockstep.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
#2385)

USDC by SEPA was the headline but no keyed provider fills it: MoonPay's
test key answers 'Currency not supported in test mode' for USDC and
Transak's quote endpoint has no SEPA. BTC by card is the one cell every
provider in the cohort quotes, so every row is scored on the same thing.
SEPA, USDC and ETH stay on the grid as their own series. Copy, FAQ,
findings and every selector updated; status draft -> live.

Live on the VPS harness: MoonPay 810 bps, Transak 410 bps (24h p50,
198 samples). Ramp, Onramper and Meld rows wait for keys.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…rker quorum passes; Ramp, Onramper, Meld return with their keys (#2386)

The worker needs min(ceil(declared/2), 3) ranked rows to publish; with
five declared and two keyed it kept the draft render forever.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…hidden spread, BTC SEPA, BTC 100 EUR, ETH card/SEPA, USDC card) (#2387)

Every cell was already measured and only readable in Prometheus; the
metric_panels expose them as the View pills and six ledger columns.
Declared fee and hidden spread split the headline number the way the
bench's own story tells it.


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

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant