fix: failed requests reach the page with an error code and the node's data (closes #533)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

A page's request that the node refuses now reaches it with the node's
own JSON-RPC code and data: a proxied read such as a reverting eth_call,
a transaction whose gas estimate reverts, and a failed broadcast. Every
other refusal carries a code too: 4100 when there is no address, -32602
when the site asks for two different gas limits or a transaction type
this wallet does not sign, and -32603 for a failure inside the wallet.

nodeError() in approvalVerify.js reads the node's error out of what
ethers throws, as failureTexts() already did inline.

Model: opus-5-5
This commit is contained in:
2026-10-18 18:41:10 +00:00
parent e48308c5b6
commit e2b50ad4a9
6 changed files with 390 additions and 30 deletions
+25 -4
View File
@@ -1161,9 +1161,12 @@ describe("a nonce collision is reported as a transaction that did not go out", (
const pending = bg.requestTx();
await settle();
// As ethers throws it: its own classification, and the node's
// JSON-RPC error under info.error.
bg.broadcastTransaction.mockRejectedValue(
Object.assign(new Error("nonce too low"), {
code: "NONCE_EXPIRED",
info: { error: { code: -32000, message: "nonce too low" } },
}),
);
const answer = bg.send(
@@ -1182,8 +1185,10 @@ describe("a nonce collision is reported as a transaction that did not go out", (
retryable: false,
stage: "nonce",
});
// The wallet's sentence, with the node's own code.
expect(pending.result()).toEqual({
error: {
code: -32000,
message: expect.stringMatching(
/transaction was not sent, because its nonce/,
),
@@ -1233,6 +1238,7 @@ describe("a nonce collision is reported as a transaction that did not go out", (
});
expect(second.result()).toEqual({
error: {
code: -32603,
message: expect.stringMatching(/nonce had already been used/),
},
});
@@ -1323,6 +1329,7 @@ describe("what the approval is verified against", () => {
);
expect(pending.result()).toEqual({
error: {
code: -32603,
message: expect.stringMatching(/approved maximum fee per gas/),
},
});
@@ -1382,7 +1389,10 @@ describe("what the approval is verified against", () => {
expect.objectContaining({ retryable: false, stage: "verify" }),
);
expect(pending.result()).toEqual({
error: { message: expect.stringMatching(/active address changed/) },
error: {
code: -32603,
message: expect.stringMatching(/active address changed/),
},
});
});
@@ -1526,7 +1536,10 @@ describe("what the approval is verified against", () => {
}),
);
expect(pending.result()).toEqual({
error: { message: expect.stringMatching(/active address changed/) },
error: {
code: -32603,
message: expect.stringMatching(/active address changed/),
},
});
});
@@ -1576,7 +1589,9 @@ describe("what the approval is verified against", () => {
error: refusal,
retryable: false,
});
expect(pending.result()).toEqual({ error: { message: refusal } });
expect(pending.result()).toEqual({
error: { code: -32603, message: refusal },
});
});
// ethers signs a `bool` field sent as the string "false" as true, and one
@@ -1611,7 +1626,9 @@ describe("what the approval is verified against", () => {
error: refusal,
retryable: false,
});
expect(pending.result()).toEqual({ error: { message: refusal } });
expect(pending.result()).toEqual({
error: { code: -32603, message: refusal },
});
},
);
@@ -1649,6 +1666,7 @@ describe("what the approval is verified against", () => {
expect(pending.result()).toEqual({
error: {
code: -32603,
message: expect.stringMatching(
/active address changed while this transaction was being prepared/,
),
@@ -1671,8 +1689,11 @@ describe("what the approval is verified against", () => {
const pending = bg.requestTx();
await settle();
// A failure with no node error in it is answered as the wallet's own;
// tests/rpcErrorCodes.test.js has the node's own revert.
expect(pending.result()).toEqual({
error: {
code: -32603,
message: expect.stringMatching(
/could not be prepared.*execution reverted/,
),