fix: Charts pair 24h Vol (token) still formatNum(raw) after #540/#544 #565

Closed
opened 2026-08-18 12:13:06 +00:00 by PlasticDigits · 19 comments
PlasticDigits commented 2026-08-18 12:13:06 +00:00 (Migrated from gitlab.com)

Summary

On Charts & Analytics pair detail (https://dex.cl8y.com/charts → select UST1/cUSTC), the 24h Stats strip still compact-formats raw volume_base / volume_quote with formatNum. Retail sees Vol (UST1) = 847.0M and Vol (cUSTC) = 157.5B for ~847 UST1 / 157K cUSTC ($763 USD already on the JSON).

This is the same formatNum(raw) class as tape Amount in/out (#557), picker volume (#534), and overview USD (#548). Pair-level Vol (token) was explicitly out of scope of #548 and assigned to closed #540 / #544 AC4, but ChartsPage.tsx never changed those two StatBoxes (git log -S 'formatNum(stats.volume_base)' is still the original charts commit).

Observed (columbus-5, 2026-08-18): GET /api/v1/pairs/terra1ceprjsxp86ggftf5e38wwt34l83e5gq7penkdnv4wsatkwcs8v6qccw55f/stats

Field API UI today (formatNum) Honest retail
volume_base 847004054 847.0M 847 UST1
volume_quote 157465643310 157.5B 157.5K cUSTC
volume_usd 763.35… not rendered (type omitted) ~$763
trade_count 41 41 OK

UST1/USTR (6/18) is worse: raw quote volume compact-formats as T.

Related: tape Amount in/out is #557 (do not duplicate here). Overview 24h USD is #548 (done). Picker/pool USD badges are #544 (closed; this issue is the leftover Charts pair-stats strip only).

Current codebase

Frontend — two raw token vols, no USD

frontend-dapp/src/pages/ChartsPage.tsx 24h Stats (when a pair is selected):

            <StatBox label={`Vol (${activePair.asset_0.symbol})`} value={formatNum(stats.volume_base)} />
            <StatBox label={`Vol (${activePair.asset_1.symbol})`} value={formatNum(stats.volume_quote)} />

formatNum is a human compact formatter (K/M/B/T). Indexer volume_base / volume_quote stay raw chain integers (swap_orientation.rs: “Volume buckets stay in raw chain units”).

USD OHLC boxes on the same grid already use high_usd / low_usd / … via pairStatsUsdField (#522). Volume USD is ignored.

IndexerPairStats omits volume_usd even though PairStatsResponse returns it (Option<String>, human USD, P522-Q / hub catalog after #548/#556). Charts tests mock stats without volume_usd and never assert the Vol boxes (ChartsPage.test.tsx).

Helpers already exist:

activePair.asset_0.decimals / asset_1.decimals are already on the pair JSON (do not match decimals by symbol).

Indexer — already has the numbers

GET /api/v1/pairs/{addr}/stats (PairStatsResponse):

  • volume_base / volume_quote: raw oriented sums (unchanged; integrators / CG)
  • volume_usd: human USD SUM(swap_events.volume_usd) for the 24h window
  • trade_count, USD OHLC, human high/low quote-per-base

No indexer schema change is required for the default USD box. Token secondary vols can be scaled in the dApp from pair-leg decimals.

Why the new implementation is needed

  1. Same page as the tape bug. After #557 humanizes Amount in/out, the stats strip above the table will still claim 847 million UST1 of 24h volume next to a tape of ~45 UST1 fills. Retail will not trust either column.
  2. #540/#544 closed with the leftover still on production. #544 AC4 / V544-1 required Charts pair stats primary Vol (USD) and optional human token remainder. The code path was never updated.
  3. USD is already indexed. volume_usd ≈ $763 is on the live stats JSON. The UI types dropped it.
  4. USTR T. 18-dec quote raw through formatNum reprints the #534 / #544 impossible-trillions bug on the pair-detail strip.

Constraints / guardrails

  1. USD is advisory, not settlement (X5 / P522). Label Vol (USD). Tooltip ≤ one sentence (24h volume in USD). Do not imply a peg.
  2. Reuse formatIndexedVolumeUsd. Do not invent a third USD formatter. Unpriced / invalid / negative → —. Trades > 0 and USD missing/0 → —, not $0. Idle (trade_count === 0) may show $0 or — — pick one and test it.
  3. Do not formatNum raw volume_base / volume_quote. If token vols remain as secondary, use formatTokenAmount(raw, asset_N.decimals) from that pair’s legs (activePair.pair_address must match). Missing decimals → —, never assume 6.
  4. JSON stays raw for volume_base / volume_quote. Do not humanize those fields in the indexer. volume_usd stays human USD.
  5. One notional (L10). Display stats.volume_usd as-is. Do not add candle volumes, limit fills, or pool+book legs.
  6. #524 invert does not swap or invert the 24h notional. Pair volume is pair-level. Do not use display-base decimals on the wrong raw field.
  7. Do not match decimals by symbol (same class as #557 A1 / #551 P551-1). Hostile ticker ≠ hub decimals.
  8. Copy (#489). Keep short labels: Vol (USD); optional Vol (UST1) / Vol (cUSTC) only if humanized. No “oriented raw quote-side integer” essays.
  9. Out of scope: tape Amount in/out/Price (#557); overview strip (#548); picker/pool badges (#544); candle histogram units; CG/CMC base_volume / target_volume; settlement/fee math.
  10. Docs + make verify-issue-<iid> in the same MR. Update docs/frontend.md (pair-level Vol was “out of scope #540/#544”) and the Charts overview skill cross-link.

Relevant files

File Role
frontend-dapp/src/pages/ChartsPage.tsx 24h Stats StatBoxes
frontend-dapp/src/pages/ChartsPage.test.tsx RTL — currently no Vol assertions
frontend-dapp/src/types/index.ts IndexerPairStats missing volume_usd
frontend-dapp/src/services/indexer/client.ts getPairStats parse
frontend-dapp/src/utils/chartsOverviewStats.ts formatIndexedVolumeUsd
frontend-dapp/src/utils/formatAmount.ts formatTokenAmount / formatNum
indexer/src/api/pairs.rs PairStatsResponse (already has volume_usd)
docs/frontend.md Charts pair stats contract
skills/AGENTS_FRONTEND_CHARTS_OVERVIEW.md Cross-link leftover
  1. Add volume_usd?: string | null to IndexerPairStats and pass through getPairStats.
  2. Primary 24h vol box: Vol (USD) = formatIndexedVolumeUsd(stats.volume_usd, stats.trade_count) with data-testid="charts-pair-volume-usd".
  3. Optional secondary human token boxes: formatTokenAmount(stats.volume_base, activePair.asset_0.decimals) and quote likewise. Labels keep Vol ({symbol}). Prefer demoting them (smaller / second row) so USD is the default read. If space is tight, USD only is acceptable (V544-1).
  4. Grep gate: ChartsPage.tsx must not contain formatNum(stats.volume_base) or formatNum(stats.volume_quote).
  5. Tests: UST1/cUSTC 6/6 (847004054 → not 847.0M); UST1/USTR 6/18 (raw 18-dec quote → not T); missing volume_usd + trade_count > 0 → —; HTML/NaN/1e309 → —.
  6. make verify-issue-<iid>: vitest ChartsPage + grep + docs mention.

Acceptance criteria

  • V1. /charts pair 24h stats primary volume is USD ($ + compact), matching GET /api/v1/pairs/{addr}/stats volume_usd (rollup lag OK). UST1/cUSTC production ~$763 class, not 847.0M / 157.5B.
  • V2. UST1/USTR pair stats never compact-format raw 18-dec quote as T.
  • V3. If token Vol boxes remain, they are human (formatTokenAmount + that leg’s decimals) and labeled with the token. Missing decimals → —.
  • V4. Unpriced USD + trade_count > 0 → —, not $0 and not formatNum(raw) fallback.
  • V5. #524 invert does not change the USD figure or swap base/quote raw onto the wrong decimals.
  • V6. Integrator JSON volume_base / volume_quote remain raw. CG/CMC unchanged.
  • V7. RTL + make verify-issue-<iid> + docs/skill cross-link.

Test plan — functional paths

Frontend RTL / unit

  • ChartsPage: mock UST1/cUSTC stats volume_base=847004054, volume_quote=157465643310, volume_usd=763.35, trade_count=41 → Vol (USD) matches /^\$/ and does not match /847\.0M|157\.5B/.
  • ChartsPage: USTR-scale volume_quote=19300000000000000000 + 18-dec pair → no /T$/ on the stats strip; USD path used when volume_usd present.
  • volume_usd null/0/'' and trade_count > 0 → —.
  • trade_count === 0 and USD 0 → documented $0 or —.
  • Invalid USD (NaN, "><script>", 200-char string, negative) → —; no exception; no HTML inject.
  • Token secondary (if present): formatTokenAmount path; 6-dec 1000000 → 1 class; missing decimals → —.
  • Invert pill toggle does not change Vol (USD) text.

Indexer (regression only)

  • Existing GET /api/v1/pairs/{addr}/stats still returns raw volume_base / volume_quote and human volume_usd. No new scan on the hot path.
  • No change required unless types/docs drift.

Manual / production

  • https://dex.cl8y.com/charts UST1/cUSTC 24h Stats: Vol (USD) ≈ curl volume_usd; token vols (if shown) ≈ raw ÷ 10^6.
  • Same pair UST1/USTR: no T on the strip.
  • Overview strip (#548) unchanged; tape Amount in/out still #557.

Test plan — attack, hack, and abuse

Vector Expected
Decimal lie — apply UST1 6-dec to USTR 18-dec volume_quote Decimals from that pair’s asset_0 / asset_1 rows only. Wrong-leg scale must fail the test.
Symbol collision — two CW20s both UST1 Decimals from pair legs / asset id, not label={Vol (${symbol})}.
USD × decimals again — UI divides already-human volume_usd by 1e6 Forbidden. volume_usd is human dollars.
Invert mix-up — use display-base decimals on volume_base after pill flip Invert does not reassign stats fields.
XSS in volume_usd / symbol Text render only; parse as decimal; no dangerouslySetInnerHTML.
Huge raw string formatTokenAmount BigInt path; USD helper length cap (#548 A4). No tab lock.
$0 lie — catalog USD NULL while trades exist —, never $0 and never raw T fallback.
Double notional — add candle volume_quote or fill rows into the box Display indexer stats.volume_usd only (L10).
Pair mismatch — stats from pair A, decimals from pair B Only render token vols when activePair.pair_address is the selected pair that fetched stats.
DoS via giant decimals i16 from pair JSON; out of range → —.

Verification criteria

make verify-issue-<iid>
# expected:
# - vitest ChartsPage pair 24h stats (USD primary; no 847.0M / T from raw)
# - grep ChartsPage.tsx: no formatNum(stats.volume_base) / formatNum(stats.volume_quote)
# - IndexerPairStats includes volume_usd
# - docs/frontend.md pair-stats contract (no longer “out of scope #540”)

Issue is done when a reviewer on dex.cl8y.com (or LocalTerra) opens /charts UST1/cUSTC and sees 24h volume in USD (and optional human token vols), matching GET /api/v1/pairs/{addr}/stats, not 847.0M UST1.

Out of scope

  • Tape Amount in / Amount out / Price (#557).
  • Charts overview 24h volume (#548).
  • Trade/Pool picker badges (#544).
  • Candle histogram units.
  • Changing on-chain events or swap settlement.
## Summary On **Charts & Analytics** pair detail (`https://dex.cl8y.com/charts` → select UST1/cUSTC), the **24h Stats** strip still compact-formats **raw** `volume_base` / `volume_quote` with `formatNum`. Retail sees **Vol (UST1) = 847.0M** and **Vol (cUSTC) = 157.5B** for ~**847 UST1** / ~**157K cUSTC** (~**$763** USD already on the JSON). This is the same `formatNum(raw)` class as tape Amount in/out ([#557](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/557)), picker volume ([#534](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/534)), and overview USD ([#548](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/548)). Pair-level **Vol (token)** was explicitly **out of scope** of #548 and assigned to closed [#540](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/540) / [#544](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/544) **AC4**, but [`ChartsPage.tsx`](frontend-dapp/src/pages/ChartsPage.tsx) never changed those two `StatBox`es (`git log -S 'formatNum(stats.volume_base)'` is still the original charts commit). **Observed (columbus-5, 2026-08-18):** `GET /api/v1/pairs/terra1ceprjsxp86ggftf5e38wwt34l83e5gq7penkdnv4wsatkwcs8v6qccw55f/stats` | Field | API | UI today (`formatNum`) | Honest retail | |-------|-----|------------------------|---------------| | `volume_base` | `847004054` | **847.0M** | 847 UST1 | | `volume_quote` | `157465643310` | **157.5B** | 157.5K cUSTC | | `volume_usd` | `763.35…` | **not rendered** (type omitted) | **~$763** | | `trade_count` | `41` | 41 | OK | UST1/USTR (6/18) is worse: raw quote volume compact-formats as **`T`**. Related: tape Amount in/out is **#557** (do not duplicate here). Overview 24h USD is **#548** (done). Picker/pool USD badges are **#544** (closed; this issue is the leftover Charts pair-stats strip only). ## Current codebase ### Frontend — two raw token vols, no USD [`frontend-dapp/src/pages/ChartsPage.tsx`](frontend-dapp/src/pages/ChartsPage.tsx) **24h Stats** (when a pair is selected): ```476:477:frontend-dapp/src/pages/ChartsPage.tsx <StatBox label={`Vol (${activePair.asset_0.symbol})`} value={formatNum(stats.volume_base)} /> <StatBox label={`Vol (${activePair.asset_1.symbol})`} value={formatNum(stats.volume_quote)} /> ``` [`formatNum`](frontend-dapp/src/utils/formatAmount.ts) is a **human compact** formatter (`K`/`M`/`B`/`T`). Indexer `volume_base` / `volume_quote` stay **raw chain integers** ([`swap_orientation.rs`](indexer/src/indexer/swap_orientation.rs): “Volume buckets stay in raw chain units”). USD OHLC boxes on the same grid already use `high_usd` / `low_usd` / … via `pairStatsUsdField` (#522). Volume USD is ignored. [`IndexerPairStats`](frontend-dapp/src/types/index.ts) **omits `volume_usd`** even though [`PairStatsResponse`](indexer/src/api/pairs.rs) returns it (`Option<String>`, human USD, P522-Q / hub catalog after #548/#556). Charts tests mock stats without `volume_usd` and never assert the Vol boxes ([`ChartsPage.test.tsx`](frontend-dapp/src/pages/ChartsPage.test.tsx)). Helpers already exist: - [`formatTokenAmount(raw, decimals)`](frontend-dapp/src/utils/formatAmount.ts) — human token compact (`"1000000"` + 6 → `"1.000"`) - [`formatIndexedVolumeUsd(usd, trades)`](frontend-dapp/src/utils/chartsOverviewStats.ts) — `$` + compact; `—` when unpriced and trades > 0; `$0` only when idle (#548 / #553) `activePair.asset_0.decimals` / `asset_1.decimals` are already on the pair JSON (do **not** match decimals by symbol). ### Indexer — already has the numbers `GET /api/v1/pairs/{addr}/stats` (`PairStatsResponse`): - `volume_base` / `volume_quote`: raw oriented sums (unchanged; integrators / CG) - `volume_usd`: human USD `SUM(swap_events.volume_usd)` for the 24h window - `trade_count`, USD OHLC, human `high`/`low` quote-per-base No indexer schema change is required for the default USD box. Token secondary vols can be scaled in the dApp from pair-leg decimals. ## Why the new implementation is needed 1. **Same page as the tape bug.** After #557 humanizes Amount in/out, the stats strip above the table will still claim **847 million UST1** of 24h volume next to a tape of ~45 UST1 fills. Retail will not trust either column. 2. **#540/#544 closed with the leftover still on production.** #544 **AC4** / **V544-1** required Charts pair stats **primary Vol (USD)** and optional human token remainder. The code path was never updated. 3. **USD is already indexed.** `volume_usd ≈ $763` is on the live stats JSON. The UI types dropped it. 4. **USTR `T`.** 18-dec quote raw through `formatNum` reprints the #534 / #544 impossible-trillions bug on the pair-detail strip. ## Constraints / guardrails 1. **USD is advisory, not settlement** (X5 / P522). Label **Vol (USD)**. Tooltip ≤ one sentence (`24h volume in USD`). Do not imply a peg. 2. **Reuse [`formatIndexedVolumeUsd`](frontend-dapp/src/utils/chartsOverviewStats.ts).** Do not invent a third USD formatter. Unpriced / invalid / negative → `—`. Trades > 0 and USD missing/`0` → `—`, not `$0`. Idle (`trade_count === 0`) may show `$0` or `—` — pick one and test it. 3. **Do not `formatNum` raw `volume_base` / `volume_quote`.** If token vols remain as secondary, use `formatTokenAmount(raw, asset_N.decimals)` from **that pair’s** legs (`activePair.pair_address` must match). Missing decimals → `—`, never assume 6. 4. **JSON stays raw** for `volume_base` / `volume_quote`. Do not humanize those fields in the indexer. `volume_usd` stays human USD. 5. **One notional (L10).** Display `stats.volume_usd` as-is. Do not add candle volumes, limit fills, or pool+book legs. 6. **#524 invert** does not swap or invert the 24h notional. Pair volume is pair-level. Do not use display-base decimals on the wrong raw field. 7. **Do not match decimals by symbol** (same class as #557 **A1** / #551 **P551-1**). Hostile ticker ≠ hub decimals. 8. **Copy (#489).** Keep short labels: **Vol (USD)**; optional **Vol (UST1)** / **Vol (cUSTC)** only if humanized. No “oriented raw quote-side integer” essays. 9. **Out of scope:** tape Amount in/out/Price (#557); overview strip (#548); picker/pool badges (#544); candle histogram units; CG/CMC `base_volume` / `target_volume`; settlement/fee math. 10. **Docs + `make verify-issue-<iid>`** in the same MR. Update [`docs/frontend.md`](docs/frontend.md) (pair-level Vol was “out of scope #540/#544”) and the Charts overview skill cross-link. ## Relevant files | File | Role | |------|------| | [`frontend-dapp/src/pages/ChartsPage.tsx`](frontend-dapp/src/pages/ChartsPage.tsx) | 24h Stats `StatBox`es | | [`frontend-dapp/src/pages/ChartsPage.test.tsx`](frontend-dapp/src/pages/ChartsPage.test.tsx) | RTL — currently no Vol assertions | | [`frontend-dapp/src/types/index.ts`](frontend-dapp/src/types/index.ts) | `IndexerPairStats` missing `volume_usd` | | [`frontend-dapp/src/services/indexer/client.ts`](frontend-dapp/src/services/indexer/client.ts) | `getPairStats` parse | | [`frontend-dapp/src/utils/chartsOverviewStats.ts`](frontend-dapp/src/utils/chartsOverviewStats.ts) | `formatIndexedVolumeUsd` | | [`frontend-dapp/src/utils/formatAmount.ts`](frontend-dapp/src/utils/formatAmount.ts) | `formatTokenAmount` / `formatNum` | | [`indexer/src/api/pairs.rs`](indexer/src/api/pairs.rs) | `PairStatsResponse` (already has `volume_usd`) | | [`docs/frontend.md`](docs/frontend.md) | Charts pair stats contract | | [`skills/AGENTS_FRONTEND_CHARTS_OVERVIEW.md`](skills/AGENTS_FRONTEND_CHARTS_OVERVIEW.md) | Cross-link leftover | ## Recommended direction 1. Add `volume_usd?: string | null` to `IndexerPairStats` and pass through `getPairStats`. 2. **Primary** 24h vol box: **Vol (USD)** = `formatIndexedVolumeUsd(stats.volume_usd, stats.trade_count)` with `data-testid="charts-pair-volume-usd"`. 3. **Optional secondary** human token boxes: `formatTokenAmount(stats.volume_base, activePair.asset_0.decimals)` and quote likewise. Labels keep `Vol ({symbol})`. Prefer demoting them (smaller / second row) so USD is the default read. If space is tight, USD only is acceptable (**V544-1**). 4. Grep gate: `ChartsPage.tsx` must not contain `formatNum(stats.volume_base)` or `formatNum(stats.volume_quote)`. 5. Tests: UST1/cUSTC 6/6 (`847004054` → not `847.0M`); UST1/USTR 6/18 (raw 18-dec quote → not `T`); missing `volume_usd` + `trade_count > 0` → `—`; HTML/`NaN`/`1e309` → `—`. 6. `make verify-issue-<iid>`: vitest ChartsPage + grep + docs mention. ## Acceptance criteria - [ ] **V1.** `/charts` pair 24h stats primary volume is **USD** (`$` + compact), matching `GET /api/v1/pairs/{addr}/stats` `volume_usd` (rollup lag OK). UST1/cUSTC production ~`$763` class, not `847.0M` / `157.5B`. - [ ] **V2.** UST1/USTR pair stats never compact-format raw 18-dec quote as `T`. - [ ] **V3.** If token Vol boxes remain, they are **human** (`formatTokenAmount` + that leg’s decimals) and labeled with the token. Missing decimals → `—`. - [ ] **V4.** Unpriced USD + `trade_count > 0` → `—`, not `$0` and not `formatNum(raw)` fallback. - [ ] **V5.** `#524` invert does not change the USD figure or swap base/quote raw onto the wrong decimals. - [ ] **V6.** Integrator JSON `volume_base` / `volume_quote` remain raw. CG/CMC unchanged. - [ ] **V7.** RTL + `make verify-issue-<iid>` + docs/skill cross-link. ## Test plan — functional paths ### Frontend RTL / unit - [ ] ChartsPage: mock UST1/cUSTC stats `volume_base=847004054`, `volume_quote=157465643310`, `volume_usd=763.35`, `trade_count=41` → Vol (USD) matches `/^\$/` and does **not** match `/847\.0M|157\.5B/`. - [ ] ChartsPage: USTR-scale `volume_quote=19300000000000000000` + 18-dec pair → no `/T$/` on the stats strip; USD path used when `volume_usd` present. - [ ] `volume_usd` null/`0`/`''` and `trade_count > 0` → `—`. - [ ] `trade_count === 0` and USD `0` → documented `$0` or `—`. - [ ] Invalid USD (`NaN`, `"><script>"`, 200-char string, negative) → `—`; no exception; no HTML inject. - [ ] Token secondary (if present): `formatTokenAmount` path; 6-dec `1000000` → `1` class; missing decimals → `—`. - [ ] Invert pill toggle does not change Vol (USD) text. ### Indexer (regression only) - [ ] Existing `GET /api/v1/pairs/{addr}/stats` still returns raw `volume_base` / `volume_quote` and human `volume_usd`. No new scan on the hot path. - [ ] No change required unless types/docs drift. ### Manual / production - [ ] `https://dex.cl8y.com/charts` UST1/cUSTC 24h Stats: Vol (USD) ≈ curl `volume_usd`; token vols (if shown) ≈ raw ÷ 10^6. - [ ] Same pair UST1/USTR: no `T` on the strip. - [ ] Overview strip (#548) unchanged; tape Amount in/out still #557. ## Test plan — attack, hack, and abuse | Vector | Expected | |--------|----------| | **Decimal lie** — apply UST1 6-dec to USTR 18-dec `volume_quote` | Decimals from **that pair’s** `asset_0` / `asset_1` rows only. Wrong-leg scale must fail the test. | | **Symbol collision** — two CW20s both `UST1` | Decimals from pair legs / asset id, not `label={`Vol (${symbol})`}`. | | **USD × decimals again** — UI divides already-human `volume_usd` by 1e6 | Forbidden. `volume_usd` is human dollars. | | **Invert mix-up** — use display-base decimals on `volume_base` after pill flip | Invert does not reassign stats fields. | | **XSS in `volume_usd` / symbol** | Text render only; parse as decimal; no `dangerouslySetInnerHTML`. | | **Huge raw string** | `formatTokenAmount` BigInt path; USD helper length cap (#548 A4). No tab lock. | | **`$0` lie** — catalog USD NULL while trades exist | `—`, never `$0` and never raw `T` fallback. | | **Double notional** — add candle `volume_quote` or fill rows into the box | Display indexer `stats.volume_usd` only (L10). | | **Pair mismatch** — stats from pair A, decimals from pair B | Only render token vols when `activePair.pair_address` is the selected pair that fetched stats. | | **DoS via giant decimals** | i16 from pair JSON; out of range → `—`. | ## Verification criteria ```bash make verify-issue-<iid> # expected: # - vitest ChartsPage pair 24h stats (USD primary; no 847.0M / T from raw) # - grep ChartsPage.tsx: no formatNum(stats.volume_base) / formatNum(stats.volume_quote) # - IndexerPairStats includes volume_usd # - docs/frontend.md pair-stats contract (no longer “out of scope #540”) ``` Issue is **done** when a reviewer on dex.cl8y.com (or LocalTerra) opens `/charts` UST1/cUSTC and sees 24h volume in **USD** (and optional human token vols), matching `GET /api/v1/pairs/{addr}/stats`, **not** `847.0M` UST1. ## Out of scope - Tape Amount in / Amount out / Price ([#557](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/557)). - Charts overview 24h volume ([#548](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/548)). - Trade/Pool picker badges ([#544](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/544)). - Candle histogram units. - Changing on-chain events or swap settlement.
PlasticDigits commented 2026-08-18 12:13:07 +00:00 (Migrated from gitlab.com)

marked as related to #540

marked as related to #540
PlasticDigits commented 2026-08-18 12:13:08 +00:00 (Migrated from gitlab.com)

marked as related to #544

marked as related to #544
PlasticDigits commented 2026-08-18 12:13:09 +00:00 (Migrated from gitlab.com)

marked as related to #548

marked as related to #548
PlasticDigits commented 2026-08-18 12:13:10 +00:00 (Migrated from gitlab.com)

marked as related to #557

marked as related to #557
PlasticDigits commented 2026-08-19 01:02:56 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1089

mentioned in merge request !1089
PlasticDigits commented 2026-08-19 01:12:34 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1093

mentioned in merge request !1093
PlasticDigits commented 2026-08-19 02:12:07 +00:00 (Migrated from gitlab.com)

mentioned in commit 975e062004

mentioned in commit 975e0620049bcb7f66cd5ad09d970d5dc00efeef
PlasticDigits commented 2026-08-19 02:12:11 +00:00 (Migrated from gitlab.com)

mentioned in commit 17790e7db4

mentioned in commit 17790e7db4c5ebac9b339f572b4b1fcce71ce301
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-08-19 02:12:11 +00:00
PlasticDigits commented 2026-08-19 02:16:48 +00:00 (Migrated from gitlab.com)

mentioned in issue #564

mentioned in issue #564
PlasticDigits commented 2026-08-19 02:16:49 +00:00 (Migrated from gitlab.com)

Post-merge note (!1089 on main, stacked on !1088 / #564). V1–V7 Vol (USD) primary + human token vols are on main. TWAP/histogram from #564 kept. Combined UI: row 1 Vol USD / Trades / Change / USD OHLC; row 2 token vols; TWAP section retained.

Remaining:

  • Manual: dex.cl8y.com/charts UST1/cUSTC Vol (USD) ≈ curl volume_usd; UST1/USTR strip has no T; overview (#548) unchanged.
  • CI was not waited. Run make verify-issue-565 and make verify-issue-564.
**Post-merge note (!1089 on main, stacked on !1088 / #564).** V1–V7 Vol (USD) primary + human token vols are on `main`. TWAP/histogram from #564 kept. Combined UI: row 1 Vol USD / Trades / Change / USD OHLC; row 2 token vols; TWAP section retained. Remaining: - Manual: `dex.cl8y.com/charts` UST1/cUSTC Vol (USD) ≈ curl `volume_usd`; UST1/USTR strip has no `T`; overview (#548) unchanged. - CI was not waited. Run `make verify-issue-565` and `make verify-issue-564`.
PlasticDigits commented 2026-08-19 02:28:46 +00:00 (Migrated from gitlab.com)

mentioned in issue #573

mentioned in issue #573
PlasticDigits commented 2026-08-19 02:29:00 +00:00 (Migrated from gitlab.com)

marked as related to #573

marked as related to #573
PlasticDigits commented 2026-08-19 11:52:57 +00:00 (Migrated from gitlab.com)

mentioned in issue #576

mentioned in issue #576
PlasticDigits commented 2026-08-26 04:15:27 +00:00 (Migrated from gitlab.com)

mentioned in issue #664

mentioned in issue #664
PlasticDigits commented 2026-08-26 04:17:22 +00:00 (Migrated from gitlab.com)

mentioned in issue #666

mentioned in issue #666
PlasticDigits commented 2026-08-26 04:17:23 +00:00 (Migrated from gitlab.com)

marked as related to #666

marked as related to #666
PlasticDigits commented 2026-08-27 00:20:53 +00:00 (Migrated from gitlab.com)

mentioned in issue #680

mentioned in issue #680
PlasticDigits commented 2026-08-28 05:22:08 +00:00 (Migrated from gitlab.com)

mentioned in issue #692

mentioned in issue #692
PlasticDigits commented 2026-08-28 05:22:11 +00:00 (Migrated from gitlab.com)

marked as related to #692

marked as related to #692
Sign in to join this conversation.
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#565
No description provided.