import {CoinselectAddressTypes, CoinselectTxInput, CoinselectTxOutput, utils} from "./utils"; // add inputs until we reach or surpass the target value (or deplete) // worst-case: O(n) export function accumulative ( utxos: CoinselectTxInput[], outputs: CoinselectTxOutput[], feeRate: number, type: CoinselectAddressTypes, requiredInputs?: CoinselectTxInput[] ): { inputs?: CoinselectTxInput[], outputs?: CoinselectTxOutput[], fee: number } { if (!isFinite(utils.uintOrNaN(feeRate))) return null; let bytesAccum = utils.transactionBytes([], outputs, type); let inAccum = 0; const inputs = []; if(requiredInputs!=null) for(let utxo of requiredInputs) { const {length: utxoBytes} = utils.inputBytes(utxo); const utxoValue = utils.uintOrNaN(utxo.value); bytesAccum += utxoBytes; inAccum += utxoValue; inputs.push(utxo); } const outAccum = utils.sumOrNaN(outputs); for (let i = 0; i < utxos.length; ++i) { const utxo = utxos[i]; const {length: utxoBytes} = utils.inputBytes(utxo); const utxoFee = feeRate * utxoBytes; const utxoValue = utils.uintOrNaN(utxo.value); // skip detrimental input if (utxoFee > utxo.value) { if (i === utxos.length - 1) return { fee: feeRate * (bytesAccum + utxoBytes) }; continue } bytesAccum += utxoBytes; inAccum += utxoValue; inputs.push(utxo); const fee = feeRate * bytesAccum; // go again? if (inAccum < outAccum + fee) continue; return utils.finalize(inputs, outputs, feeRate, type); } return { fee: feeRate * bytesAccum }; }