// Adding the first wallet left no address active until the popup was reopened, // so Send and Receive on Home only said "No active address selected." // (https://git.eeqj.de/sneak/AutistMask/issues/512). Each test adds a wallet // through one of the three import tabs and checks which address is active by // opening Receive from Home in the same popup. const { HDNodeWallet, Mnemonic, Wallet } = require("ethers"); const { bootPopup, cleanupPopup, unversionedValidProfile, ADDRESS, } = require("./support/popupBoot"); const PHRASE = "abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon about"; const PRIVATE_KEY = "0x" + "11".repeat(32); // The master key of PHRASE, so its first address is the phrase's. const XPRV = HDNodeWallet.fromSeed( Mnemonic.fromPhrase(PHRASE).computeSeed(), ).extendedKey; const PASSWORD = "correct horse battery staple"; const PHRASE_ADDRESS = HDNodeWallet.fromPhrase(PHRASE).address; // Addresses 1 and 2 of PHRASE used, address 0 not: a scan that answers these // replaces the wallet's list with one that leaves out its first address. const account = HDNodeWallet.fromPhrase(PHRASE, "", "m/44'/60'/0'/0"); const used = [1, 2].map((index) => ({ address: account.deriveChild(index).address, index, })); const TABS = [ { tab: "tab-mnemonic", field: "wallet-mnemonic", secret: PHRASE, address: PHRASE_ADDRESS, }, { tab: "tab-privkey", field: "import-private-key", secret: PRIVATE_KEY, address: new Wallet(PRIVATE_KEY).address, }, { tab: "tab-xprv", field: "import-xprv-key", secret: XPRV, address: PHRASE_ADDRESS, }, ]; // Fills in the open AddWallet screen and presses "Import". async function importOn(page, { tab, field, secret }) { await page.click(tab); page.node(field).value = secret; page.node("add-wallet-password").value = PASSWORD; page.node("add-wallet-password-confirm").value = PASSWORD; await page.click("btn-add-wallet-confirm"); } afterEach(() => { cleanupPopup(); }); describe("the first wallet's first address is active right away", () => { test.each(TABS)("added from $tab, Receive opens on it", async (entry) => { const page = await bootPopup(undefined); expect(page.pageErrors).toEqual([]); await page.click("btn-welcome-add"); await importOn(page, entry); expect(page.visibleViews()).toEqual(["main"]); await page.click("btn-main-receive"); expect(page.visibleViews()).toEqual(["receive"]); expect(page.node("receive-address-block").dataset.full).toBe( entry.address, ); }); }); describe("a scan that leaves out the first address", () => { // The key tab runs no scan. test.each(TABS.filter((t) => t.tab !== "tab-privkey"))( "added from $tab, the scan's first address is active", async (entry) => { const page = await bootPopup(undefined); const { scanForAddresses } = require("../src/shared/balances"); scanForAddresses.mockResolvedValueOnce({ addresses: used, nextIndex: 3, }); await page.click("btn-welcome-add"); await importOn(page, entry); expect(page.storage.read("autistmask").activeAddress).toBe( used[0].address, ); expect(globalThis.chrome.runtime.sendMessage).toHaveBeenCalledWith({ type: "AUTISTMASK_ACTIVE_CHANGED", }); await page.click("btn-main-receive"); expect(page.node("receive-address-block").dataset.full).toBe( used[0].address, ); }, ); }); describe("adding a wallet while an address is active", () => { test.each(TABS)( "added from $tab, the active address is unchanged", async (entry) => { const page = await bootPopup(unversionedValidProfile()); expect(page.pageErrors).toEqual([]); // The phrase and xprv scans leave out the new wallet's first // address, which was never active here. The key tab runs no scan. const { scanForAddresses } = require("../src/shared/balances"); scanForAddresses.mockResolvedValueOnce({ addresses: used, nextIndex: 3, }); await page.click("btn-add-wallet-bottom"); await importOn(page, entry); expect(page.visibleViews()).toEqual(["main"]); expect(page.storage.read("autistmask").activeAddress).toBe(ADDRESS); expect( globalThis.chrome.runtime.sendMessage, ).not.toHaveBeenCalledWith({ type: "AUTISTMASK_ACTIVE_CHANGED" }); await page.click("btn-main-receive"); expect(page.node("receive-address-block").dataset.full).toBe( ADDRESS, ); }, ); });