feat: DEX hub USD for cUSTC/UST1/USTR from largest-liquidity pools #1083

Merged
PlasticDigits merged 2 commits from 556-dex-hub-usd into main 2026-08-18 03:08:54 +00:00
PlasticDigits commented 2026-08-18 02:30:12 +00:00 (Migrated from gitlab.com)

Summary

  • Replace hardcoded P522-Q UST1 = $1 and USTR = 2.5 × USTC ingest pegs with materialized hub_prices ranked by humanized USD TVL (reserves, not last print).
  • Bootstrap is fixed: CEX USTC oracle → usd(cUSTC) → deepest cUSTC/UST1 pool → usd(UST1) → deepest USTR vs already-priced hub → usd(USTR).
  • Protocol adds a DEX reference card (protocol-dex-hub-prices) between Global stats and the CEX oracle card. CEX /oracle/price catalog stays three tickers; ustr/ust1/custc remain 400.

Closes #556

APIs

  • GET /api/v1/hub-prices and GET /api/v1/hub-prices/{ticker} (custc | ust1 | ustr). Unknown ticker → 400.
  • Additive overview fields: custc_price_usd, ust1_price_usd, ustr_price_usd (null when unresolved). ustc_price_usd stays the CEX USTC ticker.

Ranking (H1–H3, H8)

  • TVL = humanized reserves × already-resolved USD (not raw integers; 18-dec vs 6-dec cannot invert rank).
  • Floor: $100 USD TVL default (HUB_USD_TVL_FLOOR); comparison is tvl < floor (exact $100 included).
  • Ties: max TVL, then lexicographic pair address.
  • Identity: hub CW20 contract / native uusd as cUSTC-equivalent. Symbol-spoof natives skipped.
  • Stale pair_reserves skipped (book_snapshot_max_staleness_ms). Zero reserves skipped.
  • Refresh deletes all hub_prices then inserts resolved marks — oracle down → empty table, UI —, does not freeze last $1.

Guardrails kept

  • No ustr/ust1/custc on CEX OracleTicker.
  • No vFDUSD in hub USD or volume_usd.
  • No swap_events scan on GET (O(1) hub_prices read).
  • CG/CMC last_price stays human close_price.
  • Ops UST1_LP_USTR_PER_USTC in scripts/rebalance-mint-ust1-lp.sh unchanged (sizing only).
  • UI invert (#524 / #543) stays frontend invertUsd.

Docs / skills

  • New: skills/AGENTS_INDEXER_HUB_USD.md (H1–H10)
  • Updated: docs/indexer-invariants.md, docs/frontend.md, docs/testing.md, oracle + rebalance runbooks
  • Crosslinks: AGENTS.md, AGENTS_FRONTEND_PROTOCOL_STATS.md, AGENTS_INDEXER_PAIR_PRICE_USD.md, AGENTS_INDEXER_EXTERNAL_ORACLE.md, AGENTS_FRONTEND_CHARTS_OVERVIEW.md, AGENTS_REBALANCE_MINT_UST1_LP.md
  • Verify: make verify-issue-556

Test plan

  • make verify-issue-556 (docs, ingest greps, indexer lib hub_usd + pair_price_usd, integration API/ingest/oracle 400s, frontend RTL, Playwright protocol e2e)
  • Related: make verify-issue-515 550 522 543 524
  • LocalTerra Protocol + Charts hand-computed reserve ratio (issue lists as manual)
  • Mainnet smoke: dex.cl8y.com/protocol USTR visible; /oracle/price/ustr still 400

Acceptance (H1–H10)

  • H1 cUSTC = USTC oracle; oracle down → NULL
  • H2 UST1 from max USD-TVL hub cUSTC/UST1 via reserves, not $1
  • H3 USTR from max USD-TVL vs priced hub, not 2.5 × USTC
  • H4 ingest price_usd uses hub quotes; invert still UI (invertUsd) — Charts/Trade mocked via pairPriceUsd + 524/543 verifies
  • H5 Protocol DEX card; CEX tabs still 3
  • H6 /oracle/price/ustr|ust1|custc 400
  • H7 volume_usd uses hub; not vFDUSD
  • H8 dust / stale / unlisted / symbol-spoof cannot win
  • H9 skill + invariants + make verify-issue-556
  • H10 CG last_price stays human

Out of scope (unchanged)

  • #557 tape humanization, #553 charts leaderboard, #551 P&L
  • Changing ops LP seed
  • Phase 1b persisting general economic tokens (CL8Y etc.) as API tickers — helper resolve_token_vs_priced_hub exists; API only persists custc/ust1/ustr
  • On-chain TWAP / UST1 window / CEX poll symbols
## Summary - Replace hardcoded P522-Q **UST1 = $1** and **USTR = 2.5 × USTC** ingest pegs with materialized `hub_prices` ranked by humanized USD TVL (reserves, not last print). - Bootstrap is fixed: CEX USTC oracle → `usd(cUSTC)` → deepest cUSTC/UST1 pool → `usd(UST1)` → deepest USTR vs already-priced hub → `usd(USTR)`. - Protocol adds a DEX reference card (`protocol-dex-hub-prices`) between Global stats and the CEX oracle card. CEX `/oracle/price` catalog stays three tickers; `ustr`/`ust1`/`custc` remain **400**. Closes #556 ## APIs - `GET /api/v1/hub-prices` and `GET /api/v1/hub-prices/{ticker}` (`custc` \| `ust1` \| `ustr`). Unknown ticker → 400. - Additive overview fields: `custc_price_usd`, `ust1_price_usd`, `ustr_price_usd` (null when unresolved). `ustc_price_usd` stays the CEX USTC ticker. ## Ranking (H1–H3, H8) - TVL = humanized reserves × already-resolved USD (not raw integers; 18-dec vs 6-dec cannot invert rank). - Floor: `$100` USD TVL default (`HUB_USD_TVL_FLOOR`); comparison is `tvl < floor` (exact $100 included). - Ties: max TVL, then lexicographic pair address. - Identity: hub CW20 contract / native `uusd` as cUSTC-equivalent. Symbol-spoof natives skipped. - Stale `pair_reserves` skipped (`book_snapshot_max_staleness_ms`). Zero reserves skipped. - Refresh deletes all `hub_prices` then inserts resolved marks — oracle down → empty table, UI `—`, does not freeze last `$1`. ## Guardrails kept - No `ustr`/`ust1`/`custc` on CEX `OracleTicker`. - No vFDUSD in hub USD or `volume_usd`. - No `swap_events` scan on GET (O(1) `hub_prices` read). - CG/CMC `last_price` stays human `close_price`. - Ops `UST1_LP_USTR_PER_USTC` in `scripts/rebalance-mint-ust1-lp.sh` unchanged (sizing only). - UI invert (#524 / #543) stays frontend `invertUsd`. ## Docs / skills - New: `skills/AGENTS_INDEXER_HUB_USD.md` (H1–H10) - Updated: `docs/indexer-invariants.md`, `docs/frontend.md`, `docs/testing.md`, oracle + rebalance runbooks - Crosslinks: `AGENTS.md`, `AGENTS_FRONTEND_PROTOCOL_STATS.md`, `AGENTS_INDEXER_PAIR_PRICE_USD.md`, `AGENTS_INDEXER_EXTERNAL_ORACLE.md`, `AGENTS_FRONTEND_CHARTS_OVERVIEW.md`, `AGENTS_REBALANCE_MINT_UST1_LP.md` - Verify: `make verify-issue-556` ## Test plan - [x] `make verify-issue-556` (docs, ingest greps, indexer lib `hub_usd` + `pair_price_usd`, integration API/ingest/oracle 400s, frontend RTL, Playwright protocol e2e) - [x] Related: `make verify-issue-515` `550` `522` `543` `524` - [ ] LocalTerra Protocol + Charts hand-computed reserve ratio (issue lists as manual) - [ ] Mainnet smoke: `dex.cl8y.com/protocol` USTR visible; `/oracle/price/ustr` still 400 ## Acceptance (H1–H10) - [x] **H1** cUSTC = USTC oracle; oracle down → NULL - [x] **H2** UST1 from max USD-TVL hub cUSTC/UST1 via reserves, not `$1` - [x] **H3** USTR from max USD-TVL vs priced hub, not `2.5 × USTC` - [x] **H4** ingest `price_usd` uses hub quotes; invert still UI (`invertUsd`) — Charts/Trade mocked via pairPriceUsd + 524/543 verifies - [x] **H5** Protocol DEX card; CEX tabs still 3 - [x] **H6** `/oracle/price/ustr|ust1|custc` 400 - [x] **H7** `volume_usd` uses hub; not vFDUSD - [x] **H8** dust / stale / unlisted / symbol-spoof cannot win - [x] **H9** skill + invariants + `make verify-issue-556` - [x] **H10** CG `last_price` stays human ## Out of scope (unchanged) - #557 tape humanization, #553 charts leaderboard, #551 P&L - Changing ops LP seed - Phase 1b persisting general economic tokens (CL8Y etc.) as API tickers — helper `resolve_token_vs_priced_hub` exists; API only persists `custc`/`ust1`/`ustr` - On-chain TWAP / UST1 window / CEX poll symbols
PlasticDigits commented 2026-08-18 03:08:40 +00:00 (Migrated from gitlab.com)

added 9 commits

  • 5c90437d...eed4be8d - 8 commits from branch main
  • da70fed3 - Merge branch 'main' into 556-dex-hub-usd

Compare with previous version

added 9 commits <ul><li>5c90437d...eed4be8d - 8 commits from branch <code>main</code></li><li>da70fed3 - Merge branch &#39;main&#39; into 556-dex-hub-usd</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/365/diffs?diff_id=1967164796&start_sha=5c90437d896a344f5b1c3540a62667fa26535146)
PlasticDigits commented 2026-08-18 03:08:54 +00:00 (Migrated from gitlab.com)

mentioned in commit f6a06fcd1e

mentioned in commit f6a06fcd1e5ffe35a6c4685c5e96e5267e43ab9a
PlasticDigits (Migrated from gitlab.com) merged commit f6a06fcd1e into main 2026-08-18 03:08:54 +00:00
PlasticDigits commented 2026-08-18 03:09:41 +00:00 (Migrated from gitlab.com)

mentioned in commit a932718fe8

mentioned in commit a932718fe8a01beb2359bf8b884afa380735a590
PlasticDigits commented 2026-08-18 03:11:25 +00:00 (Migrated from gitlab.com)

mentioned in issue #556

mentioned in issue #556
PlasticDigits commented 2026-08-18 03:11:27 +00:00 (Migrated from gitlab.com)

mentioned in issue #559

mentioned in issue #559
PlasticDigits commented 2026-08-18 03:11:33 +00:00 (Migrated from gitlab.com)

mentioned in issue #551

mentioned in issue #551
PlasticDigits commented 2026-08-18 03:12:09 +00:00 (Migrated from gitlab.com)

mentioned in issue #560

mentioned in issue #560
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic!1083
No description provided.