nestonexStart a project
NESTONEX PLANNING NOTES

Wallet UX: designing for pending, failed and stuck transactions

Most wallet interfaces are designed around the transaction that succeeds. Almost all of the support burden, and most of the lost trust, comes from the ones that do not — and those states are where the design work actually is.

Design every state, not the happy one: connecting, signing, submitted, pending, confirmed, failed, rejected, and stuck. Tell the user what the action does, what it costs and when it is final, in words rather than in raw transaction data. Give every failure a recovery path that does not require reading a block explorer.

The states a transaction actually has

Connecting, when the wallet is being reached and may not respond. Signing, when the request is with the wallet and the interface has no control. Submitted, when it is on the network but not confirmed. Pending, which may last seconds or may not resolve. Confirmed, which for some products means one confirmation and for others means many. Failed on chain, which still costs a fee. Rejected by the user, which costs nothing. And stuck, which is pending with no realistic prospect of resolving.

Each needs distinct copy and a distinct available action. Collapsing them into a spinner produces the single most common support question in this category, which is whether anything happened at all.

Rejected and failed are the pair most often confused, and confusing them is expensive: a user who rejected deliberately being told something went wrong will try again, and a user whose transaction failed on chain being told they cancelled will not understand the fee.

  • Distinguish rejected by user from failed on chain
  • Say what pending means here: how long, and what to do
  • Name a stuck transaction rather than spinning indefinitely

What the signing moment must communicate

The signing screen is the last point at which anyone can stop a mistake, and in a non-custodial product it is the only security control that involves the user. Its copy is a safety feature.

Say what the action does in ordinary words, before the transaction data. Swapping this for that. Approving this contract to spend up to this amount. Sending this to this address. A user reading raw call data is a user approving something they did not understand.

Show the cost separately from the amount, in a currency they think in as well as the native one, and say what happens if the price moves. A swap that silently executes at a worse rate than quoted is technically correct and feels like theft.

Unlimited approvals deserve explicit friction. They are convenient, they are the mechanism behind a large share of losses, and a user should have to choose one deliberately rather than accept it as a default.

Recovery paths that do not require a block explorer

A stuck transaction needs an in-product action: speed it up, replace it, or cancel it. Telling a user to submit a replacement with the same nonce and a higher fee is telling them to go elsewhere.

A failed transaction needs a reason in plain language. Insufficient balance for the fee, slippage exceeded, the contract reverted. The raw revert string is not an answer, and the user's next action depends on which of these it was.

Insufficient gas on the native token is common enough to deserve its own designed path, because the user often has plenty of the asset they were trying to move and none of the token the network charges in.

And the history view needs to show attempts, not just successes. A user who cannot see the transaction that failed assumes it worked.

What multi-chain adds

A wrong-network state that explains itself and offers to switch, rather than failing silently. This is the single most common cause of a user thinking a product is broken.

Per-chain fee and finality expectations. One chain confirming in seconds and another in minutes is the same word, pending, meaning two very different things, and the interface should say which.

Bridge transactions are two transactions with a gap in the middle, and the gap is where users panic. Show both legs, show which one is in progress, and say what the expected time is.

And concurrency, which is an engineering problem with a UX symptom. Two of a user's own operations running at once can collide; the fix is per-user sequencing in the backend rather than an apology in the interface.

How we have built this

Gaya Wallet quotes six aggregators in parallel to find a best route across sixteen chains, then hands the winner to a per-user sequencer that executes inside a database transaction. Concurrency happens across users and never within one, which removes the collision rather than reporting it.

Wen runs on embedded wallets, so the backend never holds a private key, and its in-app AI agent calls typed, validated tools that pass the same checks as a tap in the interface. In a non-custodial product the signing screen is the security boundary, so what it says matters as much as what it signs.

Trade Rewards handles the other end: rebates, referrals and winnings accumulate in a points ledger, and nothing leaves the hot wallet until an admin approves the withdrawal, with approved requests batched per chain and signed for ERC20, BEP20, TRC20 and SPL tokens plus native SOL.

COMMON QUESTIONS /

Questions people also ask

What is the most commonly skipped wallet state?

Stuck — pending with no realistic prospect of resolving. Most interfaces show it as pending forever, which leaves the user with no action and no information. It needs its own state, its own copy, and an in-product way to replace or cancel.

Should a wallet explain gas fees?

Yes, separately from the amount and in a currency the user thinks in. Also explain what happens if the fee is insufficient, because failing for lack of the native token while holding plenty of the asset being moved is a common and confusing experience.

How should unlimited token approvals be handled?

As a deliberate choice rather than a default. Offer an exact-amount approval as the standard path, make the unlimited option explicit about what it permits, and give users somewhere in the product to see and revoke existing approvals.

Does good wallet UX reduce support load?

Substantially, because most wallet support volume is users asking whether something happened. Distinct states, plain-language failure reasons and in-product recovery answer those questions before they are asked.

THE PROOF /

Where we have actually done this.