1 Commits
Author SHA1 Message Date
clawbot 318835f397 fix: refusing a From address the wallet does not hold moves nothing (closes #609)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
Sign & Send wrote its refusal of a From address the selected wallet does not
hold onto the password error line, which reserves one line. The sentence runs
to about three, so it pushed Sign & Send down.

The refusal now has its own box above the password field, its sentence fixed
in index.html, holding its space from the first paint and only made visible,
as #583 did for the other
refusals. Drawing the screen and each press hide it again. A Chrome test
writes the other wallet into the stored selection, reopens the popup onto the
screen, presses Sign & Send and checks that nothing was broadcast and nothing
moved.

Model: opus-5-5
2026-10-19 17:48:21 +00:00
3 changed files with 35 additions and 22 deletions
+2 -2
View File
@@ -433,8 +433,8 @@ previously correct by reading only.
It also covers a send that Sign & Send refuses for its network fee: the stub
node quotes an ordinary fee while the confirmation screen is drawn and one over
the bound when Sign & Send asks again, and the refusal must broadcast nothing
and leave the password field and Sign & Send where they were. It covers the same
way a send refused because the selected wallet does not hold its From address:
and leave the password field and Sign & Send where they were. It checks the same
for a send refused because the selected wallet does not hold its From address:
with the confirmation screen showing a send from the HD wallet, the key wallet
is selected by writing it straight into extension storage, as another popup
selecting it would save it, and the popup is reopened onto that screen.
+12
View File
@@ -450,6 +450,18 @@ describe("a confirmation screen whose From is not the selected address", () => {
"visible",
);
expect(node("confirm-tx-password-error").textContent).toBe("");
// Reviewing a send again draws the screen again, which hides it.
confirmTx.show({
from: derived(0).address,
to: RECIPIENT,
amount: "0.5",
token: "ETH",
});
await settle();
expect(node("confirm-from-address-error").style.visibility).toBe(
"hidden",
);
});
});
+21 -20
View File
@@ -2266,12 +2266,7 @@ async function confirmState(page) {
amountFeeError: shown("confirm-amount-fee-error"),
gasError: shown("confirm-gas-error"),
feeUnknownError: shown("confirm-fee-unknown-error"),
// Their sentences are wrapped across lines in index.html.
fromAddressError: shown("confirm-from-address-error")
? el("confirm-from-address-error")
.textContent.replace(/\s+/g, " ")
.trim()
: "",
// Its sentence is wrapped across lines in index.html.
feeBoundError: shown("confirm-fee-bound-error")
? el("confirm-fee-bound-error")
.textContent.replace(/\s+/g, " ")
@@ -3200,22 +3195,22 @@ test("a send from an address the selected wallet does not hold leaves the passwo
);
await reopenPopup(env, "confirm-tx");
await waitForEstimate(env.page);
// The refusal shown anywhere on the screen, not only in its own box:
// shown on the password error line instead, the test fails on the
// moves checked below rather than on the wait for it.
const refusal = env.page
.locator("#view-confirm-tx")
.getByText("does not hold the From address above")
.filter({ visible: true });
const before = await confirmState(env.page);
assert(
!before.sendDisabled && before.fromAddressError === "",
!before.sendDisabled && (await refusal.count()) === 0,
"the screen is not ready to send: " + JSON.stringify(before),
);
const sent = env.routeOpts.broadcastTransactions.length;
await fillPasswordAndSend(env.page);
// The refusal shown anywhere on the screen, not only in its own box:
// shown on the password error line instead, it fails on the moves
// checked below rather than on this wait.
await env.page
.locator("#view-confirm-tx")
.getByText("does not hold the From address above")
.filter({ visible: true })
.waitFor({ timeout: 60000 });
await refusal.waitFor({ timeout: 60000 });
const after = await confirmState(env.page);
// Printed pass or fail, as the dust threshold test does.
@@ -3247,12 +3242,18 @@ test("a send from an address the selected wallet does not hold leaves the passwo
(after.sendTop - before.sendTop) +
"px when the send was refused",
);
// Only now, where the refusal is shown. Its sentence is wrapped across
// lines in index.html.
const shownIn = await refusal.evaluate((el) => ({
id: el.id,
text: el.textContent.replace(/\s+/g, " ").trim(),
}));
assert(
after.fromAddressError ===
"The selected wallet does not hold the From address above," +
" so nothing was sent. Please go back and send again.",
"wrong From address refusal: " +
JSON.stringify(after.fromAddressError),
shownIn.id === "confirm-from-address-error" &&
shownIn.text ===
"The selected wallet does not hold the From address above," +
" so nothing was sent. Please go back and send again.",
"wrong From address refusal: " + JSON.stringify(shownIn),
);
} finally {
// A reopened popup restores no Send screen beneath this one, so Back