@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
JavaScript
;
// 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;