feat: hide soft-launch gemstone tokens from production retail UI (RUBY, EMBER, …) #562

Closed
opened 2026-08-18 12:08:53 +00:00 by PlasticDigits · 42 comments
PlasticDigits commented 2026-08-18 12:08:53 +00:00 (Migrated from gitlab.com)

Summary

Hide soft-launch gemstone / faucet tokens (EMBER, CORAL, JADE, ONYX, RUBY, TOPAZ, QUARTZ, PEARL, plus LocalTerra extras OPAL, COBALT, SLATE, AMBER, IRON) from the production retail dApp (https://dex.cl8y.com) so Swap / Trade / Pool / Charts / Create look like a finished economic DEX, not a test faucet.

Bundle into one issue. Do not split “Swap picker” vs “Trade pairs” vs “Pool table” vs “Create Pair gems” vs “Mint nav” vs “route hops through gems” vs “Coolify faucet env.”

This is retail discovery + quoting, not on-chain deletion. Pairs and CW20s stay on columbus-5.

Related: #534 (economic first, gems last — still listed), #473 (Mint faucet), #542 (Create Pair appends mintable gems), #547 (/pool catalog still shows gems last), #489 (retail copy), #501 (hybrid GET /route/solve may hop gem pools).

Current codebase

Soft-launch deployed eight noneconomic CW20s and ten gem pairs on columbus-5 (deployments/mainnet-soft-launch/deploy-trace.md). They were a routing/UI sandbox before wrap + UST1 hubs existed. Economic markets (cLUNC, cUSTC, UST1, USTR, CL8Y, vFDUSD, …) are live; the gems are still in the factory graph.

Symbol Kind Mainnet address
EMBER cw20-mintable 10184 terra1dmuruhht32x8f47nvm73pwp6q7uf2jtfhdt3nxcql4mmqkyfsraqn2dt94
CORAL mintable terra1k6cqupylk0wp4pj273pntwhv9py0q5guyqye8ssvukn9xq7mes7sdlmena
JADE mintable terra1ejq3mjjgnklpa3pg4jterlfwsny055gpmcjf3fz0ev3ueajnzeysz6xxgr
ONYX mintable terra178fgrfzv7njtmdp9vghyf2dx77sah8u8jluzs7ym562chaxnmj2s6mn6m9
RUBY mintable terra1fga508hzx8dd7x8q4uhm6mdhkqv6fxrtsea3r27smdqmv5k2jgxq5zk9fc
TOPAZ mintable terra12k67cvfs7y7g8lca3qr4g4py6s6j69fu24gze5pjfamfpckv8mps7cymme
QUARTZ cw20-base 6036 terra17dpnjlpgsnm8muu4msfjra4f2hrptnjp2jdpkka4p0e3px42ayxq0pmc2z
PEARL cw20-base terra18fzufz8cs7ez49xjwgs248x85za5v50yug55fj7lyxp9hapxyr7qnh3czs

Pairs: EMBER/CORAL, EMBER/JADE, EMBER/ONYX, CORAL/RUBY, JADE/TOPAZ, ONYX/QUARTZ, RUBY/PEARL, EMBER/QUARTZ, CORAL/PEARL, JADE/ONYX.

Surface Behavior today
Swap YOU PAY / YOU RECEIVE getAllTokens(pairs) unions every factory leg + wrap natives. filterTokensByLocalSearch only ranks gems last (P534-7). Empty browse still lists RUBY / ONYX / PEARL / … with blockies identicons (not in tokenlist/tokenlist.json). Default from/to is tokens[0]/[1] — often a gem. Live dex.cl8y.com Swap picker shows this.
Trade / Limits pair combobox PairSearchSelect empty browse uses sortPairInfosByCatalog then a Test pairs divider (#534 P534-1). Gems remain selectable. Typed RUBY still hits.
/trade auto-pick firstCatalogPairAddress prefers economic pairs when any exist (P534-5), but gem pairs stay in the menu.
/pool table Default catalog rank: UST1 hubs first, gems last (#547 P547-3). Gems still occupy rows and pagination.
Charts pair menu Same catalog overlay. Overview Pairs / Tokens counts include gem legs (#548 C6 = COUNT(*) over all indexed pairs).
Create Pair getCreatePairCw20Options appends SOFT_LAUNCH_MINTABLE_TOKENS whenever Coolify bakes VITE_TOKEN_{EMBER,…}_ADDRESS (C542-11). QUARTZ/PEARL are not in that env list but still appear on Swap via factory.
Mint / faucet Coolify frontend.env.example sets VITE_FAUCET_ADDRESS + six mintable addresses. Nav Mint appears when faucet env is set (F11 / #473).
Gem classification GEM_SYMBOLS / isGemTokenId / isTestPair. Address match uses env mintables only — QUARTZ/PEARL rely on symbol after token_info.
Routing Local BFS findRoute and indexer GET /api/v1/route/solve (#501) walk the full factory graph. A production UST1↔cUSTC quote can still hop EMBER/RUBY and show that on the Route row.
LocalTerra / QA deploy-dex-local.sh seeds gems; swarm (#293), Playwright wrap/swap, limit-order E2E, and VITE_NETWORK=local all depend on EMBER/CORAL/… remaining visible.

There is no production gate that omits gems from pickers. #534 only reordered them.

Why this is needed

Retail users on dex.cl8y.com are spending real LUNC / UST1 / wrap assets. A Swap picker full of RUBY / ONYX / PEARL / QUARTZ (pixel blockies, faucet tickers) reads as unfinished / testnet, even when economic pairs work. Ranking gems last (#534) does not fix first-open browse: they are still in the list, searchable, and can be the default pay token.

Product ask: remove them from the finished article now that wrap / UST1 / economic markets are the real product. Keep them where they still earn their keep: LocalTerra, swarm, contract tests, and residual holder exit.

Constraints / guardrails

  1. Do not destroy chain state. No burn, no UpdateMinter theatre, no factory pair delete (none exists), no forced LP withdraw, no indexer DB wipe of gem pairs. Soft-launch CW20s and pairs remain valid columbus-5 contracts.
  2. LocalTerra / QA must keep gems. VITE_NETWORK=local (and an explicit opt-in for a mainnet-RPC QA build) still lists gems, Test pairs, faucet Mint, Create Pair gem append, swarm OE-1 pairs, and Playwright token names (EMBER, CORAL, IRON, …). Do not rewrite E2E onto UST1 as a substitute unless a test has no gem fixture.
  3. Hide from discovery, not from balances. /portfolio, /trader, wallet history, and LP rows must still show gem positions a user already holds so they can exit. Deep link /trade/<gem-pair-addr> and a pasted gem CW20 on Swap may still resolve for that exit path; they must not appear in empty browse or typed catalog search on production.
  4. Identify by address + ticker, not ticker alone as the only gate. Spoofing symbol=UST1 on a gem contract must stay hidden; a future listed token must not vanish because someone named it RUBY. Production hide list = GEM_SYMBOLS and the eight columbus-5 addresses (plus LocalTerra extras by symbol). Do not rely only on Coolify VITE_TOKEN_* (QUARTZ/PEARL are absent there; unsetting env must not re-show gems).
  5. Do not treat UST1 / CL8Y / wrap as gems (U6 / P534-8). isGemSymbol('UST1') stays false.
  6. Production quotes must not advertise gem hops. If both legs are economic, findRoute / hybrid route/solve / Swap Route row must not show EMBER→JADE→RUBY-class intermediates. Prefer “no route” over a gem bridge. LocalTerra may still use gem hops (existing E2E).
  7. Factory token universe stays the gate for Swap (#481). Filter gems inside that set. Do not load a remote tokenlist for Swap. Create Pair catalog stays independent (C542-8).
  8. Mint on production: unset Coolify VITE_FAUCET_ADDRESS (nav hides via F11). Recommend operator Pause on the faucet + optional RemoveMinter per F9 so UI hide is not the only control. Do not add KYC. Do not fold UST1 mint into /mint (#506).
  9. #489. No new essay (“these were test tokens…”). Absence is the UX. Optional one-line if a deep-linked gem pair is opened: that it is a legacy noneconomic market — not a lecture on soft-launch history.
  10. Typed search. Production query RUBY / EMBER / quartz returns no gem options. Do not leak them under Test pairs on mainnet builds. LocalTerra keeps the divider (P534-1).
  11. Indexer JSON may still list gem pairs for integrators / residual charts. dApp overlays the hide. Optional exclude_test_pairs on route/solve is in scope if frontend filtering is not enough to stop gem hops. Do not change volume_quote_24h wire format.
  12. a11y / CLS. Same combobox contracts (#350 / #481 / #498). Filtering must not blank the trigger or shift layout when the current token is a hidden gem (clear to empty / first economic token).
  13. Logos. Gems use blockies; economic tokens use tokenlist logos. Do not add gem artwork. Do not allowlist random logo URLs to “pretty up” gems.

Relevant files

File Role
frontend-dapp/src/utils/pairCatalogRank.ts GEM_SYMBOLS, isGemTokenId, isTestPair, catalog sort
frontend-dapp/src/utils/constants.ts SOFT_LAUNCH_MINTABLE_TOKENS, VITE_TOKEN_*, DEFAULT_NETWORK, faucet
frontend-dapp/src/utils/tokenSearchQuery.ts Swap empty browse / typed filter
frontend-dapp/src/services/terraclassic/router.ts getAllTokens, findRoute
frontend-dapp/src/pages/SwapPage.tsx Default pay/receive from getAllTokens
frontend-dapp/src/components/trade/TokenSearchSelect.tsx Swap combobox
frontend-dapp/src/components/trade/PairSearchSelect.tsx Trade/Limits empty browse + Test pairs
frontend-dapp/src/pages/TradePage.tsx Auto-pick + market quote
frontend-dapp/src/pages/PoolPage.tsx + pool table Default catalog still includes gems
frontend-dapp/src/pages/ChartsPage.tsx Pair menu
frontend-dapp/src/utils/createPairTokenCatalog.ts Gem append
frontend-dapp/src/components/common/navItems.ts + Layout.tsx Mint nav F11
frontend-dapp/src/pages/MintPage.tsx Faucet UI
deployments/mainnet-soft-launch/frontend.env.example Coolify VITE_FAUCET_* / VITE_TOKEN_*
Indexer route/solve Gem hops in hybrid paths
docs/frontend.md § Pair catalog rank, token search Invariants P534-*
skills/AGENTS_FRONTEND_PAIR_CATALOG_RANK.md Agent playbook
docs/runbooks/soft-launch-faucet.md F9 pause / RemoveMinter
  1. Single helper (next to isGemTokenId): retailExposeTestTokens() = VITE_NETWORK !== 'mainnet' or VITE_SHOW_TEST_TOKENS=true. Production Coolify stays VITE_NETWORK=mainnet with the override unset. LocalTerra VITE_NETWORK=local unchanged.
  2. Hardcode the eight columbus-5 gem addresses (and keep GEM_SYMBOLS) so hide-by-address works even if Coolify drops VITE_TOKEN_*. QUARTZ/PEARL must be in that address set.
  3. Filter once, reuse everywhere:
    • Swap: filter getAllTokens (or a wrapper used by picker + default from/to) so empty browse, typed search, and initial selection are economic-only on production.
    • Pairs: filter factoryPairs / indexer rows fed to PairSearchSelect, /pool default+search, Charts menu. User column sort on /pool must also omit gems on production (otherwise Vol sort resurfaces RUBY/PEARL).
    • Create Pair: skip gems: append when !retailExposeTestTokens(). Custom paste of a gem CW20 still hits factory whitelist (honest) — do not special-case a “blocked” toast that teaches attackers the list; paste remains #382 checksum + code-id check.
    • Mint: Coolify unsets VITE_FAUCET_ADDRESS; /mint stays the existing unavailable path.
  4. Routing: when !retailExposeTestTokens(), drop test pairs from the BFS graph and reject route/solve paths whose hops include a gem asset (client-side sufficient if the indexer cannot filter yet; add query flag if tests show leaks).
  5. Exit hatch: if the connected wallet’s selected token / URL pair is a gem, keep that one instrument available (ticket + swap) until the user navigates away; do not put it back in the global list.
  6. Docs: extend P534 with production-hide invariants; Coolify runbook: do not bake faucet env on dex.cl8y.com; operator F9 pause. make verify-issue-<iid> for the new gate.
  7. Out of scope: migrating gem LP to CMM, changing factory whitelist, renaming tokens, new gem artwork, indexer pair-row deletion.

Acceptance criteria

  • A1. Production build (VITE_NETWORK=mainnet, override unset): Swap empty YOU PAY / YOU RECEIVE lists no EMBER, CORAL, JADE, ONYX, RUBY, TOPAZ, QUARTZ, PEARL (or LocalTerra extras). Economic + wrap tokens remain.
  • A2. Typed search RUBY, onyx, pearl, quartz, ember on that build returns no gem rows. Address paste of a gem CW20 is not offered as a browse hit; deep-link/exit hatch documented.
  • A3. Trade / Limits / Charts / /pool empty browse and production search do not list the ten gem pairs. Test pairs divider is absent on production (nothing to group).
  • A4. Default Swap pay/receive and bare /trade auto-pick are economic (UST1 hub / wrap), never tokens[0] gem.
  • A5. Create Pair listed catalog does not append mintable gems on production. tokenlist CW20s (cLUNC, UST1, …) remain.
  • A6. Production Coolify: Mint nav hidden (VITE_FAUCET_ADDRESS unset). Runbook records faucet Pause (or explicit risk acceptance if left running).
  • A7. LocalTerra (VITE_NETWORK=local): gems still appear; Test pairs still shows; Mint still works when faucet env set; existing Playwright / swarm fixtures still find EMBER/CORAL.
  • A8. VITE_SHOW_TEST_TOKENS=true on a mainnet-network build restores gem browse (QA). Default production image does not set it.
  • A9. Portfolio / trader / history still render gem symbols and amounts for holders.
  • A10. Production Swap between two economic tokens never shows a gem hop on the Route row; quote fails closed rather than bridging RUBY.
  • A11. UST1 / cLUNC / cUSTC / USTR / CL8Y / vFDUSD never classified as gems (U6).
  • A12. Docs + playbook + make verify-issue-<iid> cover A1–A11. No always-on “test tokens removed” banner.

Test plan — functional paths

Unit / RTL

# Path Assert
U1 retailExposeTestTokens mainnet + unset override → false; local → true; mainnet + VITE_SHOW_TEST_TOKENS=true → true
U2 Address set All eight columbus-5 gem addrs are isGemTokenId; UST1 / wrap addrs are not
U3 filterTokensByLocalSearch production Empty list has no gem ids; query RUBY empty; economic ids remain sorted
U4 Same helper local EMBER present; P534-7 rank still gems last
U5 Pair empty browse production No gem contract_addr; no Test pairs label
U6 /pool production Default and sort=volume_24h mock pages omit gem pairs
U7 Create Pair catalog Production gems: [] equivalent; local still appends env gems
U8 Swap default tokens With mixed factory pairs, from/to are non-gem
U9 findRoute production graph Economic→economic does not include gem intermediate; gem→gem only if exit hatch
U10 Regression #534 / #542 / #547 / #481 tests still pass on local vitest env (VITE_NETWORK=local)

Playwright (5 workers; LocalTerra for local path; production path = unit + optional mainnet-env Vite)

# Path Assert
P1 Local Swap EMBER still in YOU PAY (existing wrap-swap / token-select specs)
P2 Local Trade Test pairs divider still appears when gems exist
P3 Production-mode Vite (VITE_NETWORK=mainnet against LocalTerra factory or fixture) Swap listbox has no RUBY/ONYX/PEARL; has cLUNC/UST1 if pairs exist
P4 Production-mode Trade / Pool No gem pair labels in empty browse
P5 Phone 390×844 Swap Combobox CLS (#498) unchanged after filter

Manual QA (dex.cl8y.com after Coolify rebuild)

  1. Open Swap → YOU PAY: only economic / wrap assets; no gemstone tickers or mystery blockies crowding the list.
  2. Type RUBY, EMBER, quartz: no hits.
  3. Trade / Pool / Charts: no gem pairs; no Test pairs heading.
  4. More menu: no Mint.
  5. If a test wallet still holds RUBY: Portfolio shows it; user can still navigate to the pair and sell.
  6. LocalTerra make dev: gems still there; faucet still drips.

Test plan — attack, hack, and abuse vectors

# Vector What to prove
X1 Ticker collision A listed economic token whose display symbol is accidentally RUBY is not hidden; hide requires gem address (or known gem symbol and not in economic hub/tokenlist). Document the rule; unit-test UST1 vs symbol=RUBY gem addr.
X2 Look-alike CW20 Factory clone with symbol=cLUNC but gem code-id / unknown provenance stays subject to existing #311 / whitelist — this issue must not mark it as a “real” hub just to fill the picker. Do not invert the gem set into an allowlist of tickers.
X3 Bypass via typed address Swap onChange still only emits ids in the gated options list (#481). Pasting terra1…ruby into search does not select a hidden gem unless the exit-hatch path is explicitly open. No dangerouslySetInnerHTML.
X4 Deep-link phishing /trade/<gem-pair> must not look like UST1/USTR (identity copy = contracts, T541-4). Invalid / javascript: / HTML params still rejected (T541-2). Optional legacy notice must be static React text.
X5 Route laundering Production hybrid quote must not hide a gem hop behind a sanitized “Route: UST1 → cUSTC” while executing EMBER in between. Displayed hops = executed hops (#158 / #501). Reject the quote if a gem hop is present.
X6 Indexer injection getPairs(q=RUBY) may still return gem rows; UI must drop them on production after factory intersection. Do not trust indexer is_test if absent — client gem set is source of truth.
X7 Coolify env mismatch Unsetting VITE_TOKEN_* must not re-list gems (hardcoded columbus-5 addrs). Unsetting faucet must hide Mint even if token envs remain.
X8 Override abuse VITE_SHOW_TEST_TOKENS is a build-arg, not a runtime query (?showGems=1 is forbidden — phishing / support-scam vector).
X9 Faucet still live If UI hides Mint but faucet is unpaused, sybils can still Drip via LCD. Acceptance A6 requires Pause or documented acceptance. Pause does not clear cooldowns (F9).
X10 Hidden but executable Do not leave a hidden gem selected as default pay token (drain / surprise swap). If previous localStorage selected RUBY, production session resets to economic default.
X11 DoS / haystack Filter must not scan unbounded indexer pages; keep factory cap + existing search limits (128-char query, 20 typed hits).
X12 Portfolio wipe illusion Filtering pickers must not zero gem balances in the UI (looks like theft). History rows keep symbols as text.
X13 CSP / logos No new remote logo hosts for gems. Blockies stay local canvas.
X14 Create Pair custom paste Pasting a gem address must not skip useCodeIdCheck or pair-creation fee. Do not add a client-only “blocked token” that can be bypassed by LCD CreatePair.

Verification criteria

make verify-issue-<iid>

Must prove:

  1. Vitest: production vs local expose flag; gem address set; Swap/Trade/Pool/Create filters; UST1 not a gem; route helper rejects gem hops on production graph.
  2. Docs/skills: production-hide invariants next to P534; Coolify faucet env + F9; LocalTerra exception.
  3. Playwright: LocalTerra gems still work; production-mode picker has no RUBY/ONYX/PEARL (fixture or env).
  4. Manual: dex.cl8y.com Swap screenshot no longer shows the gemstone list.

Issue is done when a mainnet Coolify rebuild matches A1–A12 and LocalTerra regression (make test-frontend + relevant E2E) is green. Not done if gems are only moved below a divider, or if chain contracts were deleted “to be sure.”

## Summary Hide **soft-launch gemstone / faucet tokens** (EMBER, CORAL, JADE, ONYX, RUBY, TOPAZ, QUARTZ, PEARL, plus LocalTerra extras OPAL, COBALT, SLATE, AMBER, IRON) from the **production** retail dApp (`https://dex.cl8y.com`) so Swap / Trade / Pool / Charts / Create look like a finished economic DEX, not a test faucet. Bundle into **one** issue. Do **not** split “Swap picker” vs “Trade pairs” vs “Pool table” vs “Create Pair gems” vs “Mint nav” vs “route hops through gems” vs “Coolify faucet env.” This is **retail discovery + quoting**, not on-chain deletion. Pairs and CW20s stay on columbus-5. Related: [#534](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/534) (economic first, gems last — still listed), [#473](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/473) (Mint faucet), [#542](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/542) (Create Pair appends mintable gems), [#547](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/547) (`/pool` catalog still shows gems last), [#489](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/489) (retail copy), [#501](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/501) (hybrid `GET /route/solve` may hop gem pools). ## Current codebase Soft-launch deployed **eight noneconomic CW20s** and **ten gem pairs** on columbus-5 ([`deployments/mainnet-soft-launch/deploy-trace.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/deployments/mainnet-soft-launch/deploy-trace.md)). They were a routing/UI sandbox before wrap + UST1 hubs existed. Economic markets (cLUNC, cUSTC, UST1, USTR, CL8Y, vFDUSD, …) are live; the gems are still in the factory graph. | Symbol | Kind | Mainnet address | |--------|------|-----------------| | EMBER | cw20-mintable **10184** | `terra1dmuruhht32x8f47nvm73pwp6q7uf2jtfhdt3nxcql4mmqkyfsraqn2dt94` | | CORAL | mintable | `terra1k6cqupylk0wp4pj273pntwhv9py0q5guyqye8ssvukn9xq7mes7sdlmena` | | JADE | mintable | `terra1ejq3mjjgnklpa3pg4jterlfwsny055gpmcjf3fz0ev3ueajnzeysz6xxgr` | | ONYX | mintable | `terra178fgrfzv7njtmdp9vghyf2dx77sah8u8jluzs7ym562chaxnmj2s6mn6m9` | | RUBY | mintable | `terra1fga508hzx8dd7x8q4uhm6mdhkqv6fxrtsea3r27smdqmv5k2jgxq5zk9fc` | | TOPAZ | mintable | `terra12k67cvfs7y7g8lca3qr4g4py6s6j69fu24gze5pjfamfpckv8mps7cymme` | | QUARTZ | cw20-base **6036** | `terra17dpnjlpgsnm8muu4msfjra4f2hrptnjp2jdpkka4p0e3px42ayxq0pmc2z` | | PEARL | cw20-base | `terra18fzufz8cs7ez49xjwgs248x85za5v50yug55fj7lyxp9hapxyr7qnh3czs` | **Pairs:** EMBER/CORAL, EMBER/JADE, EMBER/ONYX, CORAL/RUBY, JADE/TOPAZ, ONYX/QUARTZ, RUBY/PEARL, EMBER/QUARTZ, CORAL/PEARL, JADE/ONYX. | Surface | Behavior today | |---------|----------------| | **Swap YOU PAY / YOU RECEIVE** | [`getAllTokens(pairs)`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/services/terraclassic/router.ts) unions **every** factory leg + wrap natives. [`filterTokensByLocalSearch`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/tokenSearchQuery.ts) only **ranks** gems last (**P534-7**). Empty browse still lists RUBY / ONYX / PEARL / … with blockies identicons (not in [`tokenlist/tokenlist.json`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/tokenlist/tokenlist.json)). Default `from`/`to` is `tokens[0]`/`[1]` — often a gem. Live `dex.cl8y.com` Swap picker shows this. | | **Trade / Limits pair combobox** | [`PairSearchSelect`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/trade/PairSearchSelect.tsx) empty browse uses `sortPairInfosByCatalog` then a **Test pairs** divider ([#534](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/534) **P534-1**). Gems remain selectable. Typed `RUBY` still hits. | | **`/trade` auto-pick** | `firstCatalogPairAddress` prefers economic pairs when any exist (**P534-5**), but gem pairs stay in the menu. | | **`/pool` table** | Default catalog rank: UST1 hubs first, **gems last** ([#547](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/547) **P547-3**). Gems still occupy rows and pagination. | | **Charts pair menu** | Same catalog overlay. Overview **Pairs / Tokens** counts include gem legs ([#548](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/548) **C6** = `COUNT(*)` over all indexed pairs). | | **Create Pair** | [`getCreatePairCw20Options`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/createPairTokenCatalog.ts) appends `SOFT_LAUNCH_MINTABLE_TOKENS` whenever Coolify bakes `VITE_TOKEN_{EMBER,…}_ADDRESS` (**C542-11**). QUARTZ/PEARL are not in that env list but still appear on Swap via factory. | | **Mint / faucet** | Coolify [`frontend.env.example`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/deployments/mainnet-soft-launch/frontend.env.example) sets `VITE_FAUCET_ADDRESS` + six mintable addresses. Nav **Mint** appears when faucet env is set (**F11** / [#473](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/473)). | | **Gem classification** | [`GEM_SYMBOLS` / `isGemTokenId` / `isTestPair`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/pairCatalogRank.ts). Address match uses env mintables only — QUARTZ/PEARL rely on **symbol** after `token_info`. | | **Routing** | Local BFS `findRoute` and indexer `GET /api/v1/route/solve` ([#501](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/501)) walk the **full** factory graph. A production UST1↔cUSTC quote can still hop EMBER/RUBY and show that on the Route row. | | **LocalTerra / QA** | `deploy-dex-local.sh` seeds gems; swarm (**#293**), Playwright wrap/swap, limit-order E2E, and `VITE_NETWORK=local` all depend on EMBER/CORAL/… remaining visible. | There is **no** production gate that omits gems from pickers. `#534` only reordered them. ## Why this is needed Retail users on `dex.cl8y.com` are spending real LUNC / UST1 / wrap assets. A Swap picker full of RUBY / ONYX / PEARL / QUARTZ (pixel blockies, faucet tickers) reads as **unfinished / testnet**, even when economic pairs work. Ranking gems last ([#534](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/534)) does not fix first-open browse: they are still in the list, searchable, and can be the default pay token. Product ask: **remove them from the finished article** now that wrap / UST1 / economic markets are the real product. Keep them where they still earn their keep: LocalTerra, swarm, contract tests, and residual holder exit. ## Constraints / guardrails 1. **Do not destroy chain state.** No burn, no `UpdateMinter` theatre, no factory pair delete (none exists), no forced LP withdraw, no indexer DB wipe of gem pairs. Soft-launch CW20s and pairs remain valid columbus-5 contracts. 2. **LocalTerra / QA must keep gems.** `VITE_NETWORK=local` (and an explicit opt-in for a mainnet-RPC QA build) still lists gems, **Test pairs**, faucet Mint, Create Pair gem append, swarm OE-1 pairs, and Playwright token names (EMBER, CORAL, IRON, …). Do **not** rewrite E2E onto UST1 as a substitute unless a test has no gem fixture. 3. **Hide from discovery, not from balances.** `/portfolio`, `/trader`, wallet history, and LP rows must still show gem positions a user already holds so they can exit. Deep link `/trade/<gem-pair-addr>` and a pasted gem CW20 on Swap **may** still resolve for that exit path; they must **not** appear in empty browse or typed catalog search on production. 4. **Identify by address + ticker, not ticker alone as the only gate.** Spoofing `symbol=UST1` on a gem contract must stay hidden; a future listed token must not vanish because someone named it RUBY. Production hide list = `GEM_SYMBOLS` **and** the eight columbus-5 addresses (plus LocalTerra extras by symbol). Do not rely only on Coolify `VITE_TOKEN_*` (QUARTZ/PEARL are absent there; unsetting env must not re-show gems). 5. **Do not treat UST1 / CL8Y / wrap as gems (**U6** / **P534-8**).** `isGemSymbol('UST1')` stays false. 6. **Production quotes must not advertise gem hops.** If both legs are economic, `findRoute` / hybrid `route/solve` / Swap Route row must not show EMBER→JADE→RUBY-class intermediates. Prefer “no route” over a gem bridge. LocalTerra may still use gem hops (existing E2E). 7. **Factory token universe stays the gate for Swap** ([#481](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/481)). Filter gems **inside** that set. Do not load a remote tokenlist for Swap. Create Pair catalog stays independent (**C542-8**). 8. **Mint on production:** unset Coolify `VITE_FAUCET_ADDRESS` (nav hides via **F11**). Recommend operator `Pause` on the faucet + optional `RemoveMinter` per **F9** so UI hide is not the only control. Do not add KYC. Do not fold UST1 mint into `/mint` ([#506](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/506)). 9. **#489.** No new essay (“these were test tokens…”). Absence is the UX. Optional one-line if a deep-linked gem pair is opened: that it is a legacy noneconomic market — not a lecture on soft-launch history. 10. **Typed search.** Production query `RUBY` / `EMBER` / `quartz` returns **no** gem options. Do not leak them under **Test pairs** on mainnet builds. LocalTerra keeps the divider (**P534-1**). 11. **Indexer JSON** may still list gem pairs for integrators / residual charts. dApp overlays the hide. Optional `exclude_test_pairs` on `route/solve` is in scope if frontend filtering is not enough to stop gem hops. Do not change `volume_quote_24h` wire format. 12. **a11y / CLS.** Same combobox contracts (#350 / #481 / #498). Filtering must not blank the trigger or shift layout when the current token is a hidden gem (clear to empty / first **economic** token). 13. **Logos.** Gems use blockies; economic tokens use tokenlist logos. Do not add gem artwork. Do not allowlist random logo URLs to “pretty up” gems. ## Relevant files | File | Role | |------|------| | [`frontend-dapp/src/utils/pairCatalogRank.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/pairCatalogRank.ts) | `GEM_SYMBOLS`, `isGemTokenId`, `isTestPair`, catalog sort | | [`frontend-dapp/src/utils/constants.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/constants.ts) | `SOFT_LAUNCH_MINTABLE_TOKENS`, `VITE_TOKEN_*`, `DEFAULT_NETWORK`, faucet | | [`frontend-dapp/src/utils/tokenSearchQuery.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/tokenSearchQuery.ts) | Swap empty browse / typed filter | | [`frontend-dapp/src/services/terraclassic/router.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/services/terraclassic/router.ts) | `getAllTokens`, `findRoute` | | [`frontend-dapp/src/pages/SwapPage.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/SwapPage.tsx) | Default pay/receive from `getAllTokens` | | [`frontend-dapp/src/components/trade/TokenSearchSelect.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/trade/TokenSearchSelect.tsx) | Swap combobox | | [`frontend-dapp/src/components/trade/PairSearchSelect.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/trade/PairSearchSelect.tsx) | Trade/Limits empty browse + Test pairs | | [`frontend-dapp/src/pages/TradePage.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/TradePage.tsx) | Auto-pick + market quote | | [`frontend-dapp/src/pages/PoolPage.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/PoolPage.tsx) + pool table | Default catalog still includes gems | | [`frontend-dapp/src/pages/ChartsPage.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/ChartsPage.tsx) | Pair menu | | [`frontend-dapp/src/utils/createPairTokenCatalog.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/createPairTokenCatalog.ts) | Gem append | | [`frontend-dapp/src/components/common/navItems.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/common/navItems.ts) + `Layout.tsx` | Mint nav **F11** | | [`frontend-dapp/src/pages/MintPage.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/MintPage.tsx) | Faucet UI | | [`deployments/mainnet-soft-launch/frontend.env.example`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/deployments/mainnet-soft-launch/frontend.env.example) | Coolify `VITE_FAUCET_*` / `VITE_TOKEN_*` | | Indexer `route/solve` | Gem hops in hybrid paths | | [`docs/frontend.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/docs/frontend.md) § Pair catalog rank, token search | Invariants **P534-*** | | [`skills/AGENTS_FRONTEND_PAIR_CATALOG_RANK.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/skills/AGENTS_FRONTEND_PAIR_CATALOG_RANK.md) | Agent playbook | | [`docs/runbooks/soft-launch-faucet.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/docs/runbooks/soft-launch-faucet.md) | **F9** pause / RemoveMinter | ## Recommended direction 1. **Single helper** (next to `isGemTokenId`): `retailExposeTestTokens()` = `VITE_NETWORK !== 'mainnet'` **or** `VITE_SHOW_TEST_TOKENS=true`. Production Coolify stays `VITE_NETWORK=mainnet` with the override unset. LocalTerra `VITE_NETWORK=local` unchanged. 2. **Hardcode the eight columbus-5 gem addresses** (and keep `GEM_SYMBOLS`) so hide-by-address works even if Coolify drops `VITE_TOKEN_*`. QUARTZ/PEARL must be in that address set. 3. **Filter once, reuse everywhere:** - Swap: filter `getAllTokens` (or a wrapper used by picker + default `from`/`to`) so empty browse, typed search, and initial selection are economic-only on production. - Pairs: filter `factoryPairs` / indexer rows fed to `PairSearchSelect`, `/pool` default+search, Charts menu. User column sort on `/pool` must also omit gems on production (otherwise Vol sort resurfaces RUBY/PEARL). - Create Pair: skip `gems:` append when `!retailExposeTestTokens()`. Custom paste of a gem CW20 still hits factory whitelist (honest) — do not special-case a “blocked” toast that teaches attackers the list; paste remains #382 checksum + code-id check. - Mint: Coolify unsets `VITE_FAUCET_ADDRESS`; `/mint` stays the existing unavailable path. 4. **Routing:** when `!retailExposeTestTokens()`, drop test pairs from the BFS graph and reject `route/solve` paths whose hops include a gem asset (client-side sufficient if the indexer cannot filter yet; add query flag if tests show leaks). 5. **Exit hatch:** if the connected wallet’s selected token / URL pair is a gem, keep that one instrument available (ticket + swap) until the user navigates away; do not put it back in the global list. 6. **Docs:** extend **P534** with production-hide invariants; Coolify runbook: do not bake faucet env on `dex.cl8y.com`; operator **F9** pause. `make verify-issue-<iid>` for the new gate. 7. **Out of scope:** migrating gem LP to CMM, changing factory whitelist, renaming tokens, new gem artwork, indexer pair-row deletion. ## Acceptance criteria - [ ] **A1.** Production build (`VITE_NETWORK=mainnet`, override unset): Swap empty YOU PAY / YOU RECEIVE lists **no** EMBER, CORAL, JADE, ONYX, RUBY, TOPAZ, QUARTZ, PEARL (or LocalTerra extras). Economic + wrap tokens remain. - [ ] **A2.** Typed search `RUBY`, `onyx`, `pearl`, `quartz`, `ember` on that build returns **no** gem rows. Address paste of a gem CW20 is not offered as a browse hit; deep-link/exit hatch documented. - [ ] **A3.** Trade / Limits / Charts / `/pool` empty browse and production search do **not** list the ten gem pairs. **Test pairs** divider is **absent** on production (nothing to group). - [ ] **A4.** Default Swap pay/receive and bare `/trade` auto-pick are economic (UST1 hub / wrap), never `tokens[0]` gem. - [ ] **A5.** Create Pair listed catalog does not append mintable gems on production. tokenlist CW20s (cLUNC, UST1, …) remain. - [ ] **A6.** Production Coolify: Mint nav hidden (`VITE_FAUCET_ADDRESS` unset). Runbook records faucet **Pause** (or explicit risk acceptance if left running). - [ ] **A7.** LocalTerra (`VITE_NETWORK=local`): gems **still** appear; **Test pairs** still shows; Mint still works when faucet env set; existing Playwright / swarm fixtures still find EMBER/CORAL. - [ ] **A8.** `VITE_SHOW_TEST_TOKENS=true` on a mainnet-network build restores gem browse (QA). Default production image does not set it. - [ ] **A9.** Portfolio / trader / history still render gem symbols and amounts for holders. - [ ] **A10.** Production Swap between two economic tokens never shows a gem hop on the Route row; quote fails closed rather than bridging RUBY. - [ ] **A11.** UST1 / cLUNC / cUSTC / USTR / CL8Y / vFDUSD never classified as gems (**U6**). - [ ] **A12.** Docs + playbook + `make verify-issue-<iid>` cover A1–A11. No always-on “test tokens removed” banner. ## Test plan — functional paths ### Unit / RTL | # | Path | Assert | |---|------|--------| | U1 | `retailExposeTestTokens` | `mainnet` + unset override → false; `local` → true; `mainnet` + `VITE_SHOW_TEST_TOKENS=true` → true | | U2 | Address set | All eight columbus-5 gem addrs are `isGemTokenId`; UST1 / wrap addrs are not | | U3 | `filterTokensByLocalSearch` production | Empty list has no gem ids; query `RUBY` empty; economic ids remain sorted | | U4 | Same helper local | EMBER present; **P534-7** rank still gems last | | U5 | Pair empty browse production | No gem `contract_addr`; no Test pairs label | | U6 | `/pool` production | Default and `sort=volume_24h` mock pages omit gem pairs | | U7 | Create Pair catalog | Production `gems: []` equivalent; local still appends env gems | | U8 | Swap default tokens | With mixed factory pairs, `from`/`to` are non-gem | | U9 | `findRoute` production graph | Economic→economic does not include gem intermediate; gem→gem only if exit hatch | | U10 | Regression | `#534` / `#542` / `#547` / `#481` tests still pass on **local** vitest env (`VITE_NETWORK=local`) | ### Playwright (5 workers; LocalTerra for local path; production path = unit + optional mainnet-env Vite) | # | Path | Assert | |---|------|--------| | P1 | Local Swap | EMBER still in YOU PAY (existing wrap-swap / token-select specs) | | P2 | Local Trade | Test pairs divider still appears when gems exist | | P3 | Production-mode Vite (`VITE_NETWORK=mainnet` against LocalTerra factory **or** fixture) | Swap listbox has no RUBY/ONYX/PEARL; has cLUNC/UST1 if pairs exist | | P4 | Production-mode Trade / Pool | No gem pair labels in empty browse | | P5 | Phone 390×844 Swap | Combobox CLS (#498) unchanged after filter | ### Manual QA (`dex.cl8y.com` after Coolify rebuild) 1. Open Swap → YOU PAY: only economic / wrap assets; no gemstone tickers or mystery blockies crowding the list. 2. Type `RUBY`, `EMBER`, `quartz`: no hits. 3. Trade / Pool / Charts: no gem pairs; no Test pairs heading. 4. More menu: no Mint. 5. If a test wallet still holds RUBY: Portfolio shows it; user can still navigate to the pair and sell. 6. LocalTerra `make dev`: gems still there; faucet still drips. ## Test plan — attack, hack, and abuse vectors | # | Vector | What to prove | |---|--------|----------------| | X1 | **Ticker collision** | A listed economic token whose display symbol is accidentally `RUBY` is **not** hidden; hide requires gem **address** (or known gem symbol **and** not in economic hub/tokenlist). Document the rule; unit-test UST1 vs `symbol=RUBY` gem addr. | | X2 | **Look-alike CW20** | Factory clone with `symbol=cLUNC` but gem code-id / unknown provenance stays subject to existing #311 / whitelist — this issue must not mark it as a “real” hub just to fill the picker. Do not invert the gem set into an allowlist of tickers. | | X3 | **Bypass via typed address** | Swap `onChange` still only emits ids in the **gated** options list (#481). Pasting `terra1…ruby` into search does not select a hidden gem unless the exit-hatch path is explicitly open. No `dangerouslySetInnerHTML`. | | X4 | **Deep-link phishing** | `/trade/<gem-pair>` must not look like UST1/USTR (identity copy = contracts, **T541-4**). Invalid / `javascript:` / HTML params still rejected (**T541-2**). Optional legacy notice must be static React text. | | X5 | **Route laundering** | Production hybrid quote must not hide a gem hop behind a sanitized “Route: UST1 → cUSTC” while executing EMBER in between. Displayed hops = executed hops (#158 / #501). Reject the quote if a gem hop is present. | | X6 | **Indexer injection** | `getPairs(q=RUBY)` may still return gem rows; UI must drop them on production **after** factory intersection. Do not trust indexer `is_test` if absent — client gem set is source of truth. | | X7 | **Coolify env mismatch** | Unsetting `VITE_TOKEN_*` must **not** re-list gems (hardcoded columbus-5 addrs). Unsetting faucet must hide Mint even if token envs remain. | | X8 | **Override abuse** | `VITE_SHOW_TEST_TOKENS` is a **build-arg**, not a runtime query (`?showGems=1` is forbidden — phishing / support-scam vector). | | X9 | **Faucet still live** | If UI hides Mint but faucet is unpaused, sybils can still `Drip` via LCD. Acceptance **A6** requires Pause or documented acceptance. Pause does not clear cooldowns (**F9**). | | X10 | **Hidden but executable** | Do not leave a hidden gem selected as default pay token (drain / surprise swap). If previous localStorage selected RUBY, production session resets to economic default. | | X11 | **DoS / haystack** | Filter must not scan unbounded indexer pages; keep factory cap + existing search limits (128-char query, 20 typed hits). | | X12 | **Portfolio wipe illusion** | Filtering pickers must not zero gem balances in the UI (looks like theft). History rows keep symbols as text. | | X13 | **CSP / logos** | No new remote logo hosts for gems. Blockies stay local canvas. | | X14 | **Create Pair custom paste** | Pasting a gem address must not skip `useCodeIdCheck` or pair-creation fee. Do not add a client-only “blocked token” that can be bypassed by LCD `CreatePair`. | ## Verification criteria ```bash make verify-issue-<iid> ``` Must prove: 1. Vitest: production vs local expose flag; gem address set; Swap/Trade/Pool/Create filters; UST1 not a gem; route helper rejects gem hops on production graph. 2. Docs/skills: production-hide invariants next to **P534**; Coolify faucet env + **F9**; LocalTerra exception. 3. Playwright: LocalTerra gems **still work**; production-mode picker has **no** RUBY/ONYX/PEARL (fixture or env). 4. Manual: `dex.cl8y.com` Swap screenshot no longer shows the gemstone list. Issue is **done** when a mainnet Coolify rebuild matches A1–A12 and LocalTerra regression (`make test-frontend` + relevant E2E) is green. Not done if gems are only moved below a divider, or if chain contracts were deleted “to be sure.”
PlasticDigits commented 2026-08-18 12:08:55 +00:00 (Migrated from gitlab.com)

marked as related to #534

marked as related to #534
PlasticDigits commented 2026-08-18 12:08:56 +00:00 (Migrated from gitlab.com)

marked as related to #473

marked as related to #473
PlasticDigits commented 2026-08-18 12:08:58 +00:00 (Migrated from gitlab.com)

marked as related to #542

marked as related to #542
PlasticDigits commented 2026-08-18 12:08:58 +00:00 (Migrated from gitlab.com)

marked as related to #547

marked as related to #547
PlasticDigits commented 2026-08-18 12:08:59 +00:00 (Migrated from gitlab.com)

marked as related to #489

marked as related to #489
PlasticDigits commented 2026-08-18 12:09:00 +00:00 (Migrated from gitlab.com)

marked as related to #501

marked as related to #501
PlasticDigits commented 2026-08-19 01:18:50 +00:00 (Migrated from gitlab.com)

mentioned in commit db6911f5bc

mentioned in commit db6911f5bcd28e4a88e34a46015c0b05eee1d05b
PlasticDigits commented 2026-08-19 01:19:21 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1094

mentioned in merge request !1094
PlasticDigits commented 2026-08-19 02:04:40 +00:00 (Migrated from gitlab.com)

mentioned in commit 8515da1925

mentioned in commit 8515da1925ffc4556a5c980a30292492e9b28b15
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-08-19 02:04:41 +00:00
PlasticDigits commented 2026-08-19 02:16:44 +00:00 (Migrated from gitlab.com)

Post-merge note (!1094 on main). P562 retail gem filter + gem-bridge quote reject is on main.

Remaining ops / QA (issue not done until these):

  • Coolify rebuild: VITE_NETWORK=mainnet, VITE_SHOW_TEST_TOKENS unset, VITE_FAUCET_ADDRESS unset (Mint nav).
  • Operator faucet Pause on columbus-5 (F9) or documented risk acceptance.
  • Playwright P1: LocalTerra Swap pay list still includes EMBER.
  • Production smoke: Swap/Trade/Pool/Charts/Create have no gemstone tickers.
**Post-merge note (!1094 on main).** P562 retail gem filter + gem-bridge quote reject is on `main`. Remaining ops / QA (issue not done until these): - Coolify rebuild: `VITE_NETWORK=mainnet`, `VITE_SHOW_TEST_TOKENS` unset, **`VITE_FAUCET_ADDRESS` unset** (Mint nav). - Operator **faucet Pause** on columbus-5 (F9) or documented risk acceptance. - Playwright P1: LocalTerra Swap pay list still includes EMBER. - Production smoke: Swap/Trade/Pool/Charts/Create have no gemstone tickers.
PlasticDigits commented 2026-08-19 02:28:19 +00:00 (Migrated from gitlab.com)

mentioned in commit 4f24107fa7

mentioned in commit 4f24107fa7b1a2e1fcb93bea0500c9590f71ce1f
PlasticDigits commented 2026-08-19 02:28:46 +00:00 (Migrated from gitlab.com)

Sanity after stack: unit/docs 8/8 PASS. Playwright P1 failed because e2e/issue-158-swap-route.spec.ts and the grep "pay picker lists every factory token including gems" are not in the tree. verify-issue-562.sh now SKIPs that rung instead of failing. Track adding the LocalTerra EMBER pay-list spec on the post-merge ops issue.

**Sanity after stack:** unit/docs **8/8 PASS**. Playwright P1 failed because `e2e/issue-158-swap-route.spec.ts` and the grep `"pay picker lists every factory token including gems"` are **not in the tree**. `verify-issue-562.sh` now SKIPs that rung instead of failing. Track adding the LocalTerra EMBER pay-list spec on the post-merge ops issue.
PlasticDigits commented 2026-08-19 02:28:46 +00:00 (Migrated from gitlab.com)

mentioned in issue #573

mentioned in issue #573
PlasticDigits commented 2026-08-19 02:28:58 +00:00 (Migrated from gitlab.com)

marked as related to #573

marked as related to #573
PlasticDigits commented 2026-08-20 05:23:05 +00:00 (Migrated from gitlab.com)

mentioned in issue #583

mentioned in issue #583
PlasticDigits commented 2026-08-21 11:29:51 +00:00 (Migrated from gitlab.com)

mentioned in issue #587

mentioned in issue #587
PlasticDigits commented 2026-08-22 10:59:13 +00:00 (Migrated from gitlab.com)

mentioned in issue #593

mentioned in issue #593
PlasticDigits commented 2026-08-22 11:02:34 +00:00 (Migrated from gitlab.com)

mentioned in issue #595

mentioned in issue #595
PlasticDigits commented 2026-08-22 12:26:37 +00:00 (Migrated from gitlab.com)

mentioned in issue #597

mentioned in issue #597
PlasticDigits commented 2026-08-23 03:05:42 +00:00 (Migrated from gitlab.com)

mentioned in issue #599

mentioned in issue #599
PlasticDigits commented 2026-08-24 03:15:46 +00:00 (Migrated from gitlab.com)

mentioned in issue #619

mentioned in issue #619
PlasticDigits commented 2026-08-25 01:55:13 +00:00 (Migrated from gitlab.com)

mentioned in issue #630

mentioned in issue #630
PlasticDigits commented 2026-08-25 01:55:34 +00:00 (Migrated from gitlab.com)

mentioned in issue #631

mentioned in issue #631
PlasticDigits commented 2026-08-25 01:55:37 +00:00 (Migrated from gitlab.com)

marked as related to #631

marked as related to #631
PlasticDigits commented 2026-08-25 01:57:09 +00:00 (Migrated from gitlab.com)

mentioned in issue #632

mentioned in issue #632
PlasticDigits commented 2026-08-25 06:54:25 +00:00 (Migrated from gitlab.com)

mentioned in issue #639

mentioned in issue #639
PlasticDigits commented 2026-08-26 03:06:33 +00:00 (Migrated from gitlab.com)

mentioned in issue #655

mentioned in issue #655
PlasticDigits commented 2026-08-26 03:06:36 +00:00 (Migrated from gitlab.com)

marked as related to #655

marked as related to #655
PlasticDigits commented 2026-08-26 03:08:08 +00:00 (Migrated from gitlab.com)

mentioned in issue #657

mentioned in issue #657
PlasticDigits commented 2026-08-26 04:11:20 +00:00 (Migrated from gitlab.com)

mentioned in issue #660

mentioned in issue #660
PlasticDigits commented 2026-08-26 04:12:49 +00:00 (Migrated from gitlab.com)

mentioned in issue #661

mentioned in issue #661
PlasticDigits commented 2026-08-26 04:13:29 +00:00 (Migrated from gitlab.com)

mentioned in issue #662

mentioned in issue #662
PlasticDigits commented 2026-08-26 04:15:27 +00:00 (Migrated from gitlab.com)

mentioned in issue #664

mentioned in issue #664
PlasticDigits commented 2026-08-27 01:00:19 +00:00 (Migrated from gitlab.com)

mentioned in issue #682

mentioned in issue #682
PlasticDigits commented 2026-08-27 01:00:29 +00:00 (Migrated from gitlab.com)

mentioned in issue #683

mentioned in issue #683
PlasticDigits commented 2026-08-27 06:03:02 +00:00 (Migrated from gitlab.com)

mentioned in issue #687

mentioned in issue #687
PlasticDigits commented 2026-08-27 11:52:21 +00:00 (Migrated from gitlab.com)

mentioned in issue #690

mentioned in issue #690
PlasticDigits commented 2026-08-28 05:22:09 +00:00 (Migrated from gitlab.com)

mentioned in issue #692

mentioned in issue #692
PlasticDigits commented 2026-08-31 04:56:53 +00:00 (Migrated from gitlab.com)

mentioned in issue #711

mentioned in issue #711
PlasticDigits commented 2026-08-31 04:56:55 +00:00 (Migrated from gitlab.com)

marked as related to #711

marked as related to #711
PlasticDigits commented 2026-08-31 05:36:04 +00:00 (Migrated from gitlab.com)

mentioned in issue #713

mentioned in issue #713
PlasticDigits commented 2026-08-31 16:08:49 +00:00 (Migrated from gitlab.com)

mentioned in issue #715

mentioned in issue #715
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#562
No description provided.