feat(protocol): CMM-held v2 LP columns for 30d fee bps and volume rollover #1317
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#1317
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Add columns on
/protocolTop 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:
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-pairsranks five factory pairs bypair_volume_30djoined topair_liquidity_usd(indexer/src/api/protocol_top_pairs.rs,indexer/src/db/queries/protocol_top_pairs.rs). The handler never scansswap_events. Ratio isvolume_usd_30d / current liquidity_usd. Missing, non-positive, or overflow TVL becomes JSONnull(neverInfinity).The table (
frontend-dapp/src/components/protocol/ProtocolTopPairs.tsx) shows 30d vol, v2 LP, and Vol/LP. Copy infrontend-dapp/src/utils/trailingWindowCopy.tsstates v2 LP is current pool USD, not a 30-day average, and Vol/LP is trailing volume divided by that spot TVL.formatVolumePerTvlrenders a finite positive ratio asN×.pair_volume_30dis rebuilt off the request path from pricedswap_events(refresh_pair_volumes_30d). Pair trading fees live onprotocol_fee_events(withpair_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_eventsrecords provide/withdraw withproviderandlp_amount. There is no CW20 balance index and no time-weighted CMM LP rollup. Full-poolpair_liquidity_usdcannot 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:
×multiple of that LPA 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
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-pairsreads rollup stamps only. Noswap_events,protocol_fee_events, orliquidity_eventsscan and no LCD balance fanout on the request path.compute_volume_per_tvl: missing,≤ 0, or overflow (≥ 10^20) denominator or ratio → JSONnull→ em dash. NeverInfinity, never a percent for the volume multiple.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./poolincentive copy,FEE_CONFIGchange, or LP-share of commission. #1207 and the no-incentive LP how-to stay as they are.limit/windowquery rules stay: omitted or5/30donly. Unknownfrom,to,sort,tickerstill 400.Relevant files
indexer/src/api/protocol_top_pairs.rsindexer/src/db/queries/protocol_top_pairs.rsindexer/src/db/queries/volume.rs(refresh_pair_volumes_30d)indexer/src/db/queries/protocol_fees.rs,indexer/src/indexer/protocol_fees.rsindexer/src/db/queries/liquidity.rs,indexer/src/indexer/parser.rsfrontend-dapp/src/types/index.ts(ProtocolTopPairItem)frontend-dapp/src/components/protocol/ProtocolTopPairs.tsxfrontend-dapp/src/utils/trailingWindowCopy.ts×formatfrontend-dapp/src/utils/formatProtocolStats.tsfrontend-dapp/src/pages/ProtocolPage.test.tsxfrontend-dapp/src/services/indexer/client.tsRecommended direction
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 fromliquidity_eventsfor that provider, value shares with the same pool-USD / total-supply ratio already used forpair_liquidity_usd, and divide by the window length.liquidity_eventsmisses 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.nullwhen unknown):cmm_lp_usd_30d,trading_fees_usd_30d,fees_bps_per_cmm_lp,volume_per_cmm_lp. Keepliquidity_usdandvolume_per_tvlunchanged.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.reset_protocol_top_pairs_cachedoes today.Acceptance criteria
volume_usd_30d / cmm_lp_usd_tw_30d, rendered asN×. Fee figure is that fee USD over the same denominator, times 10_000, labeled bps.GET /api/v1/protocol/top-pairsdoes not query raw event tables or the chain.Given / When / Then
/protocolloads top pairs, then the row shows CMM v2 LP500, fee bps200, and volume rollover2.469×, and the existing Vol/LP cell still uses full-pool TVL.≤ 0), when the row renders, then CMM v2 LP and both ratios are em dashes and 30d vol / v2 LP / Vol/LP are unchanged.cmm_lp_usdor either ratio would overflow10^20, when the API serializes the item, then the overflowing field is JSONnull, notInfinity.Test plan
10 / 500 * 10000 = 200bps;1234.5 / 500 = 2.469volume multiple; zero, negative, missing, and≥ 10^20→NoneProtocolPagetest: 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 testspair_volume_30dVerification criteria
GET /api/v1/protocol/top-pairslists the four new fields.Out of scope
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_pairsSQL, the API schema, andProtocolTopPairsplus format/copy tests. That is more than three production files, a new rollup (not a local display tweak), and an explicit transfer-vs-liquidity_eventsgap. 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.cl8y-agent-control: queued
design_authorjob6150ecb8-83b9-4000-ba90-0dc0bc51eacc(not executed; no Hetzner VM).cl8y-agent-control: needs_human inbox card POST failed. Job stays parked.
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:
cmm_lp_usd_30d,trading_fees_usd_30d,fees_bps_per_cmm_lp,volume_per_cmm_lp). Countswap_amm/book_take/limit_placeonly; exclude wrap/unwrap and UST1 window fees. Keep #1263 ranking, full-pool Vol/LP, and rollup-only GET behavior unchanged.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-1263passed (8 indexer cases, 80 frontend tests); it does not verify #1317.