fix: a network switch in Settings keeps another page's token on the network it was added on (closes #692)
A network switch in Settings filed under the new network a token or fraud contract that another page stored since this page's last save, because the switch's save writes only the fields this page changed. Before the switch, onChainSwitch() now takes the stored tracked tokens into the page's own list with takeStoredTrackedTokens(), matched by contract address, so a token either page added or removed stays as that page left it. The switch then files that list under the previous network. When the stored record is on another network, no tokens are taken. Fraud contracts are cleared on every switch, as before. Model: opus-5-5
This commit was merged in pull request #700.
This commit is contained in:
@@ -5,6 +5,9 @@
|
||||
// a contract lookup that answers after one. Driven through the real popup over
|
||||
// a stored profile; the same switch made by the background is in
|
||||
// tests/coldWorkerChainSwitch.test.js.
|
||||
//
|
||||
// The tests of what another page stored before a switch in Settings cover a
|
||||
// fraud contract too (https://git.eeqj.de/sneak/AutistMask/issues/692).
|
||||
|
||||
const {
|
||||
bootPopup,
|
||||
@@ -178,9 +181,8 @@ test("a token added by contract address on Sepolia is tracked on Sepolia only",
|
||||
});
|
||||
|
||||
// Another popup page tracks DAI on Ethereum Mainnet after this page's last
|
||||
// save. The switch's save writes only the token lists that this page changed.
|
||||
// So DAI stays in `trackedTokens`, the active network's list.
|
||||
test("a token another page tracked before a switch in Settings stays in trackedTokens", async () => {
|
||||
// save. The switch to Sepolia puts DAI away under Ethereum Mainnet.
|
||||
test("a token another page tracked before a switch in Settings stays tracked on Ethereum Mainnet", async () => {
|
||||
const boot = await bootPopup(unversionedValidProfile());
|
||||
expect(boot.pageErrors).toEqual([]);
|
||||
boot.storage.write("autistmask", {
|
||||
@@ -193,10 +195,97 @@ test("a token another page tracked before a switch in Settings stays in trackedT
|
||||
|
||||
const stored = boot.storage.read("autistmask");
|
||||
expect(stored.networkId).toBe("sepolia");
|
||||
expect(stored.trackedTokens).toEqual([MAINNET_TOKEN]);
|
||||
expect(stored.trackedTokens).toEqual([]);
|
||||
expect(stored.networkTrackedTokens.mainnet).toEqual([MAINNET_TOKEN]);
|
||||
});
|
||||
|
||||
// Another popup page stops tracking DAI on Ethereum Mainnet after this page's
|
||||
// last save. This page still holds DAI. The switch to Sepolia does not store
|
||||
// DAI under Ethereum Mainnet again.
|
||||
test("a token another page removed before a switch in Settings stays removed", async () => {
|
||||
const boot = await bootPopup(
|
||||
unversionedValidProfile({ trackedTokens: [MAINNET_TOKEN] }),
|
||||
);
|
||||
expect(boot.pageErrors).toEqual([]);
|
||||
boot.storage.write("autistmask", {
|
||||
...boot.storage.read("autistmask"),
|
||||
trackedTokens: [],
|
||||
});
|
||||
|
||||
await boot.click("btn-settings");
|
||||
await chooseNetwork(boot, "sepolia");
|
||||
|
||||
const stored = boot.storage.read("autistmask");
|
||||
expect(stored.networkId).toBe("sepolia");
|
||||
expect(stored.trackedTokens).toEqual([]);
|
||||
expect(stored.networkTrackedTokens.mainnet).toEqual([]);
|
||||
});
|
||||
|
||||
// Another popup page removes DAI after this page's last save. That page then
|
||||
// adds DAI again, typing the contract address in lower case. The two pages'
|
||||
// entries for DAI match, because contract addresses are compared ignoring
|
||||
// letter case. The switch to Sepolia keeps this page's entry under Ethereum
|
||||
// Mainnet.
|
||||
test("a token another page added again with a lower-case address keeps this page's entry", async () => {
|
||||
const boot = await bootPopup(
|
||||
unversionedValidProfile({ trackedTokens: [MAINNET_TOKEN] }),
|
||||
);
|
||||
expect(boot.pageErrors).toEqual([]);
|
||||
boot.storage.write("autistmask", {
|
||||
...boot.storage.read("autistmask"),
|
||||
trackedTokens: [
|
||||
{ ...MAINNET_TOKEN, address: MAINNET_TOKEN.address.toLowerCase() },
|
||||
],
|
||||
});
|
||||
|
||||
await boot.click("btn-settings");
|
||||
await chooseNetwork(boot, "sepolia");
|
||||
|
||||
const stored = boot.storage.read("autistmask");
|
||||
expect(stored.networkId).toBe("sepolia");
|
||||
expect(stored.networkTrackedTokens.mainnet).toEqual([MAINNET_TOKEN]);
|
||||
});
|
||||
|
||||
// Another popup page saves a switch to Sepolia after this page's last save.
|
||||
// TST is tracked on Sepolia. This page has not taken that switch yet. A switch
|
||||
// to Sepolia in this page's Settings keeps TST off Ethereum Mainnet's list.
|
||||
test("a token tracked on Sepolia when another page switched there is not tracked on Ethereum Mainnet", async () => {
|
||||
const boot = await bootPopup(unversionedValidProfile());
|
||||
expect(boot.pageErrors).toEqual([]);
|
||||
await boot.click("btn-settings");
|
||||
boot.storage.write("autistmask", {
|
||||
...boot.storage.read("autistmask"),
|
||||
networkId: "sepolia",
|
||||
trackedTokens: [SEPOLIA_TOKEN],
|
||||
});
|
||||
|
||||
await chooseNetwork(boot, "sepolia");
|
||||
|
||||
const stored = boot.storage.read("autistmask");
|
||||
expect(stored.networkId).toBe("sepolia");
|
||||
expect(stored.trackedTokens).toEqual([SEPOLIA_TOKEN]);
|
||||
expect(stored.networkTrackedTokens.mainnet).toEqual([]);
|
||||
});
|
||||
|
||||
// Another popup page records a fraud contract on Ethereum Mainnet after this
|
||||
// page's last save. The switch to Sepolia drops that fraud contract, as the
|
||||
// switch drops this page's own.
|
||||
test("a fraud contract another page recorded before a switch in Settings is not kept on Sepolia", async () => {
|
||||
const boot = await bootPopup(unversionedValidProfile());
|
||||
expect(boot.pageErrors).toEqual([]);
|
||||
boot.storage.write("autistmask", {
|
||||
...boot.storage.read("autistmask"),
|
||||
fraudContracts: [NEW_TOKEN_ADDRESS],
|
||||
});
|
||||
|
||||
await boot.click("btn-settings");
|
||||
await chooseNetwork(boot, "sepolia");
|
||||
|
||||
const stored = boot.storage.read("autistmask");
|
||||
expect(stored.networkId).toBe("sepolia");
|
||||
expect(stored.fraudContracts).toEqual([]);
|
||||
});
|
||||
|
||||
// The contract lookup on SettingsAddToken answers on Ethereum Mainnet while the
|
||||
// switch to Sepolia waits for the lock. The page adds the token to Ethereum
|
||||
// Mainnet's list. The switch then keeps that list for Ethereum Mainnet.
|
||||
|
||||
Reference in New Issue
Block a user