W11-C4: Invalid terra1 deep link accepted as a valid pair — spinner and ambiguous 404, no "pair not found" feedback #175

Closed
opened 2026-05-21 12:59:54 +00:00 by totdking · 16 comments
totdking commented 2026-05-21 12:59:54 +00:00 (Migrated from gitlab.com)
No description provided.
totdking commented 2026-05-21 13:12:02 +00:00 (Migrated from gitlab.com)

Issue Summary

Navigating to /trade/terra1<garbage> passes the startsWith('terra1') guard in TradePage and loads the full trade UI. The order book spins indefinitely, the chart panel shows a generic "not indexed yet" message, and the pair selector displays the garbage address as if it were a valid selection. There is no indication that the address in the URL is invalid.


Reproduction Steps

  1. Start the app (VITE_NETWORK=local npm run dev) with LocalTerra running
  2. Open http://localhost:3000/trade/terra1damThat'scrazy (or any garbage string starting with terra1)
  3. Observe the Trade page

Expected Behavior

The UI should detect that the address is not a known pair and show a clear message — e.g. "Pair not found. Select a pair from the list or check the link." The pair selector should not display the garbage address as a selected value.


Actual Behavior

  • Full trade UI renders: order book (spinning indefinitely), chart panel, and order ticket all load
  • Chart panel shows: "Market data for this request was not found. The pair or route may not be indexed yet."
  • Pair selector displays the garbage address as the selected value with no invalid indicator
  • Order book never resolves — stuck in loading state
  • Console: multiple 404s from the indexer (127.0.0.1:3001), 500s from the LCD (localhost:1317)
  • Message is ambiguous — trader cannot distinguish a broken URL from a valid pair that is not yet indexed

Screen record

Screen Recording 2026-05-21 at 14.05.08.mov{width=900 height=543}


Environment Details

Field Value
OS macOS (Apple M1 Pro, 14-inch)
Browser Google Chrome 148 (desktop)
Viewport ~1440px desktop
Network localterra (local Docker)
Frontend VITE_NETWORK=local npm run dev at localhost:3000
Indexer Running (make indexer-dev)
Contracts Deployed via make deploy-local

Wallet / Device Details

  • Wallet: Keplr browser extension
  • Wallet state: Connected — localterra

Console Logs

GET http://127.0.0.1:3001/api/v1/pairs/terra1damThat'scrazy 404 (Not Found)
GET http://localhost:1317/cosmwasm/wasm/v1/contract/terra1damThat'scrazy 500 (Internal Server Error)

Severity / Impact

P2 Polish. No funds are at risk and no transaction can be submitted from an unresolved pair. However, the full UI loading with an indefinitely spinning order book and a generic "not indexed yet" message makes it impossible for a trader to distinguish a broken share link from a real pair that happens to be missing from the indexer. The pair selector accepting and displaying the garbage address compounds the confusion. Found under W11-C4 (Wrong network deep link — Display and Trader use dimensions).

### Issue Summary Navigating to `/trade/terra1<garbage>` passes the `startsWith('terra1')` guard in TradePage and loads the full trade UI. The order book spins indefinitely, the chart panel shows a generic "not indexed yet" message, and the pair selector displays the garbage address as if it were a valid selection. There is no indication that the address in the URL is invalid. --- ### Reproduction Steps 1. Start the app (`VITE_NETWORK=local npm run dev`) with LocalTerra running 2. Open `http://localhost:3000/trade/terra1damThat'scrazy` (or any garbage string starting with `terra1`) 3. Observe the Trade page --- ### Expected Behavior The UI should detect that the address is not a known pair and show a clear message — e.g. _"Pair not found. Select a pair from the list or check the link."_ The pair selector should not display the garbage address as a selected value. --- ### Actual Behavior - Full trade UI renders: order book (spinning indefinitely), chart panel, and order ticket all load - Chart panel shows: _"Market data for this request was not found. The pair or route may not be indexed yet."_ - Pair selector displays the garbage address as the selected value with no invalid indicator - Order book never resolves — stuck in loading state - Console: multiple 404s from the indexer (`127.0.0.1:3001`), 500s from the LCD (`localhost:1317`) - Message is ambiguous — trader cannot distinguish a broken URL from a valid pair that is not yet indexed --- ## Screen record ![Screen Recording 2026-05-21 at 14.05.08.mov](/uploads/d7ed36973148ce6c996721e5e06d514d/Screen_Recording_2026-05-21_at_14.05.08.mov){width=900 height=543} --- ### Environment Details | Field | Value | |-------|-------| | OS | macOS (Apple M1 Pro, 14-inch) | | Browser | Google Chrome 148 (desktop) | | Viewport | \~1440px desktop | | Network | `localterra` (local Docker) | | Frontend | `VITE_NETWORK=local npm run dev` at `localhost:3000` | | Indexer | Running (`make indexer-dev`) | | Contracts | Deployed via `make deploy-local` | --- ### Wallet / Device Details - **Wallet:** Keplr browser extension - **Wallet state:** Connected — localterra --- ### Console Logs ``` GET http://127.0.0.1:3001/api/v1/pairs/terra1damThat'scrazy 404 (Not Found) GET http://localhost:1317/cosmwasm/wasm/v1/contract/terra1damThat'scrazy 500 (Internal Server Error) ``` --- ### Severity / Impact **P2 Polish.** No funds are at risk and no transaction can be submitted from an unresolved pair. However, the full UI loading with an indefinitely spinning order book and a generic "not indexed yet" message makes it impossible for a trader to distinguish a broken share link from a real pair that happens to be missing from the indexer. The pair selector accepting and displaying the garbage address compounds the confusion. Found under **W11-C4** (Wrong network deep link — Display and Trader use dimensions).
totdking commented 2026-05-21 15:04:15 +00:00 (Migrated from gitlab.com)

mentioned in issue #116

mentioned in issue #116
Brouie commented 2026-05-25 01:34:53 +00:00 (Migrated from gitlab.com)

verified fa743326 (#176 fix) covers this case.

source: isValidTerraAddress regex /^terra1[a-z0-9]{38,}$/ rejects terra1damThat'scrazy because the uppercase T and apostrophe fail the [a-z0-9] charset.

tests: tradePairRoute.test.ts + TradePage.test.tsx 14/14 PASS. literal repro string not in the test file but the regex catches it.

note: the regex is format check, not bech32 checksum. lowercase 38+ char garbage like terra1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx would still pass and hit the indexer. want a sibling filed for the deeper edge case, or accept as out-of-scope for #175 close?

@PlasticDigits

verified `fa743326` (#176 fix) covers this case. source: `isValidTerraAddress` regex `/^terra1[a-z0-9]{38,}$/` rejects `terra1damThat'scrazy` because the uppercase `T` and apostrophe fail the `[a-z0-9]` charset. tests: `tradePairRoute.test.ts` + `TradePage.test.tsx` 14/14 PASS. literal repro string not in the test file but the regex catches it. note: the regex is format check, not bech32 checksum. lowercase 38+ char garbage like `terra1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` would still pass and hit the indexer. want a sibling filed for the deeper edge case, or accept as out-of-scope for #175 close? @PlasticDigits
PlasticDigits commented 2026-05-25 01:54:27 +00:00 (Migrated from gitlab.com)

@Brouie We shouldnt do a bech32 checksum as users may enter lowercase into the url, however we do need to show a pair/token not found error if its not in the indexer

@Brouie We shouldnt do a bech32 checksum as users may enter lowercase into the url, however we do need to show a pair/token not found error if its not in the indexer
PlasticDigits commented 2026-05-25 02:20:37 +00:00 (Migrated from gitlab.com)

mentioned in commit ba97e3a212

mentioned in commit ba97e3a212c272f58e1a83f9832575db222bef9b
PlasticDigits commented 2026-05-25 02:20:53 +00:00 (Migrated from gitlab.com)

Fix landed on main (407a74c)

Per @PlasticDigits: no bech32 checksum on URL segments (lowercase paste is fine). Unknown pairs are gated on the factory pair list after isValidTerraAddress format check — not on indexer 404 storms.

What changed

  • PairNotFoundLinkNotice — title Pair not found, quotes the deep-link segment, CTA focuses #trade-pair-select.
  • TradePage — only sets pairAddr when routePair is in getAllPairsPaginated() results; unknown valid-format links clear the URL to /trade, block auto-pick, and skip indexer/LCD workspace queries.
  • Route helpers — getUnknownTradePairRouteParam, isKnownFactoryTradePair in tradePairRoute.ts.
  • Docs / agents — docs/frontend.md § unknown pair deep link, updated skills/AGENTS_FRONTEND_TRADE_INVALID_PAIR_LINK.md.

Split from #176

Case Example UI
Charset / length invalid terra1damThat'scrazy, lilwayne babyyy Invalid pair link (#176)
Valid format, not on factory terra1 + 38× x Pair not found (#175)

Verification checklist

  • http://localhost:3000/trade/terra1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx → Pair not found alert, URL becomes /trade, selector empty (then auto-pick or manual select).
  • http://localhost:3000/trade/terra1damThat'scrazy → Invalid pair link (no indexer 404 spam).
  • Known pair deep link still loads book/chart/ticket normally.
  • npm test in frontend-dapp: TradePage.test.tsx + tradePairRoute.test.ts pass.

@brouie — please verify on localterra when you have a moment. Leaving the issue open until confirmed.

## Fix landed on `main` (`407a74c`) Per @PlasticDigits: no bech32 checksum on URL segments (lowercase paste is fine). Unknown pairs are gated on the **factory pair list** after `isValidTerraAddress` format check — not on indexer 404 storms. ### What changed - **`PairNotFoundLinkNotice`** — title **Pair not found**, quotes the deep-link segment, CTA focuses `#trade-pair-select`. - **`TradePage`** — only sets `pairAddr` when `routePair` is in `getAllPairsPaginated()` results; unknown valid-format links clear the URL to `/trade`, block auto-pick, and skip indexer/LCD workspace queries. - **Route helpers** — `getUnknownTradePairRouteParam`, `isKnownFactoryTradePair` in `tradePairRoute.ts`. - **Docs / agents** — [docs/frontend.md § unknown pair deep link](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/docs/frontend.md#trade-page-unknown-pair-link), updated [`skills/AGENTS_FRONTEND_TRADE_INVALID_PAIR_LINK.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/skills/AGENTS_FRONTEND_TRADE_INVALID_PAIR_LINK.md). ### Split from #176 | Case | Example | UI | |------|---------|-----| | Charset / length invalid | `terra1damThat'scrazy`, `lilwayne babyyy` | **Invalid pair link** (#176) | | Valid format, not on factory | `terra1` + 38× `x` | **Pair not found** (#175) | ### Verification checklist - [ ] `http://localhost:3000/trade/terra1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` → **Pair not found** alert, URL becomes `/trade`, selector empty (then auto-pick or manual select). - [ ] `http://localhost:3000/trade/terra1damThat'scrazy` → **Invalid pair link** (no indexer 404 spam). - [ ] Known pair deep link still loads book/chart/ticket normally. - [ ] `npm test` in `frontend-dapp`: `TradePage.test.tsx` + `tradePairRoute.test.ts` pass. @brouie — please verify on localterra when you have a moment. Leaving the issue **open** until confirmed.
Brouie commented 2026-05-25 02:27:43 +00:00 (Migrated from gitlab.com)

got it on no bech32 - leaving regex format check as-is. #175 good to close from QA side.

on the indexer-not-found requirement: confirmed the gap on QA stack. TradePage at line 266-279 only branches on invalidLinkNotice (format-fail) and indexerDown (outage). when getPair resolves with no pair on a valid-format address, neither fires - page falls through to empty trade UI. logging for followup.

@PlasticDigits

got it on no bech32 - leaving regex format check as-is. #175 good to close from QA side. on the indexer-not-found requirement: confirmed the gap on QA stack. TradePage at line 266-279 only branches on `invalidLinkNotice` (format-fail) and `indexerDown` (outage). when `getPair` resolves with no pair on a valid-format address, neither fires - page falls through to empty trade UI. logging for followup. @PlasticDigits
PlasticDigits commented 2026-05-25 04:09:54 +00:00 (Migrated from gitlab.com)

mentioned in commit d644e3c4d3

mentioned in commit d644e3c4d33744f51d2f7e4740fa8996b9a0ad87
PlasticDigits commented 2026-05-25 04:10:04 +00:00 (Migrated from gitlab.com)

Follow-up fix on main (d644e3c)

Addresses QA note: valid-format deep links could still show an empty trade workspace (book/chart/ticket with no getPair data) when only Invalid pair link / indexer outage banners were wired — neither applied once the route was valid-format but the pair was missing.

What changed

  • shouldShowTradeWorkspace — book/chart/ticket mount only when a factory pair is selected and no invalid/unknown link notices are active.
  • isPendingTradePairRouteResolution — while the factory list is still loading, do not render the workspace for a valid-format /trade/:pairAddr deep link.
  • isIndexerPairNotFoundError — indexer 404 on getPair for a segment not on the factory list syncs PairNotFoundLinkNotice (fallback for race/stale state).
  • Docs: § unknown pair deep link · agents: skills/AGENTS_FRONTEND_TRADE_INVALID_PAIR_LINK.md

Verification checklist

  • http://localhost:3000/trade/terra1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx → Pair not found alert, URL /trade, no empty order book/chart/ticket shell behind the notice.
  • Same URL while factory list is slow → skeleton or pair selector only; workspace appears only after a known pair is selected.
  • http://localhost:3000/trade/terra1damThat'scrazy → Invalid pair link (no indexer spam).
  • Known pair deep link with indexer temporarily missing pair metadata → workspace stays; chart Retry (#177), not Pair not found.
  • cd frontend-dapp && npm test -- --run src/pages/TradePage.test.tsx src/utils/__tests__/tradePairRoute.test.ts src/utils/__tests__/indexerErrors.test.ts — 23/23 pass.

@brouie — please verify on localterra when you can. Leaving the issue open until confirmed.

## Follow-up fix on `main` (`d644e3c`) Addresses QA note: valid-format deep links could still show an **empty trade workspace** (book/chart/ticket with no `getPair` data) when only **Invalid pair link** / **indexer outage** banners were wired — neither applied once the route was valid-format but the pair was missing. ### What changed - **`shouldShowTradeWorkspace`** — book/chart/ticket mount only when a factory pair is selected and no invalid/unknown link notices are active. - **`isPendingTradePairRouteResolution`** — while the factory list is still loading, do not render the workspace for a valid-format `/trade/:pairAddr` deep link. - **`isIndexerPairNotFoundError`** — indexer **404** on `getPair` for a segment **not** on the factory list syncs **`PairNotFoundLinkNotice`** (fallback for race/stale state). - Docs: [§ unknown pair deep link](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/docs/frontend.md#trade-page-unknown-pair-link) · agents: [`skills/AGENTS_FRONTEND_TRADE_INVALID_PAIR_LINK.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/skills/AGENTS_FRONTEND_TRADE_INVALID_PAIR_LINK.md) ### Verification checklist - [ ] `http://localhost:3000/trade/terra1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` → **Pair not found** alert, URL `/trade`, **no** empty order book/chart/ticket shell behind the notice. - [ ] Same URL while factory list is slow → skeleton or pair selector only; workspace appears only after a **known** pair is selected. - [ ] `http://localhost:3000/trade/terra1damThat'scrazy` → **Invalid pair link** (no indexer spam). - [ ] Known pair deep link with indexer temporarily missing pair metadata → workspace stays; chart **Retry** (#177), **not** Pair not found. - [ ] `cd frontend-dapp && npm test -- --run src/pages/TradePage.test.tsx src/utils/__tests__/tradePairRoute.test.ts src/utils/__tests__/indexerErrors.test.ts` — 23/23 pass. @brouie — please verify on localterra when you can. Leaving the issue **open** until confirmed.
Brouie commented 2026-05-25 08:15:10 +00:00 (Migrated from gitlab.com)

qa cleared per checklist @PlasticDigits

verified d644e3c is on main (pulled).

Tests 23/23 PASS:

  • TradePage.test.tsx 14/14
  • tradePairRoute.test.ts 7/7
  • indexerErrors.test.ts 2/2

Browser walk on local stack:

  • /trade/terra1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx → "Pair not found" alert with the deep-link segment quoted; URL clears to /trade; no empty workspace shell behind it; pair selector empty ✓
  • /trade/terra1damThat'scrazy → "Invalid pair link" (distinct message, format-fail per #176 split); URL clears to /trade ✓

Items 2 (valid-format URL during slow factory list → skeleton/selector only) and 4 (known pair + indexer pair-metadata miss → workspace stays, chart Retry) — covered by the new indexerErrors + tradePairRoute unit cases; not separately simulated in the browser.

good to close.

qa cleared per checklist @PlasticDigits verified `d644e3c` is on main (pulled). Tests 23/23 PASS: - TradePage.test.tsx 14/14 - tradePairRoute.test.ts 7/7 - indexerErrors.test.ts 2/2 Browser walk on local stack: - /trade/terra1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx → "Pair not found" alert with the deep-link segment quoted; URL clears to /trade; no empty workspace shell behind it; pair selector empty ✓ - /trade/terra1damThat'scrazy → "Invalid pair link" (distinct message, format-fail per #176 split); URL clears to /trade ✓ Items 2 (valid-format URL during slow factory list → skeleton/selector only) and 4 (known pair + indexer pair-metadata miss → workspace stays, chart Retry) — covered by the new indexerErrors + tradePairRoute unit cases; not separately simulated in the browser. good to close.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-05-27 06:27:06 +00:00
Brouie commented 2026-06-11 02:07:03 +00:00 (Migrated from gitlab.com)

mentioned in issue #357

mentioned in issue #357
Brouie commented 2026-06-11 02:54:49 +00:00 (Migrated from gitlab.com)

mentioned in issue #358

mentioned in issue #358
PlasticDigits commented 2026-06-11 15:27:02 +00:00 (Migrated from gitlab.com)

mentioned in merge request !865

mentioned in merge request !865
PlasticDigits commented 2026-08-17 03:45:40 +00:00 (Migrated from gitlab.com)

mentioned in issue #541

mentioned in issue #541
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-26 04:16:12 +00:00 (Migrated from gitlab.com)

mentioned in issue #665

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