Composition over inheritance
This commit is contained in:
parent
2f1609b918
commit
1feef9569c
6 changed files with 402 additions and 130 deletions
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -200,9 +200,9 @@
|
|||
}
|
||||
},
|
||||
"bip174": {
|
||||
"version": "0.0.14",
|
||||
"resolved": "https://registry.npmjs.org/bip174/-/bip174-0.0.14.tgz",
|
||||
"integrity": "sha512-v9cre0W4ZpAJS1v18WUJLE9yKdSZyenGpZBg7CXiZ5n35JPXganH92d4Yk8WXpRfbFZ4SMXTqKLEgpLPX1TmcA=="
|
||||
"version": "0.0.15",
|
||||
"resolved": "https://registry.npmjs.org/bip174/-/bip174-0.0.15.tgz",
|
||||
"integrity": "sha512-mK/s9p7i+PG7W2s2cAedNVk1NDZQn9wAoq1DlsS2+1zz5TXR3TRTzqRqm9BQtOXwbkxkhfLwlmsOjuiRdAYkdg=="
|
||||
},
|
||||
"bip32": {
|
||||
"version": "2.0.3",
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"dependencies": {
|
||||
"@types/node": "10.12.18",
|
||||
"bech32": "^1.1.2",
|
||||
"bip174": "0.0.14",
|
||||
"bip174": "0.0.15",
|
||||
"bip32": "^2.0.3",
|
||||
"bip66": "^1.1.0",
|
||||
"bitcoin-ops": "^1.4.0",
|
||||
|
|
199
src/psbt.js
199
src/psbt.js
|
@ -15,9 +15,9 @@ const DEFAULT_OPTS = {
|
|||
network: networks_1.bitcoin,
|
||||
maximumFeeRate: 5000,
|
||||
};
|
||||
class Psbt extends bip174_1.Psbt {
|
||||
constructor(opts = {}) {
|
||||
super();
|
||||
class Psbt {
|
||||
constructor(opts = {}, data = new bip174_1.Psbt()) {
|
||||
this.data = data;
|
||||
this.__CACHE = {
|
||||
__NON_WITNESS_UTXO_TX_CACHE: [],
|
||||
__NON_WITNESS_UTXO_BUF_CACHE: [],
|
||||
|
@ -27,11 +27,11 @@ class Psbt extends bip174_1.Psbt {
|
|||
// set defaults
|
||||
this.opts = Object.assign({}, DEFAULT_OPTS, opts);
|
||||
const c = this.__CACHE;
|
||||
c.__TX = transaction_1.Transaction.fromBuffer(this.globalMap.unsignedTx);
|
||||
this.setVersion(2);
|
||||
c.__TX = transaction_1.Transaction.fromBuffer(data.globalMap.unsignedTx);
|
||||
if (this.data.inputs.length === 0) this.setVersion(2);
|
||||
// set cache
|
||||
delete this.globalMap.unsignedTx;
|
||||
Object.defineProperty(this.globalMap, 'unsignedTx', {
|
||||
delete data.globalMap.unsignedTx;
|
||||
Object.defineProperty(data.globalMap, 'unsignedTx', {
|
||||
enumerable: true,
|
||||
get() {
|
||||
const buf = c.__TX_BUF_CACHE;
|
||||
|
@ -42,8 +42,8 @@ class Psbt extends bip174_1.Psbt {
|
|||
return c.__TX_BUF_CACHE;
|
||||
}
|
||||
},
|
||||
set(data) {
|
||||
c.__TX_BUF_CACHE = data;
|
||||
set(_data) {
|
||||
c.__TX_BUF_CACHE = _data;
|
||||
},
|
||||
});
|
||||
// Make data hidden when enumerating
|
||||
|
@ -55,29 +55,38 @@ class Psbt extends bip174_1.Psbt {
|
|||
dpew(this, '__CACHE', false, true);
|
||||
dpew(this, 'opts', false, true);
|
||||
}
|
||||
static fromTransaction(txBuf) {
|
||||
static fromTransaction(txBuf, opts = {}) {
|
||||
const tx = transaction_1.Transaction.fromBuffer(txBuf);
|
||||
checkTxEmpty(tx);
|
||||
const psbt = new this();
|
||||
const psbtBase = new bip174_1.Psbt();
|
||||
const psbt = new Psbt(opts, psbtBase);
|
||||
psbt.__CACHE.__TX = tx;
|
||||
checkTxForDupeIns(tx, psbt.__CACHE);
|
||||
let inputCount = tx.ins.length;
|
||||
let outputCount = tx.outs.length;
|
||||
while (inputCount > 0) {
|
||||
psbt.inputs.push({
|
||||
keyVals: [],
|
||||
psbtBase.inputs.push({
|
||||
unknownKeyVals: [],
|
||||
});
|
||||
inputCount--;
|
||||
}
|
||||
while (outputCount > 0) {
|
||||
psbt.outputs.push({
|
||||
keyVals: [],
|
||||
psbtBase.outputs.push({
|
||||
unknownKeyVals: [],
|
||||
});
|
||||
outputCount--;
|
||||
}
|
||||
return psbt;
|
||||
}
|
||||
static fromBuffer(buffer) {
|
||||
static fromBase64(data, opts = {}) {
|
||||
const buffer = Buffer.from(data, 'base64');
|
||||
return this.fromBuffer(buffer, opts);
|
||||
}
|
||||
static fromHex(data, opts = {}) {
|
||||
const buffer = Buffer.from(data, 'hex');
|
||||
return this.fromBuffer(buffer, opts);
|
||||
}
|
||||
static fromBuffer(buffer, opts = {}) {
|
||||
let tx;
|
||||
const txCountGetter = txBuf => {
|
||||
tx = transaction_1.Transaction.fromBuffer(txBuf);
|
||||
|
@ -87,17 +96,22 @@ class Psbt extends bip174_1.Psbt {
|
|||
outputCount: tx.outs.length,
|
||||
};
|
||||
};
|
||||
const psbt = super.fromBuffer(buffer, txCountGetter);
|
||||
const psbtBase = bip174_1.Psbt.fromBuffer(buffer, txCountGetter);
|
||||
const psbt = new Psbt(opts, psbtBase);
|
||||
psbt.__CACHE.__TX = tx;
|
||||
checkTxForDupeIns(tx, psbt.__CACHE);
|
||||
return psbt;
|
||||
}
|
||||
get inputCount() {
|
||||
return this.inputs.length;
|
||||
return this.data.inputs.length;
|
||||
}
|
||||
combine(...those) {
|
||||
this.data.combine(...those.map(o => o.data));
|
||||
return this;
|
||||
}
|
||||
clone() {
|
||||
// TODO: more efficient cloning
|
||||
const res = Psbt.fromBuffer(this.toBuffer());
|
||||
const res = Psbt.fromBuffer(this.data.toBuffer());
|
||||
res.opts = JSON.parse(JSON.stringify(this.opts));
|
||||
return res;
|
||||
}
|
||||
|
@ -107,7 +121,7 @@ class Psbt extends bip174_1.Psbt {
|
|||
}
|
||||
setVersion(version) {
|
||||
check32Bit(version);
|
||||
checkInputsForPartialSig(this.inputs, 'setVersion');
|
||||
checkInputsForPartialSig(this.data.inputs, 'setVersion');
|
||||
const c = this.__CACHE;
|
||||
c.__TX.version = version;
|
||||
c.__TX_BUF_CACHE = undefined;
|
||||
|
@ -116,7 +130,7 @@ class Psbt extends bip174_1.Psbt {
|
|||
}
|
||||
setLocktime(locktime) {
|
||||
check32Bit(locktime);
|
||||
checkInputsForPartialSig(this.inputs, 'setLocktime');
|
||||
checkInputsForPartialSig(this.data.inputs, 'setLocktime');
|
||||
const c = this.__CACHE;
|
||||
c.__TX.locktime = locktime;
|
||||
c.__TX_BUF_CACHE = undefined;
|
||||
|
@ -125,7 +139,7 @@ class Psbt extends bip174_1.Psbt {
|
|||
}
|
||||
setSequence(inputIndex, sequence) {
|
||||
check32Bit(sequence);
|
||||
checkInputsForPartialSig(this.inputs, 'setSequence');
|
||||
checkInputsForPartialSig(this.data.inputs, 'setSequence');
|
||||
const c = this.__CACHE;
|
||||
if (c.__TX.ins.length <= inputIndex) {
|
||||
throw new Error('Input index too high');
|
||||
|
@ -140,10 +154,15 @@ class Psbt extends bip174_1.Psbt {
|
|||
return this;
|
||||
}
|
||||
addInput(inputData) {
|
||||
checkInputsForPartialSig(this.inputs, 'addInput');
|
||||
checkInputsForPartialSig(this.data.inputs, 'addInput');
|
||||
const c = this.__CACHE;
|
||||
const inputAdder = getInputAdder(c);
|
||||
super.addInput(inputData, inputAdder);
|
||||
this.data.addInput(inputData, inputAdder);
|
||||
const inputIndex = this.data.inputs.length - 1;
|
||||
const input = this.data.inputs[inputIndex];
|
||||
if (input.nonWitnessUtxo) {
|
||||
addNonWitnessTxCache(this.__CACHE, input, inputIndex);
|
||||
}
|
||||
c.__FEE_RATE = undefined;
|
||||
c.__EXTRACTED_TX = undefined;
|
||||
return this;
|
||||
|
@ -153,7 +172,7 @@ class Psbt extends bip174_1.Psbt {
|
|||
return this;
|
||||
}
|
||||
addOutput(outputData) {
|
||||
checkInputsForPartialSig(this.inputs, 'addOutput');
|
||||
checkInputsForPartialSig(this.data.inputs, 'addOutput');
|
||||
const { address } = outputData;
|
||||
if (typeof address === 'string') {
|
||||
const { network } = this.opts;
|
||||
|
@ -162,30 +181,24 @@ class Psbt extends bip174_1.Psbt {
|
|||
}
|
||||
const c = this.__CACHE;
|
||||
const outputAdder = getOutputAdder(c);
|
||||
super.addOutput(outputData, true, outputAdder);
|
||||
this.data.addOutput(outputData, outputAdder, true);
|
||||
c.__FEE_RATE = undefined;
|
||||
c.__EXTRACTED_TX = undefined;
|
||||
return this;
|
||||
}
|
||||
addNonWitnessUtxoToInput(inputIndex, nonWitnessUtxo) {
|
||||
super.addNonWitnessUtxoToInput(inputIndex, nonWitnessUtxo);
|
||||
const input = this.inputs[inputIndex];
|
||||
addNonWitnessTxCache(this.__CACHE, input, inputIndex);
|
||||
return this;
|
||||
}
|
||||
extractTransaction(disableFeeCheck) {
|
||||
if (!this.inputs.every(isFinalized)) throw new Error('Not finalized');
|
||||
if (!this.data.inputs.every(isFinalized)) throw new Error('Not finalized');
|
||||
const c = this.__CACHE;
|
||||
if (!disableFeeCheck) {
|
||||
checkFees(this, c, this.opts);
|
||||
}
|
||||
if (c.__EXTRACTED_TX) return c.__EXTRACTED_TX;
|
||||
const tx = c.__TX.clone();
|
||||
inputFinalizeGetAmts(this.inputs, tx, c, true);
|
||||
inputFinalizeGetAmts(this.data.inputs, tx, c, true);
|
||||
return tx;
|
||||
}
|
||||
getFeeRate() {
|
||||
if (!this.inputs.every(isFinalized))
|
||||
if (!this.data.inputs.every(isFinalized))
|
||||
throw new Error('PSBT must be finalized to calculate fee rate');
|
||||
const c = this.__CACHE;
|
||||
if (c.__FEE_RATE) return c.__FEE_RATE;
|
||||
|
@ -197,16 +210,16 @@ class Psbt extends bip174_1.Psbt {
|
|||
} else {
|
||||
tx = c.__TX.clone();
|
||||
}
|
||||
inputFinalizeGetAmts(this.inputs, tx, c, mustFinalize);
|
||||
inputFinalizeGetAmts(this.data.inputs, tx, c, mustFinalize);
|
||||
return c.__FEE_RATE;
|
||||
}
|
||||
finalizeAllInputs() {
|
||||
utils_1.checkForInput(this.inputs, 0); // making sure we have at least one
|
||||
range(this.inputs.length).forEach(idx => this.finalizeInput(idx));
|
||||
utils_1.checkForInput(this.data.inputs, 0); // making sure we have at least one
|
||||
range(this.data.inputs.length).forEach(idx => this.finalizeInput(idx));
|
||||
return this;
|
||||
}
|
||||
finalizeInput(inputIndex) {
|
||||
const input = utils_1.checkForInput(this.inputs, inputIndex);
|
||||
const input = utils_1.checkForInput(this.data.inputs, inputIndex);
|
||||
const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput(
|
||||
inputIndex,
|
||||
input,
|
||||
|
@ -226,23 +239,23 @@ class Psbt extends bip174_1.Psbt {
|
|||
isP2WSH,
|
||||
);
|
||||
if (finalScriptSig)
|
||||
this.addFinalScriptSigToInput(inputIndex, finalScriptSig);
|
||||
this.data.addFinalScriptSigToInput(inputIndex, finalScriptSig);
|
||||
if (finalScriptWitness)
|
||||
this.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness);
|
||||
this.data.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness);
|
||||
if (!finalScriptSig && !finalScriptWitness)
|
||||
throw new Error(`Unknown error finalizing input #${inputIndex}`);
|
||||
this.clearFinalizedInput(inputIndex);
|
||||
this.data.clearFinalizedInput(inputIndex);
|
||||
return this;
|
||||
}
|
||||
validateAllSignatures() {
|
||||
utils_1.checkForInput(this.inputs, 0); // making sure we have at least one
|
||||
const results = range(this.inputs.length).map(idx =>
|
||||
utils_1.checkForInput(this.data.inputs, 0); // making sure we have at least one
|
||||
const results = range(this.data.inputs.length).map(idx =>
|
||||
this.validateSignatures(idx),
|
||||
);
|
||||
return results.reduce((final, res) => res === true && final, true);
|
||||
}
|
||||
validateSignatures(inputIndex, pubkey) {
|
||||
const input = this.inputs[inputIndex];
|
||||
const input = this.data.inputs[inputIndex];
|
||||
const partialSig = (input || {}).partialSig;
|
||||
if (!input || !partialSig || partialSig.length < 1)
|
||||
throw new Error('No signatures to validate');
|
||||
|
@ -280,7 +293,7 @@ class Psbt extends bip174_1.Psbt {
|
|||
// as input information is added, then eventually
|
||||
// optimize this method.
|
||||
const results = [];
|
||||
for (const i of range(this.inputs.length)) {
|
||||
for (const i of range(this.data.inputs.length)) {
|
||||
try {
|
||||
this.signInput(i, keyPair, sighashTypes);
|
||||
results.push(true);
|
||||
|
@ -302,7 +315,7 @@ class Psbt extends bip174_1.Psbt {
|
|||
// optimize this method.
|
||||
const results = [];
|
||||
const promises = [];
|
||||
for (const [i] of this.inputs.entries()) {
|
||||
for (const [i] of this.data.inputs.entries()) {
|
||||
promises.push(
|
||||
this.signInputAsync(i, keyPair, sighashTypes).then(
|
||||
() => {
|
||||
|
@ -330,7 +343,7 @@ class Psbt extends bip174_1.Psbt {
|
|||
if (!keyPair || !keyPair.publicKey)
|
||||
throw new Error('Need Signer to sign input');
|
||||
const { hash, sighashType } = getHashAndSighashType(
|
||||
this.inputs,
|
||||
this.data.inputs,
|
||||
inputIndex,
|
||||
keyPair.publicKey,
|
||||
this.__CACHE,
|
||||
|
@ -340,7 +353,8 @@ class Psbt extends bip174_1.Psbt {
|
|||
pubkey: keyPair.publicKey,
|
||||
signature: bscript.signature.encode(keyPair.sign(hash), sighashType),
|
||||
};
|
||||
return this.addPartialSigToInput(inputIndex, partialSig);
|
||||
this.data.addPartialSigToInput(inputIndex, partialSig);
|
||||
return this;
|
||||
}
|
||||
signInputAsync(
|
||||
inputIndex,
|
||||
|
@ -351,7 +365,7 @@ class Psbt extends bip174_1.Psbt {
|
|||
if (!keyPair || !keyPair.publicKey)
|
||||
return reject(new Error('Need Signer to sign input'));
|
||||
const { hash, sighashType } = getHashAndSighashType(
|
||||
this.inputs,
|
||||
this.data.inputs,
|
||||
inputIndex,
|
||||
keyPair.publicKey,
|
||||
this.__CACHE,
|
||||
|
@ -362,11 +376,94 @@ class Psbt extends bip174_1.Psbt {
|
|||
pubkey: keyPair.publicKey,
|
||||
signature: bscript.signature.encode(signature, sighashType),
|
||||
};
|
||||
this.addPartialSigToInput(inputIndex, partialSig);
|
||||
this.data.addPartialSigToInput(inputIndex, partialSig);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
toBuffer() {
|
||||
return this.data.toBuffer();
|
||||
}
|
||||
toHex() {
|
||||
return this.data.toHex();
|
||||
}
|
||||
toBase64() {
|
||||
return this.data.toBase64();
|
||||
}
|
||||
addGlobalXpubToGlobal(globalXpub) {
|
||||
this.data.addGlobalXpubToGlobal(globalXpub);
|
||||
return this;
|
||||
}
|
||||
addNonWitnessUtxoToInput(inputIndex, nonWitnessUtxo) {
|
||||
this.data.addNonWitnessUtxoToInput(inputIndex, nonWitnessUtxo);
|
||||
const input = this.data.inputs[inputIndex];
|
||||
addNonWitnessTxCache(this.__CACHE, input, inputIndex);
|
||||
return this;
|
||||
}
|
||||
addWitnessUtxoToInput(inputIndex, witnessUtxo) {
|
||||
this.data.addWitnessUtxoToInput(inputIndex, witnessUtxo);
|
||||
return this;
|
||||
}
|
||||
addPartialSigToInput(inputIndex, partialSig) {
|
||||
this.data.addPartialSigToInput(inputIndex, partialSig);
|
||||
return this;
|
||||
}
|
||||
addSighashTypeToInput(inputIndex, sighashType) {
|
||||
this.data.addSighashTypeToInput(inputIndex, sighashType);
|
||||
return this;
|
||||
}
|
||||
addRedeemScriptToInput(inputIndex, redeemScript) {
|
||||
this.data.addRedeemScriptToInput(inputIndex, redeemScript);
|
||||
return this;
|
||||
}
|
||||
addWitnessScriptToInput(inputIndex, witnessScript) {
|
||||
this.data.addWitnessScriptToInput(inputIndex, witnessScript);
|
||||
return this;
|
||||
}
|
||||
addBip32DerivationToInput(inputIndex, bip32Derivation) {
|
||||
this.data.addBip32DerivationToInput(inputIndex, bip32Derivation);
|
||||
return this;
|
||||
}
|
||||
addFinalScriptSigToInput(inputIndex, finalScriptSig) {
|
||||
this.data.addFinalScriptSigToInput(inputIndex, finalScriptSig);
|
||||
return this;
|
||||
}
|
||||
addFinalScriptWitnessToInput(inputIndex, finalScriptWitness) {
|
||||
this.data.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness);
|
||||
return this;
|
||||
}
|
||||
addPorCommitmentToInput(inputIndex, porCommitment) {
|
||||
this.data.addPorCommitmentToInput(inputIndex, porCommitment);
|
||||
return this;
|
||||
}
|
||||
addRedeemScriptToOutput(outputIndex, redeemScript) {
|
||||
this.data.addRedeemScriptToOutput(outputIndex, redeemScript);
|
||||
return this;
|
||||
}
|
||||
addWitnessScriptToOutput(outputIndex, witnessScript) {
|
||||
this.data.addWitnessScriptToOutput(outputIndex, witnessScript);
|
||||
return this;
|
||||
}
|
||||
addBip32DerivationToOutput(outputIndex, bip32Derivation) {
|
||||
this.data.addBip32DerivationToOutput(outputIndex, bip32Derivation);
|
||||
return this;
|
||||
}
|
||||
addUnknownKeyValToGlobal(keyVal) {
|
||||
this.data.addUnknownKeyValToGlobal(keyVal);
|
||||
return this;
|
||||
}
|
||||
addUnknownKeyValToInput(inputIndex, keyVal) {
|
||||
this.data.addUnknownKeyValToInput(inputIndex, keyVal);
|
||||
return this;
|
||||
}
|
||||
addUnknownKeyValToOutput(outputIndex, keyVal) {
|
||||
this.data.addUnknownKeyValToOutput(outputIndex, keyVal);
|
||||
return this;
|
||||
}
|
||||
clearFinalizedInput(inputIndex) {
|
||||
this.data.clearFinalizedInput(inputIndex);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
exports.Psbt = Psbt;
|
||||
function canFinalize(input, script, scriptType) {
|
||||
|
|
12
test/psbt.js
12
test/psbt.js
|
@ -143,8 +143,8 @@ describe(`Psbt`, () => {
|
|||
assert.strictEqual(transaction1, f.transaction)
|
||||
|
||||
const psbt3 = Psbt.fromBase64(f.psbt)
|
||||
delete psbt3.inputs[0].finalScriptSig
|
||||
delete psbt3.inputs[0].finalScriptWitness
|
||||
delete psbt3.data.inputs[0].finalScriptSig
|
||||
delete psbt3.data.inputs[0].finalScriptWitness
|
||||
assert.throws(() => {
|
||||
psbt3.extractTransaction()
|
||||
}, new RegExp('Not finalized'))
|
||||
|
@ -414,7 +414,7 @@ describe(`Psbt`, () => {
|
|||
assert.strictEqual(clone.toBase64(), psbt.toBase64())
|
||||
assert.strictEqual(clone.toBase64(), notAClone.toBase64())
|
||||
assert.strictEqual(psbt.toBase64(), notAClone.toBase64())
|
||||
psbt.globalMap.unsignedTx[3] = 0xff
|
||||
psbt.data.globalMap.unsignedTx[3] = 0xff
|
||||
assert.notStrictEqual(clone.toBase64(), psbt.toBase64())
|
||||
assert.notStrictEqual(clone.toBase64(), notAClone.toBase64())
|
||||
assert.strictEqual(psbt.toBase64(), notAClone.toBase64())
|
||||
|
@ -542,14 +542,14 @@ describe(`Psbt`, () => {
|
|||
|
||||
// Cache is populated
|
||||
psbt.addNonWitnessUtxoToInput(index, f.nonWitnessUtxo)
|
||||
const value = psbt.inputs[index].nonWitnessUtxo
|
||||
const value = psbt.data.inputs[index].nonWitnessUtxo
|
||||
assert.ok(psbt.__CACHE.__NON_WITNESS_UTXO_BUF_CACHE[index].equals(value))
|
||||
assert.ok(psbt.__CACHE.__NON_WITNESS_UTXO_BUF_CACHE[index].equals(f.nonWitnessUtxo))
|
||||
|
||||
// Cache is rebuilt from internal transaction object when cleared
|
||||
psbt.inputs[index].nonWitnessUtxo = Buffer.from([1,2,3])
|
||||
psbt.data.inputs[index].nonWitnessUtxo = Buffer.from([1,2,3])
|
||||
psbt.__CACHE.__NON_WITNESS_UTXO_BUF_CACHE[index] = undefined
|
||||
assert.ok(psbt.inputs[index].nonWitnessUtxo.equals(value))
|
||||
assert.ok(psbt.data.inputs[index].nonWitnessUtxo.equals(value))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
277
ts_src/psbt.ts
277
ts_src/psbt.ts
|
@ -1,11 +1,21 @@
|
|||
import { Psbt as PsbtBase } from 'bip174';
|
||||
import * as varuint from 'bip174/src/lib/converter/varint';
|
||||
import {
|
||||
Bip32Derivation,
|
||||
FinalScriptSig,
|
||||
FinalScriptWitness,
|
||||
GlobalXpub,
|
||||
KeyValue,
|
||||
NonWitnessUtxo,
|
||||
PartialSig,
|
||||
PorCommitment,
|
||||
PsbtInput,
|
||||
RedeemScript,
|
||||
SighashType,
|
||||
TransactionInput,
|
||||
TransactionOutput,
|
||||
WitnessScript,
|
||||
WitnessUtxo,
|
||||
} from 'bip174/src/lib/interfaces';
|
||||
import { checkForInput } from 'bip174/src/lib/utils';
|
||||
import { toOutputScript } from './address';
|
||||
|
@ -26,37 +36,42 @@ const DEFAULT_OPTS: PsbtOpts = {
|
|||
maximumFeeRate: 5000, // satoshi per byte
|
||||
};
|
||||
|
||||
export class Psbt extends PsbtBase {
|
||||
static fromTransaction<T extends typeof PsbtBase>(
|
||||
this: T,
|
||||
txBuf: Buffer,
|
||||
): InstanceType<T> {
|
||||
export class Psbt {
|
||||
static fromTransaction(txBuf: Buffer, opts: PsbtOptsOptional = {}): Psbt {
|
||||
const tx = Transaction.fromBuffer(txBuf);
|
||||
checkTxEmpty(tx);
|
||||
const psbt = new this() as Psbt;
|
||||
const psbtBase = new PsbtBase();
|
||||
const psbt = new Psbt(opts, psbtBase);
|
||||
psbt.__CACHE.__TX = tx;
|
||||
checkTxForDupeIns(tx, psbt.__CACHE);
|
||||
let inputCount = tx.ins.length;
|
||||
let outputCount = tx.outs.length;
|
||||
while (inputCount > 0) {
|
||||
psbt.inputs.push({
|
||||
keyVals: [],
|
||||
psbtBase.inputs.push({
|
||||
unknownKeyVals: [],
|
||||
});
|
||||
inputCount--;
|
||||
}
|
||||
while (outputCount > 0) {
|
||||
psbt.outputs.push({
|
||||
keyVals: [],
|
||||
psbtBase.outputs.push({
|
||||
unknownKeyVals: [],
|
||||
});
|
||||
outputCount--;
|
||||
}
|
||||
return psbt as InstanceType<T>;
|
||||
return psbt;
|
||||
}
|
||||
|
||||
static fromBuffer<T extends typeof PsbtBase>(
|
||||
this: T,
|
||||
buffer: Buffer,
|
||||
): InstanceType<T> {
|
||||
static fromBase64(data: string, opts: PsbtOptsOptional = {}): Psbt {
|
||||
const buffer = Buffer.from(data, 'base64');
|
||||
return this.fromBuffer(buffer, opts);
|
||||
}
|
||||
|
||||
static fromHex(data: string, opts: PsbtOptsOptional = {}): Psbt {
|
||||
const buffer = Buffer.from(data, 'hex');
|
||||
return this.fromBuffer(buffer, opts);
|
||||
}
|
||||
|
||||
static fromBuffer(buffer: Buffer, opts: PsbtOptsOptional = {}): Psbt {
|
||||
let tx: Transaction | undefined;
|
||||
const txCountGetter = (
|
||||
txBuf: Buffer,
|
||||
|
@ -71,10 +86,11 @@ export class Psbt extends PsbtBase {
|
|||
outputCount: tx.outs.length,
|
||||
};
|
||||
};
|
||||
const psbt = super.fromBuffer(buffer, txCountGetter) as Psbt;
|
||||
const psbtBase = PsbtBase.fromBuffer(buffer, txCountGetter);
|
||||
const psbt = new Psbt(opts, psbtBase);
|
||||
psbt.__CACHE.__TX = tx!;
|
||||
checkTxForDupeIns(tx!, psbt.__CACHE);
|
||||
return psbt as InstanceType<T>;
|
||||
return psbt;
|
||||
}
|
||||
|
||||
private __CACHE: PsbtCache = {
|
||||
|
@ -85,17 +101,19 @@ export class Psbt extends PsbtBase {
|
|||
};
|
||||
private opts: PsbtOpts;
|
||||
|
||||
constructor(opts: PsbtOptsOptional = {}) {
|
||||
super();
|
||||
constructor(
|
||||
opts: PsbtOptsOptional = {},
|
||||
readonly data: PsbtBase = new PsbtBase(),
|
||||
) {
|
||||
// set defaults
|
||||
this.opts = Object.assign({}, DEFAULT_OPTS, opts);
|
||||
const c = this.__CACHE;
|
||||
c.__TX = Transaction.fromBuffer(this.globalMap.unsignedTx!);
|
||||
this.setVersion(2);
|
||||
c.__TX = Transaction.fromBuffer(data.globalMap.unsignedTx!);
|
||||
if (this.data.inputs.length === 0) this.setVersion(2);
|
||||
|
||||
// set cache
|
||||
delete this.globalMap.unsignedTx;
|
||||
Object.defineProperty(this.globalMap, 'unsignedTx', {
|
||||
delete data.globalMap.unsignedTx;
|
||||
Object.defineProperty(data.globalMap, 'unsignedTx', {
|
||||
enumerable: true,
|
||||
get(): Buffer {
|
||||
const buf = c.__TX_BUF_CACHE;
|
||||
|
@ -106,8 +124,8 @@ export class Psbt extends PsbtBase {
|
|||
return c.__TX_BUF_CACHE;
|
||||
}
|
||||
},
|
||||
set(data: Buffer): void {
|
||||
c.__TX_BUF_CACHE = data;
|
||||
set(_data: Buffer): void {
|
||||
c.__TX_BUF_CACHE = _data;
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -127,12 +145,17 @@ export class Psbt extends PsbtBase {
|
|||
}
|
||||
|
||||
get inputCount(): number {
|
||||
return this.inputs.length;
|
||||
return this.data.inputs.length;
|
||||
}
|
||||
|
||||
combine(...those: Psbt[]): this {
|
||||
this.data.combine(...those.map(o => o.data));
|
||||
return this;
|
||||
}
|
||||
|
||||
clone(): Psbt {
|
||||
// TODO: more efficient cloning
|
||||
const res = Psbt.fromBuffer(this.toBuffer());
|
||||
const res = Psbt.fromBuffer(this.data.toBuffer());
|
||||
res.opts = JSON.parse(JSON.stringify(this.opts));
|
||||
return res;
|
||||
}
|
||||
|
@ -144,7 +167,7 @@ export class Psbt extends PsbtBase {
|
|||
|
||||
setVersion(version: number): this {
|
||||
check32Bit(version);
|
||||
checkInputsForPartialSig(this.inputs, 'setVersion');
|
||||
checkInputsForPartialSig(this.data.inputs, 'setVersion');
|
||||
const c = this.__CACHE;
|
||||
c.__TX.version = version;
|
||||
c.__TX_BUF_CACHE = undefined;
|
||||
|
@ -154,7 +177,7 @@ export class Psbt extends PsbtBase {
|
|||
|
||||
setLocktime(locktime: number): this {
|
||||
check32Bit(locktime);
|
||||
checkInputsForPartialSig(this.inputs, 'setLocktime');
|
||||
checkInputsForPartialSig(this.data.inputs, 'setLocktime');
|
||||
const c = this.__CACHE;
|
||||
c.__TX.locktime = locktime;
|
||||
c.__TX_BUF_CACHE = undefined;
|
||||
|
@ -164,7 +187,7 @@ export class Psbt extends PsbtBase {
|
|||
|
||||
setSequence(inputIndex: number, sequence: number): this {
|
||||
check32Bit(sequence);
|
||||
checkInputsForPartialSig(this.inputs, 'setSequence');
|
||||
checkInputsForPartialSig(this.data.inputs, 'setSequence');
|
||||
const c = this.__CACHE;
|
||||
if (c.__TX.ins.length <= inputIndex) {
|
||||
throw new Error('Input index too high');
|
||||
|
@ -181,10 +204,16 @@ export class Psbt extends PsbtBase {
|
|||
}
|
||||
|
||||
addInput(inputData: TransactionInput): this {
|
||||
checkInputsForPartialSig(this.inputs, 'addInput');
|
||||
checkInputsForPartialSig(this.data.inputs, 'addInput');
|
||||
const c = this.__CACHE;
|
||||
const inputAdder = getInputAdder(c);
|
||||
super.addInput(inputData, inputAdder);
|
||||
this.data.addInput(inputData, inputAdder);
|
||||
|
||||
const inputIndex = this.data.inputs.length - 1;
|
||||
const input = this.data.inputs[inputIndex];
|
||||
if (input.nonWitnessUtxo) {
|
||||
addNonWitnessTxCache(this.__CACHE, input, inputIndex);
|
||||
}
|
||||
c.__FEE_RATE = undefined;
|
||||
c.__EXTRACTED_TX = undefined;
|
||||
return this;
|
||||
|
@ -196,7 +225,7 @@ export class Psbt extends PsbtBase {
|
|||
}
|
||||
|
||||
addOutput(outputData: TransactionOutput): this {
|
||||
checkInputsForPartialSig(this.inputs, 'addOutput');
|
||||
checkInputsForPartialSig(this.data.inputs, 'addOutput');
|
||||
const { address } = outputData as any;
|
||||
if (typeof address === 'string') {
|
||||
const { network } = this.opts;
|
||||
|
@ -205,36 +234,26 @@ export class Psbt extends PsbtBase {
|
|||
}
|
||||
const c = this.__CACHE;
|
||||
const outputAdder = getOutputAdder(c);
|
||||
super.addOutput(outputData, true, outputAdder);
|
||||
this.data.addOutput(outputData, outputAdder, true);
|
||||
c.__FEE_RATE = undefined;
|
||||
c.__EXTRACTED_TX = undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
addNonWitnessUtxoToInput(
|
||||
inputIndex: number,
|
||||
nonWitnessUtxo: NonWitnessUtxo,
|
||||
): this {
|
||||
super.addNonWitnessUtxoToInput(inputIndex, nonWitnessUtxo);
|
||||
const input = this.inputs[inputIndex];
|
||||
addNonWitnessTxCache(this.__CACHE, input, inputIndex);
|
||||
return this;
|
||||
}
|
||||
|
||||
extractTransaction(disableFeeCheck?: boolean): Transaction {
|
||||
if (!this.inputs.every(isFinalized)) throw new Error('Not finalized');
|
||||
if (!this.data.inputs.every(isFinalized)) throw new Error('Not finalized');
|
||||
const c = this.__CACHE;
|
||||
if (!disableFeeCheck) {
|
||||
checkFees(this, c, this.opts);
|
||||
}
|
||||
if (c.__EXTRACTED_TX) return c.__EXTRACTED_TX;
|
||||
const tx = c.__TX.clone();
|
||||
inputFinalizeGetAmts(this.inputs, tx, c, true);
|
||||
inputFinalizeGetAmts(this.data.inputs, tx, c, true);
|
||||
return tx;
|
||||
}
|
||||
|
||||
getFeeRate(): number {
|
||||
if (!this.inputs.every(isFinalized))
|
||||
if (!this.data.inputs.every(isFinalized))
|
||||
throw new Error('PSBT must be finalized to calculate fee rate');
|
||||
const c = this.__CACHE;
|
||||
if (c.__FEE_RATE) return c.__FEE_RATE;
|
||||
|
@ -246,18 +265,18 @@ export class Psbt extends PsbtBase {
|
|||
} else {
|
||||
tx = c.__TX.clone();
|
||||
}
|
||||
inputFinalizeGetAmts(this.inputs, tx, c, mustFinalize);
|
||||
inputFinalizeGetAmts(this.data.inputs, tx, c, mustFinalize);
|
||||
return c.__FEE_RATE!;
|
||||
}
|
||||
|
||||
finalizeAllInputs(): this {
|
||||
checkForInput(this.inputs, 0); // making sure we have at least one
|
||||
range(this.inputs.length).forEach(idx => this.finalizeInput(idx));
|
||||
checkForInput(this.data.inputs, 0); // making sure we have at least one
|
||||
range(this.data.inputs.length).forEach(idx => this.finalizeInput(idx));
|
||||
return this;
|
||||
}
|
||||
|
||||
finalizeInput(inputIndex: number): this {
|
||||
const input = checkForInput(this.inputs, inputIndex);
|
||||
const input = checkForInput(this.data.inputs, inputIndex);
|
||||
const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput(
|
||||
inputIndex,
|
||||
input,
|
||||
|
@ -281,26 +300,26 @@ export class Psbt extends PsbtBase {
|
|||
);
|
||||
|
||||
if (finalScriptSig)
|
||||
this.addFinalScriptSigToInput(inputIndex, finalScriptSig);
|
||||
this.data.addFinalScriptSigToInput(inputIndex, finalScriptSig);
|
||||
if (finalScriptWitness)
|
||||
this.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness);
|
||||
this.data.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness);
|
||||
if (!finalScriptSig && !finalScriptWitness)
|
||||
throw new Error(`Unknown error finalizing input #${inputIndex}`);
|
||||
|
||||
this.clearFinalizedInput(inputIndex);
|
||||
this.data.clearFinalizedInput(inputIndex);
|
||||
return this;
|
||||
}
|
||||
|
||||
validateAllSignatures(): boolean {
|
||||
checkForInput(this.inputs, 0); // making sure we have at least one
|
||||
const results = range(this.inputs.length).map(idx =>
|
||||
checkForInput(this.data.inputs, 0); // making sure we have at least one
|
||||
const results = range(this.data.inputs.length).map(idx =>
|
||||
this.validateSignatures(idx),
|
||||
);
|
||||
return results.reduce((final, res) => res === true && final, true);
|
||||
}
|
||||
|
||||
validateSignatures(inputIndex: number, pubkey?: Buffer): boolean {
|
||||
const input = this.inputs[inputIndex];
|
||||
const input = this.data.inputs[inputIndex];
|
||||
const partialSig = (input || {}).partialSig;
|
||||
if (!input || !partialSig || partialSig.length < 1)
|
||||
throw new Error('No signatures to validate');
|
||||
|
@ -343,7 +362,7 @@ export class Psbt extends PsbtBase {
|
|||
// as input information is added, then eventually
|
||||
// optimize this method.
|
||||
const results: boolean[] = [];
|
||||
for (const i of range(this.inputs.length)) {
|
||||
for (const i of range(this.data.inputs.length)) {
|
||||
try {
|
||||
this.signInput(i, keyPair, sighashTypes);
|
||||
results.push(true);
|
||||
|
@ -371,7 +390,7 @@ export class Psbt extends PsbtBase {
|
|||
// optimize this method.
|
||||
const results: boolean[] = [];
|
||||
const promises: Array<Promise<void>> = [];
|
||||
for (const [i] of this.inputs.entries()) {
|
||||
for (const [i] of this.data.inputs.entries()) {
|
||||
promises.push(
|
||||
this.signInputAsync(i, keyPair, sighashTypes).then(
|
||||
() => {
|
||||
|
@ -401,7 +420,7 @@ export class Psbt extends PsbtBase {
|
|||
if (!keyPair || !keyPair.publicKey)
|
||||
throw new Error('Need Signer to sign input');
|
||||
const { hash, sighashType } = getHashAndSighashType(
|
||||
this.inputs,
|
||||
this.data.inputs,
|
||||
inputIndex,
|
||||
keyPair.publicKey,
|
||||
this.__CACHE,
|
||||
|
@ -413,7 +432,8 @@ export class Psbt extends PsbtBase {
|
|||
signature: bscript.signature.encode(keyPair.sign(hash), sighashType),
|
||||
};
|
||||
|
||||
return this.addPartialSigToInput(inputIndex, partialSig);
|
||||
this.data.addPartialSigToInput(inputIndex, partialSig);
|
||||
return this;
|
||||
}
|
||||
|
||||
signInputAsync(
|
||||
|
@ -426,7 +446,7 @@ export class Psbt extends PsbtBase {
|
|||
if (!keyPair || !keyPair.publicKey)
|
||||
return reject(new Error('Need Signer to sign input'));
|
||||
const { hash, sighashType } = getHashAndSighashType(
|
||||
this.inputs,
|
||||
this.data.inputs,
|
||||
inputIndex,
|
||||
keyPair.publicKey,
|
||||
this.__CACHE,
|
||||
|
@ -439,12 +459,143 @@ export class Psbt extends PsbtBase {
|
|||
signature: bscript.signature.encode(signature, sighashType),
|
||||
};
|
||||
|
||||
this.addPartialSigToInput(inputIndex, partialSig);
|
||||
this.data.addPartialSigToInput(inputIndex, partialSig);
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
toBuffer(): Buffer {
|
||||
return this.data.toBuffer();
|
||||
}
|
||||
|
||||
toHex(): string {
|
||||
return this.data.toHex();
|
||||
}
|
||||
|
||||
toBase64(): string {
|
||||
return this.data.toBase64();
|
||||
}
|
||||
|
||||
addGlobalXpubToGlobal(globalXpub: GlobalXpub): this {
|
||||
this.data.addGlobalXpubToGlobal(globalXpub);
|
||||
return this;
|
||||
}
|
||||
|
||||
addNonWitnessUtxoToInput(
|
||||
inputIndex: number,
|
||||
nonWitnessUtxo: NonWitnessUtxo,
|
||||
): this {
|
||||
this.data.addNonWitnessUtxoToInput(inputIndex, nonWitnessUtxo);
|
||||
const input = this.data.inputs[inputIndex];
|
||||
addNonWitnessTxCache(this.__CACHE, input, inputIndex);
|
||||
return this;
|
||||
}
|
||||
|
||||
addWitnessUtxoToInput(inputIndex: number, witnessUtxo: WitnessUtxo): this {
|
||||
this.data.addWitnessUtxoToInput(inputIndex, witnessUtxo);
|
||||
return this;
|
||||
}
|
||||
|
||||
addPartialSigToInput(inputIndex: number, partialSig: PartialSig): this {
|
||||
this.data.addPartialSigToInput(inputIndex, partialSig);
|
||||
return this;
|
||||
}
|
||||
|
||||
addSighashTypeToInput(inputIndex: number, sighashType: SighashType): this {
|
||||
this.data.addSighashTypeToInput(inputIndex, sighashType);
|
||||
return this;
|
||||
}
|
||||
|
||||
addRedeemScriptToInput(inputIndex: number, redeemScript: RedeemScript): this {
|
||||
this.data.addRedeemScriptToInput(inputIndex, redeemScript);
|
||||
return this;
|
||||
}
|
||||
|
||||
addWitnessScriptToInput(
|
||||
inputIndex: number,
|
||||
witnessScript: WitnessScript,
|
||||
): this {
|
||||
this.data.addWitnessScriptToInput(inputIndex, witnessScript);
|
||||
return this;
|
||||
}
|
||||
|
||||
addBip32DerivationToInput(
|
||||
inputIndex: number,
|
||||
bip32Derivation: Bip32Derivation,
|
||||
): this {
|
||||
this.data.addBip32DerivationToInput(inputIndex, bip32Derivation);
|
||||
return this;
|
||||
}
|
||||
|
||||
addFinalScriptSigToInput(
|
||||
inputIndex: number,
|
||||
finalScriptSig: FinalScriptSig,
|
||||
): this {
|
||||
this.data.addFinalScriptSigToInput(inputIndex, finalScriptSig);
|
||||
return this;
|
||||
}
|
||||
|
||||
addFinalScriptWitnessToInput(
|
||||
inputIndex: number,
|
||||
finalScriptWitness: FinalScriptWitness,
|
||||
): this {
|
||||
this.data.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness);
|
||||
return this;
|
||||
}
|
||||
|
||||
addPorCommitmentToInput(
|
||||
inputIndex: number,
|
||||
porCommitment: PorCommitment,
|
||||
): this {
|
||||
this.data.addPorCommitmentToInput(inputIndex, porCommitment);
|
||||
return this;
|
||||
}
|
||||
|
||||
addRedeemScriptToOutput(
|
||||
outputIndex: number,
|
||||
redeemScript: RedeemScript,
|
||||
): this {
|
||||
this.data.addRedeemScriptToOutput(outputIndex, redeemScript);
|
||||
return this;
|
||||
}
|
||||
|
||||
addWitnessScriptToOutput(
|
||||
outputIndex: number,
|
||||
witnessScript: WitnessScript,
|
||||
): this {
|
||||
this.data.addWitnessScriptToOutput(outputIndex, witnessScript);
|
||||
return this;
|
||||
}
|
||||
|
||||
addBip32DerivationToOutput(
|
||||
outputIndex: number,
|
||||
bip32Derivation: Bip32Derivation,
|
||||
): this {
|
||||
this.data.addBip32DerivationToOutput(outputIndex, bip32Derivation);
|
||||
return this;
|
||||
}
|
||||
|
||||
addUnknownKeyValToGlobal(keyVal: KeyValue): this {
|
||||
this.data.addUnknownKeyValToGlobal(keyVal);
|
||||
return this;
|
||||
}
|
||||
|
||||
addUnknownKeyValToInput(inputIndex: number, keyVal: KeyValue): this {
|
||||
this.data.addUnknownKeyValToInput(inputIndex, keyVal);
|
||||
return this;
|
||||
}
|
||||
|
||||
addUnknownKeyValToOutput(outputIndex: number, keyVal: KeyValue): this {
|
||||
this.data.addUnknownKeyValToOutput(outputIndex, keyVal);
|
||||
return this;
|
||||
}
|
||||
|
||||
clearFinalizedInput(inputIndex: number): this {
|
||||
this.data.clearFinalizedInput(inputIndex);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
interface PsbtCache {
|
||||
|
|
36
types/psbt.d.ts
vendored
36
types/psbt.d.ts
vendored
|
@ -1,16 +1,20 @@
|
|||
/// <reference types="node" />
|
||||
import { Psbt as PsbtBase } from 'bip174';
|
||||
import { NonWitnessUtxo, TransactionInput, TransactionOutput } from 'bip174/src/lib/interfaces';
|
||||
import { Bip32Derivation, FinalScriptSig, FinalScriptWitness, GlobalXpub, KeyValue, NonWitnessUtxo, PartialSig, PorCommitment, RedeemScript, SighashType, TransactionInput, TransactionOutput, WitnessScript, WitnessUtxo } from 'bip174/src/lib/interfaces';
|
||||
import { Signer, SignerAsync } from './ecpair';
|
||||
import { Network } from './networks';
|
||||
import { Transaction } from './transaction';
|
||||
export declare class Psbt extends PsbtBase {
|
||||
static fromTransaction<T extends typeof PsbtBase>(this: T, txBuf: Buffer): InstanceType<T>;
|
||||
static fromBuffer<T extends typeof PsbtBase>(this: T, buffer: Buffer): InstanceType<T>;
|
||||
export declare class Psbt {
|
||||
readonly data: PsbtBase;
|
||||
static fromTransaction(txBuf: Buffer, opts?: PsbtOptsOptional): Psbt;
|
||||
static fromBase64(data: string, opts?: PsbtOptsOptional): Psbt;
|
||||
static fromHex(data: string, opts?: PsbtOptsOptional): Psbt;
|
||||
static fromBuffer(buffer: Buffer, opts?: PsbtOptsOptional): Psbt;
|
||||
private __CACHE;
|
||||
private opts;
|
||||
constructor(opts?: PsbtOptsOptional);
|
||||
constructor(opts?: PsbtOptsOptional, data?: PsbtBase);
|
||||
readonly inputCount: number;
|
||||
combine(...those: Psbt[]): this;
|
||||
clone(): Psbt;
|
||||
setMaximumFeeRate(satoshiPerByte: number): void;
|
||||
setVersion(version: number): this;
|
||||
|
@ -20,7 +24,6 @@ export declare class Psbt extends PsbtBase {
|
|||
addInput(inputData: TransactionInput): this;
|
||||
addOutputs(outputDatas: TransactionOutput[]): this;
|
||||
addOutput(outputData: TransactionOutput): this;
|
||||
addNonWitnessUtxoToInput(inputIndex: number, nonWitnessUtxo: NonWitnessUtxo): this;
|
||||
extractTransaction(disableFeeCheck?: boolean): Transaction;
|
||||
getFeeRate(): number;
|
||||
finalizeAllInputs(): this;
|
||||
|
@ -31,6 +34,27 @@ export declare class Psbt extends PsbtBase {
|
|||
signAsync(keyPair: SignerAsync, sighashTypes?: number[]): Promise<void>;
|
||||
signInput(inputIndex: number, keyPair: Signer, sighashTypes?: number[]): this;
|
||||
signInputAsync(inputIndex: number, keyPair: SignerAsync, sighashTypes?: number[]): Promise<void>;
|
||||
toBuffer(): Buffer;
|
||||
toHex(): string;
|
||||
toBase64(): string;
|
||||
addGlobalXpubToGlobal(globalXpub: GlobalXpub): this;
|
||||
addNonWitnessUtxoToInput(inputIndex: number, nonWitnessUtxo: NonWitnessUtxo): this;
|
||||
addWitnessUtxoToInput(inputIndex: number, witnessUtxo: WitnessUtxo): this;
|
||||
addPartialSigToInput(inputIndex: number, partialSig: PartialSig): this;
|
||||
addSighashTypeToInput(inputIndex: number, sighashType: SighashType): this;
|
||||
addRedeemScriptToInput(inputIndex: number, redeemScript: RedeemScript): this;
|
||||
addWitnessScriptToInput(inputIndex: number, witnessScript: WitnessScript): this;
|
||||
addBip32DerivationToInput(inputIndex: number, bip32Derivation: Bip32Derivation): this;
|
||||
addFinalScriptSigToInput(inputIndex: number, finalScriptSig: FinalScriptSig): this;
|
||||
addFinalScriptWitnessToInput(inputIndex: number, finalScriptWitness: FinalScriptWitness): this;
|
||||
addPorCommitmentToInput(inputIndex: number, porCommitment: PorCommitment): this;
|
||||
addRedeemScriptToOutput(outputIndex: number, redeemScript: RedeemScript): this;
|
||||
addWitnessScriptToOutput(outputIndex: number, witnessScript: WitnessScript): this;
|
||||
addBip32DerivationToOutput(outputIndex: number, bip32Derivation: Bip32Derivation): this;
|
||||
addUnknownKeyValToGlobal(keyVal: KeyValue): this;
|
||||
addUnknownKeyValToInput(inputIndex: number, keyVal: KeyValue): this;
|
||||
addUnknownKeyValToOutput(outputIndex: number, keyVal: KeyValue): this;
|
||||
clearFinalizedInput(inputIndex: number): this;
|
||||
}
|
||||
interface PsbtOptsOptional {
|
||||
network?: Network;
|
||||
|
|
Loading…
Reference in a new issue