From c1ac51d514a9af9cd464afc0804fde52ecc0f7f3 Mon Sep 17 00:00:00 2001 From: sneak Date: Mon, 19 Oct 2026 00:17:07 +0000 Subject: [PATCH] fix: the confirmation screen reads its balance on the network it is drawn for (closes #558) ConfirmTx showed and checked the balance Send handed it, so a popup reopened onto a confirmation saved before a network switch stated the other network's balance and checked the amount against it. Each time it is shown, ConfirmTx now reads the From address's ETH balance, and for a token send its token balance, from the node of the network it is drawn for, and gives that node to the fee estimate, which starts once the read is done. Until then the balance line says "Loading..." and Sign & Send stays disabled; a failed read is stated as unknown. Each message the read can bring has a box reserved from the first paint, so nothing moves when it returns. Model: opus-5-5 --- README.md | 45 +++-- src/popup/index.html | 14 ++ src/popup/views/confirmTx.js | 250 +++++++++++++++---------- src/popup/views/send.js | 25 +-- src/shared/txValidation.js | 4 +- tests/addressKey.test.js | 1 - tests/confirmTxNetworkSwitch.test.js | 270 +++++++++++++++++++++++++-- tests/e2e/network.js | 32 +++- tests/e2e/run.js | 127 +++++++++---- tests/nativeCurrency.test.js | 15 +- tests/persistedFieldContract.test.js | 1 - tests/sendAmountRule.test.js | 11 +- tests/sendDisplayFloor.test.js | 35 +++- tests/sendMax.test.js | 14 +- tests/unknownScaleSend.test.js | 89 +++++---- 15 files changed, 689 insertions(+), 244 deletions(-) diff --git a/README.md b/README.md index dd58982..11527fc 100644 --- a/README.md +++ b/README.md @@ -1013,8 +1013,10 @@ rendered differently on two screens. The native token's label is a network's `nativeCurrency` in `src/shared/networks.js`: `ETH` on mainnet, `SepoliaETH` on Sepolia. The -wallet's balances and the Send and confirmation screens, which send on the -active network, use the active network's. A transaction's figures use the one of +wallet's balances and the Send screen, which sends on the active network, use +the active network's. The confirmation screen uses the one of the network it is +drawn for, the network active when it was shown, even after the network is +switched in Settings while it is open. A transaction's figures use the one of the network its chain id names, whichever network is active: the value and fee on the approval screen, the amount on the wait, success and error screens, the transaction history and the transaction detail screen, and the refusal of a fee @@ -1719,10 +1721,18 @@ view would leave a wallet one click from deletion. the reserve the transaction does not use. If the balance no longer covers the fee, the amount is left as it was and the amount-plus-fee error below blocks the send - - Your balance: value + symbol (USD in parentheses), or `unknown (SYMBOL)` - for a token whose scale is unknown + - Your balance: the From address's balance on the network the screen is + drawn for, read from that network's RPC endpoint each time the screen is + shown, so a screen the popup reopens onto after the network was switched + states and checks the balance on the new network. "Loading..." until the + read returns, then value + symbol (USD in parentheses), or + `unknown (SYMBOL)` for a token whose scale is unknown or when the read + failed. The amount check uses the same balances: the ETH balance, and for + a token transfer the token balance as well - Network fee: "Estimating..." then two lines, or "Unable to estimate", - fetched async. The first line is what the transfer is expected to cost, + fetched async once the balance is read, from the same RPC endpoint as the + balance, even if the network is switched in Settings while the balance is + being read. The first line is what the transfer is expected to cost, `gasLimit * gasPrice` (USD in parentheses); the second is the `gasLimit * maxFeePerGas` reserve the node requires, which is what the balance check gates on. The second line is omitted on a network with no @@ -1732,19 +1742,22 @@ view would leave a wallet one click from deletion. plus four reserved warning boxes made visible by the async checks — recipient with no transaction history, recipient is a contract, burn address, and an Etherscan phishing/scam label - - Errors (insufficient balance), plus three reserved error boxes — the - amount plus the fee exceeds the balance (ETH transfers), not enough ETH to - pay the fee for the transfer (ERC-20 transfers), and the fee could not be - estimated. The first two are mutually exclusive per transfer type, so only - the applicable one holds space. The last names its cause: for a token - whose scale is unknown the fee can never be estimated, and it says the - wallet does not know how many decimal places the token uses and that the - transaction cannot be sent; for any other failure it asks the user to go - back and try again + - Errors (an invalid amount), plus five reserved error boxes, so the balance + and the fee arriving later move nothing — the amount exceeds the balance + (for a token whose scale is unknown it says the token's balance is + unknown), the balance could not be read (it asks the user to go back and + try again), the amount plus the fee exceeds the balance (ETH transfers), + not enough ETH to pay the fee for the transfer (ERC-20 transfers), and the + fee could not be estimated. The third and fourth are mutually exclusive + per transfer type, so only the applicable one holds space. The last names + its cause: for a token whose scale is unknown the fee can never be + estimated, and it says the wallet does not know how many decimal places + the token uses and that the transaction cannot be sent; for any other + failure it asks the user to go back and try again - Password: an inline field on this screen, not a modal, with its own error line - - "Sign & Send" button (disabled if errors, and while the network fee - estimate is pending or unavailable) + - "Sign & Send" button (disabled if errors, while the balance is being read, + and while the network fee estimate is pending or unavailable) - **Transitions**: - "Sign & Send" (correct password) → broadcast tx → **WaitTx** - "Sign & Send" (correct password) → broadcast fails → **ErrorTx** diff --git a/src/popup/index.html b/src/popup/index.html index a433783..c666ac0 100644 --- a/src/popup/index.html +++ b/src/popup/index.html @@ -669,6 +669,20 @@ id="confirm-errors" class="mb-2 border border-border border-dashed p-2 invisible min-h-[1.25rem]" > + + +