@bitgo/wasm-utxo 1.0.0 → 1.2.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.
@@ -63,6 +63,11 @@ export declare class BitGoPsbt {
63
63
  * @returns A BitGoPsbt instance
64
64
  */
65
65
  static fromBytes(bytes: Uint8Array, network: NetworkName): BitGoPsbt;
66
+ /**
67
+ * Get the unsigned transaction ID
68
+ * @returns The unsigned transaction ID
69
+ */
70
+ unsignedTxid(): string;
66
71
  /**
67
72
  * Parse transaction with wallet keys to identify wallet inputs/outputs
68
73
  * @param walletKeys - The wallet keys to use for identification
@@ -82,5 +87,39 @@ export declare class BitGoPsbt {
82
87
  * @note This method does NOT validate wallet inputs. It only parses outputs.
83
88
  */
84
89
  parseOutputsWithWalletKeys(walletKeys: WalletKeys): ParsedOutput[];
90
+ /**
91
+ * Verify if a valid signature exists for a given extended public key at the specified input index.
92
+ *
93
+ * This method derives the public key from the xpub using the derivation path found in the
94
+ * PSBT input, then verifies the signature. It supports:
95
+ * - ECDSA signatures (for legacy/SegWit inputs)
96
+ * - Schnorr signatures (for Taproot script path inputs)
97
+ * - MuSig2 partial signatures (for Taproot keypath MuSig2 inputs)
98
+ *
99
+ * @param inputIndex - The index of the input to check (0-based)
100
+ * @param xpub - The extended public key as a base58-encoded string
101
+ * @returns true if a valid signature exists, false if no signature exists
102
+ * @throws Error if input index is out of bounds, xpub is invalid, or verification fails
103
+ */
104
+ verifySignature(inputIndex: number, xpub: string): boolean;
105
+ /**
106
+ * Verify if a replay protection input has a valid signature.
107
+ *
108
+ * This method checks if a given input is a replay protection input (like P2shP2pk) and verifies
109
+ * the signature. Replay protection inputs don't use standard derivation paths, so this method
110
+ * verifies signatures without deriving from xpub.
111
+ *
112
+ * For P2PK replay protection inputs, this:
113
+ * - Extracts the signature from final_script_sig
114
+ * - Extracts the public key from redeem_script
115
+ * - Computes the legacy P2SH sighash
116
+ * - Verifies the ECDSA signature cryptographically
117
+ *
118
+ * @param inputIndex - The index of the input to check (0-based)
119
+ * @param replayProtection - Scripts that identify replay protection inputs (same format as parseTransactionWithWalletKeys)
120
+ * @returns true if the input is a replay protection input and has a valid signature, false if no valid signature
121
+ * @throws Error if the input is not a replay protection input, index is out of bounds, or scripts are invalid
122
+ */
123
+ verifyReplayProtectionSignature(inputIndex: number, replayProtection: ReplayProtection): boolean;
85
124
  }
86
125
  export {};
@@ -35,6 +35,13 @@ export class BitGoPsbt {
35
35
  const wasm = WasmBitGoPsbt.from_bytes(bytes, network);
36
36
  return new BitGoPsbt(wasm);
37
37
  }
38
+ /**
39
+ * Get the unsigned transaction ID
40
+ * @returns The unsigned transaction ID
41
+ */
42
+ unsignedTxid() {
43
+ return this.wasm.unsigned_txid();
44
+ }
38
45
  /**
39
46
  * Parse transaction with wallet keys to identify wallet inputs/outputs
40
47
  * @param walletKeys - The wallet keys to use for identification
@@ -58,4 +65,42 @@ export class BitGoPsbt {
58
65
  parseOutputsWithWalletKeys(walletKeys) {
59
66
  return this.wasm.parse_outputs_with_wallet_keys(walletKeys);
60
67
  }
68
+ /**
69
+ * Verify if a valid signature exists for a given extended public key at the specified input index.
70
+ *
71
+ * This method derives the public key from the xpub using the derivation path found in the
72
+ * PSBT input, then verifies the signature. It supports:
73
+ * - ECDSA signatures (for legacy/SegWit inputs)
74
+ * - Schnorr signatures (for Taproot script path inputs)
75
+ * - MuSig2 partial signatures (for Taproot keypath MuSig2 inputs)
76
+ *
77
+ * @param inputIndex - The index of the input to check (0-based)
78
+ * @param xpub - The extended public key as a base58-encoded string
79
+ * @returns true if a valid signature exists, false if no signature exists
80
+ * @throws Error if input index is out of bounds, xpub is invalid, or verification fails
81
+ */
82
+ verifySignature(inputIndex, xpub) {
83
+ return this.wasm.verify_signature(inputIndex, xpub);
84
+ }
85
+ /**
86
+ * Verify if a replay protection input has a valid signature.
87
+ *
88
+ * This method checks if a given input is a replay protection input (like P2shP2pk) and verifies
89
+ * the signature. Replay protection inputs don't use standard derivation paths, so this method
90
+ * verifies signatures without deriving from xpub.
91
+ *
92
+ * For P2PK replay protection inputs, this:
93
+ * - Extracts the signature from final_script_sig
94
+ * - Extracts the public key from redeem_script
95
+ * - Computes the legacy P2SH sighash
96
+ * - Verifies the ECDSA signature cryptographically
97
+ *
98
+ * @param inputIndex - The index of the input to check (0-based)
99
+ * @param replayProtection - Scripts that identify replay protection inputs (same format as parseTransactionWithWalletKeys)
100
+ * @returns true if the input is a replay protection input and has a valid signature, false if no valid signature
101
+ * @throws Error if the input is not a replay protection input, index is out of bounds, or scripts are invalid
102
+ */
103
+ verifyReplayProtectionSignature(inputIndex, replayProtection) {
104
+ return this.wasm.verify_replay_protection_signature(inputIndex, replayProtection);
105
+ }
61
106
  }
@@ -15,6 +15,27 @@ export class BitGoPsbt {
15
15
  * Deserialize a PSBT from bytes with network-specific logic
16
16
  */
17
17
  static from_bytes(bytes: Uint8Array, network: string): BitGoPsbt;
18
+ /**
19
+ * Get the unsigned transaction ID
20
+ */
21
+ unsigned_txid(): string;
22
+ /**
23
+ * Verify if a valid signature exists for a given xpub at the specified input index
24
+ *
25
+ * This method derives the public key from the xpub using the derivation path found in the
26
+ * PSBT input, then verifies the signature. It supports both ECDSA signatures (for legacy/SegWit
27
+ * inputs) and Schnorr signatures (for Taproot script path inputs).
28
+ *
29
+ * # Arguments
30
+ * - `input_index`: The index of the input to check
31
+ * - `xpub_str`: The extended public key as a base58-encoded string
32
+ *
33
+ * # Returns
34
+ * - `Ok(true)` if a valid signature exists for the derived public key
35
+ * - `Ok(false)` if no signature exists for the derived public key
36
+ * - `Err(WasmUtxoError)` if the input index is out of bounds, xpub is invalid, derivation fails, or verification fails
37
+ */
38
+ verify_signature(input_index: number, xpub_str: string): boolean;
18
39
  /**
19
40
  * Parse outputs with wallet keys to identify which outputs belong to a wallet
20
41
  *
@@ -25,6 +46,24 @@ export class BitGoPsbt {
25
46
  * Parse transaction with wallet keys to identify wallet inputs/outputs
26
47
  */
27
48
  parse_transaction_with_wallet_keys(wallet_keys: any, replay_protection: any): any;
49
+ /**
50
+ * Verify if a replay protection input has a valid signature
51
+ *
52
+ * This method checks if a given input is a replay protection input and cryptographically verifies
53
+ * the signature. Replay protection inputs (like P2shP2pk) don't use standard derivation paths,
54
+ * so this method verifies signatures without deriving from xpub.
55
+ *
56
+ * # Arguments
57
+ * - `input_index`: The index of the input to check
58
+ * - `replay_protection`: Replay protection configuration (same format as parseTransactionWithWalletKeys)
59
+ * Can be either `{ outputScripts: Buffer[] }` or `{ addresses: string[] }`
60
+ *
61
+ * # Returns
62
+ * - `Ok(true)` if the input is a replay protection input and has a valid signature
63
+ * - `Ok(false)` if the input is a replay protection input but has no valid signature
64
+ * - `Err(WasmUtxoError)` if the input is not a replay protection input, index is out of bounds, or configuration is invalid
65
+ */
66
+ verify_replay_protection_signature(input_index: number, replay_protection: any): boolean;
28
67
  }
29
68
  export class FixedScriptWalletNamespace {
30
69
  private constructor();
@@ -289,6 +289,62 @@ export class BitGoPsbt {
289
289
  wasm.__wbindgen_add_to_stack_pointer(16);
290
290
  }
291
291
  }
292
+ /**
293
+ * Get the unsigned transaction ID
294
+ * @returns {string}
295
+ */
296
+ unsigned_txid() {
297
+ let deferred1_0;
298
+ let deferred1_1;
299
+ try {
300
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
301
+ wasm.bitgopsbt_unsigned_txid(retptr, this.__wbg_ptr);
302
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
303
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
304
+ deferred1_0 = r0;
305
+ deferred1_1 = r1;
306
+ return getStringFromWasm0(r0, r1);
307
+ } finally {
308
+ wasm.__wbindgen_add_to_stack_pointer(16);
309
+ wasm.__wbindgen_export_3(deferred1_0, deferred1_1, 1);
310
+ }
311
+ }
312
+ /**
313
+ * Verify if a valid signature exists for a given xpub at the specified input index
314
+ *
315
+ * This method derives the public key from the xpub using the derivation path found in the
316
+ * PSBT input, then verifies the signature. It supports both ECDSA signatures (for legacy/SegWit
317
+ * inputs) and Schnorr signatures (for Taproot script path inputs).
318
+ *
319
+ * # Arguments
320
+ * - `input_index`: The index of the input to check
321
+ * - `xpub_str`: The extended public key as a base58-encoded string
322
+ *
323
+ * # Returns
324
+ * - `Ok(true)` if a valid signature exists for the derived public key
325
+ * - `Ok(false)` if no signature exists for the derived public key
326
+ * - `Err(WasmUtxoError)` if the input index is out of bounds, xpub is invalid, derivation fails, or verification fails
327
+ * @param {number} input_index
328
+ * @param {string} xpub_str
329
+ * @returns {boolean}
330
+ */
331
+ verify_signature(input_index, xpub_str) {
332
+ try {
333
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
334
+ const ptr0 = passStringToWasm0(xpub_str, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
335
+ const len0 = WASM_VECTOR_LEN;
336
+ wasm.bitgopsbt_verify_signature(retptr, this.__wbg_ptr, input_index, ptr0, len0);
337
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
338
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
339
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
340
+ if (r2) {
341
+ throw takeObject(r1);
342
+ }
343
+ return r0 !== 0;
344
+ } finally {
345
+ wasm.__wbindgen_add_to_stack_pointer(16);
346
+ }
347
+ }
292
348
  /**
293
349
  * Parse outputs with wallet keys to identify which outputs belong to a wallet
294
350
  *
@@ -332,6 +388,41 @@ export class BitGoPsbt {
332
388
  wasm.__wbindgen_add_to_stack_pointer(16);
333
389
  }
334
390
  }
391
+ /**
392
+ * Verify if a replay protection input has a valid signature
393
+ *
394
+ * This method checks if a given input is a replay protection input and cryptographically verifies
395
+ * the signature. Replay protection inputs (like P2shP2pk) don't use standard derivation paths,
396
+ * so this method verifies signatures without deriving from xpub.
397
+ *
398
+ * # Arguments
399
+ * - `input_index`: The index of the input to check
400
+ * - `replay_protection`: Replay protection configuration (same format as parseTransactionWithWalletKeys)
401
+ * Can be either `{ outputScripts: Buffer[] }` or `{ addresses: string[] }`
402
+ *
403
+ * # Returns
404
+ * - `Ok(true)` if the input is a replay protection input and has a valid signature
405
+ * - `Ok(false)` if the input is a replay protection input but has no valid signature
406
+ * - `Err(WasmUtxoError)` if the input is not a replay protection input, index is out of bounds, or configuration is invalid
407
+ * @param {number} input_index
408
+ * @param {any} replay_protection
409
+ * @returns {boolean}
410
+ */
411
+ verify_replay_protection_signature(input_index, replay_protection) {
412
+ try {
413
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
414
+ wasm.bitgopsbt_verify_replay_protection_signature(retptr, this.__wbg_ptr, input_index, addHeapObject(replay_protection));
415
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
416
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
417
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
418
+ if (r2) {
419
+ throw takeObject(r1);
420
+ }
421
+ return r0 !== 0;
422
+ } finally {
423
+ wasm.__wbindgen_add_to_stack_pointer(16);
424
+ }
425
+ }
335
426
  }
336
427
  if (Symbol.dispose) BitGoPsbt.prototype[Symbol.dispose] = BitGoPsbt.prototype.free;
337
428
 
@@ -1,14 +1,29 @@
1
1
  /* tslint:disable */
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
+ export const __wbg_bitgopsbt_free: (a: number, b: number) => void;
5
+ export const __wbg_fixedscriptwalletnamespace_free: (a: number, b: number) => void;
6
+ export const __wbg_wrappsbt_free: (a: number, b: number) => void;
7
+ export const bitgopsbt_from_bytes: (a: number, b: number, c: number, d: number, e: number) => void;
8
+ export const bitgopsbt_parse_outputs_with_wallet_keys: (a: number, b: number, c: number) => void;
9
+ export const bitgopsbt_parse_transaction_with_wallet_keys: (a: number, b: number, c: number, d: number) => void;
10
+ export const bitgopsbt_unsigned_txid: (a: number, b: number) => void;
11
+ export const bitgopsbt_verify_replay_protection_signature: (a: number, b: number, c: number, d: number) => void;
12
+ export const bitgopsbt_verify_signature: (a: number, b: number, c: number, d: number, e: number) => void;
13
+ export const fixedscriptwalletnamespace_address: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
14
+ export const fixedscriptwalletnamespace_output_script: (a: number, b: number, c: number, d: number, e: number) => void;
15
+ export const wrappsbt_clone: (a: number) => number;
16
+ export const wrappsbt_deserialize: (a: number, b: number, c: number) => void;
17
+ export const wrappsbt_finalize: (a: number, b: number) => void;
18
+ export const wrappsbt_serialize: (a: number, b: number) => void;
19
+ export const wrappsbt_signWithPrv: (a: number, b: number, c: number, d: number) => void;
20
+ export const wrappsbt_signWithXprv: (a: number, b: number, c: number, d: number) => void;
21
+ export const wrappsbt_updateInputWithDescriptor: (a: number, b: number, c: number, d: number) => void;
22
+ export const wrappsbt_updateOutputWithDescriptor: (a: number, b: number, c: number, d: number) => void;
4
23
  export const __wbg_addressnamespace_free: (a: number, b: number) => void;
5
- export const __wbg_utxolibcompatnamespace_free: (a: number, b: number) => void;
6
- export const __wbg_wrapdescriptor_free: (a: number, b: number) => void;
7
- export const __wbg_wrapminiscript_free: (a: number, b: number) => void;
8
24
  export const addressnamespace_from_output_script_with_coin: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
9
25
  export const addressnamespace_to_output_script_with_coin: (a: number, b: number, c: number, d: number, e: number) => void;
10
- export const utxolibcompatnamespace_from_output_script: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
11
- export const utxolibcompatnamespace_to_output_script: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
26
+ export const __wbg_wrapdescriptor_free: (a: number, b: number) => void;
12
27
  export const wrapdescriptor_atDerivationIndex: (a: number, b: number, c: number) => void;
13
28
  export const wrapdescriptor_descType: (a: number, b: number) => void;
14
29
  export const wrapdescriptor_encode: (a: number, b: number) => void;
@@ -20,28 +35,16 @@ export const wrapdescriptor_node: (a: number, b: number) => void;
20
35
  export const wrapdescriptor_scriptPubkey: (a: number, b: number) => void;
21
36
  export const wrapdescriptor_toAsmString: (a: number, b: number) => void;
22
37
  export const wrapdescriptor_toString: (a: number, b: number) => void;
38
+ export const __wbg_utxolibcompatnamespace_free: (a: number, b: number) => void;
39
+ export const __wbg_wrapminiscript_free: (a: number, b: number) => void;
40
+ export const utxolibcompatnamespace_from_output_script: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
41
+ export const utxolibcompatnamespace_to_output_script: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
23
42
  export const wrapminiscript_encode: (a: number, b: number) => void;
24
43
  export const wrapminiscript_fromBitcoinScript: (a: number, b: number, c: number, d: number, e: number) => void;
25
44
  export const wrapminiscript_fromString: (a: number, b: number, c: number, d: number, e: number) => void;
26
45
  export const wrapminiscript_node: (a: number, b: number) => void;
27
46
  export const wrapminiscript_toAsmString: (a: number, b: number) => void;
28
47
  export const wrapminiscript_toString: (a: number, b: number) => void;
29
- export const __wbg_bitgopsbt_free: (a: number, b: number) => void;
30
- export const __wbg_fixedscriptwalletnamespace_free: (a: number, b: number) => void;
31
- export const __wbg_wrappsbt_free: (a: number, b: number) => void;
32
- export const bitgopsbt_from_bytes: (a: number, b: number, c: number, d: number, e: number) => void;
33
- export const bitgopsbt_parse_outputs_with_wallet_keys: (a: number, b: number, c: number) => void;
34
- export const bitgopsbt_parse_transaction_with_wallet_keys: (a: number, b: number, c: number, d: number) => void;
35
- export const fixedscriptwalletnamespace_address: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
36
- export const fixedscriptwalletnamespace_output_script: (a: number, b: number, c: number, d: number, e: number) => void;
37
- export const wrappsbt_clone: (a: number) => number;
38
- export const wrappsbt_deserialize: (a: number, b: number, c: number) => void;
39
- export const wrappsbt_finalize: (a: number, b: number) => void;
40
- export const wrappsbt_serialize: (a: number, b: number) => void;
41
- export const wrappsbt_signWithPrv: (a: number, b: number, c: number, d: number) => void;
42
- export const wrappsbt_signWithXprv: (a: number, b: number, c: number, d: number) => void;
43
- export const wrappsbt_updateInputWithDescriptor: (a: number, b: number, c: number, d: number) => void;
44
- export const wrappsbt_updateOutputWithDescriptor: (a: number, b: number, c: number, d: number) => void;
45
48
  export const rustsecp256k1_v0_10_0_context_create: (a: number) => number;
46
49
  export const rustsecp256k1_v0_10_0_context_destroy: (a: number) => void;
47
50
  export const rustsecp256k1_v0_10_0_default_error_callback_fn: (a: number, b: number) => void;
@@ -63,6 +63,11 @@ export declare class BitGoPsbt {
63
63
  * @returns A BitGoPsbt instance
64
64
  */
65
65
  static fromBytes(bytes: Uint8Array, network: NetworkName): BitGoPsbt;
66
+ /**
67
+ * Get the unsigned transaction ID
68
+ * @returns The unsigned transaction ID
69
+ */
70
+ unsignedTxid(): string;
66
71
  /**
67
72
  * Parse transaction with wallet keys to identify wallet inputs/outputs
68
73
  * @param walletKeys - The wallet keys to use for identification
@@ -82,5 +87,39 @@ export declare class BitGoPsbt {
82
87
  * @note This method does NOT validate wallet inputs. It only parses outputs.
83
88
  */
84
89
  parseOutputsWithWalletKeys(walletKeys: WalletKeys): ParsedOutput[];
90
+ /**
91
+ * Verify if a valid signature exists for a given extended public key at the specified input index.
92
+ *
93
+ * This method derives the public key from the xpub using the derivation path found in the
94
+ * PSBT input, then verifies the signature. It supports:
95
+ * - ECDSA signatures (for legacy/SegWit inputs)
96
+ * - Schnorr signatures (for Taproot script path inputs)
97
+ * - MuSig2 partial signatures (for Taproot keypath MuSig2 inputs)
98
+ *
99
+ * @param inputIndex - The index of the input to check (0-based)
100
+ * @param xpub - The extended public key as a base58-encoded string
101
+ * @returns true if a valid signature exists, false if no signature exists
102
+ * @throws Error if input index is out of bounds, xpub is invalid, or verification fails
103
+ */
104
+ verifySignature(inputIndex: number, xpub: string): boolean;
105
+ /**
106
+ * Verify if a replay protection input has a valid signature.
107
+ *
108
+ * This method checks if a given input is a replay protection input (like P2shP2pk) and verifies
109
+ * the signature. Replay protection inputs don't use standard derivation paths, so this method
110
+ * verifies signatures without deriving from xpub.
111
+ *
112
+ * For P2PK replay protection inputs, this:
113
+ * - Extracts the signature from final_script_sig
114
+ * - Extracts the public key from redeem_script
115
+ * - Computes the legacy P2SH sighash
116
+ * - Verifies the ECDSA signature cryptographically
117
+ *
118
+ * @param inputIndex - The index of the input to check (0-based)
119
+ * @param replayProtection - Scripts that identify replay protection inputs (same format as parseTransactionWithWalletKeys)
120
+ * @returns true if the input is a replay protection input and has a valid signature, false if no valid signature
121
+ * @throws Error if the input is not a replay protection input, index is out of bounds, or scripts are invalid
122
+ */
123
+ verifyReplayProtectionSignature(inputIndex: number, replayProtection: ReplayProtection): boolean;
85
124
  }
86
125
  export {};
@@ -41,6 +41,13 @@ class BitGoPsbt {
41
41
  const wasm = wasm_utxo_2.BitGoPsbt.from_bytes(bytes, network);
42
42
  return new BitGoPsbt(wasm);
43
43
  }
44
+ /**
45
+ * Get the unsigned transaction ID
46
+ * @returns The unsigned transaction ID
47
+ */
48
+ unsignedTxid() {
49
+ return this.wasm.unsigned_txid();
50
+ }
44
51
  /**
45
52
  * Parse transaction with wallet keys to identify wallet inputs/outputs
46
53
  * @param walletKeys - The wallet keys to use for identification
@@ -64,5 +71,43 @@ class BitGoPsbt {
64
71
  parseOutputsWithWalletKeys(walletKeys) {
65
72
  return this.wasm.parse_outputs_with_wallet_keys(walletKeys);
66
73
  }
74
+ /**
75
+ * Verify if a valid signature exists for a given extended public key at the specified input index.
76
+ *
77
+ * This method derives the public key from the xpub using the derivation path found in the
78
+ * PSBT input, then verifies the signature. It supports:
79
+ * - ECDSA signatures (for legacy/SegWit inputs)
80
+ * - Schnorr signatures (for Taproot script path inputs)
81
+ * - MuSig2 partial signatures (for Taproot keypath MuSig2 inputs)
82
+ *
83
+ * @param inputIndex - The index of the input to check (0-based)
84
+ * @param xpub - The extended public key as a base58-encoded string
85
+ * @returns true if a valid signature exists, false if no signature exists
86
+ * @throws Error if input index is out of bounds, xpub is invalid, or verification fails
87
+ */
88
+ verifySignature(inputIndex, xpub) {
89
+ return this.wasm.verify_signature(inputIndex, xpub);
90
+ }
91
+ /**
92
+ * Verify if a replay protection input has a valid signature.
93
+ *
94
+ * This method checks if a given input is a replay protection input (like P2shP2pk) and verifies
95
+ * the signature. Replay protection inputs don't use standard derivation paths, so this method
96
+ * verifies signatures without deriving from xpub.
97
+ *
98
+ * For P2PK replay protection inputs, this:
99
+ * - Extracts the signature from final_script_sig
100
+ * - Extracts the public key from redeem_script
101
+ * - Computes the legacy P2SH sighash
102
+ * - Verifies the ECDSA signature cryptographically
103
+ *
104
+ * @param inputIndex - The index of the input to check (0-based)
105
+ * @param replayProtection - Scripts that identify replay protection inputs (same format as parseTransactionWithWalletKeys)
106
+ * @returns true if the input is a replay protection input and has a valid signature, false if no valid signature
107
+ * @throws Error if the input is not a replay protection input, index is out of bounds, or scripts are invalid
108
+ */
109
+ verifyReplayProtectionSignature(inputIndex, replayProtection) {
110
+ return this.wasm.verify_replay_protection_signature(inputIndex, replayProtection);
111
+ }
67
112
  }
68
113
  exports.BitGoPsbt = BitGoPsbt;
@@ -15,6 +15,27 @@ export class BitGoPsbt {
15
15
  * Deserialize a PSBT from bytes with network-specific logic
16
16
  */
17
17
  static from_bytes(bytes: Uint8Array, network: string): BitGoPsbt;
18
+ /**
19
+ * Get the unsigned transaction ID
20
+ */
21
+ unsigned_txid(): string;
22
+ /**
23
+ * Verify if a valid signature exists for a given xpub at the specified input index
24
+ *
25
+ * This method derives the public key from the xpub using the derivation path found in the
26
+ * PSBT input, then verifies the signature. It supports both ECDSA signatures (for legacy/SegWit
27
+ * inputs) and Schnorr signatures (for Taproot script path inputs).
28
+ *
29
+ * # Arguments
30
+ * - `input_index`: The index of the input to check
31
+ * - `xpub_str`: The extended public key as a base58-encoded string
32
+ *
33
+ * # Returns
34
+ * - `Ok(true)` if a valid signature exists for the derived public key
35
+ * - `Ok(false)` if no signature exists for the derived public key
36
+ * - `Err(WasmUtxoError)` if the input index is out of bounds, xpub is invalid, derivation fails, or verification fails
37
+ */
38
+ verify_signature(input_index: number, xpub_str: string): boolean;
18
39
  /**
19
40
  * Parse outputs with wallet keys to identify which outputs belong to a wallet
20
41
  *
@@ -25,6 +46,24 @@ export class BitGoPsbt {
25
46
  * Parse transaction with wallet keys to identify wallet inputs/outputs
26
47
  */
27
48
  parse_transaction_with_wallet_keys(wallet_keys: any, replay_protection: any): any;
49
+ /**
50
+ * Verify if a replay protection input has a valid signature
51
+ *
52
+ * This method checks if a given input is a replay protection input and cryptographically verifies
53
+ * the signature. Replay protection inputs (like P2shP2pk) don't use standard derivation paths,
54
+ * so this method verifies signatures without deriving from xpub.
55
+ *
56
+ * # Arguments
57
+ * - `input_index`: The index of the input to check
58
+ * - `replay_protection`: Replay protection configuration (same format as parseTransactionWithWalletKeys)
59
+ * Can be either `{ outputScripts: Buffer[] }` or `{ addresses: string[] }`
60
+ *
61
+ * # Returns
62
+ * - `Ok(true)` if the input is a replay protection input and has a valid signature
63
+ * - `Ok(false)` if the input is a replay protection input but has no valid signature
64
+ * - `Err(WasmUtxoError)` if the input is not a replay protection input, index is out of bounds, or configuration is invalid
65
+ */
66
+ verify_replay_protection_signature(input_index: number, replay_protection: any): boolean;
28
67
  }
29
68
  export class FixedScriptWalletNamespace {
30
69
  private constructor();
@@ -281,6 +281,62 @@ class BitGoPsbt {
281
281
  wasm.__wbindgen_add_to_stack_pointer(16);
282
282
  }
283
283
  }
284
+ /**
285
+ * Get the unsigned transaction ID
286
+ * @returns {string}
287
+ */
288
+ unsigned_txid() {
289
+ let deferred1_0;
290
+ let deferred1_1;
291
+ try {
292
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
293
+ wasm.bitgopsbt_unsigned_txid(retptr, this.__wbg_ptr);
294
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
295
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
296
+ deferred1_0 = r0;
297
+ deferred1_1 = r1;
298
+ return getStringFromWasm0(r0, r1);
299
+ } finally {
300
+ wasm.__wbindgen_add_to_stack_pointer(16);
301
+ wasm.__wbindgen_export_3(deferred1_0, deferred1_1, 1);
302
+ }
303
+ }
304
+ /**
305
+ * Verify if a valid signature exists for a given xpub at the specified input index
306
+ *
307
+ * This method derives the public key from the xpub using the derivation path found in the
308
+ * PSBT input, then verifies the signature. It supports both ECDSA signatures (for legacy/SegWit
309
+ * inputs) and Schnorr signatures (for Taproot script path inputs).
310
+ *
311
+ * # Arguments
312
+ * - `input_index`: The index of the input to check
313
+ * - `xpub_str`: The extended public key as a base58-encoded string
314
+ *
315
+ * # Returns
316
+ * - `Ok(true)` if a valid signature exists for the derived public key
317
+ * - `Ok(false)` if no signature exists for the derived public key
318
+ * - `Err(WasmUtxoError)` if the input index is out of bounds, xpub is invalid, derivation fails, or verification fails
319
+ * @param {number} input_index
320
+ * @param {string} xpub_str
321
+ * @returns {boolean}
322
+ */
323
+ verify_signature(input_index, xpub_str) {
324
+ try {
325
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
326
+ const ptr0 = passStringToWasm0(xpub_str, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
327
+ const len0 = WASM_VECTOR_LEN;
328
+ wasm.bitgopsbt_verify_signature(retptr, this.__wbg_ptr, input_index, ptr0, len0);
329
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
330
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
331
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
332
+ if (r2) {
333
+ throw takeObject(r1);
334
+ }
335
+ return r0 !== 0;
336
+ } finally {
337
+ wasm.__wbindgen_add_to_stack_pointer(16);
338
+ }
339
+ }
284
340
  /**
285
341
  * Parse outputs with wallet keys to identify which outputs belong to a wallet
286
342
  *
@@ -324,6 +380,41 @@ class BitGoPsbt {
324
380
  wasm.__wbindgen_add_to_stack_pointer(16);
325
381
  }
326
382
  }
383
+ /**
384
+ * Verify if a replay protection input has a valid signature
385
+ *
386
+ * This method checks if a given input is a replay protection input and cryptographically verifies
387
+ * the signature. Replay protection inputs (like P2shP2pk) don't use standard derivation paths,
388
+ * so this method verifies signatures without deriving from xpub.
389
+ *
390
+ * # Arguments
391
+ * - `input_index`: The index of the input to check
392
+ * - `replay_protection`: Replay protection configuration (same format as parseTransactionWithWalletKeys)
393
+ * Can be either `{ outputScripts: Buffer[] }` or `{ addresses: string[] }`
394
+ *
395
+ * # Returns
396
+ * - `Ok(true)` if the input is a replay protection input and has a valid signature
397
+ * - `Ok(false)` if the input is a replay protection input but has no valid signature
398
+ * - `Err(WasmUtxoError)` if the input is not a replay protection input, index is out of bounds, or configuration is invalid
399
+ * @param {number} input_index
400
+ * @param {any} replay_protection
401
+ * @returns {boolean}
402
+ */
403
+ verify_replay_protection_signature(input_index, replay_protection) {
404
+ try {
405
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
406
+ wasm.bitgopsbt_verify_replay_protection_signature(retptr, this.__wbg_ptr, input_index, addHeapObject(replay_protection));
407
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
408
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
409
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
410
+ if (r2) {
411
+ throw takeObject(r1);
412
+ }
413
+ return r0 !== 0;
414
+ } finally {
415
+ wasm.__wbindgen_add_to_stack_pointer(16);
416
+ }
417
+ }
327
418
  }
328
419
  if (Symbol.dispose) BitGoPsbt.prototype[Symbol.dispose] = BitGoPsbt.prototype.free;
329
420
 
Binary file
@@ -1,14 +1,29 @@
1
1
  /* tslint:disable */
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
+ export const __wbg_bitgopsbt_free: (a: number, b: number) => void;
5
+ export const __wbg_fixedscriptwalletnamespace_free: (a: number, b: number) => void;
6
+ export const __wbg_wrappsbt_free: (a: number, b: number) => void;
7
+ export const bitgopsbt_from_bytes: (a: number, b: number, c: number, d: number, e: number) => void;
8
+ export const bitgopsbt_parse_outputs_with_wallet_keys: (a: number, b: number, c: number) => void;
9
+ export const bitgopsbt_parse_transaction_with_wallet_keys: (a: number, b: number, c: number, d: number) => void;
10
+ export const bitgopsbt_unsigned_txid: (a: number, b: number) => void;
11
+ export const bitgopsbt_verify_replay_protection_signature: (a: number, b: number, c: number, d: number) => void;
12
+ export const bitgopsbt_verify_signature: (a: number, b: number, c: number, d: number, e: number) => void;
13
+ export const fixedscriptwalletnamespace_address: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
14
+ export const fixedscriptwalletnamespace_output_script: (a: number, b: number, c: number, d: number, e: number) => void;
15
+ export const wrappsbt_clone: (a: number) => number;
16
+ export const wrappsbt_deserialize: (a: number, b: number, c: number) => void;
17
+ export const wrappsbt_finalize: (a: number, b: number) => void;
18
+ export const wrappsbt_serialize: (a: number, b: number) => void;
19
+ export const wrappsbt_signWithPrv: (a: number, b: number, c: number, d: number) => void;
20
+ export const wrappsbt_signWithXprv: (a: number, b: number, c: number, d: number) => void;
21
+ export const wrappsbt_updateInputWithDescriptor: (a: number, b: number, c: number, d: number) => void;
22
+ export const wrappsbt_updateOutputWithDescriptor: (a: number, b: number, c: number, d: number) => void;
4
23
  export const __wbg_addressnamespace_free: (a: number, b: number) => void;
5
- export const __wbg_utxolibcompatnamespace_free: (a: number, b: number) => void;
6
- export const __wbg_wrapdescriptor_free: (a: number, b: number) => void;
7
- export const __wbg_wrapminiscript_free: (a: number, b: number) => void;
8
24
  export const addressnamespace_from_output_script_with_coin: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
9
25
  export const addressnamespace_to_output_script_with_coin: (a: number, b: number, c: number, d: number, e: number) => void;
10
- export const utxolibcompatnamespace_from_output_script: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
11
- export const utxolibcompatnamespace_to_output_script: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
26
+ export const __wbg_wrapdescriptor_free: (a: number, b: number) => void;
12
27
  export const wrapdescriptor_atDerivationIndex: (a: number, b: number, c: number) => void;
13
28
  export const wrapdescriptor_descType: (a: number, b: number) => void;
14
29
  export const wrapdescriptor_encode: (a: number, b: number) => void;
@@ -20,28 +35,16 @@ export const wrapdescriptor_node: (a: number, b: number) => void;
20
35
  export const wrapdescriptor_scriptPubkey: (a: number, b: number) => void;
21
36
  export const wrapdescriptor_toAsmString: (a: number, b: number) => void;
22
37
  export const wrapdescriptor_toString: (a: number, b: number) => void;
38
+ export const __wbg_utxolibcompatnamespace_free: (a: number, b: number) => void;
39
+ export const __wbg_wrapminiscript_free: (a: number, b: number) => void;
40
+ export const utxolibcompatnamespace_from_output_script: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
41
+ export const utxolibcompatnamespace_to_output_script: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
23
42
  export const wrapminiscript_encode: (a: number, b: number) => void;
24
43
  export const wrapminiscript_fromBitcoinScript: (a: number, b: number, c: number, d: number, e: number) => void;
25
44
  export const wrapminiscript_fromString: (a: number, b: number, c: number, d: number, e: number) => void;
26
45
  export const wrapminiscript_node: (a: number, b: number) => void;
27
46
  export const wrapminiscript_toAsmString: (a: number, b: number) => void;
28
47
  export const wrapminiscript_toString: (a: number, b: number) => void;
29
- export const __wbg_bitgopsbt_free: (a: number, b: number) => void;
30
- export const __wbg_fixedscriptwalletnamespace_free: (a: number, b: number) => void;
31
- export const __wbg_wrappsbt_free: (a: number, b: number) => void;
32
- export const bitgopsbt_from_bytes: (a: number, b: number, c: number, d: number, e: number) => void;
33
- export const bitgopsbt_parse_outputs_with_wallet_keys: (a: number, b: number, c: number) => void;
34
- export const bitgopsbt_parse_transaction_with_wallet_keys: (a: number, b: number, c: number, d: number) => void;
35
- export const fixedscriptwalletnamespace_address: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
36
- export const fixedscriptwalletnamespace_output_script: (a: number, b: number, c: number, d: number, e: number) => void;
37
- export const wrappsbt_clone: (a: number) => number;
38
- export const wrappsbt_deserialize: (a: number, b: number, c: number) => void;
39
- export const wrappsbt_finalize: (a: number, b: number) => void;
40
- export const wrappsbt_serialize: (a: number, b: number) => void;
41
- export const wrappsbt_signWithPrv: (a: number, b: number, c: number, d: number) => void;
42
- export const wrappsbt_signWithXprv: (a: number, b: number, c: number, d: number) => void;
43
- export const wrappsbt_updateInputWithDescriptor: (a: number, b: number, c: number, d: number) => void;
44
- export const wrappsbt_updateOutputWithDescriptor: (a: number, b: number, c: number, d: number) => void;
45
48
  export const rustsecp256k1_v0_10_0_context_create: (a: number) => number;
46
49
  export const rustsecp256k1_v0_10_0_context_destroy: (a: number) => void;
47
50
  export const rustsecp256k1_v0_10_0_default_error_callback_fn: (a: number, b: number) => void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bitgo/wasm-utxo",
3
3
  "description": "WebAssembly wrapper for rust-bitcoin (beta)",
4
- "version": "1.0.0",
4
+ "version": "1.2.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/BitGo/BitGoWASM"
@@ -23,6 +23,37 @@
23
23
  ],
24
24
  "main": "dist/node/js/index.js",
25
25
  "types": "dist/node/js/index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/node/js/index.d.ts",
29
+ "browser": "./dist/browser/js/index.js",
30
+ "default": "./dist/node/js/index.js"
31
+ },
32
+ "./address": {
33
+ "types": "./dist/node/js/address.d.ts",
34
+ "browser": "./dist/browser/js/address.js",
35
+ "default": "./dist/node/js/address.js"
36
+ },
37
+ "./ast": {
38
+ "types": "./dist/node/js/ast/index.d.ts",
39
+ "browser": "./dist/browser/js/ast/index.js",
40
+ "default": "./dist/node/js/ast/index.js"
41
+ },
42
+ "./fixedScriptWallet": {
43
+ "types": "./dist/node/js/fixedScriptWallet.d.ts",
44
+ "browser": "./dist/browser/js/fixedScriptWallet.js",
45
+ "default": "./dist/node/js/fixedScriptWallet.js"
46
+ },
47
+ "./utxolibCompat": {
48
+ "types": "./dist/node/js/utxolibCompat.d.ts",
49
+ "browser": "./dist/browser/js/utxolibCompat.js",
50
+ "default": "./dist/node/js/utxolibCompat.js"
51
+ },
52
+ "./dist/browser/js/wasm/wasm_utxo_bg.js": "./dist/browser/js/wasm/wasm_utxo_bg.js",
53
+ "./dist/browser/js/wasm/wasm_utxo_bg.wasm": "./dist/browser/js/wasm/wasm_utxo_bg.wasm",
54
+ "./dist/node/js/wasm/wasm_utxo_bg.js": "./dist/node/js/wasm/wasm_utxo_bg.js",
55
+ "./dist/node/js/wasm/wasm_utxo_bg.wasm": "./dist/node/js/wasm/wasm_utxo_bg.wasm"
56
+ },
26
57
  "sideEffects": [
27
58
  "./dist/node/js/wasm/wasm_utxo.js",
28
59
  "./dist/browser/js/wasm/wasm_utxo.js"