fix: refusing a From address the wallet does not hold moves nothing (closes #609)
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
This commit was merged in pull request #617.
This commit is contained in:
@@ -442,11 +442,25 @@ describe("a confirmation screen whose From is not the selected address", () => {
|
||||
expect(Transaction.from(signed).from).toBe(derived(1).address);
|
||||
});
|
||||
|
||||
// The refusal's sentence is fixed in index.html, in a box of its own that
|
||||
// holds its space from the first paint, so showing it moves nothing.
|
||||
test("nothing is sent when the selected wallet does not hold it", async () => {
|
||||
expect(await confirmSend(derived(5).address, 0)).toBeUndefined();
|
||||
expect(node("confirm-tx-password-error").textContent).toBe(
|
||||
"The selected wallet does not hold the From address above, " +
|
||||
"so nothing was sent. Please go back and send again.",
|
||||
expect(node("confirm-from-address-error").style.visibility).toBe(
|
||||
"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",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3153,6 +3153,125 @@ test("a send refused for its fee leaves the password field and Sign & Send where
|
||||
}
|
||||
});
|
||||
|
||||
// --------- a send from an address the selected wallet does not hold (#609)
|
||||
//
|
||||
// The selection is saved apart from the confirmation screen, so the popup can
|
||||
// reopen onto the screen with a wallet selected that does not hold its From
|
||||
// address, and Sign & Send then refuses the send. Another popup selecting the
|
||||
// key wallet would save that selection; here it is written into storage, and
|
||||
// the popup reopened.
|
||||
|
||||
test("a send from an address the selected wallet does not hold leaves the password field and Sign & Send where they were (#609)", async (env) => {
|
||||
try {
|
||||
// From the HD wallet's address.
|
||||
await goToConfirm(env.page, {
|
||||
token: "ETH",
|
||||
balance: FUNDED_ETH_TEXT + " ETH",
|
||||
amount: COMFORTABLE_AMOUNT,
|
||||
});
|
||||
// The screen's own save lands first, so it cannot write over the
|
||||
// selection below.
|
||||
await waitForPersisted(
|
||||
env.page,
|
||||
"currentView",
|
||||
"confirm-tx",
|
||||
"before selecting the key wallet",
|
||||
);
|
||||
await env.page.evaluate(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
chrome.storage.local.get("autistmask", (r) => {
|
||||
const record = {
|
||||
...r.autistmask,
|
||||
selectedWallet: 1,
|
||||
selectedAddress: 0,
|
||||
};
|
||||
chrome.storage.local.set(
|
||||
{ autistmask: record },
|
||||
resolve,
|
||||
);
|
||||
});
|
||||
}),
|
||||
);
|
||||
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 && (await refusal.count()) === 0,
|
||||
"the screen is not ready to send: " + JSON.stringify(before),
|
||||
);
|
||||
|
||||
const sent = env.routeOpts.broadcastTransactions.length;
|
||||
await fillPasswordAndSend(env.page);
|
||||
await refusal.waitFor({ timeout: 60000 });
|
||||
const after = await confirmState(env.page);
|
||||
|
||||
// Printed pass or fail, as the dust threshold test does.
|
||||
console.log(
|
||||
"# refused From address: password field top " +
|
||||
before.passwordTop +
|
||||
" -> " +
|
||||
after.passwordTop +
|
||||
"px, Sign & Send top " +
|
||||
before.sendTop +
|
||||
" -> " +
|
||||
after.sendTop +
|
||||
"px",
|
||||
);
|
||||
assert(
|
||||
env.routeOpts.broadcastTransactions.length === sent,
|
||||
"a send from an address the selected wallet does not hold" +
|
||||
" reached the RPC",
|
||||
);
|
||||
assert(
|
||||
after.passwordTop === before.passwordTop,
|
||||
"the password field moved " +
|
||||
(after.passwordTop - before.passwordTop) +
|
||||
"px when the send was refused",
|
||||
);
|
||||
assert(
|
||||
after.sendTop === before.sendTop,
|
||||
"Sign & Send moved " +
|
||||
(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(
|
||||
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
|
||||
// lands on the selected address. Then Home, and the HD wallet's
|
||||
// address, which the later tests send from.
|
||||
if (await env.page.isVisible("#view-confirm-tx")) {
|
||||
await env.page.click("#btn-confirm-back");
|
||||
}
|
||||
if (await env.page.isVisible("#view-send")) {
|
||||
await env.page.click("#btn-send-back");
|
||||
}
|
||||
await visible(env.page, "#view-address");
|
||||
await env.page.click("#btn-address-back");
|
||||
await visible(env.page, "#view-main");
|
||||
await openAddressDetail(env.page);
|
||||
}
|
||||
});
|
||||
|
||||
// ------------------------------ the wait for a receipt ending in error (#315)
|
||||
//
|
||||
// README.md (WaitTx) documents two ways the wait ends on the error screen: a
|
||||
|
||||
Reference in New Issue
Block a user