Rename methods
This commit is contained in:
parent
acf59f167c
commit
e19bc58b30
6 changed files with 70 additions and 64 deletions
26
src/psbt.js
26
src/psbt.js
|
@ -42,7 +42,7 @@ const DEFAULT_OPTS = {
|
||||||
* data for updateOutput.
|
* data for updateOutput.
|
||||||
* For a list of what attributes should be what types. Check the bip174 library.
|
* For a list of what attributes should be what types. Check the bip174 library.
|
||||||
* Also, check the integration tests for some examples of usage.
|
* Also, check the integration tests for some examples of usage.
|
||||||
* Signer: There are a few methods. sign and signAsync, which will search all input
|
* Signer: There are a few methods. signAllInputs and signAsync, which will search all input
|
||||||
* information for your pubkey or pubkeyhash, and only sign inputs where it finds
|
* 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
|
* your info. Or you can explicitly sign a specific input with signInput and
|
||||||
* signInputAsync. For the async methods you can create a SignerAsync object
|
* signInputAsync. For the async methods you can create a SignerAsync object
|
||||||
|
@ -53,7 +53,7 @@ const DEFAULT_OPTS = {
|
||||||
* all sequences, version, locktime, etc. are the same before combining.
|
* all sequences, version, locktime, etc. are the same before combining.
|
||||||
* Input Finalizer: This role is fairly important. Not only does it need to construct
|
* 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.
|
* the input scriptSigs and witnesses, but it SHOULD verify the signatures etc.
|
||||||
* Before running `psbt.finalizeAllInputs()` please run `psbt.validateAllSignatures()`
|
* Before running `psbt.finalizeAllInputs()` please run `psbt.validateSignaturesOfAllInputs()`
|
||||||
* Running any finalize method will delete any data in the input(s) that are no longer
|
* 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.
|
* needed due to the finalized scripts containing the information.
|
||||||
* Transaction Extractor: This role will perform some checks before returning a
|
* Transaction Extractor: This role will perform some checks before returning a
|
||||||
|
@ -131,9 +131,9 @@ class Psbt {
|
||||||
c.__EXTRACTED_TX = undefined;
|
c.__EXTRACTED_TX = undefined;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
setSequence(inputIndex, sequence) {
|
setInputSequence(inputIndex, sequence) {
|
||||||
check32Bit(sequence);
|
check32Bit(sequence);
|
||||||
checkInputsForPartialSig(this.data.inputs, 'setSequence');
|
checkInputsForPartialSig(this.data.inputs, 'setInputSequence');
|
||||||
const c = this.__CACHE;
|
const c = this.__CACHE;
|
||||||
if (c.__TX.ins.length <= inputIndex) {
|
if (c.__TX.ins.length <= inputIndex) {
|
||||||
throw new Error('Input index too high');
|
throw new Error('Input index too high');
|
||||||
|
@ -239,14 +239,14 @@ class Psbt {
|
||||||
this.data.clearFinalizedInput(inputIndex);
|
this.data.clearFinalizedInput(inputIndex);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
validateAllSignatures() {
|
validateSignaturesOfAllInputs() {
|
||||||
utils_1.checkForInput(this.data.inputs, 0); // making sure we have at least one
|
utils_1.checkForInput(this.data.inputs, 0); // making sure we have at least one
|
||||||
const results = range(this.data.inputs.length).map(idx =>
|
const results = range(this.data.inputs.length).map(idx =>
|
||||||
this.validateSignatures(idx),
|
this.validateSignaturesOfInput(idx),
|
||||||
);
|
);
|
||||||
return results.reduce((final, res) => res === true && final, true);
|
return results.reduce((final, res) => res === true && final, true);
|
||||||
}
|
}
|
||||||
validateSignatures(inputIndex, pubkey) {
|
validateSignaturesOfInput(inputIndex, pubkey) {
|
||||||
const input = this.data.inputs[inputIndex];
|
const input = this.data.inputs[inputIndex];
|
||||||
const partialSig = (input || {}).partialSig;
|
const partialSig = (input || {}).partialSig;
|
||||||
if (!input || !partialSig || partialSig.length < 1)
|
if (!input || !partialSig || partialSig.length < 1)
|
||||||
|
@ -278,7 +278,10 @@ class Psbt {
|
||||||
}
|
}
|
||||||
return results.every(res => res === true);
|
return results.every(res => res === true);
|
||||||
}
|
}
|
||||||
signHD(hdKeyPair, sighashTypes = [transaction_1.Transaction.SIGHASH_ALL]) {
|
signAllInputsHD(
|
||||||
|
hdKeyPair,
|
||||||
|
sighashTypes = [transaction_1.Transaction.SIGHASH_ALL],
|
||||||
|
) {
|
||||||
if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
|
if (!hdKeyPair || !hdKeyPair.publicKey || !hdKeyPair.fingerprint) {
|
||||||
throw new Error('Need HDSigner to sign input');
|
throw new Error('Need HDSigner to sign input');
|
||||||
}
|
}
|
||||||
|
@ -358,7 +361,10 @@ class Psbt {
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
sign(keyPair, sighashTypes = [transaction_1.Transaction.SIGHASH_ALL]) {
|
signAllInputs(
|
||||||
|
keyPair,
|
||||||
|
sighashTypes = [transaction_1.Transaction.SIGHASH_ALL],
|
||||||
|
) {
|
||||||
if (!keyPair || !keyPair.publicKey)
|
if (!keyPair || !keyPair.publicKey)
|
||||||
throw new Error('Need Signer to sign input');
|
throw new Error('Need Signer to sign input');
|
||||||
// TODO: Add a pubkey/pubkeyhash cache to each input
|
// TODO: Add a pubkey/pubkeyhash cache to each input
|
||||||
|
@ -635,7 +641,7 @@ function checkInputsForPartialSig(inputs, action) {
|
||||||
case transaction_1.Transaction.SIGHASH_SINGLE:
|
case transaction_1.Transaction.SIGHASH_SINGLE:
|
||||||
case transaction_1.Transaction.SIGHASH_NONE:
|
case transaction_1.Transaction.SIGHASH_NONE:
|
||||||
whitelist.push('addOutput');
|
whitelist.push('addOutput');
|
||||||
whitelist.push('setSequence');
|
whitelist.push('setInputSequence');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (whitelist.indexOf(action) === -1) {
|
if (whitelist.indexOf(action) === -1) {
|
||||||
|
|
2
test/fixtures/psbt.json
vendored
2
test/fixtures/psbt.json
vendored
|
@ -526,7 +526,7 @@
|
||||||
"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="
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"validateSignatures": {
|
"validateSignaturesOfInput": {
|
||||||
"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,
|
||||||
"pubkey": "Buffer.from('029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f', 'hex')",
|
"pubkey": "Buffer.from('029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f', 'hex')",
|
||||||
|
|
|
@ -59,7 +59,7 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
|
||||||
value: 80000,
|
value: 80000,
|
||||||
});
|
});
|
||||||
psbt.signInput(0, alice);
|
psbt.signInput(0, alice);
|
||||||
psbt.validateSignatures(0);
|
psbt.validateSignaturesOfInput(0);
|
||||||
psbt.finalizeAllInputs();
|
psbt.finalizeAllInputs();
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
psbt.extractTransaction().toHex(),
|
psbt.extractTransaction().toHex(),
|
||||||
|
@ -128,8 +128,8 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
|
||||||
// Alice signs each input with the respective private keys
|
// Alice signs each input with the respective private keys
|
||||||
// signInput and signInputAsync are better
|
// signInput and signInputAsync are better
|
||||||
// (They take the input index explicitly as the first arg)
|
// (They take the input index explicitly as the first arg)
|
||||||
signer1.sign(alice1.keys[0]);
|
signer1.signAllInputs(alice1.keys[0]);
|
||||||
signer2.sign(alice2.keys[0]);
|
signer2.signAllInputs(alice2.keys[0]);
|
||||||
|
|
||||||
// If your signer object's sign method returns a promise, use the following
|
// If your signer object's sign method returns a promise, use the following
|
||||||
// await signer2.signAsync(alice2.keys[0])
|
// await signer2.signAsync(alice2.keys[0])
|
||||||
|
@ -147,8 +147,8 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
|
||||||
// Finalizer wants to check all signatures are valid before finalizing.
|
// Finalizer wants to check all signatures are valid before finalizing.
|
||||||
// If the finalizer wants to check for specific pubkeys, the second arg
|
// If the finalizer wants to check for specific pubkeys, the second arg
|
||||||
// can be passed. See the first multisig example below.
|
// can be passed. See the first multisig example below.
|
||||||
assert.strictEqual(psbt.validateSignatures(0), true);
|
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||||
assert.strictEqual(psbt.validateSignatures(1), true);
|
assert.strictEqual(psbt.validateSignaturesOfInput(1), true);
|
||||||
|
|
||||||
// This step it new. Since we separate the signing operation and
|
// This step it new. Since we separate the signing operation and
|
||||||
// the creation of the scriptSig and witness stack, we are able to
|
// the creation of the scriptSig and witness stack, we are able to
|
||||||
|
@ -183,7 +183,7 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
|
||||||
})
|
})
|
||||||
.signInput(0, alice1.keys[0]);
|
.signInput(0, alice1.keys[0]);
|
||||||
|
|
||||||
assert.strictEqual(psbt.validateSignatures(0), true);
|
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||||
psbt.finalizeAllInputs();
|
psbt.finalizeAllInputs();
|
||||||
|
|
||||||
// build and broadcast to the RegTest network
|
// build and broadcast to the RegTest network
|
||||||
|
@ -215,13 +215,13 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
|
||||||
.signInput(0, multisig.keys[0])
|
.signInput(0, multisig.keys[0])
|
||||||
.signInput(0, multisig.keys[2]);
|
.signInput(0, multisig.keys[2]);
|
||||||
|
|
||||||
assert.strictEqual(psbt.validateSignatures(0), true);
|
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
psbt.validateSignatures(0, multisig.keys[0].publicKey),
|
psbt.validateSignaturesOfInput(0, multisig.keys[0].publicKey),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.validateSignatures(0, multisig.keys[3].publicKey);
|
psbt.validateSignaturesOfInput(0, multisig.keys[3].publicKey);
|
||||||
}, new RegExp('No signatures for this pubkey'));
|
}, new RegExp('No signatures for this pubkey'));
|
||||||
psbt.finalizeAllInputs();
|
psbt.finalizeAllInputs();
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
|
||||||
const tx = new bitcoin.Psbt()
|
const tx = new bitcoin.Psbt()
|
||||||
.addInputs([inputData, inputData2])
|
.addInputs([inputData, inputData2])
|
||||||
.addOutputs([outputData, outputData2])
|
.addOutputs([outputData, outputData2])
|
||||||
.sign(keyPair)
|
.signAllInputs(keyPair)
|
||||||
.finalizeAllInputs()
|
.finalizeAllInputs()
|
||||||
.extractTransaction();
|
.extractTransaction();
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
|
||||||
})
|
})
|
||||||
.signInput(0, p2wpkh.keys[0]);
|
.signInput(0, p2wpkh.keys[0]);
|
||||||
|
|
||||||
assert.strictEqual(psbt.validateSignatures(0), true);
|
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||||
psbt.finalizeAllInputs();
|
psbt.finalizeAllInputs();
|
||||||
|
|
||||||
const tx = psbt.extractTransaction();
|
const tx = psbt.extractTransaction();
|
||||||
|
@ -340,7 +340,7 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
|
||||||
})
|
})
|
||||||
.signInput(0, p2wsh.keys[0]);
|
.signInput(0, p2wsh.keys[0]);
|
||||||
|
|
||||||
assert.strictEqual(psbt.validateSignatures(0), true);
|
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||||
psbt.finalizeAllInputs();
|
psbt.finalizeAllInputs();
|
||||||
|
|
||||||
const tx = psbt.extractTransaction();
|
const tx = psbt.extractTransaction();
|
||||||
|
@ -383,13 +383,13 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
|
||||||
.signInput(0, p2sh.keys[2])
|
.signInput(0, p2sh.keys[2])
|
||||||
.signInput(0, p2sh.keys[3]);
|
.signInput(0, p2sh.keys[3]);
|
||||||
|
|
||||||
assert.strictEqual(psbt.validateSignatures(0), true);
|
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
psbt.validateSignatures(0, p2sh.keys[3].publicKey),
|
psbt.validateSignaturesOfInput(0, p2sh.keys[3].publicKey),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.validateSignatures(0, p2sh.keys[1].publicKey);
|
psbt.validateSignaturesOfInput(0, p2sh.keys[1].publicKey);
|
||||||
}, new RegExp('No signatures for this pubkey'));
|
}, new RegExp('No signatures for this pubkey'));
|
||||||
psbt.finalizeAllInputs();
|
psbt.finalizeAllInputs();
|
||||||
|
|
||||||
|
@ -449,8 +449,8 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
|
||||||
})
|
})
|
||||||
.signInputHD(0, hdRoot); // must sign with root!!!
|
.signInputHD(0, hdRoot); // must sign with root!!!
|
||||||
|
|
||||||
assert.strictEqual(psbt.validateSignatures(0), true);
|
assert.strictEqual(psbt.validateSignaturesOfInput(0), true);
|
||||||
assert.strictEqual(psbt.validateSignatures(0, childNode.publicKey), true);
|
assert.strictEqual(psbt.validateSignaturesOfInput(0, childNode.publicKey), true);
|
||||||
psbt.finalizeAllInputs();
|
psbt.finalizeAllInputs();
|
||||||
|
|
||||||
const tx = psbt.extractTransaction();
|
const tx = psbt.extractTransaction();
|
||||||
|
|
38
test/psbt.js
38
test/psbt.js
|
@ -249,14 +249,14 @@ describe(`Psbt`, () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('sign', () => {
|
describe('signAllInputs', () => {
|
||||||
fixtures.signInput.checks.forEach(f => {
|
fixtures.signInput.checks.forEach(f => {
|
||||||
if (f.description === 'checks the input exists') return
|
if (f.description === 'checks the input exists') return
|
||||||
it(f.description, () => {
|
it(f.description, () => {
|
||||||
if (f.shouldSign) {
|
if (f.shouldSign) {
|
||||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
||||||
assert.doesNotThrow(() => {
|
assert.doesNotThrow(() => {
|
||||||
psbtThatShouldsign.sign(
|
psbtThatShouldsign.signAllInputs(
|
||||||
ECPair.fromWIF(f.shouldSign.WIF),
|
ECPair.fromWIF(f.shouldSign.WIF),
|
||||||
f.shouldSign.sighashTypes || undefined,
|
f.shouldSign.sighashTypes || undefined,
|
||||||
)
|
)
|
||||||
|
@ -266,13 +266,13 @@ describe(`Psbt`, () => {
|
||||||
if (f.shouldThrow) {
|
if (f.shouldThrow) {
|
||||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbtThatShouldThrow.sign(
|
psbtThatShouldThrow.signAllInputs(
|
||||||
ECPair.fromWIF(f.shouldThrow.WIF),
|
ECPair.fromWIF(f.shouldThrow.WIF),
|
||||||
f.shouldThrow.sighashTypes || undefined,
|
f.shouldThrow.sighashTypes || undefined,
|
||||||
)
|
)
|
||||||
}, new RegExp('No inputs were signed'))
|
}, new RegExp('No inputs were signed'))
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbtThatShouldThrow.sign()
|
psbtThatShouldThrow.signAllInputs()
|
||||||
}, new RegExp('Need Signer to sign input'))
|
}, new RegExp('Need Signer to sign input'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -374,13 +374,13 @@ describe(`Psbt`, () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('signHD', () => {
|
describe('signAllInputsHD', () => {
|
||||||
fixtures.signInputHD.checks.forEach(f => {
|
fixtures.signInputHD.checks.forEach(f => {
|
||||||
it(f.description, () => {
|
it(f.description, () => {
|
||||||
if (f.shouldSign) {
|
if (f.shouldSign) {
|
||||||
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
const psbtThatShouldsign = Psbt.fromBase64(f.shouldSign.psbt)
|
||||||
assert.doesNotThrow(() => {
|
assert.doesNotThrow(() => {
|
||||||
psbtThatShouldsign.signHD(
|
psbtThatShouldsign.signAllInputsHD(
|
||||||
bip32.fromBase58(f.shouldSign.xprv),
|
bip32.fromBase58(f.shouldSign.xprv),
|
||||||
f.shouldSign.sighashTypes || undefined,
|
f.shouldSign.sighashTypes || undefined,
|
||||||
)
|
)
|
||||||
|
@ -390,13 +390,13 @@ describe(`Psbt`, () => {
|
||||||
if (f.shouldThrow) {
|
if (f.shouldThrow) {
|
||||||
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
const psbtThatShouldThrow = Psbt.fromBase64(f.shouldThrow.psbt)
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbtThatShouldThrow.signHD(
|
psbtThatShouldThrow.signAllInputsHD(
|
||||||
bip32.fromBase58(f.shouldThrow.xprv),
|
bip32.fromBase58(f.shouldThrow.xprv),
|
||||||
f.shouldThrow.sighashTypes || undefined,
|
f.shouldThrow.sighashTypes || undefined,
|
||||||
)
|
)
|
||||||
}, new RegExp('No inputs were signed'))
|
}, new RegExp('No inputs were signed'))
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbtThatShouldThrow.signHD()
|
psbtThatShouldThrow.signAllInputsHD()
|
||||||
}, new RegExp('Need HDSigner to sign input'))
|
}, new RegExp('Need HDSigner to sign input'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -505,7 +505,7 @@ describe(`Psbt`, () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('setSequence', () => {
|
describe('setInputSequence', () => {
|
||||||
it('Sets the sequence number for a given input', () => {
|
it('Sets the sequence number for a given input', () => {
|
||||||
const psbt = new Psbt()
|
const psbt = new Psbt()
|
||||||
psbt.addInput({
|
psbt.addInput({
|
||||||
|
@ -515,7 +515,7 @@ describe(`Psbt`, () => {
|
||||||
|
|
||||||
assert.strictEqual(psbt.inputCount, 1)
|
assert.strictEqual(psbt.inputCount, 1)
|
||||||
assert.strictEqual(psbt.__CACHE.__TX.ins[0].sequence, 0xffffffff)
|
assert.strictEqual(psbt.__CACHE.__TX.ins[0].sequence, 0xffffffff)
|
||||||
psbt.setSequence(0, 0)
|
psbt.setInputSequence(0, 0)
|
||||||
assert.strictEqual(psbt.__CACHE.__TX.ins[0].sequence, 0)
|
assert.strictEqual(psbt.__CACHE.__TX.ins[0].sequence, 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -527,7 +527,7 @@ describe(`Psbt`, () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.setSequence(1, 0)
|
psbt.setInputSequence(1, 0)
|
||||||
}, new RegExp('Input index too high'))
|
}, new RegExp('Input index too high'))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -539,7 +539,7 @@ describe(`Psbt`, () => {
|
||||||
const notAClone = Object.assign(new Psbt(), psbt) // references still active
|
const notAClone = Object.assign(new Psbt(), psbt) // references still active
|
||||||
const clone = psbt.clone()
|
const clone = psbt.clone()
|
||||||
|
|
||||||
assert.strictEqual(psbt.validateAllSignatures(), true)
|
assert.strictEqual(psbt.validateSignaturesOfAllInputs(), true)
|
||||||
|
|
||||||
assert.strictEqual(clone.toBase64(), psbt.toBase64())
|
assert.strictEqual(clone.toBase64(), psbt.toBase64())
|
||||||
assert.strictEqual(clone.toBase64(), notAClone.toBase64())
|
assert.strictEqual(clone.toBase64(), notAClone.toBase64())
|
||||||
|
@ -561,22 +561,22 @@ describe(`Psbt`, () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('validateSignatures', () => {
|
describe('validateSignaturesOfInput', () => {
|
||||||
const f = fixtures.validateSignatures
|
const f = fixtures.validateSignaturesOfInput
|
||||||
it('Correctly validates a signature', () => {
|
it('Correctly validates a signature', () => {
|
||||||
const psbt = Psbt.fromBase64(f.psbt)
|
const psbt = Psbt.fromBase64(f.psbt)
|
||||||
|
|
||||||
assert.strictEqual(psbt.validateSignatures(f.index), true)
|
assert.strictEqual(psbt.validateSignaturesOfInput(f.index), true)
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.validateSignatures(f.nonExistantIndex)
|
psbt.validateSignaturesOfInput(f.nonExistantIndex)
|
||||||
}, new RegExp('No signatures to validate'))
|
}, new RegExp('No signatures to validate'))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Correctly validates a signature against a pubkey', () => {
|
it('Correctly validates a signature against a pubkey', () => {
|
||||||
const psbt = Psbt.fromBase64(f.psbt)
|
const psbt = Psbt.fromBase64(f.psbt)
|
||||||
assert.strictEqual(psbt.validateSignatures(f.index, f.pubkey), true)
|
assert.strictEqual(psbt.validateSignaturesOfInput(f.index, f.pubkey), true)
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.validateSignatures(f.index, f.incorrectPubkey)
|
psbt.validateSignaturesOfInput(f.index, f.incorrectPubkey)
|
||||||
}, new RegExp('No signatures for this pubkey'))
|
}, new RegExp('No signatures for this pubkey'))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -623,7 +623,7 @@ describe(`Psbt`, () => {
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.setVersion(3)
|
psbt.setVersion(3)
|
||||||
}, new RegExp('Can not modify transaction, signatures exist.'))
|
}, new RegExp('Can not modify transaction, signatures exist.'))
|
||||||
psbt.validateSignatures(0)
|
psbt.validateSignaturesOfInput(0)
|
||||||
psbt.finalizeAllInputs()
|
psbt.finalizeAllInputs()
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
psbt.extractTransaction().toHex(),
|
psbt.extractTransaction().toHex(),
|
||||||
|
|
|
@ -58,7 +58,7 @@ const DEFAULT_OPTS: PsbtOpts = {
|
||||||
* data for updateOutput.
|
* data for updateOutput.
|
||||||
* For a list of what attributes should be what types. Check the bip174 library.
|
* For a list of what attributes should be what types. Check the bip174 library.
|
||||||
* Also, check the integration tests for some examples of usage.
|
* Also, check the integration tests for some examples of usage.
|
||||||
* Signer: There are a few methods. sign and signAsync, which will search all input
|
* Signer: There are a few methods. signAllInputs and signAsync, which will search all input
|
||||||
* information for your pubkey or pubkeyhash, and only sign inputs where it finds
|
* 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
|
* your info. Or you can explicitly sign a specific input with signInput and
|
||||||
* signInputAsync. For the async methods you can create a SignerAsync object
|
* signInputAsync. For the async methods you can create a SignerAsync object
|
||||||
|
@ -69,7 +69,7 @@ const DEFAULT_OPTS: PsbtOpts = {
|
||||||
* all sequences, version, locktime, etc. are the same before combining.
|
* all sequences, version, locktime, etc. are the same before combining.
|
||||||
* Input Finalizer: This role is fairly important. Not only does it need to construct
|
* 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.
|
* the input scriptSigs and witnesses, but it SHOULD verify the signatures etc.
|
||||||
* Before running `psbt.finalizeAllInputs()` please run `psbt.validateAllSignatures()`
|
* Before running `psbt.finalizeAllInputs()` please run `psbt.validateSignaturesOfAllInputs()`
|
||||||
* Running any finalize method will delete any data in the input(s) that are no longer
|
* 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.
|
* needed due to the finalized scripts containing the information.
|
||||||
* Transaction Extractor: This role will perform some checks before returning a
|
* Transaction Extractor: This role will perform some checks before returning a
|
||||||
|
@ -168,9 +168,9 @@ export class Psbt {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setSequence(inputIndex: number, sequence: number): this {
|
setInputSequence(inputIndex: number, sequence: number): this {
|
||||||
check32Bit(sequence);
|
check32Bit(sequence);
|
||||||
checkInputsForPartialSig(this.data.inputs, 'setSequence');
|
checkInputsForPartialSig(this.data.inputs, 'setInputSequence');
|
||||||
const c = this.__CACHE;
|
const c = this.__CACHE;
|
||||||
if (c.__TX.ins.length <= inputIndex) {
|
if (c.__TX.ins.length <= inputIndex) {
|
||||||
throw new Error('Input index too high');
|
throw new Error('Input index too high');
|
||||||
|
@ -291,15 +291,15 @@ export class Psbt {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
validateAllSignatures(): boolean {
|
validateSignaturesOfAllInputs(): boolean {
|
||||||
checkForInput(this.data.inputs, 0); // making sure we have at least one
|
checkForInput(this.data.inputs, 0); // making sure we have at least one
|
||||||
const results = range(this.data.inputs.length).map(idx =>
|
const results = range(this.data.inputs.length).map(idx =>
|
||||||
this.validateSignatures(idx),
|
this.validateSignaturesOfInput(idx),
|
||||||
);
|
);
|
||||||
return results.reduce((final, res) => res === true && final, true);
|
return results.reduce((final, res) => res === true && final, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
validateSignatures(inputIndex: number, pubkey?: Buffer): boolean {
|
validateSignaturesOfInput(inputIndex: number, pubkey?: Buffer): boolean {
|
||||||
const input = this.data.inputs[inputIndex];
|
const input = this.data.inputs[inputIndex];
|
||||||
const partialSig = (input || {}).partialSig;
|
const partialSig = (input || {}).partialSig;
|
||||||
if (!input || !partialSig || partialSig.length < 1)
|
if (!input || !partialSig || partialSig.length < 1)
|
||||||
|
@ -332,7 +332,7 @@ export class Psbt {
|
||||||
return results.every(res => res === true);
|
return results.every(res => res === true);
|
||||||
}
|
}
|
||||||
|
|
||||||
signHD(
|
signAllInputsHD(
|
||||||
hdKeyPair: HDSigner,
|
hdKeyPair: HDSigner,
|
||||||
sighashTypes: number[] = [Transaction.SIGHASH_ALL],
|
sighashTypes: number[] = [Transaction.SIGHASH_ALL],
|
||||||
): this {
|
): this {
|
||||||
|
@ -433,7 +433,7 @@ export class Psbt {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
sign(
|
signAllInputs(
|
||||||
keyPair: Signer,
|
keyPair: Signer,
|
||||||
sighashTypes: number[] = [Transaction.SIGHASH_ALL],
|
sighashTypes: number[] = [Transaction.SIGHASH_ALL],
|
||||||
): this {
|
): this {
|
||||||
|
@ -812,7 +812,7 @@ function checkInputsForPartialSig(inputs: PsbtInput[], action: string): void {
|
||||||
case Transaction.SIGHASH_SINGLE:
|
case Transaction.SIGHASH_SINGLE:
|
||||||
case Transaction.SIGHASH_NONE:
|
case Transaction.SIGHASH_NONE:
|
||||||
whitelist.push('addOutput');
|
whitelist.push('addOutput');
|
||||||
whitelist.push('setSequence');
|
whitelist.push('setInputSequence');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (whitelist.indexOf(action) === -1) {
|
if (whitelist.indexOf(action) === -1) {
|
||||||
|
|
14
types/psbt.d.ts
vendored
14
types/psbt.d.ts
vendored
|
@ -19,7 +19,7 @@ import { Transaction } from './transaction';
|
||||||
* data for updateOutput.
|
* data for updateOutput.
|
||||||
* For a list of what attributes should be what types. Check the bip174 library.
|
* For a list of what attributes should be what types. Check the bip174 library.
|
||||||
* Also, check the integration tests for some examples of usage.
|
* Also, check the integration tests for some examples of usage.
|
||||||
* Signer: There are a few methods. sign and signAsync, which will search all input
|
* Signer: There are a few methods. signAllInputs and signAsync, which will search all input
|
||||||
* information for your pubkey or pubkeyhash, and only sign inputs where it finds
|
* 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
|
* your info. Or you can explicitly sign a specific input with signInput and
|
||||||
* signInputAsync. For the async methods you can create a SignerAsync object
|
* signInputAsync. For the async methods you can create a SignerAsync object
|
||||||
|
@ -30,7 +30,7 @@ import { Transaction } from './transaction';
|
||||||
* all sequences, version, locktime, etc. are the same before combining.
|
* all sequences, version, locktime, etc. are the same before combining.
|
||||||
* Input Finalizer: This role is fairly important. Not only does it need to construct
|
* 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.
|
* the input scriptSigs and witnesses, but it SHOULD verify the signatures etc.
|
||||||
* Before running `psbt.finalizeAllInputs()` please run `psbt.validateAllSignatures()`
|
* Before running `psbt.finalizeAllInputs()` please run `psbt.validateSignaturesOfAllInputs()`
|
||||||
* Running any finalize method will delete any data in the input(s) that are no longer
|
* 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.
|
* needed due to the finalized scripts containing the information.
|
||||||
* Transaction Extractor: This role will perform some checks before returning a
|
* Transaction Extractor: This role will perform some checks before returning a
|
||||||
|
@ -50,7 +50,7 @@ export declare class Psbt {
|
||||||
setMaximumFeeRate(satoshiPerByte: number): void;
|
setMaximumFeeRate(satoshiPerByte: number): void;
|
||||||
setVersion(version: number): this;
|
setVersion(version: number): this;
|
||||||
setLocktime(locktime: number): this;
|
setLocktime(locktime: number): this;
|
||||||
setSequence(inputIndex: number, sequence: number): this;
|
setInputSequence(inputIndex: number, sequence: number): this;
|
||||||
addInputs(inputDatas: TransactionInput[]): this;
|
addInputs(inputDatas: TransactionInput[]): this;
|
||||||
addInput(inputData: TransactionInput): this;
|
addInput(inputData: TransactionInput): this;
|
||||||
addOutputs(outputDatas: TransactionOutput[]): this;
|
addOutputs(outputDatas: TransactionOutput[]): this;
|
||||||
|
@ -59,13 +59,13 @@ export declare class Psbt {
|
||||||
getFeeRate(): number;
|
getFeeRate(): number;
|
||||||
finalizeAllInputs(): this;
|
finalizeAllInputs(): this;
|
||||||
finalizeInput(inputIndex: number): this;
|
finalizeInput(inputIndex: number): this;
|
||||||
validateAllSignatures(): boolean;
|
validateSignaturesOfAllInputs(): boolean;
|
||||||
validateSignatures(inputIndex: number, pubkey?: Buffer): boolean;
|
validateSignaturesOfInput(inputIndex: number, pubkey?: Buffer): boolean;
|
||||||
signHD(hdKeyPair: HDSigner, sighashTypes?: number[]): this;
|
signAllInputsHD(hdKeyPair: HDSigner, sighashTypes?: number[]): this;
|
||||||
signHDAsync(hdKeyPair: HDSigner | HDSignerAsync, sighashTypes?: number[]): Promise<void>;
|
signHDAsync(hdKeyPair: HDSigner | HDSignerAsync, sighashTypes?: number[]): Promise<void>;
|
||||||
signInputHD(inputIndex: number, hdKeyPair: HDSigner, sighashTypes?: number[]): this;
|
signInputHD(inputIndex: number, hdKeyPair: HDSigner, sighashTypes?: number[]): this;
|
||||||
signInputHDAsync(inputIndex: number, hdKeyPair: HDSigner | HDSignerAsync, sighashTypes?: number[]): Promise<void>;
|
signInputHDAsync(inputIndex: number, hdKeyPair: HDSigner | HDSignerAsync, sighashTypes?: number[]): Promise<void>;
|
||||||
sign(keyPair: Signer, sighashTypes?: number[]): this;
|
signAllInputs(keyPair: Signer, sighashTypes?: number[]): this;
|
||||||
signAsync(keyPair: Signer | 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: Signer | SignerAsync, sighashTypes?: number[]): Promise<void>;
|
signInputAsync(inputIndex: number, keyPair: Signer | SignerAsync, sighashTypes?: number[]): Promise<void>;
|
||||||
|
|
Loading…
Add table
Reference in a new issue