@bitgo/wasm-utxo 2.1.0 → 3.0.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.
@@ -0,0 +1,122 @@
1
+ import { WrapPsbt as WasmPsbt, } from "../wasm/wasm_utxo.js";
2
+ import { Transaction } from "../transaction.js";
3
+ export class Psbt {
4
+ _wasm;
5
+ constructor(versionOrWasm, lockTime) {
6
+ if (versionOrWasm instanceof WasmPsbt) {
7
+ this._wasm = versionOrWasm;
8
+ }
9
+ else {
10
+ this._wasm = new WasmPsbt(versionOrWasm, lockTime);
11
+ }
12
+ }
13
+ /** @internal Access the underlying WASM instance */
14
+ get wasm() {
15
+ return this._wasm;
16
+ }
17
+ // -- Static / Factory --
18
+ static create(version, lockTime) {
19
+ return new Psbt(new WasmPsbt(version, lockTime));
20
+ }
21
+ static deserialize(bytes) {
22
+ return new Psbt(WasmPsbt.deserialize(bytes));
23
+ }
24
+ // -- Serialization --
25
+ serialize() {
26
+ return this._wasm.serialize();
27
+ }
28
+ clone() {
29
+ return new Psbt(this._wasm.clone());
30
+ }
31
+ // -- IPsbt: introspection --
32
+ inputCount() {
33
+ return this._wasm.input_count();
34
+ }
35
+ outputCount() {
36
+ return this._wasm.output_count();
37
+ }
38
+ version() {
39
+ return this._wasm.version();
40
+ }
41
+ lockTime() {
42
+ return this._wasm.lock_time();
43
+ }
44
+ unsignedTxId() {
45
+ return this._wasm.unsigned_tx_id();
46
+ }
47
+ getInputs() {
48
+ return this._wasm.get_inputs();
49
+ }
50
+ getOutputs() {
51
+ return this._wasm.get_outputs();
52
+ }
53
+ getGlobalXpubs() {
54
+ return this._wasm.get_global_xpubs();
55
+ }
56
+ getOutputsWithAddress(coin) {
57
+ return this._wasm.get_outputs_with_address(coin);
58
+ }
59
+ // -- IPsbt: mutation --
60
+ addInputAtIndex(index, txid, vout, value, script, sequence) {
61
+ return this._wasm.add_input_at_index(index, txid, vout, value, script, sequence);
62
+ }
63
+ addInput(txid, vout, value, script, sequence) {
64
+ return this._wasm.add_input(txid, vout, value, script, sequence);
65
+ }
66
+ addOutputAtIndex(index, script, value) {
67
+ return this._wasm.add_output_at_index(index, script, value);
68
+ }
69
+ addOutput(script, value) {
70
+ return this._wasm.add_output(script, value);
71
+ }
72
+ removeInput(index) {
73
+ this._wasm.remove_input(index);
74
+ }
75
+ removeOutput(index) {
76
+ this._wasm.remove_output(index);
77
+ }
78
+ // -- Descriptor updates --
79
+ updateInputWithDescriptor(inputIndex, descriptor) {
80
+ this._wasm.update_input_with_descriptor(inputIndex, descriptor);
81
+ }
82
+ updateOutputWithDescriptor(outputIndex, descriptor) {
83
+ this._wasm.update_output_with_descriptor(outputIndex, descriptor);
84
+ }
85
+ // -- Signing --
86
+ signWithXprv(xprv) {
87
+ return this._wasm.sign_with_xprv(xprv);
88
+ }
89
+ signWithPrv(prv) {
90
+ return this._wasm.sign_with_prv(prv);
91
+ }
92
+ signAll(key) {
93
+ return this._wasm.sign_all(key);
94
+ }
95
+ signAllWithEcpair(key) {
96
+ return this._wasm.sign_all_with_ecpair(key);
97
+ }
98
+ // -- Signature introspection --
99
+ getPartialSignatures(inputIndex) {
100
+ return this._wasm.get_partial_signatures(inputIndex);
101
+ }
102
+ hasPartialSignatures(inputIndex) {
103
+ return this._wasm.has_partial_signatures(inputIndex);
104
+ }
105
+ // -- Validation --
106
+ validateSignatureAtInput(inputIndex, pubkey) {
107
+ return this._wasm.validate_signature_at_input(inputIndex, pubkey);
108
+ }
109
+ verifySignatureWithKey(inputIndex, key) {
110
+ return this._wasm.verify_signature_with_key(inputIndex, key);
111
+ }
112
+ // -- Transaction extraction --
113
+ getUnsignedTx() {
114
+ return this._wasm.get_unsigned_tx();
115
+ }
116
+ finalize() {
117
+ this._wasm.finalize_mut();
118
+ }
119
+ extractTransaction() {
120
+ return Transaction.fromWasm(this._wasm.extract_transaction());
121
+ }
122
+ }
@@ -40,4 +40,5 @@ export * from "./DescriptorOutput.js";
40
40
  export * from "./address.js";
41
41
  export * from "./VirtualSize.js";
42
42
  export * from "./psbt/index.js";
43
+ export { Psbt, type SignPsbtResult } from "./Psbt.js";
43
44
  export * from "./parse/PatternMatcher.js";
@@ -42,5 +42,7 @@ export * from "./address.js";
42
42
  export * from "./VirtualSize.js";
43
43
  // PSBT utilities
44
44
  export * from "./psbt/index.js";
45
+ // PSBT wrapper
46
+ export { Psbt } from "./Psbt.js";
45
47
  // Pattern matching
46
48
  export * from "./parse/PatternMatcher.js";
@@ -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 { WrapPsbt as Psbt } from "./wasm/wasm_utxo.js";
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";
@@ -21,6 +21,6 @@ export { Dimensions } from "./fixedScriptWallet/Dimensions.js";
21
21
  export { getMainnet, isMainnet, isTestnet, isCoinName } from "./coinName.js";
22
22
  export { WrapDescriptor as Descriptor } from "./wasm/wasm_utxo.js";
23
23
  export { WrapMiniscript as Miniscript } from "./wasm/wasm_utxo.js";
24
- export { WrapPsbt as Psbt } from "./wasm/wasm_utxo.js";
24
+ export { Psbt } from "./descriptorWallet/Psbt.js";
25
25
  export { DashTransaction, Transaction, ZcashTransaction } from "./transaction.js";
26
26
  export { hasPsbtMagic } from "./psbt.js";
@@ -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 network: CoinName;
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(network: CoinName, signStage: SignStage, txFormat: TxFormat, rootWalletKeys: RootWalletKeys, otherWalletKeys: RootWalletKeys, inputs: Input[], outputs: Output[], xprvTriple: Triple<BIP32>);
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(network: CoinName, signStage: SignStage, txFormat: TxFormat, suiteConfig?: SuiteConfig): AcidTest;
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
  */
@@ -1,13 +1,29 @@
1
1
  import { BitGoPsbt } from "../fixedScriptWallet/BitGoPsbt.js";
2
2
  import { ZcashBitGoPsbt } from "../fixedScriptWallet/ZcashBitGoPsbt.js";
3
3
  import { ECPair } from "../ecpair.js";
4
- import { assertChainCode, ChainCode, createOpReturnScript, inputScriptTypes, outputScript, outputScriptTypes, supportsScriptType, } from "../fixedScriptWallet/index.js";
4
+ import { Transaction } from "../transaction.js";
5
+ import { ChainCode, createOpReturnScript, inputScriptTypes, outputScript, outputScriptTypes, p2shP2pkOutputScript, supportsScriptType, } from "../fixedScriptWallet/index.js";
5
6
  import { coinNames, isMainnet } from "../coinName.js";
6
7
  import { getDefaultWalletKeys, getWalletKeysForSeed, getKeyTriple } from "./keys.js";
7
8
  export const signStages = ["unsigned", "halfsigned", "fullsigned"];
8
9
  export const txFormats = ["psbt", "psbt-lite"];
9
10
  // Re-export for convenience
10
11
  export { inputScriptTypes, outputScriptTypes };
12
+ /** Map InputScriptType to the OutputScriptType used for chain code derivation */
13
+ function inputScriptTypeToOutputScriptType(scriptType) {
14
+ switch (scriptType) {
15
+ case "p2sh":
16
+ case "p2shP2wsh":
17
+ case "p2wsh":
18
+ case "p2trLegacy":
19
+ return scriptType;
20
+ case "p2shP2pk":
21
+ return "p2sh";
22
+ case "p2trMusig2ScriptPath":
23
+ case "p2trMusig2KeyPath":
24
+ return "p2trMusig2";
25
+ }
26
+ }
11
27
  /**
12
28
  * Creates a valid PSBT with as many features as possible (kitchen sink).
13
29
  *
@@ -30,7 +46,7 @@ export { inputScriptTypes, outputScriptTypes };
30
46
  * - psbt-lite: Only witness_utxo (no non_witness_utxo)
31
47
  */
32
48
  export class AcidTest {
33
- network;
49
+ coin;
34
50
  signStage;
35
51
  txFormat;
36
52
  rootWalletKeys;
@@ -41,8 +57,8 @@ export class AcidTest {
41
57
  userXprv;
42
58
  backupXprv;
43
59
  bitgoXprv;
44
- constructor(network, signStage, txFormat, rootWalletKeys, otherWalletKeys, inputs, outputs, xprvTriple) {
45
- this.network = network;
60
+ constructor(coin, signStage, txFormat, rootWalletKeys, otherWalletKeys, inputs, outputs, xprvTriple) {
61
+ this.coin = coin;
46
62
  this.signStage = signStage;
47
63
  this.txFormat = txFormat;
48
64
  this.rootWalletKeys = rootWalletKeys;
@@ -56,7 +72,7 @@ export class AcidTest {
56
72
  /**
57
73
  * Create an AcidTest with specific configuration
58
74
  */
59
- static withConfig(network, signStage, txFormat, suiteConfig = {}) {
75
+ static withConfig(coin, signStage, txFormat, suiteConfig = {}) {
60
76
  const rootWalletKeys = getDefaultWalletKeys();
61
77
  const otherWalletKeys = getWalletKeysForSeed("too many secrets");
62
78
  // Filter inputs based on network support
@@ -67,9 +83,9 @@ export class AcidTest {
67
83
  return true;
68
84
  // Map input script types to output script types for support check
69
85
  if (scriptType === "p2trMusig2KeyPath" || scriptType === "p2trMusig2ScriptPath") {
70
- return supportsScriptType(network, "p2trMusig2");
86
+ return supportsScriptType(coin, "p2trMusig2");
71
87
  }
72
- return supportsScriptType(network, scriptType);
88
+ return supportsScriptType(coin, scriptType);
73
89
  })
74
90
  .filter((scriptType) => (suiteConfig.includeP2trMusig2ScriptPath ?? false) ||
75
91
  scriptType !== "p2trMusig2ScriptPath")
@@ -79,7 +95,7 @@ export class AcidTest {
79
95
  }));
80
96
  // Filter outputs based on network support
81
97
  const outputs = outputScriptTypes
82
- .filter((scriptType) => supportsScriptType(network, scriptType))
98
+ .filter((scriptType) => supportsScriptType(coin, scriptType))
83
99
  .map((scriptType, index) => ({
84
100
  scriptType,
85
101
  value: BigInt(900 + index * 100), // Deterministic amounts
@@ -92,13 +108,13 @@ export class AcidTest {
92
108
  outputs.push({ opReturn: "setec astronomy", value: BigInt(0) });
93
109
  // Get private keys for signing
94
110
  const xprvTriple = getKeyTriple("default");
95
- return new AcidTest(network, signStage, txFormat, rootWalletKeys, otherWalletKeys, inputs, outputs, xprvTriple);
111
+ return new AcidTest(coin, signStage, txFormat, rootWalletKeys, otherWalletKeys, inputs, outputs, xprvTriple);
96
112
  }
97
113
  /**
98
114
  * Get a human-readable name for this test configuration
99
115
  */
100
116
  get name() {
101
- return `${this.network} ${this.signStage} ${this.txFormat}`;
117
+ return `${this.coin} ${this.signStage} ${this.txFormat}`;
102
118
  }
103
119
  /**
104
120
  * Get the BIP32 user key for replay protection (p2shP2pk)
@@ -111,58 +127,55 @@ export class AcidTest {
111
127
  */
112
128
  createPsbt() {
113
129
  // Use ZcashBitGoPsbt for Zcash networks
114
- const isZcash = this.network === "zec" || this.network === "tzec";
130
+ const isZcash = this.coin === "zec" || this.coin === "tzec";
115
131
  const psbt = isZcash
116
- ? ZcashBitGoPsbt.createEmptyWithConsensusBranchId(this.network, this.rootWalletKeys, {
117
- version: 2,
118
- lockTime: 0,
119
- consensusBranchId: 0xc2d6d0b4, // NU5
132
+ ? ZcashBitGoPsbt.createEmpty(this.coin, this.rootWalletKeys, {
133
+ // Sapling activation height: mainnet=419200, testnet=280000
134
+ blockHeight: this.coin === "zec" ? 419200 : 280000,
120
135
  })
121
- : BitGoPsbt.createEmpty(this.network, this.rootWalletKeys, {
136
+ : BitGoPsbt.createEmpty(this.coin, this.rootWalletKeys, {
122
137
  version: 2,
123
138
  lockTime: 0,
124
139
  });
140
+ // Build a fake previous transaction for non_witness_utxo (psbt format)
141
+ const usePrevTx = this.txFormat === "psbt" && !isZcash;
142
+ const buildPrevTx = (vout, script, value) => {
143
+ if (!usePrevTx)
144
+ return undefined;
145
+ const tx = Transaction.create();
146
+ tx.addInput("0".repeat(64), 0xffffffff);
147
+ for (let i = 0; i < vout; i++) {
148
+ tx.addOutput(new Uint8Array(0), 0n);
149
+ }
150
+ tx.addOutput(script, value);
151
+ return tx.toBytes();
152
+ };
125
153
  // Add inputs with deterministic outpoints
126
154
  this.inputs.forEach((input, index) => {
127
- // Resolve scriptId: either from explicit scriptId or from scriptType + index
128
- const scriptId = input.scriptId ?? {
129
- chain: ChainCode.value("p2sh", "external"),
130
- index: input.index ?? index,
131
- };
132
155
  const walletKeys = input.walletKeys ?? this.rootWalletKeys;
133
- // Get scriptType: either explicit or derive from scriptId chain
134
- const scriptType = input.scriptType ?? ChainCode.scriptType(assertChainCode(scriptId.chain));
135
- if (scriptType === "p2shP2pk") {
136
- // Add replay protection input
137
- const replayKey = this.getReplayProtectionKey();
138
- // Convert BIP32 to ECPair using public key
139
- const ecpair = ECPair.fromPublicKey(replayKey.publicKey);
140
- psbt.addReplayProtectionInput({
141
- txid: "0".repeat(64),
142
- vout: index,
143
- value: input.value,
144
- }, ecpair);
156
+ const outpoint = { txid: "0".repeat(64), vout: index, value: input.value };
157
+ // scriptId variant: caller provides explicit chain + index
158
+ if (input.scriptId) {
159
+ const script = outputScript(walletKeys, input.scriptId.chain, input.scriptId.index, this.coin);
160
+ psbt.addWalletInput({ ...outpoint, prevTx: buildPrevTx(index, script, input.value) }, walletKeys, { scriptId: input.scriptId, signPath: { signer: "user", cosigner: "bitgo" } });
161
+ return;
145
162
  }
146
- else {
147
- // Determine signing path based on input type
148
- let signPath;
149
- if (scriptType === "p2trMusig2ScriptPath") {
150
- // Script path uses user + backup
151
- signPath = { signer: "user", cosigner: "backup" };
152
- }
153
- else {
154
- // Default: user + bitgo
155
- signPath = { signer: "user", cosigner: "bitgo" };
156
- }
157
- psbt.addWalletInput({
158
- txid: "0".repeat(64),
159
- vout: index,
160
- value: input.value,
161
- }, walletKeys, {
162
- scriptId,
163
- signPath,
164
- });
163
+ const scriptType = input.scriptType ?? "p2sh";
164
+ if (scriptType === "p2shP2pk") {
165
+ const ecpair = ECPair.fromPublicKey(this.getReplayProtectionKey().publicKey);
166
+ const script = p2shP2pkOutputScript(ecpair.publicKey);
167
+ psbt.addReplayProtectionInput({ ...outpoint, prevTx: buildPrevTx(index, script, input.value) }, ecpair);
168
+ return;
165
169
  }
170
+ const scriptId = {
171
+ chain: ChainCode.value(inputScriptTypeToOutputScriptType(scriptType), "external"),
172
+ index: input.index ?? index,
173
+ };
174
+ const signPath = scriptType === "p2trMusig2ScriptPath"
175
+ ? { signer: "user", cosigner: "backup" }
176
+ : { signer: "user", cosigner: "bitgo" };
177
+ const script = outputScript(walletKeys, scriptId.chain, scriptId.index, this.coin);
178
+ psbt.addWalletInput({ ...outpoint, prevTx: buildPrevTx(index, script, input.value) }, walletKeys, { scriptId, signPath });
166
179
  });
167
180
  // Add outputs
168
181
  this.outputs.forEach((output, index) => {
@@ -193,7 +206,7 @@ export class AcidTest {
193
206
  chain: scriptId.chain,
194
207
  index: output.index ?? 1000 + index,
195
208
  };
196
- const script = outputScript(this.rootWalletKeys, externalScriptId.chain, externalScriptId.index, this.network);
209
+ const script = outputScript(this.rootWalletKeys, externalScriptId.chain, externalScriptId.index, this.coin);
197
210
  psbt.addOutput(script, output.value);
198
211
  }
199
212
  else {
@@ -224,36 +237,22 @@ export class AcidTest {
224
237
  // Generate MuSig2 nonces for user if needed
225
238
  const hasMusig2Inputs = this.inputs.some((input) => input.scriptType === "p2trMusig2KeyPath" || input.scriptType === "p2trMusig2ScriptPath");
226
239
  if (hasMusig2Inputs) {
227
- const isZcash = this.network === "zec" || this.network === "tzec";
228
- if (isZcash) {
240
+ if (this.coin === "zec" || this.coin === "tzec") {
229
241
  throw new Error("Zcash does not support MuSig2/Taproot inputs");
230
242
  }
231
- // Generate nonces with user key
243
+ // MuSig2 requires ALL participant nonces before ANY signing.
244
+ // Generate nonces directly on the same PSBT for each participant key.
232
245
  psbt.generateMusig2Nonces(userKey);
233
- if (this.signStage === "fullsigned") {
234
- // Create a second PSBT with cosigner nonces for combination
235
- // For p2trMusig2ScriptPath use backup, for p2trMusig2KeyPath use bitgo
236
- // Since we might have both types, we need to generate nonces separately
237
- const bytes = psbt.serialize();
238
- const hasKeyPath = this.inputs.some((input) => input.scriptType === "p2trMusig2KeyPath");
239
- const hasScriptPath = this.inputs.some((input) => input.scriptType === "p2trMusig2ScriptPath");
240
- if (hasKeyPath && !hasScriptPath) {
241
- // Only key path inputs - generate bitgo nonces for all
242
- const psbt2 = BitGoPsbt.fromBytes(bytes, this.network);
243
- psbt2.generateMusig2Nonces(bitgoKey);
244
- psbt.combineMusig2Nonces(psbt2);
245
- }
246
- else if (hasScriptPath && !hasKeyPath) {
247
- // Only script path inputs - generate backup nonces for all
248
- const psbt2 = BitGoPsbt.fromBytes(bytes, this.network);
249
- psbt2.generateMusig2Nonces(backupKey);
250
- psbt.combineMusig2Nonces(psbt2);
251
- }
252
- else {
253
- const psbt2 = BitGoPsbt.fromBytes(bytes, this.network);
254
- psbt2.generateMusig2Nonces(bitgoKey);
255
- psbt.combineMusig2Nonces(psbt2);
256
- }
246
+ const hasKeyPath = this.inputs.some((input) => input.scriptType === "p2trMusig2KeyPath");
247
+ const hasScriptPath = this.inputs.some((input) => input.scriptType === "p2trMusig2ScriptPath");
248
+ // Key path uses user+bitgo, script path uses user+backup.
249
+ // generateMusig2Nonces fails if the key isn't a participant in any musig2 input,
250
+ // so we only call it for keys that match.
251
+ if (hasKeyPath) {
252
+ psbt.generateMusig2Nonces(bitgoKey);
253
+ }
254
+ if (hasScriptPath) {
255
+ psbt.generateMusig2Nonces(backupKey);
257
256
  }
258
257
  }
259
258
  // Sign all wallet inputs with user key (bulk - more efficient)
@@ -296,7 +295,7 @@ export class AcidTest {
296
295
  */
297
296
  static forAllNetworksSignStagesTxFormats(suiteConfig = {}) {
298
297
  return coinNames
299
- .filter((network) => isMainnet(network) && network !== "bsv") // Exclude bitcoinsv
298
+ .filter((network) => isMainnet(network) && network !== "bsv")
300
299
  .flatMap((network) => signStages.flatMap((signStage) => txFormats.map((txFormat) => AcidTest.withConfig(network, signStage, txFormat, suiteConfig))));
301
300
  }
302
301
  }