test
Friday, June 21, 2024
HomeBitcoinHow do you turn your bitcoinjs integrationfrom TransactionBuilder to transactions-psbt.js?

How do you turn your bitcoinjs integrationfrom TransactionBuilder to transactions-psbt.js?


You are solely signing the primary enter? tx.signal(0, proprietor); Normally each enter needs to be signed one way or the other.

I additionally struggled with the change to Psbt. Greatest distinction was principally requirement to have a full transaction hex of each enter for non-segwit inputs. Segwit inputs will be easier however they may also be created utilizing the complete hex of the tx utilizing non-segwit command so do not have so as to add additional logic differentiating between inputs. You possibly can not simply present txid and vout, simply add on the hex of tx that created every enter in your object.

I actually simply adopted examples https://github.com/bitcoinjs/bitcoinjs-lib#examples

So that is my tackle a really common tx with psbt that I take advantage of for now:

import * as bitcoin from 'bitcoinjs-lib'

// not all components of inputs must be outlined
// inputs - array of all information wanted for inputs
// outputs - array of all information wanted for outputs

const community = bitcoin.networks.testnet // or bitcoin.networks.bitcoin

const psbt = new bitcoin.Psbt({ community })
psbt.setVersion(2)    // default
psbt.setLocktime(0)   // default

// ************** create inputs **************

inputs.forEach(enter=> {
  psbt.addInput({
    hash: enter.txid,  // txid quantity
    index: enter.vout,  // output quantity
    sequence: enter.sequence, // typically 0xfffffffe    
    nonWitnessUtxo: Buffer.from(enter.hex, 'hex'), // works for witness inputs too!
    redeemScript: enter.redeemScript, // provided that there's redeem script
    witnessScript: enter.witnessScript // provided that there's witness script
  }) 
})

// ************** create outputs **************

outputs.forEach(output => {

  psbt.addOutput({
    handle: output.handle, // provided that not op_return kind output (no handle for these)
    worth: output.worth,
    script: output.information  // provided that there's string (utf8) information to embed in op_return
      ? bitcoin.funds.embed({ information: [Buffer.from(output.data, 'utf8')] }).output 
      : undefined
  }) 
})

// ************** signing **************

inputs.forEach((enter, index) => {

  // signal common inputs that may be merely signed
  if (!enter.redeemScript && !enter.witnessScript) {
    psbt.signInput(index, enter.keyPair)  

    // give error if signature failed
    if (!psbt.validateSignaturesOfInput(index)) {
      throw new Error('Signature validation failed for enter index ' + index.toString())
    }    
  }

})

// ************** finalizing inputs **************

inputs.forEach((enter, index) => {

  // signal common inputs that may be merely signed
  if (!enter.redeemScript && !enter.witnessScript) {
    psbt.finalizeInput(index) 
  }

  // for p2sh or p2wsh script inputs
  if (enter.redeemScript || enter.witnessScript) {
    psbt.finalizeInput(
      index, 
      getFinalScripts({ 
        inputScript: enter.inputScript, 
        community 
      })
    )
  }
})

// ************** make tx **************

const tx = psbt.extractTransaction()

const virtualSize = tx.virtualSize()
const txid = tx.getId()
const hex = tx.toHex()

console.log('tx virtualSize:', virtualSize)
console.log('tx txid:', txid)
console.log('tx hex:', hex)

And for some purpose finalizeInput for customized scripts shouldn’t be precisely inbuilt but however I discovered it in examples and simply added as a operate I import or put someplace in identical file.

operate getFinalScripts ({ inputScript, community }) {
  return operate (
    inputIndex,
    enter,
    script,
    isSegwit,
    isP2SH,
    isP2WSH,
  ) {
    // Step 1: Verify to ensure the significant script matches what you anticipate.

    // Step 2: Create closing scripts
    let fee = {
      community,
      output: script,
      enter: inputScript,
    };
    if (isP2WSH && isSegwit)
      fee = bitcoin.funds.p2wsh({
        community,
        redeem: fee,
      });
    if (isP2SH)
      fee = bitcoin.funds.p2sh({
        community,
        redeem: fee,
      });

    operate witnessStackToScriptWitness(witness) {
      let buffer = Buffer.allocUnsafe(0);

      operate writeSlice(slice) {
        buffer = Buffer.concat([buffer, Buffer.from(slice)]);
      }

      operate writeVarInt(i) {
        const currentLen = buffer.size;
        const varintLen = varuint.encodingLength(i);

        buffer = Buffer.concat([buffer, Buffer.allocUnsafe(varintLen)]);
        varuint.encode(i, buffer, currentLen);
      }

      operate writeVarSlice(slice) {
        writeVarInt(slice.size);
        writeSlice(slice);
      }

      operate writeVector(vector) {
        writeVarInt(vector.size);
        vector.forEach(writeVarSlice);
      }

      writeVector(witness);

      return buffer;
    }

    return {
      finalScriptSig: fee.enter,
      finalScriptWitness:
        fee.witness && fee.witness.size > 0
          ? witnessStackToScriptWitness(fee.witness)
          : undefined,
    };
  }
}

I have never examined each type of enter but however that is principally what I take advantage of for p2wpkh and p2wsh inputs. I attempt to discover examples spending precisely the kind of enter I want normally.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments