UNPKG

@bitcoinerlab/coinselect

Version:

A TypeScript library for Bitcoin transaction management, based on Bitcoin Descriptors for defining inputs and outputs. It facilitates optimal UTXO selection and transaction size calculation.

76 lines (75 loc) 2.83 kB
"use strict"; // Copyright (c) 2023 Jose-Luis Landabaso - https://bitcoinerlab.com // Distributed under the MIT software license Object.defineProperty(exports, "__esModule", { value: true }); exports.vsize = exports.isSegwitTx = void 0; const varuint_bitcoin_1 = require("varuint-bitcoin"); const isSegwitTx = (inputs) => inputs.some(input => input.isSegwit()); exports.isSegwitTx = isSegwitTx; /** * Computes the virtual size (vsize) of a Bitcoin transaction based on specified * inputs and outputs. * * @returns The computed virtual size (vsize) of the transaction, rounded up to * the nearest integer. * * *NOTE:* When the descriptor in an input is `addr(address)`, it is assumed * that any `addr(SH_TYPE_ADDRESS)` is in fact a Segwit `SH_WPKH` * (Script Hash-Witness Public Key Hash). * For inputs using arbitrary scripts (not standard addresses), * use a descriptor in the format `sh(MINISCRIPT)`. * Similarly, add(TR_TYPE_ADDRESS) is assumed to be a single-key tr address. * * @example * ``` * const vsizeValue = vsize( * [new Output({ descriptor: 'addr(...)' })], // inputs * [new Output({ descriptor: 'addr(...)' })] // outputs * ); * ``` * * @see {@link https://bitcoinerlab.com/modules/descriptors} for details on * OutputInstance and descriptors. */ function vsize( /** * Array of `OutputInstance` representing the inputs of the transaction. */ inputs, /** * Array of `OutputInstance` representing the outputs of the transaction. */ outputs, /** * Optional array of arrays containing signatures. * The outer array corresponds to each input in the transaction. The inner array contains * signatures for each public key associated with the respective input. * * If provided, enables calculation of exact signature sizes. * Defaults to assuming 72 bytes per signature. * Mainly used for testing and accurate fee estimation. */ signaturesPerInput) { const isSegwitTxValue = (0, exports.isSegwitTx)(inputs); let totalWeight = 0; inputs.forEach(function (input, index) { if (signaturesPerInput) { const signatures = signaturesPerInput[index]; if (!signatures) throw new Error(`signaturesPerInput not defined for ${index}`); totalWeight += input.inputWeight(isSegwitTxValue, signatures); } else totalWeight += input.inputWeight(isSegwitTxValue, 'DANGEROUSLY_USE_FAKE_SIGNATURES'); }); outputs.forEach(function (output) { totalWeight += output.outputWeight(); }); if (isSegwitTxValue) totalWeight += 2; totalWeight += 8 * 4; totalWeight += (0, varuint_bitcoin_1.encodingLength)(inputs.length) * 4; totalWeight += (0, varuint_bitcoin_1.encodingLength)(outputs.length) * 4; return Math.ceil(totalWeight / 4); } exports.vsize = vsize;