Skip to content

Stellar Index v0.21.7

Choose a tag to compare

@github-actions github-actions released this 30 Jul 22:32

[v0.21.7] — 2026-07-30

Fixed

  • 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.