Skip to content

Rates Engine v0.5.0-rc.22

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 07 May 17:49
· 1349 commits to main since this release
8cbad62

[v0.5.0-rc.22] — 2026-05-07

Added

  • /embed/currency/[ticker] iframe widget. Third widget category
    alongside the existing asset + pair cards: ticker / name header,
    inverse-USD rate as headline, 7d % change badge, 7d sparkline,
    attribution + cross-rate footer. SEO opt-out via robots noindex.
    Pre-renders for every ticker /v1/currencies returns at build;
    falls back to eight majors when upstream is unreachable. /widgets
    page gets a "Currency card" section with EUR / GBP / JPY iframe
    snippets.
  • /auth/callback handler on the explorer. Magic-link emails
    point to {DashboardBaseURL}/auth/callback?token=…; this page
    is the missing landing handler for when DashboardBaseURL is
    ratesengine.net. Reads the token, full-page-redirects to the
    API's /v1/auth/callback so Set-Cookie applies and the 303 lands
    the browser on /account logged in. Closes the magic-link loop on
    the explorer side.

Fixed

  • Navbar mobile menu. The IA-restructure (#888) wrapped the
    desktop nav in hidden md:flex without a mobile fallback —
    < 768px screens saw only the logo. New hamburger drawer mirrors
    the desktop dropdowns: Currencies link, Blockchain group
    (collapsible), API Docs, About group (collapsible), Sign in /
    Create account at the bottom. Auto-closes on route change.
  • /v1/sources response unwrapping in DexProtocolsTable + OraclesView.
    Both client components used Array.isArray(env) ? env : [] against
    apiGet<SourceRow[]> — but /v1/sources returns the standard
    { data, as_of, flags } envelope, so the array branch never fired
    and the table rendered empty. Now correctly typed
    apiGet<{ data: SourceRow[] }> and unwraps env.data. Same fix
    applied to OraclesView's /v1/oracle/streams call.

Added

  • /v1/coins listing gains opt-in ?include=sparkline with
    per-row 24h hourly history. Backed by new
    Store.GetCoinsPriceHistory24hBatch — single CTE pass over all
    requested asset_ids (rather than N+1 per-asset queries),
    returning a map[asset_id][]CoinPricePoint. Wire shape:
    Coin.price_history_24h (already present from /v1/coins/{slug};
    now also populated on the listing when opted-in). /assets table
    renders the result as a tiny inline SVG sparkline column —
    client-side draw, signed colour by direction.
  • /v1/coins/{slug} returns 7-day daily price history + sparkline
    toggle on /assets/[slug].
    New Store.GetCoinPriceHistory7d
    emits 7 daily USD-price samples (oldest first), reusing the same
    direct-then-XLM-triangulated path as the 24h series. Coin wire
    shape gains optional price_history_7d. The asset-detail Price
    panel's sparkline now toggles between 24h and 7d windows; falls
    back to whichever series is populated when one is empty (newly-
    observed assets only have hours of history at first).
  • /v1/currencies returns per-row 7d change% + optional sparkline.
    Each CurrencyEntry now carries change_7d_pct (computed
    server-side from the cached history series so every consumer
    agrees on the math). Adding ?include=sparkline attaches
    history_7d_rates (the per-day inverse-USD series) to every
    row — opt-in to keep the default list payload lean. /currencies
    table now has 7d % + 7d chart columns; signed colour follows the
    change direction.
  • Per-source 24h volume sparkline column on the /dexes
    protocol-overview table and the /exchanges CEX table — fulfils
    the user IA spec ("chart showing volume over time"). Backed by
    a new opt-in ?include=stats,sparkline flag on /v1/sources
    that joins per-(source, hour) USD-volume buckets via new
    Store.GetSourceVolumeHistory24h. Same XLM/USD CTE as the
    rest of the volume-derivation surfaces. Holes are zero-filled
    server-side so the wire array always has 24 entries (oldest →
    newest); frontend renders mini SVG bars sized by max bucket.
  • /assets/[slug] converter goes cross-currency. AssetConverter
    now offers any currency from the /v1/currencies snapshot as the
    fiat side of the conversion (USD / EUR / GBP / JPY / CHF / CAD /
    AUD / CNY / INR / BRL / MXN by default; "All currencies…" option
    unlocks the full ~200-ticker list). Computes via the asset's
    USD price + the FX leg from the cached forex snapshot. Footer
    shows both the cross-rate and the FX leg explicitly so users can
    see how the conversion was assembled. Same swap-direction button
    as before — direction state controls which side gets the
    currency selector.
  • /v1/currencies/{ticker} returns 7-day historical series + sparkline
    on /currencies/[ticker].
    Forex worker now backfills the trailing
    7 daily snapshots from currency-api on first run + once per day,
    cached in-memory alongside the latest snapshot. Per-ticker series
    surfaces in the wire shape as history_7d: [{date, rate_usd, inverse_usd}]. Frontend renders a 7-day USD-value sparkline + 7d
    change percentage above the converter. Days where the upstream
    has no published file (rare) are silently skipped — the series
    may have ≤ 7 points.
  • /aggregators surfaces the reference-price aggregators we
    cross-check against.
    New "Reference price aggregators" table
    below the Soroswap-Router / DeFindex cards, backed by
    /v1/sources?class=aggregator&include=stats. Lists CoinGecko,
    CoinMarketCap, CryptoCompare with their cost (free/paid),
    backfill availability, and role. Footer note explains the
    exclusion-from-VWAP policy (they aggregate the same upstream
    venues we already index — including them would double-count).
  • /assets/[slug] gains a USD ↔ asset converter widget per the
    user IA spec ("currency converter widget" on the per-asset page).
    Bidirectional input with a swap button — type a USD amount to see
    asset units, or vice versa. Pure client-side maths against the
    live priceUSD already on the page; refreshes when the parent
    re-fetches /v1/price. Cross-currency conversion (asset → EUR/JPY/…)
    is a follow-up — needs the forex snapshot threaded into the page.

Changed

  • Navbar shows session state. Replaces the static "Sign in /
    Create account" CTAs with a session-aware widget: signed-out
    users still see the CTAs; signed-in users see their email
    in a chip with a dropdown for Account + Sign out. Backed by a
    new useMe() React Query hook that polls /v1/account/me with
    credentials: 'include' (5-min refetch, single shared cache).
    401 responses surface as null without throwing — the navbar
    treats that as "anonymous" rather than an error state.
  • /account uses magic-link cookie auth, surfaces user/account info.
    Replaces the API-key-paste flow with cookie-credential fetches
    (credentials: 'include'). Anonymous visitors see a "sign in"
    prompt linking to /signin instead of an API-key input. Authenticated
    view shows user email + account name + tier + sign-out button +
    the existing key-list/mint flow. /v1/account/me extended to return
    {user, account} nested objects when called via the magic-link
    session — the API-key fields stay populated for bearer-token
    callers, so both flows coexist on the same wire shape.
  • /signin and /signup now use magic-link auth, not API keys.
    Replaces /signup's "POST /v1/signup → here is your plaintext key"
    flow with a magic-link form posting to /v1/auth/login (which
    already existed via the dashboardauth bundle). The /signin
    placeholder shipped in #888 also gets the real form. Both pages
    share the same SignInForm component with a mode flag for
    copy variation. The email link goes to whatever the operator
    configured as DashboardBaseURL — the existing dashboardauth
    /v1/auth/callback handler verifies the token, sets the session
    cookie, and redirects. New emails create the account on first
    callback (no separate signup step). Stale SignupForm.tsx
    removed.
  • /assets adds a network-filter chip row + suppresses market cap
    on low-volume rows.
    Per the user spec: "we need a filter at the
    top to choose the network ... we probably just wont show a market
    cap for low volume assets because we wont have the data confidence
    in doing so." Network is currently all / stellar (Stellar is
    the only ingested network today; the chip writes ?network= for
    forward-compat). Market cap is hidden as whenever the row's
    24h USD volume is < $1,000 — below that the price feed underlying
    the cap is too thin for the cap to be a confident number.

Added

  • GET /v1/currencies/{ticker} + /currencies/[ticker] detail page.
    Returns the requested currency's USD-base rate, inverse rate, and
    full cross-rates map (1 unit of ticker → every other supported
    currency, derived from the cached USD-base snapshot). New per-
    currency page surfaces this with: a converter widget (input
    amount + target dropdown, derived live), and a cross-rates table
    showing the most common targets up front with a "show all" expander.
    Statically pre-rendered for every ticker the upstream covers
    (build-time fetch, falls back to the majors list if upstream is
    unavailable). 404 with problem+json shape when the ticker isn't
    in the snapshot; 503 while the cache warms up.
  • GET /v1/currencies + /currencies real table. Replaces the
    forex placeholder shipped in #888 with live fiat coverage. New
    internal/sources/forex package wraps the free, MIT-licensed
    currency-api (ECB / FRBNY-aggregated, daily-updated, 200+
    currencies, no API key, hosted on jsDelivr). The API binary
    starts a background worker that refreshes the in-memory snapshot
    hourly; GET /v1/currencies reads from the snapshot and returns
    ticker / name / USD-denominated rate per currency, with the
    upstream's published-at date so clients can render staleness.
    Frontend table is sortable + searchable; per-currency drill-down
    with 1h / 24h / 7d change windows + market cap + volume + supply
    lands once we wire a paid forex feed (currency-api is daily-
    granularity only).
  • GET /v1/lending/pools — returns one row per Blend pool
    observed in the auction stream, with 24h / all-time auction
    counts + 30d unique users + last-seen timestamp. Backed by new
    Store.ListBlendPools. Per-pool TVL / utilisation / APYs land
    via additional fields when the pool-storage reader worker ships;
    the wire shape is designed to grow rather than version-bump.
  • /lending pools table — surfaces the new endpoint at the
    bottom of /lending, below the existing Blend narrative card,
    per the user IA spec ("1 table showing all the lending pools,
    the protocol — all will be blend for now"). Each pool address
    links out to stellar.expert for the contract page.
  • /exchanges page (real, replacing the placeholder shell): per-CEX
    table sorted by 24h USD volume desc, with trade count, pair count,
    and a share-of-CEX-volume bar. Backed by /v1/sources?include=stats
    filtered to Subclass=CEX. Per-exchange detail pages at
    /exchanges/{binance,coinbase,kraken,bitstamp} with 24h activity
    card + paginated pair table backed by /v1/markets?source=.
    Statically pre-rendered for the 4 connected CEXes.
  • GET /v1/oracle/streams — returns one row per
    (source, asset, quote) triple, the latest observation in the
    trailing 7d window. New Store.LatestOracleStreams underneath
    uses DISTINCT ON (source, asset, quote) … ORDER BY ts DESC for
    the per-stream latest. Backs the new "price streams" table on
    the explorer's /oracles page (the second table per the user IA
    spec — "1 at the bottom showing all price streams from all
    oracles").

Changed

  • /oracles rebuilt as two live tables. Replaces the curated
    Oracle-card grid with: (1) per-oracle activity table backed by
    /v1/sources?class=oracle&include=stats (24h updates + active
    stream count + last update + VWAP-inclusion policy) and (2) the
    full price-streams table backed by /v1/oracle/streams. Keeps the
    SEP-40 compatibility panel as a footer note. Curated narrative
    notes per oracle moved to /sources/ and the integration
    audits under /research/discovery.
  • /dexes adds the DEX-protocols overview table above the
    all-pools table — per the user spec ("2 tables, at the top
    lists all our connected dexes with basic overview info about
    them"). Per-row: protocol name, 24h USD volume, 24h trade count,
    active pool count (markets_count_24h), and a details link to the
    per-protocol /sources/ drilldown. Backed by
    /v1/sources?include=stats filtered to Subclass=DEX and sorted by
    volume desc. Updates the page header to clarify CEX pairs live
    at /exchanges (not /markets).
  • Top nav restructured to grouped IA. Navbar collapses from a
    flat 11-item bar to: Currencies / Blockchain (dropdown) /
    API Docs / About (dropdown) / Sign in / Create account. Blockchain
    contains Assets, Exchanges, Dexes, Lending, Aggregators, Oracles,
    Networks. About contains Pricing, Blog, API status (external),
    Company, Careers, Contact. Status pill stays as a compact dot
    beside the search/theme controls. The route formerly at /network
    is now /networks (singular → plural to match the dropdown label
    and reflect that the page is per-network even though only Stellar
    is wired today).

Added

  • New route shells. /currencies, /exchanges, /pricing, /blog,
    /company, /careers, /signin land as honest placeholders explaining
    what's in flight rather than mock data — the live build wires the
    full table once the underlying ingest / agg / page work merges
    (forex feed for /currencies, per-CEX aggregations for /exchanges,
    magic-link auth for /signin).
  • /v1/pools ?source=<name> filter. Restricts the result to
    one DEX's pools. Non-DEX names (binance, coinbase, …) return an
    empty list rather than 400 — callers can pass through user input
    without separately validating against the registry. Backs the
    /dexes venue-chip row, which now triggers a server-side re-fetch
    per chip rather than client-side filtering the current page (the
    prior behaviour broke for users who wanted to see Soroban-only
    pools, since page 1 by USD-volume-desc is dominated by SDEX).

Fixed

  • /v1/sources surfaces 24h USD volume on Soroban DEX sources
    same root cause as the /v1/pools fix below: SUM(usd_volume) on
    Phoenix/Aquarius/Comet trades was NULL because their trades had
    null usd_volume. GetSourceStats now applies the same XLM/USD
    CTE so per-protocol totals on /v1/sources?include=stats are
    populated. Backs the new "DEX protocols" overview table at the
    top of /dexes.
  • /v1/pools surfaces 24h USD volume on Soroban DEX pools
    Phoenix / Aquarius / Comet trades against the XLM SAC wrapper
    (CAS3J7GY…) had NULL usd_volume because the operator's USD-pegged
    Phase 1 allow-list doesn't include XLM itself. The vol_24h CTE
    now derives USD volume per (source, base, quote) directly from
    trades: trades with non-null usd_volume use it as-is; trades
    with native or XLM SAC on either side use base_amount/quote_amount
    × XLM/USD (read from the same on-chain XLM/USDC vwap that powers
    /v1/coins). Pure SEP-41/SEP-41 token swaps still emit null until a
    per-token oracle wires in. Side benefit: per-source attribution —
    two DEXes trading the same canonical pair now get separate vol
    numbers rather than the cross-source sum. Same Pool.Volume24hUSD
    wire field; previously-empty values now populate.
  • /v1/pools is DEX-only, never CEX rows. "Pool" is AMM/DEX
    terminology — applying it to CEX trading pairs (binance,
    coinbase, kraken, bitstamp) misnames the data. Handler now
    resolves the DEX subset of the source registry
    (Class=Exchange + Subclass=DEX → soroswap, phoenix, aquarius,
    sdex, comet) and constrains the trades scan with
    t.source = ANY($N). CEX trading pairs are at /v1/markets,
    which has always been the cross-venue collapsed view. Frontend
    copy on /dexes updated to "DEX pools" with a link to /markets
    for CEX pairs.

Changed

  • /dexes is now the all-pools table — same shape as /assets,
    one row per (venue, base, quote) tuple. Replaces the 5
    per-DEX summary cards. Sortable by 24h volume desc / source-pair
    alphabetical. Cursor-paginated 100 pools per page. Source-filter
    chip row at the top scopes the table to one venue. Each row
    deep-links to /markets/<base~quote> for the standard pair detail.
    Backend: new /v1/pools endpoint backed by Store.AllPools
    one row per (source, base, quote) tuple, distinct from
    /v1/markets which collapses across sources.

Added

  • /dexes/: full pool table per DEX. Click any DEX
    card on /dexes to drill into a paginated table of every
    (base, quote) pool the source observed in the last 14 days,
    with per-pool 24h volume, 24h trade count, and last-trade
    relative timestamp. Sortable by 24h volume desc (default) or
    pair alphabetical. Each row deep-links to /markets/
    for the standard chart + OHLC + trade history view.
    Backend: extended MarketsReader with a SourceMarkets
    method that filters trades by source before grouping; new
    query parameter /v1/markets?source=<name>. Cache-keyed
    separately from the global markets list.
  • /dexes shows real per-DEX volume + trades + pool count.
    Was: 5 cards of static prose. Now: each card has live 24h
    USD volume, trade count, and pool count (unique base/quote
    pairs the source observed in 24h) from
    /v1/sources?include=stats. Backend extension: GetSourceStats
    now returns SUM(usd_volume) + COUNT(DISTINCT (base, quote))
    alongside the existing trade-count column. Page header shows
    rolled-up totals across all five venues.

Removed

  • /compare page dropped from explorer. Redundant with
    /assets + per-asset detail, and rarely worked cleanly. Removed
    from navbar, footer search, and sitemap. The route directory
    is gone.

Performance

  • /v1/markets cold-cache p99: 30s → 3.7s. Reported by user
    ("markets doesn't load in any reasonable time"). Root cause was
    a correlated (SELECT vol_usd FROM vol_24h v WHERE v.base_asset = t.base_asset AND v.quote_asset = t.quote_asset) subquery
    evaluated up to 4× per output row (SELECT + 2× HAVING + ORDER
    BY) in buildDistinctPairsQuery. Refactored to a single LEFT
    JOIN against the vol_24h CTE; the planner now resolves
    volume once per (base, quote) tuple. 8× cold-cache improvement;
    warm cache unchanged at ~100ms. Deployed on r1 as
    v0.5.0-rc.22-perf via the manual scp path (GH Actions still
    billing-blocked).

Fixed

  • Top markets + Markets table: defensive null-asset handling.
    Audit-and-harden pass after the home Recent-trades crash
    (#879). Same .startsWith() pattern in HomeTopMarkets
    and markets/MarketsTable would have crashed on the same
    rare /v1/markets row with one side null. Both renderers now
    return "—" for null/undefined input. Embed and pair-detail
    call sites take their input from a URL split on ~ so
    both sides are always defined; no change needed there.
  • Home Recent trades: crash on null base/quote asset.
    HomeRecentTrades's short() helper called .startsWith() on
    the canonical asset string, but rare /v1/history rows arrive
    with one side null. The crash bubbled up the React tree and
    blanked the home page. Now short() returns "—" for null
    inputs; the row still renders the price + timestamp + source,
    and the pair label displays without a link (since
    /markets/native~undefined would 404).

Changed

  • Navbar surfaces SDK link. Adds SDK between Research and
    Docs in the navbar so Go integrators can find the typed
    pkg/client examples without having to drill into the footer
    or Cmd-K search first.
  • Home hero: "Get a free key" CTA. Adds a fifth pill linking
    to /signup next to Browse assets / Browse markets / API docs
    / Read methodology. The conversion path was previously hidden
    in the navbar's Sign-up button only; surfacing it as a hero
    CTA matches what every other enterprise data API does on its
    landing page.
  • Home live-panels: explicit "Open" CTAs. NetworkLivePanel
    and SystemHealthLivePanel on the home 3-up grid now end with
    small "Open network →" / "Open diagnostics →" links matching
    the Diagnostics teaser's pattern. Wrapping the whole Panel in
    a Link would conflict with the source-reveal button, so the
    CTA sits at the bottom of the panel content instead.
  • docs.ratesengine.net topbar: 3 new links. Adds Methodology,
    Go SDK, and Changelog to the docs site's topbar between Explorer
    and Status. Visitors landing on the API reference can now jump
    to the explainer, the typed SDK page, or the release feed
    without having to bounce back to the explorer first.
  • HomeTryAPI: nudge to /sdk when Go tab is selected. The Go
    example renders stdlib http.Get (matches the curl/JS/Python
    shape — same one-liner). When the visitor picks the Go tab,
    the footnote now adds "For idiomatic Go using the official SDK,
    see /sdk" so they can switch to the typed client.

Added

  • /sdk showcase page. Surfaces the official Go SDK at
    pkg/client. Install command, quick-start example, five
    paste-ready common patterns (batch lookup, history, SSE
    stream, OHLC bar, error handling), authentication modes
    (anonymous / API key / SEP-10), and links to godoc + GitHub
    source + REST reference. Reuses the CopyableSnippet
    component from /widgets for the code blocks. Linked from
    footer + Cmd-K search + sitemap.
  • /diagnostics BackfillSummary card. Surfaces backfill
    worker state (active workers / slowest active lag / furthest
    ledger reached / distinct shards) as a sibling card to the
    existing live-ingest HealthSummary. Same /v1/diagnostics/cursors
    call powers both — no extra round trip. Page now reads
    "Live ingest" + "Backfill workers" as two clearly-labeled
    health surfaces rather than mixing them.
  • Home Try-the-API: rc.21 endpoints surfaced. Adds two
    example tabs covering features shipped in rc.21 — Network stats — 24h volume + market count (/v1/network/stats)
    and Sources with 24h trade counts
    (/v1/sources?include=stats). Ten canonical examples now,
    up from seven.
  • Home "Recently shipped" widget: Subscribe (Atom) ↗ link.
    Surfaces /changelog.atom directly from the home widget so
    visitors can subscribe to release feeds without first
    scrolling to the dedicated changelog page.

Changed

  • Home network strip cells are now clickable. Each of the
    five cards on the home strip deep-links to its corresponding
    page: 24h volume + Active markets → /markets, Assets indexed
    /assets, Sources online → /sources, XLM → /assets/XLM.
    Hover state matches the rest of the explorer's link chrome
    (border + shadow lift on hover). Visitors can drill from the
    scale-of-the-network number straight into the underlying
    catalogue.

Added

  • /research/operations runbook browser. Curated set of four
    cross-cutting operator docs — archival-node-bringup,
    release-process, deploy-workflow, sev-playbook — rendered as
    static pages on /research/operations/<slug>. Per-alert on-call
    runbooks (60+ files in docs/operations/runbooks/) stay
    GitHub-only; these four are the canonical "stand up your own
    copy" + incident-response procedures any auditor or prospective
    operator would want to read. Removes the GitHub-link-only
    catch-all "Browse by topic" section since every topic now has a
    curated on-site browser.

Changed

  • /network + /divergences: ADR mentions deep-link. Plain-text
    ADR-0004 / ADR-0008 / ADR-0015 callouts on /network and the
    ADR-0019 mention on /divergences now jump straight to the
    rendered ADR pages instead of being inert text.

Performance

  • status site: tier probe cadence. The status page used to
    hammer every public endpoint every 30 s — including expensive
    catalogue/history queries that drive the API's SLO burn rate.
    Endpoints now carry a tier: hot (30 s — healthz, readyz,
    price, price/batch, price/tip, sources, network/stats) keep
    the original cadence; warm (2 min — coins, markets, issuers,
    history, observations, oracle/lastprice, vwap/twap/ohlc/chart)
    drop their poll rate by 4×. Should clear the recurring
    slo_latency_burn_medium page-level alert without sacrificing
    outage-detection latency on the cheap probes that actually
    need it.

Added

  • /changelog.atom syndication feed. RFC-4287 Atom feed of
    every release entry on the explorer side, generated at build
    time from CHANGELOG.md. Designed for Feedly, Slack RSS bot,
    and any other feed reader that wants push-style notifications
    when a release ships — no polling. The /changelog page header
    now surfaces a "Subscribe (Atom) ↗" link. Same pattern the
    status site uses for /v1/incidents.atom.
  • /sources/<name>: integration audit link. When the source
    has a corresponding /research/discovery/<slug> audit, the
    detail header now shows a "Read integration audit →" CTA.
    Reflector's three contracts (cex/dex/fx) collapse to a single
    audit page since they share the on-chain interface. CEX/aggregator
    sources without published audits (binance, coinbase, kraken,
    etc.) render no link.

Changed

  • /anomalies, /divergences, /lending: deep-link to specific
    research pages.
    ADR-0019 mentions on /anomalies + /divergences
    now link directly to /research/adr/0019 instead of the generic
    /research index. /lending's "Discovery notes (Blend)" + "(Comet
    backstop)" CTAs now jump to /research/discovery/blend and
    /research/discovery/comet.

Fixed

  • NetworkLivePanel: assets-indexed count capped at 500. The
    side panel on home was reading useCoins(500).coins.length
    for the asset count — silently capped at the page limit. Same
    bug as #854 fixed for the network strip; this is the same fix
    for the side panel. Switches to /v1/network/stats.assets_indexed
    (real count, ~85,750). Latest-ledger field also reads from
    network/stats with cursor-table fallback.

Added

  • /contact page. Single destination for the previously-orphaned
    "Contact sales" callouts on /signup. Five channel cards covering
    security disclosures (security@), sales (sales@), GitHub issues,
    status feed subscription, and architecture/methodology research
    links. Plus a four-question FAQ. Pro/Business/Enterprise tier
    cells on /signup now deep-link here. Linked from footer + Cmd-K
    search + sitemap.

Changed

  • /markets/<pair>: full CandleChart with timeframe + granularity
    controls.
    Replaces the static 24h sparkline with the same chart
    surface /assets/<slug> ships — 24h / 7d / 30d / 1y timeframes,
    1m / 15m / 1h / 4h / 1d granularities. Pair-specific (no quote
    toggle since the URL already pins the pair). 24h change % and
    last-hour USD volume keep the original build-time fetch so
    metadata + headline numbers stay server-rendered.

Added

  • /widgets showcase page. Public docs + live preview for the
    embeddable iframe widgets (/embed/asset/<slug>,
    /embed/pair/<base~quote>). Three asset cards (XLM, USDC, AQUA)
    • two pair cards (XLM/USDC, XLM/USD) render live with
      paste-ready iframe HTML next to each. Linked from footer +
      Cmd-K search. The widgets themselves were always there but had
      no surface explaining how to use them; this closes the loop.

Changed

  • /dexes + /oracles: deep-link directly to per-protocol audits.
    Each card's "Read integration audit" CTA now jumps straight to
    /research/discovery/<slug> (Soroswap → soroswap, Phoenix →
    phoenix, etc.) instead of dumping the visitor on the generic
    /research index. Visual change: external-link icon dropped
    for the internal arrow style.

Added

  • /research/discovery integration audit browser. Curated
    set of ten per-DEX/per-oracle Phase-1 audits — sdex, soroswap,
    phoenix, aquarius, comet, blend, reflector, band, redstone,
    chainlink — rendered as static pages on
    /research/discovery/<slug>. Each audit names the contract
    repo + commit checked, the upstream-source quirks we found,
    and how the decoder handles them. Allow-listed via a CURATED
    array; the rest of docs/discovery/ stays private.
  • SearchModal: missing pages. Cmd-K search now lists the new
    /methodology, /research, /changelog, /compare,
    /signup, and external status.ratesengine.net alongside the
    existing pages.
  • /markets table: sortable Base + 24h volume columns. Click
    the Base header to flip to alphabetical-by-pair (the API's
    pair order_by); click 24h volume to flip back to volume-desc.
    Active sort is mirrored in the URL as ?order=... for
    bookmark + back-button parity with /assets.
  • Live navbar status pill. Replaces the hard-coded green dot
    next to the navbar's Status link with a real-time poll of
    /v1/status.overall. Green pulses when ok, amber on degraded,
    red on down, slate when the fetch fails. Tooltip surfaces the
    current state in plain English. Polls every 60 s with 30 s
    shared cache so navigating between pages doesn't burst the
    API.
  • Source detail page: 24h trade count. /sources/<name>
    now shows that venue's 24h trade contribution baked at build
    time alongside the rest of the registry profile (e.g. binance
    → 3.56M, coinbase → 1.81M, sdex → 1.56M). Same ?include=stats
    opt-in the listing already uses (#852).
  • Home hero: "Read methodology" CTA. Adds a fourth pill
    alongside Browse assets / Browse markets / API docs that links
    to /methodology. Footer System column gains the same link.

Fixed

  • Home network strip: undercounted 24h volume + market + asset
    totals.
    Previously the strip summed useMarkets(500, ...) and
    counted useCoins(50) client-side, capping the displayed
    numbers at the first page of each list. Now consumes
    /v1/network/stats (rc.21) directly — server-aggregated across
    the full corpus. Real numbers visible on the home page: 24h
    volume jumps from a partial sum to the actual ~$5.8B aggregate,
    and "Active markets" jumps from 500 to ~23,400.