Skip to content

Serialized: brand colour + logo alignment - #2400

Merged
Flotapponnier merged 1 commit into
devfrom
fix/serialized-brand-logo
Sep 16, 2026
Merged

Flotapponnier merged 1 commit into
devfrom
fix/serialized-brand-logo

Conversation

@Flotapponnier

Copy link
Copy Markdown
Collaborator

Serialized had no brand colour and drew the same orange as Mobula on every chart; now its logo blue. The mark's viewBox is re-centred so it sits like the other logos.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

…mark centred in its box

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw
@Flotapponnier
Flotapponnier merged commit eb3591f into dev Sep 16, 2026
@Flotapponnier
Flotapponnier deleted the fix/serialized-brand-logo branch September 16, 2026 13:23
Flotapponnier added a commit that referenced this pull request Sep 17, 2026
…ontested-chain scoring the wallet-labels spec relies on) (#2422)

* fix(products): per-chain chips show real leadership only, with the denominator (#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 "#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. "#1 on
Solana" was #1 of 2 on bench 008 while sitting next to "#3 of 8" for the
aggregate. They now read "#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>
(cherry picked from commit eda2da8)

* fix(ranking): rank multi-chain benches by contested-chain wins, not the mix (#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 "#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>
(cherry picked from commit b6ba6b0)

* fix(scoring): scope the value to contested chains, opt-in per bench (#2281)

Replaces the global chain-wins sort from #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>
(cherry picked from commit 401d0a7)

* chore(cache): bump bench-unfiltered and all-benchmarks for contested-chain scope (#2282)

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>
(cherry picked from commit 5ef21d8)

* feat: add Serialized as provider on benches 004 and 008 (#2261)

Wires serialized.xyz into metadata-coverage (004) and wallet-labels (008),
the two benches where their endpoints map 1:1 to the existing scoring rule.

Both providers throttle client-side at ~16 rps: Serialized enforces a hard
40 req/s burst cap and an unthrottled worker pool turns coverage into a
rate-limit artifact (measured 77% -> 37%).

Adds the registry entry, logo and a full onboarding audit documenting the
apples-to-apples numbers and two scoring flaws the tests exposed in our
own benches (logo presence vs resolution on 004, name-service strings
counted as entity labels on 008).

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

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 5dc8d21)

* feat: declare Serialized in the 004 and 008 bench specs (#2262)

The harnesses emit provider="serialized" but the leaderboards are
driven by the explicit providers block in each spec, so the series
never rendered. Adds the block for both benches, same query shape as
the incumbents.

Validated with SpecSchema.safeParse across all 218 specs; every
formula stays under the 240-char cap that silently drops a spec.

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

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 0730b30)

* feat: add Serialized to benches 005 and 090 (chain coverage) (#2263)

Serialized publishes its chain list at the free GET /v1/meta/chains.
The same list answers both benches: they run their own indexers and
do not separate asset-registry coverage from DEX-pool coverage, so
the count is identical on 005 and 090 by construction.

Only chains the endpoint marks status=live are counted, so a future
beta or deprecated status cannot inflate the number.

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

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 8ae50fe)

* docs: correct the head-lag claim in the Serialized audit, add follow-ups (#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>
(cherry picked from commit dcfe080)

* feat(001): measure Base against the flashblock reference, re-add Serialized (#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>
(cherry picked from commit 9a354bc)

* Serialized: brand blue (was the palette orange next to Mobula), logo mark centred in its box (#2400)

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>
(cherry picked from commit eb3591f)

---------

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