Commit Graph

6 Commits

Author SHA1 Message Date
5092cf162a test: drive ConfirmTx in the e2e suite, gate assertion included (closes #238)
All checks were successful
check / check (push) Successful in 36s
The screen that decides what gets signed had no automated coverage of its
own behaviour: no unit tests, and the e2e suite never reached it. The
arithmetic underneath is well covered in src/shared/txValidation.js; the
gap was the wiring — which number reaches the gate, when the gate re-runs,
what the fee block renders, and whether Send is enabled.

The confirmation screen quotes the fee ESTIMATE (gasLimit * gasPrice) and
gates on the fee RESERVE (gasLimit * maxFeePerGas). Reading the quoted
number instead was issue #154, and until now that was correct by reading
only — a mutant swapping the two passed the whole suite. It no longer
does: two of the new tests fail on it, one per transaction type.

The harness gains a funded-balance fixture to make any of this reachable.
tests/e2e/network.js now serves a configurable ETH balance, an ERC-20
holding, a latest block with a baseFeePerGas (without which ethers has no
maxFeePerGas and the reserve and the estimate collapse into one number),
and decimals() for the stub token. It can also refuse a gas estimate, and
hold one open so the pending state can be observed rather than raced.

Nine tests, over both the native ETH and the ERC-20 path: Send disabled
while the estimate is pending, enabled once it lands, the fee block
quoting both numbers, the distinct message for an estimate that failed,
refusal for a send past the balance, refusal for a send the reserve does
not cover, and the view height constant across every one of those
transitions.

Driving a failure path means provoking the console.error the code is
supposed to emit, which the harness fails a run on. ErrorCollector gains
expect(): it consumes exactly one matching record, and a declaration
nothing matched fails its test just as an undeclared error does, so it
cannot be used to silence anything. Both halves of that were verified by
running the suite against a deliberately wrong pattern.
2026-08-12 09:32:28 +00:00
c6a1f97247 fix: explain a rejected dust threshold instead of silently snapping back (closes #233)
All checks were successful
check / check (push) Successful in 33s
The dust-threshold field was the only validated input in Settings that rejected
without saying anything: the value silently changed back to the stored one with
no explanation. It now flashes "Please enter a whole number of gwei, zero or
greater." alongside the existing resync, matching the idiom the RPC URL field
already uses.

The parse moves to its own module and accepts plain decimal digits only, zero
or greater. Hex and exponent notation are refused rather than accepted: Number()
reads "0x10" as 16 and "1e3" as 1000, neither of which the previous parseInt
produced, and storing a number the user did not type is the same silent
substitution this change exists to remove.

The message must fit one line of the reserved flash area -- a wrapped message
pushes the settings view down, which the No Layout Shift policy forbids. That is
pinned by an end-to-end test measuring the rendered line height and the position
of the elements below it, in a single round trip because the flash clears after
two seconds.
2026-08-12 11:29:09 +02:00
937f699fb1 feat: remove an address from an HD wallet, behind a confirmation (closes #162)
All checks were successful
check / check (push) Successful in 36s
Address rows on Home gain an [x] control, on wallets that derive addresses from
an extended key and hold more than one, opening a DeleteAddress confirmation
screen.

Removal cannot destroy anything: the key material stays. Derivation indices are
not renumbered, so the next "+" derives the next unused index rather than
resurrecting the removed one. The confirmation states the real route back --
delete the whole wallet in Settings, which asks for the password and destroys
the stored recovery phrase, then import it again -- and notes that the scan
which follows only finds addresses with on-chain activity. The copy varies by
wallet type, since an xprv wallet has no recovery phrase.

Removing an address that holds a balance is allowed, with a warning naming no
figure; the funds are at the address on-chain and stay there either way.
Selection and active address move only when the removed address was the one
selected, and site permissions are dropped for it alone.

The state transition shares its address comparison, permission cleanup and
active-changed broadcast with the wallet-level removal.
2026-08-12 11:16:29 +02:00
bf1dbec87c fix: run libsodium on WebAssembly under the extension CSP (closes #182)
All checks were successful
check / check (push) Successful in 26s
2026-08-12 10:30:15 +02:00
3e5d6323ce feat: password-gated recovery phrase display for HD wallets (closes #161)
Some checks failed
check / check (push) Has been cancelled
2026-08-11 15:25:17 +02:00
e8ad8325c8 test: containerized Chrome end-to-end harness that drives the real popup (closes #181)
Some checks failed
check / check (push) Has been cancelled
Runs the real popup in a pinned containerized Chrome and fails on any uncaught
page error or console.error. Also fixes the two defects it caught: the missing
showView import in addToken.js and the missing addressDotHtml import in
transactionDetail.js.

closes #150
closes #151
2026-08-10 15:49:32 +02:00