feat: /pool sortable table, UST1-first volume default, charts links, strip lectures #547

Closed
opened 2026-08-17 10:26:05 +00:00 by PlasticDigits · 26 comments
PlasticDigits commented 2026-08-17 10:26:05 +00:00 (Migrated from gitlab.com)

Summary

Rebuild /pool as a sortable table of pools (not a stack of cards), defaulting to UST1 markets first then 24h volume, with a Charts link on every row. Strip the page-chrome lectures (title, indexer/factory essays, pair-count trivia). Remove the unused Router-known filter. Make the How to add liquidity block fully dismissible.

Bundle these into one frontend issue. Do not split “table vs cards” vs “UST1 first” vs “sort carets” vs “charts links” vs “delete header copy” vs “dismiss how-to” vs “drop Router-known.”

Related: #489 (anti-cognitive-overload), #531 (opt-in LP how-to), #533 (one-sided add/withdraw), #534 (catalog rank — explicitly skipped /pool lists today), #112 (indexer vs factory list + Router-known filter), #541 (token identity / explorer), #476 / #537 (pair fee-tier chrome), #215 (indexer outage banner).

Current codebase

/pool is a human-facing page that currently reads like an indexer runbook.

Layer Behavior today
List PoolPage.tsx loads GET /api/v1/pairs (getPairs) with limit=20, default sort=symbol order=asc. Each row is a PoolCard: symbols, 24h vol, In router (factory) / Indexer only badges, PairTokenLinks, on-chain reserves, fee badge, Advanced two-sided provide/withdraw.
Sort UI Separate Sort MenuSelect (symbol / volume_24h / fee / created / id) and Order MenuSelect (asc/desc). Choosing volume forces order=desc. Carets are not on column headers (there are no columns).
Default rank #534 sortIndexerPairsByCatalog (UST1 hub first, gems last, human 24h volume) is used on Trade/Limits/Charts pickers. Playbook explicitly says do not reorder /pool card lists the user sorted by fee/created/id. Default pool list is A–Z symbol, so faucet gems and UST1 markets are interleaved by ticker.
Charts ChartsPage.tsx keeps selectedPairAddr in React state only. App.tsx has /charts with no :pairAddr. /trade/:pairAddr already deep-links Trade (which also embeds a chart). Pool cards have no Charts (or Trade) link.
Router-known Checkbox “Router-known (factory) only on this page” filters the current indexer page to factoryPairAddresses (#112). Product: unused. Tests in PoolPage.test.tsx assert it.
Header chrome Always-on: Liquidity Pools h2, “Browse pairs, compare fees…”, CL8Y eligibility note (pool-fee-discount-eligibility-note) + /tiers, List source: indexer vs factory paragraph + GitLab frontend.md link, indexer-vs-factory drift note, right-rail N pair(s) (indexer total) / indexed tokens / on-chain (factory, router graph). This is agent/ops copy (#489 invariant 9).
How-to (#531) PoolLpHowto.tsx: first-visit hint is dismissible (cl8y-dex-pool-lp-howto-hint-dismissed). The <details> “How to add liquidity” stays on the page forever. Footer / Portfolio still link /pool#lp-howto.
Retail provide OneSidedAddCard + OneSidedWithdrawCard sit above the list (#533). Keep them.
Live status (keep) Indexer outage banner (pool-market-data-outage-banner), fee-discount registry warning, pause/blacklist on provide, IL on Advanced provide. Pair-level fee CTA when unwired/unregistered (I14 / #537).
Volume format Cards already use formatQuoteVolume24h (quote decimals) — P534-4. Do not regress to formatNum(raw).

Why this is needed

  1. Cards do not scan. Users comparing volume / fee / pair name need a table. Separate Sort + Order dropdowns are a second UI for the same job; the caret belongs next to each sortable header.
  2. Default A–Z hides the launch markets. Same failure #534 fixed for pickers: UST1 pairs should lead; gems last. /pool was carved out; that carve-out is wrong for first paint.
  3. Charts are a dead-end away. /charts cannot be opened on a specific pool. Users who see a pool cannot jump to its tape.
  4. Header copy violates #489. “List source: indexer…”, factory counts, and the page title duplicate the nav. Humans do not need GitLab data-source essays to add liquidity. Agents already have docs/frontend.md § Liquidity pools list.
  5. Router-known is unused and only filters the current page (easy to think the whole catalog is factory-only). Remove it.
  6. How-to still lectures after hint dismiss. The <details> summary is always-on. Users asked for a dismiss on the how-to block itself; #lp-howto and footer must still be able to restore it.

Constraints / guardrails

  1. #489. Page chrome after this issue = controls + live status + CTAs. No always-on architecture, indexer-vs-factory, or “N indexed tokens” text. Do not move that essay into a permanent <details> on /pool either. Engineering docs stay in GitLab.
  2. Keep safety and provide flows. One-sided add/withdraw, Advanced two-sided, IL, pause, blacklist, gas gates, pre-sign summary, clickwrap, NFA, fee-registry outage banner, pair I14 fee chrome on the row (not a page lecture).
  3. Do not change pool math, wrap fees, or factory registration. Badges may become a compact column or icon; do not add a new on-chain verify per row (still O(1) set lookup from getAllPairsPaginated).
  4. Catalog rank vs pagination. Indexer GET /api/v1/pairs has no sort=catalog. Re-sorting only the current 20 is not “UST1 first” globally. Default view must make page 1 UST1-hub economic pairs (then volume), gems last — fetch a large enough window and/or client-paginate catalog order. Typed search stays indexer relevance / q (P534-6). User-chosen column sorts (volume, fee, created, name, id) use indexer sort/order and must not secretly re-apply catalog overlay (update the #534 playbook sentence that forbade /pool reorder — default catalog is in scope; user column sort is not overridden).
  5. Volume is human. formatQuoteVolume24h + quote decimals. Do not sort 18-dec raw against 6-dec raw in the catalog default (P534-3).
  6. Charts deep link. Add a real URL (/charts/:pairAddr and/or ?pair=) using the same Terra address rules as tradePairRoute.ts. Invalid / javascript: / HTML → no navigation (same spirit as T541-2). Link only; no window.open to untrusted hosts.
  7. How-to (#531). Dismissing hides hint and <details>. Persist (extend poolLpHowto.ts or a second key). Hash #lp-howto re-opens. Footer / Portfolio links still work. Copy stays in poolLpHowtoCopy.ts; no innerHTML; no APR. Update H531-7 (today: hint dismissible, details stay).
  8. Remove the page title “Liquidity Pools” and the subtitle. Nav already names Pool.
  9. Remove pool-fee-discount-eligibility-note from the header. Row-level unregistered CTA / fee badge stays (I12/I14).
  10. a11y. role="table" (or native <table>), aria-sort on the active column, keyboard-activatable headers, caret is not the only sort indicator. Light + dark. Do not cover one-sided CTAs with how-to (position: relative only).
  11. Themes / density. Reuse glass table patterns (TradesTable, portfolio tables). Mobile: horizontal scroll is OK; do not go back to stacked cards as the only layout without a documented exception.
  12. LocalTerra for smoke with real pairs; do not skip chain when asserting Charts deep-link against a factory pair.

Relevant files

File Role
frontend-dapp/src/pages/PoolPage.tsx Header chrome, sort dropdowns, Router-known, PoolCard list
frontend-dapp/src/pages/PoolPage.test.tsx List source / filter / badges tests (will change)
frontend-dapp/src/pages/ChartsPage.tsx Pair selection is local state — needs deep link
frontend-dapp/src/App.tsx /charts route
frontend-dapp/src/utils/tradePairRoute.ts Address validation pattern for Trade deep links
frontend-dapp/src/utils/pairCatalogRank.ts UST1 hub + human volume + gems last
frontend-dapp/src/utils/pairListBadges.ts Factory set for badges
frontend-dapp/src/utils/formatAmount.ts formatQuoteVolume24h
frontend-dapp/src/components/pool/PoolLpHowto.tsx Hint + always-on details
frontend-dapp/src/utils/poolLpHowto.ts Hint dismiss storage
frontend-dapp/src/components/pool/OneSidedAddCard.tsx / OneSidedWithdrawCard.tsx Keep
frontend-dapp/src/components/ui/PairTokenLinks.tsx Identity on row
docs/frontend.md § Liquidity pools list / pair catalog rank / retail copy Invariants to update
skills/AGENTS_FRONTEND_COPY_COGNITIVE_LOAD.md No lectures
skills/AGENTS_FRONTEND_PAIR_CATALOG_RANK.md Remove /pool exception
skills/AGENTS_FRONTEND_POOL_LP_HOWTO.md H531-7 dismiss rules
indexer/src/api/pairs.rs sort=id|fee|created|symbol|volume_24h|relevance
  1. Delete page header copy in PoolPage: no h2 “Liquidity Pools”, no browse subtitle, no list-source paragraph, no drift note, no indexer/factory/token counts, no header eligibility note. Search stays. Outage + registry warning stay.
  2. How-to: one dismiss control hides the whole #lp-howto section (hint + details). Persist. #lp-howto sets visible + opens <details>. Optional quiet “How to” text button if dismissed (not a paragraph).
  3. Remove Router-known checkbox and routerKnownOnly state. Drop empty-state copy that only exists for that filter.
  4. Replace PoolCard stack with a <table> (e.g. PoolPairsTable):
    • Columns (suggested): Pair (sortable), 24h vol (sortable), Fee (sortable), Created or TVL/reserves (sortable if data exists without N extra LCD calls on first paint — reserves today are per-card getPool; do not N+1 LCD on every row for default paint; show vol/fee from indexer; lazy-load reserves on expand or omit from default columns), Charts link, optional compact factory/indexer mark.
    • Header label + small caret immediately after the text for each sortable column; caret shows current column + direction. Click toggles asc/desc; clicking a new column sorts by that key (volume default desc; name default asc).
    • Remove the Sort/Order dropdowns.
    • Row expands or links to Advanced provide/withdraw without bringing back full cards as the list. Prefer expand-in-place or a single “Manage” disclosure so one-sided cards remain the retail add path.
    • Keep PairTokenLinks / identity (T541-*); do not wrap the pair name in an explorer <a>.
  5. Default sort: catalog rank (sortIndexerPairsByCatalog) so UST1 pairs first, then other economic hubs, human 24h volume within group, test pairs last. Implementation options (pick one, document in frontend.md):
    • Fetch a larger first window (limit well above 20) of sort=volume_24h&order=desc, client catalog-sort, client-paginate; or
    • Indexer sort=catalog only if this issue also ships indexer work (optional; do not block the table on a new API if a client window is enough for current pair count).
  6. Charts: Link to /charts/:pairAddr (mirror Trade). Charts page reads the param, validates bech32, selects that pair (fetch getPair if not on the current menu page — Charts already has needsPairFetch). Unknown/invalid: stay on /charts without executing scripts; no wallet prompt.
  7. Tests + docs: rewrite PoolPage.test.tsx assertions that require “List source” / pair counts / Router-known. Update #112 section in frontend.md (filter gone; badges optional). Update #534 playbook. make verify-issue-<iid>.

Acceptance criteria

  • AC1 — Table, not cards. /pool pair list is a table with sortable headers. No stacked PoolCard as the primary list.
  • AC2 — Caret-by-label. Each sortable header has a small caret next to the header text (not a separate Order dropdown). Only one column shows active direction; others show a neutral/inactive caret or none.
  • AC3 — Default UST1 first. First paint / default sort shows UST1-hub economic pairs before gems; within economic, catalog hub + human volume (P534-1–P534-4, P534-8). Not default symbol A–Z.
  • AC4 — Volume sort. User can sort by 24h volume via the Vol header (indexer volume_24h); formatted with formatQuoteVolume24h.
  • AC5 — Other sorts. Pair name, fee, created, and/or id work via headers when those indexer keys exist; user sort is not overwritten by catalog overlay.
  • AC6 — Charts link. Every row has a same-origin Charts control that opens that pair’s chart via a URL a user can share. Invalid addresses do not navigate to an attacker URL.
  • AC7 — No Router-known. Checkbox and filter logic gone. Tests that required it updated.
  • AC8 — How-to dismiss. Whole how-to section (not only the hint) can be dismissed and stays dismissed on reload; #lp-howto restores it. Footer/Portfolio still land on the how-to.
  • AC9 — Header lectures gone. No “Liquidity Pools” title, no browse blurb, no list-source/indexer/factory counts, no drift note, no header eligibility essay. Search + one-sided cards + live outage/registry banners remain.
  • AC10 — Safety unchanged. Provide/withdraw, IL, pause, blacklist, I14 fee row chrome, #541 identity, #489 (no new lectures).
  • AC11 — Verify. make verify-issue-<iid> + RTL + Playwright smoke (5 workers).

Test plan (all paths)

IA / copy

# Path Assert
C1 /pool first visit No Liquidity Pools heading; no “List source”; no “indexed tokens”; no “factory, router graph”; no drift note; no pool-fee-discount-eligibility-note
C2 Search Still filters via indexer q; empty → catalog default
C3 How-to visible Dismiss control on the how-to section; after dismiss, no “How to add liquidity” details; one-sided Add still visible
C4 Reload after dismiss How-to stays hidden
C5 /pool#lp-howto How-to shown + details open even if previously dismissed
C6 Footer “Add liquidity” Same as C5
C7 Router-known Control absent; no pool-filter-router

Sort / table

# Path Assert
S1 Default Page 1 leads with UST1 pair(s) when those pairs exist in the dataset (mock + LocalTerra)
S2 Click Vol getPairs called with sort=volume_24h; caret on Vol; gems may interleave by volume (catalog overlay off)
S3 Click Vol again Toggles order asc↔desc; caret flips
S4 Click Pair sort=symbol (or documented name key); caret moves; Vol caret inactive
S5 Fee / created / id Same pattern if columns exist
S6 Pagination Next/prev still work; sort params preserved
S7 Volume format 18-dec quote does not show T compact junk (P534-4)
S8 Keyboard Header is a button (or th+button); Enter/Space sorts; aria-sort

Charts

# Path Assert
H1 Row Charts Link href /charts/<pairAddr> (or documented query)
H2 Open Charts Selected pair matches row; chart query uses that address
H3 Invalid param /charts/not-a-terra or /charts/<script> → no XSS; fallback empty/default pair; no javascript:
H4 Unknown but valid terra1 Charts does not crash; optional unknown notice (Trade-style) without factory-clone lectures

Provide / identity (regression)

# Path Assert
R1 One-sided add/withdraw Still above the table; #533 tests green
R2 Advanced two-sided Reachable per row or documented Manage expand
R3 PairTokenLinks Copy + explorer on legs + pair; explorer getExplorerAddressUrl only
R4 Fee I14 Unwired pair: no phantom strikethrough; wired unregistered: row CTA not header essay
R5 Indexer 502 pool-market-data-outage-banner; no VITE_INDEXER_URL leak (#215)
R6 Light + dark Table + carets readable

Unit / RTL

  1. Rewrite PoolPage.test.tsx: default catalog order with mocked UST1 + gem pairs; no list-source strings; no Router-known; table role; header sort calls getPairs with expected sort/order.
  2. PoolLpHowto.test.tsx: dismiss hides details; hash reopens; storage key documented.
  3. Charts deep-link tests (new): param parse, invalid rejected.
  4. pairCatalogRank still covers UST1 vs gems (may add a pool-list helper test).
  5. Existing fee-discount registry banner tests still pass.

Playwright (5 workers, smoke; tx not required unless provide expand is asserted on-chain)

# Path Assert
P1 /pool desktop Table visible; no header essay; how-to dismissible
P2 Click Vol header URL or network: sort=volume_24h; caret updates
P3 Charts from first row Lands on /charts/…; pair selected
P4 Tablet 820×1180 Table scrollable; one-sided CTAs not covered
P5 Phone 390×844 Same; bottom nav Pool still works
P6 #lp-howto Opens how-to after dismiss

Manual QA

  1. Fresh profile: /pool should look like a tool (search + add + table), not a protocol README.
  2. Confirm UST1/cUSTC, UST1/USTR, cLUNC/UST1 are at the top of default list when indexed.
  3. Confirm Router-known is gone and gems still appear (last on default).
  4. Share a Charts URL from a pool row; open in a new tab.

Test plan — attack, hack, and abuse vectors

# Vector What to prove
A1 XSS via pair deep link Charts/Pool links never use unsanitized href. javascript:, data:, HTML, non-bech32 → no navigation / no dangerouslySetInnerHTML.
A2 Open redirect Charts Link is same-origin path only; no https://evil from indexer website / logo_url (T541-7).
A3 Look-alike pair Charts link uses pair contract address, not display symbol. Identity copy payload is contract/denom (T541-4).
A4 Indexer only / fake pair Row can still link Charts for an indexer-only address; provide/swap must not imply factory routing. Do not resurrect Router-known as the only warning — compact mark or omit; never execute swap from this table.
A5 Sort param injection UI only sends known IndexerPairSort keys; ignore crafted query strings if you add URL state.
A6 Prototype pollution / storage How-to dismiss uses the existing string key '1'/'0'; do not JSON.parse untrusted localStorage into React nodes.
A7 Clickjacking / overlay How-to and table headers must not use position:fixed over wallet/clickwrap/provide (H531 in-flow).
A8 N+1 LCD DoS Default table paint must not getPool/getPairFeeConfig for every row on a large page (cards do this today — fix in the table design: indexer fields first; LCD on expand).
A9 Factory fetch cap Badge/set still capped (FACTORY_PAIRS_MAX_FOR_POOL_LIST); missing factory membership ≠ “safe to hide.” Do not filter the list by factory by default (that was Router-known).
A10 Outage copy leak Failed getPairs still retail banner; no host:port / env names.
A11 Fee chrome lie Removing header eligibility note must not advertise discounts on unwired pairs (I14).
A12 CSP / innerHTML How-to stays static React strings.

Verification criteria

  1. make verify-issue-<iid> fails if: “List source”, “Router-known”, pool-fee-discount-eligibility-note, or h2 Liquidity Pools still exist on PoolPage.tsx; how-to details remain undismissable; PoolCard is still the list; Charts route cannot take a pair address.
  2. RTL: default catalog order with UST1 before gems; header sort; how-to dismiss + hash restore; Charts Link href.
  3. Playwright P1–P6 green (5 workers).
  4. docs/frontend.md + skills (#489, #531 H531-7, #534 /pool exception removed, #112 filter removed) match the UI.
  5. make test-frontend scoped Pool/Charts/how-to/catalog; no regression on #533 / #537 / #541 tests.
  6. Light + dark eyeball: caret next to header text, not a remote Order dropdown.

Out of scope

  • Changing indexer JSON volume_quote_24h (still raw).
  • Pool provide math, one-sided zap, wrap fees.
  • Building the range-ladder MM (separate investigation issue).
  • Replacing /charts canvas or #524/#543 invert math.
  • Protocol factory/router AddressRow clones on /pool.
## Summary Rebuild `/pool` as a **sortable table of pools** (not a stack of cards), defaulting to **UST1 markets first** then **24h volume**, with a **Charts** link on every row. Strip the **page-chrome lectures** (title, indexer/factory essays, pair-count trivia). Remove the unused **Router-known** filter. Make the **How to add liquidity** block **fully dismissible**. Bundle these into **one** frontend issue. Do **not** split “table vs cards” vs “UST1 first” vs “sort carets” vs “charts links” vs “delete header copy” vs “dismiss how-to” vs “drop Router-known.” Related: [#489](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/489) (anti-cognitive-overload), [#531](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/531) (opt-in LP how-to), [#533](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/533) (one-sided add/withdraw), [#534](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/534) (catalog rank — **explicitly skipped `/pool` lists** today), [#112](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/112) (indexer vs factory list + Router-known filter), [#541](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/541) (token identity / explorer), [#476](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/476) / [#537](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/537) (pair fee-tier chrome), [#215](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/215) (indexer outage banner). ## Current codebase `/pool` is a **human-facing** page that currently reads like an **indexer runbook**. | Layer | Behavior today | |-------|----------------| | **List** | [`PoolPage.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/PoolPage.tsx) loads `GET /api/v1/pairs` (`getPairs`) with `limit=20`, default **`sort=symbol` `order=asc`**. Each row is a **`PoolCard`**: symbols, 24h vol, **In router (factory)** / **Indexer only** badges, `PairTokenLinks`, on-chain reserves, fee badge, Advanced two-sided provide/withdraw. | | **Sort UI** | Separate **Sort** `MenuSelect` (`symbol` / `volume_24h` / `fee` / `created` / `id`) and **Order** `MenuSelect` (asc/desc). Choosing volume forces `order=desc`. Carets are **not** on column headers (there are no columns). | | **Default rank** | [#534](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/534) `sortIndexerPairsByCatalog` (UST1 hub first, gems last, human 24h volume) is used on Trade/Limits/Charts **pickers**. Playbook **explicitly says do not reorder `/pool` card lists** the user sorted by fee/created/id. Default pool list is **A–Z symbol**, so faucet gems and UST1 markets are interleaved by ticker. | | **Charts** | [`ChartsPage.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/ChartsPage.tsx) keeps `selectedPairAddr` in **React state only**. [`App.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/App.tsx) has `/charts` with **no** `:pairAddr`. `/trade/:pairAddr` already deep-links Trade (which also embeds a chart). Pool cards have **no** Charts (or Trade) link. | | **Router-known** | Checkbox “Router-known (factory) only on this page” filters the **current indexer page** to `factoryPairAddresses` ([#112](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/112)). Product: unused. Tests in `PoolPage.test.tsx` assert it. | | **Header chrome** | Always-on: **Liquidity Pools** `h2`, “Browse pairs, compare fees…”, CL8Y eligibility note (`pool-fee-discount-eligibility-note`) + `/tiers`, **List source:** indexer vs factory paragraph + GitLab `frontend.md` link, indexer-vs-factory **drift note**, right-rail **N pair(s) (indexer total)** / **indexed tokens** / **on-chain (factory, router graph)**. This is agent/ops copy ([#489](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/489) invariant 9). | | **How-to ([#531](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/531))** | [`PoolLpHowto.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/pool/PoolLpHowto.tsx): first-visit **hint** is dismissible (`cl8y-dex-pool-lp-howto-hint-dismissed`). The **`<details>` “How to add liquidity”** stays on the page forever. Footer / Portfolio still link `/pool#lp-howto`. | | **Retail provide** | [`OneSidedAddCard`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/pool/OneSidedAddCard.tsx) + [`OneSidedWithdrawCard`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/pool/OneSidedWithdrawCard.tsx) sit **above** the list ([#533](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/533)). Keep them. | | **Live status (keep)** | Indexer outage banner (`pool-market-data-outage-banner`), fee-discount **registry** warning, pause/blacklist on provide, IL on Advanced provide. Pair-level fee CTA when unwired/unregistered (**I14** / [#537](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/537)). | | **Volume format** | Cards already use `formatQuoteVolume24h` (quote decimals) — **P534-4**. Do not regress to `formatNum(raw)`. | ## Why this is needed 1. **Cards do not scan.** Users comparing volume / fee / pair name need a **table**. Separate Sort + Order dropdowns are a second UI for the same job; the caret belongs **next to each sortable header**. 2. **Default A–Z hides the launch markets.** Same failure [#534](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/534) fixed for pickers: UST1 pairs should lead; gems last. `/pool` was carved out; that carve-out is wrong for first paint. 3. **Charts are a dead-end away.** `/charts` cannot be opened on a specific pool. Users who see a pool cannot jump to its tape. 4. **Header copy violates [#489](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/489).** “List source: indexer…”, factory counts, and the page title duplicate the nav. Humans do not need GitLab data-source essays to add liquidity. Agents already have `docs/frontend.md` § Liquidity pools list. 5. **Router-known is unused** and only filters the current page (easy to think the whole catalog is factory-only). Remove it. 6. **How-to still lectures after hint dismiss.** The `<details>` summary is always-on. Users asked for a **dismiss** on the how-to block itself; `#lp-howto` and footer must still be able to restore it. ## Constraints / guardrails 1. **#489.** Page chrome after this issue = **controls + live status + CTAs**. No always-on architecture, indexer-vs-factory, or “N indexed tokens” text. Do **not** move that essay into a permanent `<details>` on `/pool` either. Engineering docs stay in GitLab. 2. **Keep safety and provide flows.** One-sided add/withdraw, Advanced two-sided, IL, pause, blacklist, gas gates, pre-sign summary, clickwrap, NFA, fee-registry **outage** banner, pair **I14** fee chrome on the **row** (not a page lecture). 3. **Do not change pool math, wrap fees, or factory registration.** Badges may become a compact column or icon; do not add a new on-chain verify per row (still O(1) set lookup from `getAllPairsPaginated`). 4. **Catalog rank vs pagination.** Indexer `GET /api/v1/pairs` has **no** `sort=catalog`. Re-sorting **only the current 20** is not “UST1 first” globally. Default view must make **page 1** UST1-hub economic pairs (then volume), gems last — fetch a large enough window and/or client-paginate catalog order. Typed **search** stays indexer `relevance` / `q` (**P534-6**). User-chosen column sorts (volume, fee, created, name, id) use indexer `sort`/`order` and **must not** secretly re-apply catalog overlay (update the #534 playbook sentence that forbade `/pool` reorder — default catalog **is** in scope; user column sort is not overridden). 5. **Volume is human.** `formatQuoteVolume24h` + quote decimals. Do not sort 18-dec raw against 6-dec raw in the catalog default (**P534-3**). 6. **Charts deep link.** Add a real URL (`/charts/:pairAddr` and/or `?pair=`) using the same Terra address rules as [`tradePairRoute.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/tradePairRoute.ts). Invalid / `javascript:` / HTML → no navigation (same spirit as **T541-2**). `Link` only; no `window.open` to untrusted hosts. 7. **How-to ([#531](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/531)).** Dismissing hides **hint and `<details>`**. Persist (extend `poolLpHowto.ts` or a second key). Hash `#lp-howto` **re-opens**. Footer / Portfolio links still work. Copy stays in `poolLpHowtoCopy.ts`; no `innerHTML`; no APR. Update **H531-7** (today: hint dismissible, details stay). 8. **Remove the page title** “Liquidity Pools” and the subtitle. Nav already names Pool. 9. **Remove** `pool-fee-discount-eligibility-note` from the **header**. Row-level unregistered CTA / fee badge stays (**I12**/**I14**). 10. **a11y.** `role="table"` (or native `<table>`), `aria-sort` on the active column, keyboard-activatable headers, caret is not the only sort indicator. Light + dark. Do not cover one-sided CTAs with how-to (`position: relative` only). 11. **Themes / density.** Reuse glass table patterns (`TradesTable`, portfolio tables). Mobile: horizontal scroll is OK; do not go back to stacked cards as the only layout without a documented exception. 12. **LocalTerra** for smoke with real pairs; do not skip chain when asserting Charts deep-link against a factory pair. ## Relevant files | File | Role | |------|------| | [`frontend-dapp/src/pages/PoolPage.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/PoolPage.tsx) | Header chrome, sort dropdowns, Router-known, `PoolCard` list | | [`frontend-dapp/src/pages/PoolPage.test.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/PoolPage.test.tsx) | List source / filter / badges tests (will change) | | [`frontend-dapp/src/pages/ChartsPage.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/ChartsPage.tsx) | Pair selection is local state — needs deep link | | [`frontend-dapp/src/App.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/App.tsx) | `/charts` route | | [`frontend-dapp/src/utils/tradePairRoute.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/tradePairRoute.ts) | Address validation pattern for Trade deep links | | [`frontend-dapp/src/utils/pairCatalogRank.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/pairCatalogRank.ts) | UST1 hub + human volume + gems last | | [`frontend-dapp/src/utils/pairListBadges.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/pairListBadges.ts) | Factory set for badges | | [`frontend-dapp/src/utils/formatAmount.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/formatAmount.ts) | `formatQuoteVolume24h` | | [`frontend-dapp/src/components/pool/PoolLpHowto.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/pool/PoolLpHowto.tsx) | Hint + always-on details | | [`frontend-dapp/src/utils/poolLpHowto.ts`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/utils/poolLpHowto.ts) | Hint dismiss storage | | [`frontend-dapp/src/components/pool/OneSidedAddCard.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/pool/OneSidedAddCard.tsx) / `OneSidedWithdrawCard.tsx` | Keep | | [`frontend-dapp/src/components/ui/PairTokenLinks.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/ui/PairTokenLinks.tsx) | Identity on row | | [`docs/frontend.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/docs/frontend.md) § Liquidity pools list / pair catalog rank / retail copy | Invariants to update | | [`skills/AGENTS_FRONTEND_COPY_COGNITIVE_LOAD.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/skills/AGENTS_FRONTEND_COPY_COGNITIVE_LOAD.md) | No lectures | | [`skills/AGENTS_FRONTEND_PAIR_CATALOG_RANK.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/skills/AGENTS_FRONTEND_PAIR_CATALOG_RANK.md) | Remove `/pool` exception | | [`skills/AGENTS_FRONTEND_POOL_LP_HOWTO.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/skills/AGENTS_FRONTEND_POOL_LP_HOWTO.md) | H531-7 dismiss rules | | [`indexer/src/api/pairs.rs`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/indexer/src/api/pairs.rs) | `sort=id\|fee\|created\|symbol\|volume_24h\|relevance` | ## Recommended direction 1. **Delete page header copy** in `PoolPage`: no `h2` “Liquidity Pools”, no browse subtitle, no list-source paragraph, no drift note, no indexer/factory/token counts, no header eligibility note. Search stays. Outage + registry warning stay. 2. **How-to:** one dismiss control hides the whole `#lp-howto` section (hint + details). Persist. `#lp-howto` sets visible + opens `<details>`. Optional quiet “How to” text button if dismissed (not a paragraph). 3. **Remove** Router-known checkbox and `routerKnownOnly` state. Drop empty-state copy that only exists for that filter. 4. **Replace `PoolCard` stack** with a `<table>` (e.g. `PoolPairsTable`): - Columns (suggested): **Pair** (sortable), **24h vol** (sortable), **Fee** (sortable), **Created** or **TVL/reserves** (sortable if data exists without N extra LCD calls on first paint — reserves today are per-card `getPool`; **do not** N+1 LCD on every row for default paint; show vol/fee from indexer; lazy-load reserves on expand or omit from default columns), **Charts** link, optional compact factory/indexer mark. - Header label + **small caret** immediately after the text for each sortable column; caret shows current column + direction. Click toggles asc/desc; clicking a new column sorts by that key (volume default desc; name default asc). - Remove the Sort/Order dropdowns. - Row expands or links to Advanced provide/withdraw **without** bringing back full cards as the list. Prefer expand-in-place or a single “Manage” disclosure so one-sided cards remain the retail add path. - Keep `PairTokenLinks` / identity (**T541-***); do not wrap the pair name in an explorer `<a>`. 5. **Default sort:** catalog rank (`sortIndexerPairsByCatalog`) so **UST1 pairs first**, then other economic hubs, **human 24h volume** within group, **test pairs last**. Implementation options (pick one, document in `frontend.md`): - Fetch a larger first window (`limit` well above 20) of `sort=volume_24h&order=desc`, client catalog-sort, client-paginate; or - Indexer `sort=catalog` **only if** this issue also ships indexer work (optional; do not block the table on a new API if a client window is enough for current pair count). 6. **Charts:** `Link` to `/charts/:pairAddr` (mirror Trade). Charts page reads the param, validates bech32, selects that pair (fetch `getPair` if not on the current menu page — Charts already has `needsPairFetch`). Unknown/invalid: stay on `/charts` without executing scripts; no wallet prompt. 7. **Tests + docs:** rewrite `PoolPage.test.tsx` assertions that require “List source” / pair counts / Router-known. Update #112 section in `frontend.md` (filter gone; badges optional). Update #534 playbook. `make verify-issue-<iid>`. ## Acceptance criteria - [ ] **AC1 — Table, not cards.** `/pool` pair list is a table with sortable headers. No stacked `PoolCard` as the primary list. - [ ] **AC2 — Caret-by-label.** Each sortable header has a small caret **next to the header text** (not a separate Order dropdown). Only one column shows active direction; others show a neutral/inactive caret or none. - [ ] **AC3 — Default UST1 first.** First paint / default sort shows UST1-hub economic pairs before gems; within economic, catalog hub + human volume (**P534-1–P534-4**, **P534-8**). Not default `symbol` A–Z. - [ ] **AC4 — Volume sort.** User can sort by 24h volume via the **Vol** header (indexer `volume_24h`); formatted with `formatQuoteVolume24h`. - [ ] **AC5 — Other sorts.** Pair name, fee, created, and/or id work via headers when those indexer keys exist; user sort is **not** overwritten by catalog overlay. - [ ] **AC6 — Charts link.** Every row has a same-origin Charts control that opens that pair’s chart via a **URL** a user can share. Invalid addresses do not navigate to an attacker URL. - [ ] **AC7 — No Router-known.** Checkbox and filter logic gone. Tests that required it updated. - [ ] **AC8 — How-to dismiss.** Whole how-to section (not only the hint) can be dismissed and stays dismissed on reload; `#lp-howto` restores it. Footer/Portfolio still land on the how-to. - [ ] **AC9 — Header lectures gone.** No “Liquidity Pools” title, no browse blurb, no list-source/indexer/factory counts, no drift note, no header eligibility essay. Search + one-sided cards + live outage/registry banners remain. - [ ] **AC10 — Safety unchanged.** Provide/withdraw, IL, pause, blacklist, I14 fee row chrome, #541 identity, #489 (no new lectures). - [ ] **AC11 — Verify.** `make verify-issue-<iid>` + RTL + Playwright smoke (5 workers). ## Test plan (all paths) ### IA / copy | # | Path | Assert | |---|------|--------| | C1 | `/pool` first visit | No `Liquidity Pools` heading; no “List source”; no “indexed tokens”; no “factory, router graph”; no drift note; no `pool-fee-discount-eligibility-note` | | C2 | Search | Still filters via indexer `q`; empty → catalog default | | C3 | How-to visible | Dismiss control on the how-to **section**; after dismiss, no “How to add liquidity” details; one-sided Add still visible | | C4 | Reload after dismiss | How-to stays hidden | | C5 | `/pool#lp-howto` | How-to shown + details open even if previously dismissed | | C6 | Footer “Add liquidity” | Same as C5 | | C7 | Router-known | Control absent; no `pool-filter-router` | ### Sort / table | # | Path | Assert | |---|------|--------| | S1 | Default | Page 1 leads with UST1 pair(s) when those pairs exist in the dataset (mock + LocalTerra) | | S2 | Click **Vol** | `getPairs` called with `sort=volume_24h`; caret on Vol; gems may interleave by volume (catalog overlay **off**) | | S3 | Click **Vol** again | Toggles `order` asc↔desc; caret flips | | S4 | Click **Pair** | `sort=symbol` (or documented name key); caret moves; Vol caret inactive | | S5 | Fee / created / id | Same pattern if columns exist | | S6 | Pagination | Next/prev still work; sort params preserved | | S7 | Volume format | 18-dec quote does not show `T` compact junk (**P534-4**) | | S8 | Keyboard | Header is a `button` (or `th`+button); Enter/Space sorts; `aria-sort` | ### Charts | # | Path | Assert | |---|------|--------| | H1 | Row Charts | `Link` href `/charts/<pairAddr>` (or documented query) | | H2 | Open Charts | Selected pair matches row; chart query uses that address | | H3 | Invalid param | `/charts/not-a-terra` or `/charts/<script>` → no XSS; fallback empty/default pair; no `javascript:` | | H4 | Unknown but valid terra1 | Charts does not crash; optional unknown notice (Trade-style) without factory-clone lectures | ### Provide / identity (regression) | # | Path | Assert | |---|------|--------| | R1 | One-sided add/withdraw | Still above the table; #533 tests green | | R2 | Advanced two-sided | Reachable per row or documented Manage expand | | R3 | `PairTokenLinks` | Copy + explorer on legs + pair; explorer `getExplorerAddressUrl` only | | R4 | Fee I14 | Unwired pair: no phantom strikethrough; wired unregistered: row CTA not header essay | | R5 | Indexer 502 | `pool-market-data-outage-banner`; no `VITE_INDEXER_URL` leak ([#215](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/215)) | | R6 | Light + dark | Table + carets readable | ### Unit / RTL 1. Rewrite `PoolPage.test.tsx`: default catalog order with mocked UST1 + gem pairs; no list-source strings; no Router-known; table role; header sort calls `getPairs` with expected `sort`/`order`. 2. `PoolLpHowto.test.tsx`: dismiss hides details; hash reopens; storage key documented. 3. Charts deep-link tests (new): param parse, invalid rejected. 4. `pairCatalogRank` still covers UST1 vs gems (may add a pool-list helper test). 5. Existing fee-discount registry banner tests still pass. ### Playwright (5 workers, smoke; tx not required unless provide expand is asserted on-chain) | # | Path | Assert | |---|------|--------| | P1 | `/pool` desktop | Table visible; no header essay; how-to dismissible | | P2 | Click Vol header | URL or network: `sort=volume_24h`; caret updates | | P3 | Charts from first row | Lands on `/charts/…`; pair selected | | P4 | Tablet 820×1180 | Table scrollable; one-sided CTAs not covered | | P5 | Phone 390×844 | Same; bottom nav Pool still works | | P6 | `#lp-howto` | Opens how-to after dismiss | ### Manual QA 1. Fresh profile: `/pool` should look like a tool (search + add + table), not a protocol README. 2. Confirm UST1/cUSTC, UST1/USTR, cLUNC/UST1 are at the top of default list when indexed. 3. Confirm Router-known is gone and gems still appear (last on default). 4. Share a Charts URL from a pool row; open in a new tab. ## Test plan — attack, hack, and abuse vectors | # | Vector | What to prove | |---|--------|----------------| | A1 | **XSS via pair deep link** | Charts/Pool links never use unsanitized `href`. `javascript:`, `data:`, HTML, non-bech32 → no navigation / no `dangerouslySetInnerHTML`. | | A2 | **Open redirect** | Charts `Link` is same-origin path only; no `https://evil` from indexer `website` / `logo_url` (**T541-7**). | | A3 | **Look-alike pair** | Charts link uses **pair contract** address, not display symbol. Identity copy payload is contract/denom (**T541-4**). | | A4 | **Indexer only / fake pair** | Row can still link Charts for an indexer-only address; provide/swap must not imply factory routing. Do not resurrect Router-known as the only warning — compact mark or omit; never execute swap from this table. | | A5 | **Sort param injection** | UI only sends known `IndexerPairSort` keys; ignore crafted query strings if you add URL state. | | A6 | **Prototype pollution / storage** | How-to dismiss uses the existing string key `'1'`/`'0'`; do not `JSON.parse` untrusted localStorage into React nodes. | | A7 | **Clickjacking / overlay** | How-to and table headers must not use `position:fixed` over wallet/clickwrap/provide (**H531** in-flow). | | A8 | **N+1 LCD DoS** | Default table paint must not `getPool`/`getPairFeeConfig` for every row on a large page (cards do this today — **fix** in the table design: indexer fields first; LCD on expand). | | A9 | **Factory fetch cap** | Badge/set still capped (`FACTORY_PAIRS_MAX_FOR_POOL_LIST`); missing factory membership ≠ “safe to hide.” Do not filter the list by factory by default (that was Router-known). | | A10 | **Outage copy leak** | Failed `getPairs` still retail banner; no host:port / env names. | | A11 | **Fee chrome lie** | Removing header eligibility note must not advertise discounts on unwired pairs (I14). | | A12 | **CSP / innerHTML** | How-to stays static React strings. | ## Verification criteria 1. `make verify-issue-<iid>` fails if: “List source”, “Router-known”, `pool-fee-discount-eligibility-note`, or `h2` Liquidity Pools still exist on `PoolPage.tsx`; how-to details remain undismissable; `PoolCard` is still the list; Charts route cannot take a pair address. 2. RTL: default catalog order with UST1 before gems; header sort; how-to dismiss + hash restore; Charts `Link` href. 3. Playwright P1–P6 green (5 workers). 4. `docs/frontend.md` + skills (#489, #531 H531-7, #534 `/pool` exception removed, #112 filter removed) match the UI. 5. `make test-frontend` scoped Pool/Charts/how-to/catalog; no regression on #533 / #537 / #541 tests. 6. Light + dark eyeball: caret next to header text, not a remote Order dropdown. ## Out of scope - Changing indexer JSON `volume_quote_24h` (still raw). - Pool provide math, one-sided zap, wrap fees. - Building the range-ladder MM (separate investigation issue). - Replacing `/charts` canvas or #524/#543 invert math. - Protocol factory/router `AddressRow` clones on `/pool`.
PlasticDigits commented 2026-08-17 10:26:07 +00:00 (Migrated from gitlab.com)

marked as related to #489

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

marked as related to #531

marked as related to #531
PlasticDigits commented 2026-08-17 10:26:09 +00:00 (Migrated from gitlab.com)

marked as related to #534

marked as related to #534
PlasticDigits commented 2026-08-17 10:26:09 +00:00 (Migrated from gitlab.com)

marked as related to #112

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

marked as related to #541

marked as related to #541
PlasticDigits commented 2026-08-17 10:26:11 +00:00 (Migrated from gitlab.com)

marked as related to #533

marked as related to #533
PlasticDigits commented 2026-08-17 12:01:25 +00:00 (Migrated from gitlab.com)

mentioned in commit f9f0387af0

mentioned in commit f9f0387af03554f3cb839eacaf3257dac101f69e
PlasticDigits commented 2026-08-17 12:01:46 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1077

mentioned in merge request !1077
PlasticDigits commented 2026-08-17 13:40:26 +00:00 (Migrated from gitlab.com)

mentioned in commit 7524010089

mentioned in commit 752401008905963fceb20fd2a839303016363c0c
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-08-17 13:40:27 +00:00
PlasticDigits commented 2026-08-17 13:49:00 +00:00 (Migrated from gitlab.com)

Merged as !1077 onto main (75240100) after resolving conflicts with !1076 (#548): Makefile keeps both verify-issue-547 and verify-issue-548; ChartsPage keeps USD overview strip and /charts/:pairAddr deep links.

Remaining / post-merge:

  • Created column cells are — (documented P547-4): indexer list JSON has no timestamp; header sort still uses indexer created.
  • A8 is enforced by component split + verify grep, not an RTL “no getPool before Manage” assertion.
  • Charts H2 RTL (valid :pairAddr) logs React Query undefined for indexer-pair-one (test passes).
  • Manual QA from the issue (fresh /pool layout, UST1-hub first, gems last, shareable Charts URL, light+dark carets) is still open.

Tracking: new post-merge issue for remaining manual QA.

Merged as !1077 onto `main` (`75240100`) after resolving conflicts with !1076 (#548): Makefile keeps both `verify-issue-547` and `verify-issue-548`; `ChartsPage` keeps USD overview strip **and** `/charts/:pairAddr` deep links. Remaining / post-merge: - **Created column** cells are `—` (documented P547-4): indexer list JSON has no timestamp; header sort still uses indexer `created`. - **A8** is enforced by component split + verify grep, not an RTL “no `getPool` before Manage” assertion. - **Charts H2** RTL (`valid :pairAddr`) logs React Query `undefined` for `indexer-pair-one` (test passes). - **Manual QA** from the issue (fresh `/pool` layout, UST1-hub first, gems last, shareable Charts URL, light+dark carets) is still open. Tracking: new post-merge issue for remaining manual QA.
PlasticDigits commented 2026-08-17 13:49:02 +00:00 (Migrated from gitlab.com)

mentioned in issue #550

mentioned in issue #550
PlasticDigits commented 2026-08-17 13:49:46 +00:00 (Migrated from gitlab.com)

mentioned in issue #552

mentioned in issue #552
PlasticDigits commented 2026-08-17 13:49:47 +00:00 (Migrated from gitlab.com)

marked as related to #552

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

mentioned in issue #562

mentioned in issue #562
PlasticDigits commented 2026-08-18 12:08:58 +00:00 (Migrated from gitlab.com)

marked as related to #562

marked as related to #562
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:33 +00:00 (Migrated from gitlab.com)

marked as related to #655

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

mentioned in issue #660

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

marked as related to #660

marked as related to #660
PlasticDigits commented 2026-08-26 04:12:48 +00:00 (Migrated from gitlab.com)

mentioned in issue #661

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

mentioned in issue #662

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

marked as related to #662

marked as related to #662
PlasticDigits commented 2026-08-26 04:17:22 +00:00 (Migrated from gitlab.com)

mentioned in issue #666

mentioned in issue #666
PlasticDigits commented 2026-08-27 00:20:53 +00:00 (Migrated from gitlab.com)

mentioned in issue #680

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

mentioned in issue #692

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

marked as related to #692

marked as related to #692
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#547
No description provided.