Stellar Index v0.44.2
[v0.44.2] — 2026-08-25
Tested against Stellar protocol 22.
Added
- Scam-pricing gate. An asset whose issuer is flagged scam-class
(malicious/unsafe/fraud/scam/hack/phishing) in the curated
account directory now has its aggregated price AND market cap/FDV
withheld — a scam token no longer publishes a value that lends it
legitimacy, even when its market clears the thin-market substance floor
(RIO-GBNLJIYH… did: it showed a $0.0072 price + a $540k market cap on a
deprecated-scam issuer). Wired at the price-reader seam so one gate
covers/v1/price,/v1/price/batch,/v1/twap,/v1/vwap, the SEP-40
oracle price paths, the asset headline and the live tip (keyed on the
base, so it holds across quotes incl. XLM triangulation), plus a payload
suppression on the/v1/assetslisting + detail (market_cap / fdv /
price / change). Raw trade surfaces (/v1/ohlc,/v1/observations,
/v1/history) andcirculating_supplystay visible; the gate fails
open on a directory outage. Deliberately overturns the directory's
historical "display-only, tags never gate pricing" invariant. (#182)
Fixed
completeness_incomplete{source=comet}fired persistently after the
2026-08-25 Blend/Comet exploit — NOT a data gap (the lake is 100%
complete, watermark at tip) but a verdict artifact: the exploit's 36
self-pair swaps (token_in == token_out) failcanonical.NewPair, so
the comet decoder returned an error and the completeness re-derive
counted each as an undecodable blind spot, holding the source
complete=falseforever (the INV-3 do-nothing re-derive trap). The
decoder now returns "zero rows, no error" for determinate business-rule
rejections (self-pair swap, non-positive amounts) so the re-derive
counts them asexpected=0; the error path stays reserved for
indeterminate parse failures. (#185)external_fx_rate_rejections{reason=history_deviation}paged
indefinitely on a correctly-refused broken ETB history bar
(2026-08-19 = 44, the pre-float peg vs the correct ~160). The band was
right to refuse it; the_stuckreclassification that de-noises the
alert never engaged because the in-band branch cleared the stuck streak
that a good sibling bar in the same trailing-7d sweep had just
incremented. Removed the reset so a persistently-broken bar reaches the
_stuckthreshold (and drops out of the alert), while a genuinely new
bad feed still pages. (#185)- Explorer asset-page price chart was blank for USDC and every fiat
currency: those chart againstfiat:USD, which the/v1/ohlccandle
path has no rows for (a fiat pair has no on-chain constituent; only
/v1/chartcarries the fx-cross series). Fiat currencies now render a
USD line from/v1/chart, and USDC — the dollar reference, which has no
USDC/USD series of its own — shows a "≈ $1.00 reference" panel (linking
the divergence board for depeg watching) instead of an empty grid. (#184) - Explorer "Top assets by activity" ranked by all-time
observation_count
(a cumulative counter that floats long-lived stablecoins to the top) and
omitted native XLM entirely (it has noclassic_assetsrow, so it never
appears in/v1/assets) — so USDC ranked #1 and XLM, the most-traded
asset on Stellar, was absent. Now ranks by trailing-24h volume and injects
native XLM (useNativeCoinover/v1/assets/native); XLM takes the #1
spot it earns on volume (~$43M vs USDC's ~$36M). (#181) - Explorer nav: restored a top-level Ledgers entry in the Stellar
section (it had been folded into the Network hub, making it undiscoverable
from the rail). (#181) /v1/protocols/{name}per-contract activity ran the raw
contract_events FINALscan (merge-on-read of the 12.8B-row
ReplacingMergeTree), which blew ClickHouse's 2 GiB per-query memory
limit (Code 241) — that memory kill was the "certified-lake reader
unavailable" verdict on the protocol page, and the 57s / 3.2B-row scans
were a primary CH-load source behind the API p95/p99 latency alerts and
the tx-outcome read timeouts. Now routed through the existing
contract_events_dailypre-aggregation (like the daily-activity and
event-breakdown views already are) — measured 0.5s vs 57s, no memory
kill. Last-seen is day-grain (sufficient for the roster column). (#180)/v1/anomaliesreturned 500 on every request —FreezeReasonCounts
andFreezeDailyReasonCountsused the same fragile($1 || ' days')
interval concat that took down/v1/divergence: it types$1as
text, but the handler passes anint, and pgx v5 has no int→text
encode plan. Also fixed the latent same bug inListDivergenceSeries
(/v1/divergence/series,$4/$5). All now usemake_interval, and
a package-wide test forbids the concat form so it can't return a third
time. (#179)