diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/buildtx.js | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/lib/buildtx.js b/lib/buildtx.js new file mode 100644 index 00000000..351f8081 --- /dev/null +++ b/lib/buildtx.js @@ -0,0 +1,76 @@ +const axios = require("axios"); +const bitcoin = require("bitcoinjs-lib"); +const coinselect = require("coinselect"); +const split = require("coinselect/split"); +const api = prod ? "https://blockstream.info/api" : "http://localhost:3002"; +const SATS = 100000000; +const network = prod + ? bitcoin.networks["bitcoin"] + : bitcoin.networks["regtest"]; + +module.exports = async ({ address, amount, feeRate, user }) => { + if (!feeRate) feeRate = (await bc.estimateSmartFee(6)).feerate * SATS; + feeRate = Math.round(feeRate / 1000); + + const payments = await db.Payment.findAll({ + where: { + received: true, + account_id: user.account_id, + } + }); + + const utxos = []; + for (let i = 0; i < payments.length; i++) { + try { + utxos.push(...(await axios.get(`${api}/address/${payments[i].address}/utxo`)).data); + } catch (e) { + l.error("problem fetching utxos", e.message); + } + } + + let targets = [ + { + address, + value: amount + } + ]; + + let { inputs, outputs, fee } = coinselect(utxos, targets, feeRate); + + if (!inputs || !outputs) { + l.info("utxos", amount, feeRate, utxos, inputs, outputs); + throw new Error("Failed to create transaction"); + } + + let psbt = new bitcoin.Psbt({ network }); + let total = 0; + + outputs.map(({ address, value }) => { + total += value; + if (!address) { + address = payments[payments.length - 1].address; + change.push(address); + } + + psbt = psbt.addOutput({ + address, + value + }); + }); + + for (let i = 0; i < inputs.length; i++) { + let { txid, vout } = inputs[i]; + let nonWitnessUtxo = Buffer.from(await bc.getRawTransaction(txid), "hex"); + psbt = psbt.addInput({ + hash: txid, + index: vout, + nonWitnessUtxo + }); + } + + feeRate = Math.round(feeRate * 1000); + psbt = psbt.toBase64(); + + l.info("returning", { tx: psbt, feeRate }); + return { tx: psbt, feeRate }; +}; |
