import * as crypto from "@node-lightning/crypto" ; import { BitcoinError } from "./BitcoinError" ; import { BitcoinErrorCode } from "./BitcoinErrorCode" ; import { BufferWriter } from "@node-lightning/bufio" ; import { HdKeyCodec } from "./HdKeyCodec" ; import { HdKeyType } from "./HdKeyType" ; import { Network } from "./Network" ; import { PublicKey } from "./PublicKey" ; const HARDENED_INDEX = 0x80000000 ; /**
 * A hierarchical deterministic extended public key as defined in BIP32.
 * This class allows derivation of unhardened public keys. It may be
 * generated from a derivation, decoded, or obtained a parent.
 *  HdPrivateKey .
  export class HdPublicKey { remarks param input throws BitcoinError throws when there is an invalid
     * encoding, bad checksum, or if you attempt to decode a private key.
     *
     *  returns public static decode ( input ) { const result = HdKeyCodec . decode ( input ) ; if ( ! ( result instanceof HdPublicKey ) ) { throw new BitcoinError ( BitcoinErrorCode . InvalidHdPublicKey , input ) ; } return result ; } /**
     * Indicates if this is an xpub, ypub, or zpub public key.
     */ public type : HdKeyType ; /**
     * The depth of key from 0 to 255.
     */ public depth : number ; /**
     * The 4-byte fingerprint of the parent compressed public key. The
     * fingerprint of the parent only serves as a fast way to detect
     * parent and child keys and software must be willing to deal with
     * collisions.
     */ public parentFingerprint : Buffer ; /**
     * The key number. Values of 0 to 2^31-1 are normal keys. Values of
     * 2^31 to 2^32-1 are hardened and the derive method will throw an
     * error.
     */ public number : number ; /**
     * The chaincode used to derive the public key
     */ public chainCode : Buffer ; /**
     * The underlying secp256k1 point
     */ public publicKey : PublicKey ; private _fingerprint : Buffer ; /**
     * Gets the numeric version from the underlying network
     */ public get version ( ) : number { switch ( this . type ) { case HdKeyType . x : return this . network . xpubVersion ; case HdKeyType . y : return this . network . ypubVersion ; case HdKeyType . z : return this . network . zpubVersion ; } } /**
     * Gets the network this public key is associated with
     */ public get network ( ) : Network { return this . publicKey . network ; } /**
     * Returns true if the public key is hardened, meaning the number
     * is between 2^31 and 2^32-1.
     */ public get isHardened ( ) : boolean { return this . number >= HARDENED_INDEX ; } /**
     * Lazy loads the fingerprint of the public key. This is defined as
     * the `hash160(compressed_pubkey)`;
     */ public get fingerprint ( ) : Buffer { if ( ! this . _fingerprint ) { this . _fingerprint = crypto . hash160 ( this . publicKey . toBuffer ( ) ) ; } return this . _fingerprint ; } remarks The derivation is defined in BIP32 using HMAC-SHA512
     *  https *
     * The derivation uses the parent's chaincode as the key.  Then uses
     * `parent public key || i` as the HMAC data.
     *
     * The resulting 64-bytes are split where where the left half is
     * used to tweakAdd against the parent public key. The right half
     * is the child's chain_code.
     *
     *  param i throws BitcoinError throws an `InvalidHdDerivation` error
     * code if there is an attempt to derive a hardened child key. Throws
     * if the tweak value is invalid.
     *
     *
     *  returns child non-hardened  HdPublicKey public derive ( i ) { if ( i >= HARDENED_INDEX ) { throw new BitcoinError ( BitcoinErrorCode . InvalidHdDerivation ) ; } const data = new BufferWriter ( Buffer . alloc ( 37 ) ) ; data . writeBytes ( this . publicKey . toBuffer ( ) ) ; data . writeUInt32BE ( i ) ; const l = crypto . hmac ( this . chainCode , data . toBuffer ( ) , "sha512" ) ; const ll = l . slice ( 0 , 32 ) ; const lr = l . slice ( 32 ) ; const childPubKey = this . publicKey . tweakAdd ( ll ) ; const childChainCode = lr ; const child = new HdPublicKey ( ) ; child . type = this . type ; child . depth = this . depth + 1 ; child . number = this . number ; child . publicKey = childPubKey ; child . chainCode = childChainCode ; return child ; } /**
     * Encodes the  HdPublicKey according to BIP32.
     *
     * For example:
     * xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8
     *
     *  remarks returns public encode ( ) { return HdKeyCodec . encode ( this ) ; } returns public toAddress ( ) { switch ( this . type ) { case HdKeyType . x : return this . publicKey . toP2pkhAddress ( ) ; case HdKeyType . y : return this . publicKey . toP2nwpkhAddress ( ) ; case HdKeyType . z : return this . publicKey . toP2wpkhAddress ( ) ; } } returns public toSecBuffer ( ) { return this . publicKey . toBuffer ( ) ; } returns public toSecHex ( ) { return this . publicKey . toHex ( ) ; } }