From 4c016b9fb0c0a979422caee2e525d5e6d1477202 Mon Sep 17 00:00:00 2001 From: dumbledope <84159538+dumbledope@users.noreply.github.com> Date: Fri, 26 Aug 2022 12:32:18 -0700 Subject: [PATCH] feat: automatically consolidate UTXOs on redeem --- .changeset/clean-zebras-flow.md | 5 +++++ src/processors/redeem-htlc.ts | 27 ++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 .changeset/clean-zebras-flow.md diff --git a/.changeset/clean-zebras-flow.md b/.changeset/clean-zebras-flow.md new file mode 100644 index 0000000..a532502 --- /dev/null +++ b/.changeset/clean-zebras-flow.md @@ -0,0 +1,5 @@ +--- +'magic-supplier': patch +--- + +Automatically consolidate UTXOs when redeeming inbound HTLCs diff --git a/src/processors/redeem-htlc.ts b/src/processors/redeem-htlc.ts index 3469cf3..206a6f3 100644 --- a/src/processors/redeem-htlc.ts +++ b/src/processors/redeem-htlc.ts @@ -2,7 +2,7 @@ import { getBtcAddress, getBtcSigner, getSupplierId } from '../config'; import { networks, Psbt, script as bScript, payments, opcodes } from 'bitcoinjs-lib'; import { getRedeemedHTLC, setRedeemedHTLC, RedisClient } from '../store'; import { logger as _logger } from '../logger'; -import { getFeeRate, tryBroadcast, withElectrumClient } from '../wallet'; +import { getFeeRate, listUnspent, tryBroadcast, txWeight, withElectrumClient } from '../wallet'; import { bridgeContract, stacksProvider } from '../stacks'; import { bytesToHex, hexToBytes } from 'micro-stacks/common'; import { getBtcTxUrl, satsToBtc } from '../utils'; @@ -59,9 +59,10 @@ export async function redeem(txid: string, preimage: Uint8Array) { const psbt = new Psbt({ network: networks.regtest }); const signer = getBtcSigner(); const address = getBtcAddress(); - const weight = 312; - const feeRate = await getFeeRate(client); - const fee = weight * feeRate; + const baseWeight = 312n; + const [unspents, feeRate] = await Promise.all([listUnspent(client), getFeeRate(client)]); + const size = baseWeight + txWeight(unspents.length, 1); + const fee = size * BigInt(feeRate); psbt.addInput({ hash: txid, @@ -70,9 +71,25 @@ export async function redeem(txid: string, preimage: Uint8Array) { redeemScript: Buffer.from(swap.redeemScript), }); + let consolidateTotal = 0n; + psbt.addInputs( + await Promise.all( + unspents.map(async coin => { + const txHex = await client.blockchain_transaction_get(coin.tx_hash); + consolidateTotal += BigInt(coin.value); + return { + hash: coin.tx_hash, + index: coin.tx_pos, + nonWitnessUtxo: Buffer.from(txHex, 'hex'), + }; + }) + ) + ); + + const outputAmount = consolidateTotal + swap.sats - fee; psbt.addOutput({ address, - value: Number(swap.sats) - fee, + value: Number(outputAmount), }); await psbt.signInputAsync(0, signer);