From 4bcdc9b653ea5cf1f44681a169675cdf43d589bb Mon Sep 17 00:00:00 2001 From: guptamukund22 Date: Wed, 17 Apr 2024 00:33:28 +0530 Subject: [PATCH 1/6] HDW --- bitcoinutils/hdwallet.py | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/bitcoinutils/hdwallet.py b/bitcoinutils/hdwallet.py index 3b4e168b..357b1f26 100644 --- a/bitcoinutils/hdwallet.py +++ b/bitcoinutils/hdwallet.py @@ -17,10 +17,34 @@ from bitcoinutils.setup import is_mainnet from bitcoinutils.keys import PrivateKey - -# class HDW: -# """Implements mnemonic codes (BIP-39) and hierarchical deterministic -# wallet (BIP-32)""" +from mnemonic import Mnemonic +from Crypto.Protocol.KDF import PBKDF2 +from Crypto.Hash import SHA512 +import binascii + +class HDW: + """Implements mnemonic codes (BIP-39) and hierarchical deterministic wallet (BIP-32).""" + + def __init__(self, language='english'): + """Initialize the HDWallet with a specific language for the mnemonic.""" + self.mnemonic_generator = Mnemonic(language) + + def generate_mnemonic(self, words=12): + """Generate a mnemonic phrase.""" + return self.mnemonic_generator.generate(strength={12: 128, 15: 160, 18: 192, 21: 224, 24: 256}[words]) + + def mnemonic_to_seed(self, mnemonic, passphrase=''): + """Convert mnemonic phrase to seed.""" + return PBKDF2(mnemonic, 'mnemonic' + passphrase, dkLen=64, count=2048, hmac_hash_module=SHA512) + + def create_wallet(self, words=12, passphrase=''): + """Create a new wallet with a mnemonic and derive the seed.""" + mnemonic = self.generate_mnemonic(words) + seed = self.mnemonic_to_seed(mnemonic, passphrase) + return { + 'mnemonic': mnemonic, + 'seed': binascii.hexlify(seed).decode('utf-8') + } class HDWallet: From ffe93e9cb8889dfef2a459a6830edaf08ddf3446 Mon Sep 17 00:00:00 2001 From: guptamukund22 Date: Mon, 29 Apr 2024 19:41:57 +0530 Subject: [PATCH 2/6] from_seed --- bitcoinutils/hdwallet.py | 42 ++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/bitcoinutils/hdwallet.py b/bitcoinutils/hdwallet.py index 357b1f26..149d0dbe 100644 --- a/bitcoinutils/hdwallet.py +++ b/bitcoinutils/hdwallet.py @@ -17,35 +17,23 @@ from bitcoinutils.setup import is_mainnet from bitcoinutils.keys import PrivateKey -from mnemonic import Mnemonic -from Crypto.Protocol.KDF import PBKDF2 -from Crypto.Hash import SHA512 -import binascii +import hashlib +import hmac +from binascii import unhexlify class HDW: - """Implements mnemonic codes (BIP-39) and hierarchical deterministic wallet (BIP-32).""" - - def __init__(self, language='english'): - """Initialize the HDWallet with a specific language for the mnemonic.""" - self.mnemonic_generator = Mnemonic(language) - - def generate_mnemonic(self, words=12): - """Generate a mnemonic phrase.""" - return self.mnemonic_generator.generate(strength={12: 128, 15: 160, 18: 192, 21: 224, 24: 256}[words]) - - def mnemonic_to_seed(self, mnemonic, passphrase=''): - """Convert mnemonic phrase to seed.""" - return PBKDF2(mnemonic, 'mnemonic' + passphrase, dkLen=64, count=2048, hmac_hash_module=SHA512) - - def create_wallet(self, words=12, passphrase=''): - """Create a new wallet with a mnemonic and derive the seed.""" - mnemonic = self.generate_mnemonic(words) - seed = self.mnemonic_to_seed(mnemonic, passphrase) - return { - 'mnemonic': mnemonic, - 'seed': binascii.hexlify(seed).decode('utf-8') - } - + def __init__(self, seed): + seed_bytes = unhexlify(seed) # Convert hex string to bytes + self.seed = seed_bytes + self.master_private_key, self.master_chain_code = self.from_seed(seed_bytes) + + def from_seed(self, seed_bytes): + """ Generate the master keys from the seed bytes """ + key = b"Bitcoin seed" + h = hmac.new(key, seed_bytes, hashlib.sha512).digest() + master_private_key = h[:32] + master_chain_code = h[32:] + return master_private_key, master_chain_code class HDWallet: """Wraps the python hdwallet library to provide basic HD wallet functionality From d468626fd9e22b22234580ff8440ae6054bc841d Mon Sep 17 00:00:00 2001 From: guptamukund22 Date: Wed, 1 May 2024 17:59:49 +0530 Subject: [PATCH 3/6] from_mnemonic --- bitcoinutils/hdwallet.py | 74 +++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 9 deletions(-) diff --git a/bitcoinutils/hdwallet.py b/bitcoinutils/hdwallet.py index d37e7976..3c178359 100644 --- a/bitcoinutils/hdwallet.py +++ b/bitcoinutils/hdwallet.py @@ -23,32 +23,49 @@ import unicodedata class HDW: - def __init__(self, seed): - seed_bytes = unhexlify(seed) # Convert hex string to bytes - self.seed = seed_bytes - self.master_private_key, self.master_chain_code = self.from_seed(seed_bytes) + def __init__(self, seed: Optional[str] = None): + """ + Initialize the HD Wallet with a seed if provided. + + Args: + seed (Optional[str]): A hexadecimal string representing the seed from which the HD Wallet will derive its keys. + """ + self.strength: Optional[int] = None + if seed: + seed_bytes = unhexlify(seed) # Convert hex string to bytes + self.seed = seed_bytes + # Generate the master private key and master chain code from the seed. + self.master_private_key, self.master_chain_code = self.from_seed(seed_bytes) def from_seed(self, seed_bytes): - """ Generate the master keys from the seed bytes """ + """ + Generate the master keys from the seed bytes. + + Args: + seed_bytes (bytes): Seed from which the master private key and chain code are derived. + + Returns: + tuple: Tuple containing (master_private_key, master_chain_code). + """ + key = b"Bitcoin seed" h = hmac.new(key, seed_bytes, hashlib.sha512).digest() + # Split the hash into two halves: private key and chain code. master_private_key = h[:32] master_chain_code = h[32:] return master_private_key, master_chain_code @staticmethod - def get_mnemonic_strength(mnemonic: str, language: str = None) -> int: + def get_mnemonic_strength(mnemonic: str) -> int: """ Get mnemonic strength. :param mnemonic: Mnemonic words. :type mnemonic: str - :param language: Mnemonic language, default to None. - :type language: str :returns: int -- Mnemonic strength. """ - + words = len(unicodedata.normalize("NFKD", mnemonic).split(" ")) if words == 12: return 128 @@ -63,6 +80,45 @@ def get_mnemonic_strength(mnemonic: str, language: str = None) -> int: else: raise ValueError("Unsupported number of words in mnemonic.") + def from_mnemonic(self, mnemonic: str, passphrase: str = "") -> "HDW": + """ + Create keys from a mnemonic phrase. + + Args: + mnemonic (str): Mnemonic phrase used to generate the seed. + passphrase (str): Additional passphrase used with the mnemonic for added security. + + Returns: + HDW: Returns itself after initializing the master keys. + """ + + self.strength = self.get_mnemonic_strength(mnemonic=self._mnemonic) + normalized_mnemonic = unicodedata.normalize("NFKD", mnemonic) + seed = self.to_seed(normalized_mnemonic, passphrase) + self.master_private_key, self.master_chain_code = self.from_seed(seed) + return self + + def to_seed(self, mnemonic: str, passphrase: str = "") -> bytes: + """ + Generate a seed from a mnemonic and a passphrase. + + Args: + mnemonic (str): Mnemonic phrase. + passphrase (str): Optional passphrase for additional security. + + Returns: + bytes: The seed generated from the mnemonic and passphrase. + """ + + passphrase = "mnemonic" + passphrase + mnemonic_bytes = mnemonic.encode("utf-8") + passphrase_bytes = passphrase.encode("utf-8") + #PBKDF2 HMAC-SHA512 to derive the seed from the mnemonic and passphrase. + stretched = hashlib.pbkdf2_hmac( + "sha512", mnemonic_bytes, passphrase_bytes, 2048 + ) + return stretched[:64] + class HDWallet: """Wraps the python hdwallet library to provide basic HD wallet functionality From 4a832f164b6bbaa625a510cb3e6c2c7f07e462fb Mon Sep 17 00:00:00 2001 From: guptamukund22 Date: Wed, 1 May 2024 18:48:01 +0530 Subject: [PATCH 4/6] from_xprivate_key --- bitcoinutils/hdwallet.py | 67 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/bitcoinutils/hdwallet.py b/bitcoinutils/hdwallet.py index 3c178359..8b7a6644 100644 --- a/bitcoinutils/hdwallet.py +++ b/bitcoinutils/hdwallet.py @@ -19,8 +19,11 @@ import hashlib import hmac -from binascii import unhexlify +from binascii import unhexlify, b2a_hex import unicodedata +import ecdsa +import struct +from ecdsa.curves import SECP256k1 class HDW: def __init__(self, seed: Optional[str] = None): @@ -31,6 +34,9 @@ def __init__(self, seed: Optional[str] = None): seed (Optional[str]): A hexadecimal string representing the seed from which the HD Wallet will derive its keys. """ self.strength: Optional[int] = None + self._depth: int = 0 + self._index: int = 0 + self._parent_fingerprint: bytes = b"\0\0\0\0" if seed: seed_bytes = unhexlify(seed) # Convert hex string to bytes self.seed = seed_bytes @@ -92,9 +98,9 @@ def from_mnemonic(self, mnemonic: str, passphrase: str = "") -> "HDW": HDW: Returns itself after initializing the master keys. """ + self._mnemonic = unicodedata.normalize("NFKD", mnemonic) self.strength = self.get_mnemonic_strength(mnemonic=self._mnemonic) - normalized_mnemonic = unicodedata.normalize("NFKD", mnemonic) - seed = self.to_seed(normalized_mnemonic, passphrase) + seed = self.to_seed(self._mnemonic, passphrase) self.master_private_key, self.master_chain_code = self.from_seed(seed) return self @@ -118,6 +124,61 @@ def to_seed(self, mnemonic: str, passphrase: str = "") -> bytes: "sha512", mnemonic_bytes, passphrase_bytes, 2048 ) return stretched[:64] + + @staticmethod + def _deserialize_xprivate_key(xprivate_key: str, encoded: bool = True) -> tuple: + """ + Deserialize an extended private key (xprivate key). + + Args: + xprivate_key (str): The xprivate key as a string. + encoded (bool): Flag indicating if the xprivate key is hex-encoded. + + Returns: + tuple: A tuple containing different parts of the xprivate key. + + Raises: + ValueError: If the xprivate key is invalid or improperly sized. + """ + decoded_xprivate_key = b2a_hex(xprivate_key) if encoded else xprivate_key + if len(decoded_xprivate_key) != 156: + raise ValueError("Invalid xprivate key.") + return ( + decoded_xprivate_key[:4], # Version bytes + decoded_xprivate_key[4:5], # Depth + decoded_xprivate_key[5:9], # Parent fingerprint + decoded_xprivate_key[9:13], # Child number (index) + decoded_xprivate_key[13:45], # Private key data + decoded_xprivate_key[46:] # Chain code + ) + + def from_xprivate_key(self, xprivate_key: str, strict: bool = False) -> "HDW": + """ + Initialize the HD wallet from an extended private key (xprivate key). + + Args: + xprivate_key (str): The xprivate key as a string. + strict (bool): If True, the xprivate key must be a root key. + + Returns: + HDW: An instance of the HDWallet class initialized with the xprivate key. + + Raises: + ValueError: If strict checking is enabled and the key is not a root key. + """ + _parts = self._deserialize_xprivate_key(xprivate_key) + if strict and _parts[0] != b'\x04\x88\xAD\xE4': # version bytes for xprv + raise ValueError("Invalid root xprivate key.") + + self._depth, self._parent_fingerprint, self._index = ( + int.from_bytes(_parts[1], "big"), + _parts[2], + struct.unpack(">L", _parts[3])[0] + ) + self.master_private_key, self.master_chain_code = _parts[4][:32], _parts[4][32:] + self._key = ecdsa.SigningKey.from_string(self.master_private_key, curve=ecdsa.SECP256k1) + self._verified_key = self._key.get_verifying_key() + return self class HDWallet: """Wraps the python hdwallet library to provide basic HD wallet functionality From 4a2198ccaee1e2dec10c8f5b82b14604116ebe62 Mon Sep 17 00:00:00 2001 From: guptamukund22 Date: Thu, 2 May 2024 04:43:57 +0530 Subject: [PATCH 5/6] HDW --- bitcoinutils/constants.py | 2 + bitcoinutils/hdwallet.py | 185 +++++++++++++++++++++++++++++++------- 2 files changed, 154 insertions(+), 33 deletions(-) diff --git a/bitcoinutils/constants.py b/bitcoinutils/constants.py index ffcf4bee..0bb11904 100644 --- a/bitcoinutils/constants.py +++ b/bitcoinutils/constants.py @@ -87,3 +87,5 @@ # Monetary constants SATOSHIS_PER_BITCOIN = 100000000 NEGATIVE_SATOSHI = -1 + +BIP32KEY_HARDEN = 0x80000000 \ No newline at end of file diff --git a/bitcoinutils/hdwallet.py b/bitcoinutils/hdwallet.py index 8b7a6644..15c5170e 100644 --- a/bitcoinutils/hdwallet.py +++ b/bitcoinutils/hdwallet.py @@ -11,11 +11,9 @@ from typing import Optional -from hdwallet import HDWallet as ext_HDWallet # type: ignore -from hdwallet.symbols import BTC, BTCTEST # type: ignore - from bitcoinutils.setup import is_mainnet from bitcoinutils.keys import PrivateKey +from bitcoinutils.constants import BIP32KEY_HARDEN import hashlib import hmac @@ -24,9 +22,11 @@ import ecdsa import struct from ecdsa.curves import SECP256k1 +from ecdsa.util import string_to_number, number_to_string +import base58 class HDW: - def __init__(self, seed: Optional[str] = None): + def __init__(self): """ Initialize the HD Wallet with a seed if provided. @@ -37,13 +37,12 @@ def __init__(self, seed: Optional[str] = None): self._depth: int = 0 self._index: int = 0 self._parent_fingerprint: bytes = b"\0\0\0\0" - if seed: - seed_bytes = unhexlify(seed) # Convert hex string to bytes - self.seed = seed_bytes - # Generate the master private key and master chain code from the seed. - self.master_private_key, self.master_chain_code = self.from_seed(seed_bytes) + self.master_private_key : Optional[str] = None + self.master_chain_code : Optional[str] = None + self.seed : Optional[str] = None + self._root_private_key: Optional[tuple] = None - def from_seed(self, seed_bytes): + def from_seed(self, seed : str): """ Generate the master keys from the seed bytes. @@ -53,12 +52,15 @@ def from_seed(self, seed_bytes): Returns: tuple: Tuple containing (master_private_key, master_chain_code). """ - + self.seed = seed + seed_bytes = unhexlify(seed) key = b"Bitcoin seed" h = hmac.new(key, seed_bytes, hashlib.sha512).digest() # Split the hash into two halves: private key and chain code. master_private_key = h[:32] master_chain_code = h[32:] + self._root_private_key = (master_private_key, master_chain_code) + self.master_private_key, self.master_chain_code = master_private_key, master_chain_code return master_private_key, master_chain_code @staticmethod @@ -100,7 +102,7 @@ def from_mnemonic(self, mnemonic: str, passphrase: str = "") -> "HDW": self._mnemonic = unicodedata.normalize("NFKD", mnemonic) self.strength = self.get_mnemonic_strength(mnemonic=self._mnemonic) - seed = self.to_seed(self._mnemonic, passphrase) + seed = self.to_seed(self._mnemonic, passphrase).hex() self.master_private_key, self.master_chain_code = self.from_seed(seed) return self @@ -140,16 +142,27 @@ def _deserialize_xprivate_key(xprivate_key: str, encoded: bool = True) -> tuple: Raises: ValueError: If the xprivate key is invalid or improperly sized. """ - decoded_xprivate_key = b2a_hex(xprivate_key) if encoded else xprivate_key - if len(decoded_xprivate_key) != 156: - raise ValueError("Invalid xprivate key.") + if encoded: + # Decode from Base58Check to bytes + try: + xprivate_key_bytes = base58.b58decode_check(xprivate_key) + except ValueError: + raise ValueError("Invalid Base58Check in xprivate key.") + else: + # If the key is not encoded, directly convert it assuming it's in UTF-8 format + xprivate_key_bytes = xprivate_key.encode() + + # Verify the length of the decoded xprivate key + if len(xprivate_key_bytes) != 78: + raise ValueError("Invalid xprivate key size.") + return ( - decoded_xprivate_key[:4], # Version bytes - decoded_xprivate_key[4:5], # Depth - decoded_xprivate_key[5:9], # Parent fingerprint - decoded_xprivate_key[9:13], # Child number (index) - decoded_xprivate_key[13:45], # Private key data - decoded_xprivate_key[46:] # Chain code + xprivate_key_bytes[:4], # Version bytes + xprivate_key_bytes[4:5], # Depth + xprivate_key_bytes[5:9], # Parent fingerprint + xprivate_key_bytes[9:13], # Child number (index) + xprivate_key_bytes[13:45], # Private key data + xprivate_key_bytes[46:] # Chain code ) def from_xprivate_key(self, xprivate_key: str, strict: bool = False) -> "HDW": @@ -175,10 +188,116 @@ def from_xprivate_key(self, xprivate_key: str, strict: bool = False) -> "HDW": _parts[2], struct.unpack(">L", _parts[3])[0] ) - self.master_private_key, self.master_chain_code = _parts[4][:32], _parts[4][32:] + self._root_private_key = (_parts[5], _parts[4]) + self._i = _parts[5] + _parts[4] + self.master_private_key, self.master_chain_code = self._i[:32], self._i[32:] self._key = ecdsa.SigningKey.from_string(self.master_private_key, curve=ecdsa.SECP256k1) self._verified_key = self._key.get_verifying_key() return self + + def from_path(self, path: str) -> 'HDW': + """ + Derive keys from a specified BIP32 path. + + Args: + path (Union[str, Derivation]): BIP32 path. + + Returns: + HDW: The HDWallet after deriving the specified path. + """ + path = path.lstrip("m/").split("/") if isinstance(path, str) else path.to_path() + for p in path: + index = int(p[:-1]) + BIP32KEY_HARDEN if "'" in p else int(p) + self = self._derive_key_by_index(index) + return self + + def _derive_key_by_index(self, index: int) -> 'HDW': + """ + Derive a child key by index. + + Args: + index (int): Index for the child key derivation. + + Returns: + HDW: New instance of HDWallet for the derived key. + """ + if index & BIP32KEY_HARDEN: # Hardened + data = b'\x00' + self.master_private_key + struct.pack('>L', index) + else: # Non-hardened + data = self._public_key_from_private(self.master_private_key) + struct.pack('>L', index) + + I = hmac.new(self.master_chain_code, data, hashlib.sha512).digest() + IL, IR = I[:32], I[32:] + new_priv_key = (string_to_number(IL) + string_to_number(self.master_private_key)) % SECP256k1.order + if new_priv_key == 0: + raise Exception("Invalid child key derived") + + # Update the instance's keys and chain code + self.master_private_key = new_priv_key.to_bytes(32, 'big') + self.master_chain_code = IR + + # Update the public and private keys + self._key = ecdsa.SigningKey.from_string(self.master_private_key, curve=SECP256k1) + self._verified_key = self._key.get_verifying_key() + + return self # Return the updated instance + + def _public_key_from_private(self, private_key): + """ + Generate the public key corresponding to the given private key, in compressed format. + + Args: + private_key (bytes): Private key. + + Returns: + bytes: Compressed public key. + """ + sk = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1) + vk = sk.get_verifying_key() + # Get the compressed form of the public key + if vk.pubkey.point.y() & 1: + return b'\x03' + vk.to_string()[:32] + else: + return b'\x02' + vk.to_string()[:32] + + + def wif(self, is_testnet=True) -> Optional[str]: + """ + Get Wallet Import Format. + + Args: + is_testnet (bool): Flag indicating whether to generate WIF for testnet. + + Returns: + str: Wallet Import Format string if the key exists, None otherwise. + """ + if self.master_private_key: + # Set the prefix based on the network + prefix = b'\xef' if is_testnet else b'\x80' + # Prepare the payload with the private key and a suffix '01' which denotes that the corresponding public key is compressed + payload = prefix + self.master_private_key + b'\x01' + # Compute the checksum: first 4 bytes of SHA-256(SHA-256(payload)) + checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4] + # Encode the result using Base58 + return base58.b58encode(payload + checksum).decode('utf-8') + else: + return None + + def clean_derivation(self) -> "HDW": + """ + Clean derivation Path or Indexes. + + Returns: + HDW: Hierarchical Deterministic Wallet instance reset to its root configuration. + """ + if self._root_private_key: + self._path, self._path_class, self._depth, self._parent_fingerprint, self._index = ( + "m", "m", 0, b"\0\0\0\0", 0 + ) + self.master_private_key, self.master_chain_code = self._root_private_key + self._key = ecdsa.SigningKey.from_string(self.master_private_key, curve=SECP256k1) + self._verified_key = self._key.get_verifying_key() + class HDWallet: """Wraps the python hdwallet library to provide basic HD wallet functionality @@ -194,28 +313,28 @@ def __init__( xprivate_key: Optional[str] = None, path: Optional[str] = None, mnemonic: Optional[str] = None, + passphrase : Optional[str] = "" ): """Instantiate a hdwallet object using the corresponding library with BTC""" - symbol = None - if is_mainnet(): - symbol = BTC - else: - symbol = BTCTEST - - self.hdw = ext_HDWallet(symbol) + # symbol = None + # if is_mainnet(): + # symbol = BTC + # else: + # symbol = BTCTEST + self.hdw = HDW() if mnemonic: - self.hdw.from_mnemonic(mnemonic=mnemonic) + self.hdw.from_mnemonic(mnemonic=mnemonic,passphrase=passphrase) if xprivate_key and path: self.hdw.from_xprivate_key(xprivate_key=xprivate_key) self.hdw.from_path(path=path) @classmethod - def from_mnemonic(cls, mnemonic: str): + def from_mnemonic(cls, mnemonic: str , passphrase : str = ""): """Class method to instantiate from a mnemonic code for the HD Wallet""" - return cls(mnemonic=mnemonic) + return cls(mnemonic=mnemonic,passphrase=passphrase) @classmethod def from_xprivate_key(cls, xprivate_key: str, path: Optional[str] = None): @@ -234,4 +353,4 @@ def from_path(self, path: str): def get_private_key(self): """Return a PrivateKey object used throughout bitcoinutils library""" - return PrivateKey(self.hdw.wif()) # type: ignore + return PrivateKey(self.hdw.wif()) # type: ignore \ No newline at end of file From e6c46ad69496dc88b81326643cfbc10e45877e4f Mon Sep 17 00:00:00 2001 From: guptamukund22 Date: Sat, 4 May 2024 13:43:14 +0530 Subject: [PATCH 6/6] cleanups --- bitcoinutils/hdwallet.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/bitcoinutils/hdwallet.py b/bitcoinutils/hdwallet.py index 15c5170e..93c998f7 100644 --- a/bitcoinutils/hdwallet.py +++ b/bitcoinutils/hdwallet.py @@ -17,16 +17,16 @@ import hashlib import hmac -from binascii import unhexlify, b2a_hex +from binascii import unhexlify import unicodedata import ecdsa import struct from ecdsa.curves import SECP256k1 -from ecdsa.util import string_to_number, number_to_string +from ecdsa.util import string_to_number import base58 class HDW: - def __init__(self): + def __init__(self,symbol): """ Initialize the HD Wallet with a seed if provided. @@ -41,6 +41,7 @@ def __init__(self): self.master_chain_code : Optional[str] = None self.seed : Optional[str] = None self._root_private_key: Optional[tuple] = None + self.is_testnet = symbol def from_seed(self, seed : str): """ @@ -273,7 +274,7 @@ def wif(self, is_testnet=True) -> Optional[str]: """ if self.master_private_key: # Set the prefix based on the network - prefix = b'\xef' if is_testnet else b'\x80' + prefix = b'\xef' if self.is_testnet else b'\x80' # Prepare the payload with the private key and a suffix '01' which denotes that the corresponding public key is compressed payload = prefix + self.master_private_key + b'\x01' # Compute the checksum: first 4 bytes of SHA-256(SHA-256(payload)) @@ -315,15 +316,12 @@ def __init__( mnemonic: Optional[str] = None, passphrase : Optional[str] = "" ): - """Instantiate a hdwallet object using the corresponding library with BTC""" - - # symbol = None - # if is_mainnet(): - # symbol = BTC - # else: - # symbol = BTCTEST - - self.hdw = HDW() + symbol = None + if is_mainnet(): + symbol = False + else: + symbol = True + self.hdw = HDW(symbol) if mnemonic: self.hdw.from_mnemonic(mnemonic=mnemonic,passphrase=passphrase)