2021-09-23 15:05:10 +02:00
|
|
|
import bip38 from 'bip38';
|
2024-05-20 11:54:13 +02:00
|
|
|
import wif from 'wif';
|
2021-09-23 15:05:10 +02:00
|
|
|
|
2024-05-20 11:54:13 +02:00
|
|
|
import loc from '../loc';
|
2019-12-27 03:21:07 +01:00
|
|
|
import {
|
2021-09-23 15:05:10 +02:00
|
|
|
HDAezeedWallet,
|
2019-12-27 03:21:07 +01:00
|
|
|
HDLegacyBreadwalletWallet,
|
2021-09-23 15:05:10 +02:00
|
|
|
HDLegacyElectrumSeedP2PKHWallet,
|
2019-12-27 03:21:07 +01:00
|
|
|
HDLegacyP2PKHWallet,
|
|
|
|
HDSegwitBech32Wallet,
|
2020-05-04 11:52:01 +02:00
|
|
|
HDSegwitElectrumSeedP2WPKHWallet,
|
2021-09-23 15:05:10 +02:00
|
|
|
HDSegwitP2SHWallet,
|
|
|
|
LegacyWallet,
|
|
|
|
LightningCustodianWallet,
|
2020-10-05 23:25:14 +02:00
|
|
|
MultisigHDWallet,
|
2024-05-20 11:54:13 +02:00
|
|
|
SegwitBech32Wallet,
|
|
|
|
SegwitP2SHWallet,
|
2021-04-15 19:52:48 +02:00
|
|
|
SLIP39LegacyP2PKHWallet,
|
|
|
|
SLIP39SegwitBech32Wallet,
|
2021-09-23 15:05:10 +02:00
|
|
|
SLIP39SegwitP2SHWallet,
|
|
|
|
WatchOnlyWallet,
|
2020-05-24 12:27:08 +02:00
|
|
|
} from '.';
|
2021-09-23 15:05:10 +02:00
|
|
|
import bip39WalletFormats from './bip39_wallet_formats.json'; // https://github.com/spesmilo/electrum/blob/master/electrum/bip39_wallet_formats.json
|
|
|
|
import bip39WalletFormatsBlueWallet from './bip39_wallet_formats_bluewallet.json';
|
2024-05-20 11:54:13 +02:00
|
|
|
import type { TWallet } from './wallets/types';
|
2021-09-23 15:05:10 +02:00
|
|
|
|
|
|
|
// https://github.com/bitcoinjs/bip32/blob/master/ts-src/bip32.ts#L43
|
2024-02-11 19:39:44 +01:00
|
|
|
export const validateBip32 = (path: string) => path.match(/^(m\/)?(\d+'?\/)*\d+'?$/) !== null;
|
|
|
|
|
2024-11-09 13:40:42 +01:00
|
|
|
type TStatus = {
|
2024-02-11 19:39:44 +01:00
|
|
|
cancelled: boolean;
|
|
|
|
stopped: boolean;
|
|
|
|
wallets: TWallet[];
|
|
|
|
};
|
2021-09-23 15:05:10 +02:00
|
|
|
|
2024-11-09 13:40:42 +01:00
|
|
|
export type TImport = {
|
|
|
|
promise: Promise<TStatus>;
|
|
|
|
stop: () => void;
|
|
|
|
};
|
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
/**
|
|
|
|
* Function that starts wallet search and import process. It has async generator inside, so
|
|
|
|
* that the process can be stoped at any time. It reporst all the progress through callbacks.
|
|
|
|
*
|
2024-02-11 19:39:44 +01:00
|
|
|
* @param askPassphrase {boolean} If true import process will call onPassword callback for wallet with optional password.
|
|
|
|
* @param searchAccounts {boolean} If true import process will scan for all known derivation path from bip39_wallet_formats.json. If false it will use limited version.
|
2021-09-23 15:05:10 +02:00
|
|
|
* @param onProgress {function} Callback to report scanning progress
|
|
|
|
* @param onWallet {function} Callback to report wallet found
|
|
|
|
* @param onPassword {function} Callback to ask for password if needed
|
|
|
|
* @returns {{promise: Promise, stop: function}}
|
|
|
|
*/
|
2024-02-11 19:39:44 +01:00
|
|
|
const startImport = (
|
|
|
|
importTextOrig: string,
|
|
|
|
askPassphrase: boolean = false,
|
|
|
|
searchAccounts: boolean = false,
|
2024-11-10 21:07:17 +01:00
|
|
|
offline: boolean = false,
|
2024-02-11 19:39:44 +01:00
|
|
|
onProgress: (name: string) => void,
|
|
|
|
onWallet: (wallet: TWallet) => void,
|
|
|
|
onPassword: (title: string, text: string) => Promise<string>,
|
2024-11-09 13:40:42 +01:00
|
|
|
): TImport => {
|
2021-09-23 15:05:10 +02:00
|
|
|
// state
|
2024-11-09 13:40:42 +01:00
|
|
|
let promiseResolve: (arg: TStatus) => void;
|
2024-02-11 19:39:44 +01:00
|
|
|
let promiseReject: (reason?: any) => void;
|
2021-09-23 15:05:10 +02:00
|
|
|
let running = true; // if you put it to false, internal generator stops
|
2024-02-11 19:39:44 +01:00
|
|
|
const wallets: TWallet[] = [];
|
2024-11-09 13:40:42 +01:00
|
|
|
const promise = new Promise<TStatus>((resolve, reject) => {
|
2021-09-23 15:05:10 +02:00
|
|
|
promiseResolve = resolve;
|
|
|
|
promiseReject = reject;
|
|
|
|
});
|
|
|
|
|
2024-11-10 21:07:17 +01:00
|
|
|
// helpers
|
|
|
|
// in offline mode all wallets are considered used
|
|
|
|
const wasUsed = async (wallet: TWallet): Promise<boolean> => {
|
|
|
|
if (offline) return true;
|
|
|
|
return wallet.wasEverUsed();
|
|
|
|
};
|
|
|
|
const fetch = async (wallet: TWallet, balance: boolean = false, transactions: boolean = false) => {
|
|
|
|
if (offline) return;
|
|
|
|
if (balance) await wallet.fetchBalance();
|
|
|
|
if (transactions) await wallet.fetchTransactions();
|
|
|
|
};
|
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
// actions
|
2024-02-11 19:39:44 +01:00
|
|
|
const reportProgress = (name: string) => {
|
2021-09-23 15:05:10 +02:00
|
|
|
onProgress(name);
|
2020-10-24 19:20:59 +02:00
|
|
|
};
|
2024-02-11 19:39:44 +01:00
|
|
|
const reportFinish = (cancelled: boolean = false, stopped: boolean = false) => {
|
2021-09-23 15:05:10 +02:00
|
|
|
promiseResolve({ cancelled, stopped, wallets });
|
2020-10-24 19:20:59 +02:00
|
|
|
};
|
2024-02-11 19:39:44 +01:00
|
|
|
const reportWallet = (wallet: TWallet) => {
|
2021-09-23 15:05:10 +02:00
|
|
|
if (wallets.some(w => w.getID() === wallet.getID())) return; // do not add duplicates
|
|
|
|
wallets.push(wallet);
|
|
|
|
onWallet(wallet);
|
2020-10-24 19:20:59 +02:00
|
|
|
};
|
2021-09-23 15:05:10 +02:00
|
|
|
const stop = () => (running = false);
|
2019-12-27 03:21:07 +01:00
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
async function* importGenerator() {
|
|
|
|
// The plan:
|
|
|
|
// -3. ask for password, if needed and validate it
|
|
|
|
// -2. check if BIP38 encrypted
|
|
|
|
// -1a. check if multisig
|
|
|
|
// -1. check lightning custodian
|
|
|
|
// 0. check if its HDSegwitBech32Wallet (BIP84)
|
|
|
|
// 1. check if its HDSegwitP2SHWallet (BIP49)
|
|
|
|
// 2. check if its HDLegacyP2PKHWallet (BIP44)
|
|
|
|
// 3. check if its HDLegacyBreadwalletWallet (no BIP, just "m/0")
|
|
|
|
// 3.1 check HD Electrum legacy
|
|
|
|
// 3.2 check if its AEZEED
|
|
|
|
// 3.3 check if its SLIP39
|
|
|
|
// 4. check if its Segwit WIF (P2SH)
|
|
|
|
// 5. check if its Legacy WIF
|
|
|
|
// 6. check if its address (watch-only wallet)
|
|
|
|
// 7. check if its private key (segwit address P2SH) TODO
|
|
|
|
// 7. check if its private key (legacy address) TODO
|
2023-04-26 22:58:41 +02:00
|
|
|
// 8. check if its a json array from BC-UR with multiple accounts
|
2021-09-23 15:05:10 +02:00
|
|
|
let text = importTextOrig.trim();
|
2021-07-20 16:36:44 +02:00
|
|
|
let password;
|
|
|
|
|
|
|
|
// BIP38 password required
|
|
|
|
if (text.startsWith('6P')) {
|
|
|
|
do {
|
2021-09-23 15:05:10 +02:00
|
|
|
password = await onPassword(loc.wallets.looks_like_bip38, loc.wallets.enter_bip38_password);
|
2021-07-20 16:36:44 +02:00
|
|
|
} while (!password);
|
|
|
|
}
|
|
|
|
|
|
|
|
// HD BIP39 wallet password is optinal
|
|
|
|
const hd = new HDSegwitBech32Wallet();
|
|
|
|
hd.setSecret(text);
|
2021-09-23 15:05:10 +02:00
|
|
|
if (askPassphrase && hd.validateMnemonic()) {
|
|
|
|
password = await onPassword(loc.wallets.import_passphrase_title, loc.wallets.import_passphrase_message);
|
2021-07-20 16:36:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// AEZEED password needs to be correct
|
|
|
|
const aezeed = new HDAezeedWallet();
|
|
|
|
aezeed.setSecret(text);
|
|
|
|
if (await aezeed.mnemonicInvalidPassword()) {
|
|
|
|
do {
|
2021-09-23 15:05:10 +02:00
|
|
|
password = await onPassword('', loc.wallets.enter_bip38_password);
|
2021-07-20 16:36:44 +02:00
|
|
|
aezeed.setPassphrase(password);
|
|
|
|
} while (await aezeed.mnemonicInvalidPassword());
|
|
|
|
}
|
|
|
|
|
|
|
|
// SLIP39 wallet password is optinal
|
2021-09-23 15:05:10 +02:00
|
|
|
if (askPassphrase && text.includes('\n')) {
|
2021-07-20 16:36:44 +02:00
|
|
|
const s1 = new SLIP39SegwitP2SHWallet();
|
|
|
|
s1.setSecret(text);
|
|
|
|
|
|
|
|
if (s1.validateMnemonic()) {
|
2021-09-23 15:05:10 +02:00
|
|
|
password = await onPassword(loc.wallets.import_passphrase_title, loc.wallets.import_passphrase_message);
|
2021-07-20 16:36:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-26 10:22:34 +02:00
|
|
|
// ELECTRUM segwit wallet password is optinal
|
|
|
|
const electrum1 = new HDSegwitElectrumSeedP2WPKHWallet();
|
2021-09-23 15:05:10 +02:00
|
|
|
electrum1.setSecret(text);
|
|
|
|
if (askPassphrase && electrum1.validateMnemonic()) {
|
|
|
|
password = await onPassword(loc.wallets.import_passphrase_title, loc.wallets.import_passphrase_message);
|
2021-07-26 10:22:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ELECTRUM legacy wallet password is optinal
|
|
|
|
const electrum2 = new HDLegacyElectrumSeedP2PKHWallet();
|
2021-09-23 15:05:10 +02:00
|
|
|
electrum2.setSecret(text);
|
|
|
|
if (askPassphrase && electrum2.validateMnemonic()) {
|
|
|
|
password = await onPassword(loc.wallets.import_passphrase_title, loc.wallets.import_passphrase_message);
|
2021-09-09 13:00:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
// is it bip38 encrypted
|
2024-02-11 19:39:44 +01:00
|
|
|
if (text.startsWith('6P') && password) {
|
2021-09-23 15:05:10 +02:00
|
|
|
const decryptedKey = await bip38.decryptAsync(text, password);
|
2020-10-05 23:25:14 +02:00
|
|
|
|
2020-10-15 13:14:55 +02:00
|
|
|
if (decryptedKey) {
|
2021-09-23 15:05:10 +02:00
|
|
|
text = wif.encode(0x80, decryptedKey.privateKey, decryptedKey.compressed);
|
2019-12-27 03:21:07 +01:00
|
|
|
}
|
2020-10-15 13:14:55 +02:00
|
|
|
}
|
2019-12-27 03:21:07 +01:00
|
|
|
|
2020-10-15 13:14:55 +02:00
|
|
|
// is it multisig?
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { progress: 'multisignature' };
|
|
|
|
const ms = new MultisigHDWallet();
|
|
|
|
ms.setSecret(text);
|
|
|
|
if (ms.getN() > 0 && ms.getM() > 0) {
|
2024-11-10 21:07:17 +01:00
|
|
|
await fetch(ms, true, false);
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { wallet: ms };
|
2020-10-15 13:14:55 +02:00
|
|
|
}
|
2019-12-27 03:21:07 +01:00
|
|
|
|
2020-10-15 13:14:55 +02:00
|
|
|
// is it lightning custodian?
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { progress: 'lightning custodian' };
|
|
|
|
if (text.startsWith('blitzhub://') || text.startsWith('lndhub://')) {
|
2020-10-15 13:14:55 +02:00
|
|
|
const lnd = new LightningCustodianWallet();
|
2021-09-23 15:05:10 +02:00
|
|
|
if (text.includes('@')) {
|
|
|
|
const split = text.split('@');
|
2020-10-15 13:14:55 +02:00
|
|
|
lnd.setBaseURI(split[1]);
|
|
|
|
lnd.setSecret(split[0]);
|
2019-12-27 03:21:07 +01:00
|
|
|
}
|
2021-10-23 21:17:00 +02:00
|
|
|
await lnd.init();
|
2024-11-10 21:07:17 +01:00
|
|
|
if (!offline) {
|
|
|
|
await lnd.authorize();
|
|
|
|
await lnd.fetchTransactions();
|
|
|
|
await lnd.fetchUserInvoices();
|
|
|
|
await lnd.fetchPendingTransactions();
|
|
|
|
await lnd.fetchBalance();
|
|
|
|
}
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { wallet: lnd };
|
2020-10-15 13:14:55 +02:00
|
|
|
}
|
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
// check bip39 wallets
|
|
|
|
yield { progress: 'bip39' };
|
|
|
|
const hd2 = new HDSegwitBech32Wallet();
|
|
|
|
hd2.setSecret(text);
|
2024-02-11 19:39:44 +01:00
|
|
|
if (password) {
|
|
|
|
hd2.setPassphrase(password);
|
|
|
|
}
|
2021-09-23 15:05:10 +02:00
|
|
|
if (hd2.validateMnemonic()) {
|
|
|
|
let walletFound = false;
|
|
|
|
// by default we don't try all the paths and options
|
2023-07-25 15:50:04 +02:00
|
|
|
const searchPaths = searchAccounts ? bip39WalletFormats : bip39WalletFormatsBlueWallet;
|
|
|
|
for (const i of searchPaths) {
|
2021-09-23 15:05:10 +02:00
|
|
|
// we need to skip m/0' p2pkh from default scan list. It could be a BRD wallet and will be handled later
|
|
|
|
if (i.derivation_path === "m/0'" && i.script_type === 'p2pkh') continue;
|
|
|
|
let paths;
|
|
|
|
if (i.iterate_accounts && searchAccounts) {
|
|
|
|
const basicPath = i.derivation_path.slice(0, -2); // remove 0' from the end
|
|
|
|
paths = [...Array(10).keys()].map(j => basicPath + j + "'"); // add account number
|
|
|
|
} else {
|
|
|
|
paths = [i.derivation_path];
|
|
|
|
}
|
|
|
|
let WalletClass;
|
|
|
|
switch (i.script_type) {
|
|
|
|
case 'p2pkh':
|
|
|
|
WalletClass = HDLegacyP2PKHWallet;
|
|
|
|
break;
|
|
|
|
case 'p2wpkh-p2sh':
|
|
|
|
WalletClass = HDSegwitP2SHWallet;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// p2wpkh
|
|
|
|
WalletClass = HDSegwitBech32Wallet;
|
|
|
|
}
|
|
|
|
for (const path of paths) {
|
|
|
|
const wallet = new WalletClass();
|
|
|
|
wallet.setSecret(text);
|
2024-02-11 19:39:44 +01:00
|
|
|
if (password) {
|
|
|
|
wallet.setPassphrase(password);
|
|
|
|
}
|
2021-09-23 15:05:10 +02:00
|
|
|
wallet.setDerivationPath(path);
|
|
|
|
yield { progress: `bip39 ${i.script_type} ${path}` };
|
2024-11-10 21:07:17 +01:00
|
|
|
if (await wasUsed(wallet)) {
|
2022-10-31 13:25:26 +01:00
|
|
|
yield { wallet };
|
2021-09-23 15:05:10 +02:00
|
|
|
walletFound = true;
|
|
|
|
} else {
|
|
|
|
break; // don't check second account if first one is empty
|
|
|
|
}
|
|
|
|
}
|
2021-03-25 16:28:25 +01:00
|
|
|
}
|
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
// m/0' p2pkh is a special case. It could be regular a HD wallet or a BRD wallet.
|
|
|
|
// to decide which one is it let's compare number of transactions
|
|
|
|
const m0Legacy = new HDLegacyP2PKHWallet();
|
|
|
|
m0Legacy.setSecret(text);
|
2024-02-11 19:39:44 +01:00
|
|
|
if (password) {
|
|
|
|
m0Legacy.setPassphrase(password);
|
|
|
|
}
|
2021-09-23 15:05:10 +02:00
|
|
|
m0Legacy.setDerivationPath("m/0'");
|
|
|
|
yield { progress: "bip39 p2pkh m/0'" };
|
|
|
|
// BRD doesn't support passphrase and only works with 12 words seeds
|
2024-11-10 21:07:17 +01:00
|
|
|
// do not try to guess BRD wallet in offline mode
|
|
|
|
if (!password && text.split(' ').length === 12 && !offline) {
|
2021-09-23 15:05:10 +02:00
|
|
|
const brd = new HDLegacyBreadwalletWallet();
|
|
|
|
brd.setSecret(text);
|
|
|
|
|
2024-11-10 21:07:17 +01:00
|
|
|
if (await wasUsed(m0Legacy)) {
|
2021-09-23 15:05:10 +02:00
|
|
|
await m0Legacy.fetchBalance();
|
|
|
|
await m0Legacy.fetchTransactions();
|
|
|
|
yield { progress: 'BRD' };
|
|
|
|
await brd.fetchBalance();
|
|
|
|
await brd.fetchTransactions();
|
|
|
|
if (brd.getTransactions().length > m0Legacy.getTransactions().length) {
|
|
|
|
yield { wallet: brd };
|
|
|
|
} else {
|
|
|
|
yield { wallet: m0Legacy };
|
|
|
|
}
|
|
|
|
walletFound = true;
|
|
|
|
}
|
|
|
|
} else {
|
2024-11-10 21:07:17 +01:00
|
|
|
if (await wasUsed(m0Legacy)) {
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { wallet: m0Legacy };
|
|
|
|
walletFound = true;
|
|
|
|
}
|
2021-03-25 16:28:25 +01:00
|
|
|
}
|
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
// if we havent found any wallet for this seed suggest new bech32 wallet
|
|
|
|
if (!walletFound) {
|
|
|
|
yield { wallet: hd2 };
|
2021-03-25 16:28:25 +01:00
|
|
|
}
|
2020-10-15 13:14:55 +02:00
|
|
|
}
|
2019-12-27 03:21:07 +01:00
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { progress: 'wif' };
|
2020-10-15 13:14:55 +02:00
|
|
|
const segwitWallet = new SegwitP2SHWallet();
|
2021-09-23 15:05:10 +02:00
|
|
|
segwitWallet.setSecret(text);
|
2020-10-15 13:14:55 +02:00
|
|
|
if (segwitWallet.getAddress()) {
|
|
|
|
// ok its a valid WIF
|
2022-03-12 10:13:03 +01:00
|
|
|
let walletFound = false;
|
2019-12-27 03:21:07 +01:00
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { progress: 'wif p2wpkh' };
|
2020-10-15 13:14:55 +02:00
|
|
|
const segwitBech32Wallet = new SegwitBech32Wallet();
|
2021-09-23 15:05:10 +02:00
|
|
|
segwitBech32Wallet.setSecret(text);
|
2024-11-10 21:07:17 +01:00
|
|
|
if (await wasUsed(segwitBech32Wallet)) {
|
2020-10-15 13:14:55 +02:00
|
|
|
// yep, its single-address bech32 wallet
|
2024-11-10 21:07:17 +01:00
|
|
|
await fetch(segwitBech32Wallet, true);
|
2022-03-12 10:13:03 +01:00
|
|
|
walletFound = true;
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { wallet: segwitBech32Wallet };
|
2021-03-25 16:28:25 +01:00
|
|
|
}
|
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { progress: 'wif p2wpkh-p2sh' };
|
2024-11-10 21:07:17 +01:00
|
|
|
if (await wasUsed(segwitWallet)) {
|
2022-03-12 10:13:03 +01:00
|
|
|
// yep, its single-address p2wpkh wallet
|
2024-11-10 21:07:17 +01:00
|
|
|
await fetch(segwitWallet, true);
|
2022-03-12 10:13:03 +01:00
|
|
|
walletFound = true;
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { wallet: segwitWallet };
|
2019-12-27 03:21:07 +01:00
|
|
|
}
|
2021-03-25 16:28:25 +01:00
|
|
|
|
|
|
|
// default wallet is Legacy
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { progress: 'wif p2pkh' };
|
2021-03-25 16:28:25 +01:00
|
|
|
const legacyWallet = new LegacyWallet();
|
2021-09-23 15:05:10 +02:00
|
|
|
legacyWallet.setSecret(text);
|
2024-11-10 21:07:17 +01:00
|
|
|
if (await wasUsed(legacyWallet)) {
|
2022-03-12 10:13:03 +01:00
|
|
|
// yep, its single-address legacy wallet
|
2024-11-10 21:07:17 +01:00
|
|
|
await fetch(legacyWallet, true);
|
2022-03-12 10:13:03 +01:00
|
|
|
walletFound = true;
|
|
|
|
yield { wallet: legacyWallet };
|
|
|
|
}
|
|
|
|
|
|
|
|
// if no wallets was ever used, import all of them
|
|
|
|
if (!walletFound) {
|
|
|
|
yield { wallet: segwitBech32Wallet };
|
|
|
|
yield { wallet: segwitWallet };
|
|
|
|
yield { wallet: legacyWallet };
|
|
|
|
}
|
2020-10-15 13:14:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// case - WIF is valid, just has uncompressed pubkey
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { progress: 'wif p2pkh' };
|
2020-10-15 13:14:55 +02:00
|
|
|
const legacyWallet = new LegacyWallet();
|
2021-09-23 15:05:10 +02:00
|
|
|
legacyWallet.setSecret(text);
|
2020-10-15 13:14:55 +02:00
|
|
|
if (legacyWallet.getAddress()) {
|
2024-11-10 21:07:17 +01:00
|
|
|
await fetch(legacyWallet, true, true);
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { wallet: legacyWallet };
|
2020-10-15 13:14:55 +02:00
|
|
|
}
|
|
|
|
|
2021-05-13 21:53:29 +02:00
|
|
|
// maybe its a watch-only address?
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { progress: 'watch only' };
|
2021-05-13 21:53:29 +02:00
|
|
|
const watchOnly = new WatchOnlyWallet();
|
2021-09-23 15:05:10 +02:00
|
|
|
watchOnly.setSecret(text);
|
2021-05-13 21:53:29 +02:00
|
|
|
if (watchOnly.valid()) {
|
2024-11-10 21:07:17 +01:00
|
|
|
await fetch(watchOnly, true);
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { wallet: watchOnly };
|
|
|
|
}
|
|
|
|
|
|
|
|
// electrum p2wpkh-p2sh
|
|
|
|
yield { progress: 'electrum p2wpkh-p2sh' };
|
|
|
|
const el1 = new HDSegwitElectrumSeedP2WPKHWallet();
|
|
|
|
el1.setSecret(text);
|
2024-02-11 19:39:44 +01:00
|
|
|
if (password) {
|
|
|
|
el1.setPassphrase(password);
|
|
|
|
}
|
2021-09-23 15:05:10 +02:00
|
|
|
if (el1.validateMnemonic()) {
|
|
|
|
yield { wallet: el1 }; // not fetching txs or balances, fuck it, yolo, life is too short
|
|
|
|
}
|
|
|
|
|
|
|
|
// electrum p2wpkh-p2sh
|
|
|
|
yield { progress: 'electrum p2pkh' };
|
|
|
|
const el2 = new HDLegacyElectrumSeedP2PKHWallet();
|
|
|
|
el2.setSecret(text);
|
2024-02-11 19:39:44 +01:00
|
|
|
if (password) {
|
|
|
|
el2.setPassphrase(password);
|
|
|
|
}
|
2021-09-23 15:05:10 +02:00
|
|
|
if (el2.validateMnemonic()) {
|
|
|
|
yield { wallet: el2 }; // not fetching txs or balances, fuck it, yolo, life is too short
|
2021-05-13 21:53:29 +02:00
|
|
|
}
|
2019-12-27 03:21:07 +01:00
|
|
|
|
2021-01-28 13:54:23 +01:00
|
|
|
// is it AEZEED?
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { progress: 'aezeed' };
|
|
|
|
const aezeed2 = new HDAezeedWallet();
|
|
|
|
aezeed2.setSecret(text);
|
2024-02-11 19:39:44 +01:00
|
|
|
if (password) {
|
|
|
|
aezeed2.setPassphrase(password);
|
|
|
|
}
|
2021-09-23 15:05:10 +02:00
|
|
|
if (await aezeed2.validateMnemonicAsync()) {
|
|
|
|
yield { wallet: aezeed2 }; // not fetching txs or balances, fuck it, yolo, life is too short
|
|
|
|
}
|
2021-01-28 13:54:23 +01:00
|
|
|
|
2024-06-02 21:31:14 +02:00
|
|
|
// Let's try SLIP39
|
2021-09-23 15:05:10 +02:00
|
|
|
yield { progress: 'SLIP39' };
|
2024-06-02 21:31:14 +02:00
|
|
|
const s1 = new SLIP39SegwitP2SHWallet();
|
|
|
|
s1.setSecret(text);
|
2021-04-15 19:52:48 +02:00
|
|
|
|
2024-06-02 21:31:14 +02:00
|
|
|
if (s1.validateMnemonic()) {
|
|
|
|
yield { progress: 'SLIP39 p2wpkh-p2sh' };
|
|
|
|
if (password) {
|
|
|
|
s1.setPassphrase(password);
|
|
|
|
}
|
2024-11-10 21:07:17 +01:00
|
|
|
if (await wasUsed(s1)) {
|
2024-06-02 21:31:14 +02:00
|
|
|
yield { wallet: s1 };
|
|
|
|
}
|
2021-04-15 19:52:48 +02:00
|
|
|
|
2024-06-02 21:31:14 +02:00
|
|
|
yield { progress: 'SLIP39 p2pkh' };
|
|
|
|
const s2 = new SLIP39LegacyP2PKHWallet();
|
|
|
|
if (password) {
|
|
|
|
s2.setPassphrase(password);
|
|
|
|
}
|
|
|
|
s2.setSecret(text);
|
2024-11-10 21:07:17 +01:00
|
|
|
if (await wasUsed(s2)) {
|
2024-06-02 21:31:14 +02:00
|
|
|
yield { wallet: s2 };
|
|
|
|
}
|
2021-04-15 19:52:48 +02:00
|
|
|
|
2024-06-02 21:31:14 +02:00
|
|
|
yield { progress: 'SLIP39 p2wpkh' };
|
|
|
|
const s3 = new SLIP39SegwitBech32Wallet();
|
|
|
|
s3.setSecret(text);
|
|
|
|
if (password) {
|
|
|
|
s3.setPassphrase(password);
|
2021-04-15 19:52:48 +02:00
|
|
|
}
|
2024-06-02 21:31:14 +02:00
|
|
|
yield { wallet: s3 };
|
2021-04-15 19:52:48 +02:00
|
|
|
}
|
2023-04-26 22:58:41 +02:00
|
|
|
|
|
|
|
// is it BC-UR payload with multiple accounts?
|
|
|
|
yield { progress: 'BC-UR' };
|
|
|
|
try {
|
|
|
|
const json = JSON.parse(text);
|
|
|
|
if (Array.isArray(json)) {
|
|
|
|
for (const account of json) {
|
|
|
|
if (account.ExtPubKey && account.MasterFingerprint && account.AccountKeyPath) {
|
|
|
|
const wallet = new WatchOnlyWallet();
|
|
|
|
wallet.setSecret(JSON.stringify(account));
|
|
|
|
wallet.init();
|
|
|
|
yield { wallet };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (_) {}
|
2021-09-23 15:05:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// POEHALI
|
|
|
|
(async () => {
|
|
|
|
const generator = importGenerator();
|
|
|
|
while (true) {
|
|
|
|
const next = await generator.next();
|
|
|
|
if (!running) throw new Error('Discovery stopped'); // break if stop() has been called
|
|
|
|
if (next.value?.progress) reportProgress(next.value.progress);
|
|
|
|
if (next.value?.wallet) reportWallet(next.value.wallet);
|
|
|
|
if (next.done) break; // break if generator has been finished
|
2024-11-10 21:07:17 +01:00
|
|
|
await new Promise(resolve => setTimeout(resolve, 1)); // try not to block the thread
|
2021-09-23 15:05:10 +02:00
|
|
|
}
|
|
|
|
reportFinish();
|
|
|
|
})().catch(e => {
|
|
|
|
if (e.message === 'Cancel Pressed') {
|
|
|
|
reportFinish(true);
|
|
|
|
return;
|
|
|
|
} else if (e.message === 'Discovery stopped') {
|
|
|
|
reportFinish(undefined, true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
promiseReject(e);
|
|
|
|
});
|
2021-04-15 19:52:48 +02:00
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
return { promise, stop };
|
|
|
|
};
|
2020-10-24 19:20:59 +02:00
|
|
|
|
2021-09-23 15:05:10 +02:00
|
|
|
export default startImport;
|