diff --git a/.travis.yml b/.travis.yml
index bb87738..f7aad0e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,6 +19,8 @@ matrix:
       env: TEST_SUITE=gitdiff:ci
     - node_js: "lts/*"
       env: TEST_SUITE=lint
+    - node_js: "lts/*"
+      env: TEST_SUITE=lint:tests
     - node_js: "lts/*"
       env: TEST_SUITE=coverage
 env:
diff --git a/README.md b/README.md
index a94d0ae..b034f20 100644
--- a/README.md
+++ b/README.md
@@ -85,14 +85,6 @@ The below examples are implemented as integration tests, they should be very eas
 Otherwise, pull requests are appreciated.
 Some examples interact (via HTTPS) with a 3rd Party Blockchain Provider (3PBP).
 
-### Warning: Currently the tests use TransactionBuilder, which will be removed in the future (v6.x.x or higher)
-We will move towards replacing all instances of TransactionBuilder in the tests with the new Psbt.
-
-Currently we have a few examples on how to use the newer Psbt class at the following link:
-- [Psbt examples](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions-psbt.spec.ts)
-
-The rest of the examples are below (using TransactionBuilder for Transaction creation)
-
 - [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
 - [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
 - [Generate a 2-of-3 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
@@ -104,7 +96,6 @@ The rest of the examples are below (using TransactionBuilder for Transaction cre
 - [Generate a Testnet address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
 - [Generate a Litecoin address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
 - [Create a 1-to-1 Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.spec.ts)
-- [Create a 2-to-2 Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.spec.ts)
 - [Create (and broadcast via 3PBP) a typical Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.spec.ts)
 - [Create (and broadcast via 3PBP) a Transaction with an OP\_RETURN output](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.spec.ts)
 - [Create (and broadcast via 3PBP) a Transaction with a 2-of-4 P2SH(multisig) input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.spec.ts)
@@ -112,7 +103,7 @@ The rest of the examples are below (using TransactionBuilder for Transaction cre
 - [Create (and broadcast via 3PBP) a Transaction with a SegWit P2WPKH input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.spec.ts)
 - [Create (and broadcast via 3PBP) a Transaction with a SegWit P2PK input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.spec.ts)
 - [Create (and broadcast via 3PBP) a Transaction with a SegWit 3-of-4 P2SH(P2WSH(multisig)) input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.spec.ts)
-- [Verify a Transaction signature](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.spec.ts)
+- [Create (and broadcast via 3PBP) a Transaction and sign with an HDSigner interface (bip32)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.spec.ts)
 - [Import a BIP32 testnet xpriv and export to WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.spec.ts)
 - [Export a BIP32 xpriv, then import it](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.spec.ts)
 - [Export a BIP32 xpub](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/bip32.spec.ts)
diff --git a/package-lock.json b/package-lock.json
index 5812365..4c3dd29 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -156,9 +156,9 @@
       "dev": true
     },
     "@types/node": {
-      "version": "10.12.18",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
-      "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ=="
+      "version": "12.7.5",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz",
+      "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w=="
     },
     "@types/proxyquire": {
       "version": "1.3.28",
@@ -261,6 +261,13 @@
         "tiny-secp256k1": "^1.1.0",
         "typeforce": "^1.11.5",
         "wif": "^2.0.6"
+      },
+      "dependencies": {
+        "@types/node": {
+          "version": "10.12.18",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
+          "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ=="
+        }
       }
     },
     "bip39": {
diff --git a/package.json b/package.json
index 700b7fd..093a097 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
     "gitdiff:ci": "npm run build && git diff --exit-code",
     "integration": "npm run build && npm run nobuild:integration",
     "lint": "tslint -p tsconfig.json -c tslint.json",
+    "lint:tests": "tslint -p test/tsconfig.json -c tslint.json",
     "mocha:ts": "mocha --recursive --require test/ts-node-register",
     "nobuild:coverage-report": "nyc report --reporter=lcov",
     "nobuild:coverage-html": "nyc report --reporter=html",
@@ -48,7 +49,7 @@
     "types"
   ],
   "dependencies": {
-    "@types/node": "10.12.18",
+    "@types/node": "12.7.5",
     "bech32": "^1.1.2",
     "bip174": "^1.0.1",
     "bip32": "^2.0.4",
diff --git a/test/bitcoin.core.spec.ts b/test/bitcoin.core.spec.ts
index 55b16ac..94b74e3 100644
--- a/test/bitcoin.core.spec.ts
+++ b/test/bitcoin.core.spec.ts
@@ -7,8 +7,8 @@ import * as base58KeysInvalid from './fixtures/core/base58_keys_invalid.json';
 import * as base58KeysValid from './fixtures/core/base58_keys_valid.json';
 import * as blocksValid from './fixtures/core/blocks.json';
 import * as sigCanonical from './fixtures/core/sig_canonical.json';
-import * as sigHash from './fixtures/core/sighash.json';
 import * as sigNoncanonical from './fixtures/core/sig_noncanonical.json';
+import * as sigHash from './fixtures/core/sighash.json';
 import * as txValid from './fixtures/core/tx_valid.json';
 
 describe('Bitcoin-core', () => {
@@ -72,11 +72,11 @@ describe('Bitcoin-core', () => {
     ];
 
     base58KeysInvalid.forEach(f => {
-      const string = f[0];
+      const strng = f[0];
 
-      it('throws on ' + string, () => {
+      it('throws on ' + strng, () => {
         assert.throws(() => {
-          const address = bitcoin.address.fromBase58Check(string);
+          const address = bitcoin.address.fromBase58Check(strng);
 
           assert.notStrictEqual(
             allowedNetworks.indexOf(address.version),
@@ -121,11 +121,11 @@ describe('Bitcoin-core', () => {
     ];
 
     base58KeysInvalid.forEach(f => {
-      const string = f[0];
+      const strng = f[0];
 
-      it('throws on ' + string, () => {
+      it('throws on ' + strng, () => {
         assert.throws(() => {
-          bitcoin.ECPair.fromWIF(string, allowedNetworks);
+          bitcoin.ECPair.fromWIF(strng, allowedNetworks);
         }, /(Invalid|Unknown) (checksum|compression flag|network version|WIF length)/);
       });
     });
@@ -242,9 +242,14 @@ describe('Bitcoin-core', () => {
       const buffer = Buffer.from(hex, 'hex');
 
       it('throws on ' + description, () => {
+        const reg = new RegExp(
+          'Expected DER (integer|sequence)|(R|S) value (excessively ' +
+            'padded|is negative)|(R|S|DER sequence) length is (zero|too ' +
+            'short|too long|invalid)|Invalid hashType',
+        );
         assert.throws(() => {
           bitcoin.script.signature.decode(buffer);
-        }, /Expected DER (integer|sequence)|(R|S) value (excessively padded|is negative)|(R|S|DER sequence) length is (zero|too short|too long|invalid)|Invalid hashType/);
+        }, reg);
       });
     });
   });
diff --git a/test/block.spec.ts b/test/block.spec.ts
index 6f8ed03..0f74392 100644
--- a/test/block.spec.ts
+++ b/test/block.spec.ts
@@ -8,7 +8,9 @@ describe('Block', () => {
   describe('version', () => {
     it('should be interpreted as an int32le', () => {
       const blockHex =
-        'ffffffff0000000000000000000000000000000000000000000000000000000000000000414141414141414141414141414141414141414141414141414141414141414101000000020000000300000000';
+        'ffffffff000000000000000000000000000000000000000000000000000000000000' +
+        '00004141414141414141414141414141414141414141414141414141414141414141' +
+        '01000000020000000300000000';
       const block = Block.fromHex(blockHex);
       assert.strictEqual(-1, block.version);
       assert.strictEqual(1, block.timestamp);
diff --git a/test/bufferutils.spec.ts b/test/bufferutils.spec.ts
index 4308af9..33ad8f5 100644
--- a/test/bufferutils.spec.ts
+++ b/test/bufferutils.spec.ts
@@ -9,9 +9,9 @@ describe('bufferutils', () => {
     fixtures.valid.forEach(f => {
       it('decodes ' + f.hex, () => {
         const buffer = Buffer.from(f.hex, 'hex');
-        const number = bufferutils.readUInt64LE(buffer, 0);
+        const num = bufferutils.readUInt64LE(buffer, 0);
 
-        assert.strictEqual(number, f.dec);
+        assert.strictEqual(num, f.dec);
       });
     });
 
diff --git a/test/classify.spec.ts b/test/classify.spec.ts
index b2464c0..931250e 100644
--- a/test/classify.spec.ts
+++ b/test/classify.spec.ts
@@ -1,7 +1,7 @@
 import * as assert from 'assert';
 import { describe, it } from 'mocha';
-import * as bscript from '../src/script';
 import * as classify from '../src/classify';
+import * as bscript from '../src/script';
 
 import * as fixtures from './fixtures/templates.json';
 
@@ -10,9 +10,9 @@ import * as nullData from '../src/templates/nulldata';
 import * as pubKey from '../src/templates/pubkey';
 import * as pubKeyHash from '../src/templates/pubkeyhash';
 import * as scriptHash from '../src/templates/scripthash';
+import * as witnessCommitment from '../src/templates/witnesscommitment';
 import * as witnessPubKeyHash from '../src/templates/witnesspubkeyhash';
 import * as witnessScriptHash from '../src/templates/witnessscripthash';
-import * as witnessCommitment from '../src/templates/witnesscommitment';
 
 const tmap = {
   pubKey,
diff --git a/test/integration/addresses.spec.ts b/test/integration/addresses.spec.ts
index 49dc578..d8feb7c 100644
--- a/test/integration/addresses.spec.ts
+++ b/test/integration/addresses.spec.ts
@@ -6,23 +6,27 @@ const dhttp = regtestUtils.dhttp;
 const TESTNET = bitcoin.networks.testnet;
 
 describe('bitcoinjs-lib (addresses)', () => {
-  it('can generate a random address [and support the retrieval of transactions for that address (via 3PBP)', async () => {
-    const keyPair = bitcoin.ECPair.makeRandom();
-    const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey });
+  it(
+    'can generate a random address [and support the retrieval of ' +
+      'transactions for that address (via 3PBP)]',
+    async () => {
+      const keyPair = bitcoin.ECPair.makeRandom();
+      const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey });
 
-    // bitcoin P2PKH addresses start with a '1'
-    assert.strictEqual(address!.startsWith('1'), true);
+      // bitcoin P2PKH addresses start with a '1'
+      assert.strictEqual(address!.startsWith('1'), true);
 
-    const result = await dhttp({
-      method: 'GET',
-      url: 'https://blockchain.info/rawaddr/' + address,
-    });
+      const result = await dhttp({
+        method: 'GET',
+        url: 'https://blockchain.info/rawaddr/' + address,
+      });
 
-    // random private keys [probably!] have no transactions
-    assert.strictEqual((result as any).n_tx, 0);
-    assert.strictEqual((result as any).total_received, 0);
-    assert.strictEqual((result as any).total_sent, 0);
-  });
+      // random private keys [probably!] have no transactions
+      assert.strictEqual((result as any).n_tx, 0);
+      assert.strictEqual((result as any).total_received, 0);
+      assert.strictEqual((result as any).total_sent, 0);
+    },
+  );
 
   it('can import an address via WIF', () => {
     const keyPair = bitcoin.ECPair.fromWIF(
diff --git a/test/integration/bip32.spec.ts b/test/integration/bip32.spec.ts
index 1279d78..7cd9e2f 100644
--- a/test/integration/bip32.spec.ts
+++ b/test/integration/bip32.spec.ts
@@ -1,7 +1,7 @@
 import * as assert from 'assert';
-import { describe, it } from 'mocha';
 import * as bip32 from 'bip32';
 import * as bip39 from 'bip39';
+import { describe, it } from 'mocha';
 import * as bitcoin from '../..';
 
 function getAddress(node: any, network?: any): string {
@@ -25,8 +25,8 @@ describe('bitcoinjs-lib (BIP32)', () => {
       'praise you muffin lion enable neck grocery crumble super myself license ghost';
     const seed = bip39.mnemonicToSeedSync(mnemonic);
     const node = bip32.fromSeed(seed);
-    const string = node.toBase58();
-    const restored = bip32.fromBase58(string);
+    const strng = node.toBase58();
+    const restored = bip32.fromBase58(strng);
 
     assert.strictEqual(getAddress(node), getAddress(restored)); // same public key
     assert.strictEqual(node.toWIF(), restored.toWIF()); // same private key
@@ -37,10 +37,10 @@ describe('bitcoinjs-lib (BIP32)', () => {
       'praise you muffin lion enable neck grocery crumble super myself license ghost';
     const seed = bip39.mnemonicToSeedSync(mnemonic);
     const node = bip32.fromSeed(seed);
-    const string = node.neutered().toBase58();
+    const strng = node.neutered().toBase58();
 
     assert.strictEqual(
-      string,
+      strng,
       'xpub661MyMwAqRbcGhVeaVfEBA25e3cP9DsJQZoE8iep5fZSxy3TnPBNBgWnMZx56oreNc48ZoTkQfatNJ9VWnQ7ZcLZcVStpaXLTeG8bGrzX3n',
     );
   });
diff --git a/test/integration/blocks.spec.ts b/test/integration/blocks.spec.ts
index 5eed0fc..a98c5eb 100644
--- a/test/integration/blocks.spec.ts
+++ b/test/integration/blocks.spec.ts
@@ -6,7 +6,14 @@ describe('bitcoinjs-lib (blocks)', () => {
   it('can extract a height from a CoinBase transaction', () => {
     // from 00000000000000000097669cdca131f24d40c4cc7d80eaa65967a2d09acf6ce6
     const txHex =
-      '010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff50037f9a07174d696e656420627920416e74506f6f6c685b205a2b1f7bfabe6d6d36afe1910eca9405b66f97750940a656e38e2c0312958190ff8e98fd16761d220400000000000000aa340000d49f0000ffffffff02b07fc366000000001976a9148349212dc27ce3ab4c5b29b85c4dec643d764b1788ac0000000000000000266a24aa21a9ed72d9432948505e3d3062f1307a3f027a5dea846ff85e47159680919c12bf1e400120000000000000000000000000000000000000000000000000000000000000000000000000';
+      '010000000001010000000000000000000000000000000000000000000000000000000' +
+      '000000000ffffffff50037f9a07174d696e656420627920416e74506f6f6c685b205a' +
+      '2b1f7bfabe6d6d36afe1910eca9405b66f97750940a656e38e2c0312958190ff8e98f' +
+      'd16761d220400000000000000aa340000d49f0000ffffffff02b07fc3660000000019' +
+      '76a9148349212dc27ce3ab4c5b29b85c4dec643d764b1788ac0000000000000000266' +
+      'a24aa21a9ed72d9432948505e3d3062f1307a3f027a5dea846ff85e47159680919c12' +
+      'bf1e40012000000000000000000000000000000000000000000000000000000000000' +
+      '0000000000000';
     const tx = bitcoin.Transaction.fromHex(txHex);
 
     assert.strictEqual(tx.ins.length, 1);
diff --git a/test/integration/cltv.spec.ts b/test/integration/cltv.spec.ts
index afdcaa5..d5141c7 100644
--- a/test/integration/cltv.spec.ts
+++ b/test/integration/cltv.spec.ts
@@ -5,6 +5,14 @@ import { regtestUtils } from './_regtest';
 const regtest = regtestUtils.network;
 const bip65 = require('bip65');
 
+function toOutputScript(address: string): Buffer {
+  return bitcoin.address.toOutputScript(address, regtest);
+}
+
+function idToHash(txid: string): Buffer {
+  return Buffer.from(txid, 'hex').reverse();
+}
+
 const alice = bitcoin.ECPair.fromWIF(
   'cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe',
   regtest,
@@ -13,7 +21,6 @@ const bob = bitcoin.ECPair.fromWIF(
   'cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x',
   regtest,
 );
-console.warn = () => {}; // Silence the Deprecation Warning
 
 describe('bitcoinjs-lib (transactions w/ CLTV)', () => {
   // force update MTP
@@ -23,8 +30,14 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', () => {
 
   const hashType = bitcoin.Transaction.SIGHASH_ALL;
 
-  type keyPair = { publicKey: Buffer };
-  function cltvCheckSigOutput(aQ: keyPair, bQ: keyPair, lockTime: number) {
+  interface KeyPair {
+    publicKey: Buffer;
+  }
+  function cltvCheckSigOutput(
+    aQ: KeyPair,
+    bQ: KeyPair,
+    lockTime: number,
+  ): Buffer {
     return bitcoin.script.fromASM(
       `
       OP_IF
@@ -43,177 +56,201 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', () => {
     );
   }
 
-  function utcNow() {
+  function utcNow(): number {
     return Math.floor(Date.now() / 1000);
   }
 
   // expiry past, {Alice's signature} OP_TRUE
-  it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the past)', async () => {
-    // 3 hours ago
-    const lockTime = bip65.encode({ utc: utcNow() - 3600 * 3 });
-    const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
-    const { address } = bitcoin.payments.p2sh({
-      redeem: { output: redeemScript, network: regtest },
-      network: regtest,
-    });
+  it(
+    'can create (and broadcast via 3PBP) a Transaction where Alice can redeem ' +
+      'the output after the expiry (in the past)',
+    async () => {
+      // 3 hours ago
+      const lockTime = bip65.encode({ utc: utcNow() - 3600 * 3 });
+      const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
+      const { address } = bitcoin.payments.p2sh({
+        redeem: { output: redeemScript, network: regtest },
+        network: regtest,
+      });
 
-    // fund the P2SH(CLTV) address
-    const unspent = await regtestUtils.faucet(address!, 1e5);
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.setLockTime(lockTime);
-    // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
-    txb.addInput(unspent.txId, unspent.vout, 0xfffffffe);
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4);
+      // fund the P2SH(CLTV) address
+      const unspent = await regtestUtils.faucet(address!, 1e5);
+      const tx = new bitcoin.Transaction();
+      tx.locktime = lockTime;
+      // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
+      tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
+      tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 7e4);
 
-    // {Alice's signature} OP_TRUE
-    const tx = txb.buildIncomplete();
-    const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
-    const redeemScriptSig = bitcoin.payments.p2sh({
-      redeem: {
-        input: bitcoin.script.compile([
-          bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
-          bitcoin.opcodes.OP_TRUE,
-        ]),
-        output: redeemScript,
-      },
-    }).input;
-    tx.setInputScript(0, redeemScriptSig!);
+      // {Alice's signature} OP_TRUE
+      const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
+      const redeemScriptSig = bitcoin.payments.p2sh({
+        redeem: {
+          input: bitcoin.script.compile([
+            bitcoin.script.signature.encode(
+              alice.sign(signatureHash),
+              hashType,
+            ),
+            bitcoin.opcodes.OP_TRUE,
+          ]),
+          output: redeemScript,
+        },
+      }).input;
+      tx.setInputScript(0, redeemScriptSig!);
 
-    await regtestUtils.broadcast(tx.toHex());
+      await regtestUtils.broadcast(tx.toHex());
 
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 7e4,
-    });
-  });
+      await regtestUtils.verify({
+        txId: tx.getId(),
+        address: regtestUtils.RANDOM_ADDRESS,
+        vout: 0,
+        value: 7e4,
+      });
+    },
+  );
 
   // expiry will pass, {Alice's signature} OP_TRUE
-  it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the future)', async () => {
-    const height = await regtestUtils.height();
-    // 5 blocks from now
-    const lockTime = bip65.encode({ blocks: height + 5 });
-    const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
-    const { address } = bitcoin.payments.p2sh({
-      redeem: { output: redeemScript, network: regtest },
-      network: regtest,
-    });
+  it(
+    'can create (and broadcast via 3PBP) a Transaction where Alice can redeem ' +
+      'the output after the expiry (in the future)',
+    async () => {
+      const height = await regtestUtils.height();
+      // 5 blocks from now
+      const lockTime = bip65.encode({ blocks: height + 5 });
+      const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
+      const { address } = bitcoin.payments.p2sh({
+        redeem: { output: redeemScript, network: regtest },
+        network: regtest,
+      });
 
-    // fund the P2SH(CLTV) address
-    const unspent = await regtestUtils.faucet(address!, 1e5);
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.setLockTime(lockTime);
-    // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
-    txb.addInput(unspent.txId, unspent.vout, 0xfffffffe);
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4);
+      // fund the P2SH(CLTV) address
+      const unspent = await regtestUtils.faucet(address!, 1e5);
+      const tx = new bitcoin.Transaction();
+      tx.locktime = lockTime;
+      // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
+      tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
+      tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 7e4);
 
-    // {Alice's signature} OP_TRUE
-    const tx = txb.buildIncomplete();
-    const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
-    const redeemScriptSig = bitcoin.payments.p2sh({
-      redeem: {
-        input: bitcoin.script.compile([
-          bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
-          bitcoin.opcodes.OP_TRUE,
-        ]),
-        output: redeemScript,
-      },
-    }).input;
-    tx.setInputScript(0, redeemScriptSig!);
+      // {Alice's signature} OP_TRUE
+      const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
+      const redeemScriptSig = bitcoin.payments.p2sh({
+        redeem: {
+          input: bitcoin.script.compile([
+            bitcoin.script.signature.encode(
+              alice.sign(signatureHash),
+              hashType,
+            ),
+            bitcoin.opcodes.OP_TRUE,
+          ]),
+          output: redeemScript,
+        },
+      }).input;
+      tx.setInputScript(0, redeemScriptSig!);
 
-    // TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently
-    // ...
-    // into the future!
-    await regtestUtils.mine(5);
-    await regtestUtils.broadcast(tx.toHex());
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 7e4,
-    });
-  });
+      // TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently
+      // ...
+      // into the future!
+      await regtestUtils.mine(5);
+      await regtestUtils.broadcast(tx.toHex());
+      await regtestUtils.verify({
+        txId: tx.getId(),
+        address: regtestUtils.RANDOM_ADDRESS,
+        vout: 0,
+        value: 7e4,
+      });
+    },
+  );
 
   // expiry ignored, {Bob's signature} {Alice's signature} OP_FALSE
-  it('can create (and broadcast via 3PBP) a Transaction where Alice and Bob can redeem the output at any time', async () => {
-    // two hours ago
-    const lockTime = bip65.encode({ utc: utcNow() - 3600 * 2 });
-    const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
-    const { address } = bitcoin.payments.p2sh({
-      redeem: { output: redeemScript, network: regtest },
-      network: regtest,
-    });
+  it(
+    'can create (and broadcast via 3PBP) a Transaction where Alice and Bob can ' +
+      'redeem the output at any time',
+    async () => {
+      // two hours ago
+      const lockTime = bip65.encode({ utc: utcNow() - 3600 * 2 });
+      const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
+      const { address } = bitcoin.payments.p2sh({
+        redeem: { output: redeemScript, network: regtest },
+        network: regtest,
+      });
 
-    // fund the P2SH(CLTV) address
-    const unspent = await regtestUtils.faucet(address!, 2e5);
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.setLockTime(lockTime);
-    // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
-    txb.addInput(unspent.txId, unspent.vout, 0xfffffffe);
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 8e4);
+      // fund the P2SH(CLTV) address
+      const unspent = await regtestUtils.faucet(address!, 2e5);
+      const tx = new bitcoin.Transaction();
+      tx.locktime = lockTime;
+      // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
+      tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
+      tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 8e4);
 
-    // {Alice's signature} {Bob's signature} OP_FALSE
-    const tx = txb.buildIncomplete();
-    const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
-    const redeemScriptSig = bitcoin.payments.p2sh({
-      redeem: {
-        input: bitcoin.script.compile([
-          bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
-          bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
-          bitcoin.opcodes.OP_FALSE,
-        ]),
-        output: redeemScript,
-      },
-    }).input;
-    tx.setInputScript(0, redeemScriptSig!);
+      // {Alice's signature} {Bob's signature} OP_FALSE
+      const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
+      const redeemScriptSig = bitcoin.payments.p2sh({
+        redeem: {
+          input: bitcoin.script.compile([
+            bitcoin.script.signature.encode(
+              alice.sign(signatureHash),
+              hashType,
+            ),
+            bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
+            bitcoin.opcodes.OP_FALSE,
+          ]),
+          output: redeemScript,
+        },
+      }).input;
+      tx.setInputScript(0, redeemScriptSig!);
 
-    await regtestUtils.broadcast(tx.toHex());
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 8e4,
-    });
-  });
+      await regtestUtils.broadcast(tx.toHex());
+      await regtestUtils.verify({
+        txId: tx.getId(),
+        address: regtestUtils.RANDOM_ADDRESS,
+        vout: 0,
+        value: 8e4,
+      });
+    },
+  );
 
   // expiry in the future, {Alice's signature} OP_TRUE
-  it('can create (but fail to broadcast via 3PBP) a Transaction where Alice attempts to redeem before the expiry', async () => {
-    // two hours from now
-    const lockTime = bip65.encode({ utc: utcNow() + 3600 * 2 });
-    const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
-    const { address } = bitcoin.payments.p2sh({
-      redeem: { output: redeemScript, network: regtest },
-      network: regtest,
-    });
+  it(
+    'can create (but fail to broadcast via 3PBP) a Transaction where Alice ' +
+      'attempts to redeem before the expiry',
+    async () => {
+      // two hours from now
+      const lockTime = bip65.encode({ utc: utcNow() + 3600 * 2 });
+      const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
+      const { address } = bitcoin.payments.p2sh({
+        redeem: { output: redeemScript, network: regtest },
+        network: regtest,
+      });
 
-    // fund the P2SH(CLTV) address
-    const unspent = await regtestUtils.faucet(address!, 2e4);
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.setLockTime(lockTime);
-    // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
-    txb.addInput(unspent.txId, unspent.vout, 0xfffffffe);
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4);
+      // fund the P2SH(CLTV) address
+      const unspent = await regtestUtils.faucet(address!, 2e4);
+      const tx = new bitcoin.Transaction();
+      tx.locktime = lockTime;
+      // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
+      tx.addInput(idToHash(unspent.txId), unspent.vout, 0xfffffffe);
+      tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 1e4);
 
-    // {Alice's signature} OP_TRUE
-    const tx = txb.buildIncomplete();
-    const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
-    const redeemScriptSig = bitcoin.payments.p2sh({
-      redeem: {
-        input: bitcoin.script.compile([
-          bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
-          bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
-          bitcoin.opcodes.OP_TRUE,
-        ]),
-        output: redeemScript,
-      },
-    }).input;
-    tx.setInputScript(0, redeemScriptSig!);
+      // {Alice's signature} OP_TRUE
+      const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
+      const redeemScriptSig = bitcoin.payments.p2sh({
+        redeem: {
+          input: bitcoin.script.compile([
+            bitcoin.script.signature.encode(
+              alice.sign(signatureHash),
+              hashType,
+            ),
+            bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
+            bitcoin.opcodes.OP_TRUE,
+          ]),
+          output: redeemScript,
+        },
+      }).input;
+      tx.setInputScript(0, redeemScriptSig!);
 
-    await regtestUtils.broadcast(tx.toHex()).catch(err => {
-      assert.throws(() => {
-        if (err) throw err;
-      }, /Error: non-final \(code 64\)/);
-    });
-  });
+      await regtestUtils.broadcast(tx.toHex()).catch(err => {
+        assert.throws(() => {
+          if (err) throw err;
+        }, /Error: non-final \(code 64\)/);
+      });
+    },
+  );
 });
diff --git a/test/integration/csv.spec.ts b/test/integration/csv.spec.ts
index 0bfb970..d6f99c7 100644
--- a/test/integration/csv.spec.ts
+++ b/test/integration/csv.spec.ts
@@ -5,6 +5,14 @@ import { regtestUtils } from './_regtest';
 const regtest = regtestUtils.network;
 const bip68 = require('bip68');
 
+function toOutputScript(address: string): Buffer {
+  return bitcoin.address.toOutputScript(address, regtest);
+}
+
+function idToHash(txid: string): Buffer {
+  return Buffer.from(txid, 'hex').reverse();
+}
+
 const alice = bitcoin.ECPair.fromWIF(
   'cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe',
   regtest,
@@ -21,7 +29,6 @@ const dave = bitcoin.ECPair.fromWIF(
   'cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsMwS4pqnx',
   regtest,
 );
-console.warn = () => {}; // Silence the Deprecation Warning
 
 describe('bitcoinjs-lib (transactions w/ CSV)', () => {
   // force update MTP
@@ -31,9 +38,15 @@ describe('bitcoinjs-lib (transactions w/ CSV)', () => {
 
   const hashType = bitcoin.Transaction.SIGHASH_ALL;
 
-  type keyPair = { publicKey: Buffer };
+  interface KeyPair {
+    publicKey: Buffer;
+  }
   // IF MTP (from when confirmed) > seconds, _alice can redeem
-  function csvCheckSigOutput(_alice: keyPair, _bob: keyPair, sequence: number) {
+  function csvCheckSigOutput(
+    _alice: KeyPair,
+    _bob: KeyPair,
+    sequence: number,
+  ): Buffer {
     return bitcoin.script.fromASM(
       `
       OP_IF
@@ -55,17 +68,20 @@ describe('bitcoinjs-lib (transactions w/ CSV)', () => {
   // 2 of 3 multisig of _bob, _charles, _dave,
   // but after sequence1 time, _alice can allow the multisig to become 1 of 3.
   // but after sequence2 time, _alice can sign for the output all by themself.
+
+  /* tslint:disable-next-line */
   // Ref: https://github.com/bitcoinbook/bitcoinbook/blob/f8b883dcd4e3d1b9adf40fed59b7e898fbd9241f/ch07.asciidoc#complex-script-example
+
   // Note: bitcoinjs-lib will not offer specific support for problems with
   //       advanced script usages such as below. Use at your own risk.
   function complexCsvOutput(
-    _alice: keyPair,
-    _bob: keyPair,
-    _charles: keyPair,
-    _dave: keyPair,
+    _alice: KeyPair,
+    _bob: KeyPair,
+    _charles: KeyPair,
+    _dave: KeyPair,
     sequence1: number,
     sequence2: number,
-  ) {
+  ): Buffer {
     return bitcoin.script.fromASM(
       `
       OP_IF
@@ -98,287 +114,319 @@ describe('bitcoinjs-lib (transactions w/ CSV)', () => {
   }
 
   // expiry will pass, {Alice's signature} OP_TRUE
-  it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the future) (simple CHECKSEQUENCEVERIFY)', async () => {
-    // 5 blocks from now
-    const sequence = bip68.encode({ blocks: 5 });
-    const p2sh = bitcoin.payments.p2sh({
-      redeem: {
-        output: csvCheckSigOutput(alice, bob, sequence),
-      },
-      network: regtest,
-    });
-
-    // fund the P2SH(CSV) address
-    const unspent = await regtestUtils.faucet(p2sh.address!, 1e5);
-
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.addInput(unspent.txId, unspent.vout, sequence);
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4);
-
-    // {Alice's signature} OP_TRUE
-    const tx = txb.buildIncomplete();
-    const signatureHash = tx.hashForSignature(
-      0,
-      p2sh.redeem!.output!,
-      hashType,
-    );
-    const redeemScriptSig = bitcoin.payments.p2sh({
-      network: regtest,
-      redeem: {
+  it(
+    'can create (and broadcast via 3PBP) a Transaction where Alice can redeem ' +
+      'the output after the expiry (in the future) (simple CHECKSEQUENCEVERIFY)',
+    async () => {
+      // 5 blocks from now
+      const sequence = bip68.encode({ blocks: 5 });
+      const p2sh = bitcoin.payments.p2sh({
+        redeem: {
+          output: csvCheckSigOutput(alice, bob, sequence),
+        },
         network: regtest,
-        output: p2sh.redeem!.output,
-        input: bitcoin.script.compile([
-          bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
-          bitcoin.opcodes.OP_TRUE,
-        ]),
-      },
-    }).input;
-    tx.setInputScript(0, redeemScriptSig!);
+      });
 
-    // TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently
-    // ...
-    // into the future!
-    await regtestUtils.mine(10);
+      // fund the P2SH(CSV) address
+      const unspent = await regtestUtils.faucet(p2sh.address!, 1e5);
 
-    await regtestUtils.broadcast(tx.toHex());
+      const tx = new bitcoin.Transaction();
+      tx.version = 2;
+      tx.addInput(idToHash(unspent.txId), unspent.vout, sequence);
+      tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 7e4);
 
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 7e4,
-    });
-  });
+      // {Alice's signature} OP_TRUE
+      const signatureHash = tx.hashForSignature(
+        0,
+        p2sh.redeem!.output!,
+        hashType,
+      );
+      const redeemScriptSig = bitcoin.payments.p2sh({
+        network: regtest,
+        redeem: {
+          network: regtest,
+          output: p2sh.redeem!.output,
+          input: bitcoin.script.compile([
+            bitcoin.script.signature.encode(
+              alice.sign(signatureHash),
+              hashType,
+            ),
+            bitcoin.opcodes.OP_TRUE,
+          ]),
+        },
+      }).input;
+      tx.setInputScript(0, redeemScriptSig!);
+
+      // TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently
+      // ...
+      // into the future!
+      await regtestUtils.mine(10);
+
+      await regtestUtils.broadcast(tx.toHex());
+
+      await regtestUtils.verify({
+        txId: tx.getId(),
+        address: regtestUtils.RANDOM_ADDRESS,
+        vout: 0,
+        value: 7e4,
+      });
+    },
+  );
 
   // expiry in the future, {Alice's signature} OP_TRUE
-  it('can create (but fail to broadcast via 3PBP) a Transaction where Alice attempts to redeem before the expiry (simple CHECKSEQUENCEVERIFY)', async () => {
-    // two hours after confirmation
-    const sequence = bip68.encode({ seconds: 7168 });
-    const p2sh = bitcoin.payments.p2sh({
-      network: regtest,
-      redeem: {
-        output: csvCheckSigOutput(alice, bob, sequence),
-      },
-    });
-
-    // fund the P2SH(CSV) address
-    const unspent = await regtestUtils.faucet(p2sh.address!, 2e4);
-
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.addInput(unspent.txId, unspent.vout, sequence);
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4);
-
-    // {Alice's signature} OP_TRUE
-    const tx = txb.buildIncomplete();
-    const signatureHash = tx.hashForSignature(
-      0,
-      p2sh.redeem!.output!,
-      hashType,
-    );
-    const redeemScriptSig = bitcoin.payments.p2sh({
-      network: regtest,
-      redeem: {
+  it(
+    'can create (but fail to broadcast via 3PBP) a Transaction where Alice ' +
+      'attempts to redeem before the expiry (simple CHECKSEQUENCEVERIFY)',
+    async () => {
+      // two hours after confirmation
+      const sequence = bip68.encode({ seconds: 7168 });
+      const p2sh = bitcoin.payments.p2sh({
         network: regtest,
-        output: p2sh.redeem!.output,
-        input: bitcoin.script.compile([
-          bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
-          bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
-          bitcoin.opcodes.OP_TRUE,
-        ]),
-      },
-    }).input;
-    tx.setInputScript(0, redeemScriptSig!);
+        redeem: {
+          output: csvCheckSigOutput(alice, bob, sequence),
+        },
+      });
 
-    await regtestUtils.broadcast(tx.toHex()).catch(err => {
-      assert.throws(() => {
-        if (err) throw err;
-      }, /Error: non-BIP68-final \(code 64\)/);
-    });
-  });
+      // fund the P2SH(CSV) address
+      const unspent = await regtestUtils.faucet(p2sh.address!, 2e4);
+
+      const tx = new bitcoin.Transaction();
+      tx.version = 2;
+      tx.addInput(idToHash(unspent.txId), unspent.vout, sequence);
+      tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 1e4);
+
+      // {Alice's signature} OP_TRUE
+      const signatureHash = tx.hashForSignature(
+        0,
+        p2sh.redeem!.output!,
+        hashType,
+      );
+      const redeemScriptSig = bitcoin.payments.p2sh({
+        network: regtest,
+        redeem: {
+          network: regtest,
+          output: p2sh.redeem!.output,
+          input: bitcoin.script.compile([
+            bitcoin.script.signature.encode(
+              alice.sign(signatureHash),
+              hashType,
+            ),
+            bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
+            bitcoin.opcodes.OP_TRUE,
+          ]),
+        },
+      }).input;
+      tx.setInputScript(0, redeemScriptSig!);
+
+      await regtestUtils.broadcast(tx.toHex()).catch(err => {
+        assert.throws(() => {
+          if (err) throw err;
+        }, /Error: non-BIP68-final \(code 64\)/);
+      });
+    },
+  );
 
   // Check first combination of complex CSV, 2 of 3
-  it('can create (and broadcast via 3PBP) a Transaction where Bob and Charles can send (complex CHECKSEQUENCEVERIFY)', async () => {
-    // 2 blocks from now
-    const sequence1 = bip68.encode({ blocks: 2 });
-    // 5 blocks from now
-    const sequence2 = bip68.encode({ blocks: 5 });
-    const p2sh = bitcoin.payments.p2sh({
-      redeem: {
-        output: complexCsvOutput(
-          alice,
-          bob,
-          charles,
-          dave,
-          sequence1,
-          sequence2,
-        ),
-      },
-      network: regtest,
-    });
-
-    // fund the P2SH(CCSV) address
-    const unspent = await regtestUtils.faucet(p2sh.address!, 1e5);
-
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.addInput(unspent.txId, unspent.vout);
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4);
-
-    // OP_0 {Bob sig} {Charles sig} OP_TRUE OP_TRUE
-    const tx = txb.buildIncomplete();
-    const signatureHash = tx.hashForSignature(
-      0,
-      p2sh.redeem!.output!,
-      hashType,
-    );
-    const redeemScriptSig = bitcoin.payments.p2sh({
-      network: regtest,
-      redeem: {
-        network: regtest,
-        output: p2sh.redeem!.output,
-        input: bitcoin.script.compile([
-          bitcoin.opcodes.OP_0,
-          bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
-          bitcoin.script.signature.encode(
-            charles.sign(signatureHash),
-            hashType,
+  it(
+    'can create (and broadcast via 3PBP) a Transaction where Bob and Charles ' +
+      'can send (complex CHECKSEQUENCEVERIFY)',
+    async () => {
+      // 2 blocks from now
+      const sequence1 = bip68.encode({ blocks: 2 });
+      // 5 blocks from now
+      const sequence2 = bip68.encode({ blocks: 5 });
+      const p2sh = bitcoin.payments.p2sh({
+        redeem: {
+          output: complexCsvOutput(
+            alice,
+            bob,
+            charles,
+            dave,
+            sequence1,
+            sequence2,
           ),
-          bitcoin.opcodes.OP_TRUE,
-          bitcoin.opcodes.OP_TRUE,
-        ]),
-      },
-    }).input;
-    tx.setInputScript(0, redeemScriptSig!);
+        },
+        network: regtest,
+      });
 
-    await regtestUtils.broadcast(tx.toHex());
+      // fund the P2SH(CCSV) address
+      const unspent = await regtestUtils.faucet(p2sh.address!, 1e5);
 
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 7e4,
-    });
-  });
+      const tx = new bitcoin.Transaction();
+      tx.version = 2;
+      tx.addInput(idToHash(unspent.txId), unspent.vout);
+      tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 7e4);
+
+      // OP_0 {Bob sig} {Charles sig} OP_TRUE OP_TRUE
+      const signatureHash = tx.hashForSignature(
+        0,
+        p2sh.redeem!.output!,
+        hashType,
+      );
+      const redeemScriptSig = bitcoin.payments.p2sh({
+        network: regtest,
+        redeem: {
+          network: regtest,
+          output: p2sh.redeem!.output,
+          input: bitcoin.script.compile([
+            bitcoin.opcodes.OP_0,
+            bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
+            bitcoin.script.signature.encode(
+              charles.sign(signatureHash),
+              hashType,
+            ),
+            bitcoin.opcodes.OP_TRUE,
+            bitcoin.opcodes.OP_TRUE,
+          ]),
+        },
+      }).input;
+      tx.setInputScript(0, redeemScriptSig!);
+
+      await regtestUtils.broadcast(tx.toHex());
+
+      await regtestUtils.verify({
+        txId: tx.getId(),
+        address: regtestUtils.RANDOM_ADDRESS,
+        vout: 0,
+        value: 7e4,
+      });
+    },
+  );
 
   // Check first combination of complex CSV, mediator + 1 of 3 after 2 blocks
-  it('can create (and broadcast via 3PBP) a Transaction where Alice (mediator) and Bob can send after 2 blocks (complex CHECKSEQUENCEVERIFY)', async () => {
-    // 2 blocks from now
-    const sequence1 = bip68.encode({ blocks: 2 });
-    // 5 blocks from now
-    const sequence2 = bip68.encode({ blocks: 5 });
-    const p2sh = bitcoin.payments.p2sh({
-      redeem: {
-        output: complexCsvOutput(
-          alice,
-          bob,
-          charles,
-          dave,
-          sequence1,
-          sequence2,
-        ),
-      },
-      network: regtest,
-    });
-
-    // fund the P2SH(CCSV) address
-    const unspent = await regtestUtils.faucet(p2sh.address!, 1e5);
-
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.addInput(unspent.txId, unspent.vout, sequence1); // Set sequence1 for input
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4);
-
-    // OP_0 {Bob sig} {Alice mediator sig} OP_FALSE OP_TRUE
-    const tx = txb.buildIncomplete();
-    const signatureHash = tx.hashForSignature(
-      0,
-      p2sh.redeem!.output!,
-      hashType,
-    );
-    const redeemScriptSig = bitcoin.payments.p2sh({
-      network: regtest,
-      redeem: {
+  it(
+    'can create (and broadcast via 3PBP) a Transaction where Alice (mediator) ' +
+      'and Bob can send after 2 blocks (complex CHECKSEQUENCEVERIFY)',
+    async () => {
+      // 2 blocks from now
+      const sequence1 = bip68.encode({ blocks: 2 });
+      // 5 blocks from now
+      const sequence2 = bip68.encode({ blocks: 5 });
+      const p2sh = bitcoin.payments.p2sh({
+        redeem: {
+          output: complexCsvOutput(
+            alice,
+            bob,
+            charles,
+            dave,
+            sequence1,
+            sequence2,
+          ),
+        },
         network: regtest,
-        output: p2sh.redeem!.output,
-        input: bitcoin.script.compile([
-          bitcoin.opcodes.OP_0,
-          bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
-          bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
-          bitcoin.opcodes.OP_0,
-          bitcoin.opcodes.OP_TRUE,
-        ]),
-      },
-    }).input;
-    tx.setInputScript(0, redeemScriptSig!);
+      });
 
-    // Wait 2 blocks
-    await regtestUtils.mine(2);
+      // fund the P2SH(CCSV) address
+      const unspent = await regtestUtils.faucet(p2sh.address!, 1e5);
 
-    await regtestUtils.broadcast(tx.toHex());
+      const tx = new bitcoin.Transaction();
+      tx.version = 2;
+      tx.addInput(idToHash(unspent.txId), unspent.vout, sequence1); // Set sequence1 for input
+      tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 7e4);
 
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 7e4,
-    });
-  });
+      // OP_0 {Bob sig} {Alice mediator sig} OP_FALSE OP_TRUE
+      const signatureHash = tx.hashForSignature(
+        0,
+        p2sh.redeem!.output!,
+        hashType,
+      );
+      const redeemScriptSig = bitcoin.payments.p2sh({
+        network: regtest,
+        redeem: {
+          network: regtest,
+          output: p2sh.redeem!.output,
+          input: bitcoin.script.compile([
+            bitcoin.opcodes.OP_0,
+            bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
+            bitcoin.script.signature.encode(
+              alice.sign(signatureHash),
+              hashType,
+            ),
+            bitcoin.opcodes.OP_0,
+            bitcoin.opcodes.OP_TRUE,
+          ]),
+        },
+      }).input;
+      tx.setInputScript(0, redeemScriptSig!);
+
+      // Wait 2 blocks
+      await regtestUtils.mine(2);
+
+      await regtestUtils.broadcast(tx.toHex());
+
+      await regtestUtils.verify({
+        txId: tx.getId(),
+        address: regtestUtils.RANDOM_ADDRESS,
+        vout: 0,
+        value: 7e4,
+      });
+    },
+  );
 
   // Check first combination of complex CSV, mediator after 5 blocks
-  it('can create (and broadcast via 3PBP) a Transaction where Alice (mediator) can send after 5 blocks (complex CHECKSEQUENCEVERIFY)', async () => {
-    // 2 blocks from now
-    const sequence1 = bip68.encode({ blocks: 2 });
-    // 5 blocks from now
-    const sequence2 = bip68.encode({ blocks: 5 });
-    const p2sh = bitcoin.payments.p2sh({
-      redeem: {
-        output: complexCsvOutput(
-          alice,
-          bob,
-          charles,
-          dave,
-          sequence1,
-          sequence2,
-        ),
-      },
-      network: regtest,
-    });
-
-    // fund the P2SH(CCSV) address
-    const unspent = await regtestUtils.faucet(p2sh.address!, 1e5);
-
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.addInput(unspent.txId, unspent.vout, sequence2); // Set sequence2 for input
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4);
-
-    // {Alice mediator sig} OP_FALSE
-    const tx = txb.buildIncomplete();
-    const signatureHash = tx.hashForSignature(
-      0,
-      p2sh.redeem!.output!,
-      hashType,
-    );
-    const redeemScriptSig = bitcoin.payments.p2sh({
-      network: regtest,
-      redeem: {
+  it(
+    'can create (and broadcast via 3PBP) a Transaction where Alice (mediator) ' +
+      'can send after 5 blocks (complex CHECKSEQUENCEVERIFY)',
+    async () => {
+      // 2 blocks from now
+      const sequence1 = bip68.encode({ blocks: 2 });
+      // 5 blocks from now
+      const sequence2 = bip68.encode({ blocks: 5 });
+      const p2sh = bitcoin.payments.p2sh({
+        redeem: {
+          output: complexCsvOutput(
+            alice,
+            bob,
+            charles,
+            dave,
+            sequence1,
+            sequence2,
+          ),
+        },
         network: regtest,
-        output: p2sh.redeem!.output,
-        input: bitcoin.script.compile([
-          bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
-          bitcoin.opcodes.OP_0,
-        ]),
-      },
-    }).input;
-    tx.setInputScript(0, redeemScriptSig!);
+      });
 
-    // Wait 5 blocks
-    await regtestUtils.mine(5);
+      // fund the P2SH(CCSV) address
+      const unspent = await regtestUtils.faucet(p2sh.address!, 1e5);
 
-    await regtestUtils.broadcast(tx.toHex());
+      const tx = new bitcoin.Transaction();
+      tx.version = 2;
+      tx.addInput(idToHash(unspent.txId), unspent.vout, sequence2); // Set sequence2 for input
+      tx.addOutput(toOutputScript(regtestUtils.RANDOM_ADDRESS), 7e4);
 
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 7e4,
-    });
-  });
+      // {Alice mediator sig} OP_FALSE
+      const signatureHash = tx.hashForSignature(
+        0,
+        p2sh.redeem!.output!,
+        hashType,
+      );
+      const redeemScriptSig = bitcoin.payments.p2sh({
+        network: regtest,
+        redeem: {
+          network: regtest,
+          output: p2sh.redeem!.output,
+          input: bitcoin.script.compile([
+            bitcoin.script.signature.encode(
+              alice.sign(signatureHash),
+              hashType,
+            ),
+            bitcoin.opcodes.OP_0,
+          ]),
+        },
+      }).input;
+      tx.setInputScript(0, redeemScriptSig!);
+
+      // Wait 5 blocks
+      await regtestUtils.mine(5);
+
+      await regtestUtils.broadcast(tx.toHex());
+
+      await regtestUtils.verify({
+        txId: tx.getId(),
+        address: regtestUtils.RANDOM_ADDRESS,
+        vout: 0,
+        value: 7e4,
+      });
+    },
+  );
 });
diff --git a/test/integration/payments.spec.ts b/test/integration/payments.spec.ts
index 6592c2c..58f48f5 100644
--- a/test/integration/payments.spec.ts
+++ b/test/integration/payments.spec.ts
@@ -6,46 +6,43 @@ const keyPairs = [
   bitcoin.ECPair.makeRandom({ network: NETWORK }),
   bitcoin.ECPair.makeRandom({ network: NETWORK }),
 ];
-console.warn = () => {}; // Silence the Deprecation Warning
 
 async function buildAndSign(
   depends: any,
   prevOutput: any,
   redeemScript: any,
   witnessScript: any,
-) {
+): Promise<null> {
   const unspent = await regtestUtils.faucetComplex(prevOutput, 5e4);
+  const utx = await regtestUtils.fetch(unspent.txId);
 
-  const txb = new bitcoin.TransactionBuilder(NETWORK);
-  txb.addInput(unspent.txId, unspent.vout, undefined, prevOutput);
-  txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4);
-
-  const posType = depends.prevOutScriptType;
-  const needsValue = !!witnessScript || posType.slice(-6) === 'p2wpkh';
+  const psbt = new bitcoin.Psbt({ network: NETWORK })
+    .addInput({
+      hash: unspent.txId,
+      index: unspent.vout,
+      nonWitnessUtxo: Buffer.from(utx.txHex, 'hex'),
+      ...(redeemScript ? { redeemScript } : {}),
+      ...(witnessScript ? { witnessScript } : {}),
+    })
+    .addOutput({
+      address: regtestUtils.RANDOM_ADDRESS,
+      value: 2e4,
+    });
 
   if (depends.signatures) {
     keyPairs.forEach(keyPair => {
-      txb.sign({
-        prevOutScriptType: posType,
-        vin: 0,
-        keyPair,
-        redeemScript,
-        witnessValue: needsValue ? unspent.value : undefined,
-        witnessScript,
-      });
+      psbt.signInput(0, keyPair);
     });
   } else if (depends.signature) {
-    txb.sign({
-      prevOutScriptType: posType,
-      vin: 0,
-      keyPair: keyPairs[0],
-      redeemScript,
-      witnessValue: needsValue ? unspent.value : undefined,
-      witnessScript,
-    });
+    psbt.signInput(0, keyPairs[0]);
   }
 
-  return regtestUtils.broadcast(txb.build().toHex());
+  return regtestUtils.broadcast(
+    psbt
+      .finalizeAllInputs()
+      .extractTransaction()
+      .toHex(),
+  );
 }
 
 ['p2ms', 'p2pk', 'p2pkh', 'p2wpkh'].forEach(k => {
diff --git a/test/integration/transactions-psbt.spec.ts b/test/integration/transactions-psbt.spec.ts
deleted file mode 100644
index a98407d..0000000
--- a/test/integration/transactions-psbt.spec.ts
+++ /dev/null
@@ -1,669 +0,0 @@
-import * as assert from 'assert';
-import { describe, it } from 'mocha';
-import * as bitcoin from '../..';
-import { regtestUtils } from './_regtest';
-import * as bip32 from 'bip32';
-const rng = require('randombytes');
-const regtest = regtestUtils.network;
-
-// See bottom of file for some helper functions used to make the payment objects needed.
-
-describe('bitcoinjs-lib (transactions with psbt)', () => {
-  it('can create a 1-to-1 Transaction', () => {
-    const alice = bitcoin.ECPair.fromWIF(
-      'L2uPYXe17xSTqbCjZvL2DsyXPCbXspvcu5mHLDYUgzdUbZGSKrSr',
-    );
-    const psbt = new bitcoin.Psbt();
-    psbt.setVersion(2); // These are defaults. This line is not needed.
-    psbt.setLocktime(0); // These are defaults. This line is not needed.
-    psbt.addInput({
-      // if hash is string, txid, if hash is Buffer, is reversed compared to txid
-      hash: '7d067b4a697a09d2c3cff7d4d9506c9955e93bff41bf82d439da7d030382bc3e',
-      index: 0,
-      sequence: 0xffffffff, // These are defaults. This line is not needed.
-
-      // non-segwit inputs now require passing the whole previous tx as Buffer
-      nonWitnessUtxo: Buffer.from(
-        '0200000001f9f34e95b9d5c8abcd20fc5bd4a825d1517be62f0f775e5f36da944d9' +
-          '452e550000000006b483045022100c86e9a111afc90f64b4904bd609e9eaed80d48' +
-          'ca17c162b1aca0a788ac3526f002207bb79b60d4fc6526329bf18a77135dc566020' +
-          '9e761da46e1c2f1152ec013215801210211755115eabf846720f5cb18f248666fec' +
-          '631e5e1e66009ce3710ceea5b1ad13ffffffff01' +
-          // value in satoshis (Int64LE) = 0x015f90 = 90000
-          '905f010000000000' +
-          // scriptPubkey length
-          '19' +
-          // scriptPubkey
-          '76a9148bbc95d2709c71607c60ee3f097c1217482f518d88ac' +
-          // locktime
-          '00000000',
-        'hex',
-      ),
-
-      // // If this input was segwit, instead of nonWitnessUtxo, you would add
-      // // a witnessUtxo as follows. The scriptPubkey and the value only are needed.
-      // witnessUtxo: {
-      //   script: Buffer.from(
-      //     '76a9148bbc95d2709c71607c60ee3f097c1217482f518d88ac',
-      //     'hex',
-      //   ),
-      //   value: 90000,
-      // },
-
-      // Not featured here:
-      //   redeemScript. A Buffer of the redeemScript for P2SH
-      //   witnessScript. A Buffer of the witnessScript for P2WSH
-    });
-    psbt.addOutput({
-      address: '1KRMKfeZcmosxALVYESdPNez1AP1mEtywp',
-      value: 80000,
-    });
-    psbt.signInput(0, alice);
-    psbt.validateSignaturesOfInput(0);
-    psbt.finalizeAllInputs();
-    assert.strictEqual(
-      psbt.extractTransaction().toHex(),
-      '02000000013ebc8203037dda39d482bf41ff3be955996c50d9d4f7cfc3d2097a694a7' +
-        'b067d000000006b483045022100931b6db94aed25d5486884d83fc37160f37f3368c0' +
-        'd7f48c757112abefec983802205fda64cff98c849577026eb2ce916a50ea70626a766' +
-        '9f8596dd89b720a26b4d501210365db9da3f8a260078a7e8f8b708a1161468fb2323f' +
-        'fda5ec16b261ec1056f455ffffffff0180380100000000001976a914ca0d36044e0dc' +
-        '08a22724efa6f6a07b0ec4c79aa88ac00000000',
-    );
-  });
-
-  it('can create (and broadcast via 3PBP) a typical Transaction', async () => {
-    // these are { payment: Payment; keys: ECPair[] }
-    const alice1 = createPayment('p2pkh');
-    const alice2 = createPayment('p2pkh');
-
-    // give Alice 2 unspent outputs
-    const inputData1 = await getInputData(
-      5e4,
-      alice1.payment,
-      false,
-      'noredeem',
-    );
-    const inputData2 = await getInputData(
-      7e4,
-      alice2.payment,
-      false,
-      'noredeem',
-    );
-    {
-      const {
-        hash, // string of txid or Buffer of tx hash. (txid and hash are reverse order)
-        index, // the output index of the txo you are spending
-        nonWitnessUtxo, // the full previous transaction as a Buffer
-      } = inputData1;
-      assert.deepStrictEqual({ hash, index, nonWitnessUtxo }, inputData1);
-    }
-
-    // network is only needed if you pass an address to addOutput
-    // using script (Buffer of scriptPubkey) instead will avoid needed network.
-    const psbt = new bitcoin.Psbt({ network: regtest })
-      .addInput(inputData1) // alice1 unspent
-      .addInput(inputData2) // alice2 unspent
-      .addOutput({
-        address: 'mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf',
-        value: 8e4,
-      }) // the actual "spend"
-      .addOutput({
-        address: alice2.payment.address, // OR script, which is a Buffer.
-        value: 1e4,
-      }); // Alice's change
-    // (in)(5e4 + 7e4) - (out)(8e4 + 1e4) = (fee)3e4 = 30000, this is the miner fee
-
-    // Let's show a new feature with PSBT.
-    // We can have multiple signers sign in parrallel and combine them.
-    // (this is not necessary, but a nice feature)
-
-    // encode to send out to the signers
-    const psbtBaseText = psbt.toBase64();
-
-    // each signer imports
-    const signer1 = bitcoin.Psbt.fromBase64(psbtBaseText);
-    const signer2 = bitcoin.Psbt.fromBase64(psbtBaseText);
-
-    // Alice signs each input with the respective private keys
-    // signInput and signInputAsync are better
-    // (They take the input index explicitly as the first arg)
-    signer1.signAllInputs(alice1.keys[0]);
-    signer2.signAllInputs(alice2.keys[0]);
-
-    // If your signer object's sign method returns a promise, use the following
-    // await signer2.signAllInputsAsync(alice2.keys[0])
-
-    // encode to send back to combiner (signer 1 and 2 are not near each other)
-    const s1text = signer1.toBase64();
-    const s2text = signer2.toBase64();
-
-    const final1 = bitcoin.Psbt.fromBase64(s1text);
-    const final2 = bitcoin.Psbt.fromBase64(s2text);
-
-    // final1.combine(final2) would give the exact same result
-    psbt.combine(final1, final2);
-
-    // Finalizer wants to check all signatures are valid before finalizing.
-    // If the finalizer wants to check for specific pubkeys, the second arg
-    // can be passed. See the first multisig example below.
-    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
-    assert.strictEqual(psbt.validateSignaturesOfInput(1), true);
-
-    // This step it new. Since we separate the signing operation and
-    // the creation of the scriptSig and witness stack, we are able to
-    psbt.finalizeAllInputs();
-
-    // build and broadcast our RegTest network
-    await regtestUtils.broadcast(psbt.extractTransaction().toHex());
-    // to build and broadcast to the actual Bitcoin network, see https://github.com/bitcoinjs/bitcoinjs-lib/issues/839
-  });
-
-  it('can create (and broadcast via 3PBP) a Transaction with an OP_RETURN output', async () => {
-    const alice1 = createPayment('p2pkh');
-    const inputData1 = await getInputData(
-      2e5,
-      alice1.payment,
-      false,
-      'noredeem',
-    );
-
-    const data = Buffer.from('bitcoinjs-lib', 'utf8');
-    const embed = bitcoin.payments.embed({ data: [data] });
-
-    const psbt = new bitcoin.Psbt({ network: regtest })
-      .addInput(inputData1)
-      .addOutput({
-        script: embed.output!,
-        value: 1000,
-      })
-      .addOutput({
-        address: regtestUtils.RANDOM_ADDRESS,
-        value: 1e5,
-      })
-      .signInput(0, alice1.keys[0]);
-
-    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
-    psbt.finalizeAllInputs();
-
-    // build and broadcast to the RegTest network
-    await regtestUtils.broadcast(psbt.extractTransaction().toHex());
-  });
-
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2MS(2 of 4)) (multisig) input', async () => {
-    const multisig = createPayment('p2sh-p2ms(2 of 4)');
-    const inputData1 = await getInputData(2e4, multisig.payment, false, 'p2sh');
-    {
-      const {
-        hash,
-        index,
-        nonWitnessUtxo,
-        redeemScript, // NEW: P2SH needs to give redeemScript when adding an input.
-      } = inputData1;
-      assert.deepStrictEqual(
-        { hash, index, nonWitnessUtxo, redeemScript },
-        inputData1,
-      );
-    }
-
-    const psbt = new bitcoin.Psbt({ network: regtest })
-      .addInput(inputData1)
-      .addOutput({
-        address: regtestUtils.RANDOM_ADDRESS,
-        value: 1e4,
-      })
-      .signInput(0, multisig.keys[0])
-      .signInput(0, multisig.keys[2]);
-
-    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
-    assert.strictEqual(
-      psbt.validateSignaturesOfInput(0, multisig.keys[0].publicKey),
-      true,
-    );
-    assert.throws(() => {
-      psbt.validateSignaturesOfInput(0, multisig.keys[3].publicKey);
-    }, new RegExp('No signatures for this pubkey'));
-    psbt.finalizeAllInputs();
-
-    const tx = psbt.extractTransaction();
-
-    // build and broadcast to the Bitcoin RegTest network
-    await regtestUtils.broadcast(tx.toHex());
-
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 1e4,
-    });
-  });
-
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WPKH) input', async () => {
-    const p2sh = createPayment('p2sh-p2wpkh');
-    const inputData = await getInputData(5e4, p2sh.payment, true, 'p2sh');
-    const inputData2 = await getInputData(5e4, p2sh.payment, true, 'p2sh');
-    {
-      const {
-        hash,
-        index,
-        witnessUtxo, // NEW: this is an object of the output being spent { script: Buffer; value: Satoshis; }
-        redeemScript,
-      } = inputData;
-      assert.deepStrictEqual(
-        { hash, index, witnessUtxo, redeemScript },
-        inputData,
-      );
-    }
-    const keyPair = p2sh.keys[0];
-    const outputData = {
-      script: p2sh.payment.output, // sending to myself for fun
-      value: 2e4,
-    };
-    const outputData2 = {
-      script: p2sh.payment.output, // sending to myself for fun
-      value: 7e4,
-    };
-
-    const tx = new bitcoin.Psbt()
-      .addInputs([inputData, inputData2])
-      .addOutputs([outputData, outputData2])
-      .signAllInputs(keyPair)
-      .finalizeAllInputs()
-      .extractTransaction();
-
-    // build and broadcast to the Bitcoin RegTest network
-    await regtestUtils.broadcast(tx.toHex());
-
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: p2sh.payment.address,
-      vout: 0,
-      value: 2e4,
-    });
-  });
-
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WPKH) input with nonWitnessUtxo', async () => {
-    // For learning purposes, ignore this test.
-    // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
-    const p2sh = createPayment('p2sh-p2wpkh');
-    const inputData = await getInputData(5e4, p2sh.payment, false, 'p2sh');
-    const inputData2 = await getInputData(5e4, p2sh.payment, false, 'p2sh');
-    const keyPair = p2sh.keys[0];
-    const outputData = {
-      script: p2sh.payment.output,
-      value: 2e4,
-    };
-    const outputData2 = {
-      script: p2sh.payment.output,
-      value: 7e4,
-    };
-    const tx = new bitcoin.Psbt()
-      .addInputs([inputData, inputData2])
-      .addOutputs([outputData, outputData2])
-      .signAllInputs(keyPair)
-      .finalizeAllInputs()
-      .extractTransaction();
-    await regtestUtils.broadcast(tx.toHex());
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: p2sh.payment.address,
-      vout: 0,
-      value: 2e4,
-    });
-  });
-
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input', async () => {
-    // the only thing that changes is you don't give a redeemscript for input data
-
-    const p2wpkh = createPayment('p2wpkh');
-    const inputData = await getInputData(5e4, p2wpkh.payment, true, 'noredeem');
-    {
-      const { hash, index, witnessUtxo } = inputData;
-      assert.deepStrictEqual({ hash, index, witnessUtxo }, inputData);
-    }
-
-    const psbt = new bitcoin.Psbt({ network: regtest })
-      .addInput(inputData)
-      .addOutput({
-        address: regtestUtils.RANDOM_ADDRESS,
-        value: 2e4,
-      })
-      .signInput(0, p2wpkh.keys[0]);
-
-    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
-    psbt.finalizeAllInputs();
-
-    const tx = psbt.extractTransaction();
-
-    // build and broadcast to the Bitcoin RegTest network
-    await regtestUtils.broadcast(tx.toHex());
-
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 2e4,
-    });
-  });
-
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input with nonWitnessUtxo', async () => {
-    // For learning purposes, ignore this test.
-    // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
-    const p2wpkh = createPayment('p2wpkh');
-    const inputData = await getInputData(
-      5e4,
-      p2wpkh.payment,
-      false,
-      'noredeem',
-    );
-    const psbt = new bitcoin.Psbt({ network: regtest })
-      .addInput(inputData)
-      .addOutput({
-        address: regtestUtils.RANDOM_ADDRESS,
-        value: 2e4,
-      })
-      .signInput(0, p2wpkh.keys[0]);
-    psbt.finalizeAllInputs();
-    const tx = psbt.extractTransaction();
-    await regtestUtils.broadcast(tx.toHex());
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 2e4,
-    });
-  });
-
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WSH(P2PK) input', async () => {
-    const p2wsh = createPayment('p2wsh-p2pk');
-    const inputData = await getInputData(5e4, p2wsh.payment, true, 'p2wsh');
-    {
-      const {
-        hash,
-        index,
-        witnessUtxo,
-        witnessScript, // NEW: A Buffer of the witnessScript
-      } = inputData;
-      assert.deepStrictEqual(
-        { hash, index, witnessUtxo, witnessScript },
-        inputData,
-      );
-    }
-
-    const psbt = new bitcoin.Psbt({ network: regtest })
-      .addInput(inputData)
-      .addOutput({
-        address: regtestUtils.RANDOM_ADDRESS,
-        value: 2e4,
-      })
-      .signInput(0, p2wsh.keys[0]);
-
-    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
-    psbt.finalizeAllInputs();
-
-    const tx = psbt.extractTransaction();
-
-    // build and broadcast to the Bitcoin RegTest network
-    await regtestUtils.broadcast(tx.toHex());
-
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 2e4,
-    });
-  });
-
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WSH(P2PK) input with nonWitnessUtxo', async () => {
-    // For learning purposes, ignore this test.
-    // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
-    const p2wsh = createPayment('p2wsh-p2pk');
-    const inputData = await getInputData(5e4, p2wsh.payment, false, 'p2wsh');
-    const psbt = new bitcoin.Psbt({ network: regtest })
-      .addInput(inputData)
-      .addOutput({
-        address: regtestUtils.RANDOM_ADDRESS,
-        value: 2e4,
-      })
-      .signInput(0, p2wsh.keys[0]);
-    psbt.finalizeAllInputs();
-    const tx = psbt.extractTransaction();
-    await regtestUtils.broadcast(tx.toHex());
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 2e4,
-    });
-  });
-
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input', async () => {
-    const p2sh = createPayment('p2sh-p2wsh-p2ms(3 of 4)');
-    const inputData = await getInputData(5e4, p2sh.payment, true, 'p2sh-p2wsh');
-    {
-      const {
-        hash,
-        index,
-        witnessUtxo,
-        redeemScript,
-        witnessScript,
-      } = inputData;
-      assert.deepStrictEqual(
-        { hash, index, witnessUtxo, redeemScript, witnessScript },
-        inputData,
-      );
-    }
-
-    const psbt = new bitcoin.Psbt({ network: regtest })
-      .addInput(inputData)
-      .addOutput({
-        address: regtestUtils.RANDOM_ADDRESS,
-        value: 2e4,
-      })
-      .signInput(0, p2sh.keys[0])
-      .signInput(0, p2sh.keys[2])
-      .signInput(0, p2sh.keys[3]);
-
-    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
-    assert.strictEqual(
-      psbt.validateSignaturesOfInput(0, p2sh.keys[3].publicKey),
-      true,
-    );
-    assert.throws(() => {
-      psbt.validateSignaturesOfInput(0, p2sh.keys[1].publicKey);
-    }, new RegExp('No signatures for this pubkey'));
-    psbt.finalizeAllInputs();
-
-    const tx = psbt.extractTransaction();
-
-    // build and broadcast to the Bitcoin RegTest network
-    await regtestUtils.broadcast(tx.toHex());
-
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 2e4,
-    });
-  });
-
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input with nonWitnessUtxo', async () => {
-    // For learning purposes, ignore this test.
-    // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
-    const p2sh = createPayment('p2sh-p2wsh-p2ms(3 of 4)');
-    const inputData = await getInputData(
-      5e4,
-      p2sh.payment,
-      false,
-      'p2sh-p2wsh',
-    );
-    const psbt = new bitcoin.Psbt({ network: regtest })
-      .addInput(inputData)
-      .addOutput({
-        address: regtestUtils.RANDOM_ADDRESS,
-        value: 2e4,
-      })
-      .signInput(0, p2sh.keys[0])
-      .signInput(0, p2sh.keys[2])
-      .signInput(0, p2sh.keys[3]);
-    psbt.finalizeAllInputs();
-    const tx = psbt.extractTransaction();
-    await regtestUtils.broadcast(tx.toHex());
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 2e4,
-    });
-  });
-
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input using HD', async () => {
-    const hdRoot = bip32.fromSeed(rng(64));
-    const masterFingerprint = hdRoot.fingerprint;
-    const path = "m/84'/0'/0'/0/0";
-    const childNode = hdRoot.derivePath(path);
-    const pubkey = childNode.publicKey;
-
-    // This information should be added to your input via updateInput
-    // You can add multiple bip32Derivation objects for multisig, but
-    // each must have a unique pubkey.
-    //
-    // This is useful because as long as you store the masterFingerprint on
-    // the PSBT Creator's server, you can have the PSBT Creator do the heavy
-    // lifting with derivation from your m/84'/0'/0' xpub, (deriving only 0/0 )
-    // and your signer just needs to pass in an HDSigner interface (ie. bip32 library)
-    const updateData = {
-      bip32Derivation: [
-        {
-          masterFingerprint,
-          path,
-          pubkey,
-        },
-      ],
-    };
-    const p2wpkh = createPayment('p2wpkh', [childNode]);
-    const inputData = await getInputData(5e4, p2wpkh.payment, true, 'noredeem');
-    {
-      const { hash, index, witnessUtxo } = inputData;
-      assert.deepStrictEqual({ hash, index, witnessUtxo }, inputData);
-    }
-
-    // You can add extra attributes for updateData into the addInput(s) object(s)
-    Object.assign(inputData, updateData);
-
-    const psbt = new bitcoin.Psbt({ network: regtest })
-      .addInput(inputData)
-      // .updateInput(0, updateData) // if you didn't merge the bip32Derivation with inputData
-      .addOutput({
-        address: regtestUtils.RANDOM_ADDRESS,
-        value: 2e4,
-      })
-      .signInputHD(0, hdRoot); // must sign with root!!!
-
-    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
-    assert.strictEqual(
-      psbt.validateSignaturesOfInput(0, childNode.publicKey),
-      true,
-    );
-    psbt.finalizeAllInputs();
-
-    const tx = psbt.extractTransaction();
-
-    // build and broadcast to the Bitcoin RegTest network
-    await regtestUtils.broadcast(tx.toHex());
-
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address: regtestUtils.RANDOM_ADDRESS,
-      vout: 0,
-      value: 2e4,
-    });
-  });
-});
-
-function createPayment(_type: string, myKeys?: any[], network?: any) {
-  network = network || regtest;
-  const splitType = _type.split('-').reverse();
-  const isMultisig = splitType[0].slice(0, 4) === 'p2ms';
-  const keys = myKeys || [];
-  let m: number | undefined;
-  if (isMultisig) {
-    const match = splitType[0].match(/^p2ms\((\d+) of (\d+)\)$/);
-    m = parseInt(match![1]);
-    let n = parseInt(match![2]);
-    if (keys.length > 0 && keys.length !== n) {
-      throw new Error('Need n keys for multisig');
-    }
-    while (!myKeys && n > 1) {
-      keys.push(bitcoin.ECPair.makeRandom({ network }));
-      n--;
-    }
-  }
-  if (!myKeys) keys.push(bitcoin.ECPair.makeRandom({ network }));
-
-  let payment: any;
-  splitType.forEach(type => {
-    if (type.slice(0, 4) === 'p2ms') {
-      payment = bitcoin.payments.p2ms({
-        m,
-        pubkeys: keys.map(key => key.publicKey).sort(),
-        network,
-      });
-    } else if (['p2sh', 'p2wsh'].indexOf(type) > -1) {
-      payment = (bitcoin.payments as any)[type]({
-        redeem: payment,
-        network,
-      });
-    } else {
-      payment = (bitcoin.payments as any)[type]({
-        pubkey: keys[0].publicKey,
-        network,
-      });
-    }
-  });
-
-  return {
-    payment,
-    keys,
-  };
-}
-
-function getWitnessUtxo(out: any) {
-  delete out.address;
-  out.script = Buffer.from(out.script, 'hex');
-  return out;
-}
-
-async function getInputData(
-  amount: number,
-  payment: any,
-  isSegwit: boolean,
-  redeemType: string,
-) {
-  const unspent = await regtestUtils.faucetComplex(payment.output, amount);
-  const utx = await regtestUtils.fetch(unspent.txId);
-  // for non segwit inputs, you must pass the full transaction buffer
-  const nonWitnessUtxo = Buffer.from(utx.txHex, 'hex');
-  // for segwit inputs, you only need the output script and value as an object.
-  const witnessUtxo = getWitnessUtxo(utx.outs[unspent.vout]);
-  const mixin = isSegwit ? { witnessUtxo } : { nonWitnessUtxo };
-  const mixin2: any = {};
-  switch (redeemType) {
-    case 'p2sh':
-      mixin2.redeemScript = payment.redeem.output;
-      break;
-    case 'p2wsh':
-      mixin2.witnessScript = payment.redeem.output;
-      break;
-    case 'p2sh-p2wsh':
-      mixin2.witnessScript = payment.redeem.redeem.output;
-      mixin2.redeemScript = payment.redeem.output;
-      break;
-  }
-  return {
-    hash: unspent.txId,
-    index: unspent.vout,
-    ...mixin,
-    ...mixin2,
-  };
-}
diff --git a/test/integration/transactions.spec.ts b/test/integration/transactions.spec.ts
index 8a313f2..2bcee3b 100644
--- a/test/integration/transactions.spec.ts
+++ b/test/integration/transactions.spec.ts
@@ -1,191 +1,231 @@
 import * as assert from 'assert';
+import * as bip32 from 'bip32';
 import { describe, it } from 'mocha';
 import * as bitcoin from '../..';
 import { regtestUtils } from './_regtest';
+const rng = require('randombytes');
 const regtest = regtestUtils.network;
-console.warn = () => {}; // Silence the Deprecation Warning
 
-function rng() {
-  return Buffer.from('YT8dAtK4d16A3P1z+TpwB2jJ4aFH3g9M1EioIBkLEV4=', 'base64');
-}
+// See bottom of file for some helper functions used to make the payment objects needed.
 
-describe('bitcoinjs-lib (transactions)', () => {
+describe('bitcoinjs-lib (transactions with psbt)', () => {
   it('can create a 1-to-1 Transaction', () => {
     const alice = bitcoin.ECPair.fromWIF(
-      'L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy',
+      'L2uPYXe17xSTqbCjZvL2DsyXPCbXspvcu5mHLDYUgzdUbZGSKrSr',
     );
-    const txb = new bitcoin.TransactionBuilder();
+    const psbt = new bitcoin.Psbt();
+    psbt.setVersion(2); // These are defaults. This line is not needed.
+    psbt.setLocktime(0); // These are defaults. This line is not needed.
+    psbt.addInput({
+      // if hash is string, txid, if hash is Buffer, is reversed compared to txid
+      hash: '7d067b4a697a09d2c3cff7d4d9506c9955e93bff41bf82d439da7d030382bc3e',
+      index: 0,
+      sequence: 0xffffffff, // These are defaults. This line is not needed.
 
-    txb.setVersion(1);
-    txb.addInput(
-      '61d520ccb74288c96bc1a2b20ea1c0d5a704776dd0164a396efec3ea7040349d',
-      0,
-    ); // Alice's previous transaction output, has 15000 satoshis
-    txb.addOutput('1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP', 12000);
-    // (in)15000 - (out)12000 = (fee)3000, this is the miner fee
+      // non-segwit inputs now require passing the whole previous tx as Buffer
+      nonWitnessUtxo: Buffer.from(
+        '0200000001f9f34e95b9d5c8abcd20fc5bd4a825d1517be62f0f775e5f36da944d9' +
+          '452e550000000006b483045022100c86e9a111afc90f64b4904bd609e9eaed80d48' +
+          'ca17c162b1aca0a788ac3526f002207bb79b60d4fc6526329bf18a77135dc566020' +
+          '9e761da46e1c2f1152ec013215801210211755115eabf846720f5cb18f248666fec' +
+          '631e5e1e66009ce3710ceea5b1ad13ffffffff01' +
+          // value in satoshis (Int64LE) = 0x015f90 = 90000
+          '905f010000000000' +
+          // scriptPubkey length
+          '19' +
+          // scriptPubkey
+          '76a9148bbc95d2709c71607c60ee3f097c1217482f518d88ac' +
+          // locktime
+          '00000000',
+        'hex',
+      ),
 
-    txb.sign({
-      prevOutScriptType: 'p2pkh',
-      vin: 0,
-      keyPair: alice,
+      // // If this input was segwit, instead of nonWitnessUtxo, you would add
+      // // a witnessUtxo as follows. The scriptPubkey and the value only are needed.
+      // witnessUtxo: {
+      //   script: Buffer.from(
+      //     '76a9148bbc95d2709c71607c60ee3f097c1217482f518d88ac',
+      //     'hex',
+      //   ),
+      //   value: 90000,
+      // },
+
+      // Not featured here:
+      //   redeemScript. A Buffer of the redeemScript for P2SH
+      //   witnessScript. A Buffer of the witnessScript for P2WSH
     });
-
-    // prepare for broadcast to the Bitcoin network, see "can broadcast a Transaction" below
+    psbt.addOutput({
+      address: '1KRMKfeZcmosxALVYESdPNez1AP1mEtywp',
+      value: 80000,
+    });
+    psbt.signInput(0, alice);
+    psbt.validateSignaturesOfInput(0);
+    psbt.finalizeAllInputs();
     assert.strictEqual(
-      txb.build().toHex(),
-      '01000000019d344070eac3fe6e394a16d06d7704a7d5c0a10eb2a2c16bc98842b7cc20d561000000006b48304502210088828c0bdfcdca68d8ae0caeb6ec62cd3fd5f9b2191848edae33feb533df35d302202e0beadd35e17e7f83a733f5277028a9b453d525553e3f5d2d7a7aa8010a81d60121029f50f51d63b345039a290c94bffd3180c99ed659ff6ea6b1242bca47eb93b59fffffffff01e02e0000000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac00000000',
-    );
-  });
-
-  it('can create a 2-to-2 Transaction', () => {
-    const alice = bitcoin.ECPair.fromWIF(
-      'L1Knwj9W3qK3qMKdTvmg3VfzUs3ij2LETTFhxza9LfD5dngnoLG1',
-    );
-    const bob = bitcoin.ECPair.fromWIF(
-      'KwcN2pT3wnRAurhy7qMczzbkpY5nXMW2ubh696UBc1bcwctTx26z',
-    );
-
-    const txb = new bitcoin.TransactionBuilder();
-    txb.setVersion(1);
-    txb.addInput(
-      'b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c',
-      6,
-    ); // Alice's previous transaction output, has 200000 satoshis
-    txb.addInput(
-      '7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730',
-      0,
-    ); // Bob's previous transaction output, has 300000 satoshis
-    txb.addOutput('1CUNEBjYrCn2y1SdiUMohaKUi4wpP326Lb', 180000);
-    txb.addOutput('1JtK9CQw1syfWj1WtFMWomrYdV3W2tWBF9', 170000);
-    // (in)(200000 + 300000) - (out)(180000 + 170000) = (fee)150000, this is the miner fee
-
-    txb.sign({
-      prevOutScriptType: 'p2pkh',
-      vin: 1,
-      keyPair: bob,
-    }); // Bob signs his input, which was the second input (1th)
-    txb.sign({
-      prevOutScriptType: 'p2pkh',
-      vin: 0,
-      keyPair: alice,
-    }); // Alice signs her input, which was the first input (0th)
-
-    // prepare for broadcast to the Bitcoin network, see "can broadcast a Transaction" below
-    assert.strictEqual(
-      txb.build().toHex(),
-      '01000000024c94e48a870b85f41228d33cf25213dfcc8dd796e7211ed6b1f9a014809dbbb5060000006a473044022041450c258ce7cac7da97316bf2ea1ce66d88967c4df94f3e91f4c2a30f5d08cb02203674d516e6bb2b0afd084c3551614bd9cec3c2945231245e891b145f2d6951f0012103e05ce435e462ec503143305feb6c00e06a3ad52fbf939e85c65f3a765bb7baacffffffff3077d9de049574c3af9bc9c09a7c9db80f2d94caaf63988c9166249b955e867d000000006b483045022100aeb5f1332c79c446d3f906e4499b2e678500580a3f90329edf1ba502eec9402e022072c8b863f8c8d6c26f4c691ac9a6610aa4200edc697306648ee844cfbc089d7a012103df7940ee7cddd2f97763f67e1fb13488da3fbdd7f9c68ec5ef0864074745a289ffffffff0220bf0200000000001976a9147dd65592d0ab2fe0d0257d571abf032cd9db93dc88ac10980200000000001976a914c42e7ef92fdb603af844d064faad95db9bcdfd3d88ac00000000',
+      psbt.extractTransaction().toHex(),
+      '02000000013ebc8203037dda39d482bf41ff3be955996c50d9d4f7cfc3d2097a694a7' +
+        'b067d000000006b483045022100931b6db94aed25d5486884d83fc37160f37f3368c0' +
+        'd7f48c757112abefec983802205fda64cff98c849577026eb2ce916a50ea70626a766' +
+        '9f8596dd89b720a26b4d501210365db9da3f8a260078a7e8f8b708a1161468fb2323f' +
+        'fda5ec16b261ec1056f455ffffffff0180380100000000001976a914ca0d36044e0dc' +
+        '08a22724efa6f6a07b0ec4c79aa88ac00000000',
     );
   });
 
   it('can create (and broadcast via 3PBP) a typical Transaction', async () => {
-    const alice1 = bitcoin.ECPair.makeRandom({ network: regtest });
-    const alice2 = bitcoin.ECPair.makeRandom({ network: regtest });
-    const aliceChange = bitcoin.ECPair.makeRandom({
-      network: regtest,
-      rng: rng,
-    });
-
-    const alice1pkh = bitcoin.payments.p2pkh({
-      pubkey: alice1.publicKey,
-      network: regtest,
-    });
-    const alice2pkh = bitcoin.payments.p2pkh({
-      pubkey: alice2.publicKey,
-      network: regtest,
-    });
-    const aliceCpkh = bitcoin.payments.p2pkh({
-      pubkey: aliceChange.publicKey,
-      network: regtest,
-    });
+    // these are { payment: Payment; keys: ECPair[] }
+    const alice1 = createPayment('p2pkh');
+    const alice2 = createPayment('p2pkh');
 
     // give Alice 2 unspent outputs
-    const unspent0 = await regtestUtils.faucet(alice1pkh.address!, 5e4);
+    const inputData1 = await getInputData(
+      5e4,
+      alice1.payment,
+      false,
+      'noredeem',
+    );
+    const inputData2 = await getInputData(
+      7e4,
+      alice2.payment,
+      false,
+      'noredeem',
+    );
+    {
+      const {
+        hash, // string of txid or Buffer of tx hash. (txid and hash are reverse order)
+        index, // the output index of the txo you are spending
+        nonWitnessUtxo, // the full previous transaction as a Buffer
+      } = inputData1;
+      assert.deepStrictEqual({ hash, index, nonWitnessUtxo }, inputData1);
+    }
 
-    const unspent1 = await regtestUtils.faucet(alice2pkh.address!, 7e4);
-
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.addInput(unspent0.txId, unspent0.vout); // alice1 unspent
-    txb.addInput(unspent1.txId, unspent1.vout); // alice2 unspent
-    txb.addOutput('mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf', 8e4); // the actual "spend"
-    txb.addOutput(aliceCpkh.address!, 1e4); // Alice's change
+    // network is only needed if you pass an address to addOutput
+    // using script (Buffer of scriptPubkey) instead will avoid needed network.
+    const psbt = new bitcoin.Psbt({ network: regtest })
+      .addInput(inputData1) // alice1 unspent
+      .addInput(inputData2) // alice2 unspent
+      .addOutput({
+        address: 'mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf',
+        value: 8e4,
+      }) // the actual "spend"
+      .addOutput({
+        address: alice2.payment.address, // OR script, which is a Buffer.
+        value: 1e4,
+      }); // Alice's change
     // (in)(5e4 + 7e4) - (out)(8e4 + 1e4) = (fee)3e4 = 30000, this is the miner fee
 
+    // Let's show a new feature with PSBT.
+    // We can have multiple signers sign in parrallel and combine them.
+    // (this is not necessary, but a nice feature)
+
+    // encode to send out to the signers
+    const psbtBaseText = psbt.toBase64();
+
+    // each signer imports
+    const signer1 = bitcoin.Psbt.fromBase64(psbtBaseText);
+    const signer2 = bitcoin.Psbt.fromBase64(psbtBaseText);
+
     // Alice signs each input with the respective private keys
-    txb.sign({
-      prevOutScriptType: 'p2pkh',
-      vin: 0,
-      keyPair: alice1,
-    });
-    txb.sign({
-      prevOutScriptType: 'p2pkh',
-      vin: 1,
-      keyPair: alice2,
-    });
+    // signInput and signInputAsync are better
+    // (They take the input index explicitly as the first arg)
+    signer1.signAllInputs(alice1.keys[0]);
+    signer2.signAllInputs(alice2.keys[0]);
+
+    // If your signer object's sign method returns a promise, use the following
+    // await signer2.signAllInputsAsync(alice2.keys[0])
+
+    // encode to send back to combiner (signer 1 and 2 are not near each other)
+    const s1text = signer1.toBase64();
+    const s2text = signer2.toBase64();
+
+    const final1 = bitcoin.Psbt.fromBase64(s1text);
+    const final2 = bitcoin.Psbt.fromBase64(s2text);
+
+    // final1.combine(final2) would give the exact same result
+    psbt.combine(final1, final2);
+
+    // Finalizer wants to check all signatures are valid before finalizing.
+    // If the finalizer wants to check for specific pubkeys, the second arg
+    // can be passed. See the first multisig example below.
+    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
+    assert.strictEqual(psbt.validateSignaturesOfInput(1), true);
+
+    // This step it new. Since we separate the signing operation and
+    // the creation of the scriptSig and witness stack, we are able to
+    psbt.finalizeAllInputs();
 
     // build and broadcast our RegTest network
-    await regtestUtils.broadcast(txb.build().toHex());
+    await regtestUtils.broadcast(psbt.extractTransaction().toHex());
     // to build and broadcast to the actual Bitcoin network, see https://github.com/bitcoinjs/bitcoinjs-lib/issues/839
   });
 
   it('can create (and broadcast via 3PBP) a Transaction with an OP_RETURN output', async () => {
-    const keyPair = bitcoin.ECPair.makeRandom({ network: regtest });
-    const p2pkh = bitcoin.payments.p2pkh({
-      pubkey: keyPair.publicKey,
-      network: regtest,
-    });
+    const alice1 = createPayment('p2pkh');
+    const inputData1 = await getInputData(
+      2e5,
+      alice1.payment,
+      false,
+      'noredeem',
+    );
 
-    const unspent = await regtestUtils.faucet(p2pkh.address!, 2e5);
-
-    const txb = new bitcoin.TransactionBuilder(regtest);
     const data = Buffer.from('bitcoinjs-lib', 'utf8');
     const embed = bitcoin.payments.embed({ data: [data] });
-    txb.addInput(unspent.txId, unspent.vout);
-    txb.addOutput(embed.output!, 1000);
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e5);
-    txb.sign({
-      prevOutScriptType: 'p2pkh',
-      vin: 0,
-      keyPair,
-    });
+
+    const psbt = new bitcoin.Psbt({ network: regtest })
+      .addInput(inputData1)
+      .addOutput({
+        script: embed.output!,
+        value: 1000,
+      })
+      .addOutput({
+        address: regtestUtils.RANDOM_ADDRESS,
+        value: 1e5,
+      })
+      .signInput(0, alice1.keys[0]);
+
+    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
+    psbt.finalizeAllInputs();
 
     // build and broadcast to the RegTest network
-    await regtestUtils.broadcast(txb.build().toHex());
+    await regtestUtils.broadcast(psbt.extractTransaction().toHex());
   });
 
   it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2MS(2 of 4)) (multisig) input', async () => {
-    const keyPairs = [
-      bitcoin.ECPair.makeRandom({ network: regtest }),
-      bitcoin.ECPair.makeRandom({ network: regtest }),
-      bitcoin.ECPair.makeRandom({ network: regtest }),
-      bitcoin.ECPair.makeRandom({ network: regtest }),
-    ];
-    const pubkeys = keyPairs.map(x => x.publicKey);
-    const p2ms = bitcoin.payments.p2ms({
-      m: 2,
-      pubkeys: pubkeys,
-      network: regtest,
-    });
-    const p2sh = bitcoin.payments.p2sh({ redeem: p2ms, network: regtest });
+    const multisig = createPayment('p2sh-p2ms(2 of 4)');
+    const inputData1 = await getInputData(2e4, multisig.payment, false, 'p2sh');
+    {
+      const {
+        hash,
+        index,
+        nonWitnessUtxo,
+        redeemScript, // NEW: P2SH needs to give redeemScript when adding an input.
+      } = inputData1;
+      assert.deepStrictEqual(
+        { hash, index, nonWitnessUtxo, redeemScript },
+        inputData1,
+      );
+    }
 
-    const unspent = await regtestUtils.faucet(p2sh.address!, 2e4);
+    const psbt = new bitcoin.Psbt({ network: regtest })
+      .addInput(inputData1)
+      .addOutput({
+        address: regtestUtils.RANDOM_ADDRESS,
+        value: 1e4,
+      })
+      .signInput(0, multisig.keys[0])
+      .signInput(0, multisig.keys[2]);
 
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.addInput(unspent.txId, unspent.vout);
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4);
+    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
+    assert.strictEqual(
+      psbt.validateSignaturesOfInput(0, multisig.keys[0].publicKey),
+      true,
+    );
+    assert.throws(() => {
+      psbt.validateSignaturesOfInput(0, multisig.keys[3].publicKey);
+    }, new RegExp('No signatures for this pubkey'));
+    psbt.finalizeAllInputs();
 
-    txb.sign({
-      prevOutScriptType: 'p2sh-p2ms',
-      vin: 0,
-      keyPair: keyPairs[0],
-      redeemScript: p2sh.redeem!.output,
-    });
-    txb.sign({
-      prevOutScriptType: 'p2sh-p2ms',
-      vin: 0,
-      keyPair: keyPairs[2],
-      redeemScript: p2sh.redeem!.output,
-    });
-    const tx = txb.build();
+    const tx = psbt.extractTransaction();
 
     // build and broadcast to the Bitcoin RegTest network
     await regtestUtils.broadcast(tx.toHex());
@@ -199,27 +239,101 @@ describe('bitcoinjs-lib (transactions)', () => {
   });
 
   it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WPKH) input', async () => {
-    const keyPair = bitcoin.ECPair.makeRandom({ network: regtest });
-    const p2wpkh = bitcoin.payments.p2wpkh({
-      pubkey: keyPair.publicKey,
-      network: regtest,
+    const p2sh = createPayment('p2sh-p2wpkh');
+    const inputData = await getInputData(5e4, p2sh.payment, true, 'p2sh');
+    const inputData2 = await getInputData(5e4, p2sh.payment, true, 'p2sh');
+    {
+      const {
+        hash,
+        index,
+        witnessUtxo, // NEW: this is an object of the output being spent { script: Buffer; value: Satoshis; }
+        redeemScript,
+      } = inputData;
+      assert.deepStrictEqual(
+        { hash, index, witnessUtxo, redeemScript },
+        inputData,
+      );
+    }
+    const keyPair = p2sh.keys[0];
+    const outputData = {
+      script: p2sh.payment.output, // sending to myself for fun
+      value: 2e4,
+    };
+    const outputData2 = {
+      script: p2sh.payment.output, // sending to myself for fun
+      value: 7e4,
+    };
+
+    const tx = new bitcoin.Psbt()
+      .addInputs([inputData, inputData2])
+      .addOutputs([outputData, outputData2])
+      .signAllInputs(keyPair)
+      .finalizeAllInputs()
+      .extractTransaction();
+
+    // build and broadcast to the Bitcoin RegTest network
+    await regtestUtils.broadcast(tx.toHex());
+
+    await regtestUtils.verify({
+      txId: tx.getId(),
+      address: p2sh.payment.address,
+      vout: 0,
+      value: 2e4,
     });
-    const p2sh = bitcoin.payments.p2sh({ redeem: p2wpkh, network: regtest });
+  });
 
-    const unspent = await regtestUtils.faucet(p2sh.address!, 5e4);
-
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.addInput(unspent.txId, unspent.vout);
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4);
-    txb.sign({
-      prevOutScriptType: 'p2sh-p2wpkh',
-      vin: 0,
-      keyPair: keyPair,
-      redeemScript: p2sh.redeem!.output,
-      witnessValue: unspent.value,
+  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WPKH) input with nonWitnessUtxo', async () => {
+    // For learning purposes, ignore this test.
+    // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
+    const p2sh = createPayment('p2sh-p2wpkh');
+    const inputData = await getInputData(5e4, p2sh.payment, false, 'p2sh');
+    const inputData2 = await getInputData(5e4, p2sh.payment, false, 'p2sh');
+    const keyPair = p2sh.keys[0];
+    const outputData = {
+      script: p2sh.payment.output,
+      value: 2e4,
+    };
+    const outputData2 = {
+      script: p2sh.payment.output,
+      value: 7e4,
+    };
+    const tx = new bitcoin.Psbt()
+      .addInputs([inputData, inputData2])
+      .addOutputs([outputData, outputData2])
+      .signAllInputs(keyPair)
+      .finalizeAllInputs()
+      .extractTransaction();
+    await regtestUtils.broadcast(tx.toHex());
+    await regtestUtils.verify({
+      txId: tx.getId(),
+      address: p2sh.payment.address,
+      vout: 0,
+      value: 2e4,
     });
+  });
 
-    const tx = txb.build();
+  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input', async () => {
+    // the only thing that changes is you don't give a redeemscript for input data
+
+    const p2wpkh = createPayment('p2wpkh');
+    const inputData = await getInputData(5e4, p2wpkh.payment, true, 'noredeem');
+    {
+      const { hash, index, witnessUtxo } = inputData;
+      assert.deepStrictEqual({ hash, index, witnessUtxo }, inputData);
+    }
+
+    const psbt = new bitcoin.Psbt({ network: regtest })
+      .addInput(inputData)
+      .addOutput({
+        address: regtestUtils.RANDOM_ADDRESS,
+        value: 2e4,
+      })
+      .signInput(0, p2wpkh.keys[0]);
+
+    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
+    psbt.finalizeAllInputs();
+
+    const tx = psbt.extractTransaction();
 
     // build and broadcast to the Bitcoin RegTest network
     await regtestUtils.broadcast(tx.toHex());
@@ -232,30 +346,26 @@ describe('bitcoinjs-lib (transactions)', () => {
     });
   });
 
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input', async () => {
-    const keyPair = bitcoin.ECPair.makeRandom({ network: regtest });
-    const p2wpkh = bitcoin.payments.p2wpkh({
-      pubkey: keyPair.publicKey,
-      network: regtest,
-    });
-
-    const unspent = await regtestUtils.faucetComplex(p2wpkh.output!, 5e4);
-
-    // XXX: build the Transaction w/ a P2WPKH input
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.addInput(unspent.txId, unspent.vout, undefined, p2wpkh.output); // NOTE: provide the prevOutScript!
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4);
-    txb.sign({
-      prevOutScriptType: 'p2wpkh',
-      vin: 0,
-      keyPair: keyPair,
-      witnessValue: unspent.value,
-    }); // NOTE: no redeem script
-    const tx = txb.build();
-
-    // build and broadcast (the P2WPKH transaction) to the Bitcoin RegTest network
+  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input with nonWitnessUtxo', async () => {
+    // For learning purposes, ignore this test.
+    // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
+    const p2wpkh = createPayment('p2wpkh');
+    const inputData = await getInputData(
+      5e4,
+      p2wpkh.payment,
+      false,
+      'noredeem',
+    );
+    const psbt = new bitcoin.Psbt({ network: regtest })
+      .addInput(inputData)
+      .addOutput({
+        address: regtestUtils.RANDOM_ADDRESS,
+        value: 2e4,
+      })
+      .signInput(0, p2wpkh.keys[0]);
+    psbt.finalizeAllInputs();
+    const tx = psbt.extractTransaction();
     await regtestUtils.broadcast(tx.toHex());
-
     await regtestUtils.verify({
       txId: tx.getId(),
       address: regtestUtils.RANDOM_ADDRESS,
@@ -265,29 +375,35 @@ describe('bitcoinjs-lib (transactions)', () => {
   });
 
   it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WSH(P2PK) input', async () => {
-    const keyPair = bitcoin.ECPair.makeRandom({ network: regtest });
-    const p2pk = bitcoin.payments.p2pk({
-      pubkey: keyPair.publicKey,
-      network: regtest,
-    });
-    const p2wsh = bitcoin.payments.p2wsh({ redeem: p2pk, network: regtest });
+    const p2wsh = createPayment('p2wsh-p2pk');
+    const inputData = await getInputData(5e4, p2wsh.payment, true, 'p2wsh');
+    {
+      const {
+        hash,
+        index,
+        witnessUtxo,
+        witnessScript, // NEW: A Buffer of the witnessScript
+      } = inputData;
+      assert.deepStrictEqual(
+        { hash, index, witnessUtxo, witnessScript },
+        inputData,
+      );
+    }
 
-    const unspent = await regtestUtils.faucetComplex(p2wsh.output!, 5e4);
+    const psbt = new bitcoin.Psbt({ network: regtest })
+      .addInput(inputData)
+      .addOutput({
+        address: regtestUtils.RANDOM_ADDRESS,
+        value: 2e4,
+      })
+      .signInput(0, p2wsh.keys[0]);
 
-    // XXX: build the Transaction w/ a P2WSH input
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.addInput(unspent.txId, unspent.vout, undefined, p2wsh.output); // NOTE: provide the prevOutScript!
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4);
-    txb.sign({
-      prevOutScriptType: 'p2wsh-p2pk',
-      vin: 0,
-      keyPair: keyPair,
-      witnessValue: 5e4,
-      witnessScript: p2wsh.redeem!.output,
-    }); // NOTE: provide a witnessScript!
-    const tx = txb.build();
+    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
+    psbt.finalizeAllInputs();
 
-    // build and broadcast (the P2WSH transaction) to the Bitcoin RegTest network
+    const tx = psbt.extractTransaction();
+
+    // build and broadcast to the Bitcoin RegTest network
     await regtestUtils.broadcast(tx.toHex());
 
     await regtestUtils.verify({
@@ -298,50 +414,173 @@ describe('bitcoinjs-lib (transactions)', () => {
     });
   });
 
-  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input', async () => {
-    const keyPairs = [
-      bitcoin.ECPair.makeRandom({ network: regtest }),
-      bitcoin.ECPair.makeRandom({ network: regtest }),
-      bitcoin.ECPair.makeRandom({ network: regtest }),
-      bitcoin.ECPair.makeRandom({ network: regtest }),
-    ];
-    const pubkeys = keyPairs.map(x => x.publicKey);
-
-    const p2ms = bitcoin.payments.p2ms({ m: 3, pubkeys, network: regtest });
-    const p2wsh = bitcoin.payments.p2wsh({ redeem: p2ms, network: regtest });
-    const p2sh = bitcoin.payments.p2sh({ redeem: p2wsh, network: regtest });
-
-    const unspent = await regtestUtils.faucet(p2sh.address!, 6e4);
-
-    const txb = new bitcoin.TransactionBuilder(regtest);
-    txb.addInput(unspent.txId, unspent.vout, undefined, p2sh.output);
-    txb.addOutput(regtestUtils.RANDOM_ADDRESS, 3e4);
-    txb.sign({
-      prevOutScriptType: 'p2sh-p2wsh-p2ms',
-      vin: 0,
-      keyPair: keyPairs[0],
-      redeemScript: p2sh.redeem!.output,
-      witnessValue: unspent.value,
-      witnessScript: p2wsh.redeem!.output,
-    });
-    txb.sign({
-      prevOutScriptType: 'p2sh-p2wsh-p2ms',
-      vin: 0,
-      keyPair: keyPairs[2],
-      redeemScript: p2sh.redeem!.output,
-      witnessValue: unspent.value,
-      witnessScript: p2wsh.redeem!.output,
-    });
-    txb.sign({
-      prevOutScriptType: 'p2sh-p2wsh-p2ms',
-      vin: 0,
-      keyPair: keyPairs[3],
-      redeemScript: p2sh.redeem!.output,
-      witnessValue: unspent.value,
-      witnessScript: p2wsh.redeem!.output,
+  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WSH(P2PK) input with nonWitnessUtxo', async () => {
+    // For learning purposes, ignore this test.
+    // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
+    const p2wsh = createPayment('p2wsh-p2pk');
+    const inputData = await getInputData(5e4, p2wsh.payment, false, 'p2wsh');
+    const psbt = new bitcoin.Psbt({ network: regtest })
+      .addInput(inputData)
+      .addOutput({
+        address: regtestUtils.RANDOM_ADDRESS,
+        value: 2e4,
+      })
+      .signInput(0, p2wsh.keys[0]);
+    psbt.finalizeAllInputs();
+    const tx = psbt.extractTransaction();
+    await regtestUtils.broadcast(tx.toHex());
+    await regtestUtils.verify({
+      txId: tx.getId(),
+      address: regtestUtils.RANDOM_ADDRESS,
+      vout: 0,
+      value: 2e4,
     });
+  });
 
-    const tx = txb.build();
+  it(
+    'can create (and broadcast via 3PBP) a Transaction, w/ a ' +
+      'P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input',
+    async () => {
+      const p2sh = createPayment('p2sh-p2wsh-p2ms(3 of 4)');
+      const inputData = await getInputData(
+        5e4,
+        p2sh.payment,
+        true,
+        'p2sh-p2wsh',
+      );
+      {
+        const {
+          hash,
+          index,
+          witnessUtxo,
+          redeemScript,
+          witnessScript,
+        } = inputData;
+        assert.deepStrictEqual(
+          { hash, index, witnessUtxo, redeemScript, witnessScript },
+          inputData,
+        );
+      }
+
+      const psbt = new bitcoin.Psbt({ network: regtest })
+        .addInput(inputData)
+        .addOutput({
+          address: regtestUtils.RANDOM_ADDRESS,
+          value: 2e4,
+        })
+        .signInput(0, p2sh.keys[0])
+        .signInput(0, p2sh.keys[2])
+        .signInput(0, p2sh.keys[3]);
+
+      assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
+      assert.strictEqual(
+        psbt.validateSignaturesOfInput(0, p2sh.keys[3].publicKey),
+        true,
+      );
+      assert.throws(() => {
+        psbt.validateSignaturesOfInput(0, p2sh.keys[1].publicKey);
+      }, new RegExp('No signatures for this pubkey'));
+      psbt.finalizeAllInputs();
+
+      const tx = psbt.extractTransaction();
+
+      // build and broadcast to the Bitcoin RegTest network
+      await regtestUtils.broadcast(tx.toHex());
+
+      await regtestUtils.verify({
+        txId: tx.getId(),
+        address: regtestUtils.RANDOM_ADDRESS,
+        vout: 0,
+        value: 2e4,
+      });
+    },
+  );
+
+  it(
+    'can create (and broadcast via 3PBP) a Transaction, w/ a ' +
+      'P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input with nonWitnessUtxo',
+    async () => {
+      // For learning purposes, ignore this test.
+      // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
+      const p2sh = createPayment('p2sh-p2wsh-p2ms(3 of 4)');
+      const inputData = await getInputData(
+        5e4,
+        p2sh.payment,
+        false,
+        'p2sh-p2wsh',
+      );
+      const psbt = new bitcoin.Psbt({ network: regtest })
+        .addInput(inputData)
+        .addOutput({
+          address: regtestUtils.RANDOM_ADDRESS,
+          value: 2e4,
+        })
+        .signInput(0, p2sh.keys[0])
+        .signInput(0, p2sh.keys[2])
+        .signInput(0, p2sh.keys[3]);
+      psbt.finalizeAllInputs();
+      const tx = psbt.extractTransaction();
+      await regtestUtils.broadcast(tx.toHex());
+      await regtestUtils.verify({
+        txId: tx.getId(),
+        address: regtestUtils.RANDOM_ADDRESS,
+        vout: 0,
+        value: 2e4,
+      });
+    },
+  );
+
+  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input using HD', async () => {
+    const hdRoot = bip32.fromSeed(rng(64));
+    const masterFingerprint = hdRoot.fingerprint;
+    const path = "m/84'/0'/0'/0/0";
+    const childNode = hdRoot.derivePath(path);
+    const pubkey = childNode.publicKey;
+
+    // This information should be added to your input via updateInput
+    // You can add multiple bip32Derivation objects for multisig, but
+    // each must have a unique pubkey.
+    //
+    // This is useful because as long as you store the masterFingerprint on
+    // the PSBT Creator's server, you can have the PSBT Creator do the heavy
+    // lifting with derivation from your m/84'/0'/0' xpub, (deriving only 0/0 )
+    // and your signer just needs to pass in an HDSigner interface (ie. bip32 library)
+    const updateData = {
+      bip32Derivation: [
+        {
+          masterFingerprint,
+          path,
+          pubkey,
+        },
+      ],
+    };
+    const p2wpkh = createPayment('p2wpkh', [childNode]);
+    const inputData = await getInputData(5e4, p2wpkh.payment, true, 'noredeem');
+    {
+      const { hash, index, witnessUtxo } = inputData;
+      assert.deepStrictEqual({ hash, index, witnessUtxo }, inputData);
+    }
+
+    // You can add extra attributes for updateData into the addInput(s) object(s)
+    Object.assign(inputData, updateData);
+
+    const psbt = new bitcoin.Psbt({ network: regtest })
+      .addInput(inputData)
+      // .updateInput(0, updateData) // if you didn't merge the bip32Derivation with inputData
+      .addOutput({
+        address: regtestUtils.RANDOM_ADDRESS,
+        value: 2e4,
+      })
+      .signInputHD(0, hdRoot); // must sign with root!!!
+
+    assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
+    assert.strictEqual(
+      psbt.validateSignaturesOfInput(0, childNode.publicKey),
+      true,
+    );
+    psbt.finalizeAllInputs();
+
+    const tx = psbt.extractTransaction();
 
     // build and broadcast to the Bitcoin RegTest network
     await regtestUtils.broadcast(tx.toHex());
@@ -350,72 +589,94 @@ describe('bitcoinjs-lib (transactions)', () => {
       txId: tx.getId(),
       address: regtestUtils.RANDOM_ADDRESS,
       vout: 0,
-      value: 3e4,
-    });
-  });
-
-  it('can verify Transaction (P2PKH) signatures', () => {
-    const txHex =
-      '010000000321c5f7e7bc98b3feda84aad36a5c99a02bcb8823a2f3eccbcd5da209698b5c20000000006b48304502210099e021772830207cf7c55b69948d3b16b4dcbf1f55a9cd80ebf8221a169735f9022064d33f11d62cd28240b3862afc0b901adc9f231c7124dd19bdb30367b61964c50121032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63dffffffff8a75ce85441ddb3f342708ee33cc8ed418b07d9ba9e0e7c4e1cccfe9f52d8a88000000006946304302207916c23dae212c95a920423902fa44e939fb3d542f4478a7b46e9cde53705800021f0d74e9504146e404c1b8f9cba4dff2d4782e3075491c9ed07ce4a7d1c4461a01210216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2affffffffdfef93f69fe32e944fad79fa8f882b3a155d80383252348caba1a77a5abbf7ef000000006b483045022100faa6e9ca289b46c64764a624c59ac30d9abcf1d4a04c4de9089e67cbe0d300a502206930afa683f6807502de5c2431bf9a1fd333c8a2910a76304df0f3d23d83443f0121039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18fffffffff01ff4b0000000000001976a9146c86476d1d85cd60116cd122a274e6a570a5a35c88acc96d0700';
-    const keyPairs = [
-      '032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63d',
-      '0216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2a',
-      '039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18f',
-    ].map(q => {
-      return bitcoin.ECPair.fromPublicKey(Buffer.from(q, 'hex'));
-    });
-
-    const tx = bitcoin.Transaction.fromHex(txHex);
-
-    tx.ins.forEach((input, i) => {
-      const keyPair = keyPairs[i];
-      const p2pkh = bitcoin.payments.p2pkh({
-        pubkey: keyPair.publicKey,
-        input: input.script,
-      });
-
-      const ss = bitcoin.script.signature.decode(p2pkh.signature!);
-      const hash = tx.hashForSignature(i, p2pkh.output!, ss.hashType);
-
-      assert.strictEqual(keyPair.verify(hash, ss.signature), true);
-    });
-  });
-
-  it('can verify Transaction (P2SH(P2WPKH)) signatures', () => {
-    const utxos = {
-      'f72d1d83ac40fcedd01415751556a905844ab5f44bbb7728565ebb91b1590109:0': {
-        value: 50000,
-      },
-    };
-
-    const txHex =
-      '02000000000101090159b191bb5e562877bb4bf4b54a8405a95615751514d0edfc40ac831d2df7000000001716001435a179e5516947a39ae9c8a25e9fe62c0fc598edffffffff01204e0000000000001976a91431d43308d3c886d53e9ae8a45728370571ff456988ac0247304402206ec41f685b997a51f325b07ee852e82a535f6b52ef54485cc133e05168aa052a022070bafa86108acb51c77b2b259ae8fb7fd1efa10fef804fcfe9b13c2db719acf5012103fb03e9d0a9af86cbed94225dbb8bb70f6b82109bce0a61ddcf41dab6cbb4871100000000';
-    const tx = bitcoin.Transaction.fromHex(txHex);
-
-    tx.ins.forEach((input, i) => {
-      const txId = (Buffer.from(input.hash).reverse() as Buffer).toString(
-        'hex',
-      );
-      const utxo = (utxos as any)[`${txId}:${i}`];
-      if (!utxo) throw new Error('Missing utxo');
-
-      const p2sh = bitcoin.payments.p2sh({
-        input: input.script,
-        witness: input.witness,
-      });
-      const p2wpkh = bitcoin.payments.p2wpkh(p2sh.redeem!);
-      const p2pkh = bitcoin.payments.p2pkh({ pubkey: p2wpkh.pubkey }); // because P2WPKH is annoying
-
-      const ss = bitcoin.script.signature.decode(p2wpkh.signature!);
-      const hash = tx.hashForWitnessV0(
-        i,
-        p2pkh.output!,
-        utxo.value,
-        ss.hashType,
-      );
-      const keyPair = bitcoin.ECPair.fromPublicKey(p2wpkh.pubkey!); // aka, cQ3EtF4mApRcogNGSeyPTKbmfxxn3Yfb1wecfKSws9a8bnYuxoAk
-
-      assert.strictEqual(keyPair.verify(hash, ss.signature), true);
+      value: 2e4,
     });
   });
 });
+
+function createPayment(_type: string, myKeys?: any[], network?: any): any {
+  network = network || regtest;
+  const splitType = _type.split('-').reverse();
+  const isMultisig = splitType[0].slice(0, 4) === 'p2ms';
+  const keys = myKeys || [];
+  let m: number | undefined;
+  if (isMultisig) {
+    const match = splitType[0].match(/^p2ms\((\d+) of (\d+)\)$/);
+    m = parseInt(match![1], 10);
+    let n = parseInt(match![2], 10);
+    if (keys.length > 0 && keys.length !== n) {
+      throw new Error('Need n keys for multisig');
+    }
+    while (!myKeys && n > 1) {
+      keys.push(bitcoin.ECPair.makeRandom({ network }));
+      n--;
+    }
+  }
+  if (!myKeys) keys.push(bitcoin.ECPair.makeRandom({ network }));
+
+  let payment: any;
+  splitType.forEach(type => {
+    if (type.slice(0, 4) === 'p2ms') {
+      payment = bitcoin.payments.p2ms({
+        m,
+        pubkeys: keys.map(key => key.publicKey).sort(),
+        network,
+      });
+    } else if (['p2sh', 'p2wsh'].indexOf(type) > -1) {
+      payment = (bitcoin.payments as any)[type]({
+        redeem: payment,
+        network,
+      });
+    } else {
+      payment = (bitcoin.payments as any)[type]({
+        pubkey: keys[0].publicKey,
+        network,
+      });
+    }
+  });
+
+  return {
+    payment,
+    keys,
+  };
+}
+
+function getWitnessUtxo(out: any): any {
+  delete out.address;
+  out.script = Buffer.from(out.script, 'hex');
+  return out;
+}
+
+async function getInputData(
+  amount: number,
+  payment: any,
+  isSegwit: boolean,
+  redeemType: string,
+): Promise<any> {
+  const unspent = await regtestUtils.faucetComplex(payment.output, amount);
+  const utx = await regtestUtils.fetch(unspent.txId);
+  // for non segwit inputs, you must pass the full transaction buffer
+  const nonWitnessUtxo = Buffer.from(utx.txHex, 'hex');
+  // for segwit inputs, you only need the output script and value as an object.
+  const witnessUtxo = getWitnessUtxo(utx.outs[unspent.vout]);
+  const mixin = isSegwit ? { witnessUtxo } : { nonWitnessUtxo };
+  const mixin2: any = {};
+  switch (redeemType) {
+    case 'p2sh':
+      mixin2.redeemScript = payment.redeem.output;
+      break;
+    case 'p2wsh':
+      mixin2.witnessScript = payment.redeem.output;
+      break;
+    case 'p2sh-p2wsh':
+      mixin2.witnessScript = payment.redeem.redeem.output;
+      mixin2.redeemScript = payment.redeem.output;
+      break;
+  }
+  return {
+    hash: unspent.txId,
+    index: unspent.vout,
+    ...mixin,
+    ...mixin2,
+  };
+}
diff --git a/test/payments.spec.ts b/test/payments.spec.ts
index 051cc04..bc123cb 100644
--- a/test/payments.spec.ts
+++ b/test/payments.spec.ts
@@ -1,11 +1,11 @@
 import * as assert from 'assert';
 import { describe, it } from 'mocha';
-import * as u from './payments.utils';
 import { PaymentCreator } from '../src/payments';
+import * as u from './payments.utils';
 ['embed', 'p2ms', 'p2pk', 'p2pkh', 'p2sh', 'p2wpkh', 'p2wsh'].forEach(p => {
   describe(p, () => {
     let fn: PaymentCreator;
-    let payment = require('../src/payments/' + p);
+    const payment = require('../src/payments/' + p);
     if (p === 'embed') {
       fn = payment.p2data;
     } else {
@@ -83,7 +83,7 @@ import { PaymentCreator } from '../src/payments';
           disabled[k] = true;
         });
 
-      for (let key in depends) {
+      for (const key in depends) {
         if (key in disabled) continue;
         const dependencies = depends[key];
 
diff --git a/test/payments.utils.ts b/test/payments.utils.ts
index bcf79c7..3f0ce23 100644
--- a/test/payments.utils.ts
+++ b/test/payments.utils.ts
@@ -1,6 +1,6 @@
 import * as t from 'assert';
-import * as bscript from '../src/script';
 import * as BNETWORKS from '../src/networks';
+import * as bscript from '../src/script';
 
 function tryHex(x: Buffer | Buffer[]): string | string[] {
   if (Buffer.isBuffer(x)) return x.toString('hex');
@@ -17,12 +17,13 @@ function tryASM(x: Buffer): string {
   if (Buffer.isBuffer(x)) return bscript.toASM(x);
   return x;
 }
-function asmToBuffer(x: string) {
+function asmToBuffer(x: string): Buffer {
   if (x === '') return Buffer.alloc(0);
   return bscript.fromASM(x);
 }
-function carryOver(a: any, b: any) {
-  for (let k in b) {
+function carryOver(a: any, b: any): void {
+  for (const k in b) {
+    if (!k) continue;
     if (k in a && k === 'redeem') {
       carryOver(a[k], b[k]);
       continue;
@@ -36,7 +37,7 @@ function carryOver(a: any, b: any) {
   }
 }
 
-function equateBase(a: any, b: any, context: string) {
+function equateBase(a: any, b: any, context: string): void {
   if ('output' in b)
     t.strictEqual(
       tryASM(a.output),
@@ -53,7 +54,7 @@ function equateBase(a: any, b: any, context: string) {
     );
 }
 
-export function equate(a: any, b: any, args?: any) {
+export function equate(a: any, b: any, args?: any): void {
   b = Object.assign({}, b);
   carryOver(b, args);
 
@@ -108,7 +109,7 @@ export function equate(a: any, b: any, args?: any) {
     t.deepStrictEqual(tryHex(a.data), tryHex(b.data), 'Inequal *.data');
 }
 
-export function preform(x: any) {
+export function preform(x: any): any {
   x = Object.assign({}, x);
 
   if (x.network) x.network = (BNETWORKS as any)[x.network];
@@ -148,7 +149,7 @@ export function preform(x: any) {
   return x;
 }
 
-export function from(path: string, object: any, result?: any) {
+export function from(path: string, object: any, result?: any): any {
   const paths = path.split('.');
   result = result || {};
 
diff --git a/test/psbt.spec.ts b/test/psbt.spec.ts
index 02a420d..4eb32dc 100644
--- a/test/psbt.spec.ts
+++ b/test/psbt.spec.ts
@@ -14,12 +14,12 @@ const initBuffers = (object: any): typeof preFixtures =>
     const data = result[1];
     const encoding = result[2];
 
-    return Buffer.from(data, encoding);
+    return Buffer.from(data, encoding as BufferEncoding);
   });
 
 const fixtures = initBuffers(preFixtures);
 
-const upperCaseFirstLetter = (str: string) =>
+const upperCaseFirstLetter = (str: string): string =>
   str.replace(/^./, s => s.toUpperCase());
 
 // const b = (hex: string) => Buffer.from(hex, 'hex');
@@ -662,7 +662,7 @@ describe(`Psbt`, () => {
       const psbt = Psbt.fromBuffer(
         Buffer.from(
           '70736274ff01000a01000000000000000000000000',
-          'hex', //cHNidP8BAAoBAAAAAAAAAAAAAAAA
+          'hex', // cHNidP8BAAoBAAAAAAAAAAAAAAAA
         ),
       );
       assert.strictEqual(psbt instanceof Psbt, true);
diff --git a/test/script.spec.ts b/test/script.spec.ts
index 23da986..95a339d 100644
--- a/test/script.spec.ts
+++ b/test/script.spec.ts
@@ -12,7 +12,7 @@ describe('script', () => {
       assert.strictEqual(false, bscript.isCanonicalPubKey(0 as any));
     });
     it('rejects smaller than 33', () => {
-      for (var i = 0; i < 33; i++) {
+      for (let i = 0; i < 33; i++) {
         assert.strictEqual(
           false,
           bscript.isCanonicalPubKey(Buffer.allocUnsafe(i)),
@@ -20,7 +20,9 @@ describe('script', () => {
       }
     });
   });
-  describe.skip('isCanonicalScriptSignature', () => {});
+  describe.skip('isCanonicalScriptSignature', () => {
+    assert.ok(true);
+  });
 
   describe('fromASM/toASM', () => {
     fixtures.valid.forEach(f => {
@@ -157,19 +159,19 @@ describe('script', () => {
       });
     });
 
-    function testEncodingForSize(i: number) {
-      it('compliant for data PUSH of length ' + i, () => {
-        const buffer = Buffer.alloc(i);
+    function testEncodingForSize(num: number): void {
+      it('compliant for data PUSH of length ' + num, () => {
+        const buffer = Buffer.alloc(num);
         const script = bscript.compile([buffer]);
 
         assert(
           minimalData(script),
-          'Failed for ' + i + ' length script: ' + script.toString('hex'),
+          'Failed for ' + num + ' length script: ' + script.toString('hex'),
         );
       });
     }
 
-    for (var i = 0; i < 520; ++i) {
+    for (let i = 0; i < 520; ++i) {
       testEncodingForSize(i);
     }
   });
diff --git a/test/script_signature.spec.ts b/test/script_signature.spec.ts
index 3be52ad..54c416e 100644
--- a/test/script_signature.spec.ts
+++ b/test/script_signature.spec.ts
@@ -4,14 +4,19 @@ import { signature as bscriptSig } from '../src/script';
 import * as fixtures from './fixtures/signature.json';
 
 describe('Script Signatures', () => {
-  function fromRaw(signature: { r: string; s: string }) {
+  function fromRaw(signature: { r: string; s: string }): Buffer {
     return Buffer.concat(
       [Buffer.from(signature.r, 'hex'), Buffer.from(signature.s, 'hex')],
       64,
     );
   }
 
-  function toRaw(signature: Buffer) {
+  function toRaw(
+    signature: Buffer,
+  ): {
+    r: string;
+    s: string;
+  } {
     return {
       r: signature.slice(0, 32).toString('hex'),
       s: signature.slice(32, 64).toString('hex'),
diff --git a/test/transaction.spec.ts b/test/transaction.spec.ts
index c87d9e6..6744545 100644
--- a/test/transaction.spec.ts
+++ b/test/transaction.spec.ts
@@ -5,7 +5,7 @@ import * as bscript from '../src/script';
 import * as fixtures from './fixtures/transaction.json';
 
 describe('Transaction', () => {
-  function fromRaw(raw: any, noWitness?: boolean) {
+  function fromRaw(raw: any, noWitness?: boolean): Transaction {
     const tx = new Transaction();
     tx.version = raw.version;
     tx.locktime = raw.locktime;
@@ -47,7 +47,7 @@ describe('Transaction', () => {
   }
 
   describe('fromBuffer/fromHex', () => {
-    function importExport(f: any) {
+    function importExport(f: any): void {
       const id = f.id || f.hash;
       const txHex = f.hex || f.txHex;
 
@@ -218,7 +218,7 @@ describe('Transaction', () => {
   });
 
   describe('getHash/getId', () => {
-    function verify(f: any) {
+    function verify(f: any): void {
       it('should return the id for ' + f.id + '(' + f.description + ')', () => {
         const tx = Transaction.fromHex(f.whex || f.hex);
 
@@ -231,7 +231,7 @@ describe('Transaction', () => {
   });
 
   describe('isCoinbase', () => {
-    function verify(f: any) {
+    function verify(f: any): void {
       it(
         'should return ' +
           f.coinbase +
diff --git a/test/transaction_builder.spec.ts b/test/transaction_builder.spec.ts
index 0daa103..b07462e 100644
--- a/test/transaction_builder.spec.ts
+++ b/test/transaction_builder.spec.ts
@@ -1,16 +1,18 @@
 import * as assert from 'assert';
 import { beforeEach, describe, it } from 'mocha';
-import * as baddress from '../src/address';
-import * as bscript from '../src/script';
-import * as payments from '../src/payments';
 import {
   ECPair,
   networks as NETWORKS,
   Transaction,
   TransactionBuilder,
 } from '..';
+import * as baddress from '../src/address';
+import * as payments from '../src/payments';
+import * as bscript from '../src/script';
 
-console.warn = () => {}; // Silence the Deprecation Warning
+console.warn = (): void => {
+  return;
+}; // Silence the Deprecation Warning
 
 import * as fixtures from './fixtures/transaction_builder.json';
 
@@ -128,7 +130,7 @@ for (const useOldSignArgs of [false, true]) {
   if (useOldSignArgs) {
     consoleWarn = console.warn;
     // Silence console.warn during these tests
-    console.warn = () => undefined;
+    console.warn = (): undefined => undefined;
   }
   describe(`TransactionBuilder: useOldSignArgs === ${useOldSignArgs}`, () => {
     // constants
@@ -425,13 +427,13 @@ for (const useOldSignArgs of [false, true]) {
 
     describe('sign', () => {
       it('supports the alternative abstract interface { publicKey, sign }', () => {
-        const keyPair = {
+        const innerKeyPair = {
           publicKey: ECPair.makeRandom({
-            rng: () => {
+            rng: (): Buffer => {
               return Buffer.alloc(32, 1);
             },
           }).publicKey,
-          sign: () => {
+          sign: (): Buffer => {
             return Buffer.alloc(64, 0x5f);
           },
         };
@@ -446,11 +448,16 @@ for (const useOldSignArgs of [false, true]) {
         txb.sign({
           prevOutScriptType: 'p2pkh',
           vin: 0,
-          keyPair,
+          keyPair: innerKeyPair,
         });
         assert.strictEqual(
           txb.build().toHex(),
-          '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006a47304402205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f02205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f0121031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078fffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000',
+          '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff' +
+            'ffffffff010000006a47304402205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f' +
+            '5f5f5f5f5f5f5f5f5f5f5f5f5f02205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f' +
+            '5f5f5f5f5f5f5f5f5f5f5f5f5f5f0121031b84c5567b126440995d3ed5aaba0565' +
+            'd71e1834604819ff9c17f5e9d5dd078fffffffff01a0860100000000001976a914' +
+            '000000000000000000000000000000000000000088ac00000000',
         );
       });
 
@@ -470,7 +477,12 @@ for (const useOldSignArgs of [false, true]) {
         // high R
         assert.strictEqual(
           txb.build().toHex(),
-          '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006b483045022100b872677f35c9c14ad9c41d83649fb049250f32574e0b2547d67e209ed14ff05d022059b36ad058be54e887a1a311d5c393cb4941f6b93a0b090845ec67094de8972b01210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000',
+          '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff' +
+            'ffffffff010000006b483045022100b872677f35c9c14ad9c41d83649fb049250f' +
+            '32574e0b2547d67e209ed14ff05d022059b36ad058be54e887a1a311d5c393cb49' +
+            '41f6b93a0b090845ec67094de8972b01210279be667ef9dcbbac55a06295ce870b' +
+            '07029bfcdb2dce28d959f2815b16f81798ffffffff01a0860100000000001976a9' +
+            '14000000000000000000000000000000000000000088ac00000000',
         );
 
         txb = new TransactionBuilder();
@@ -489,12 +501,17 @@ for (const useOldSignArgs of [false, true]) {
         // low R
         assert.strictEqual(
           txb.build().toHex(),
-          '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006a473044022012a601efa8756ebe83e9ac7a7db061c3147e3b49d8be67685799fe51a4c8c62f02204d568d301d5ce14af390d566d4fd50e7b8ee48e71ec67786c029e721194dae3601210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000',
+          '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff' +
+            'ffffffff010000006a473044022012a601efa8756ebe83e9ac7a7db061c3147e3b' +
+            '49d8be67685799fe51a4c8c62f02204d568d301d5ce14af390d566d4fd50e7b8ee' +
+            '48e71ec67786c029e721194dae3601210279be667ef9dcbbac55a06295ce870b07' +
+            '029bfcdb2dce28d959f2815b16f81798ffffffff01a0860100000000001976a914' +
+            '000000000000000000000000000000000000000088ac00000000',
         );
       });
 
       it('fails when missing required arguments', () => {
-        let txb = new TransactionBuilder();
+        const txb = new TransactionBuilder();
         txb.setVersion(1);
         txb.addInput(
           'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
@@ -663,7 +680,12 @@ for (const useOldSignArgs of [false, true]) {
 
       it('for incomplete with 0 signatures', () => {
         const randomTxData =
-          '0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000';
+          '010000000001010001000000000000000000000000000000000000000000000000' +
+          '0000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4' +
+          '207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2' +
+          'c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f7' +
+          '4d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d345102' +
+          '5c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000';
         const randomAddress = '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH';
 
         const randomTx = Transaction.fromHex(randomTxData);
@@ -676,7 +698,9 @@ for (const useOldSignArgs of [false, true]) {
 
       it('for incomplete P2SH with 0 signatures', () => {
         const inp = Buffer.from(
-          '010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a80400000017a91471a8ec07ff69c6c4fee489184c462a9b1b9237488700000000',
+          '010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be9' +
+            '59391c100000000000ffffffff0100c817a80400000017a91471a8ec07ff69c6c4' +
+            'fee489184c462a9b1b9237488700000000',
           'hex',
         ); // arbitrary P2SH input
         const inpTx = Transaction.fromBuffer(inp);
@@ -690,7 +714,9 @@ for (const useOldSignArgs of [false, true]) {
 
       it('for incomplete P2WPKH with 0 signatures', () => {
         const inp = Buffer.from(
-          '010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a8040000001600141a15805e1f4040c9f68ccc887fca2e63547d794b00000000',
+          '010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be9' +
+            '59391c100000000000ffffffff0100c817a8040000001600141a15805e1f4040c9' +
+            'f68ccc887fca2e63547d794b00000000',
           'hex',
         );
         const inpTx = Transaction.fromBuffer(inp);
@@ -705,7 +731,9 @@ for (const useOldSignArgs of [false, true]) {
       it('for incomplete P2WSH with 0 signatures', () => {
         const inpTx = Transaction.fromBuffer(
           Buffer.from(
-            '010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a80400000022002072df76fcc0b231b94bdf7d8c25d7eef4716597818d211e19ade7813bff7a250200000000',
+            '010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80b' +
+              'e959391c100000000000ffffffff0100c817a80400000022002072df76fcc0b2' +
+              '31b94bdf7d8c25d7eef4716597818d211e19ade7813bff7a250200000000',
             'hex',
           ),
         );
@@ -800,12 +828,14 @@ for (const useOldSignArgs of [false, true]) {
       });
 
       it('should classify witness inputs with witness = true during multisigning', () => {
-        const keyPair = ECPair.fromWIF(
+        const innerKeyPair = ECPair.fromWIF(
           'cRAwuVuVSBZMPu7hdrYvMCZ8eevzmkExjFbaBLhqnDdrezxN3nTS',
           network,
         );
         const witnessScript = Buffer.from(
-          '522102bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e352e22102d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532b9ea1952ae',
+          '522102bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e3' +
+            '52e22102d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532' +
+            'b9ea1952ae',
           'hex',
         );
         const redeemScript = Buffer.from(
@@ -828,7 +858,7 @@ for (const useOldSignArgs of [false, true]) {
         txb.sign({
           prevOutScriptType: 'p2sh-p2wsh-p2ms',
           vin: 0,
-          keyPair,
+          keyPair: innerKeyPair,
           redeemScript,
           witnessValue: 100000,
           witnessScript,
@@ -850,10 +880,24 @@ for (const useOldSignArgs of [false, true]) {
       it('should handle badly pre-filled OP_0s', () => {
         // OP_0 is used where a signature is missing
         const redeemScripSig = bscript.fromASM(
-          'OP_0 OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae',
+          'OP_0 OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17' +
+            'be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621eb' +
+            'd9691d6b48c0d4283d7d01 52410479be667ef9dcbbac55a06295ce870b07029bf' +
+            'cdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b44' +
+            '8a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778' +
+            'e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f6326' +
+            '53266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c' +
+            '845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99' +
+            '934c2231b6cb9fd7584b8e67253ae',
         );
         const redeemScript = bscript.fromASM(
-          'OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG',
+          'OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f' +
+            '81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d' +
+            '4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c70' +
+            '9ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe5' +
+            '2a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce03' +
+            '6f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67' +
+            '2 OP_3 OP_CHECKMULTISIG',
         );
 
         const tx = new Transaction();
@@ -895,7 +939,17 @@ for (const useOldSignArgs of [false, true]) {
         );
         assert.strictEqual(
           bscript.toASM(tx2.ins[0].script),
-          'OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae',
+          'OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b' +
+            '63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691' +
+            'd6b48c0d4283d7d01 3045022100a346c61738304eac5e7702188764d19cdf68f4' +
+            '466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881' +
+            'd7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870' +
+            'b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a' +
+            '8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07' +
+            'cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceae' +
+            'ef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5' +
+            '229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f35' +
+            '66500a99934c2231b6cb9fd7584b8e67253ae',
         );
       });
 
@@ -908,7 +962,7 @@ for (const useOldSignArgs of [false, true]) {
         );
 
         const incomplete = txb.buildIncomplete().toHex();
-        const keyPair = ECPair.fromWIF(
+        const innerKeyPair = ECPair.fromWIF(
           'L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy',
         );
 
@@ -917,7 +971,7 @@ for (const useOldSignArgs of [false, true]) {
         txb.sign({
           prevOutScriptType: 'p2pkh',
           vin: 0,
-          keyPair,
+          keyPair: innerKeyPair,
         });
         const txId = txb.build().getId();
         assert.strictEqual(
@@ -933,7 +987,7 @@ for (const useOldSignArgs of [false, true]) {
         txb.sign({
           prevOutScriptType: 'p2pkh',
           vin: 0,
-          keyPair,
+          keyPair: innerKeyPair,
         });
         const txId2 = txb.build().getId();
         assert.strictEqual(txId, txId2);
diff --git a/tslint.json b/tslint.json
index 8a9cde6..d42da60 100644
--- a/tslint.json
+++ b/tslint.json
@@ -21,7 +21,7 @@
     "no-var-requires": false,
     "no-unused-expression": false,
     "object-literal-sort-keys": false,
-    "quotemark": [true, "single"],
+    "quotemark": [true, "single", "avoid-escape"],
     "typedef": [
       true,
       "call-signature",
diff --git a/types/address.d.ts b/types/address.d.ts
index be0e00a..5c7ed5a 100644
--- a/types/address.d.ts
+++ b/types/address.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Network } from './networks';
 export interface Base58CheckResult {
     hash: Buffer;
diff --git a/types/block.d.ts b/types/block.d.ts
index 0cda4c8..d77bb1b 100644
--- a/types/block.d.ts
+++ b/types/block.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Transaction } from './transaction';
 export declare class Block {
     static fromBuffer(buffer: Buffer): Block;
diff --git a/types/bufferutils.d.ts b/types/bufferutils.d.ts
index 2686e4e..1eff78d 100644
--- a/types/bufferutils.d.ts
+++ b/types/bufferutils.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 export declare function readUInt64LE(buffer: Buffer, offset: number): number;
 export declare function writeUInt64LE(buffer: Buffer, value: number, offset: number): number;
 export declare function reverseBuffer(buffer: Buffer): Buffer;
diff --git a/types/classify.d.ts b/types/classify.d.ts
index d0f07b4..6ea4754 100644
--- a/types/classify.d.ts
+++ b/types/classify.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 declare const types: {
     P2MS: string;
     NONSTANDARD: string;
diff --git a/types/crypto.d.ts b/types/crypto.d.ts
index 1743681..5d93acd 100644
--- a/types/crypto.d.ts
+++ b/types/crypto.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 export declare function ripemd160(buffer: Buffer): Buffer;
 export declare function sha1(buffer: Buffer): Buffer;
 export declare function sha256(buffer: Buffer): Buffer;
diff --git a/types/ecpair.d.ts b/types/ecpair.d.ts
index 0b69dfe..447c608 100644
--- a/types/ecpair.d.ts
+++ b/types/ecpair.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Network } from './networks';
 interface ECPairOptions {
     compressed?: boolean;
diff --git a/types/payments/index.d.ts b/types/payments/index.d.ts
index 1edf071..922e0bf 100644
--- a/types/payments/index.d.ts
+++ b/types/payments/index.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Network } from '../networks';
 import { p2data as embed } from './embed';
 import { p2ms } from './p2ms';
diff --git a/types/psbt.d.ts b/types/psbt.d.ts
index 4db075c..b1bacea 100644
--- a/types/psbt.d.ts
+++ b/types/psbt.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Psbt as PsbtBase } from 'bip174';
 import { KeyValue, PsbtGlobalUpdate, PsbtInput, PsbtInputUpdate, PsbtOutput, PsbtOutputUpdate, TransactionInput } from 'bip174/src/lib/interfaces';
 import { Signer, SignerAsync } from './ecpair';
diff --git a/types/script.d.ts b/types/script.d.ts
index 52ad4dd..4b04615 100644
--- a/types/script.d.ts
+++ b/types/script.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Stack } from './payments';
 import * as scriptNumber from './script_number';
 import * as scriptSignature from './script_signature';
diff --git a/types/script_number.d.ts b/types/script_number.d.ts
index 015bb89..cf535fc 100644
--- a/types/script_number.d.ts
+++ b/types/script_number.d.ts
@@ -1,3 +1,2 @@
-/// <reference types="node" />
 export declare function decode(buffer: Buffer, maxLength?: number, minimal?: boolean): number;
 export declare function encode(_number: number): Buffer;
diff --git a/types/script_signature.d.ts b/types/script_signature.d.ts
index 2057dd9..fbf18d5 100644
--- a/types/script_signature.d.ts
+++ b/types/script_signature.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 interface ScriptSignature {
     signature: Buffer;
     hashType: number;
diff --git a/types/templates/multisig/input.d.ts b/types/templates/multisig/input.d.ts
index a207dd6..6d46515 100644
--- a/types/templates/multisig/input.d.ts
+++ b/types/templates/multisig/input.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Stack } from '../../payments';
 export declare function check(script: Buffer | Stack, allowIncomplete?: boolean): boolean;
 export declare namespace check {
diff --git a/types/templates/multisig/output.d.ts b/types/templates/multisig/output.d.ts
index a207dd6..6d46515 100644
--- a/types/templates/multisig/output.d.ts
+++ b/types/templates/multisig/output.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Stack } from '../../payments';
 export declare function check(script: Buffer | Stack, allowIncomplete?: boolean): boolean;
 export declare namespace check {
diff --git a/types/templates/nulldata.d.ts b/types/templates/nulldata.d.ts
index aff3cd0..bf6497c 100644
--- a/types/templates/nulldata.d.ts
+++ b/types/templates/nulldata.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 export declare function check(script: Buffer | Array<number | Buffer>): boolean;
 export declare namespace check {
     var toJSON: () => string;
diff --git a/types/templates/pubkey/input.d.ts b/types/templates/pubkey/input.d.ts
index c4ffeab..4b70d2d 100644
--- a/types/templates/pubkey/input.d.ts
+++ b/types/templates/pubkey/input.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Stack } from '../../payments';
 export declare function check(script: Buffer | Stack): boolean;
 export declare namespace check {
diff --git a/types/templates/pubkey/output.d.ts b/types/templates/pubkey/output.d.ts
index c4ffeab..4b70d2d 100644
--- a/types/templates/pubkey/output.d.ts
+++ b/types/templates/pubkey/output.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Stack } from '../../payments';
 export declare function check(script: Buffer | Stack): boolean;
 export declare namespace check {
diff --git a/types/templates/pubkeyhash/input.d.ts b/types/templates/pubkeyhash/input.d.ts
index c4ffeab..4b70d2d 100644
--- a/types/templates/pubkeyhash/input.d.ts
+++ b/types/templates/pubkeyhash/input.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Stack } from '../../payments';
 export declare function check(script: Buffer | Stack): boolean;
 export declare namespace check {
diff --git a/types/templates/pubkeyhash/output.d.ts b/types/templates/pubkeyhash/output.d.ts
index 091758f..d66d8ac 100644
--- a/types/templates/pubkeyhash/output.d.ts
+++ b/types/templates/pubkeyhash/output.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 export declare function check(script: Buffer | Array<number | Buffer>): boolean;
 export declare namespace check {
     var toJSON: () => string;
diff --git a/types/templates/scripthash/input.d.ts b/types/templates/scripthash/input.d.ts
index a04d03c..14bbd5b 100644
--- a/types/templates/scripthash/input.d.ts
+++ b/types/templates/scripthash/input.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 export declare function check(script: Buffer | Array<number | Buffer>, allowIncomplete?: boolean): boolean;
 export declare namespace check {
     var toJSON: () => string;
diff --git a/types/templates/scripthash/output.d.ts b/types/templates/scripthash/output.d.ts
index 091758f..d66d8ac 100644
--- a/types/templates/scripthash/output.d.ts
+++ b/types/templates/scripthash/output.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 export declare function check(script: Buffer | Array<number | Buffer>): boolean;
 export declare namespace check {
     var toJSON: () => string;
diff --git a/types/templates/witnesscommitment/output.d.ts b/types/templates/witnesscommitment/output.d.ts
index 778c9a1..ec155a2 100644
--- a/types/templates/witnesscommitment/output.d.ts
+++ b/types/templates/witnesscommitment/output.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 export declare function check(script: Buffer | Array<number | Buffer>): boolean;
 export declare namespace check {
     var toJSON: () => string;
diff --git a/types/templates/witnesspubkeyhash/input.d.ts b/types/templates/witnesspubkeyhash/input.d.ts
index c4ffeab..4b70d2d 100644
--- a/types/templates/witnesspubkeyhash/input.d.ts
+++ b/types/templates/witnesspubkeyhash/input.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Stack } from '../../payments';
 export declare function check(script: Buffer | Stack): boolean;
 export declare namespace check {
diff --git a/types/templates/witnesspubkeyhash/output.d.ts b/types/templates/witnesspubkeyhash/output.d.ts
index 091758f..d66d8ac 100644
--- a/types/templates/witnesspubkeyhash/output.d.ts
+++ b/types/templates/witnesspubkeyhash/output.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 export declare function check(script: Buffer | Array<number | Buffer>): boolean;
 export declare namespace check {
     var toJSON: () => string;
diff --git a/types/templates/witnessscripthash/input.d.ts b/types/templates/witnessscripthash/input.d.ts
index b2a6e8a..767df3a 100644
--- a/types/templates/witnessscripthash/input.d.ts
+++ b/types/templates/witnessscripthash/input.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 export declare function check(chunks: Buffer[], allowIncomplete?: boolean): boolean;
 export declare namespace check {
     var toJSON: () => string;
diff --git a/types/templates/witnessscripthash/output.d.ts b/types/templates/witnessscripthash/output.d.ts
index 091758f..d66d8ac 100644
--- a/types/templates/witnessscripthash/output.d.ts
+++ b/types/templates/witnessscripthash/output.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 export declare function check(script: Buffer | Array<number | Buffer>): boolean;
 export declare namespace check {
     var toJSON: () => string;
diff --git a/types/transaction.d.ts b/types/transaction.d.ts
index 9bdba19..d7462b4 100644
--- a/types/transaction.d.ts
+++ b/types/transaction.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 export interface BlankOutput {
     script: Buffer;
     valueBuffer: Buffer;
diff --git a/types/transaction_builder.d.ts b/types/transaction_builder.d.ts
index 2799464..a80fc0f 100644
--- a/types/transaction_builder.d.ts
+++ b/types/transaction_builder.d.ts
@@ -1,4 +1,3 @@
-/// <reference types="node" />
 import { Signer } from './ecpair';
 import { Network } from './networks';
 import { Transaction } from './transaction';