1 Commits
Author SHA1 Message Date
sneak a17499beed fix: Blockscout and Etherscan lookups are off until the user turns them on (closes #668)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
Out of the box the wallet sent the user's addresses to Blockscout for history
and token lookups, and each recipient to Etherscan for its label. Two settings,
"Use Blockscout" and "Check recipients on Etherscan", now gate those requests
where they are made. Both are off in a new profile and offered unticked on
Welcome and in Settings. While one is off, the screens that relied on it say so
in a plain line naming the setting. README and the user guide say what is
contacted by default and what each setting adds. Unit tests show each request
skipped while its setting is off and made while it is on; the Chrome suite
watches every request from a fresh install, then turns each setting on.

Model: opus-5-5
2026-10-21 13:14:27 +00:00
5 changed files with 58 additions and 101 deletions

No files matched your search

+22 -30
View File
@@ -18,14 +18,13 @@ don't implement any crypto, and don't send user-specific data anywhere but a
unless the user turns on one of the two lookups below. Out of the box the unless the user turns on one of the two lookups below. Out of the box the
extension contacts the configured RPC node for blockchain interactions and a extension contacts the configured RPC node for blockchain interactions and a
public CoinDesk API (no API key) for realtime price information, which is sent public CoinDesk API (no API key) for realtime price information, which is sent
token symbols and nothing else. Two more services are sent none of the user's token symbols and nothing else. Two more services are asked nothing until the
data until the user turns them on, on the Welcome screen or in Settings: a user turns them on, on the Welcome screen or in Settings: a Blockscout
Blockscout block-explorer API for transaction history, the tokens the user has block-explorer API for transaction history, the tokens the user has not tracked
not tracked and transaction details ("Use Blockscout"), and best-effort and transaction details ("Use Blockscout"), and best-effort Etherscan address
Etherscan address label lookups during transaction confirmation ("Check label lookups during transaction confirmation ("Check recipients on Etherscan").
recipients on Etherscan"). A community-maintained phishing domain blocklist is A community-maintained phishing domain blocklist is built into the extension at
built into the extension at build time and checked locally; nothing is fetched build time and checked locally; nothing is fetched for it at runtime.
for it at runtime.
In the extension is a hardcoded list of the top ERC20 contract addresses. You In the extension is a hardcoded list of the top ERC20 contract addresses. You
can add any ERC20 contract by contract address if you wish, but the hardcoded can add any ERC20 contract by contract address if you wish, but the hardcoded
@@ -429,20 +428,16 @@ mainnet must take it down, both while Settings is still on screen.
It also covers what a new install sends to Blockscout and Etherscan It also covers what a new install sends to Blockscout and Etherscan
([#668](https://git.eeqj.de/sneak/AutistMask/issues/668)). The route handler ([#668](https://git.eeqj.de/sneak/AutistMask/issues/668)). The route handler
records every request the extension makes, from its pages and its background records every request the extension makes, from its pages and its background
worker, from when the harness installs it, before the first popup page opens; a worker, from the moment the browser starts. Welcome must offer "Use Blockscout"
request the background worker makes while it starts up, before then, is not and "Check recipients on Etherscan" unticked. With neither changed, Home,
recorded. Welcome must offer "Use Blockscout" and "Check recipients on AddressDetail, AddressToken and ConfirmTx must show the lines saying what is
Etherscan" unticked. With neither changed, Home, AddressDetail, AddressToken and off; the popup is then closed until the background has run a balance refresh of
ConfirmTx must show the lines saying what is off; the popup is then closed until its own, and not one recorded request may have gone to Blockscout or Etherscan.
the background has run a balance refresh of its own, and not one recorded Each is then ticked in Settings, after which Blockscout must be asked for the
request may have gone to Blockscout or Etherscan. "Use Blockscout" is then history and the token balances, and ConfirmTx must ask Etherscan about the
ticked from AddressDetail's gear: on "Back", AddressDetail must ask Blockscout recipient and show the label the stub page gives it. Both stay on for the rest
for its history and no longer say it is off, and Blockscout must then be asked of the run. TransactionDetail with "Use Blockscout" off is not driven here,
for the token balances. "Check recipients on Etherscan" is ticked from since no history row leads to it then; the unit tests cover it.
ConfirmTx's gear: on "Back", ConfirmTx must ask Etherscan about the recipient
and show the label the stub page gives it. Both stay on for the rest of the run.
TransactionDetail with "Use Blockscout" off is not driven here, since no history
row leads to it then; the unit tests cover it.
It also covers the confirmation screen, for both a native ETH send and an ERC-20 It also covers the confirmation screen, for both a native ETH send and an ERC-20
send: Send disabled while the fee estimate is in flight, enabled once it lands, send: Send disabled while the fee estimate is in flight, enabled once it lands,
@@ -1604,10 +1599,7 @@ renders as it goes, and `viewRouter.js` records every screen that reaches
more — rendering it a second time would re-fetch and overwrite what it holds, more — rendering it a second time would re-fetch and overwrite what it holds,
such as an edit typed into Settings and not yet saved. Home is the one screen such as an edit typed into Settings and not yet saved. Home is the one screen
"Back" always re-renders, so the wallet list reflects anything that changed "Back" always re-renders, so the wallet list reflects anything that changed
while the user was away from it. Changing "Use Blockscout" or "Check recipients while the user was away from it.
on Etherscan" in Settings makes every screen but Settings count as not yet
rendered, so "Back" renders the screen it lands on under the new setting; the
stack is left as it is.
A network switch leaves every screen on the page showing the previous network. A network switch leaves every screen on the page showing the previous network.
The user makes it in Settings, or approves a site's request and the background The user makes it in Settings, or approves a site's request and the background
@@ -2740,10 +2732,10 @@ view would leave a wallet one click from deletion.
AutistMask is not a fully self-contained offline tool. By default it sends the AutistMask is not a fully self-contained offline tool. By default it sends the
user's data to one service only, the Ethereum RPC endpoint, and asks one more, user's data to one service only, the Ethereum RPC endpoint, and asks one more,
the CoinDesk price API, for prices with nothing but token symbols. Two more the CoinDesk price API, for prices with nothing but token symbols. Two more
services are sent none of the user's data until the user turns on the setting services are asked nothing until the user turns on the setting for each, on the
for each, on the Welcome screen or in Settings: Blockscout ("Use Blockscout") Welcome screen or in Settings: Blockscout ("Use Blockscout") and Etherscan
and Etherscan ("Check recipients on Etherscan"). Both settings are off in a new ("Check recipients on Etherscan"). Both settings are off in a new profile, and
profile, and each is one setting for every network. each is one setting for every network.
Contacted by default: Contacted by default:
+3 -3
View File
@@ -72,9 +72,9 @@ analytics, use a portfolio tracker. The wallet is not the place for any of that.
AutistMask is a browser extension that runs entirely in your browser. It does AutistMask is a browser extension that runs entirely in your browser. It does
not have a backend server. Out of the box it sends your data only to the not have a backend server. Out of the box it sends your data only to the
Ethereum RPC endpoint, and asks the CoinDesk price API for prices with nothing Ethereum RPC endpoint, and asks the CoinDesk price API for prices with nothing
but token symbols. Blockscout and Etherscan are sent none of your data until you but token symbols. Blockscout and Etherscan are asked nothing until you turn on
turn on "Use Blockscout" or "Check recipients on Etherscan", on the Welcome "Use Blockscout" or "Check recipients on Etherscan", on the Welcome screen or
screen or later in Settings. Both are off in a new install. later in Settings. Both are off in a new install.
### External Services ### External Services
+3 -5
View File
@@ -40,11 +40,9 @@ function markViewRendered(view) {
// Begin a fresh page-load scope. The popup gets one by being loaded, and // Begin a fresh page-load scope. The popup gets one by being loaded, and
// asks for one after a network switch, because every screen then on the page // asks for one after a network switch, because every screen then on the page
// shows the previous network (showNewNetwork() in views/settings.js), and // shows the previous network (showNewNetwork() in views/settings.js); the
// after "Use Blockscout" or "Check recipients on Etherscan" changes in // unit tests, which simulate several page loads against one module
// Settings, because every screen then on the page was drawn under the old // instance, ask for one too.
// setting; the unit tests, which simulate several page loads against one
// module instance, ask for one too.
function resetRenderedViews() { function resetRenderedViews() {
renderedViews.clear(); renderedViews.clear();
} }
+2 -9
View File
@@ -367,16 +367,11 @@ function init(_ctx) {
showFlash("Saved."); showFlash("Saved.");
}); });
// The screens under Settings were drawn under the old setting, so each // Welcome offers the same two settings, and Back from here to Welcome only
// change makes every screen but Settings count as not yet drawn, as a // unhides it, so its boxes are set here too.
// network switch does, and Back draws the one it lands on again. Welcome
// offers the same two settings and is only unhidden on Back, so its boxes
// are set here too.
$("settings-use-blockscout").addEventListener("change", async () => { $("settings-use-blockscout").addEventListener("change", async () => {
state.useBlockscout = $("settings-use-blockscout").checked; state.useBlockscout = $("settings-use-blockscout").checked;
$("welcome-use-blockscout").checked = state.useBlockscout; $("welcome-use-blockscout").checked = state.useBlockscout;
resetRenderedViews();
markViewRendered("settings");
await saveState(); await saveState();
}); });
@@ -388,8 +383,6 @@ function init(_ctx) {
).checked; ).checked;
$("welcome-check-recipients-on-etherscan").checked = $("welcome-check-recipients-on-etherscan").checked =
state.checkRecipientsOnEtherscan; state.checkRecipientsOnEtherscan;
resetRenderedViews();
markViewRendered("settings");
await saveState(); await saveState();
}, },
); );
+28 -54
View File
@@ -274,13 +274,10 @@ test("the exact confirmation phrase erases the record and reloads into Welcome (
// A fresh install asks neither Blockscout nor Etherscan anything until the // A fresh install asks neither Blockscout nor Etherscan anything until the
// user turns on "Use Blockscout" or "Check recipients on Etherscan". The route // user turns on "Use Blockscout" or "Check recipients on Etherscan". The route
// handler in tests/e2e/network.js records every request the extension makes, // handler in tests/e2e/network.js records every request the extension makes,
// from its pages and its background worker, in env.routeOpts.requests. // from its pages and its background worker, from the moment the browser
// Recording starts when launch() in tests/e2e/harness.js installs that // starts, in env.routeOpts.requests. These tests drive every screen that
// handler, before the first popup page opens; a request the background worker // would ask either service, and the background's own balance refresh, before
// makes while it starts up, before then, is not recorded. These tests drive // either setting is changed, then turn each on and watch its requests start.
// every screen that would ask either service, and the background's own
// balance refresh, before either setting is changed, then turn each on and
// watch its requests start.
// What the three transaction lists say while Use Blockscout is off. Written // What the three transaction lists say while Use Blockscout is off. Written
// out here rather than imported, so the assertion does not compare the popup // out here rather than imported, so the assertion does not compare the popup
@@ -447,41 +444,23 @@ test("with neither setting changed, nothing has reached Blockscout or Etherscan,
await visible(env.page, "#view-address"); await visible(env.page, "#view-address");
}); });
// Ticked from AddressDetail's gear, so Back lands on the screen that said the test("turning on Use Blockscout in Settings asks Blockscout for the history and the tokens (#668)", async (env) => {
// setting is off.
test("turning on Use Blockscout from AddressDetail's gear asks Blockscout for that screen's history on Back, then for the tokens (#668)", async (env) => {
await openAddressDetail(env.page);
await waitForHistoryOff(env.page, "tx-list");
await openSettings(env.page); await openSettings(env.page);
await env.page.check("#settings-use-blockscout"); await env.page.check("#settings-use-blockscout");
await waitForPersisted(env.page, "useBlockscout", true, "once ticked"); await waitForPersisted(env.page, "useBlockscout", true, "once ticked");
const historyAsked = env.page.waitForRequest( const asked = Promise.all([
(r) => env.page.waitForRequest(
r.url().includes("blockscout.com") && (r) =>
r.url().endsWith("/transactions"), r.url().includes("blockscout.com") &&
); r.url().endsWith("/transactions"),
const tokensAsked = env.page.waitForRequest( ),
(r) => r.url().endsWith("/token-balances"), env.page.waitForRequest((r) => r.url().endsWith("/token-balances"), {
{ timeout: 30000 }, timeout: 30000,
); }),
]);
await env.page.click("#btn-settings-back"); await env.page.click("#btn-settings-back");
await visible(env.page, "#view-address");
await historyAsked;
await env.page.waitForFunction(
() =>
document
.getElementById("tx-list")
.textContent.includes("No transactions found."),
null,
{ timeout: 15000 },
);
assert(
!(await env.page.isVisible("#address-tokens-note")),
"AddressDetail still says only tracked tokens are listed",
);
await goHome(env.page); await goHome(env.page);
await tokensAsked; await asked;
await env.page.waitForFunction( await env.page.waitForFunction(
() => () =>
document document
@@ -496,21 +475,11 @@ test("turning on Use Blockscout from AddressDetail's gear asks Blockscout for th
); );
}); });
// Ticked from ConfirmTx's gear, so Back lands on the screen that said no // Left on for the rest of the run, as the check was always made before #668.
// Etherscan check was made. Left on for the rest of the run, as the check was test("turning on Check recipients on Etherscan in Settings has ConfirmTx ask Etherscan and show its label (#668)", async (env) => {
// always made before #668.
test("turning on Check recipients on Etherscan from ConfirmTx's gear has ConfirmTx ask Etherscan on Back and show its label (#668)", async (env) => {
env.routeOpts.ethBalanceWei = toHexWei(FUNDED_ETH_WEI); env.routeOpts.ethBalanceWei = toHexWei(FUNDED_ETH_WEI);
env.routeOpts.etherscanLabel = "Fake_Phishing668"; env.routeOpts.etherscanLabel = "Fake_Phishing668";
try { try {
await settleOnMain(env, { ethWei: FUNDED_ETH_WEI });
await goToConfirm(env.page, {
token: "ETH",
balance: FUNDED_ETH_TEXT + " ETH",
amount: COMFORTABLE_AMOUNT,
});
await visible(env.page, "#confirm-etherscan-note");
await openSettings(env.page); await openSettings(env.page);
await env.page.check("#settings-check-recipients-on-etherscan"); await env.page.check("#settings-check-recipients-on-etherscan");
await waitForPersisted( await waitForPersisted(
@@ -519,9 +488,15 @@ test("turning on Check recipients on Etherscan from ConfirmTx's gear has Confirm
true, true,
"once ticked", "once ticked",
); );
const before = env.routeOpts.requests.length;
await env.page.click("#btn-settings-back"); await env.page.click("#btn-settings-back");
await visible(env.page, "#view-confirm-tx"); await settleOnMain(env, { ethWei: FUNDED_ETH_WEI });
const before = env.routeOpts.requests.length;
await goToConfirm(env.page, {
token: "ETH",
balance: FUNDED_ETH_TEXT + " ETH",
amount: COMFORTABLE_AMOUNT,
});
await visible(env.page, "#confirm-etherscan-warning", 30000); await visible(env.page, "#confirm-etherscan-warning", 30000);
assert( assert(
!(await env.page.isVisible("#confirm-etherscan-note")), !(await env.page.isVisible("#confirm-etherscan-note")),
@@ -5513,9 +5488,8 @@ async function main() {
// order. The dApp transaction round trip asserts against these bytes // order. The dApp transaction round trip asserts against these bytes
// rather than against anything the extension reported about them. // rather than against anything the extension reported about them.
broadcastTransactions: [], broadcastTransactions: [],
// Every request the extension makes, in order, from when launch() // Every request the extension makes, from the browser's start, in
// installs the route handler, before the first popup page opens // order (#668).
// (#668).
requests: [], requests: [],
}; };