fix: tracked tokens are kept per network, and bundled picks are offered on mainnet only (closes #523)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

A network switch now puts the outgoing network's tracked tokens away in a new
persisted field, networkTrackedTokens, and brings back the incoming network's
list, or an empty one, the way endpoints are kept per network. trackedTokens
stays the active network's list, so its readers are unchanged, and the
background's switch goes through the same function. The two add-token screens
offer their common-token picks, which are mainnet contracts, on Ethereum
Mainnet only. After a switch in Settings, Back finds the screens beneath as a
reopened popup does: it renders the one it lands on for the new network, and
the stack is cut at the first screen that cannot be rendered from saved state.

Model: opus-5-5
This commit is contained in:
2026-10-19 01:48:44 +00:00
parent d2fd0f532a
commit 1727a4af07
12 changed files with 361 additions and 55 deletions
+12 -8
View File
@@ -42,9 +42,11 @@ const { log } = require("./log");
// and writes THIS object, never the proxy: the guard is for callers.
const rawState = {
...DEFAULT_STATE,
// Its own object, not the one DEFAULT_STATE holds: applyChainSwitchFields()
// mutates this map in place, and a spread copies the reference.
// Their own objects, not the ones DEFAULT_STATE holds:
// applyChainSwitchFields() mutates these maps in place, and a spread copies
// the reference.
networkEndpoints: {},
networkTrackedTokens: {},
currentView: null,
selectedWallet: null,
selectedAddress: null,
@@ -438,12 +440,14 @@ function mergeNetworkEndpoints(base, ours, theirs) {
//
// Every other persisted field stays a whole-field diff:
// `trackedTokens`/`fraudContracts`/`viewStack` are arrays of scalars with no
// per-element identity to merge by; `tokenHolderCache` is a map shaped like
// the ones above, but nothing in src/ ever writes an entry into it — it is
// only ever reset wholesale to `{}` (applyChainSwitchFields()) — so there is
// no in-place mutation for a whole-field diff to collide with; `viewData` is
// this page's own UI scratch space, not data another page has any reason to
// share membership of.
// per-element identity to merge by; `networkTrackedTokens` is diffed whole like
// `trackedTokens` and `networkId`, the two fields a network switch moves
// together with it; `tokenHolderCache` is a map shaped like the ones above,
// but nothing in src/ ever writes an entry into it — it is only ever reset
// wholesale to `{}` (applyChainSwitchFields()) — so there is no in-place
// mutation for a whole-field diff to collide with; `viewData` is this page's
// own UI scratch space, not data another page has any reason to share
// membership of.
//
// This does not make two pages that both change the SAME leaf concurrently
// safe: last write wins on that one leaf, same as before. What it removes