Skip to content

Stellar Index v0.31.0

Choose a tag to compare

@github-actions github-actions released this 10 Aug 14:04
· 190 commits to main since this release

[v0.31.0] — 2026-08-10

Fixed

  • Detached-refresh gate is now class-fair (inventory #26 item 5,
    second half): the single global bound stopped the unauthenticated
    scan-amplification but let one key class starve the rest — a crawler
    churning fabricated contract ids could hold every slot while cold
    account/holders/directory pages fast-503d behind it. Each refresh
    class (account state, contract detail, asset holders, contracts
    directory) is now additionally capped at half the global limit; the
    global pool-safety bound is unchanged.
  • /v1/contracts directory census: 40s scans replaced by a day-keyed
    rollup
    (inventory #26 item 2 — the single heaviest explorer read,
    ~160 runs per 3h across the prewarm rungs). New
    stellar.contracts_census_daily (plain per-day per-contract counts;
    whole days recomputed and swapped via REPLACE PARTITION — no MV, so
    the Summing double-count class cannot arise) maintained by the new
    stellarindex-ops ch-census-rollup on a 30-min timer; the reader
    sums day rows (sub-second) with a coverage check that falls back to
    the exact scan while a backfill is incomplete. Window floors round
    to UTC-day resolution.
  • Aquarius claim_protocol_fee now records WHICH token was claimed
    (sources-decode audit 2026-08-04, finding 5): the token address lives
    in topic[1] — not the body — and migration 0129 shipped no token
    column on the documented premise that a recent trade could resolve
    it; the lake refutes that (one tx claims two different tokens with
    near-identical amounts), and per-pool SUM(amount) without the token
    adds integers of different token scales. FeeEvent gains Token
    (decode refuses a claim without it), migration 0139 adds the nullable
    column, and the 163 token-less rows already on r1 re-derive via
    projector-replay -source aquarius (queued).
  • DeFindex harvest events are now decoded (sources-decode audit
    2026-08-04, finding 4): the recognise-and-drop premise ("body never
    observed on-chain") was disproved by the lake — 1,018 harvests with
    body {amount, from, price_per_share}, the exact shape decodeFlow
    reads by name. Harvests now emit direction='harvest' strategy-flow
    rows (migration 0138 widens the CHECK; user-position sums exclude
    them by construction — harvest is strategy yield, not a user flow).
    Historical recovery via projector-replay -source defindex (queued).
  • Phoenix pre-upgrade swaps no longer dropped (sources-decode
    audit 2026-08-04, finding 1 — HIGH): the pre-upgrade pool WASM
    (ledgers 51,019,036 → 53,134,167) emitted 7 field-events per swap —
    no "actual received amount" — but RawSwap.Complete() required that
    slot even though decodeSwap deliberately never reads it, so all
    5,161 pre-upgrade swaps aged out as orphans (r1-confirmed: zero
    phoenix trades before ledger 53,134,242). Aged-out groups whose
    decode-consumed slots are present are now decoded at sweep time
    instead of orphaned; the current era's eager 8-field emit and orphan
    accounting are unchanged. Recovery of the historical rows needs
    projector-replay -source phoenix -from 51019036 (queued).
  • /v1/contracts/{id}/code-history cold reads (the last persistent
    503 class in the route sweep): new keyed
    stellar.contract_instance_changes index — an MV-fed
    ReplacingMergeTree holding one narrow row per captured
    instance-entry write with the executable verdict pre-extracted via
    fixed-offset XDR substrings (byte-verified against go-stellar-sdk
    marshalling and against live r1 data). The reader walks the
    contract's primary key instead of a scan-shaped key_xdr predicate
    over the whole changes log; legacy scan remains the fallback where
    the index is absent. Historical fill via the new
    stellarindex-ops ch-instance-backfill (windowed, resumable, under
    run-heavy-job.sh).

Fixed

  • /ledgers table was permanently stuck on "Loading…" — the page
    wrapped LedgersTable (which takes no useSearchParams) in a
    vestigial <Suspense fallback={null}>, and the static exporter
    emitted that boundary as a never-completing pending template, so
    browsers never hydrated or client-rendered the subtree (zero network
    activity; the only such boundary on the site — audited all pages).
    Wrapper removed. The live-follow refetch on /ledgers + /operations
    is also throttled to one per 10s (operations' newest row structurally
    trails the ingest-tip stream, so unthrottled it refetched every
    close, ~12 req/min per viewer) and no longer fires while the initial
    page fetch is in flight.