@bitgo/wasm-utxo 2.1.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/js/bip322/index.d.ts +5 -0
- package/dist/cjs/js/bip322/index.js +8 -0
- package/dist/cjs/js/coinName.d.ts +3 -0
- package/dist/cjs/js/coinName.js +49 -0
- package/dist/cjs/js/descriptorWallet/Psbt.d.ts +49 -0
- package/dist/cjs/js/descriptorWallet/Psbt.js +126 -0
- package/dist/cjs/js/descriptorWallet/index.d.ts +1 -0
- package/dist/cjs/js/descriptorWallet/index.js +4 -0
- package/dist/cjs/js/index.d.ts +1 -31
- package/dist/cjs/js/index.js +2 -2
- package/dist/cjs/js/testutils/AcidTest.d.ts +3 -3
- package/dist/cjs/js/testutils/AcidTest.js +79 -80
- package/dist/cjs/js/wasm/wasm_utxo.d.ts +32 -110
- package/dist/cjs/js/wasm/wasm_utxo.js +83 -97
- package/dist/cjs/js/wasm/wasm_utxo_bg.wasm +0 -0
- package/dist/cjs/js/wasm/wasm_utxo_bg.wasm.d.ts +75 -74
- package/dist/esm/js/bip322/index.d.ts +5 -0
- package/dist/esm/js/bip322/index.js +7 -0
- package/dist/esm/js/coinName.d.ts +3 -0
- package/dist/esm/js/coinName.js +48 -0
- package/dist/esm/js/descriptorWallet/Psbt.d.ts +49 -0
- package/dist/esm/js/descriptorWallet/Psbt.js +122 -0
- package/dist/esm/js/descriptorWallet/index.d.ts +1 -0
- package/dist/esm/js/descriptorWallet/index.js +2 -0
- package/dist/esm/js/index.d.ts +1 -31
- package/dist/esm/js/index.js +1 -1
- package/dist/esm/js/testutils/AcidTest.d.ts +3 -3
- package/dist/esm/js/testutils/AcidTest.js +80 -81
- package/dist/esm/js/wasm/wasm_utxo.d.ts +32 -110
- package/dist/esm/js/wasm/wasm_utxo_bg.js +83 -97
- package/dist/esm/js/wasm/wasm_utxo_bg.wasm +0 -0
- package/dist/esm/js/wasm/wasm_utxo_bg.wasm.d.ts +75 -74
- package/package.json +1 -1
|
@@ -106,6 +106,11 @@ export type VerifyBip322TxInputParams = VerifyBip322InputParams & {
|
|
|
106
106
|
* ```
|
|
107
107
|
*/
|
|
108
108
|
export declare function addBip322Input(psbt: BitGoPsbt, params: AddBip322InputParams): number;
|
|
109
|
+
/**
|
|
110
|
+
* Get the BIP322 message stored at a PSBT input index.
|
|
111
|
+
* Returns null if no message is stored.
|
|
112
|
+
*/
|
|
113
|
+
export declare function getBip322Message(psbt: BitGoPsbt, inputIndex: number): string | null;
|
|
109
114
|
/**
|
|
110
115
|
* Verify a single input of a BIP-0322 transaction proof
|
|
111
116
|
*
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
*/
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
exports.addBip322Input = addBip322Input;
|
|
39
|
+
exports.getBip322Message = getBip322Message;
|
|
39
40
|
exports.verifyBip322TxInput = verifyBip322TxInput;
|
|
40
41
|
exports.verifyBip322PsbtInput = verifyBip322PsbtInput;
|
|
41
42
|
exports.verifyBip322PsbtInputWithPubkeys = verifyBip322PsbtInputWithPubkeys;
|
|
@@ -75,6 +76,13 @@ function addBip322Input(psbt, params) {
|
|
|
75
76
|
const keys = RootWalletKeys_js_1.RootWalletKeys.from(params.rootWalletKeys);
|
|
76
77
|
return wasm_utxo_js_1.Bip322Namespace.add_bip322_input(psbt.wasm, params.message, params.scriptId.chain, params.scriptId.index, keys.wasm, params.signPath?.signer, params.signPath?.cosigner, params.tag);
|
|
77
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Get the BIP322 message stored at a PSBT input index.
|
|
81
|
+
* Returns null if no message is stored.
|
|
82
|
+
*/
|
|
83
|
+
function getBip322Message(psbt, inputIndex) {
|
|
84
|
+
return wasm_utxo_js_1.Bip322Namespace.get_bip322_message(psbt.wasm, inputIndex) ?? null;
|
|
85
|
+
}
|
|
78
86
|
/**
|
|
79
87
|
* Verify a single input of a BIP-0322 transaction proof
|
|
80
88
|
*
|
|
@@ -4,3 +4,6 @@ export declare function getMainnet(name: CoinName): CoinName;
|
|
|
4
4
|
export declare function isMainnet(name: CoinName): boolean;
|
|
5
5
|
export declare function isTestnet(name: CoinName): boolean;
|
|
6
6
|
export declare function isCoinName(v: string): v is CoinName;
|
|
7
|
+
import type { UtxolibName } from "./utxolibCompat.js";
|
|
8
|
+
/** Convert a CoinName or UtxolibName to CoinName */
|
|
9
|
+
export declare function toCoinName(name: CoinName | UtxolibName): CoinName;
|
package/dist/cjs/js/coinName.js
CHANGED
|
@@ -5,6 +5,7 @@ exports.getMainnet = getMainnet;
|
|
|
5
5
|
exports.isMainnet = isMainnet;
|
|
6
6
|
exports.isTestnet = isTestnet;
|
|
7
7
|
exports.isCoinName = isCoinName;
|
|
8
|
+
exports.toCoinName = toCoinName;
|
|
8
9
|
// BitGo coin names (from Network::from_coin_name in src/networks.rs)
|
|
9
10
|
exports.coinNames = [
|
|
10
11
|
"btc",
|
|
@@ -65,3 +66,51 @@ function isTestnet(name) {
|
|
|
65
66
|
function isCoinName(v) {
|
|
66
67
|
return exports.coinNames.includes(v);
|
|
67
68
|
}
|
|
69
|
+
/** Convert a CoinName or UtxolibName to CoinName */
|
|
70
|
+
function toCoinName(name) {
|
|
71
|
+
switch (name) {
|
|
72
|
+
case "bitcoin":
|
|
73
|
+
return "btc";
|
|
74
|
+
case "testnet":
|
|
75
|
+
return "tbtc";
|
|
76
|
+
case "bitcoinTestnet4":
|
|
77
|
+
return "tbtc4";
|
|
78
|
+
case "bitcoinPublicSignet":
|
|
79
|
+
return "tbtcsig";
|
|
80
|
+
case "bitcoinBitGoSignet":
|
|
81
|
+
return "tbtcbgsig";
|
|
82
|
+
case "bitcoincash":
|
|
83
|
+
return "bch";
|
|
84
|
+
case "bitcoincashTestnet":
|
|
85
|
+
return "tbch";
|
|
86
|
+
case "ecash":
|
|
87
|
+
return "bcha";
|
|
88
|
+
case "ecashTest":
|
|
89
|
+
return "tbcha";
|
|
90
|
+
case "bitcoingold":
|
|
91
|
+
return "btg";
|
|
92
|
+
case "bitcoingoldTestnet":
|
|
93
|
+
return "tbtg";
|
|
94
|
+
case "bitcoinsv":
|
|
95
|
+
return "bsv";
|
|
96
|
+
case "bitcoinsvTestnet":
|
|
97
|
+
return "tbsv";
|
|
98
|
+
case "dashTest":
|
|
99
|
+
return "tdash";
|
|
100
|
+
case "dogecoin":
|
|
101
|
+
return "doge";
|
|
102
|
+
case "dogecoinTest":
|
|
103
|
+
return "tdoge";
|
|
104
|
+
case "litecoin":
|
|
105
|
+
return "ltc";
|
|
106
|
+
case "litecoinTest":
|
|
107
|
+
return "tltc";
|
|
108
|
+
case "zcash":
|
|
109
|
+
return "zec";
|
|
110
|
+
case "zcashTest":
|
|
111
|
+
return "tzec";
|
|
112
|
+
default:
|
|
113
|
+
// CoinName values pass through (including "dash" which is both CoinName and UtxolibName)
|
|
114
|
+
return name;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { WrapPsbt as WasmPsbt, type WasmBIP32, type WasmECPair, type WrapDescriptor, type PsbtInputData, type PsbtOutputData, type PsbtOutputDataWithAddress } from "../wasm/wasm_utxo.js";
|
|
2
|
+
import type { IPsbt } from "../psbt.js";
|
|
3
|
+
import type { CoinName } from "../coinName.js";
|
|
4
|
+
import type { BIP32 } from "../bip32.js";
|
|
5
|
+
import { Transaction } from "../transaction.js";
|
|
6
|
+
export type SignPsbtResult = {
|
|
7
|
+
[inputIndex: number]: [pubkey: string][];
|
|
8
|
+
};
|
|
9
|
+
export declare class Psbt implements IPsbt {
|
|
10
|
+
private _wasm;
|
|
11
|
+
constructor(versionOrWasm?: number | WasmPsbt, lockTime?: number);
|
|
12
|
+
/** @internal Access the underlying WASM instance */
|
|
13
|
+
get wasm(): WasmPsbt;
|
|
14
|
+
static create(version?: number, lockTime?: number): Psbt;
|
|
15
|
+
static deserialize(bytes: Uint8Array): Psbt;
|
|
16
|
+
serialize(): Uint8Array;
|
|
17
|
+
clone(): Psbt;
|
|
18
|
+
inputCount(): number;
|
|
19
|
+
outputCount(): number;
|
|
20
|
+
version(): number;
|
|
21
|
+
lockTime(): number;
|
|
22
|
+
unsignedTxId(): string;
|
|
23
|
+
getInputs(): PsbtInputData[];
|
|
24
|
+
getOutputs(): PsbtOutputData[];
|
|
25
|
+
getGlobalXpubs(): BIP32[];
|
|
26
|
+
getOutputsWithAddress(coin: CoinName): PsbtOutputDataWithAddress[];
|
|
27
|
+
addInputAtIndex(index: number, txid: string, vout: number, value: bigint, script: Uint8Array, sequence?: number): number;
|
|
28
|
+
addInput(txid: string, vout: number, value: bigint, script: Uint8Array, sequence?: number): number;
|
|
29
|
+
addOutputAtIndex(index: number, script: Uint8Array, value: bigint): number;
|
|
30
|
+
addOutput(script: Uint8Array, value: bigint): number;
|
|
31
|
+
removeInput(index: number): void;
|
|
32
|
+
removeOutput(index: number): void;
|
|
33
|
+
updateInputWithDescriptor(inputIndex: number, descriptor: WrapDescriptor): void;
|
|
34
|
+
updateOutputWithDescriptor(outputIndex: number, descriptor: WrapDescriptor): void;
|
|
35
|
+
signWithXprv(xprv: string): SignPsbtResult;
|
|
36
|
+
signWithPrv(prv: Uint8Array): SignPsbtResult;
|
|
37
|
+
signAll(key: WasmBIP32): SignPsbtResult;
|
|
38
|
+
signAllWithEcpair(key: WasmECPair): SignPsbtResult;
|
|
39
|
+
getPartialSignatures(inputIndex: number): Array<{
|
|
40
|
+
pubkey: Uint8Array;
|
|
41
|
+
signature: Uint8Array;
|
|
42
|
+
}>;
|
|
43
|
+
hasPartialSignatures(inputIndex: number): boolean;
|
|
44
|
+
validateSignatureAtInput(inputIndex: number, pubkey: Uint8Array): boolean;
|
|
45
|
+
verifySignatureWithKey(inputIndex: number, key: WasmBIP32): boolean;
|
|
46
|
+
getUnsignedTx(): Uint8Array;
|
|
47
|
+
finalize(): void;
|
|
48
|
+
extractTransaction(): Transaction;
|
|
49
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Psbt = void 0;
|
|
4
|
+
const wasm_utxo_js_1 = require("../wasm/wasm_utxo.js");
|
|
5
|
+
const transaction_js_1 = require("../transaction.js");
|
|
6
|
+
class Psbt {
|
|
7
|
+
_wasm;
|
|
8
|
+
constructor(versionOrWasm, lockTime) {
|
|
9
|
+
if (versionOrWasm instanceof wasm_utxo_js_1.WrapPsbt) {
|
|
10
|
+
this._wasm = versionOrWasm;
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
this._wasm = new wasm_utxo_js_1.WrapPsbt(versionOrWasm, lockTime);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** @internal Access the underlying WASM instance */
|
|
17
|
+
get wasm() {
|
|
18
|
+
return this._wasm;
|
|
19
|
+
}
|
|
20
|
+
// -- Static / Factory --
|
|
21
|
+
static create(version, lockTime) {
|
|
22
|
+
return new Psbt(new wasm_utxo_js_1.WrapPsbt(version, lockTime));
|
|
23
|
+
}
|
|
24
|
+
static deserialize(bytes) {
|
|
25
|
+
return new Psbt(wasm_utxo_js_1.WrapPsbt.deserialize(bytes));
|
|
26
|
+
}
|
|
27
|
+
// -- Serialization --
|
|
28
|
+
serialize() {
|
|
29
|
+
return this._wasm.serialize();
|
|
30
|
+
}
|
|
31
|
+
clone() {
|
|
32
|
+
return new Psbt(this._wasm.clone());
|
|
33
|
+
}
|
|
34
|
+
// -- IPsbt: introspection --
|
|
35
|
+
inputCount() {
|
|
36
|
+
return this._wasm.input_count();
|
|
37
|
+
}
|
|
38
|
+
outputCount() {
|
|
39
|
+
return this._wasm.output_count();
|
|
40
|
+
}
|
|
41
|
+
version() {
|
|
42
|
+
return this._wasm.version();
|
|
43
|
+
}
|
|
44
|
+
lockTime() {
|
|
45
|
+
return this._wasm.lock_time();
|
|
46
|
+
}
|
|
47
|
+
unsignedTxId() {
|
|
48
|
+
return this._wasm.unsigned_tx_id();
|
|
49
|
+
}
|
|
50
|
+
getInputs() {
|
|
51
|
+
return this._wasm.get_inputs();
|
|
52
|
+
}
|
|
53
|
+
getOutputs() {
|
|
54
|
+
return this._wasm.get_outputs();
|
|
55
|
+
}
|
|
56
|
+
getGlobalXpubs() {
|
|
57
|
+
return this._wasm.get_global_xpubs();
|
|
58
|
+
}
|
|
59
|
+
getOutputsWithAddress(coin) {
|
|
60
|
+
return this._wasm.get_outputs_with_address(coin);
|
|
61
|
+
}
|
|
62
|
+
// -- IPsbt: mutation --
|
|
63
|
+
addInputAtIndex(index, txid, vout, value, script, sequence) {
|
|
64
|
+
return this._wasm.add_input_at_index(index, txid, vout, value, script, sequence);
|
|
65
|
+
}
|
|
66
|
+
addInput(txid, vout, value, script, sequence) {
|
|
67
|
+
return this._wasm.add_input(txid, vout, value, script, sequence);
|
|
68
|
+
}
|
|
69
|
+
addOutputAtIndex(index, script, value) {
|
|
70
|
+
return this._wasm.add_output_at_index(index, script, value);
|
|
71
|
+
}
|
|
72
|
+
addOutput(script, value) {
|
|
73
|
+
return this._wasm.add_output(script, value);
|
|
74
|
+
}
|
|
75
|
+
removeInput(index) {
|
|
76
|
+
this._wasm.remove_input(index);
|
|
77
|
+
}
|
|
78
|
+
removeOutput(index) {
|
|
79
|
+
this._wasm.remove_output(index);
|
|
80
|
+
}
|
|
81
|
+
// -- Descriptor updates --
|
|
82
|
+
updateInputWithDescriptor(inputIndex, descriptor) {
|
|
83
|
+
this._wasm.update_input_with_descriptor(inputIndex, descriptor);
|
|
84
|
+
}
|
|
85
|
+
updateOutputWithDescriptor(outputIndex, descriptor) {
|
|
86
|
+
this._wasm.update_output_with_descriptor(outputIndex, descriptor);
|
|
87
|
+
}
|
|
88
|
+
// -- Signing --
|
|
89
|
+
signWithXprv(xprv) {
|
|
90
|
+
return this._wasm.sign_with_xprv(xprv);
|
|
91
|
+
}
|
|
92
|
+
signWithPrv(prv) {
|
|
93
|
+
return this._wasm.sign_with_prv(prv);
|
|
94
|
+
}
|
|
95
|
+
signAll(key) {
|
|
96
|
+
return this._wasm.sign_all(key);
|
|
97
|
+
}
|
|
98
|
+
signAllWithEcpair(key) {
|
|
99
|
+
return this._wasm.sign_all_with_ecpair(key);
|
|
100
|
+
}
|
|
101
|
+
// -- Signature introspection --
|
|
102
|
+
getPartialSignatures(inputIndex) {
|
|
103
|
+
return this._wasm.get_partial_signatures(inputIndex);
|
|
104
|
+
}
|
|
105
|
+
hasPartialSignatures(inputIndex) {
|
|
106
|
+
return this._wasm.has_partial_signatures(inputIndex);
|
|
107
|
+
}
|
|
108
|
+
// -- Validation --
|
|
109
|
+
validateSignatureAtInput(inputIndex, pubkey) {
|
|
110
|
+
return this._wasm.validate_signature_at_input(inputIndex, pubkey);
|
|
111
|
+
}
|
|
112
|
+
verifySignatureWithKey(inputIndex, key) {
|
|
113
|
+
return this._wasm.verify_signature_with_key(inputIndex, key);
|
|
114
|
+
}
|
|
115
|
+
// -- Transaction extraction --
|
|
116
|
+
getUnsignedTx() {
|
|
117
|
+
return this._wasm.get_unsigned_tx();
|
|
118
|
+
}
|
|
119
|
+
finalize() {
|
|
120
|
+
this._wasm.finalize_mut();
|
|
121
|
+
}
|
|
122
|
+
extractTransaction() {
|
|
123
|
+
return transaction_js_1.Transaction.fromWasm(this._wasm.extract_transaction());
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
exports.Psbt = Psbt;
|
|
@@ -49,6 +49,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
49
49
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
50
50
|
};
|
|
51
51
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.Psbt = void 0;
|
|
52
53
|
// Core types and utilities
|
|
53
54
|
__exportStar(require("./Output.js"), exports);
|
|
54
55
|
__exportStar(require("./DescriptorMap.js"), exports);
|
|
@@ -58,5 +59,8 @@ __exportStar(require("./address.js"), exports);
|
|
|
58
59
|
__exportStar(require("./VirtualSize.js"), exports);
|
|
59
60
|
// PSBT utilities
|
|
60
61
|
__exportStar(require("./psbt/index.js"), exports);
|
|
62
|
+
// PSBT wrapper
|
|
63
|
+
var Psbt_js_1 = require("./Psbt.js");
|
|
64
|
+
Object.defineProperty(exports, "Psbt", { enumerable: true, get: function () { return Psbt_js_1.Psbt; } });
|
|
61
65
|
// Pattern matching
|
|
62
66
|
__exportStar(require("./parse/PatternMatcher.js"), exports);
|
package/dist/cjs/js/index.d.ts
CHANGED
|
@@ -17,9 +17,6 @@ export type { AddressFormat } from "./address.js";
|
|
|
17
17
|
export type { TapLeafScript, PreparedInscriptionRevealData } from "./inscriptions.js";
|
|
18
18
|
export type DescriptorPkType = "derivable" | "definite" | "string";
|
|
19
19
|
export type ScriptContext = "tap" | "segwitv0" | "legacy";
|
|
20
|
-
export type SignPsbtResult = {
|
|
21
|
-
[inputIndex: number]: [pubkey: string][];
|
|
22
|
-
};
|
|
23
20
|
declare module "./wasm/wasm_utxo.js" {
|
|
24
21
|
interface WrapDescriptor {
|
|
25
22
|
/** These are not the same types of nodes as in the ast module */
|
|
@@ -64,36 +61,9 @@ declare module "./wasm/wasm_utxo.js" {
|
|
|
64
61
|
interface PsbtOutputDataWithAddress extends PsbtOutputData {
|
|
65
62
|
address: string;
|
|
66
63
|
}
|
|
67
|
-
interface WrapPsbt {
|
|
68
|
-
signWithXprv(this: WrapPsbt, xprv: string): SignPsbtResult;
|
|
69
|
-
signWithPrv(this: WrapPsbt, prv: Uint8Array): SignPsbtResult;
|
|
70
|
-
signAll(this: WrapPsbt, key: WasmBIP32): SignPsbtResult;
|
|
71
|
-
signAllWithEcpair(this: WrapPsbt, key: WasmECPair): SignPsbtResult;
|
|
72
|
-
inputCount(): number;
|
|
73
|
-
outputCount(): number;
|
|
74
|
-
getInputs(): PsbtInputData[];
|
|
75
|
-
getOutputs(): PsbtOutputData[];
|
|
76
|
-
getOutputsWithAddress(coin: import("./coinName.js").CoinName): PsbtOutputDataWithAddress[];
|
|
77
|
-
getGlobalXpubs(): WasmBIP32[];
|
|
78
|
-
getPartialSignatures(inputIndex: number): Array<{
|
|
79
|
-
pubkey: Uint8Array;
|
|
80
|
-
signature: Uint8Array;
|
|
81
|
-
}>;
|
|
82
|
-
hasPartialSignatures(inputIndex: number): boolean;
|
|
83
|
-
validateSignatureAtInput(inputIndex: number, pubkey: Uint8Array): boolean;
|
|
84
|
-
verifySignatureWithKey(inputIndex: number, key: WasmBIP32): boolean;
|
|
85
|
-
extractTransaction(): WasmTransaction;
|
|
86
|
-
addInputAtIndex(index: number, txid: string, vout: number, value: bigint, script: Uint8Array, sequence?: number): number;
|
|
87
|
-
addOutputAtIndex(index: number, script: Uint8Array, value: bigint): number;
|
|
88
|
-
removeInput(index: number): void;
|
|
89
|
-
removeOutput(index: number): void;
|
|
90
|
-
unsignedTxId(): string;
|
|
91
|
-
lockTime(): number;
|
|
92
|
-
version(): number;
|
|
93
|
-
}
|
|
94
64
|
}
|
|
95
65
|
export { WrapDescriptor as Descriptor } from "./wasm/wasm_utxo.js";
|
|
96
66
|
export { WrapMiniscript as Miniscript } from "./wasm/wasm_utxo.js";
|
|
97
|
-
export {
|
|
67
|
+
export { Psbt } from "./descriptorWallet/Psbt.js";
|
|
98
68
|
export { DashTransaction, Transaction, ZcashTransaction } from "./transaction.js";
|
|
99
69
|
export { hasPsbtMagic, type IPsbt, type IPsbtWithAddress } from "./psbt.js";
|
package/dist/cjs/js/index.js
CHANGED
|
@@ -66,8 +66,8 @@ var wasm_utxo_js_1 = require("./wasm/wasm_utxo.js");
|
|
|
66
66
|
Object.defineProperty(exports, "Descriptor", { enumerable: true, get: function () { return wasm_utxo_js_1.WrapDescriptor; } });
|
|
67
67
|
var wasm_utxo_js_2 = require("./wasm/wasm_utxo.js");
|
|
68
68
|
Object.defineProperty(exports, "Miniscript", { enumerable: true, get: function () { return wasm_utxo_js_2.WrapMiniscript; } });
|
|
69
|
-
var
|
|
70
|
-
Object.defineProperty(exports, "Psbt", { enumerable: true, get: function () { return
|
|
69
|
+
var Psbt_js_1 = require("./descriptorWallet/Psbt.js");
|
|
70
|
+
Object.defineProperty(exports, "Psbt", { enumerable: true, get: function () { return Psbt_js_1.Psbt; } });
|
|
71
71
|
var transaction_js_1 = require("./transaction.js");
|
|
72
72
|
Object.defineProperty(exports, "DashTransaction", { enumerable: true, get: function () { return transaction_js_1.DashTransaction; } });
|
|
73
73
|
Object.defineProperty(exports, "Transaction", { enumerable: true, get: function () { return transaction_js_1.Transaction; } });
|
|
@@ -94,7 +94,7 @@ export { inputScriptTypes, outputScriptTypes };
|
|
|
94
94
|
* - psbt-lite: Only witness_utxo (no non_witness_utxo)
|
|
95
95
|
*/
|
|
96
96
|
export declare class AcidTest {
|
|
97
|
-
readonly
|
|
97
|
+
readonly coin: CoinName;
|
|
98
98
|
readonly signStage: SignStage;
|
|
99
99
|
readonly txFormat: TxFormat;
|
|
100
100
|
readonly rootWalletKeys: RootWalletKeys;
|
|
@@ -104,11 +104,11 @@ export declare class AcidTest {
|
|
|
104
104
|
private readonly userXprv;
|
|
105
105
|
private readonly backupXprv;
|
|
106
106
|
private readonly bitgoXprv;
|
|
107
|
-
constructor(
|
|
107
|
+
constructor(coin: CoinName, signStage: SignStage, txFormat: TxFormat, rootWalletKeys: RootWalletKeys, otherWalletKeys: RootWalletKeys, inputs: Input[], outputs: Output[], xprvTriple: Triple<BIP32>);
|
|
108
108
|
/**
|
|
109
109
|
* Create an AcidTest with specific configuration
|
|
110
110
|
*/
|
|
111
|
-
static withConfig(
|
|
111
|
+
static withConfig(coin: CoinName, signStage: SignStage, txFormat: TxFormat, suiteConfig?: SuiteConfig): AcidTest;
|
|
112
112
|
/**
|
|
113
113
|
* Get a human-readable name for this test configuration
|
|
114
114
|
*/
|
|
@@ -4,6 +4,7 @@ exports.AcidTest = exports.outputScriptTypes = exports.inputScriptTypes = export
|
|
|
4
4
|
const BitGoPsbt_js_1 = require("../fixedScriptWallet/BitGoPsbt.js");
|
|
5
5
|
const ZcashBitGoPsbt_js_1 = require("../fixedScriptWallet/ZcashBitGoPsbt.js");
|
|
6
6
|
const ecpair_js_1 = require("../ecpair.js");
|
|
7
|
+
const transaction_js_1 = require("../transaction.js");
|
|
7
8
|
const index_js_1 = require("../fixedScriptWallet/index.js");
|
|
8
9
|
Object.defineProperty(exports, "inputScriptTypes", { enumerable: true, get: function () { return index_js_1.inputScriptTypes; } });
|
|
9
10
|
Object.defineProperty(exports, "outputScriptTypes", { enumerable: true, get: function () { return index_js_1.outputScriptTypes; } });
|
|
@@ -11,6 +12,21 @@ const coinName_js_1 = require("../coinName.js");
|
|
|
11
12
|
const keys_js_1 = require("./keys.js");
|
|
12
13
|
exports.signStages = ["unsigned", "halfsigned", "fullsigned"];
|
|
13
14
|
exports.txFormats = ["psbt", "psbt-lite"];
|
|
15
|
+
/** Map InputScriptType to the OutputScriptType used for chain code derivation */
|
|
16
|
+
function inputScriptTypeToOutputScriptType(scriptType) {
|
|
17
|
+
switch (scriptType) {
|
|
18
|
+
case "p2sh":
|
|
19
|
+
case "p2shP2wsh":
|
|
20
|
+
case "p2wsh":
|
|
21
|
+
case "p2trLegacy":
|
|
22
|
+
return scriptType;
|
|
23
|
+
case "p2shP2pk":
|
|
24
|
+
return "p2sh";
|
|
25
|
+
case "p2trMusig2ScriptPath":
|
|
26
|
+
case "p2trMusig2KeyPath":
|
|
27
|
+
return "p2trMusig2";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
14
30
|
/**
|
|
15
31
|
* Creates a valid PSBT with as many features as possible (kitchen sink).
|
|
16
32
|
*
|
|
@@ -33,7 +49,7 @@ exports.txFormats = ["psbt", "psbt-lite"];
|
|
|
33
49
|
* - psbt-lite: Only witness_utxo (no non_witness_utxo)
|
|
34
50
|
*/
|
|
35
51
|
class AcidTest {
|
|
36
|
-
|
|
52
|
+
coin;
|
|
37
53
|
signStage;
|
|
38
54
|
txFormat;
|
|
39
55
|
rootWalletKeys;
|
|
@@ -44,8 +60,8 @@ class AcidTest {
|
|
|
44
60
|
userXprv;
|
|
45
61
|
backupXprv;
|
|
46
62
|
bitgoXprv;
|
|
47
|
-
constructor(
|
|
48
|
-
this.
|
|
63
|
+
constructor(coin, signStage, txFormat, rootWalletKeys, otherWalletKeys, inputs, outputs, xprvTriple) {
|
|
64
|
+
this.coin = coin;
|
|
49
65
|
this.signStage = signStage;
|
|
50
66
|
this.txFormat = txFormat;
|
|
51
67
|
this.rootWalletKeys = rootWalletKeys;
|
|
@@ -59,7 +75,7 @@ class AcidTest {
|
|
|
59
75
|
/**
|
|
60
76
|
* Create an AcidTest with specific configuration
|
|
61
77
|
*/
|
|
62
|
-
static withConfig(
|
|
78
|
+
static withConfig(coin, signStage, txFormat, suiteConfig = {}) {
|
|
63
79
|
const rootWalletKeys = (0, keys_js_1.getDefaultWalletKeys)();
|
|
64
80
|
const otherWalletKeys = (0, keys_js_1.getWalletKeysForSeed)("too many secrets");
|
|
65
81
|
// Filter inputs based on network support
|
|
@@ -70,9 +86,9 @@ class AcidTest {
|
|
|
70
86
|
return true;
|
|
71
87
|
// Map input script types to output script types for support check
|
|
72
88
|
if (scriptType === "p2trMusig2KeyPath" || scriptType === "p2trMusig2ScriptPath") {
|
|
73
|
-
return (0, index_js_1.supportsScriptType)(
|
|
89
|
+
return (0, index_js_1.supportsScriptType)(coin, "p2trMusig2");
|
|
74
90
|
}
|
|
75
|
-
return (0, index_js_1.supportsScriptType)(
|
|
91
|
+
return (0, index_js_1.supportsScriptType)(coin, scriptType);
|
|
76
92
|
})
|
|
77
93
|
.filter((scriptType) => (suiteConfig.includeP2trMusig2ScriptPath ?? false) ||
|
|
78
94
|
scriptType !== "p2trMusig2ScriptPath")
|
|
@@ -82,7 +98,7 @@ class AcidTest {
|
|
|
82
98
|
}));
|
|
83
99
|
// Filter outputs based on network support
|
|
84
100
|
const outputs = index_js_1.outputScriptTypes
|
|
85
|
-
.filter((scriptType) => (0, index_js_1.supportsScriptType)(
|
|
101
|
+
.filter((scriptType) => (0, index_js_1.supportsScriptType)(coin, scriptType))
|
|
86
102
|
.map((scriptType, index) => ({
|
|
87
103
|
scriptType,
|
|
88
104
|
value: BigInt(900 + index * 100), // Deterministic amounts
|
|
@@ -95,13 +111,13 @@ class AcidTest {
|
|
|
95
111
|
outputs.push({ opReturn: "setec astronomy", value: BigInt(0) });
|
|
96
112
|
// Get private keys for signing
|
|
97
113
|
const xprvTriple = (0, keys_js_1.getKeyTriple)("default");
|
|
98
|
-
return new AcidTest(
|
|
114
|
+
return new AcidTest(coin, signStage, txFormat, rootWalletKeys, otherWalletKeys, inputs, outputs, xprvTriple);
|
|
99
115
|
}
|
|
100
116
|
/**
|
|
101
117
|
* Get a human-readable name for this test configuration
|
|
102
118
|
*/
|
|
103
119
|
get name() {
|
|
104
|
-
return `${this.
|
|
120
|
+
return `${this.coin} ${this.signStage} ${this.txFormat}`;
|
|
105
121
|
}
|
|
106
122
|
/**
|
|
107
123
|
* Get the BIP32 user key for replay protection (p2shP2pk)
|
|
@@ -114,58 +130,55 @@ class AcidTest {
|
|
|
114
130
|
*/
|
|
115
131
|
createPsbt() {
|
|
116
132
|
// Use ZcashBitGoPsbt for Zcash networks
|
|
117
|
-
const isZcash = this.
|
|
133
|
+
const isZcash = this.coin === "zec" || this.coin === "tzec";
|
|
118
134
|
const psbt = isZcash
|
|
119
|
-
? ZcashBitGoPsbt_js_1.ZcashBitGoPsbt.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
consensusBranchId: 0xc2d6d0b4, // NU5
|
|
135
|
+
? ZcashBitGoPsbt_js_1.ZcashBitGoPsbt.createEmpty(this.coin, this.rootWalletKeys, {
|
|
136
|
+
// Sapling activation height: mainnet=419200, testnet=280000
|
|
137
|
+
blockHeight: this.coin === "zec" ? 419200 : 280000,
|
|
123
138
|
})
|
|
124
|
-
: BitGoPsbt_js_1.BitGoPsbt.createEmpty(this.
|
|
139
|
+
: BitGoPsbt_js_1.BitGoPsbt.createEmpty(this.coin, this.rootWalletKeys, {
|
|
125
140
|
version: 2,
|
|
126
141
|
lockTime: 0,
|
|
127
142
|
});
|
|
143
|
+
// Build a fake previous transaction for non_witness_utxo (psbt format)
|
|
144
|
+
const usePrevTx = this.txFormat === "psbt" && !isZcash;
|
|
145
|
+
const buildPrevTx = (vout, script, value) => {
|
|
146
|
+
if (!usePrevTx)
|
|
147
|
+
return undefined;
|
|
148
|
+
const tx = transaction_js_1.Transaction.create();
|
|
149
|
+
tx.addInput("0".repeat(64), 0xffffffff);
|
|
150
|
+
for (let i = 0; i < vout; i++) {
|
|
151
|
+
tx.addOutput(new Uint8Array(0), 0n);
|
|
152
|
+
}
|
|
153
|
+
tx.addOutput(script, value);
|
|
154
|
+
return tx.toBytes();
|
|
155
|
+
};
|
|
128
156
|
// Add inputs with deterministic outpoints
|
|
129
157
|
this.inputs.forEach((input, index) => {
|
|
130
|
-
// Resolve scriptId: either from explicit scriptId or from scriptType + index
|
|
131
|
-
const scriptId = input.scriptId ?? {
|
|
132
|
-
chain: index_js_1.ChainCode.value("p2sh", "external"),
|
|
133
|
-
index: input.index ?? index,
|
|
134
|
-
};
|
|
135
158
|
const walletKeys = input.walletKeys ?? this.rootWalletKeys;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const ecpair = ecpair_js_1.ECPair.fromPublicKey(replayKey.publicKey);
|
|
143
|
-
psbt.addReplayProtectionInput({
|
|
144
|
-
txid: "0".repeat(64),
|
|
145
|
-
vout: index,
|
|
146
|
-
value: input.value,
|
|
147
|
-
}, ecpair);
|
|
159
|
+
const outpoint = { txid: "0".repeat(64), vout: index, value: input.value };
|
|
160
|
+
// scriptId variant: caller provides explicit chain + index
|
|
161
|
+
if (input.scriptId) {
|
|
162
|
+
const script = (0, index_js_1.outputScript)(walletKeys, input.scriptId.chain, input.scriptId.index, this.coin);
|
|
163
|
+
psbt.addWalletInput({ ...outpoint, prevTx: buildPrevTx(index, script, input.value) }, walletKeys, { scriptId: input.scriptId, signPath: { signer: "user", cosigner: "bitgo" } });
|
|
164
|
+
return;
|
|
148
165
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
// Default: user + bitgo
|
|
158
|
-
signPath = { signer: "user", cosigner: "bitgo" };
|
|
159
|
-
}
|
|
160
|
-
psbt.addWalletInput({
|
|
161
|
-
txid: "0".repeat(64),
|
|
162
|
-
vout: index,
|
|
163
|
-
value: input.value,
|
|
164
|
-
}, walletKeys, {
|
|
165
|
-
scriptId,
|
|
166
|
-
signPath,
|
|
167
|
-
});
|
|
166
|
+
const scriptType = input.scriptType ?? "p2sh";
|
|
167
|
+
if (scriptType === "p2shP2pk") {
|
|
168
|
+
const ecpair = ecpair_js_1.ECPair.fromPublicKey(this.getReplayProtectionKey().publicKey);
|
|
169
|
+
const script = (0, index_js_1.p2shP2pkOutputScript)(ecpair.publicKey);
|
|
170
|
+
psbt.addReplayProtectionInput({ ...outpoint, prevTx: buildPrevTx(index, script, input.value) }, ecpair);
|
|
171
|
+
return;
|
|
168
172
|
}
|
|
173
|
+
const scriptId = {
|
|
174
|
+
chain: index_js_1.ChainCode.value(inputScriptTypeToOutputScriptType(scriptType), "external"),
|
|
175
|
+
index: input.index ?? index,
|
|
176
|
+
};
|
|
177
|
+
const signPath = scriptType === "p2trMusig2ScriptPath"
|
|
178
|
+
? { signer: "user", cosigner: "backup" }
|
|
179
|
+
: { signer: "user", cosigner: "bitgo" };
|
|
180
|
+
const script = (0, index_js_1.outputScript)(walletKeys, scriptId.chain, scriptId.index, this.coin);
|
|
181
|
+
psbt.addWalletInput({ ...outpoint, prevTx: buildPrevTx(index, script, input.value) }, walletKeys, { scriptId, signPath });
|
|
169
182
|
});
|
|
170
183
|
// Add outputs
|
|
171
184
|
this.outputs.forEach((output, index) => {
|
|
@@ -196,7 +209,7 @@ class AcidTest {
|
|
|
196
209
|
chain: scriptId.chain,
|
|
197
210
|
index: output.index ?? 1000 + index,
|
|
198
211
|
};
|
|
199
|
-
const script = (0, index_js_1.outputScript)(this.rootWalletKeys, externalScriptId.chain, externalScriptId.index, this.
|
|
212
|
+
const script = (0, index_js_1.outputScript)(this.rootWalletKeys, externalScriptId.chain, externalScriptId.index, this.coin);
|
|
200
213
|
psbt.addOutput(script, output.value);
|
|
201
214
|
}
|
|
202
215
|
else {
|
|
@@ -227,36 +240,22 @@ class AcidTest {
|
|
|
227
240
|
// Generate MuSig2 nonces for user if needed
|
|
228
241
|
const hasMusig2Inputs = this.inputs.some((input) => input.scriptType === "p2trMusig2KeyPath" || input.scriptType === "p2trMusig2ScriptPath");
|
|
229
242
|
if (hasMusig2Inputs) {
|
|
230
|
-
|
|
231
|
-
if (isZcash) {
|
|
243
|
+
if (this.coin === "zec" || this.coin === "tzec") {
|
|
232
244
|
throw new Error("Zcash does not support MuSig2/Taproot inputs");
|
|
233
245
|
}
|
|
234
|
-
//
|
|
246
|
+
// MuSig2 requires ALL participant nonces before ANY signing.
|
|
247
|
+
// Generate nonces directly on the same PSBT for each participant key.
|
|
235
248
|
psbt.generateMusig2Nonces(userKey);
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
psbt2.generateMusig2Nonces(bitgoKey);
|
|
247
|
-
psbt.combineMusig2Nonces(psbt2);
|
|
248
|
-
}
|
|
249
|
-
else if (hasScriptPath && !hasKeyPath) {
|
|
250
|
-
// Only script path inputs - generate backup nonces for all
|
|
251
|
-
const psbt2 = BitGoPsbt_js_1.BitGoPsbt.fromBytes(bytes, this.network);
|
|
252
|
-
psbt2.generateMusig2Nonces(backupKey);
|
|
253
|
-
psbt.combineMusig2Nonces(psbt2);
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
const psbt2 = BitGoPsbt_js_1.BitGoPsbt.fromBytes(bytes, this.network);
|
|
257
|
-
psbt2.generateMusig2Nonces(bitgoKey);
|
|
258
|
-
psbt.combineMusig2Nonces(psbt2);
|
|
259
|
-
}
|
|
249
|
+
const hasKeyPath = this.inputs.some((input) => input.scriptType === "p2trMusig2KeyPath");
|
|
250
|
+
const hasScriptPath = this.inputs.some((input) => input.scriptType === "p2trMusig2ScriptPath");
|
|
251
|
+
// Key path uses user+bitgo, script path uses user+backup.
|
|
252
|
+
// generateMusig2Nonces fails if the key isn't a participant in any musig2 input,
|
|
253
|
+
// so we only call it for keys that match.
|
|
254
|
+
if (hasKeyPath) {
|
|
255
|
+
psbt.generateMusig2Nonces(bitgoKey);
|
|
256
|
+
}
|
|
257
|
+
if (hasScriptPath) {
|
|
258
|
+
psbt.generateMusig2Nonces(backupKey);
|
|
260
259
|
}
|
|
261
260
|
}
|
|
262
261
|
// Sign all wallet inputs with user key (bulk - more efficient)
|
|
@@ -299,7 +298,7 @@ class AcidTest {
|
|
|
299
298
|
*/
|
|
300
299
|
static forAllNetworksSignStagesTxFormats(suiteConfig = {}) {
|
|
301
300
|
return coinName_js_1.coinNames
|
|
302
|
-
.filter((network) => (0, coinName_js_1.isMainnet)(network) && network !== "bsv")
|
|
301
|
+
.filter((network) => (0, coinName_js_1.isMainnet)(network) && network !== "bsv")
|
|
303
302
|
.flatMap((network) => exports.signStages.flatMap((signStage) => exports.txFormats.map((txFormat) => AcidTest.withConfig(network, signStage, txFormat, suiteConfig))));
|
|
304
303
|
}
|
|
305
304
|
}
|