<p>You're only signing the first input? <code>tx.sign(0, owner);</code> Usually every input has to be signed somehow.</p>

<p>I also struggled with the switch to Psbt. Biggest difference was basically requirement to have a full transaction hex of every input for non-segwit inputs. Segwit inputs can be simpler but they can also be created using the full hex of the tx using non-segwit command so don't have to add extra logic differentiating between inputs. You can no longer just provide txid and vout, just add on the hex of tx that created each input for your object.</p>

<p>I really just followed examples <a href="https://github.com/bitcoinjs/bitcoinjs-lib#examples" rel="nofollow noreferrer">https://github.com/bitcoinjs/bitcoinjs-lib#examples</a></p>

<p>So this is my take on a very general tx with psbt that I use for now:</p>

<pre><code>import * as bitcoin from 'bitcoinjs-lib'

// not all parts of inputs have to be defined
// inputs - array of all data needed for inputs
// outputs - array of all data needed for outputs

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

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

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

inputs.forEach(input=&gt; {
  psbt.addInput({
    hash: input.txid,  // txid number
    index: input.vout,  // output number
    sequence: input.sequence, // often 0xfffffffe    
    nonWitnessUtxo: Buffer.from(input.hex, 'hex'), // works for witness inputs too!
    redeemScript: input.redeemScript, // only if there's redeem script
    witnessScript: input.witnessScript // only if there's witness script
  }) 
})

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

outputs.forEach(output =&gt; {

  psbt.addOutput({
    address: output.address, // only if not op_return type output (no address for those)
    value: output.value,
    script: output.data  // only if there's string (utf8) data to embed in op_return
      ? bitcoin.payments.embed({ data: [Buffer.from(output.data, 'utf8')] }).output 
      : undefined
  }) 
})

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

inputs.forEach((input, index) =&gt; {

  // sign regular inputs that can be simply signed
  if (!input.redeemScript &amp;&amp; !input.witnessScript) {
    psbt.signInput(index, input.keyPair)  

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

})

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

inputs.forEach((input, index) =&gt; {

  // sign regular inputs that can be simply signed
  if (!input.redeemScript &amp;&amp; !input.witnessScript) {
    psbt.finalizeInput(index) 
  }

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

// ************** 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)

</code></pre>

<p>And for some reason finalizeInput for custom scripts is not exactly built in yet but I found it <a href="https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/csv.spec.ts" rel="nofollow noreferrer">in examples</a> and just added as a function I import or put somewhere in same file.</p>

<pre><code>function getFinalScripts ({ inputScript, network }) {
  return function (
    inputIndex,
    input,
    script,
    isSegwit,
    isP2SH,
    isP2WSH,
  ) {
    // Step 1: Check to make sure the meaningful script matches what you expect.

    // Step 2: Create final scripts
    let payment = {
      network,
      output: script,
      input: inputScript,
    };
    if (isP2WSH &amp;&amp; isSegwit)
      payment = bitcoin.payments.p2wsh({
        network,
        redeem: payment,
      });
    if (isP2SH)
      payment = bitcoin.payments.p2sh({
        network,
        redeem: payment,
      });

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

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

      function writeVarInt(i) {
        const currentLen = buffer.length;
        const varintLen = varuint.encodingLength(i);

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

      function writeVarSlice(slice) {
        writeVarInt(slice.length);
        writeSlice(slice);
      }

      function writeVector(vector) {
        writeVarInt(vector.length);
        vector.forEach(writeVarSlice);
      }

      writeVector(witness);

      return buffer;
    }

    return {
      finalScriptSig: payment.input,
      finalScriptWitness:
        payment.witness &amp;&amp; payment.witness.length &gt; 0
          ? witnessStackToScriptWitness(payment.witness)
          : undefined,
    };
  }
}
</code></pre>

<p>I haven't tested every kind of input yet but this is basically what I use for p2wpkh and p2wsh inputs. I try to find examples spending exactly the type of input I need usually.</p>

CC BY-SA 4.0
2020-02-22T19:48:20.113Z
2020-02-22T19:48:20.113Z
ildarmgt
<p>Here is an example (native Segwit, you need to modify "witnessUtxo" appropriately for a p2pkh, see <a href="https://github.com/bitcoinjs/bitcoinjs-lib/issues/1507" rel="nofollow noreferrer">this</a>):</p>

<pre><code>const bitcoin = require('bitcoinjs-lib');
let testnet = bitcoin.networks.testnet;


let keyPair1 = bitcoin.ECPair.fromWIF('privateKey1', testnet);    
let keyPair1wpkh = bitcoin.payments.p2wpkh({pubkey: keyPair1.publicKey, network: testnet});    
let keyPair2 = bitcoin.ECPair.fromWIF('privateKey2', testnet);
let keyPair2wpkh = bitcoin.payments.p2wpkh({pubkey: keyPair2.publicKey, network: testnet});

const psbt = new bitcoin.Psbt({ network: testnet }) 
let inputdata1 = {
  hash: "hash of the previous transaction" ,
  index: index,
  witnessUtxo: {
    script: Buffer.from('scriptPubKey_hex', 'hex'),
    value: 98e4 
  }
};

psbt.addInput(inputdata1);    
let output1 = {address: keyPair2wpkh.address, value: 97e4};    
psbt.addOutput(output1);    
psbt.signInput(0, keyPair1);    
psbt.finalizeAllInputs();    
const raw = psbt.extractTransaction().toHex();    
console.log(raw);
</code></pre>

CC BY-SA 4.0
2020-01-22T14:54:02.547Z
2020-01-22T14:54:02.547Z
Soren
<p>Let me first of all say I am a complete newbie so I might be wrong. Regarding the sign method deprecation, what has been <strong>already</strong> deprecated is not the method tx.sign() itself, but the way we passed the parameters. In order not to get the DEPRECATED message for the sign method you should pass an object of the form</p>

<p>{
  prevOutScriptType: string;
  vin: number;
  keyPair: Signer;
  redeemScript?: Buffer;
  hashType?: number;
  witnessValue?: number;
  witnessScript?: Buffer;
} </p>

<p>(see <a href="https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/transaction_builder.ts" rel="nofollow noreferrer">https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/transaction_builder.ts</a> line 74)</p>

<p>so concretely in your case</p>

<p>tx.sign({prevOutScriptType:'p2pkh', vin: 0, keyPair: owner})</p>

CC BY-SA 4.0
2020-01-22T08:48:26.963Z
2020-01-22T08:48:26.963Z
Soren
<p>the code below works:</p>



<pre><code>const btc = require('bitcoinjs-lib');

var tx = new btc.TransactionBuilder(net);
inputs.forEach(o =&gt; tx.addInput(o.txId, o.vout));
outputs.forEach(o =&gt; tx.addOutput(o.address, o.value));
tx.sign(0, owner);
var body = tx.build().toHex();
</code></pre>

<p>but it's complaining that TransactionBuilder is deprecated... sigh...</p>

<blockquote>
  <p>Deprecation Warning: TransactionBuilder will be removed in the future.
  (v6.x.x or later) Please use the Psbt class instead. Examples of usage
  are available in the transactions-psbt.js integration test file on our
  Github. A high level explanation is available in the psbt.ts and
  psbt.js files as well</p>
</blockquote>

<p>and apparently the signing methodology has also changed (grr):</p>

<blockquote>
  <p>DEPRECATED: TransactionBuilder sign method arguments will change in
  v6, please use the TxbSignArg interface</p>
</blockquote>

<p>I've read the documentation on Psbt and understand the general concept but have not found a guide that helps with the transition.  I tried to simply change <code>tx.sign()</code> for <code>tx.signInput()</code> but it pukes</p>

<p>I've also looked at the test suite for the library but it's too complicated for me to understand.  How do I convert my code to the new mechanism?</p>

<raw-transaction><bitcoinjs><bip174-psbt>
How do you switch your bitcoinjs integrationfrom TransactionBuilder to transactions-psbt.js?
ekkis
# How do you switch your bitcoinjs integrationfrom TransactionBuilder to transactions-psbt.js?

(Asked by: username_0 on 2020-01-11)

the code below works:

```
const btc = require('bitcoinjs-lib');

var tx = new btc.TransactionBuilder(net);
inputs.forEach(o => tx.addInput(o.txId, o.vout));
outputs.forEach(o => tx.addOutput(o.address, o.value));
tx.sign(0, owner);
var body = tx.build().toHex();

```

but it's complaining that TransactionBuilder is deprecated... sigh...

> Deprecation Warning: TransactionBuilder will be removed in the future.
> (v6.x.x or later) Please use the Psbt class instead. Examples of usage
> are available in the transactions-psbt.js integration test file on our
> Github. A high level explanation is available in the psbt.ts and
> psbt.js files as well

and apparently the signing methodology has also changed (grr):

> DEPRECATED: TransactionBuilder sign method arguments will change in
> v6, please use the TxbSignArg interface

I've read the documentation on Psbt and understand the general concept but have not found a guide that helps with the transition. I tried to simply change `tx.sign()` for `tx.signInput()` but it pukes

I've also looked at the test suite for the library but it's too complicated for me to understand. How do I convert my code to the new mechanism?

**Tags:** raw-transaction, bitcoinjs, bip174-psbt


---

## 3 answers

### Answer by username_1 on 2020-02-22. Score: 3

You're only signing the first input? `tx.sign(0, owner);` Usually every input has to be signed somehow.

I also struggled with the switch to Psbt. Biggest difference was basically requirement to have a full transaction hex of every input for non-segwit inputs. Segwit inputs can be simpler but they can also be created using the full hex of the tx using non-segwit command so don't have to add extra logic differentiating between inputs. You can no longer just provide txid and vout, just add on the hex of tx that created each input for your object.

I really just followed examples <https://github.com/bitcoinjs/bitcoinjs-lib#examples>

So this is my take on a very general tx with psbt that I use for now:

```
import * as bitcoin from 'bitcoinjs-lib'

// not all parts of inputs have to be defined
// inputs - array of all data needed for inputs
// outputs - array of all data needed for outputs

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

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

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

inputs.forEach(input=> {
  psbt.addInput({
    hash: input.txid,  // txid number
    index: input.vout,  // output number
    sequence: input.sequence, // often 0xfffffffe    
    nonWitnessUtxo: Buffer.from(input.hex, 'hex'), // works for witness inputs too!
    redeemScript: input.redeemScript, // only if there's redeem script
    witnessScript: input.witnessScript // only if there's witness script
  }) 
})

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

outputs.forEach(output => {

  psbt.addOutput({
    address: output.address, // only if not op_return type output (no address for those)
    value: output.value,
    script: output.data  // only if there's string (utf8) data to embed in op_return
      ? bitcoin.payments.embed({ data: [Buffer.from(output.data, 'utf8')] }).output 
      : undefined
  }) 
})

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

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

  // sign regular inputs that can be simply signed
  if (!input.redeemScript && !input.witnessScript) {
    psbt.signInput(index, input.keyPair)  

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

})

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

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

  // sign regular inputs that can be simply signed
  if (!input.redeemScript && !input.witnessScript) {
    psbt.finalizeInput(index) 
  }

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

// ************** 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 reason finalizeInput for custom scripts is not exactly built in yet but I found it [in examples](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/csv.spec.ts) and just added as a function I import or put somewhere in same file.

```
function getFinalScripts ({ inputScript, network }) {
  return function (
    inputIndex,
    input,
    script,
    isSegwit,
    isP2SH,
    isP2WSH,
  ) {
    // Step 1: Check to make sure the meaningful script matches what you expect.

    // Step 2: Create final scripts
    let payment = {
      network,
      output: script,
      input: inputScript,
    };
    if (isP2WSH && isSegwit)
      payment = bitcoin.payments.p2wsh({
        network,
        redeem: payment,
      });
    if (isP2SH)
      payment = bitcoin.payments.p2sh({
        network,
        redeem: payment,
      });

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

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

      function writeVarInt(i) {
        const currentLen = buffer.length;
        const varintLen = varuint.encodingLength(i);

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

      function writeVarSlice(slice) {
        writeVarInt(slice.length);
        writeSlice(slice);
      }

      function writeVector(vector) {
        writeVarInt(vector.length);
        vector.forEach(writeVarSlice);
      }

      writeVector(witness);

      return buffer;
    }

    return {
      finalScriptSig: payment.input,
      finalScriptWitness:
        payment.witness && payment.witness.length > 0
          ? witnessStackToScriptWitness(payment.witness)
          : undefined,
    };
  }
}

```

I haven't tested every kind of input yet but this is basically what I use for p2wpkh and p2wsh inputs. I try to find examples spending exactly the type of input I need usually.


---

### Answer by username_2 on 2020-01-22. Score: 0

Here is an example (native Segwit, you need to modify "witnessUtxo" appropriately for a p2pkh, see [this](https://github.com/bitcoinjs/bitcoinjs-lib/issues/1507)):

```
const bitcoin = require('bitcoinjs-lib');
let testnet = bitcoin.networks.testnet;

let keyPair1 = bitcoin.ECPair.fromWIF('privateKey1', testnet);    
let keyPair1wpkh = bitcoin.payments.p2wpkh({pubkey: keyPair1.publicKey, network: testnet});    
let keyPair2 = bitcoin.ECPair.fromWIF('privateKey2', testnet);
let keyPair2wpkh = bitcoin.payments.p2wpkh({pubkey: keyPair2.publicKey, network: testnet});

const psbt = new bitcoin.Psbt({ network: testnet }) 
let inputdata1 = {
  hash: "hash of the previous transaction" ,
  index: index,
  witnessUtxo: {
    script: Buffer.from('scriptPubKey_hex', 'hex'),
    value: 98e4 
  }
};

psbt.addInput(inputdata1);    
let output1 = {address: keyPair2wpkh.address, value: 97e4};    
psbt.addOutput(output1);    
psbt.signInput(0, keyPair1);    
psbt.finalizeAllInputs();    
const raw = psbt.extractTransaction().toHex();    
console.log(raw);

```


---

### Answer by username_2 on 2020-01-22. Score: 0

Let me first of all say I am a complete newbie so I might be wrong. Regarding the sign method deprecation, what has been **already** deprecated is not the method tx.sign() itself, but the way we passed the parameters. In order not to get the DEPRECATED message for the sign method you should pass an object of the form

{
prevOutScriptType: string;
vin: number;
keyPair: Signer;
redeemScript?: Buffer;
hashType?: number;
witnessValue?: number;
witnessScript?: Buffer;
}

(see <https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/transaction_builder.ts> line 74)

so concretely in your case

tx.sign({prevOutScriptType:'p2pkh', vin: 0, keyPair: owner})


---

