OE-8 UI: no distinct "broadcast → awaiting confirmation" state; "/trade" success alerts say "submitted" on already-confirmed txs #304

Closed
opened 2026-06-04 13:52:27 +00:00 by totdking · 10 comments
totdking commented 2026-06-04 13:52:27 +00:00 (Migrated from gitlab.com)
No description provided.
totdking commented 2026-06-04 13:53:25 +00:00 (Migrated from gitlab.com)

Summary

Two related gaps in the tx lifecycle display:

  1. No intermediate "broadcast received, awaiting confirmation" state — The signing phase and the block-confirmation wait share a single isPending: true mutation state. The UI shows a static label ("Swapping…", "Submitting…") from when Keplr opens all the way through block inclusion — up to 2 minutes — with no indication the tx hash was received and the app is now waiting for a block.
  2. "Submitted" success language on already-confirmed txs — /trade market order and limit order flows show "submitted" on success, but the success alert fires only after pollTx has returned and txResponse.code === 0 has been verified. The tx is on-chain and confirmed at that point. /swap and /pool correctly use confirmed language ("Swap successful!", "Liquidity provided!").

Root cause (code verified)

No intermediate state: terraBroadcast.ts:107–118 — broadcastTx (sign + send) and pollTx (wait for block) are sequential awaits inside the same async mutationFn. There is no callback or state emission between broadcastTx resolving (tx hash received) and pollTx completing (confirmed), so the mutation stays isPending: true throughout with no hook to update the UI mid-flight.

Language inconsistency:

  • TradeMarketOrderPanel.tsx:569: "Market swap submitted." — fires after pollTx confirms code === 0
  • TradeOrderTicket.tsx:850: "Limit order submitted." — same condition
  • LimitOrderLadderPanel.tsx:303: "Ladder submitted." — same condition
  • SwapPage.tsx:1370: "Swap successful!" — correct
  • PoolPage.tsx:713: "Liquidity provided!" — correct

Steps to reproduce

Missing broadcast state:

  1. Connect Keplr on /swap, select a pair, enter an amount and click Swap
  2. Approve in Keplr
  3. Observe: button shows "Swapping…" from the moment Keplr opens through block confirmation — no state change when the tx hash is received and the confirmation wait begins

"Submitted" on confirmed tx:

  1. Connect Keplr on /trade/:pairAddr
  2. Enter a market order amount and submit; approve in Keplr
  3. Observe the success alert after confirmation: reads "Market swap submitted." — the tx is already included in a block at this point

Expected behavior

Once broadcastTx returns a hash but pollTx is still running, the UI should switch to a distinct label such as "Confirming…" or "Waiting for confirmation…" so the user knows the tx was sent and the app is waiting for block inclusion — not that the app is still waiting for the wallet.

Success alerts should use confirmed language ("confirmed", "placed", "successful") on all flows consistently, since the success state is only reached after on-chain confirmation.


Actual behavior

  • A single static label ("Swapping…" / "Submitting…") covers the full signing-through-confirmation window with no intermediate state change.
  • /trade market and limit flows show "submitted" on success; /swap and /pool show "successful" / "provided" on the same confirmed condition.

Environment

  • Chain: localterra
  • LCD: http://localhost:1317
  • Wallet: Keplr (Terra Classic)
  • Browser: Chromium (DevTools open)
  • Pages tested: / (Swap), /trade/:pairAddr, /limits, /pool
  • Network throttle applied: No

Severity: P3- Nit -> no functional issue; txs land correctly. The broadcast-state gap affects UX transparency when confirmation is slow; the language inconsistency is a polish gap between pages.

cc: @PlasticDigits

### Summary Two related gaps in the tx lifecycle display: 1. **No intermediate "broadcast received, awaiting confirmation" state** — The signing phase and the block-confirmation wait share a single `isPending: true` mutation state. The UI shows a static label ("Swapping…", "Submitting…") from when Keplr opens all the way through block inclusion — up to 2 minutes — with no indication the tx hash was received and the app is now waiting for a block. 2. **"Submitted" success language on already-confirmed txs** — `/trade` market order and limit order flows show "submitted" on success, but the success alert fires only after `pollTx` has returned and `txResponse.code === 0` has been verified. The tx is on-chain and confirmed at that point. `/swap` and `/pool` correctly use confirmed language ("Swap successful!", "Liquidity provided!"). --- ### Root cause (code verified) **No intermediate state:** `terraBroadcast.ts:107–118` — `broadcastTx` (sign + send) and `pollTx` (wait for block) are sequential awaits inside the same `async mutationFn`. There is no callback or state emission between `broadcastTx` resolving (tx hash received) and `pollTx` completing (confirmed), so the mutation stays `isPending: true` throughout with no hook to update the UI mid-flight. **Language inconsistency:** - `TradeMarketOrderPanel.tsx:569`: `"Market swap submitted."` — fires after `pollTx` confirms `code === 0` - `TradeOrderTicket.tsx:850`: `"Limit order submitted."` — same condition - `LimitOrderLadderPanel.tsx:303`: `"Ladder submitted."` — same condition - `SwapPage.tsx:1370`: `"Swap successful!"` — correct - `PoolPage.tsx:713`: `"Liquidity provided!"` — correct --- ### Steps to reproduce **Missing broadcast state:** 1. Connect Keplr on `/swap`, select a pair, enter an amount and click Swap 2. Approve in Keplr 3. Observe: button shows "Swapping…" from the moment Keplr opens through block confirmation — no state change when the tx hash is received and the confirmation wait begins **"Submitted" on confirmed tx:** 1. Connect Keplr on `/trade/:pairAddr` 2. Enter a market order amount and submit; approve in Keplr 3. Observe the success alert after confirmation: reads "Market swap submitted." — the tx is already included in a block at this point --- ### Expected behavior Once `broadcastTx` returns a hash but `pollTx` is still running, the UI should switch to a distinct label such as "Confirming…" or "Waiting for confirmation…" so the user knows the tx was sent and the app is waiting for block inclusion — not that the app is still waiting for the wallet. Success alerts should use confirmed language ("confirmed", "placed", "successful") on all flows consistently, since the success state is only reached after on-chain confirmation. --- ### Actual behavior - A single static label ("Swapping…" / "Submitting…") covers the full signing-through-confirmation window with no intermediate state change. - `/trade` market and limit flows show "submitted" on success; `/swap` and `/pool` show "successful" / "provided" on the same confirmed condition. --- ### Environment - Chain: localterra - LCD: [http://localhost:1317](http://localhost:1317) - Wallet: Keplr (Terra Classic) - Browser: Chromium (DevTools open) - Pages tested: `/` (Swap), `/trade/:pairAddr`, `/limits`, `/pool` - Network throttle applied: No --- **Severity:** P3- Nit -\> no functional issue; txs land correctly. The broadcast-state gap affects UX transparency when confirmation is slow; the language inconsistency is a polish gap between pages. cc: @PlasticDigits
totdking commented 2026-06-04 13:55:15 +00:00 (Migrated from gitlab.com)

mentioned in issue #291

mentioned in issue #291
Brouie commented 2026-06-05 03:04:23 +00:00 (Migrated from gitlab.com)

mentioned in merge request !755

mentioned in merge request !755
Brouie commented 2026-06-05 03:04:34 +00:00 (Migrated from gitlab.com)

Did the language half — MR !755. The /trade market, /trade limit, /limits, and ladder success alerts said "submitted" even though they fire only after pollTx confirms code==0 (the tx is on-chain by then), while /swap and /pool already say "successful"/"provided". Switched the four to "confirmed"/"placed". Also caught a 4th occurrence your note didn't list — LimitOrdersPage.tsx:597 — fixed that too. tsc -b clean.

The intermediate "broadcast -> confirming" state (part 1) I left out on purpose: terraBroadcast.ts runs broadcastTx then pollTx as sequential awaits in one mutationFn, so there's no hook to flip to a "Confirming..." label mid-flight — that's a broadcast-pattern change worth its own MR. Visual/browser verification is yours. @PlasticDigits

Did the language half — MR !755. The /trade market, /trade limit, /limits, and ladder success alerts said "submitted" even though they fire only after pollTx confirms code==0 (the tx is on-chain by then), while /swap and /pool already say "successful"/"provided". Switched the four to "confirmed"/"placed". Also caught a 4th occurrence your note didn't list — LimitOrdersPage.tsx:597 — fixed that too. tsc -b clean. The intermediate "broadcast -> confirming" state (part 1) I left out on purpose: terraBroadcast.ts runs broadcastTx then pollTx as sequential awaits in one mutationFn, so there's no hook to flip to a "Confirming..." label mid-flight — that's a broadcast-pattern change worth its own MR. Visual/browser verification is yours. @PlasticDigits
PlasticDigits commented 2026-06-05 03:23:33 +00:00 (Migrated from gitlab.com)

mentioned in commit c71e3474fb

mentioned in commit c71e3474fb36d980dc2696a2cc79c281835ccec3
PlasticDigits commented 2026-06-05 04:06:19 +00:00 (Migrated from gitlab.com)

Followup issue should be created for consistent UX with standardized component for showing user tx states

Followup issue should be created for consistent UX with standardized component for showing user tx states
PlasticDigits commented 2026-06-05 04:08:08 +00:00 (Migrated from gitlab.com)

mentioned in issue #305

mentioned in issue #305
PlasticDigits commented 2026-06-05 04:08:08 +00:00 (Migrated from gitlab.com)

marked as related to #305

marked as related to #305
PlasticDigits commented 2026-06-05 08:17:05 +00:00 (Migrated from gitlab.com)

mentioned in merge request !778

mentioned in merge request !778
PlasticDigits commented 2026-06-05 10:33:44 +00:00 (Migrated from gitlab.com)

Verification report — issue #304

Issue: https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/304
Branch verified: main @ 531d00e (includes !755 language fix and #305 broadcast phases)

Acceptance criteria

Item Result How verified
1. Distinct post-broadcast “confirming” state (button copy + tx hash link while pollTx runs) PASS Code: broadcastTerraExecuteContracts emits signing → broadcasting → confirming (terraBroadcast.ts); useTerraBroadcastMutation + terraBroadcastPendingButtonLabel wired on Swap, Pool, Limits, Trade market/limit/ladder. Unit: terraBroadcast.test.ts, useTerraBroadcastMutation.test.tsx, terraBroadcastUi.test.ts (11/11). Browser (Simulated Wallet, LocalTerra): swap button showed Confirming… mid-flight; market order showed Broadcasting…; TerraBroadcastPendingLink visible during confirming.
2. Success alerts use confirmed language after pollTx + code === 0 PASS Code grep: trade/limit/ladder/limits place success → Market swap confirmed. / Limit order placed. / Ladder placed. (no * submitted. on those paths). MR !755 merged. Browser: swap alert Swap successful!; market order Market swap confirmed.
3. tsc -b (frontend) PASS npx tsc -b in frontend-dapp (exit 0)

Commands / environment

# Unit tests
cd frontend-dapp && npm test -- --run \
  src/utils/__tests__/terraBroadcastUi.test.ts \
  src/services/terraclassic/__tests__/terraBroadcast.test.ts \
  src/hooks/__tests__/useTerraBroadcastMutation.test.tsx

# Stack for browser QA
make start && make wait-healthy && make deploy-local
# indexer: cargo run --release (port 3001)
# frontend: make dev (port 5173)

Notes

  • Part 1 landed via #305 (feat(frontend): Terra broadcast signing → confirming UI phases) on main; this issue’s scope is satisfied on current main.
  • Remaining “submitted” strings are cancel/refund flows only (out of scope for this nit).
  • PlasticDigits follow-up (standardized tx-state component) remains a separate product item — not blocking closure here.

Verifier: agent:verify automation — all criteria PASS. Closing as implemented on main.

## Verification report — issue #304 **Issue:** https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/304 **Branch verified:** `main` @ `531d00e` (includes !755 language fix and #305 broadcast phases) ### Acceptance criteria | Item | Result | How verified | |------|--------|--------------| | **1. Distinct post-broadcast “confirming” state** (button copy + tx hash link while `pollTx` runs) | **PASS** | Code: `broadcastTerraExecuteContracts` emits `signing` → `broadcasting` → `confirming` (`terraBroadcast.ts`); `useTerraBroadcastMutation` + `terraBroadcastPendingButtonLabel` wired on Swap, Pool, Limits, Trade market/limit/ladder. Unit: `terraBroadcast.test.ts`, `useTerraBroadcastMutation.test.tsx`, `terraBroadcastUi.test.ts` (11/11). **Browser (Simulated Wallet, LocalTerra):** swap button showed **Confirming…** mid-flight; market order showed **Broadcasting…**; `TerraBroadcastPendingLink` visible during confirming. | | **2. Success alerts use confirmed language after `pollTx` + `code === 0`** | **PASS** | Code grep: trade/limit/ladder/limits place success → `Market swap confirmed.` / `Limit order placed.` / `Ladder placed.` (no `* submitted.` on those paths). MR !755 merged. **Browser:** swap alert **Swap successful!**; market order **Market swap confirmed.** | | **3. `tsc -b` (frontend)** | **PASS** | `npx tsc -b` in `frontend-dapp` (exit 0) | ### Commands / environment ```bash # Unit tests cd frontend-dapp && npm test -- --run \ src/utils/__tests__/terraBroadcastUi.test.ts \ src/services/terraclassic/__tests__/terraBroadcast.test.ts \ src/hooks/__tests__/useTerraBroadcastMutation.test.tsx # Stack for browser QA make start && make wait-healthy && make deploy-local # indexer: cargo run --release (port 3001) # frontend: make dev (port 5173) ``` ### Notes - Part 1 landed via **#305** (`feat(frontend): Terra broadcast signing → confirming UI phases`) on `main`; this issue’s scope is satisfied on current `main`. - Remaining “submitted” strings are **cancel/refund** flows only (out of scope for this nit). - PlasticDigits follow-up (standardized tx-state component) remains a separate product item — not blocking closure here. **Verifier:** `agent:verify` automation — all criteria **PASS**. Closing as implemented on `main`.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-05 10:33:48 +00:00
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#304
No description provided.