fix: /cg/tickers liquidity_in_usd is 24h volume — plus other CG/CMC listing field mislabels #685
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#685
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?
Parent / related
Follow-up on closed docs audit #224 (do not reopen
#224). Exchange form child: #643. Catalog: #639. True TVL already exists aspair_liquidity_usd/protocol_pair_tvl(#569 / #655). GeckoTerminal event reserves are #684 — different crawler (/gt/*).Summary
CoinGecko
/cg/tickersand several sibling CMC/CG listing fields do not mean what their names orCG_CMC_COMPLIANCE.mdsay. The worst isliquidity_in_usd: aggregators treat it as pool TVL; we emit 24hvolume_usd. Docs still describe it as pool liquidity (or"0"until an oracle exists). That can inflate exchange “liquidity” to equal volume and leak into Llama/GT if anyone copies the field.Bundle field truthfulness for
/cg/*+/cmc/*in one issue: TVL, fake ticker bid/ask, freeze flag, CMC id types, gem leak, symbol-key collisions, and docs that invert trade side / limits. Do not split “rename the comment” vs “wirepair_liquidity_usd” vs “fix the markdown table.”Current codebase
GET /cg/tickers→liquidity_in_usd"0"unless an oracle is configured (CG_CMC_COMPLIANCE.md§ tickers).indexer/src/api/cg.rssets it fromstats.volume_usd("0"if NULL). Rust comment already admits: “Mislabeled 24hvolume_usd(legacy aggregator field).”protocol_pair_tvl+pair_liquidity_usdstamp (#569 / #655). Overviewtotal_liquidity_usdexplicitly not CGliquidity_in_usd.aggregator_snapshot.rsnever JOINspair_liquidity_usd./cg/tickersbid/asklast_price * 0.999/* 1.001viaf64(always 20 bps wide). Not the hybrid book./cmc/summaryhighest_bid/lowest_ask* 0.999/* 1.001incmc.rs./cg/orderbook+/cmc/orderbook/cmc/tickerisFrozen0active /1frozen."0". Paircode_id_frozen(#585) is unused./cmc/tickerbase_id/quote_id0).assets.cmc_idexists and is used only on/cmc/assets./cg/pairs,/cg/tickers,/cmc/*gemscoingecko-exchange.md, L639-2)./gt/*404s gems.get_all_pairs— no gem / ALPHA / USTRIX / SpaceUSD filter. GT form even tells the vendor to ignore gems in/cg/pairs.ticker_id={symbol}_{symbol}find_pair_by_tickeror_insert— first pair wins. Two UST1/… markets or spoofed symbols collide; orderbook/trades resolve to the wrongpool_id./cmc/assetsHashMap keyed by symbol overwrites./cg/historical_tradessideis_buy = offer_asset_id == asset_1(offer quote = buy base). CEX-standard. Docs are inverted.limitInvariants already warn operators:
docs/indexer-invariants.md,docs/DEFILLAMA.md,docs/runbooks/overview-global-stats-brin.md— “CGliquidity_in_usdis mislabeled 24h volume; never publish as Llama TVL.” That is a workaround, not a fix.Why a new implementation is needed
liquidity_in_usdas TVL. CoinGecko’s exchange ticker schema uses that name for pool USD. Serving 24h volume makes a quiet book look deep after one large print, and a deep idle pool look empty."0"; buy vs sell; trade limit; CMC ids).#224aligned timestamps/wrappers; it did not fix these field semantics.pair_liquidity_usdis the same P522-Q / hub catalog as Protocol Total liquidity. Wiring it is a JOIN on the stamp, not a new oracle./cg/orderbookon the same host. A crawler that prefers ticker bid/ask over the book will invent a 0.2% market that does not exist./cg/pairsfight#562/#646/ listing-form policy. Soft-launch pairs become “official” CG markets.#224. That ticket is the closed spec-matrix pass. This is implementation + doc truth.Constraints / guardrails
liquidity_in_usd. Do not rename it in JSON (crawlers are keyed). Change the value to AMM v2 TVL frompair_liquidity_usd/protocol_pair_tvl. Unpriced / stale / overflow / same-asset →"0"or omit only if the Kujira/CG schema allows — prefer"0"for this required string field. Never$1UST1, never2.5×USTR, never vFDUSD, never book escrow, never CG volume.pair_reserves ⋈oracles on/cg/tickers(same rule as#655). Stamp already refreshed with protocol TVL / hub./gt/eventshere. Llama =#631on-chainPool {}. GT historical reserves =#684.#216/ L10).cl8y_extensionsstay additive/optional.last_pricestays human quote-per-base (H10), notprice_usd./cg/orderbook) or reserve-implied mid ±fee_bps. Do not LCD N+1 per ticker on the cached list path. If best bid/ask cannot be computed cheaply, document the remaining approximation and stop claiming it is the book.f64mid * 0.999 is banned for the replacement (precision + fake width)./gt(L639-2 /#562). 404 / omit from/cg/pairs, tickers, CMC summary/ticker/assets as applicable. Frozen pairs may stay listed withisFrozen=1.isFrozen:1whencode_id_frozen(or pair inactive). Do not invent a pause bit from missing volume.base_id/quote_id: pick one and make docs + OpenAPI + JSON agree. Preferred: numericassets.cmc_idwhen set, else0, and put contract/denom in a documented extension — or keep contract strings and rewrite the compliance table/example (today they claim numbers). Do not ship both silently.EMBER_LUNC(or two UST1 pairs) to the first insert. Preferpool_iddisambiguation in lookup, or skip duplicateticker_ids and log. HashMap-by-symbol on/cmc/assetsmust not drop the economic token for a gem spoof.limit/offsetstill 400. No raw SQL from query strings.liquidity_in_usd,cl8y_extensions, orpool_id. Do not wrap/cg/tickersin{ tickers: [...] }unless product explicitly accepts a crawler break (Kujira wrap is Partial today — leave it).Relevant files
indexer/src/api/cg.rsliquidity_in_usd, fake bid/ask, pairs list, trades sideindexer/src/api/cmc.rsisFrozen, assets mapindexer/src/api/aggregator_snapshot.rspair_liquidity_usd, gem filterindexer/src/api/mod.rsfind_pair_by_tickercollisionindexer/src/db/queries/pair_liquidity_usd.rsindexer/src/indexer/protocol_tvl.rsprotocol_pair_tvl— do not forkindexer/src/indexer/defillama.rsCOLUMBUS5_GEM_ADDRESSES— share with GTindexer/src/api/gt.rsEXCLUDED_CW20/is_excluded_cw20— keep lockstepindexer/tests/api_cg.rs,api_cmc.rs,api_aggregator_batch.rsdocs/CG_CMC_COMPLIANCE.mddocs/indexer-invariants.mddocs/DEFILLAMA.md,docs/runbooks/overview-global-stats-brin.mddocs/listings/forms/coingecko-exchange.mdscripts/qa/+Makefilemake verify-issue-NNN(do not overloadverify-issue-224)Recommended direction
load_aggregator_pairs: LEFT JOINpair_liquidity_usd. Map to tickerliquidity_in_usdas the human USD string. Unpriced →"0". Stop copyingvolume_usd.last_price) when the book snapshot is fresh; else omit-equivalent (last_priceboth sides) or reserve mid ±fee_bps— pick one, test it. Killto_f64() * 0.999.isFrozen:code_id_frozen/is_active./gt(one helper)./cmc/assetsskip excluded CW20s; last-write-wins on symbol must prefer the permanent economic pin if a collision remains.SYMBOL_SYMBOL, do notor_insertthe first forever — prefer factory-listed non-gem, else skip key and requirepool_id.liquidity_in_usd= AMM TVL stamp; buy = offer quote; trades limit 500; drop “0 unless oracle.”make verify-issue-NNN. Coolify indexer redeploy. No wasm migrate. No dApp change.Acceptance criteria
/cg/tickersliquidity_in_usdequalspair_liquidity_usd/protocol_pair_tvlfor a priced pair (e.g. UST1/cUSTC), not 24hvolume_usd."0"(not volume, not$1UST1, not2.5×USTR).liquidity_in_usdand largebase_volume/target_volume.bid≤last_price≤askwhen a book/reserve mid exists; width is not hardcoded 20 bps unless that is the documented fallback. Nof64 * 0.999./cmc/summarybid/ask follow the same rule as CG tickers.code_id_frozen) →/cmc/tickerisFrozen="1"(or1— match existing string type).base_id/quote_idmatch the rewritten spec (numbers or contracts — not both)./cg/pairs,/cg/tickers,/cmc/summary,/cmc/ticker./gtexclude list stays lockstep.ticker_iddoes not silently bind orderbook/trades to the wrong pair.historical_tradesdocs match code (buy = offer quote / buy base). Limit docs = 500.swap_eventsor live-sum reserves for TVL (EXPLAIN/ test).#288cache + pagination unchanged.make verify-issue-NNN+ compliance doc grep.#224stays closed.Test plan (all paths)
liquidity_in_usd= stamp TVL, ≠volume_usd"0"#569/cmc/summarysame pairliquidity_in_usdfield (CMC schema); bid/ask not 20 bps toy if book existsclose * 0.999isFrozen=1; still listed unless gem/gt/pairstill 404pool_id/cmc/assetsgem + real token same symbol/cmc/tickeridsbuy[]; sell: offer = base insell[]limit=200/limit=500/limit=501on tradesoffset>10000tickers/cg/pairspage still haspool_idTest plan (attack, hack, abuse)
volume_usdinliquidity_in_usd)$1UST1 /2.5×USTRRESERVES(stamp), notbalanceOfCL8Y_UST1ticker_id/cg/tickersisFrozen=1COLUMBUS5_GEM_ADDRESSES+ GT listlimit=1000tickers with live book sim per rowVerification criteria
Live (after indexer redeploy), no chat logs:
CG_CMC_COMPLIANCE.mdfield table matches JSON./gt/eventsunchanged except shared gem helper if extracted.#224remains closed;#684remains the GT reserve ticket.Out of scope
/cg/tickersin{ tickers: [...] }(Kujira wrap)/poolTVL (already#569/#655)liquidity_in_usdor inventingliquidity_in_usd_realmarked as related to #224
marked as related to #643
marked as related to #569
marked as related to #655
marked as related to #684
mentioned in issue #643
mentioned in merge request !1188
mentioned in merge request !1189
mentioned in commit
4fd3d2fd19mentioned in merge request !1190
mentioned in commit
cf1c0a63e6mentioned in commit
906b6e7f0dmentioned in issue #688
marked as related to #688
Merged as !1190 onto
main(906b6e7f). Local AC1–AC13 passed (make verify-issue-685). Conflicts vs !1187/!1189 resolved: Makefile kept verify-issue-684/685/686/687;gt.rsuses sharedlisting_exclude::is_excluded_cw20(no duplicate helper).Leftovers (do not reopen unless a merged invariant is wrong): Coolify indexer redeploy (no wasm/dApp). Live check:
/cg/tickersliquidity_in_usd≈ pairliquidity_usdstamp and ≠ 24h volume. Tracked on #688.CI was
failed(ci_quota_exceeded); not waited.Non-blocking: list path can still emit duplicate
SYMBOL_SYMBOLrows with differentpool_id(orderbook/trades 404); bid/ask is reserve mid ±fee_bps, not hybrid book best (documented L685-3).