UNPKG

@aladas-org/cryptocalc

Version:
265 lines (211 loc) 11.3 kB
// ============================================================================================================================================ // ===================================================== hd_wallet.js ===================================================== // ============================================================================================================================================ "use strict"; const bip39 = require('bip39'); const bs58check = require('bs58check'); const bs58 = require('bs58'); const { _RED_, _CYAN_, _PURPLE_, _YELLOW_, _END_ } = require('../../util/color/color_console_codes.js'); const { pretty_func_header_log, pretty_log } = require('../../util/log/log_utils.js'); const { COIN, COIN_TYPE, ETHEREUM, BINANCE_BSC, ETHEREUM_CLASSIC, BITCOIN, DOGECOIN, LITECOIN, SOLANA, CARDANO, STELLAR, SUI, RIPPLE, TON, DASH, VECHAIN, FIRO, TRON, AVALANCHE, POLYGON, BITCOIN_CASH, BITCOIN_SV, RAVENCOIN, HORIZEN, MAINNET, COIN_ABBREVIATIONS } = require('../const_blockchains.js'); const { NULL_HEX, CRYPTO_NET, ADDRESS, PRIVATE_KEY, PUBLIC_KEY_HEX, PRIV_KEY } = require('../const_wallet.js'); const { BLOCKCHAIN, NULL_BLOCKCHAIN, WALLET_MODE, HD_WALLET_TYPE, UUID, MNEMONICS, WIF, BIP32_PROTOCOL, BIP32_PASSPHRASE, ACCOUNT, ADDRESS_INDEX, DERIVATION_PATH } = require('../../const_keywords.js'); const { hexWithoutPrefix, uint8ArrayToHex, hexToUint8Array } = require('../hex_utils.js'); const { Bip39Utils } = require('../bip39_utils.js'); const { Bip32Utils } = require('./bip32_utils.js'); const { CardanoHD_API } = require('./cardano_hd_api.js'); const { SolanaHD_API } = require('./solana_hd_api.js'); const { Sui_HD_API } = require('./sui_hd_api.js'); const btcToZec = (btcAddress) => { // Decode the BTC address // const decoded = bs58check.decode(btcAddress); const decoded = bs58.decode(btcAddress); // Get the payload (without the BTC version byte) const payload = decoded.slice(1); // Determine the ZEC version byte based on BTC address type let zecVersion; // P2PKH (starts with '1') if (btcAddress.startsWith('1')) { zecVersion = 0x1cb8; // ZEC P2PKH version bytes } // P2SH (starts with '3') else if (btcAddress.startsWith('3')) { zecVersion = 0x1cbd; // ZEC P2SH version bytes } // Bech32 (starts with 'bc1') - not supported in ZEC else if (btcAddress.startsWith('bc1')) { throw new Error('Bech32 addresses cannot be converted to ZEC'); } else { throw new Error('Unrecognized BTC address format'); } // Create a buffer with ZEC version bytes // Note: ZEC uses 2-byte version prefixes const versionBuffer = Buffer.alloc(2); versionBuffer.writeUInt16BE(zecVersion, 0); // Combine the version and payload const zecData = Buffer.concat([versionBuffer, payload]); // Encode to Base58Check return bs58.encode(zecData); // return bs58check.encode(zecData); }; // btcToZec() // https://runkit.com/gojomo/baddr2taddr /** * Converts a Bitcoin "Pay To Public Key Hash" (P2PKH) public * address to a ZCash t-address. (Such Bitcoin addresses always * start with a '1'. * * The same private key (aka "spending key") that generated * the Bitcoin address can be used to control funds associated * with the ZCash t-address. (This requires a ZCash wallet system * which allows that private key to be imported. For example, * zcashd with its `importprivkey` function) */ const btc_addr_to_t_zcash_addr = ( btc_addr_str ) => { if ( ! btc_addr_str[0] == '1' ) throw new Error("not a supported Bitcoin address"); pretty_log("> btc_addr_to_t_zcash_addr: btc_addr_str: " , btc_addr_str); //let btc_addr = bs58check.decode(btc_addr_str).slice(1); // discard type byte let btc_addr = bs58.decode(btc_addr_str); // discard type byte pretty_log("> btc_addr_to_t_zcash_addr: A btc_addr: JSON " ,JSON.stringify(btc_addr)); btc_addr = btc_addr.slice(1); // discard type byte pretty_log("> btc_addr_to_t_zcash_addr: B btc_addr: JSON " , JSON.stringify(btc_addr)); // btc_addr = btc_addr.slice(2); // discard 2 bytes btc_addr = btc_addr.slice(2,22); // discard 2 bytes pretty_log("> btc_addr_to_t_zcash_addr: C btc_addr: JSON " , JSON.stringify(btc_addr)); let zcash_t_addr = new Uint8Array(22); pretty_log("> btc_addr_to_t_zcash_addr: 1 zcash_t_addr: " , JSON.stringify(zcash_t_addr)); // zcash_t_addr.set(btc_addr, 2); zcash_t_addr.set(btc_addr,2); pretty_log("> btc_addr_to_t_zcash_addr: 2 zcash_t_addr: " , JSON.stringify(zcash_t_addr)); zcash_t_addr.set([0x1c,0xb8], 0); // set zcash type bytes pretty_log("> btc_addr_to_t_zcash_addr: 3 zcash_t_addr: " , JSON.stringify(zcash_t_addr)); return bs58.encode(Buffer.from(zcash_t_addr)); }; // btc_addr_to_t_zcash_addr (BTC to ZCASH address) class HDWallet { // static async GetWallet( entropy_hex, salt_uuid, blockchain, crypto_net, bip32_passphrase, account, address_index, bip32_protocol ) { static async GetWallet( entropy_hex, salt_uuid, args ) { if ( entropy_hex == undefined || entropy_hex == "" ) { throw new Error("HDWallet.GetWallet 'entropy_hex' NOT DEFINED"); } if ( salt_uuid == undefined || salt_uuid == "" ) { throw new Error("HDWallet.GetWallet 'salt_uuid' NOT DEFINED"); } // let options = { [BLOCKCHAIN]: blockchain, [CRYPTO_NET]: crypto_net, [BIP32_PASSPHRASE]: bip32_passphrase, [ACCOUNT]: account, [ADDRESS_INDEX]: address_index }; let crypto_net = ( args[CRYPTO_NET] != undefined ) ? args[CRYPTO_NET] : MAINNET; let blockchain = ( args[BLOCKCHAIN] != undefined ) ? args[BLOCKCHAIN] : BITCOIN; let bip32_protocol = ( args[BIP32_PROTOCOL] != undefined ) ? args[BIP32_PROTOCOL] : 44; let bip32_passphrase = ( args[BIP32_PASSPHRASE] != undefined ) ? args[BIP32_PASSPHRASE] : ""; let account = ( args[ACCOUNT] != undefined ) ? args[ACCOUNT] : 0; let address_index = ( args[ADDRESS_INDEX] != undefined ) ? args[ADDRESS_INDEX] : 0; let coin = COIN_ABBREVIATIONS[blockchain]; pretty_func_header_log( "++++++++++++ HDWallet.GetWallet", blockchain + " " + coin + " " + crypto_net ); pretty_log( "hdw.gw> bip32_protocol", bip32_protocol ); //pretty_log( "hdw.gw> entropy_hex", entropy_hex ); let mnemonics = Bip39Utils.EntropyToMnemonics( entropy_hex ); let mnemonics_items = Bip39Utils.MnemonicsAsTwoParts( mnemonics ); pretty_log( "hdw.gw> mnemonics", mnemonics_items[0] ); if ( mnemonics_items[1].length > 0 ) { pretty_log( "", mnemonics_items[1] ); } pretty_log( "hdw.gw> blockchain", blockchain ); // pretty_log( "hdw.gw> account", account ); // pretty_log( "hdw.gw> address_index", address_index ); let options = { [BLOCKCHAIN]: blockchain, [BIP32_PROTOCOL]: bip32_protocol, [BIP32_PASSPHRASE]: bip32_passphrase, [ACCOUNT]: account, [ADDRESS_INDEX]: address_index, [UUID]: salt_uuid }; let new_wallet = HDWallet.InitializeWallet(); new_wallet[WALLET_MODE] = HD_WALLET_TYPE; new_wallet[BLOCKCHAIN] = blockchain; new_wallet[MNEMONICS] = mnemonics; new_wallet[CRYPTO_NET] = crypto_net; if ( blockchain == BITCOIN || blockchain == ETHEREUM || blockchain == BINANCE_BSC || blockchain == AVALANCHE || blockchain == POLYGON || blockchain == DOGECOIN || blockchain == LITECOIN || blockchain == ETHEREUM_CLASSIC || blockchain == STELLAR || blockchain == RIPPLE || blockchain == TRON || blockchain == BITCOIN_CASH || blockchain == BITCOIN_SV || blockchain == RAVENCOIN || blockchain == VECHAIN || blockchain == DASH || blockchain == FIRO ) { if ( blockchain == AVALANCHE || blockchain == POLYGON || blockchain == BINANCE_BSC ) { options[BLOCKCHAIN] = ETHEREUM } // let blockchain_was_ZCASH = false; // if (blockchain == ZCASH) { // options[BLOCKCHAIN] = BITCOIN; // blockchain_was_ZCASH = true; // } // Trap "console.warn" let save_console_warn = console.warn; console.warn = () => {}; let hdwallet_info = await Bip32Utils.MnemonicsToHDWalletInfo( mnemonics, options ); console.warn = save_console_warn; //console.log(" >> hdwallet_info:\n" + JSON.stringify(hdwallet_info)); new_wallet[ADDRESS] = hdwallet_info[ADDRESS]; // if ( blockchain_was_ZCASH ) { // // new_wallet[ADDRESS] = btc_addr_to_t_zcash_addr(hdwallet_info[ADDRESS]); // new_wallet[ADDRESS] = btcToZec(hdwallet_info[ADDRESS]); // } pretty_log("hdw.gw> wallet address", new_wallet[ADDRESS]); // pretty_log("hdw.gw> wallet address", new_wallet[ADDRESS]); new_wallet[COIN] = hdwallet_info[COIN]; new_wallet[COIN_TYPE] = hdwallet_info[COIN_TYPE]; if ( hdwallet_info[BIP32_PASSPHRASE] != undefined && hdwallet_info[BIP32_PASSPHRASE] != "") { new_wallet[BIP32_PASSPHRASE] = hdwallet_info[BIP32_PASSPHRASE]; } new_wallet[PRIVATE_KEY] = hdwallet_info[PRIVATE_KEY]; new_wallet[DERIVATION_PATH] = hdwallet_info[DERIVATION_PATH]; // pretty_log("hdw.gw> derivation_path", new_wallet[DERIVATION_PATH]); new_wallet[WIF] = hdwallet_info[WIF]; pretty_log("hdw.gw> WIF", new_wallet[WIF]); new_wallet[PRIV_KEY] = hdwallet_info[PRIV_KEY]; } else if ( blockchain == CARDANO ) { new_wallet = await CardanoHD_API.GetWallet ( entropy_hex, salt_uuid, blockchain, crypto_net, bip32_passphrase, account, address_index ); } else if ( blockchain == SOLANA ) { new_wallet = await SolanaHD_API.GetWallet ( entropy_hex, salt_uuid, blockchain, crypto_net, bip32_passphrase, account, address_index ); } else if ( blockchain == SUI ) { new_wallet = await Sui_HD_API.GetWallet ( entropy_hex, salt_uuid, blockchain, crypto_net, bip32_passphrase, account, address_index ); } return new_wallet; } // HDWallet.GetWallet() static InitializeWallet() { let null_wallet = {}; null_wallet[BLOCKCHAIN] = NULL_BLOCKCHAIN; null_wallet[CRYPTO_NET] = "Null-NET"; null_wallet[UUID] = "Null-UUID"; null_wallet[PRIVATE_KEY] = NULL_HEX; null_wallet[PUBLIC_KEY_HEX] = NULL_HEX; null_wallet[BIP32_PROTOCOL] = 44; null_wallet[ADDRESS] = "Null-ADDRESS"; null_wallet[MNEMONICS] = "Null-MNEMONICS"; return null_wallet; } // HDWallet.InitializeWallet() } // HDWallet class if (typeof exports === 'object') { exports.HDWallet = HDWallet } // exports of 'hd_wallet.js'