def from_xpub( xpub: str, xpub_type: Optional[XpubType] = None, path: Optional[str] = None, ) -> 'HDKey': """ Instantiate an HDKey from an xpub. Populates all possible fields Args: xpub (str): the xpub path (str): the path if it's known. useful for calling derive_path Returns: (HDKey): the key object May raise: - XPUBError if there is a problem with decoding the xpub """ xpub_bytes = b58decode(xpub) if len(xpub_bytes) < 78: raise XPUBError(f'Given XPUB {xpub} is too small') try: pubkey = PublicKey(xpub_bytes[45:78]) except ValueError as e: raise XPUBError(str(e)) from e result = _parse_prefix(xpub_bytes[0:4]) if not result.is_public: raise XPUBError('Given xpub is an extended private key') if result.network != 'mainnet': raise XPUBError('Given xpub is not for the bitcoin mainnet') hint = result.hint if xpub_type is not None and xpub_type.matches_prefix( xpub[0:4]) is False: # the given type does not match the prefix, re-encode with correct pref new_xpub = bytearray() new_xpub.extend(xpub_type.prefix_bytes()) new_xpub.extend(xpub_bytes[4:]) new_xpub_bytes = new_xpub hint = xpub_type.prefix() xpub = b58encode(bytes(new_xpub_bytes)).decode('ascii') return HDKey( path=path, network=result.network, depth=xpub_bytes[4], parent_fingerprint=xpub_bytes[5:9], index=int.from_bytes(xpub_bytes[9:13], byteorder='big'), parent=None, chain_code=xpub_bytes[13:45], fingerprint=hash160(pubkey.format(COMPRESSED_PUBKEY))[:4], xpriv=None, xpub=xpub, privkey=None, pubkey=pubkey, hint=hint, )
def from_xpub(xpub: str, path: Optional[str] = None) -> 'HDKey': """ Instantiate an HDKey from an xpub. Populates all possible fields Args: xpub (str): the xpub path (str): the path if it's known. useful for calling derive_path Returns: (HDKey): the key object May raise: - XPUBError if there is a problem with decoding the xpub """ xpub_bytes = b58decode(xpub) if len(xpub_bytes) < 78: raise XPUBError(f'Given XPUB {xpub} is too small') try: pubkey = PublicKey(xpub_bytes[45:78]) except ValueError as e: raise XPUBError(str(e)) from e result = _parse_prefix(xpub_bytes[0:4]) if not result.is_public: raise XPUBError('Given xpub is an extended private key') return HDKey( path=path, network=result.network, depth=xpub_bytes[4], parent_fingerprint=xpub_bytes[5:9], index=int.from_bytes(xpub_bytes[9:13], byteorder='big'), parent=None, chain_code=xpub_bytes[13:45], fingerprint=hash160(pubkey.format(COMPRESSED_PUBKEY))[:4], xpriv=None, xpub=xpub, privkey=None, pubkey=pubkey, hint=result.hint, )
def _child_from_xpub(self, index: int, child_xpub: str) -> 'HDKey': """ Returns a new HDKey object based on the current object and the new child xpub. Don't call this directly, it's for child derivation. Args: index (int): the index of the child child_xpub (str): the child's xpub Returns HDKey: the new child object """ path: Optional[str] if self.path is not None: path = '{}/{}'.format(self.path, str(index)) else: path = None xpub_bytes = b58decode(child_xpub) pubkey = xpub_bytes[45:78] result = _parse_prefix(xpub_bytes[0:4]) if not result.is_public: raise XPUBError('Given xpub is an extended private key') return HDKey( path=path, network=result.network, depth=xpub_bytes[4], parent_fingerprint=xpub_bytes[5:9], index=int.from_bytes(xpub_bytes[9:13], byteorder='big'), parent=self, chain_code=xpub_bytes[13:45], fingerprint=hash160(pubkey)[:4], xpriv=None, xpub=child_xpub, privkey=None, pubkey=PublicKey(pubkey), hint=result.hint, )