feat: /trade identity row — v2 LP USD (humanized AMM TVL) #664
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#664
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
Show humanized factory v2 AMM LP USD on
/trade/{pair}next to the existing token-identity chips (leg names + pair address). Bundle the same identity chrome on/charts/{pair}(sharedPairTokenLinks) plusGET /api/v1/pairs/{addr}returning the per-pair field. Do not split “Trade chip” vs “Charts chip” vs “single-pair JSON.”This is pair TVL (both reserve legs, P522-Q / hub catalog — same number as #569
protocol_pair_tvland the #655 list stamp). It is not the connected wallet’s LP-token mark-to-market, not book escrow, not V3 Grid / #619 vaults, not 24h volume, not CoinGeckoliquidity_in_usd(mislabeled volume).Depends on / shares rollup with #655 (
pair_liquidity_usd+ listliquidity_usd). This ticket owns single-pair GET + Trade / Charts identity. Do not re-implement the/poolsortable column here.Related: #541 (
PairTokenLinks), #655 (/poolcolumn + list rollup), #569 (protocol TVL math), #556 (hub USD), #524 (invert), #489 (no lectures), #653 (no nested chrome), #565 (Charts 24h Vol USD is flow, not stock), #430 (href safety).Current codebase
/trade/{pair}already identifies the market (symbols + pair bech32). It does not show how large the v2 pool is. Protocol can price a factory pair; the single-pair API does not return that number. Charts pair 24h Stats show volume USD, which is easy to confuse with pool size./tradeidentityTradePage.tsxmountsPairTokenLinksundertrade-pair-select-panel, outsidePairSearchSelect. Chips: factoryasset_0/asset_1viaTokenIdentity+ pairAddressRow(token-identity-pair). Hidden when workspace is off (#176 / #175 / unknown pair — T541-6). No LP / TVL / USD.GET /api/v1/pairs/{addr}(queryKey: ['indexer-pair-trade', pairAddr],staleTime: 60_000) viagetPair. Used for tape USD / freeze / unknown-pair — not for identity LP. Identity assets still come from factoryPairInfo./chartsidentityChartsPage.tsxuses the samePairTokenLinksunder the pairMenuSelect. Pair 24h Stats (charts-pair-24h-stats) show Last 24h Vol (USD) fromGET …/statsvolume_usd(P565-1) — flow, not pool stock.PairTokenLinksinvertedreorders chips; payloads stay factory assets (T541-5). No USD prop. Also used on/pooltable rows and Manage expand — those rows must not grow a second LP chip (column is #655).GET /api/v1/pairs/{addr}(indexer/src/api/pairs.rsget_pair) returnsPairResponse: address, assets,lp_token,fee_bps,is_active,code_id_frozen,volume_quote_24h: None. Noliquidity_usd. Unknown addr → 404.GET /api/v1/pairshasvolume_quote_24honly. Per-pair USD stamp +sort=liquidity_usdis #655 — do not fork a second field name.GET /api/v1/pairs/{addr}/statsis 24h OHLC + volume (volume_usdis swap notional). Do not overload this with TVL.protocol_tvl.rsprotocol_pair_tvl/pair_usable_for_protocol_tvl. Both legs priced →h0×usd0 + h1×usd1. One catalogued →2×that leg (CPAMM). Neither / stale / same-asset / overflow /reserve_*=0→ omit (not$0). Book escrow excluded. Writes globaltotal_liquidity_usdonly until #655 materializes per-pair.uusd→ USTC oracle; LUNC/cLUNC/uluna→ LUNC; UST1/USTR →hub_prices. Never$1UST1, never2.5×USTR, never vFDUSD/FDUSD (P569-4). Identity = contract/denom.pair_reservesviabook_snapshot.rs(~10s). Stale TTL same class as hub / protocol TVL.formatProtocolUsd: missing / non-finite →—, neverInfinity. Compact viaformatNum. Protocol Total liquidity already uses this.trade-pair-select-panelis alreadyshell-panel— no innerStatBox/card-glass. #541: explorer stays a sibling; do not wrap symbols in<a>.PairTokenLinks.test.tsx,TradePage.test.tsx#541describe,ChartsPage.test.tsx,e2e/token-identity-541.spec.ts,make verify-issue-541. Indexer:api_pairs.rs.docs/frontend.md§ Token identity (T541-1–T541-8),skills/AGENTS_FRONTEND_TOKEN_IDENTITY.md,docs/indexer-invariants.md(pair GET / protocol TVL).Why this is needed
/trade/{pair}is where size vs book vs slippage is decided. Identity shows which tokens; it does not show how much v2 LP backs the market. Charts 24h Vol (USD) answers flow, not stock — easy to misread as TVL.protocol_pair_tvlis the census primitive. #655 stamps it for the list. Trade already calls single-pair GET, which today returns metadata only (volume_quote_24hforcedNone). Without that field on{addr}, the UI will LCDgetPoolor invent USD from volume /$1UST1.PairTokenLinks(#541). Trade asked first; Charts is the same pair-detail identity row. Implementing Trade-only would leave Charts as a leftover (same class as the old #188 pair-chip leftover).liquidity_in_usd, LP supply × last print) will drift from Protocol and the/poolcolumn.Constraints / guardrails
liquidity_usd(human USD decimal string). Callprotocol_pair_tvl/ read the #655pair_liquidity_usdstamp. Never a second catalog. Never vFDUSD. Never$1UST1. Never2.5×USTR. Identity = contract/denom.GET /api/v1/pairs/{addr}must not joinpair_reserves× oracles × hub on the request path. Read the same materialized stamp as #655 (orNULLif that row is missing). If this ticket lands first, still create/read that stamp — do not compute TVL inget_pair./stats.volume_usdstays 24h swap notional. Mixing stock into flow JSON will break Charts #565 consumers.$0. Stale / zero reserves / same-asset / overflow / hub-oracle down / neither leg catalogued → omit/null. UI em-dash or omit the chip.$0only if a priced empty pool can exist afterreserves_usable; otherwise still—.$…(≤ ~5 words).title/aria-label: factory AMM pool USD (snapshot), not 24h volume. No lecture paragraph (#489-9).token-identity-pairinsidePairTokenLinks(or an adjacent typographic node in the same flex wrap). NoStatBox/card-glassinsidetrade-pair-select-panel(C653-1). No gold fill. Light + dark; 375px wrap is OK./poolmust not double-paint.PairTokenLinkstakes an optionalliquidityUsd. Trade + Charts pass it. Pool table / Manage do not (column is #655). Default omit = today’s row.getPool/getPairFeeConfig/GET /hub-prices/GET /overviewsolely to render this chip. Use the existinggetPairquery (refetch interval may shorten vs 60s if the stamp is fresher; do not poll LCD).<>/javascript:/ non-finite / scientific overflow →—. Text only — noinnerHTML.—; never a leftover$from the previous pair after switch./tokenroute, no picker-option LP badges.Relevant files
indexer/src/api/pairs.rsPairResponse+get_pairmust emit optionalliquidity_usdfrom the #655 stampindexer/src/indexer/protocol_tvl.rsindexer/src/db/queries/pairs.rsNone)indexer/tests/api_pairs.rsGET /pairs/{addr}field / 404 / no live sumfrontend-dapp/src/types/index.tsIndexerPair.liquidity_usd?: string | null(shared with #655)frontend-dapp/src/services/indexer/client.tsgetPairtypes only — no new clientfrontend-dapp/src/components/ui/PairTokenLinks.tsxfrontend-dapp/src/pages/TradePage.tsxindexerPairQuery.data?.liquidity_usdfrontend-dapp/src/pages/ChartsPage.tsxgetPairor list field — prefergetPairso it does not wait on #655 list JOIN)frontend-dapp/src/utils/formatProtocolStats.tsformatProtocolUsdfrontend-dapp/src/components/ui/__tests__/PairTokenLinks.test.tsxfrontend-dapp/src/pages/TradePage.test.tsx#541still holds; new LP casesfrontend-dapp/src/pages/ChartsPage.test.tsxfrontend-dapp/src/components/pool/PoolPairsTable.tsxliquidityUsdfrontend-dapp/e2e/token-identity-541.spec.ts/trade/{pair}+/chartsdocs/frontend.mddocs/indexer-invariants.mdliquidity_usdskills/AGENTS_FRONTEND_TOKEN_IDENTITY.mdscripts/qa/verify-issue-NNN.sh+Makefilemake verify-issue-NNNRecommended direction
get_pairJOINspair_liquidity_usdand setsliquidity_usd: Option<String>(skip_serializing_if). 404 still 404. Do not populatevolume_quote_24has a side effect. Do not compute TVL in the handler.PairTokenLinks: OptionalliquidityUsd?: string \| null. WhenformatProtocolUsd≠—, render a compact siblingdata-testid="token-identity-v2-lp-usd": label v2 LP +$…. When—/ missing, omit the chip (or show—only if the pair row is visible and we need a stable testid — prefer omit-when-unpriced so identity stays quiet).indexerPairQuery.data?.liquidity_usd. Pair switch must drop the previous pair’s$immediately (key the chip onpairAddr).make verify-issue-NNN. Vitest +GET /pairs/{addr}indexer test + scoped Playwright (5 workers, no e2e-tx).make verify-issue-541stays green.Do not LCD
getPoolto multiply reserves in the browser. Do notGET /overviewand pretend protocol TVL is this pair.Acceptance criteria
/trade/{pair}identity row shows v2 LP + compact human USD next to token chips / pair address whenliquidity_usdis priced./charts/{pair}identity row shows the same chip for the selected pair. Charts 24h Vol (USD) is unchanged (stillvolume_usd).GET /api/v1/pairs/{addr}includes optionalliquidity_usdstring when stamped; omitted/nullwhen not. Additive. Unknown addr still 404.protocol_pair_tvlfor the same stamp (UST1/cUSTC not$1/leg; USTR not2.5×USTC).""/"Infinity"/"NaN"/ hostile → no fake$0; chip omitted or—./pooltablePairTokenLinksdoes not show the chip (no double paint vs #655 column).getPool/ hub / overview fetch on Trade first paint. ExistinggetPaironly.StatBox/ nestedcard-glassin the pair-select panel. No TVL lecture.make verify-issue-NNNland with the implementation.make verify-issue-541still green.Test plan (all paths)
Indexer (
GET /api/v1/pairs/{addr})liquidity_usd= stampedprotocol_pair_tvlstringnull; 200liquidity_usd: "0")$12.5×pair_reserves× oracle on GETvolume_quote_24hon single GET staysNone/ unchangedcode_id_frozen/lp_tokenunchangedFrontend — Trade
getPair$compact next to identitygetPairmissing field / null / hostile—; page does not crash/tradeauto-pick$gone before B paintspair-token-links, no LP chip$Frontend — Charts + shared
/charts/{pair}identityvolume_usd/formatIndexedVolumeUsd; not TVLPairTokenLinkswithoutliquidityUsd"1234.5"$+ compact (formatProtocolUsd)<>—or omitE2E / LocalTerra
/trade/{factoryPair}$or quiet omit — not blank garbage/charts/{same}Test plan (attack, hack, abuse)
liquidity_usd=<img onerror=…>/javascript:$12Mmust not linger on a dust / unpriced pair (spoof size)volume_quote_24h/stats.volume_usd/ CGliquidity_in_usdgetPoolon Trade paintget_pair$1UST1 /2.5×USTRsymbol=USTR$0liquidity_usdto/statsand Charts reading the wrong field/poolidentity must not takeliquidityUsdcard-glasschip, no “this is AMM TVL not book” blurb1e+19/ huge string—/ omit; no tab lockjavascript:routeVerification criteria
Ship is done when all of the following hold:
make verify-issue-NNN(new) is green: indexerGET /pairs/{addr}stamp/omit/404; VitestPairTokenLinks+ Trade + Charts; static check that Trade identity does not callgetPool.make verify-issue-541still green (identity copy/explorer/invert/hide).make verify-issue-565still green (Charts Vol USD is still flow).make verify-issue-655(or its verify target) still green; Trade/Charts USD equals the/poolcell for the same pair./trade/{pair}and/charts/{pair}show v2 LP$…or quiet omit; pair switch; invert; no LCD storm.docs/frontend.mdtoken identity,docs/indexer-invariants.mdsingle-pairliquidity_usd,skills/AGENTS_FRONTEND_TOKEN_IDENTITY.md. AGENTS.md verify one-liner if that is house style.Out of scope:
/poolsortable v2 LP USD column and listsort=liquidity_usd(#655); Protocol global TVL (#569); V3 Grid TVL (#619); per-wallet LP on/portfolio; Charts 24h Stats extra tile; CGliquidity_in_usdrename.marked as related to #655
mentioned in commit
cbb45740f0mentioned in merge request !1162
mentioned in commit
211055203dmentioned in commit
72071a1016mentioned in commit
638e9ca59cMerged to
mainvia !1162. KeptformatPairV2LpUsdplus #667 census formatters. Pool table LP USD is !1173 (#655).Leftover: Trade/Charts identity v2 LP chip after indexer stamp + frontend rebuild. Unstamped pairs omit
$.make verify-issue-664.mentioned in issue #673
mentioned in issue #692
mentioned in issue #701