Compare commits
1
Commits
next
...
6324e6c22d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6324e6c22d |
@@ -45,6 +45,13 @@ but the review is broader than any of them.
|
|||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
|
- 2026-10-04: A method the wallet does not implement is refused with EIP-1193
|
||||||
|
code `4200` ([#279](https://git.eeqj.de/sneak/AutistMask/issues/279)). The
|
||||||
|
background's `Unsupported method: <method>` error carried no code, so a site
|
||||||
|
probing for an optional method could not tell "not implemented" from "the call
|
||||||
|
failed". The message is unchanged; the background's other errors with no code
|
||||||
|
are untouched.
|
||||||
|
|
||||||
- 2026-10-04: Settings lists the sites connected without "Remember", and
|
- 2026-10-04: Settings lists the sites connected without "Remember", and
|
||||||
removing a site there disconnects it
|
removing a site there disconnects it
|
||||||
([#406](https://git.eeqj.de/sneak/AutistMask/issues/406)). Such a connection
|
([#406](https://git.eeqj.de/sneak/AutistMask/issues/406)). Such a connection
|
||||||
|
|||||||
@@ -932,7 +932,9 @@ async function handleRpc(method, params, origin) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { error: { message: "Unsupported method: " + method } };
|
// EIP-1193 4200 lets a site tell "this wallet does not implement that"
|
||||||
|
// from "that call failed", and fall back.
|
||||||
|
return { error: { code: 4200, message: "Unsupported method: " + method } };
|
||||||
}
|
}
|
||||||
|
|
||||||
// The body of eth_sendTransaction, from the connection check through to the
|
// The body of eth_sendTransaction, from the connection check through to the
|
||||||
|
|||||||
@@ -31,11 +31,12 @@
|
|||||||
// an error instead of accepting the refusal.
|
// an error instead of accepting the refusal.
|
||||||
//
|
//
|
||||||
// Whatever code arrived is passed through verbatim rather than being
|
// Whatever code arrived is passed through verbatim rather than being
|
||||||
// matched against a list: the extension emits 4001, 4100 and 4902 today,
|
// matched against a list: the extension emits codes such as 4001, 4100,
|
||||||
// and a code this file has never heard of is still the truth about what
|
// 4200 and 4902, and a code this file has never heard of is still the
|
||||||
// happened. An error reported with no code at all stays a plain Error —
|
// truth about what happened. An error reported with no code at all stays
|
||||||
// a ProviderRpcError whose `code` is undefined would advertise a
|
// a plain Error — a ProviderRpcError whose `code` is undefined would
|
||||||
// conformance it does not have. `message` is untouched in every case.
|
// advertise a conformance it does not have. `message` is untouched in
|
||||||
|
// every case.
|
||||||
function toPageError(error) {
|
function toPageError(error) {
|
||||||
const message = (error && error.message) || "Request failed";
|
const message = (error && error.message) || "Request failed";
|
||||||
if (error && error.code !== undefined && error.code !== null) {
|
if (error && error.code !== undefined && error.code !== null) {
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class StubCustomEvent extends StubEvent {
|
|||||||
// through whatever arrived — but the cases below are the real ones.
|
// through whatever arrived — but the cases below are the real ones.
|
||||||
const REJECTED = 4001; // user rejected the request
|
const REJECTED = 4001; // user rejected the request
|
||||||
const UNAUTHORIZED = 4100; // site not connected / wrong address
|
const UNAUTHORIZED = 4100; // site not connected / wrong address
|
||||||
|
const UNSUPPORTED_METHOD = 4200; // a method the wallet does not implement
|
||||||
const UNRECOGNIZED_CHAIN = 4902; // switch/add to an unsupported chain
|
const UNRECOGNIZED_CHAIN = 4902; // switch/add to an unsupported chain
|
||||||
|
|
||||||
// A stub window with the four things inpage.js touches: message listeners,
|
// A stub window with the four things inpage.js touches: message listeners,
|
||||||
@@ -115,6 +116,41 @@ async function rejectionFrom(start, response) {
|
|||||||
return outcome.error;
|
return outcome.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The reply the real background worker (src/background/index.js) sends for
|
||||||
|
// `method`, loaded against just enough of the extension API to receive one
|
||||||
|
// RPC message. Same shape as tests/coldWorkerChainId.test.js.
|
||||||
|
function backgroundReply(method) {
|
||||||
|
jest.resetModules();
|
||||||
|
jest.doMock("../src/shared/alarms", () => ({
|
||||||
|
BALANCE_REFRESH_ALARM: "balance",
|
||||||
|
BALANCE_REFRESH_PERIOD_MINUTES: 1,
|
||||||
|
ensureRecurringAlarms: async () => {},
|
||||||
|
registerAlarmHandlers: () => {},
|
||||||
|
}));
|
||||||
|
|
||||||
|
let messageListener = null;
|
||||||
|
global.chrome = {
|
||||||
|
runtime: {
|
||||||
|
onMessage: {
|
||||||
|
addListener: (fn) => {
|
||||||
|
messageListener = fn;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onConnect: { addListener: () => {} },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
require("../src/background/index");
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
messageListener(
|
||||||
|
{ type: "AUTISTMASK_RPC", method, params: [] },
|
||||||
|
{ origin: "https://dapp.example" },
|
||||||
|
resolve,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
describe("an EIP-1193 code reaches the page", () => {
|
describe("an EIP-1193 code reaches the page", () => {
|
||||||
test("a user rejection arrives as code 4001", async () => {
|
test("a user rejection arrives as code 4001", async () => {
|
||||||
const err = await rejectionFrom(
|
const err = await rejectionFrom(
|
||||||
@@ -203,6 +239,26 @@ describe("an EIP-1193 code reaches the page", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// The reply here is the background's own, not one written in this file: it
|
||||||
|
// used to carry no code for a method the wallet does not implement
|
||||||
|
// (https://git.eeqj.de/sneak/AutistMask/issues/279), so a site probing for an
|
||||||
|
// optional method could not tell "not implemented" from "the call failed".
|
||||||
|
describe("a method the wallet does not implement", () => {
|
||||||
|
afterEach(() => {
|
||||||
|
delete global.chrome;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("reaches the page as code 4200", async () => {
|
||||||
|
const method = "wallet_noSuchMethod";
|
||||||
|
const err = await rejectionFrom(
|
||||||
|
(p) => p.request({ method }),
|
||||||
|
await backgroundReply(method),
|
||||||
|
);
|
||||||
|
expect(err.code).toBe(UNSUPPORTED_METHOD);
|
||||||
|
expect(err.message).toBe("Unsupported method: " + method);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("the message is untouched", () => {
|
describe("the message is untouched", () => {
|
||||||
test("a coded error keeps the message byte for byte", async () => {
|
test("a coded error keeps the message byte for byte", async () => {
|
||||||
const message =
|
const message =
|
||||||
|
|||||||
Reference in New Issue
Block a user