UNPKG

@ledgerhq/hw-app-btc

Version:
154 lines 6.67 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const bs58_1 = __importDefault(require("bs58")); const sha256_1 = require("@noble/hashes/sha256"); const ripemd160_1 = require("@noble/hashes/ripemd160"); const createTransaction_1 = require("./createTransaction"); const getWalletPublicKey_1 = require("./getWalletPublicKey"); const bip32_1 = require("./bip32"); const signMessage_1 = require("./signMessage"); /** * @class BtcOld * @description This Bitcoin old API is compatible with versions of the Bitcoin nano app that are earlier than 2.1.0 * */ class BtcOld { transport; constructor(transport) { this.transport = transport; } derivationsCache = {}; async derivatePath(path) { if (this.derivationsCache[path]) return this.derivationsCache[path]; const res = await (0, getWalletPublicKey_1.getWalletPublicKey)(this.transport, { path, }); this.derivationsCache[path] = res; return res; } async getWalletXpub({ path, xpubVersion, }) { const pathElements = (0, bip32_1.pathStringToArray)(path); const parentPath = pathElements.slice(0, -1); const parentDerivation = await this.derivatePath((0, bip32_1.pathArrayToString)(parentPath)); const accountDerivation = await this.derivatePath(path); const fingerprint = makeFingerprint(compressPublicKeySECP256(Buffer.from(parentDerivation.publicKey, "hex"))); const xpub = makeXpub(xpubVersion, pathElements.length, fingerprint, pathElements[pathElements.length - 1], Buffer.from(accountDerivation.chainCode, "hex"), compressPublicKeySECP256(Buffer.from(accountDerivation.publicKey, "hex"))); return xpub; } /** * @param path a BIP 32 path * @param options an object with optional these fields: * * - verify (boolean) will ask user to confirm the address on the device * * - format ("legacy" | "p2sh" | "bech32" | "bech32m" | "cashaddr") to use different bitcoin address formatter. * * NB The normal usage is to use: * * - legacy format with 44' paths * * - p2sh format with 49' paths * * - bech32 format with 84' paths * * - bech32m format with 86' paths * * - cashaddr in case of Bitcoin Cash * * @example * btc.getWalletPublicKey("44'/0'/0'/0/0").then(o => o.bitcoinAddress) * btc.getWalletPublicKey("49'/0'/0'/0/0", { format: "p2sh" }).then(o => o.bitcoinAddress) */ getWalletPublicKey(path, opts) { if (opts?.format === "bech32m") { throw new Error("Unsupported address format bech32m"); } return (0, getWalletPublicKey_1.getWalletPublicKey)(this.transport, { ...opts, path }); } /** * To sign a transaction involving standard (P2PKH) inputs, call createTransaction with the following parameters * @param inputs is an array of [ transaction, output_index, optional redeem script, optional sequence ] where * * * transaction is the previously computed transaction object for this UTXO * * output_index is the output in the transaction used as input for this UTXO (counting from 0) * * redeem script is the optional redeem script to use when consuming a Segregated Witness input * * sequence is the sequence number to use for this input (when using RBF), or non present * @param associatedKeysets is an array of BIP 32 paths pointing to the path to the private key used for each UTXO * @param changePath is an optional BIP 32 path pointing to the path to the public key used to compute the change address * @param outputScriptHex is the hexadecimal serialized outputs of the transaction to sign * @param lockTime is the optional lockTime of the transaction to sign, or default (0) * @param sigHashType is the hash type of the transaction to sign, or default (all) * @param segwit is an optional boolean indicating wether to use segwit or not * @param additionals list of additionnal options * * - "bech32" for spending native segwit outputs * - "abc" for bch * - "gold" for btg * - "decred" for decred * - "zcash" for zcash * - "bipxxx" for using BIPxxx * - "sapling" to indicate a zec transaction is supporting sapling (to be set over block 419200) * @param expiryHeight is an optional Buffer for zec overwinter / sapling Txs * @param useTrustedInputForSegwit trust inputs for segwit transactions * @return the signed transaction ready to be broadcast * @example btc.createTransaction({ inputs: [ [tx1, 1] ], associatedKeysets: ["0'/0/0"], outputScriptHex: "01905f0100000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88ac" }).then(res => ...); */ createPaymentTransaction(arg) { if (arguments.length > 1) { throw new Error("@ledgerhq/hw-app-btc: createPaymentTransaction multi argument signature is deprecated. please switch to named parameters."); } return (0, createTransaction_1.createTransaction)(this.transport, arg); } async signMessage({ path, messageHex }) { return (0, signMessage_1.signMessage)(this.transport, { path, messageHex, }); } } exports.default = BtcOld; function makeFingerprint(compressedPubKey) { return hash160(compressedPubKey).slice(0, 4); } function asBufferUInt32BE(n) { const buf = Buffer.allocUnsafe(4); buf.writeUInt32BE(n, 0); return buf; } const compressPublicKeySECP256 = (publicKey) => Buffer.concat([Buffer.from([0x02 + (publicKey[64] & 0x01)]), publicKey.slice(1, 33)]); function makeXpub(version, depth, parentFingerprint, index, chainCode, pubKey) { const indexBuffer = asBufferUInt32BE(index); indexBuffer[0] |= 0x80; const extendedKeyBytes = Buffer.concat([ asBufferUInt32BE(version), Buffer.from([depth]), parentFingerprint, indexBuffer, chainCode, pubKey, ]); const checksum = hash256(extendedKeyBytes).slice(0, 4); return bs58_1.default.encode(Buffer.concat([extendedKeyBytes, checksum])); } function sha256(buffer) { return Buffer.from((0, sha256_1.sha256)(buffer)); } function hash256(buffer) { return sha256(sha256(buffer)); } function ripemd160(buffer) { return Buffer.from((0, ripemd160_1.ripemd160)(buffer)); } function hash160(buffer) { return ripemd160(sha256(buffer)); } //# sourceMappingURL=BtcOld.js.map