fix: the bundled token list names tokens on Ethereum Mainnet only (closes #632)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

bundledToken(address, chainId) in tokenList.js answers only for Ethereum
Mainnet's chain id. Every reader of TOKEN_BY_ADDRESS now goes through it,
with the chain id of the transaction, balance or history entry it draws.
The token sources the screens build carry that chain id. The Uniswap
decoder sets the transaction's chain id on them. fetchTokenBalances()
takes the chain id of the network it asks about.

isSpoofedSymbol() takes the chain id of the token's network. It checks the
bundled list's symbols only on Ethereum Mainnet. The native asset's labels
stay reserved on every network.

Eighteen existing tests and three shared test helpers read the bundled
list without naming a network. Each now names Ethereum Mainnet.

Model: opus-5-5
This commit is contained in:
clawbot
2026-10-27 19:25:44 +00:00
committed by sneak
parent 8998d6c661
commit c85eb5bf52
21 changed files with 684 additions and 120 deletions
+75 -2
View File
@@ -133,13 +133,13 @@ function trackedRow(balance, decimals = null, holders = null) {
};
}
async function refresh(addresses, trackedTokens) {
async function refresh(addresses, trackedTokens, networkId = "mainnet") {
await refreshBalances(
[{ addresses }],
RPC_URL,
EXPLORER_URL,
trackedTokens,
"mainnet",
networkId,
new AbortController().signal,
);
return addresses;
@@ -307,3 +307,76 @@ test("a tracked token wearing a known symbol from another contract is not listed
);
expect(first.tokenBalances).toEqual([]);
});
// https://git.eeqj.de/sneak/AutistMask/issues/632: the bundled list holds
// Ethereum Mainnet contracts. A token outside the tracked tokens with an
// unknown holder count is listed only when the bundled list names it.
test("an untracked bundled token with an unknown holder count is listed on Ethereum Mainnet only", async () => {
explorerRows = [explorerRow(USDC, "USDC", 5000000, null)];
const [mainnet] = await refresh(
[{ address: FIRST, tokenBalances: [] }],
[],
);
expect(mainnet.tokenBalances).toEqual([
{
address: USDC,
name: "USDC",
symbol: "USDC",
decimals: 6,
balance: "5.0",
holders: null,
},
]);
const [sepolia] = await refresh(
[{ address: FIRST, tokenBalances: [] }],
[],
"sepolia",
);
expect(sepolia.tokenBalances).toEqual([]);
});
test("a tracked token at a bundled token's address takes the bundled scale on Ethereum Mainnet only", async () => {
holdings[USDC] = { [FIRST]: 5000000n };
// The tracked entry records no decimals, and Blockscout fails.
const tracked = [
{ address: USDC, symbol: "USDC", name: "USD Coin", decimals: null },
];
const row = (balance) => ({
address: USDC,
name: "USD Coin",
symbol: "USDC",
decimals: null,
balance: balance,
holders: null,
});
const [mainnet] = await refresh(
[{ address: FIRST, tokenBalances: [] }],
tracked,
);
expect(mainnet.tokenBalances).toEqual([row("5.0")]);
const [sepolia] = await refresh(
[{ address: FIRST, tokenBalances: [] }],
tracked,
"sepolia",
);
expect(sepolia.tokenBalances).toEqual([row(null)]);
});
test("with Sepolia active, a tracked token wearing a bundled symbol from another contract is listed", async () => {
holdings[OTHER] = { [FIRST]: 5000000n };
const [first] = await refresh(
[{ address: FIRST, tokenBalances: [] }],
[{ address: OTHER, symbol: "USDC", name: "Other", decimals: 6 }],
"sepolia",
);
expect(first.tokenBalances).toEqual([
{
address: OTHER,
name: "Other",
symbol: "USDC",
decimals: null,
balance: "5.0",
holders: null,
},
]);
});