You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Soroswap trades now carry their trader (taker) — and a replay
backfills all history.SwapEvent.to (the swap recipient) is
on-chain in every soroswap swap since genesis, but the decoder
dropped it — soroswap was the one venue with 0% trades.taker
coverage (every sibling: 100%), which excluded soroswap from the
per-address trades view and its page's trader metrics. Captured
best-effort (an unreadable recipient never drops the trade); the
trades upsert already carries taker = EXCLUDED.taker, so a projector-replay -source soroswap retro-fills every historical
trade.
Added
Every protocol category now ships a full visual suite (the
"primary point for protocols to show their stats" directive) —
window-reactive (24h/7d/30d/90d pills now on EVERY protocol page,
hourly buckets at 24h): Lending/Blend — activity-by-pool +
event-kind donuts, supply-vs-borrow / backstop / auction series,
per-pool top-5 lines, flash-loan table (counts over mixed-asset
sums by policy); SoroCredit — positions + settlement series; Yield/DeFindex — vault deposits-vs-withdrawals lines, flows-by-
vault donut, per-vault table (single-asset amounts only — the 2
multi-asset vaults honestly render "—"); Oracles (reflector ×3,
redstone, band) — update-cadence series, per-feed top-5 lines,
updates-by-feed donut, feeds table, freshness + median-interval
KPIs (counts and timestamps only — no price restatement). All new
SQL validated read-only on r1 with timings pinned in comments.
Fixed
CCTP flow volumes no longer double-count: transfers are deduplicated
and mint_and_forward is excluded from sums. Ground-truthed on r1
(2026-07-30, all 52,205 cctp_events rows): (1) rows decoded before
event_index landed (migration 0112) coexist with their re-derived
copies — 12,139 (tx, op, type) groups hold a legacy event_index-0 row
plus the true-index row with identical amounts — so every flow query
now collapses to one row per (tx_hash, op_index) transfer; (2) every mint_and_forward op also emits mint_and_withdraw for the SAME
funds (0 forward-only ops), with the forward amount exactly 10× on
all 13,651 pairs — it restates the canonical 6-decimal value at the
local 7-decimal scale, so summing both inflated a forwarded transfer
11×. Inbound sums now use deduplicated mint_and_withdraw only.
Shape tests pin both rules. (The stale legacy rows themselves remain
in the table; queries are dedupe-safe regardless — an operator
cleanup can drop them independently.)
Redstone subset attribution is order-preserving — the residual 170
blind ledgers resolve. The v0.21.5 full verify cut the blind class
1,626 → 170; the residue was prices matching TWO candidates' medians
simultaneously, which the unordered rule refused. The adapter builds updated_feeds in a single pass over feed_ids (the same fact that
makes the equal-arity case a positional zip), so the surviving
entries are an ordered SUBSEQUENCE — attribution is now a
DP-counted subsequence alignment that attributes only a UNIQUE
complete alignment. Order can only disambiguate, never misattribute
(any true assignment is order-preserving by construction); genuinely
ambiguous events still refuse. Golden-pinned on the real
ledger-60104689 event (7 feeds → 5 survivors with a shared-median
collision). Completeness flips at the post-deploy replay + verify.
Added
Explorer: the 24h/7d/30d/90d analytics window pills now live at
BespokeSection level, so EVERY protocol category's bespoke block —
KPIs included — is window-reactive. Previously only the bridge
showcase owned pills (and its KPIs stayed pinned to 90d while its
charts switched). Switching a pill refetches /v1/protocols/{name}?days=N and swaps the whole block;
BridgeShowcase now consumes the section-level window as props (its
all-time cumulative headline stays pinned to the initial fetch), and
non-bridge categories gain generic rendering for " · "
series — folded into one palette-colored multi-line panel per group
(the DEX "Top pairs · XLM/USDC" lines) instead of one panel per
series — plus window-labelled donuts/tables and honest
loading/empty/error states. TimeSeriesChart accepts the hourly
"YYYY-MM-DDTHH:MM" 24h-grain point dates with a time-of-day axis.
Vitest covers the lift for both paths: all categories refetch, the
bridge suite is unaffected.
DEX/AMM protocol pages get the full visual analytics suite
(soroswap / aquarius / phoenix / comet / sdex; no spec change — every
shape exists in 1.15.0). The bespoke block now serves: a "Volume by
pair" composition (top 8 pairs by USD volume + a SQL-side "Others"
fold, so SDEX's ~99k window pairs never cross the wire); USD-volume,
trade-count and unique-trader time-series plus top-5-pairs-by-volume
multi-series ("Top pairs · XLM/USDC", …), hourly-grained at the 24h
window via the real-time source_volume_1h rollup; avg-trade-size
(exact NUMERIC division by the PRICED trade count) and unique-trader
KPIs; honest "since 2026-03-18" lifetime totals labelled by the daily
rollup's materialization floor (never "all-time" — raw SDEX history
reaches 2018); and a window-scoped "Largest trades" top-10 table with
tx links. Pair labels resolve token contracts through the verified-
currency catalogue's derived SAC addresses (XLM/USDC, …); unverified
tokens show truncated contract ids, never guessed symbols. Every
query was validated read-only on r1 (2026-07-30): two deliberate
SQL shapes keep SDEX's 90d window sub-second (hash-agg pair count
0.67s vs 6.0s naive; direct CAGG join for top-5 series 0.87s vs
19.8s), and raw-trades-derived surfaces (traders / avg size / largest
trades) are gated to ≤7d windows on SDEX with the omission Noted on
the block — soroswap's trader metrics are omitted honestly too (its
decoder captures no taker). Shape tests pin the grain, the window
bounds, the ADR-0003 NUMERIC rules and both perf-critical shapes.
CCTP SDF-showcase analytics suite: where USDC comes from and where
it goes (spec 1.15.0, additive). /v1/protocols/cctp's bespoke
block gains a generic breakdowns field (named composition datasets
for donut rendering) carrying "Inflows by source chain" / "Outflows by
destination chain"; per-chain top-5 inbound + outbound time-series
("Inbound · Base", …); an all-time daily "Cumulative net inflow"
series; all-time inbound/outbound/net KPIs plus unique depositor and
recipient counts; and a window-scoped "Largest transfers" table.
Source chains are attributed from the burn-side USDC token embedded in
each transfer's CCTP BurnMessage; destinations via Circle's public
domain registry — both maps verified against Circle's primary docs
(USDC contract addresses + domain list, 2026-07-30), including the
32-byte-address tails for Solana / Aptos / Starknet. Unrecognised
tokens/domains are labelled "Unverified (0x…)" / "Domain N" — never
guessed. The explorer's CCTP page renders the suite: side-by-side
source/destination donuts, per-chain multi-line charts, the headline
cumulative net-inflow chart, and largest transfers linking to /transactions/{hash}, all reactive to the existing window pills.
/v1/protocols/{name} accepts ?days= (1/7/30/90, default 90) to
window the bespoke analytics block (spec 1.14.0, additive). Anything
outside the whitelist is a 400 problem+json (never a silent clamp);
the detail TTL cache now keys on (protocol, window) so window switches
can't serve another window's cached numbers. At days=1 the bridge
flow series bucket HOURLY (a daily bucket collapses 24h to one point);
series names dropped their grain prefix and are now window-stable —
cctp "Inbound (USDC)" / "Outbound (USDC)", rozo "Settled volume
(USDC)". Lake-analytics fields keep their fixed 90-day lookback. The
explorer's bridge pages (cctp/rozo) render the flows as one combined
inbound/outbound line chart with 24h/7d/30d/90d window pills.
Bridge pages show USDC-denominated in/out FLOWS, not just counts. /v1/protocols/cctp gains directional volumes (inbound = mints from
remote burns, outbound = deposit_for_burn), daily in/out series, and
per-domain volumes; /v1/protocols/rozo gains its first bespoke
block (settled payment volume + daily series; admin flush sweeps
excluded to avoid double-counting). Amount scales ground-truthed
on-chain against the USDC SAC leg of real transactions — and they
DIFFER: CCTP events are canonical 6-decimal, Rozo events are local
7-decimal SAC stroops (the documented external-scaling trap class).
Exact NUMERIC division end-to-end. Registry genesis labels corrected
to lake-derived exact first events (cctp 62,403,000→62,146,641 —
the re-projected head; rozo 62,403,000→60,829,397).
Fixed
Unknown tx hashes no longer trigger a 10.5B-row scan. TransactionByHash fell through to the full-table bloom probe on
every index miss — written when tx_hash_index was partially
backfilled. The index now covers genesis→tip (20.78B rows from
ledger 3, verified on r1), so an index miss is an authoritative
not-found; the scan remains only for index-path errors and
index/base inconsistencies (both pinned by tests). Closes the last
serving-path instance of the non-sort-key filter class — and an
unauthenticated multi-second-per-request lever.
Fixed
Account history (tx + ops) sourced arms are primary-index reads —
the 6-second bloom probe is gone./v1/accounts/{g}/transactions
and /operations resolved "transactions this account SOURCED" via
the source_account bloom skip-index over the full 23B/34B-row
tables — granule-pruned but scan-shaped (measured on r1: 6.17 s for
the sourced arm vs 0.056 s for the participant arm on the SAME
328-op account), which is what pushed heavy-history accounts into
the 8s 503 class under load. New slim projection stellar.ops_by_source (the ttl_live_until fix class:
deploy/clickhouse/ops_by_source.sql — table + MVs from BOTH
operations and transactions so op-source overrides stay exact, plus
windowed backfills) turns both sourced arms into PK-prefix reads.
Fail-loud without the table (no scan fallback); deploy order:
DDL + backfill before the binary.
Added
GET /v1/accounts/{g}/trades — per-address historic trades. The
served-tier trades hypertable read per-address: newest first,
keyset-paged by an opaque (ts, ledger, tx_hash, op_index) cursor,
limit clamped to 200, amounts/usd_volume as decimal strings
(ADR-0003). Attribution rides the table's real account columns — taker (acting account: sdex/aquarius/phoenix/comet) and maker
(resting sdex offer) via a two-arm UNION so each arm walks its own
account-leading partial index (migration 0123, trades_taker_ts_idx/trades_maker_ts_idx — build CONCURRENTLY by
hand on r1 first, see the migration header); a static note
discloses the venues that structurally cannot attribute (soroswap
records no acting account; off-chain CEX/FX rows have no Stellar
account). Spec 1.13.0; explorer account page gains a Trades panel.
GET /v1/accounts/{g}/activity — segmented "what has this address
been doing" breakdown. One aggregate payload: all-time per-op-type
counts involving the account (ClickHouse — the same two
skip-index/participant UNION arms as /operations, aggregated with
per-arm uniqExact so un-merged ReplacingMergeTree parts can't
inflate counts, under the explorerScanSettings pin), attributed
trades total, per-(protocol, action) DeFi event counts
(blend/blend_backstop/blend_auctions/phoenix_stake/defindex/
sorocredit/aquarius — only tables that genuinely carry a per-account
column), and rozo + cctp bridge-transfer counts (cctp parties matched
inside the attributes jsonb; the matching limits are documented on
the wire in bridge_transfers.note). Whole-history aggregates never
run on the request path: the payload is served through the shared
contract-detail stale-while-revalidate cache (act: key, existing contract_detail SWR metric label), with per-segment honest degrade
via coverage_note. Explorer account page gains an Activity summary
panel.