@aladas-org/cryptocalc
Version:
Cryptocurrency wallet generator
265 lines (211 loc) • 11.3 kB
JavaScript
// ============================================================================================================================================
// ===================================================== hd_wallet.js =====================================================
// ============================================================================================================================================
;
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'