123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- /*
- Consolidate all UTXOs in an address into a single UTXO
- */
- // REST API servers.
- const BCHN_MAINNET = 'https://bchn.fullstack.cash/v5/'
- // bch-js-examples require code from the main bch-js repo
- import BCHJS from '@psf/bch-js'
- // Instantiate bch-js based on the network.
- const bchjs = new BCHJS({ restURL: BCHN_MAINNET })
- const SEND_ADDR = walletInfo.cashAddress
- const SEND_MNEMONIC = walletInfo.mnemonic
- const MAX_NUM_UTXOS = 100
- async function consolidateUtxos () {
- try {
- // instance of transaction builder
- const transactionBuilder = new bchjs.TransactionBuilder()
- let sendAmount = 0
- const inputs = []
- const data = await bchjs.Electrumx.utxo(SEND_ADDR)
- const utxos = data.utxos
- let maxLen = utxos.length
- console.log(`There are ${maxLen} UTXOs to consolidate.`)
- if(maxLen > MAX_NUM_UTXOS) maxLen = MAX_NUM_UTXOS
- // Loop through each UTXO assigned to this address.
- for (let i = 0; i < maxLen; i++) {
- const thisUtxo = utxos[i]
- inputs.push(thisUtxo)
- sendAmount += thisUtxo.value
- // ..Add the utxo as an input to the transaction.
- transactionBuilder.addInput(thisUtxo.tx_hash, thisUtxo.tx_pos)
- }
- // get byte count to calculate fee. paying 1.2 sat/byte
- const byteCount = bchjs.BitcoinCash.getByteCount(
- { P2PKH: inputs.length },
- { P2PKH: 1 }
- )
- console.log(`byteCount: ${byteCount}`)
- const satoshisPerByte = 1.0
- const txFee = Math.ceil(satoshisPerByte * byteCount)
- console.log(`txFee: ${txFee}`)
- // Exit if the transaction costs too much to send.
- if (sendAmount - txFee < 0) {
- console.log(
- "Transaction fee costs more combined UTXOs. Can't send transaction."
- )
- return
- }
- // add output w/ address and amount to send
- transactionBuilder.addOutput(SEND_ADDR, sendAmount - txFee)
- // Generate a change address from a Mnemonic of a private key.
- const change = await changeAddrFromMnemonic(SEND_MNEMONIC)
- // Generate a keypair from the change address.
- const keyPair = bchjs.HDNode.toKeyPair(change)
- // sign w/ HDNode
- let redeemScript
- inputs.forEach((input, index) => {
- transactionBuilder.sign(
- index,
- keyPair,
- redeemScript,
- transactionBuilder.hashTypes.SIGHASH_ALL,
- input.value
- )
- })
- // build tx
- const tx = transactionBuilder.build()
- // output rawhex
- const hex = tx.toHex()
- // console.log(`TX hex: ${hex}`)
- console.log(' ')
- // Broadcast transation to the network
- const txid = await bchjs.RawTransactions.sendRawTransaction([hex])
- // import from util.js file
- const util = require('../util.js')
- console.log(`Transaction ID: ${txid}`)
- console.log('Check the status of your transaction on this block explorer:')
- util.transactionStatus(txid, 'mainnet')
- } catch (err) {
- console.log('error: ', err)
- }
- }
- consolidateUtxos()
- // Generate a change address from a Mnemonic of a private key.
- async function changeAddrFromMnemonic (mnemonic) {
- // root seed buffer
- const rootSeed = await bchjs.Mnemonic.toSeed(mnemonic)
- // master HDNode
- const masterHDNode = bchjs.HDNode.fromSeed(rootSeed)
- // HDNode of BIP44 account
- const account = bchjs.HDNode.derivePath(masterHDNode, "m/44'/145'/0'")
- // derive the first external change address HDNode which is going to spend utxo
- const change = bchjs.HDNode.derivePath(account, '0/0')
- return change
- }
|