Add comments and remove fromTransaction
This commit is contained in:
parent
71ddd656a3
commit
19a33f7da8
5 changed files with 144 additions and 70 deletions
76
src/psbt.js
76
src/psbt.js
|
@ -11,10 +11,54 @@ const networks_1 = require('./networks');
|
||||||
const payments = require('./payments');
|
const payments = require('./payments');
|
||||||
const bscript = require('./script');
|
const bscript = require('./script');
|
||||||
const transaction_1 = require('./transaction');
|
const transaction_1 = require('./transaction');
|
||||||
|
/**
|
||||||
|
* These are the default arguments for a Psbt instance.
|
||||||
|
*/
|
||||||
const DEFAULT_OPTS = {
|
const DEFAULT_OPTS = {
|
||||||
|
/**
|
||||||
|
* A bitcoinjs Network object. This is only used if you pass an `address`
|
||||||
|
* parameter to addOutput. Otherwise it is not needed and can be left default.
|
||||||
|
*/
|
||||||
network: networks_1.bitcoin,
|
network: networks_1.bitcoin,
|
||||||
|
/**
|
||||||
|
* When extractTransaction is called, the fee rate is checked.
|
||||||
|
* THIS IS NOT TO BE RELIED ON.
|
||||||
|
* It is only here as a last ditch effort to prevent sending a 500 BTC fee etc.
|
||||||
|
*/
|
||||||
maximumFeeRate: 5000,
|
maximumFeeRate: 5000,
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* Psbt class can parse and generate a PSBT binary based off of the BIP174.
|
||||||
|
* There are 6 roles that this class fulfills. (Explained in BIP174)
|
||||||
|
*
|
||||||
|
* Creator: This can be done with `new Psbt()`
|
||||||
|
* Updater: This can be done with `psbt.addInput(input)`, `psbt.addInputs(inputs)`,
|
||||||
|
* `psbt.addOutput(output)`, `psbt.addOutputs(outputs)` when you are looking to
|
||||||
|
* add new inputs and outputs to the PSBT, and `psbt.updateGlobal(itemObject)`,
|
||||||
|
* `psbt.updateInput(itemObject)`, `psbt.updateOutput(itemObject)`
|
||||||
|
* addInput requires hash: Buffer | string; and index: number; as attributes
|
||||||
|
* and can also include any attributes that are used in updateInput method.
|
||||||
|
* addOutput requires script: Buffer; and value: number; and likewise can include
|
||||||
|
* data for updateOutput.
|
||||||
|
* For a list of what attributes should be what types. Check the bip174 library.
|
||||||
|
* Also, check the integration tests for some examples of usage.
|
||||||
|
* Signer: There are a few methods. sign and signAsync, which will search all input
|
||||||
|
* information for your pubkey or pubkeyhash, and only sign inputs where it finds
|
||||||
|
* your info. Or you can explicitly sign a specific input with signInput and
|
||||||
|
* signInputAsync. For the async methods you can create a SignerAsync object
|
||||||
|
* and use something like a hardware wallet to sign with. (You must implement this)
|
||||||
|
* Combiner: psbts can be combined easily with `psbt.combine(psbt2, psbt3, psbt4 ...)`
|
||||||
|
* the psbt calling combine will always have precedence when a conflict occurs.
|
||||||
|
* Combine checks if the internal bitcoin transaction is the same, so be sure that
|
||||||
|
* all sequences, version, locktime, etc. are the same before combining.
|
||||||
|
* Input Finalizer: This role is fairly important. Not only does it need to construct
|
||||||
|
* the input scriptSigs and witnesses, but it SHOULD verify the signatures etc.
|
||||||
|
* Before running `psbt.finalizeAllInputs()` please run `psbt.validateAllSignatures()`
|
||||||
|
* Running any finalize method will delete any data in the input(s) that are no longer
|
||||||
|
* needed due to the finalized scripts containing the information.
|
||||||
|
* Transaction Extractor: This role will perform some checks before returning a
|
||||||
|
* Transaction object. Such as fee rate not being larger than maximumFeeRate etc.
|
||||||
|
*/
|
||||||
class Psbt {
|
class Psbt {
|
||||||
constructor(opts = {}, data = new bip174_1.Psbt(new PsbtTransaction())) {
|
constructor(opts = {}, data = new bip174_1.Psbt(new PsbtTransaction())) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
@ -55,25 +99,6 @@ class Psbt {
|
||||||
dpew(this, '__CACHE', false, true);
|
dpew(this, '__CACHE', false, true);
|
||||||
dpew(this, 'opts', false, true);
|
dpew(this, 'opts', false, true);
|
||||||
}
|
}
|
||||||
static fromTransaction(txBuf, opts = {}) {
|
|
||||||
const tx = new PsbtTransaction(txBuf);
|
|
||||||
checkTxEmpty(tx.tx);
|
|
||||||
const psbtBase = new bip174_1.Psbt(tx);
|
|
||||||
const psbt = new Psbt(opts, psbtBase);
|
|
||||||
psbt.__CACHE.__TX = tx.tx;
|
|
||||||
checkTxForDupeIns(tx.tx, psbt.__CACHE);
|
|
||||||
let inputCount = tx.tx.ins.length;
|
|
||||||
let outputCount = tx.tx.outs.length;
|
|
||||||
while (inputCount > 0) {
|
|
||||||
psbtBase.inputs.push({});
|
|
||||||
inputCount--;
|
|
||||||
}
|
|
||||||
while (outputCount > 0) {
|
|
||||||
psbtBase.outputs.push({});
|
|
||||||
outputCount--;
|
|
||||||
}
|
|
||||||
return psbt;
|
|
||||||
}
|
|
||||||
static fromBase64(data, opts = {}) {
|
static fromBase64(data, opts = {}) {
|
||||||
const buffer = Buffer.from(data, 'base64');
|
const buffer = Buffer.from(data, 'base64');
|
||||||
return this.fromBuffer(buffer, opts);
|
return this.fromBuffer(buffer, opts);
|
||||||
|
@ -418,13 +443,20 @@ class Psbt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Psbt = Psbt;
|
exports.Psbt = Psbt;
|
||||||
|
/**
|
||||||
|
* This function is needed to pass to the bip174 base class's fromBuffer.
|
||||||
|
* It takes the "transaction buffer" portion of the psbt buffer and returns a
|
||||||
|
* Transaction (From the bip174 library) interface.
|
||||||
|
*/
|
||||||
const transactionFromBuffer = buffer => new PsbtTransaction(buffer);
|
const transactionFromBuffer = buffer => new PsbtTransaction(buffer);
|
||||||
|
/**
|
||||||
|
* This class implements the Transaction interface from bip174 library.
|
||||||
|
* It contains a bitcoinjs-lib Transaction object.
|
||||||
|
*/
|
||||||
class PsbtTransaction {
|
class PsbtTransaction {
|
||||||
constructor(buffer = Buffer.from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0])) {
|
constructor(buffer = Buffer.from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0])) {
|
||||||
this.tx = transaction_1.Transaction.fromBuffer(buffer);
|
this.tx = transaction_1.Transaction.fromBuffer(buffer);
|
||||||
if (this.tx.ins.some(input => input.script.length !== 0)) {
|
checkTxEmpty(this.tx);
|
||||||
throw new Error('Format Error: Transaction ScriptSigs are not empty');
|
|
||||||
}
|
|
||||||
Object.defineProperty(this, 'tx', {
|
Object.defineProperty(this, 'tx', {
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
writable: true,
|
writable: true,
|
||||||
|
|
6
test/fixtures/psbt.json
vendored
6
test/fixtures/psbt.json
vendored
|
@ -480,12 +480,6 @@
|
||||||
"result": "cHNidP8BAKYCAAAAAlwKQ3suPWwEJ/zQ9sZsIioOcHKU1KoLMxlMNSXVIkEWAAAAAAD/////YYDJMap+mYgbTrCNAdpWHN+EkKvl+XYao/6co/EQfwMAAAAAAP////8CkF8BAAAAAAAWABRnPBAmVHz2HL+8/1U+QG5L2thjmjhKAAAAAAAAIgAg700yfFRyhWzQnPHIUb/XQqsjlpf4A0uw682pCVWuQ8IAAAAAAAEBKzB1AAAAAAAAIgAgth9oE4cDfC5aV58VgkW5CptHsIxppYzJV8C5kT6aTo8BCG4CSDBFAiEAs7TFGm6o/dpWSb4M/KSu2p7p881KA1uWn0r0wDCa0ckCIAdXlm9k3xWLj2f+j0hIXK+0ew9dc8qoHEL2babYeWliASMhA182CcWcQ9L2zg9j8jlt7OlaIATNDgNFMBKB1J14wzTprAABASuAOAEAAAAAACIAILYfaBOHA3wuWlefFYJFuQqbR7CMaaWMyVfAuZE+mk6PAQhuAkgwRQIhALpc3q2mj2ZiVl6PgFdJKHkPUrpogsF9DhYFZdSshLHrAiBVrEVSzPzLn3EnVXixnWpqsdf2ln4wmYspuXZlJp2KygEjIQNfNgnFnEPS9s4PY/I5bezpWiAEzQ4DRTASgdSdeMM06awAAAA="
|
"result": "cHNidP8BAKYCAAAAAlwKQ3suPWwEJ/zQ9sZsIioOcHKU1KoLMxlMNSXVIkEWAAAAAAD/////YYDJMap+mYgbTrCNAdpWHN+EkKvl+XYao/6co/EQfwMAAAAAAP////8CkF8BAAAAAAAWABRnPBAmVHz2HL+8/1U+QG5L2thjmjhKAAAAAAAAIgAg700yfFRyhWzQnPHIUb/XQqsjlpf4A0uw682pCVWuQ8IAAAAAAAEBKzB1AAAAAAAAIgAgth9oE4cDfC5aV58VgkW5CptHsIxppYzJV8C5kT6aTo8BCG4CSDBFAiEAs7TFGm6o/dpWSb4M/KSu2p7p881KA1uWn0r0wDCa0ckCIAdXlm9k3xWLj2f+j0hIXK+0ew9dc8qoHEL2babYeWliASMhA182CcWcQ9L2zg9j8jlt7OlaIATNDgNFMBKB1J14wzTprAABASuAOAEAAAAAACIAILYfaBOHA3wuWlefFYJFuQqbR7CMaaWMyVfAuZE+mk6PAQhuAkgwRQIhALpc3q2mj2ZiVl6PgFdJKHkPUrpogsF9DhYFZdSshLHrAiBVrEVSzPzLn3EnVXixnWpqsdf2ln4wmYspuXZlJp2KygEjIQNfNgnFnEPS9s4PY/I5bezpWiAEzQ4DRTASgdSdeMM06awAAAA="
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fromTransaction": [
|
|
||||||
{
|
|
||||||
"transaction": "020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000",
|
|
||||||
"result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAAAAAA="
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"validateSignatures": {
|
"validateSignatures": {
|
||||||
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEiAgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc0cwRAIgZfRbpZmLWaJ//hp77QFq8fH5DVSzqo90UKpfVqJRA70CIH9yRwOtHtuWaAsoS1bU/8uI9/t1nqu+CKow8puFE4PSAQEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA",
|
"psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEiAgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc0cwRAIgZfRbpZmLWaJ//hp77QFq8fH5DVSzqo90UKpfVqJRA70CIH9yRwOtHtuWaAsoS1bU/8uI9/t1nqu+CKow8puFE4PSAQEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA",
|
||||||
"index": 0,
|
"index": 0,
|
||||||
|
|
14
test/psbt.js
14
test/psbt.js
|
@ -309,15 +309,6 @@ describe(`Psbt`, () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('fromTransaction', () => {
|
|
||||||
fixtures.fromTransaction.forEach(f => {
|
|
||||||
it('Creates the expected PSBT from a transaction buffer', () => {
|
|
||||||
const psbt = Psbt.fromTransaction(Buffer.from(f.transaction, 'hex'))
|
|
||||||
assert.strictEqual(psbt.toBase64(), f.result)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('addInput', () => {
|
describe('addInput', () => {
|
||||||
fixtures.addInput.checks.forEach(f => {
|
fixtures.addInput.checks.forEach(f => {
|
||||||
it(f.description, () => {
|
it(f.description, () => {
|
||||||
|
@ -521,11 +512,6 @@ describe(`Psbt`, () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Method return types', () => {
|
describe('Method return types', () => {
|
||||||
it('fromTransaction returns Psbt type (not base class)', () => {
|
|
||||||
const psbt = Psbt.fromTransaction(Buffer.from([2,0,0,0,0,0,0,0,0,0]));
|
|
||||||
assert.strictEqual(psbt instanceof Psbt, true);
|
|
||||||
assert.ok(psbt.__CACHE.__TX);
|
|
||||||
})
|
|
||||||
it('fromBuffer returns Psbt type (not base class)', () => {
|
it('fromBuffer returns Psbt type (not base class)', () => {
|
||||||
const psbt = Psbt.fromBuffer(Buffer.from(
|
const psbt = Psbt.fromBuffer(Buffer.from(
|
||||||
'70736274ff01000a01000000000000000000000000', 'hex' //cHNidP8BAAoBAAAAAAAAAAAAAAAA
|
'70736274ff01000a01000000000000000000000000', 'hex' //cHNidP8BAAoBAAAAAAAAAAAAAAAA
|
||||||
|
|
|
@ -26,32 +26,56 @@ import * as payments from './payments';
|
||||||
import * as bscript from './script';
|
import * as bscript from './script';
|
||||||
import { Output, Transaction } from './transaction';
|
import { Output, Transaction } from './transaction';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are the default arguments for a Psbt instance.
|
||||||
|
*/
|
||||||
const DEFAULT_OPTS: PsbtOpts = {
|
const DEFAULT_OPTS: PsbtOpts = {
|
||||||
|
/**
|
||||||
|
* A bitcoinjs Network object. This is only used if you pass an `address`
|
||||||
|
* parameter to addOutput. Otherwise it is not needed and can be left default.
|
||||||
|
*/
|
||||||
network: btcNetwork,
|
network: btcNetwork,
|
||||||
|
/**
|
||||||
|
* When extractTransaction is called, the fee rate is checked.
|
||||||
|
* THIS IS NOT TO BE RELIED ON.
|
||||||
|
* It is only here as a last ditch effort to prevent sending a 500 BTC fee etc.
|
||||||
|
*/
|
||||||
maximumFeeRate: 5000, // satoshi per byte
|
maximumFeeRate: 5000, // satoshi per byte
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Psbt class can parse and generate a PSBT binary based off of the BIP174.
|
||||||
|
* There are 6 roles that this class fulfills. (Explained in BIP174)
|
||||||
|
*
|
||||||
|
* Creator: This can be done with `new Psbt()`
|
||||||
|
* Updater: This can be done with `psbt.addInput(input)`, `psbt.addInputs(inputs)`,
|
||||||
|
* `psbt.addOutput(output)`, `psbt.addOutputs(outputs)` when you are looking to
|
||||||
|
* add new inputs and outputs to the PSBT, and `psbt.updateGlobal(itemObject)`,
|
||||||
|
* `psbt.updateInput(itemObject)`, `psbt.updateOutput(itemObject)`
|
||||||
|
* addInput requires hash: Buffer | string; and index: number; as attributes
|
||||||
|
* and can also include any attributes that are used in updateInput method.
|
||||||
|
* addOutput requires script: Buffer; and value: number; and likewise can include
|
||||||
|
* data for updateOutput.
|
||||||
|
* For a list of what attributes should be what types. Check the bip174 library.
|
||||||
|
* Also, check the integration tests for some examples of usage.
|
||||||
|
* Signer: There are a few methods. sign and signAsync, which will search all input
|
||||||
|
* information for your pubkey or pubkeyhash, and only sign inputs where it finds
|
||||||
|
* your info. Or you can explicitly sign a specific input with signInput and
|
||||||
|
* signInputAsync. For the async methods you can create a SignerAsync object
|
||||||
|
* and use something like a hardware wallet to sign with. (You must implement this)
|
||||||
|
* Combiner: psbts can be combined easily with `psbt.combine(psbt2, psbt3, psbt4 ...)`
|
||||||
|
* the psbt calling combine will always have precedence when a conflict occurs.
|
||||||
|
* Combine checks if the internal bitcoin transaction is the same, so be sure that
|
||||||
|
* all sequences, version, locktime, etc. are the same before combining.
|
||||||
|
* Input Finalizer: This role is fairly important. Not only does it need to construct
|
||||||
|
* the input scriptSigs and witnesses, but it SHOULD verify the signatures etc.
|
||||||
|
* Before running `psbt.finalizeAllInputs()` please run `psbt.validateAllSignatures()`
|
||||||
|
* Running any finalize method will delete any data in the input(s) that are no longer
|
||||||
|
* needed due to the finalized scripts containing the information.
|
||||||
|
* Transaction Extractor: This role will perform some checks before returning a
|
||||||
|
* Transaction object. Such as fee rate not being larger than maximumFeeRate etc.
|
||||||
|
*/
|
||||||
export class Psbt {
|
export class Psbt {
|
||||||
static fromTransaction(txBuf: Buffer, opts: PsbtOptsOptional = {}): Psbt {
|
|
||||||
const tx = new PsbtTransaction(txBuf);
|
|
||||||
checkTxEmpty(tx.tx);
|
|
||||||
const psbtBase = new PsbtBase(tx);
|
|
||||||
const psbt = new Psbt(opts, psbtBase);
|
|
||||||
psbt.__CACHE.__TX = tx.tx;
|
|
||||||
checkTxForDupeIns(tx.tx, psbt.__CACHE);
|
|
||||||
let inputCount = tx.tx.ins.length;
|
|
||||||
let outputCount = tx.tx.outs.length;
|
|
||||||
while (inputCount > 0) {
|
|
||||||
psbtBase.inputs.push({});
|
|
||||||
inputCount--;
|
|
||||||
}
|
|
||||||
while (outputCount > 0) {
|
|
||||||
psbtBase.outputs.push({});
|
|
||||||
outputCount--;
|
|
||||||
}
|
|
||||||
return psbt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromBase64(data: string, opts: PsbtOptsOptional = {}): Psbt {
|
static fromBase64(data: string, opts: PsbtOptsOptional = {}): Psbt {
|
||||||
const buffer = Buffer.from(data, 'base64');
|
const buffer = Buffer.from(data, 'base64');
|
||||||
return this.fromBuffer(buffer, opts);
|
return this.fromBuffer(buffer, opts);
|
||||||
|
@ -356,7 +380,7 @@ export class Psbt {
|
||||||
}
|
}
|
||||||
|
|
||||||
signAsync(
|
signAsync(
|
||||||
keyPair: SignerAsync,
|
keyPair: Signer | SignerAsync,
|
||||||
sighashTypes: number[] = [Transaction.SIGHASH_ALL],
|
sighashTypes: number[] = [Transaction.SIGHASH_ALL],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return new Promise(
|
return new Promise(
|
||||||
|
@ -419,7 +443,7 @@ export class Psbt {
|
||||||
|
|
||||||
signInputAsync(
|
signInputAsync(
|
||||||
inputIndex: number,
|
inputIndex: number,
|
||||||
keyPair: SignerAsync,
|
keyPair: Signer | SignerAsync,
|
||||||
sighashTypes: number[] = [Transaction.SIGHASH_ALL],
|
sighashTypes: number[] = [Transaction.SIGHASH_ALL],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return new Promise(
|
return new Promise(
|
||||||
|
@ -524,17 +548,24 @@ interface PsbtOpts {
|
||||||
maximumFeeRate: number;
|
maximumFeeRate: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is needed to pass to the bip174 base class's fromBuffer.
|
||||||
|
* It takes the "transaction buffer" portion of the psbt buffer and returns a
|
||||||
|
* Transaction (From the bip174 library) interface.
|
||||||
|
*/
|
||||||
const transactionFromBuffer: TransactionFromBuffer = (
|
const transactionFromBuffer: TransactionFromBuffer = (
|
||||||
buffer: Buffer,
|
buffer: Buffer,
|
||||||
): ITransaction => new PsbtTransaction(buffer);
|
): ITransaction => new PsbtTransaction(buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class implements the Transaction interface from bip174 library.
|
||||||
|
* It contains a bitcoinjs-lib Transaction object.
|
||||||
|
*/
|
||||||
class PsbtTransaction implements ITransaction {
|
class PsbtTransaction implements ITransaction {
|
||||||
tx: Transaction;
|
tx: Transaction;
|
||||||
constructor(buffer: Buffer = Buffer.from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0])) {
|
constructor(buffer: Buffer = Buffer.from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0])) {
|
||||||
this.tx = Transaction.fromBuffer(buffer);
|
this.tx = Transaction.fromBuffer(buffer);
|
||||||
if (this.tx.ins.some(input => input.script.length !== 0)) {
|
checkTxEmpty(this.tx);
|
||||||
throw new Error('Format Error: Transaction ScriptSigs are not empty');
|
|
||||||
}
|
|
||||||
Object.defineProperty(this, 'tx', {
|
Object.defineProperty(this, 'tx', {
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
writable: true,
|
writable: true,
|
||||||
|
|
37
types/psbt.d.ts
vendored
37
types/psbt.d.ts
vendored
|
@ -4,9 +4,40 @@ import { KeyValue, PsbtGlobalUpdate, PsbtInputUpdate, PsbtOutputUpdate, Transact
|
||||||
import { Signer, SignerAsync } from './ecpair';
|
import { Signer, SignerAsync } from './ecpair';
|
||||||
import { Network } from './networks';
|
import { Network } from './networks';
|
||||||
import { Transaction } from './transaction';
|
import { Transaction } from './transaction';
|
||||||
|
/**
|
||||||
|
* Psbt class can parse and generate a PSBT binary based off of the BIP174.
|
||||||
|
* There are 6 roles that this class fulfills. (Explained in BIP174)
|
||||||
|
*
|
||||||
|
* Creator: This can be done with `new Psbt()`
|
||||||
|
* Updater: This can be done with `psbt.addInput(input)`, `psbt.addInputs(inputs)`,
|
||||||
|
* `psbt.addOutput(output)`, `psbt.addOutputs(outputs)` when you are looking to
|
||||||
|
* add new inputs and outputs to the PSBT, and `psbt.updateGlobal(itemObject)`,
|
||||||
|
* `psbt.updateInput(itemObject)`, `psbt.updateOutput(itemObject)`
|
||||||
|
* addInput requires hash: Buffer | string; and index: number; as attributes
|
||||||
|
* and can also include any attributes that are used in updateInput method.
|
||||||
|
* addOutput requires script: Buffer; and value: number; and likewise can include
|
||||||
|
* data for updateOutput.
|
||||||
|
* For a list of what attributes should be what types. Check the bip174 library.
|
||||||
|
* Also, check the integration tests for some examples of usage.
|
||||||
|
* Signer: There are a few methods. sign and signAsync, which will search all input
|
||||||
|
* information for your pubkey or pubkeyhash, and only sign inputs where it finds
|
||||||
|
* your info. Or you can explicitly sign a specific input with signInput and
|
||||||
|
* signInputAsync. For the async methods you can create a SignerAsync object
|
||||||
|
* and use something like a hardware wallet to sign with. (You must implement this)
|
||||||
|
* Combiner: psbts can be combined easily with `psbt.combine(psbt2, psbt3, psbt4 ...)`
|
||||||
|
* the psbt calling combine will always have precedence when a conflict occurs.
|
||||||
|
* Combine checks if the internal bitcoin transaction is the same, so be sure that
|
||||||
|
* all sequences, version, locktime, etc. are the same before combining.
|
||||||
|
* Input Finalizer: This role is fairly important. Not only does it need to construct
|
||||||
|
* the input scriptSigs and witnesses, but it SHOULD verify the signatures etc.
|
||||||
|
* Before running `psbt.finalizeAllInputs()` please run `psbt.validateAllSignatures()`
|
||||||
|
* Running any finalize method will delete any data in the input(s) that are no longer
|
||||||
|
* needed due to the finalized scripts containing the information.
|
||||||
|
* Transaction Extractor: This role will perform some checks before returning a
|
||||||
|
* Transaction object. Such as fee rate not being larger than maximumFeeRate etc.
|
||||||
|
*/
|
||||||
export declare class Psbt {
|
export declare class Psbt {
|
||||||
readonly data: PsbtBase;
|
readonly data: PsbtBase;
|
||||||
static fromTransaction(txBuf: Buffer, opts?: PsbtOptsOptional): Psbt;
|
|
||||||
static fromBase64(data: string, opts?: PsbtOptsOptional): Psbt;
|
static fromBase64(data: string, opts?: PsbtOptsOptional): Psbt;
|
||||||
static fromHex(data: string, opts?: PsbtOptsOptional): Psbt;
|
static fromHex(data: string, opts?: PsbtOptsOptional): Psbt;
|
||||||
static fromBuffer(buffer: Buffer, opts?: PsbtOptsOptional): Psbt;
|
static fromBuffer(buffer: Buffer, opts?: PsbtOptsOptional): Psbt;
|
||||||
|
@ -32,9 +63,9 @@ export declare class Psbt {
|
||||||
validateAllSignatures(): boolean;
|
validateAllSignatures(): boolean;
|
||||||
validateSignatures(inputIndex: number, pubkey?: Buffer): boolean;
|
validateSignatures(inputIndex: number, pubkey?: Buffer): boolean;
|
||||||
sign(keyPair: Signer, sighashTypes?: number[]): this;
|
sign(keyPair: Signer, sighashTypes?: number[]): this;
|
||||||
signAsync(keyPair: SignerAsync, sighashTypes?: number[]): Promise<void>;
|
signAsync(keyPair: Signer | SignerAsync, sighashTypes?: number[]): Promise<void>;
|
||||||
signInput(inputIndex: number, keyPair: Signer, sighashTypes?: number[]): this;
|
signInput(inputIndex: number, keyPair: Signer, sighashTypes?: number[]): this;
|
||||||
signInputAsync(inputIndex: number, keyPair: SignerAsync, sighashTypes?: number[]): Promise<void>;
|
signInputAsync(inputIndex: number, keyPair: Signer | SignerAsync, sighashTypes?: number[]): Promise<void>;
|
||||||
toBuffer(): Buffer;
|
toBuffer(): Buffer;
|
||||||
toHex(): string;
|
toHex(): string;
|
||||||
toBase64(): string;
|
toBase64(): string;
|
||||||
|
|
Loading…
Add table
Reference in a new issue