coinselect
An unspent transaction output (UTXO) selection module for bitcoin.
WARNING: Value units are in satoshi
s, not Bitcoin.
Algorithms
Module | Algorithm | Re-orders UTXOs? |
---|
require('coinselect') | Blackjack, with Accumulative fallback | By Descending Value |
require('coinselect/accumulative') | Accumulative - accumulates inputs until the target value (+fees) is reached, skipping detrimental inputs | - |
require('coinselect/blackjack') | Blackjack - accumulates inputs until the target value (+fees) is matched, does not accumulate inputs that go over the target value (within a threshold) | - |
require('coinselect/break') | Break - breaks the input values into equal denominations of output (as provided) | - |
require('coinselect/split') | Split - splits the input values evenly between all outputs , any provided output with .value remains unchanged | - |
Note: Each algorithm will add a change output if the input - output - fee
value difference is over a dust threshold.
This is calculated independently by utils.finalize
, irrespective of the algorithm chosen, for the purposes of safety.
Pro-tip: if you want to send-all inputs to an output address, coinselect/split
with a partial output (.address
defined, no .value
) can be used to send-all, while leaving an appropriate amount for the fee
.
Example
let coinSelect = require('coinselect')
let feeRate = 55
let utxos = [
...,
{
txId: '...',
vout: 0,
...,
value: 10000,
nonWitnessUtxo: Buffer.from('...full raw hex of txId tx...', 'hex'),
witnessUtxo: {
script: Buffer.from('... scriptPubkey hex...', 'hex'),
value: 10000
}
}
]
let targets = [
...,
{
address: '1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm',
value: 5000
}
]
let { inputs, outputs, fee } = coinSelect(utxos, targets, feeRate)
console.log(fee)
if (!inputs || !outputs) return
let psbt = new bitcoin.Psbt()
inputs.forEach(input =>
psbt.addInput({
hash: input.txId,
index: input.vout,
nonWitnessUtxo: input.nonWitnessUtxo,
witnessUtxo: input.witnessUtxo,
})
)
outputs.forEach(output => {
if (!output.address) {
output.address = wallet.getChangeAddress()
wallet.nextChangeAddress()
}
psbt.addOutput({
address: output.address,
value: output.value,
})
})
License MIT