Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
effc452f3b |
@@ -56,14 +56,6 @@ but the review is broader than any of them.
|
|||||||
message several lines long on the line and fails if the line or the screen
|
message several lines long on the line and fails if the line or the screen
|
||||||
below it moves. The two approval-screen error boxes are left to
|
below it moves. The two approval-screen error boxes are left to
|
||||||
[#297](https://git.eeqj.de/sneak/AutistMask/issues/297).
|
[#297](https://git.eeqj.de/sneak/AutistMask/issues/297).
|
||||||
|
|
||||||
- 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,9 +932,7 @@ async function handleRpc(method, params, origin) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EIP-1193 4200 lets a site tell "this wallet does not implement that"
|
return { error: { message: "Unsupported method: " + method } };
|
||||||
// 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,12 +31,11 @@
|
|||||||
// 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 codes such as 4001, 4100,
|
// matched against a list: the extension emits 4001, 4100 and 4902 today,
|
||||||
// 4200 and 4902, and a code this file has never heard of is still the
|
// and a code this file has never heard of is still the truth about what
|
||||||
// truth about what happened. An error reported with no code at all stays
|
// happened. An error reported with no code at all stays a plain Error —
|
||||||
// a plain Error — a ProviderRpcError whose `code` is undefined would
|
// a ProviderRpcError whose `code` is undefined would advertise a
|
||||||
// advertise a conformance it does not have. `message` is untouched in
|
// conformance it does not have. `message` is untouched in every case.
|
||||||
// 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) {
|
||||||
|
|||||||
@@ -49,12 +49,11 @@ class StubCustomEvent extends StubEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Examples of codes the background emits on the RPC path, read out of
|
// Every code the background emits on the RPC path today, read out of
|
||||||
// src/background/index.js. The provider must not know any list of codes — it
|
// src/background/index.js. The provider must not know this list — it passes
|
||||||
// passes through whatever arrived — but the cases below are 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,
|
||||||
@@ -116,41 +115,6 @@ 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(
|
||||||
@@ -200,9 +164,8 @@ describe("an EIP-1193 code reaches the page", () => {
|
|||||||
expect(err.message).toBe(message);
|
expect(err.message).toBe(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
// The provider is not allowed to know the codes above: any other code,
|
// The provider is not allowed to know the list above: a code added to the
|
||||||
// including one added to the background later, must reach the page
|
// background later must reach the page without this file being edited.
|
||||||
// without inpage.js being edited.
|
|
||||||
test("a code the provider has never heard of is passed through", async () => {
|
test("a code the provider has never heard of is passed through", async () => {
|
||||||
const err = await rejectionFrom(
|
const err = await rejectionFrom(
|
||||||
(p) => p.request({ method: "eth_accounts" }),
|
(p) => p.request({ method: "eth_accounts" }),
|
||||||
@@ -240,26 +203,6 @@ 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