fix: WaitTx 60s timeout overwrites an already-rendered success screen #155

Closed
opened 2026-08-09 03:43:32 +02:00 by clawbot · 0 comments
Collaborator

Problem

In src/popup/views/txStatus.js:69-87, a single poll tick can render both
outcomes. When a receipt is found the code calls showSuccess(...)
(txStatus.js:73) but then falls through to the elapsed-time check at
txStatus.js:79-86. On the tick that coincides with the 60-second deadline it
also calls showError(...), replacing the just-rendered "Transaction
Confirmed" screen with "not confirmed within 60 seconds".

The user's transaction succeeded and they are told it did not. Given the
screen also carries the tx hash and etherscan link, this is actively
misleading at the worst possible moment.

Separately, wait-tx is not in RESTORABLE_VIEWS (src/popup/index.js:104-115)
and its timers live only in the popup, so closing the popup while waiting
silently abandons the poll. README.md:415-418 specifies polling every 10
seconds with a transition to SuccessTx on receipt, which does not survive a
popup close today.

Implementation requirements

  • Add the missing return (or otherwise make the success and timeout branches
    mutually exclusive) so a tick can only ever produce one outcome. Clear the
    poll interval on both paths so no timer outlives the view.
  • Audit the same file for the mirror-image case: a timeout firing while a
    receipt lookup is in flight should not clobber a subsequent success, and
    vice versa. Guard with a single "already resolved" flag rather than
    scattering returns.
  • For the popup-close problem, choose and implement one:
    • add wait-tx to RESTORABLE_VIEWS and rehydrate the poll from persisted
      state on popup open; or
    • move the receipt polling to the background so it survives popup close.
      The background option is more correct and matches how approvals already
      work, but note it interacts with the MV3 service-worker lifetime issue
      tracked separately — do not depend on setInterval surviving in the worker.
      State the choice and rationale in the PR.
  • Do not change the 60-second threshold or the copy without saying so.

Definition of done

  • A receipt arriving on the same tick as the 60-second deadline leaves the
    user on the "Transaction Confirmed" screen. Covered by a unit test with
    faked timers.
  • A genuine timeout with no receipt still shows the error screen with the
    tx hash and etherscan link.
  • No timer continues running after the view is left.
  • Closing and reopening the popup while a transaction is pending resumes
    the wait (or the PR documents the chosen alternative and it is
    implemented).
  • TODO.md updated in the same commit.
  • make check passes.
## Problem In `src/popup/views/txStatus.js:69-87`, a single poll tick can render both outcomes. When a receipt is found the code calls `showSuccess(...)` (`txStatus.js:73`) but then **falls through** to the elapsed-time check at `txStatus.js:79-86`. On the tick that coincides with the 60-second deadline it also calls `showError(...)`, replacing the just-rendered "Transaction Confirmed" screen with "not confirmed within 60 seconds". The user's transaction succeeded and they are told it did not. Given the screen also carries the tx hash and etherscan link, this is actively misleading at the worst possible moment. Separately, `wait-tx` is not in `RESTORABLE_VIEWS` (`src/popup/index.js:104-115`) and its timers live only in the popup, so closing the popup while waiting silently abandons the poll. `README.md:415-418` specifies polling every 10 seconds with a transition to SuccessTx on receipt, which does not survive a popup close today. ## Implementation requirements - Add the missing `return` (or otherwise make the success and timeout branches mutually exclusive) so a tick can only ever produce one outcome. Clear the poll interval on both paths so no timer outlives the view. - Audit the same file for the mirror-image case: a timeout firing while a receipt lookup is in flight should not clobber a subsequent success, and vice versa. Guard with a single "already resolved" flag rather than scattering returns. - For the popup-close problem, choose and implement one: - add `wait-tx` to `RESTORABLE_VIEWS` and rehydrate the poll from persisted state on popup open; or - move the receipt polling to the background so it survives popup close. The background option is more correct and matches how approvals already work, but note it interacts with the MV3 service-worker lifetime issue tracked separately — do not depend on `setInterval` surviving in the worker. State the choice and rationale in the PR. - Do not change the 60-second threshold or the copy without saying so. ## Definition of done - [ ] A receipt arriving on the same tick as the 60-second deadline leaves the user on the "Transaction Confirmed" screen. Covered by a unit test with faked timers. - [ ] A genuine timeout with no receipt still shows the error screen with the tx hash and etherscan link. - [ ] No timer continues running after the view is left. - [ ] Closing and reopening the popup while a transaction is pending resumes the wait (or the PR documents the chosen alternative and it is implemented). - [ ] `TODO.md` updated in the same commit. - [ ] `make check` passes.
clawbot added this to the 1.0.0 milestone 2026-08-09 03:43:32 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/AutistMask#155