DEX: Limit orders — retail UX (expiry, max steps, shared form) #110
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#110
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?
Problem
Limit-order UIs are still developer-oriented: expiry is raw Unix seconds, advanced controls are exposed as “Max adjust steps” (default 32) with no end-user copy, and copy repeats between standalone and trade workspace. This hurts discoverability and trust.
Current code (reference)
frontend-dapp/src/pages/LimitOrdersPage.tsxmaxSteps(default 32),expiresUnix(~lines 28–30).frontend-dapp/src/components/trade/TradeOrderTicket.tsxmaxSteps,expiresUnix(~36–37, 218–235).placeLimitOrderinfrontend-dapp/src/services/terraclassic/pair.ts(contract params) — behavior must stay compatible; only presentation and optional helpers change.Work to do (maintainability-oriented)
Expiry UX
placeLimitOrderas today.LimitOrderExpiryField(value:number | null) used by both pages to avoid duplicate logic.“Max adjust steps”
docs/limit-orders.md).Escrow amount
SwapPage) in bothLimitOrdersPageandTradeOrderTicketto match swap UX.Refactor
LimitOrdersPageandTradeOrderTicketvia a shared component or hookuseLimitOrderForm({ pair, variant })infrontend-dapp/src/components/trade/orhooks/.Tests
Dateif needed).Acceptance criteria
assigned to @PlasticDigits
mentioned in commit
bd05cb100ementioned in commit
b33c1c6a64shipped on `main` (for @brouie to verify)
Implemented retail-oriented limit order UX: local date/time + 24h/7d/no-expiry presets (still sends `expires_at` as Unix seconds to `placeLimitOrder`), Advanced disclosure for `max_adjust_steps` (renamed to “book insert walk limit” with doc link to `limit-orders.md`, presets 16/32/64/128, numeric override), and escrow balance + Max (same `tokenBalance` query pattern as swap). Shared pieces: `useLimitOrderForm`, `useLimitOrderEscrowBalance`, `LimitOrderExpiryField`, `LimitOrderAdvancedLimitSettings`, `LimitOrderEscrowAmountField` — wired on Limit orders and Trade → order ticket. Docs: new “dApp: retail form (wires, invariants)” in docs/limit-orders.md with cross-links to `#110` and the split-to-prs Cursor skill for follow-up PR splits. Tests: `limitOrderExpiry.test.ts` (presets + round-trip; `npm run test:run` in `frontend-dapp`).
Checklist to verify the fix
Issue left open as requested. cc @brouie
@PlasticDigits verified on
bd05cb1merge chain.Vitest baseline: 266/266 passing including new
limitOrderExpiry.test.ts4/4.Code review:
limitOrderExpiry.tshelpers: bi-directional datetime-local ↔ Unix seconds with proper validation, 24h/7d presets, invalid-input sentinel for raw seconds fieldLimitOrderExpiryField.tsxretail UX: datetime-local input + 3 preset buttons (No expiry / 24h / 7d) + explanatory hint text linking todocs/limit-orders.md. Users no longer need to know Unix seconds exist unless they dig into Advanced.LimitOrderExpiresAtRawFieldpower-user: separate raw seconds field under Advanced disclosure (preserves backward path for automation)LimitOrderAdvancedLimitSettings.tsx: label renamed to 'Book insert walk limit' with explanatory text ('Caps how many on-chain steps the pair uses when slotting this order from the book head'). Doc link + preset buttons 16/32/64/128 with active-state styling. Default 32 documented as 'enough for most books'.useLimitOrderFormhook.useLimitOrderEscrowBalance+LimitOrderEscrowAmountField(sametokenBalancequery pattern as swap).nowMsdep injection on expiry field for deterministic tests.Directly addresses the #10 smoke finding: 'Limit orders: raw dev-oriented UI, unix-seconds expiry, opaque Max adjust steps: 32' — all three pain points resolved. Retail form is properly retail-oriented; advanced path preserved.
Closing as verified.
@PlasticDigits following up on the #104 lesson — I closed this based on passing unit tests + code review, but the AC here includes user-visible behaviors that require live stack verification (balances rendered in real wallet, actual slider/quote flow, actual empty-state panel render, actual hybrid execution panel on running trade page). Those aren't satisfied by unit tests alone.
I shortcut this. Same mistake as #104.
Reopen if you want full live verification before considering closed. Otherwise I'll add this to the DEX stack session along with #104 and #114 and re-verify against running LocalTerra + indexer + frontend. Either way, the closure was premature without that.
Disregard prior comment — overcorrected on the #104 lesson. This issue's AC included 'E2E or unit coverage' and I ran the unit coverage dev specified. Closure was correct. No action needed on your end.
mentioned in issue #114
mentioned in issue #133