fix: show LUNC/USTC (not uluna/uusd) in token pickers #630
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#630
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
Retail token pickers (Swap You Pay / You Receive, and every other
TokenSearchSelect/TokenSelect/TokenDisplaysurface) show bank denomsulunaanduusdinstead of product tickers LUNC and USTC. Wrapped rows already show cLUNC / cUSTC. Users cannot tell native bank LUNC/USTC from CosmWasm wrap CW20s by ticker, and the denom strings look like internal ids.Reported from production Swap token dropdown (native rows sit next to cLUNC / cUSTC / USTR). LCD can be down (
Could not connect to the network) while the indexer catalog is still up — that is enough to leak the wrong labels.Related: #507 (cLUNC / cUSTC product symbols), #481 (Swap combobox), #541 (copy payload stays denom), #489 (retail copy).
Current codebase
What already maps correctly
frontend-dapp/src/utils/tokenRegistry.tsDENOM_MAP:uluna→ LUNC,uusd→ USTC. Wrap CW20s → cLUNC / cUSTC.getTokenDisplaySymbollookupByTokenId; unit tests already expectuluna→LUNC.tokenSearchQuery.tsLUNC/ulunaboth match. Filter ids stayuluna/uusd.getAllTokensuluna/uusdplus wrap CW20s so Swap can wrap without a factory pair (#507).ulunaalready labeled LUNC.Token ids used for balances, quotes, and execute must stay
uluna/uusd. Only the visible label is wrong.Why the dropdown still shows
uluna/uusduseTokenDisplayInfois the label source forTokenSearchSelect(Swap, Pool one-sided, Pay invoice) andTokenSelect(Mint):LUNC-Ccannot win.GET /api/v1/tokensreturnssymbol: "uluna"/"uusd", that beats the registry (LUNC/USTC).chainSymbol(registry viagetCachedTokenSymbol) is only the last fallback.Why the indexer catalog stores denom-as-symbol
indexer/src/indexer/asset_resolver.rson first native sight:nameandsymbolare both the raw denom. Integration seeds use the retail pair (uluna/Luna Classic/LUNC), but live ingest does not.GET /api/v1/tokensthen servessymbol=uluna/uusd.Surfaces that inherit the leak
Same hook or raw indexer
asset_*.symbol:TokenSearchSelect←useTokenDisplayInfoPayWithAnyToken.tsxTokenSelect.tsxTokenDisplay.tsx,TokenIdentity.tsxPoolAdvancedManage.tsxactivePair.asset_0.symbol/asset_1.symbol(factory pairs are usually CW20-only; still fix catalog so native legs cannot leak)data-testidstaystoken-option-uluna/token-option-uusd(id, not label). E2E helpers must keep selecting by id.Why this is needed
Retail users know LUNC and USTC. Showing
uluna/uusdnext to cLUNC / cUSTC looks like four different assets (or broken metadata). That is a wrap/unwrap selection hazard: picking the wrong row wraps when the user wanted wrapped CW20, or the reverse.getTokenDisplaySymboland the registry already encode the product names. The shared display hook throws that away whenever the indexer is reachable. QA wrap checklist already requires the selector to list LUNC, cLUNC, USTC, cUSTC (docs/qa-templates/wrap-unwrap-test-pass.md).Constraints / guardrails
uluna/uusd(or wrap CW20 addresses). Do not rename on-chain denoms.wrapProductSymbol. A compromised or stale indexer must not relabelulunaas UST1 / USTR / a gem ticker.uluna→ LUNC anduusd→ USTC (casefold). Do not invent tickers for IBC or other bank denoms.uluna/uusdandLUNC/USTCso power users and retail queries work. Do not drop denom from search.getAllTokens(pairs)+ wrap enrichment. Do not add an external token list to “fix” labels.uluna/uusdstay economic hubs. Do not hide them in production. Do not treat a spoofed indexer symbol as gem/hub identity.resolveTrustedTokenLogoUrl.assets.symbolstaysulunauntil a repair migration. If indexer upsert is fixed, unknown denoms still use denom-as-symbol (fail closed).Relevant files
Frontend (primary)
frontend-dapp/src/hooks/useTokenDisplayInfo.ts— label precedencefrontend-dapp/src/utils/tokenRegistry.ts—lookupByDenom/TOKENSfrontend-dapp/src/utils/tokenDisplay.ts—getTokenDisplaySymbol(already correct)frontend-dapp/src/components/trade/TokenSearchSelect.tsxfrontend-dapp/src/components/ui/TokenSelect.tsxfrontend-dapp/src/components/ui/TokenDisplay.tsxfrontend-dapp/src/components/ui/TokenIdentity.tsxfrontend-dapp/src/pages/SwapPage.tsxfrontend-dapp/src/components/pool/OneSidedAddCard.tsx,OneSidedWithdrawCard.tsxfrontend-dapp/src/components/payments/PayWithAnyToken.tsxfrontend-dapp/src/utils/tokenSearchQuery.tsdocs/frontend.md§ Token search comboboxdocs/qa-templates/wrap-unwrap-test-pass.mdNATIVE_TOKEN_WRAPPING.md(E11: selector shows LUNC and cLUNC, USTC and cUSTC)Indexer (catalog consistency)
indexer/src/indexer/asset_resolver.rs— native upsertname=denom, symbol=denomindexer/src/db/queries/assets.rs—upsert_assetindexer/src/api/tokens.rs—GET /api/v1/tokensindexer/tests/common/mod.rs/indexer/scripts/seed-charts-integration.sql— already seedLUNCTests to extend
frontend-dapp/src/utils/__tests__/tokenDisplay.test.tsfrontend-dapp/src/utils/__tests__/tokenRegistry.test.tsfrontend-dapp/src/components/trade/__tests__/TokenSearchSelect.test.tsxfrontend-dapp/src/hooks/__tests__/useTokenDisplayInfo.test.ts(or equivalent)Recommended direction
1. dApp (must ship; unblocks the screenshot)
In
useTokenDisplayInfo, resolve a product symbol from the static registry for known natives and wrap CW20s beforeindexerMeta.symbol:lookupByDenom(uluna|uusd)→ LUNC / USTCwrapProductSymbol→ cLUNC / cUSTCgetCachedTokenSymbol/ shortened address / raw idPrefer a small helper (e.g.
registryProductSymbol(tokenId)) used by both the hook andgetTokenDisplaySymbolso precedence cannot drift.Do not special-case only
TokenSearchSelect. Fixing the hook covers Mint, Pool, Pay invoice, TokenDisplay, TokenIdentity.2. Indexer (same issue; keeps API / pair chrome honest)
When inserting
uluna/uusdthe first time, write retailname/symbol(Luna Classic/LUNC,TerraClassicUSD/USTC), matchingtokenRegistryand existing test seeds. Leave other denoms as denom/denom.Optional: one-time SQL repair for existing
assetsrows wheredenom in ('uluna','uusd')andsymbolis the denom. Do not rewrite CW20 wrap rows (those stay cLUNC / cUSTC via #507).3. Docs / verify target
Add a short invariant to
docs/frontend.md§ Token search (and wrap QA template if not already explicit): visible option text is LUNC / USTC, neveruluna/uusd.make verify-issue-<this>runs the new Vitest files.Acceptance criteria
TokenSelect,TokenDisplay, andTokenIdentity.GET /api/v1/tokens(after ingest or repair) reportssymbol=LUNC/USTCfordenom=uluna/uusd.onChange,data-testid, balances, and execute remainsuluna/uusd.LUNC,lunc,uluna,USTC,uusdstill finds the correct row.symbol: "uluna"/"UST1"/ HTML / empty string cannot override registry LUNC/USTC.ufoo) still displays asufoo.uluna/uusd; no Finder link for natives.queryDraft).Test plan (all paths)
Unit — display precedence
lookupByDenom('uluna'|'uusd'|'ULUNA')→ LUNC / USTC (existing + casefold).getTokenDisplaySymbol('uluna'|'uusd')→ LUNC / USTC.useTokenDisplayInfo({ native_token: { denom: 'uluna' } })with:{ denom: 'uluna', symbol: 'uluna' }→ LUNC (registry wins){ denom: 'uluna', symbol: 'UST1' }→ LUNC (spoof rejected){ denom: 'uusd', symbol: 'uusd' }→ USTCLUNC-C/USTC-C(#507).{ denom: 'ibc/ABC' }→ raw denom (or indexer symbol if present and not a known-native override).token_info/ shortened address.Unit — picker / search
TokenSearchSelectoptions: visible text LUNC / USTC;data-testidstilltoken-option-uluna/token-option-uusd.value="uluna".filterTokensByLocalSearch(..., 'LUNC')and'uluna'both return['uluna'](and USTC /uusd).excludeTokenstill omits the other leg.ulunastill sorts as economic LUNC).Indexer
resolve_assetforNativeToken { denom: "uluna" }/"uusd"upserts symbol LUNC / USTC (not the denom).usdr) still stores denom as symbol.uluna/uusdrows with symbol=denom become LUNC/USTC; wrap CW20 rows untouched.Integration / E2E (LocalTerra or production-shaped env)
uluna.uusd.e2e/swap-token-select-cls.spec.tsstill passes (#498).uluna/uusdas the visible pair-leg ticker if a native leg exists; factory CW20 pairs unchanged (cLUNC/cUSTC).Regression (must not break)
make test-frontendscoped to token registry / display / TokenSearchSelect / TokenSelect keyboard / token identity.cd frontend-dapp && npm test -- src/utils/__tests__/tokenSearchQuery.test.ts src/components/trade/__tests__/TokenSearchSelect.test.tsx src/components/ui/__tests__/TokenSelect.keyboard.test.tsxgetTokenDisplaySymbol(already LUNC).Test plan (attack / abuse)
symbol=UST1(or USTR / CL8Y / gem ticker) fordenom=ulunasymbol=<script>…/ HTML / very long string forulunainnerHTML).logo_urlpoints atjavascript:or a non-allowlisted hostresolveTrustedTokenLogoUrldrops it; LUNC/USTC fall back to tokenlist GitLab art.contract_addresscolliding on stringulunaindexerTokenForIdmust not bind a CW20 to the native id. Native match isdenom === tokenIdonly.TOKEN_SEARCH_MAX_QUERY_LENGTH(128). No freeze.ulunahoping to pick a look-alike CW20 named ULUNAtoken_info.symbolisuluna/LUNCis a different row (address id). Do not collapse it into native LUNC.uluna, notLUNC. Search forLUNCis fine; execute never uses the display string as an address.ulunaulunamust not hide bank LUNC.cl8y-dex-token-infopoisoned withuluna: { symbol: 'HACK' }lookupByTokenId/ registry runs before that cache for known natives.Verification criteria
Manual (mainnet or LocalTerra with wrap env):
uluna/uusdin option text.uluna(network fee row still LUNC).uusd.ulunaandLUNC— both highlight the native LUNC row. Typeuusd/USTC— native USTC.uluna/uusdoptions.Done when a reviewer cannot find
ulunaoruusdas visible ticker text on Swap/Pool/Pay/Mint pickers, and execute still uses the bank denoms.mentioned in issue #632
mentioned in merge request !1141
mentioned in merge request !1142
mentioned in commit
d7050d853cmentioned in commit
796b647e7e!1142 merged to
main(d7050d85) without waiting for CI. Conflicts were Makefile help/PHONY only.make verify-issue-63011/11 (N630-1–N630-8 + indexer lib + #541 copy stays denom).Leftover (not proven on this merge):
20260825140000_repair_native_bank_tickers.sqlso liveGET /api/v1/tokensstoressymbol=LUNC/USTC. The dApp no longer needs that catalog repair (registry wins), but the catalog leak remains until migrate.Do not reopen unless a merged invariant is wrong. Operator leftovers go on the post-merge leftover issue.
mentioned in issue #638
marked as related to #638
Post-merge leftovers for the !1140/!1142/!1143/!1144/!1145 pass: #638.
mentioned in issue #661
mentioned in issue #680
mentioned in issue #691
mentioned in issue #711
mentioned in issue #713
mentioned in issue #715
marked as related to #715