Trade page reverts any non-default pair to EMBER/CORAL on mount: default-pick effect clobbers the route-set effect #357
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#357
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
On /trade, navigating to or deep-linking any pair other than the default (factory pairs[0] = EMBER/CORAL) loads it for a moment, then snaps the URL back to the default pair. No crash, no console error. This is separate from #354 (the ErrorBoundary crash, fixed) and #350 (type+Enter value, fixed) — those are both resolved; this is a third defect in the same area. With it, you cannot trade or deep-link any non-default pair via the /trade UI.
Repro (cleanest — no selector involved)
Paste a non-default pair URL straight into the address bar, fresh load:
/trade/terra1nc84knc0n7td5xqplwy0luh97zd8hv5mhvm9cdempc05xk0xvxyqjr6cyg(EMBER/JADE)-> it loads briefly, then the URL reverts to
/trade/terra146ypndztcmmrmyxef7e20cul82gh43vjnw4uacwdvg5sp9kva7sqc9mjav(the default EMBER/CORAL). Reproduces in a clean incognito window. Clicking a pair in the search selector and type+Enter both hit the same revert.Backend is fine: the factory LCD
pairsquery returns all 27 incl. this pair, and the indexer/api/v1/pairs/{addr}returns 200 for it — so it is a known factory pair, not a data gap.Root cause (TradePage.tsx)
Two effects race on the mount render, when
pairAddris still '' fromuseState(''):isKnownFactoryTradePair(routePair, pairs)is true for the deep-linked pair, so it queuessetPairAddr(routePair).if (pairAddr || pairs.length === 0 || invalidRoutePair || unknownRoutePair || ...) return. On the mount renderpairAddris still '' (A's update has not applied yet), pairs is resolved, and there is no invalid/unknown notice — so the guard does not catch it and it queuessetPairAddr(pairs[0])+navigate('/trade/<default>', { replace: true }).Effect B runs after A in the same commit and its navigate wins, so the URL ends on the default pair. Effect B guards against invalid and unknown route params but not against a valid, KNOWN routePair — which is exactly the case it should leave to effect A.
This fires whenever TradePage mounts (or remounts) with a pair in the URL and the factory list is resolved — i.e. every deep link to a non-default pair, and any pair switch that remounts the page (/trade and /trade/:pairAddr are two separate Route entries).
Fix direction
Effect B (default-pick) should only run when there is NO route param to honor. Add a guard so it bails when
routePairis present and not invalid/unknown (let effect A own the known-pair case) — e.g. early-return ifroutePairis set, or gate the default-pick on!routePair. A deep-link-to-non-default-pair test (assert the URL stays on the requested pair after pairs resolve) would lock it.Impact
Breaks pair selection and shareable deep links on /trade for every pair except the default — only EMBER/CORAL is reachable through the trade UI. Gates the master-checklist core-flow / nav items (#337). Note TradePage.tsx is unchanged in the recent range, so this is pre-existing, not introduced by the #350/#353/#354 fixes.
cc @PlasticDigits
mentioned in commit
1aeaf2c362Fix landed on
main(1aeaf2c)Root cause: On mount, the default-pair effect (
pairs[0]+navigate) raced the route→state sync effect whilepairAddrwas still''. Effect B did not bail for valid known:pairAddrsegments, so non-default deep links and pair-selector switches snapped back to the first factory pair.Change:
shouldAutoPickDefaultTradePairintradePairRoute.ts— default-pick runs only for bare/trade(no valid deep-link segment, no invalid/unknown notice, not pending factory resolution).TradePage.tsxdefault-pick effect.TradePage.test.tsx+tradePairRoute.test.ts.skills/AGENTS_FRONTEND_TRADE_INVALID_PAIR_LINK.md(§ Known pair deep link).Verification checklist
/trade/<non-default-factory-pair>— URL stays on requested pair after pairs load (no snap to EMBER/CORAL)./tradestill auto-navigates to first factory pair./trade/lilwayne%20babyyy) still shows invalid notice and clears URL.TradePage.test.tsx+tradePairRoute.test.tspass locally.Follow-ups
None identified — this was a frontend routing race only; backend/indexer were already correct per issue repro notes.
Requesting verification from the QA agent team when convenient.
mentioned in commit
f63957a171mentioned in merge request !862
Agent verification (local1/357-impl-deep-link)
Core fix on
main(1aeaf2c):shouldAutoPickDefaultTradePairgates default-pick to bare/tradeonly; route→state sync owns known:pairAddrsegments.Browser verified on LocalTerra +
make dev: deep link to factory pairs[1] (EMBER/JADE) stays on requested URL and pair selector after pairs resolve — no snap to EMBER/CORAL.Note for manual QA: use addresses from current factory LCD (
getAllPairsPaginated). Stale indexer-only pair rows (absent from factory) correctly trigger unknown-pair handling, not #357 snap-back.Checklist for QA
/trade/<non-default factory LCD pair>— URL stable after pairs load/tradestill auto-navigates to first factory pairTradePage.test.tsx+tradePairRoute.test.tspassMR
https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/144 (QA doc clarification for agent manual repro)
Follow-ups
None — routing race only; backend/indexer were already correct per issue repro.
mentioned in commit
3169af0e90Source + unit pass on the merged fix (
1aeaf2c, main3169af0) — adding the human layer on top of the agent's browser pass.3169af0: 28/28 green, including the new "keeps non-default deep link after factory pairs resolve" regression.1aeaf2c^) — the deep-link test fails with the exact filed snap-back (pathname ends on pairs[0] instead of the requested pair). Bare-/trade default-pick behaves the same pre/post, as intended.One marginal find, not a blocker: the guard trims routePair but the route-sync side (isKnownFactoryTradePair) doesn't, so a deep link with encoded whitespace like /trade/%20terra1... now selects nothing silently, where before it snapped to default. Takes a literal %20 in the URL to hit — P3, can ride along with any future touch on this file.
Left from the checklist: the browser rows (fresh-tab deep link, selector pick, bare /trade, invalid/unknown notices). Those run in my next laptop browser batch, deep-linking addresses from the current factory LCD per the note above. Each already has unit coverage at HEAD, so that pass is confirmation, not discovery.
mentioned in issue #337
mentioned in issue #358
Browser half done — checklist run on the dapp at
3169af0, fresh tabs, address-bar navigation, factory-LCD addresses.f07a71ckeyed-Outlet remount wiping the notice state, NOT a1aeaf2cregression (probed bit-identical ate198dcband3169af0). The unit row stays green only because the test router has no Layout shell — test gap documented there too.3169af0, pre-fix discrimination proven (earlier note).The #357 defect itself — known-pair deep links + selector switching — is verified end to end: source, unit, real browser. Good to close from my side, with #358 tracking the unknown-link row separately. @PlasticDigits
Agent verification — PASS (close #357)
Verified fix on
main(1aeaf2c, HEAD69c0aa1):shouldAutoPickDefaultTradePairgates default-pick to bare/tradeonly; route→state sync owns valid known:pairAddrsegments.Checklist
/trade/<non-default factory pair>stays after pairs loadmake dev; EMBER/JADE (terra1nc84…6cyg) URL stable after factory resolvecl8y-dex-risk-ack)/tradeauto-navigates to first factory pairterra146yp…mjav)/trade/lilwayne%20babyyyTradePage.test.tsx+tradePairRoute.test.tskeeps non-default deep link…fails on1aeaf2c^with snap-back topairs[0]Environment
make setup-cloud-localterra(factory LCD pairs[0]=EMBER/CORAL, pairs[1]=EMBER/JADE)indexer-dev:3001, Vitemake dev:5173No repo changes from this verification pass.
mentioned in merge request !865
mentioned in issue #680