feat(protocol): CMM-held v2 LP columns for 30d fee bps and volume rollover #1317

Closed
opened 2026-09-22 05:15:07 +00:00 by PlasticDigits · 3 comments

Summary

Add columns on /protocol Top pairs (30d) that measure trailing-30-day volume and trading fees against v2 LP held by the CMM custodian, not against full-pool TVL.

The denominator is a 30-day LP-seconds accumulator (time-weighted CMM-held v2 LP in USD). Two derived figures:

  • 30d fees as bps of that CMM-adjusted v2 LP
  • Volume rollover as a multiple (0.00×) of that same CMM v2 LP

#1263 already shipped pair, 30d volume, full-pool v2 LP, and Vol/LP. This issue does not reopen it. #1207 stays a farming/cash-flow research memo; these columns are a census, not an APR, farm, or fee-split.

Current codebase

GET /api/v1/protocol/top-pairs ranks five factory pairs by pair_volume_30d joined to pair_liquidity_usd (indexer/src/api/protocol_top_pairs.rs, indexer/src/db/queries/protocol_top_pairs.rs). The handler never scans swap_events. Ratio is volume_usd_30d / current liquidity_usd. Missing, non-positive, or overflow TVL becomes JSON null (never Infinity).

The table (frontend-dapp/src/components/protocol/ProtocolTopPairs.tsx) shows 30d vol, v2 LP, and Vol/LP. Copy in frontend-dapp/src/utils/trailingWindowCopy.ts states v2 LP is current pool USD, not a 30-day average, and Vol/LP is trailing volume divided by that spot TVL. formatVolumePerTvl renders a finite positive ratio as N×.

pair_volume_30d is rebuilt off the request path from priced swap_events (refresh_pair_volumes_30d). Pair trading fees live on protocol_fee_events (with pair_id) but are not stamped per pair for this table. Protocol fee totals on the page are venue-wide and explicitly not a CMM balance (ProtocolFeeStats.tsx).

liquidity_events records provide/withdraw with provider and lp_amount. There is no CW20 balance index and no time-weighted CMM LP rollup. Full-pool pair_liquidity_usd cannot be substituted for LP the CMM custodian holds.

Why this work is needed

Vol/LP divides venue volume by everyone’s current pool USD. Liquidity deployment needs the same 30-day window against CMM-held v2 LP, plus fee yield on that capital:

  • fees accrued over 30 days, as basis points of CMM-adjusted v2 LP
  • volume turnover over 30 days, as a × multiple of that LP

A spot CMM balance repeats the mismatch the v2 LP tooltip already calls out (current USD vs a 30-day flow). The denominator has to be accumulated over the same trailing window as volume and fees.

Constraints / guardrails

  • Same top-5 membership and sort as today: trailing 30d priced volume descending, gems excluded. New columns do not re-rank rows.
  • Existing columns stay: pair, 30d vol, full-pool v2 LP, Vol/LP. Do not redefine Vol/LP as the CMM ratio.
  • CMM-adjusted v2 LP means time-weighted USD of factory LP shares held by the configured CMM LP custodian (the treasury that already custodies protocol-owned LP). It is not full-pool TVL and not “pool minus CMM.”
  • Fee numerator is pair trading fees only (swap_amm, book_take, limit_place) over the trailing 30 days. Wrap, unwrap, UST1 mint, and UST1 redeem stay out of this bps figure.
  • GET /api/v1/protocol/top-pairs reads rollup stamps only. No swap_events, protocol_fee_events, or liquidity_events scan and no LCD balance fanout on the request path.
  • Null policy matches compute_volume_per_tvl: missing, ≤ 0, or overflow (≥ 10^20) denominator or ratio → JSON null → em dash. Never Infinity, never a percent for the volume multiple.
  • Fee bps = trading_fees_usd_30d / cmm_lp_usd_tw_30d * 10000. Volume rollover = volume_usd_30d / cmm_lp_usd_tw_30d, displayed with the existing × formatter.
  • Census only. No farm, APR, points, /pool incentive copy, FEE_CONFIG change, or LP-share of commission. #1207 and the no-incentive LP how-to stay as they are.
  • Custodian identity comes from existing config / documented CMM treasury, not a new hardcoded secret. Do not print hostnames, deploy targets, or credentials.
  • limit / window query rules stay: omitted or 5 / 30d only. Unknown from, to, sort, ticker still 400.

Relevant files

Area Path
Top-pairs handler and ratio indexer/src/api/protocol_top_pairs.rs
Ranking SQL indexer/src/db/queries/protocol_top_pairs.rs
30d volume stamp indexer/src/db/queries/volume.rs (refresh_pair_volumes_30d)
Fee events (off-request rollup source) indexer/src/db/queries/protocol_fees.rs, indexer/src/indexer/protocol_fees.rs
LP provide/withdraw indexer/src/db/queries/liquidity.rs, indexer/src/indexer/parser.rs
Response types frontend-dapp/src/types/index.ts (ProtocolTopPairItem)
Table frontend-dapp/src/components/protocol/ProtocolTopPairs.tsx
Copy frontend-dapp/src/utils/trailingWindowCopy.ts
× format frontend-dapp/src/utils/formatProtocolStats.ts
Page tests frontend-dapp/src/pages/ProtocolPage.test.tsx
Client frontend-dapp/src/services/indexer/client.ts
  1. Off-request stamps (same refresh family as pair_volume_30d):
    • pair_trading_fees_30d: sum of priced pair trading fees in the trailing 30 days. Unpriced → NULL (do not coerce to 0). Idle → 0.
    • pair_cmm_lp_usd_30d: time-weighted average USD of LP held by the CMM custodian. Build LP-share seconds from liquidity_events for that provider, value shares with the same pool-USD / total-supply ratio already used for pair_liquidity_usd, and divide by the window length.
  2. Transfer gap. liquidity_events misses bare CW20 transfers of the LP token. If those transfers can change CMM custody by a material amount, ingest them into the same accumulator (or seed the integral from a balance observation off the GET path). Document the choice in the handler comment. Do not silently treat spot full-pool TVL as CMM LP.
  3. API fields on each top-pair item (omit or null when unknown): cmm_lp_usd_30d, trading_fees_usd_30d, fees_bps_per_cmm_lp, volume_per_cmm_lp. Keep liquidity_usd and volume_per_tvl unchanged.
  4. UI. Three columns after Vol/LP: CMM v2 LP, 30d fee bps, Vol/CMM LP (0.00×). Tooltips state time-weighted 30d CMM LP, trading-fee bps (not wrap/window), and volume divided by that LP (not a percent, not full-pool Vol/LP). Horizontal scroll already wraps the table; do not drop columns on narrow viewports by overlapping text.
  5. Cache. Extend the existing 60s response cache so new fields cannot serve a stale pre-change body after refresh. Tests reset the cache the same way reset_protocol_top_pairs_cache does today.

Acceptance criteria

  • AC1. Top-5 set, order, gem filter, and full-pool Vol/LP match current behavior for the same stamps.
  • AC2. CMM v2 LP is the trailing-30d time-weighted USD of LP held by the CMM custodian, produced by an accumulator updated off the request path.
  • AC3. Fee bps uses only pair trading fees. Wrap and UST1 window fees do not enter the numerator.
  • AC4. Volume rollover is volume_usd_30d / cmm_lp_usd_tw_30d, rendered as N×. Fee figure is that fee USD over the same denominator, times 10_000, labeled bps.
  • AC5. Non-positive, missing, or overflow CMM LP yields null ratios and em dashes. Existing cells still render.
  • AC6. GET /api/v1/protocol/top-pairs does not query raw event tables or the chain.
  • AC7. No farm, APR, or fee-destination change.

Given / When / Then

  • Given a top-5 pair whose CMM custodian’s time-weighted v2 LP over 30 days is 500 USD, trailing volume is 1,234.5 USD, and trailing trading fees are 10 USD, when /protocol loads top pairs, then the row shows CMM v2 LP 500, fee bps 200, and volume rollover 2.469×, and the existing Vol/LP cell still uses full-pool TVL.
  • Given that pair’s only 30d protocol fees are wrap or UST1 window, when fee bps is computed, then the trading-fee numerator is 0 or null and fee bps is an em dash.
  • Given the CMM custodian held no LP on that pair (weight ≤ 0), when the row renders, then CMM v2 LP and both ratios are em dashes and 30d vol / v2 LP / Vol/LP are unchanged.
  • Given cmm_lp_usd or either ratio would overflow 10^20, when the API serializes the item, then the overflowing field is JSON null, not Infinity.
  • Given the indexer has not migrated the new stamps, when the dApp receives items without the new keys, then the three new cells are em dashes and the panel still lists the original four columns.

Test plan

ID Path How to test
P1 Ratio math Rust unit tests: 10 / 500 * 10000 = 200 bps; 1234.5 / 500 = 2.469 volume multiple; zero, negative, missing, and ≥ 10^20 → None
P2 Fee mix Fixture with swap_amm + wrap on one pair; stamp includes only swap_amm (and book_take / limit_place when present)
P3 Accumulator Two CMM provide/withdraw points inside 30d; time-weighted USD matches hand integral; a non-CMM provider does not move the integral
P4 GET boundary Handler test: SQL is the stamp join; response cache returns the new fields; disallowed query keys still 400
P5 UI ProtocolPage test: three new headers and cells; nulls are em dashes; Vol/LP snapshot unchanged; no horizontal text collision at the existing phone width used by protocol table tests
P6 Idle pair No CMM LP events and no trading fees → new cells em dash; pair can still appear from pair_volume_30d
P7 Copy Tooltips distinguish CMM time-weighted LP from current full-pool v2 LP and exclude wrap/window from fee bps

Verification criteria

  • Indexer tests for the bps helper, volume-multiple helper, fee-source filter, and LP-seconds integral pass.
  • Frontend tests for the three columns, null dashes, and unchanged Vol/LP pass.
  • OpenAPI / schema for GET /api/v1/protocol/top-pairs lists the four new fields.
  • A reviewer can recompute one fixture row from the stamp inputs without reading raw swaps on the request path.

Out of scope

  • Re-ranking top pairs by fee bps or by CMM volume rollover.
  • Changing full-pool Vol/LP, venue-wide fee StatBoxes, or DeFiLlama adapters.
  • Farming, LP fee share, APR badges, or CMM LP custody changes (#1207, #558).
  • Per-address portfolio LP views.

First-pass model recommendation

Recommendation: grok-high

Rationale: The work adds a migration-backed LP-seconds accumulator and a per-pair 30d trading-fee stamp, then threads both through protocol_top_pairs SQL, the API schema, and ProtocolTopPairs plus format/copy tests. That is more than three production files, a new rollup (not a local display tweak), and an explicit transfer-vs-liquidity_events gap. Low-risk Composer first pass does not fit: the denominator is new indexed state, and a wrong CMM-LP definition would misstate fee bps and volume turnover used for liquidity deployment. Verify with the P1–P5 tests above, not a visual snapshot alone.

## Summary Add columns on `/protocol` **Top pairs (30d)** that measure trailing-30-day volume and trading fees against **v2 LP held by the CMM custodian**, not against full-pool TVL. The denominator is a **30-day LP-seconds accumulator** (time-weighted CMM-held v2 LP in USD). Two derived figures: - **30d fees as bps** of that CMM-adjusted v2 LP - **Volume rollover** as a multiple (`0.00×`) of that same CMM v2 LP [#1263](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1263) already shipped pair, 30d volume, full-pool v2 LP, and Vol/LP. This issue does not reopen it. [#1207](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1207) stays a farming/cash-flow research memo; these columns are a census, not an APR, farm, or fee-split. ## Current codebase `GET /api/v1/protocol/top-pairs` ranks five factory pairs by `pair_volume_30d` joined to `pair_liquidity_usd` ([`indexer/src/api/protocol_top_pairs.rs`](indexer/src/api/protocol_top_pairs.rs), [`indexer/src/db/queries/protocol_top_pairs.rs`](indexer/src/db/queries/protocol_top_pairs.rs)). The handler never scans `swap_events`. Ratio is `volume_usd_30d / current liquidity_usd`. Missing, non-positive, or overflow TVL becomes JSON `null` (never `Infinity`). The table ([`frontend-dapp/src/components/protocol/ProtocolTopPairs.tsx`](frontend-dapp/src/components/protocol/ProtocolTopPairs.tsx)) shows **30d vol**, **v2 LP**, and **Vol/LP**. Copy in [`frontend-dapp/src/utils/trailingWindowCopy.ts`](frontend-dapp/src/utils/trailingWindowCopy.ts) states v2 LP is **current pool USD, not a 30-day average**, and Vol/LP is trailing volume divided by that spot TVL. [`formatVolumePerTvl`](frontend-dapp/src/utils/formatProtocolStats.ts) renders a finite positive ratio as `N×`. `pair_volume_30d` is rebuilt off the request path from priced `swap_events` ([`refresh_pair_volumes_30d`](indexer/src/db/queries/volume.rs)). Pair trading fees live on `protocol_fee_events` (with `pair_id`) but are **not** stamped per pair for this table. Protocol fee totals on the page are venue-wide and explicitly not a CMM balance ([`ProtocolFeeStats.tsx`](frontend-dapp/src/components/protocol/ProtocolFeeStats.tsx)). `liquidity_events` records provide/withdraw with `provider` and `lp_amount`. There is no CW20 balance index and no time-weighted CMM LP rollup. Full-pool `pair_liquidity_usd` cannot be substituted for LP the CMM custodian holds. ## Why this work is needed Vol/LP divides venue volume by **everyone’s** current pool USD. Liquidity deployment needs the same 30-day window against **CMM-held** v2 LP, plus fee yield on that capital: - fees accrued over 30 days, as basis points of CMM-adjusted v2 LP - volume turnover over 30 days, as a `×` multiple of that LP A spot CMM balance repeats the mismatch the v2 LP tooltip already calls out (current USD vs a 30-day flow). The denominator has to be accumulated over the same trailing window as volume and fees. ## Constraints / guardrails - Same top-5 membership and sort as today: trailing 30d priced volume descending, gems excluded. New columns do not re-rank rows. - Existing columns stay: pair, 30d vol, full-pool v2 LP, Vol/LP. Do not redefine Vol/LP as the CMM ratio. - **CMM-adjusted v2 LP** means time-weighted USD of factory LP shares held by the configured CMM LP custodian (the treasury that already custodies protocol-owned LP). It is not full-pool TVL and not “pool minus CMM.” - Fee numerator is **pair trading fees only** (`swap_amm`, `book_take`, `limit_place`) over the trailing 30 days. Wrap, unwrap, UST1 mint, and UST1 redeem stay out of this bps figure. - `GET /api/v1/protocol/top-pairs` reads rollup stamps only. No `swap_events`, `protocol_fee_events`, or `liquidity_events` scan and no LCD balance fanout on the request path. - Null policy matches `compute_volume_per_tvl`: missing, `≤ 0`, or overflow (`≥ 10^20`) denominator or ratio → JSON `null` → em dash. Never `Infinity`, never a percent for the volume multiple. - Fee bps = `trading_fees_usd_30d / cmm_lp_usd_tw_30d * 10000`. Volume rollover = `volume_usd_30d / cmm_lp_usd_tw_30d`, displayed with the existing `×` formatter. - Census only. No farm, APR, points, `/pool` incentive copy, `FEE_CONFIG` change, or LP-share of commission. [#1207](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1207) and the no-incentive LP how-to stay as they are. - Custodian identity comes from existing config / documented CMM treasury, not a new hardcoded secret. Do not print hostnames, deploy targets, or credentials. - `limit` / `window` query rules stay: omitted or `5` / `30d` only. Unknown `from`, `to`, `sort`, `ticker` still **400**. ## Relevant files | Area | Path | |------|------| | Top-pairs handler and ratio | `indexer/src/api/protocol_top_pairs.rs` | | Ranking SQL | `indexer/src/db/queries/protocol_top_pairs.rs` | | 30d volume stamp | `indexer/src/db/queries/volume.rs` (`refresh_pair_volumes_30d`) | | Fee events (off-request rollup source) | `indexer/src/db/queries/protocol_fees.rs`, `indexer/src/indexer/protocol_fees.rs` | | LP provide/withdraw | `indexer/src/db/queries/liquidity.rs`, `indexer/src/indexer/parser.rs` | | Response types | `frontend-dapp/src/types/index.ts` (`ProtocolTopPairItem`) | | Table | `frontend-dapp/src/components/protocol/ProtocolTopPairs.tsx` | | Copy | `frontend-dapp/src/utils/trailingWindowCopy.ts` | | `×` format | `frontend-dapp/src/utils/formatProtocolStats.ts` | | Page tests | `frontend-dapp/src/pages/ProtocolPage.test.tsx` | | Client | `frontend-dapp/src/services/indexer/client.ts` | ## Recommended direction 1. **Off-request stamps** (same refresh family as `pair_volume_30d`): - `pair_trading_fees_30d`: sum of priced pair trading fees in the trailing 30 days. Unpriced → `NULL` (do not coerce to 0). Idle → `0`. - `pair_cmm_lp_usd_30d`: time-weighted average USD of LP held by the CMM custodian. Build LP-share seconds from `liquidity_events` for that provider, value shares with the same pool-USD / total-supply ratio already used for `pair_liquidity_usd`, and divide by the window length. 2. **Transfer gap.** `liquidity_events` misses bare CW20 transfers of the LP token. If those transfers can change CMM custody by a material amount, ingest them into the same accumulator (or seed the integral from a balance observation **off** the GET path). Document the choice in the handler comment. Do not silently treat spot full-pool TVL as CMM LP. 3. **API fields** on each top-pair item (omit or `null` when unknown): `cmm_lp_usd_30d`, `trading_fees_usd_30d`, `fees_bps_per_cmm_lp`, `volume_per_cmm_lp`. Keep `liquidity_usd` and `volume_per_tvl` unchanged. 4. **UI.** Three columns after Vol/LP: **CMM v2 LP**, **30d fee bps**, **Vol/CMM LP** (`0.00×`). Tooltips state time-weighted 30d CMM LP, trading-fee bps (not wrap/window), and volume divided by that LP (not a percent, not full-pool Vol/LP). Horizontal scroll already wraps the table; do not drop columns on narrow viewports by overlapping text. 5. **Cache.** Extend the existing 60s response cache so new fields cannot serve a stale pre-change body after refresh. Tests reset the cache the same way `reset_protocol_top_pairs_cache` does today. ## Acceptance criteria - [ ] **AC1.** Top-5 set, order, gem filter, and full-pool Vol/LP match current behavior for the same stamps. - [ ] **AC2.** CMM v2 LP is the trailing-30d time-weighted USD of LP held by the CMM custodian, produced by an accumulator updated off the request path. - [ ] **AC3.** Fee bps uses only pair trading fees. Wrap and UST1 window fees do not enter the numerator. - [ ] **AC4.** Volume rollover is `volume_usd_30d / cmm_lp_usd_tw_30d`, rendered as `N×`. Fee figure is that fee USD over the same denominator, times 10_000, labeled bps. - [ ] **AC5.** Non-positive, missing, or overflow CMM LP yields null ratios and em dashes. Existing cells still render. - [ ] **AC6.** `GET /api/v1/protocol/top-pairs` does not query raw event tables or the chain. - [ ] **AC7.** No farm, APR, or fee-destination change. ### Given / When / Then - **Given** a top-5 pair whose CMM custodian’s time-weighted v2 LP over 30 days is 500 USD, trailing volume is 1,234.5 USD, and trailing trading fees are 10 USD, **when** `/protocol` loads top pairs, **then** the row shows CMM v2 LP `500`, fee bps `200`, and volume rollover `2.469×`, and the existing Vol/LP cell still uses full-pool TVL. - **Given** that pair’s only 30d protocol fees are wrap or UST1 window, **when** fee bps is computed, **then** the trading-fee numerator is 0 or null and fee bps is an em dash. - **Given** the CMM custodian held no LP on that pair (weight `≤ 0`), **when** the row renders, **then** CMM v2 LP and both ratios are em dashes and 30d vol / v2 LP / Vol/LP are unchanged. - **Given** `cmm_lp_usd` or either ratio would overflow `10^20`, **when** the API serializes the item, **then** the overflowing field is JSON `null`, not `Infinity`. - **Given** the indexer has not migrated the new stamps, **when** the dApp receives items without the new keys, **then** the three new cells are em dashes and the panel still lists the original four columns. ## Test plan | ID | Path | How to test | |----|------|-------------| | P1 | Ratio math | Rust unit tests: `10 / 500 * 10000 = 200` bps; `1234.5 / 500 = 2.469` volume multiple; zero, negative, missing, and `≥ 10^20` → `None` | | P2 | Fee mix | Fixture with swap_amm + wrap on one pair; stamp includes only swap_amm (and book_take / limit_place when present) | | P3 | Accumulator | Two CMM provide/withdraw points inside 30d; time-weighted USD matches hand integral; a non-CMM provider does not move the integral | | P4 | GET boundary | Handler test: SQL is the stamp join; response cache returns the new fields; disallowed query keys still 400 | | P5 | UI | `ProtocolPage` test: three new headers and cells; nulls are em dashes; Vol/LP snapshot unchanged; no horizontal text collision at the existing phone width used by protocol table tests | | P6 | Idle pair | No CMM LP events and no trading fees → new cells em dash; pair can still appear from `pair_volume_30d` | | P7 | Copy | Tooltips distinguish CMM time-weighted LP from current full-pool v2 LP and exclude wrap/window from fee bps | ## Verification criteria - Indexer tests for the bps helper, volume-multiple helper, fee-source filter, and LP-seconds integral pass. - Frontend tests for the three columns, null dashes, and unchanged Vol/LP pass. - OpenAPI / schema for `GET /api/v1/protocol/top-pairs` lists the four new fields. - A reviewer can recompute one fixture row from the stamp inputs without reading raw swaps on the request path. ## Out of scope - Re-ranking top pairs by fee bps or by CMM volume rollover. - Changing full-pool Vol/LP, venue-wide fee StatBoxes, or DeFiLlama adapters. - Farming, LP fee share, APR badges, or CMM LP custody changes ([#1207](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1207), [#558](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/558)). - Per-address portfolio LP views. ## First-pass model recommendation Recommendation: grok-high Rationale: The work adds a migration-backed LP-seconds accumulator and a per-pair 30d trading-fee stamp, then threads both through `protocol_top_pairs` SQL, the API schema, and `ProtocolTopPairs` plus format/copy tests. That is more than three production files, a new rollup (not a local display tweak), and an explicit transfer-vs-`liquidity_events` gap. Low-risk Composer first pass does not fit: the denominator is new indexed state, and a wrong CMM-LP definition would misstate fee bps and volume turnover used for liquidity deployment. Verify with the P1–P5 tests above, not a visual snapshot alone.
Author
Owner

cl8y-agent-control: queued design_author job 6150ecb8-83b9-4000-ba90-0dc0bc51eacc (not executed; no Hetzner VM).

cl8y-agent-control: queued `design_author` job `6150ecb8-83b9-4000-ba90-0dc0bc51eacc` (not executed; no Hetzner VM).
Author
Owner

cl8y-agent-control: needs_human inbox card POST failed. Job stays parked.

cl8y-agent-control: needs_human inbox card POST failed. Job stays parked.
Author
Owner

Audit at origin/main (54c4868e): #1317 remains open. The current API/UI still expose only the #1263 fields; no #1317 verifier or newer issue tracks these acceptance criteria.

Remaining:

  • Add an off-request trailing-30d time-weighted USD accumulator for CMM-held LP shares, including a documented solution for bare LP-token transfers.
  • Add per-pair priced 30d trading-fee stamps and additive API/OpenAPI fields (cmm_lp_usd_30d, trading_fees_usd_30d, fees_bps_per_cmm_lp, volume_per_cmm_lp). Count swap_amm / book_take / limit_place only; exclude wrap/unwrap and UST1 window fees. Keep #1263 ranking, full-pool Vol/LP, and rollup-only GET behavior unchanged.
  • Add the three UI columns, scoped tooltips, null/legacy fallback, and the issue’s indexer/API/cache/OpenAPI/mobile regression coverage. No APR/farm or fee-destination changes.

Related: #1263 is the shipped baseline; #1269 covers complete multihop fee ingestion; #558 tracks CMM LP custody operations; #1207 remains separate yield research. VERIFY_ISSUE_1263_SKIP_RELATED=1 make verify-issue-1263 passed (8 indexer cases, 80 frontend tests); it does not verify #1317.

Audit at `origin/main` (`54c4868e`): #1317 remains open. The current API/UI still expose only the #1263 fields; no #1317 verifier or newer issue tracks these acceptance criteria. Remaining: - Add an off-request trailing-30d time-weighted USD accumulator for CMM-held LP shares, including a documented solution for bare LP-token transfers. - Add per-pair priced 30d trading-fee stamps and additive API/OpenAPI fields (`cmm_lp_usd_30d`, `trading_fees_usd_30d`, `fees_bps_per_cmm_lp`, `volume_per_cmm_lp`). Count `swap_amm` / `book_take` / `limit_place` only; exclude wrap/unwrap and UST1 window fees. Keep #1263 ranking, full-pool Vol/LP, and rollup-only GET behavior unchanged. - Add the three UI columns, scoped tooltips, null/legacy fallback, and the issue’s indexer/API/cache/OpenAPI/mobile regression coverage. No APR/farm or fee-destination changes. Related: #1263 is the shipped baseline; #1269 covers complete multihop fee ingestion; #558 tracks CMM LP custody operations; #1207 remains separate yield research. `VERIFY_ISSUE_1263_SKIP_RELATED=1 make verify-issue-1263` passed (8 indexer cases, 80 frontend tests); it does not verify #1317.
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#1317
No description provided.