130 lines
4.1 KiB
JavaScript
130 lines
4.1 KiB
JavaScript
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,
|
|
);
|
|
}
|
|
|
|
module.exports = { init, show };
|