1 Commits
Author SHA1 Message Date
sneak a8e7c119ae 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 and each
recipient to Etherscan. Two settings, "Use Blockscout" and "Check recipients on
Etherscan", now gate those requests. Both are off in a new install and offered
unticked on Welcome and in Settings. While one is off, the screens that relied
on it say so in a plain line. Each gated request reads its setting from storage
before it asks and when the answer lands, and drops a late answer. An open popup
takes another page's change and draws its screens again. While "Use Blockscout"
is off, no address keeps an untracked token, and no screen names a token from
Blockscout's report. ENS lookups ask only the RPC endpoint.

Model: opus-5-5
2026-10-26 11:14:48 +00:00
8 changed files with 43 additions and 39 deletions

No files matched your search

+12 -13
View File
@@ -2599,12 +2599,12 @@ view would leave a wallet one click from deletion.
a swap pays only the From address, a `Paid to` line for each other address
it pays, or saying that a token stays in the router or who it pays is
unknown (see Transaction Decoding)
- While "Use Blockscout" is off, a line under each token in the decoded
action whose name or decimals are missing from the bundled list and the
tracked tokens: "Blockscout's report of your balances is not used to name
this token, because "Use Blockscout" is off in Settings." Blockscout's
report of the user's balances gives a token's name and decimals only while
the setting is on (see Unknown token scale).
- A line under each token of the decoded action: "Blockscout's report of
your balances is not used to name this token, because "Use Blockscout" is
off in Settings." It shows while "Use Blockscout" is off and the token's
name or decimals are missing from the bundled list and the tracked tokens.
Blockscout's report of the user's balances gives a token's name and
decimals only while the setting is on (see Unknown token scale).
- From: color dot + full address + etherscan link
- Contract: color dot + full address + etherscan link, token symbol label if
known; for a contract creation, the same sentence as on WaitTx
@@ -2684,11 +2684,10 @@ view would leave a wallet one click from deletion.
the site puts in the message, except a `Permit`'s token, which is the
domain's `verifyingContract`; any those fields do not give is shown as
`Unknown`, and the domain, type and message lines still follow. Only typed
data that cannot be read at all is shown as raw text. While "Use
Blockscout" is off, a token whose name or decimals are missing from the
bundled list and the tracked tokens has the same line under it as on
TxApproval. As there, Blockscout's report of the user's balances gives a
token's name and decimals only while the setting is on.
data that cannot be read at all is shown as raw text. A token gets the
same line under it as on TxApproval, in the same case. As there,
Blockscout's report of the user's balances gives a token's name and
decimals only while the setting is on.
- Raw data (`personal_sign` and `eth_sign`): the message's hex exactly as
the site sent it. The bytes it encodes are what is signed, as an EIP-191
personal message.
@@ -2831,8 +2830,8 @@ settings:
Both settings are on the Welcome screen and in Settings. Both are off in a new
install. Each setting applies to every network.
A request that either setting gates reads the setting from storage before it
asks, and again when the answer lands. While the setting is off, nothing is
Before each of these requests, the wallet reads its setting from storage. It
reads it again when the answer lands. While the setting is off, nothing is
asked, and an answer that lands is dropped.
Contacted by default:
+3 -3
View File
@@ -11,7 +11,7 @@ const {
onViewLeave,
formatFee,
tokenLabel,
tokenLookupOffHtml,
blockscoutOffTokenNoteHtml,
tokenSourcesByChainId,
} = require("./helpers");
const { state, saveState, currentNetwork } = require("../../shared/state");
@@ -402,7 +402,7 @@ function showTxApproval(details) {
if (d.address) {
if (d.isToken) {
detailsHtml += `<div class="font-bold">${escapeHtml(tokenLabel(d.address, approvedTx.chainId) || "Unknown token")}</div>`;
detailsHtml += tokenLookupOffHtml(
detailsHtml += blockscoutOffTokenNoteHtml(
d.address,
approvedTx.chainId,
);
@@ -657,7 +657,7 @@ function permitWarningHtml(types, primaryType, domain, message) {
html += `<div class="mb-2"><div>Token</div>`;
if (token) {
html += `<div>${escapeHtml(tokenLabel(token) || "Unknown token")}</div>`;
html += tokenLookupOffHtml(token);
html += blockscoutOffTokenNoteHtml(token);
html += approvalAddressHtml(token);
} else {
html += `<div>Unknown</div>`;
+2 -2
View File
@@ -332,7 +332,7 @@ function tokenSourcesByChainId(chainId) {
// active network when none is given. "ETH" and null are no contract, and get
// "". A token that is not text also gets "": WaitTx and ErrorTx pass a token
// restored from storage unchecked.
function tokenLookupOffHtml(token, chainId) {
function blockscoutOffTokenNoteHtml(token, chainId) {
if (typeof token !== "string") return "";
if (state.useBlockscout || !token || token === "ETH") return "";
const sources = tokenSourcesByChainId(chainId);
@@ -829,7 +829,7 @@ module.exports = {
unknownableAmount,
nativeCurrency,
tokenSourcesByChainId,
tokenLookupOffHtml,
blockscoutOffTokenNoteHtml,
tokenLabel,
formatFee,
addressDotHtml,
+10 -6
View File
@@ -14,7 +14,7 @@ const {
displaySymbol,
clearViewStack,
tokenLabel,
tokenLookupOffHtml,
blockscoutOffTokenNoteHtml,
reviewedNetworkProvider,
} = require("./helpers");
const { state } = require("../../shared/state");
@@ -109,7 +109,7 @@ function startWait(txInfo, txHash, broadcastTime, pollNow) {
}
$("wait-tx-summary").textContent =
txInfo.amount + (symbol ? " " + symbol : "");
$("wait-tx-token-note").innerHTML = tokenLookupOffHtml(
$("wait-tx-token-note").innerHTML = blockscoutOffTokenNoteHtml(
txInfo.token,
txInfo.chainId,
);
@@ -221,8 +221,9 @@ function showWait(txInfo, txHash) {
// broadcastTime leaves an unexitable wait counting "NaNs". txInfo.chainId picks
// the node the receipt is asked of and the explorer the links open, so it has
// to name a network. txInfo.token and txInfo.tokenSymbol are not checked here.
// tokenLookupOffHtml() shows no line for a token that is not text. Everything
// else only compares and coalesces them, and tokenSymbol is null for ETH.
// blockscoutOffTokenNoteHtml() shows no line for a token that is not text.
// Everything else only compares and coalesces them, and tokenSymbol is null for
// ETH.
function restoreWait() {
const d = state.viewData;
if (!d || !d.pendingWait) return false;
@@ -287,7 +288,7 @@ function decodedDetailsHtml(decoded, chainId) {
if (d.isToken) {
const sym = tokenLabel(d.address, chainId) || "Unknown token";
html += `<div class="font-bold">${escapeHtml(sym)}</div>`;
html += tokenLookupOffHtml(d.address, chainId);
html += blockscoutOffTokenNoteHtml(d.address, chainId);
html += toAddressHtml(d.address, chainId);
} else {
html += toAddressHtml(d.address, chainId);
@@ -365,7 +366,10 @@ function renderError() {
if (!d || !d.message) return;
$("error-tx-summary").textContent =
d.amount + (d.symbol ? " " + d.symbol : "");
$("error-tx-token-note").innerHTML = tokenLookupOffHtml(d.token, d.chainId);
$("error-tx-token-note").innerHTML = blockscoutOffTokenNoteHtml(
d.token,
d.chainId,
);
$("error-tx-to").innerHTML = toAddressHtml(d.to, d.chainId);
$("error-tx-message").textContent = d.message;
+4 -4
View File
@@ -1,10 +1,10 @@
// Reads "Use Blockscout" or "Check recipients on Etherscan" from the stored
// profile.
//
// A request that either setting gates reads it here twice: before it asks, and
// again when the answer lands. While the setting is off, nothing is asked, and
// an answer that lands is dropped. A page's own copy of the setting is not
// used, because another page may have just changed it.
// Before each request to Blockscout or Etherscan, the wallet reads its setting
// from storage. It reads it again when the answer lands. While the setting is
// off, nothing is asked, and an answer that lands is dropped. A page's own copy
// of the setting is not used, because another page may have just changed it.
const { storageGet } = require("./browserApi");
const { normalizePersisted } = require("./persistedState");
+2 -2
View File
@@ -2,8 +2,8 @@
// TxApproval name a token, and scale its amount, from the bundled list and the
// tracked tokens alone (https://git.eeqj.de/sneak/AutistMask/issues/668). A
// token they lack gets a line saying Blockscout's report of the user's balances
// is not used to name it. While the setting is on, what Blockscout reported for
// a token the user holds names and scales it, as before.
// is not used to name it. While the setting is on, Blockscout's report of the
// user's holding names and scales the token, as before.
//
// Booted through the real popup entry point, as the approval window or as a
// popup reopened onto SuccessTx, WaitTx or ErrorTx. The vault is mocked so that
+6 -6
View File
@@ -7,10 +7,10 @@
// the Blockscout URL in Settings. It asks that URL only for `/stats` and sends
// none of the user's data.
//
// A request that either setting gates reads the stored setting, not the page's
// copy, before it asks and again when the answer lands. So a change another
// page saved applies to it at once. An open page also takes such a change and
// draws its screens again.
// Before any other request to Blockscout or Etherscan, the wallet reads its
// setting from storage, not the page's copy. It reads it again when the answer
// lands. So a change another page saved applies at once. An open page also
// takes such a change and draws its screens again.
//
// Only Blockscout reports the tokens the user has not tracked. While "Use
// Blockscout" is off, no address keeps them and no screen lists them.
@@ -583,8 +583,8 @@ describe("the popup", () => {
}
// The token ids of the options created after the first `from` elements.
// The page stub keeps no children, so this is where the options Send's
// dropdown was filled with are read.
// The page stub keeps no children, so this reads the options for Send's
// dropdown from the elements the page created.
function optionsSince(page, from) {
return page.document.created
.slice(from)
+4 -3
View File
@@ -5,9 +5,10 @@
// (https://git.eeqj.de/sneak/AutistMask/issues/668). With the flag set, such a
// name does not resolve.
//
// The provider getProvider() builds runs against a fake JSON-RPC node. Its
// answers go through ethers' own request hook, which also records the address
// of every request ethers makes, the off-chain fetch included.
// The test builds its provider with getProvider() and runs it against a fake
// JSON-RPC node. Its answers go through ethers' own request hook, which also
// records the address of every request ethers makes, the off-chain fetch
// included.
const { FetchRequest, Interface } = require("ethers");
const { getProvider } = require("../src/shared/balances");