const { $, showView, showFlash } = require("./helpers"); const { generateMnemonic, hdWalletFromMnemonic, isValidMnemonic, } = require("../../shared/wallet"); const { encryptWithPassword } = require("../../shared/vault"); const { state, saveState } = require("../../shared/state"); const { scanForAddresses } = require("../../shared/balances"); function show() { $("wallet-mnemonic").value = ""; $("add-wallet-password").value = ""; $("add-wallet-password-confirm").value = ""; $("add-wallet-phrase-warning").classList.add("hidden"); showView("add-wallet"); } function init(ctx) { $("btn-generate-phrase").addEventListener("click", () => { $("wallet-mnemonic").value = generateMnemonic(); $("add-wallet-phrase-warning").classList.remove("hidden"); }); $("btn-add-wallet-confirm").addEventListener("click", async () => { const mnemonic = $("wallet-mnemonic").value.trim(); if (!mnemonic) { showFlash( "Enter a recovery phrase or press the die to generate one.", ); return; } const words = mnemonic.split(/\s+/); if (words.length !== 12 && words.length !== 24) { showFlash( "Recovery phrase must be 12 or 24 words. You entered " + words.length + ".", ); return; } if (!isValidMnemonic(mnemonic)) { showFlash("Invalid recovery phrase. Check for typos."); return; } const pw = $("add-wallet-password").value; const pw2 = $("add-wallet-password-confirm").value; if (!pw) { showFlash("Please choose a password."); return; } if (pw.length < 12) { showFlash("Password must be at least 12 characters."); return; } if (pw !== pw2) { showFlash("Passwords do not match."); return; } const { xpub, firstAddress } = hdWalletFromMnemonic(mnemonic); const duplicate = state.wallets.find( (w) => w.type === "hd" && w.addresses[0] && w.addresses[0].address.toLowerCase() === firstAddress.toLowerCase(), ); if (duplicate) { showFlash( "This recovery phrase is already added (" + duplicate.name + ").", ); return; } const encrypted = await encryptWithPassword(mnemonic, pw); const walletNum = state.wallets.length + 1; const wallet = { type: "hd", name: "Wallet " + walletNum, xpub: xpub, encryptedSecret: encrypted, nextIndex: 1, addresses: [ { address: firstAddress, balance: "0.0000", tokenBalances: [] }, ], }; state.wallets.push(wallet); state.hasWallet = true; await saveState(); ctx.renderWalletList(); showView("main"); // Scan for used HD addresses beyond index 0. showFlash("Scanning for addresses...", 30000); const scan = await scanForAddresses(xpub, state.rpcUrl); if (scan.addresses.length > 1) { wallet.addresses = scan.addresses.map((a) => ({ address: a.address, balance: "0.0000", tokenBalances: [], })); wallet.nextIndex = scan.nextIndex; await saveState(); ctx.renderWalletList(); showFlash("Found " + scan.addresses.length + " addresses."); } else { showFlash("Ready.", 1000); } ctx.doRefreshAndRender(); }); $("btn-add-wallet-back").addEventListener("click", () => { if (!state.hasWallet) { showView("welcome"); } else { ctx.renderWalletList(); showView("main"); } }); $("btn-add-wallet-import-key").addEventListener( "click", ctx.showImportKeyView, ); $("btn-add-wallet-import-xprv").addEventListener( "click", ctx.showImportXprvView, ); } module.exports = { init, show };