|
| 1 | +import { WasmReplayProtection } from "../wasm/wasm_utxo.js"; |
| 2 | +import { type ECPairArg, ECPair } from "../ecpair.js"; |
| 3 | + |
| 4 | +/** |
| 5 | + * ReplayProtectionArg represents the various forms that replay protection can take |
| 6 | + * before being converted to a WasmReplayProtection instance |
| 7 | + */ |
| 8 | +export type ReplayProtectionArg = |
| 9 | + | ReplayProtection |
| 10 | + | WasmReplayProtection |
| 11 | + | { |
| 12 | + publicKeys: ECPairArg[]; |
| 13 | + } |
| 14 | + | { |
| 15 | + /** @deprecated - use publicKeys instead */ |
| 16 | + outputScripts: Uint8Array[]; |
| 17 | + } |
| 18 | + | { |
| 19 | + /** @deprecated - use publicKeys instead */ |
| 20 | + addresses: string[]; |
| 21 | + }; |
| 22 | + |
| 23 | +/** |
| 24 | + * ReplayProtection wrapper class for PSBT replay protection inputs |
| 25 | + */ |
| 26 | +export class ReplayProtection { |
| 27 | + private constructor(private _wasm: WasmReplayProtection) {} |
| 28 | + |
| 29 | + /** |
| 30 | + * Create a ReplayProtection instance from a WasmReplayProtection instance (internal use) |
| 31 | + * @internal |
| 32 | + */ |
| 33 | + static fromWasm(wasm: WasmReplayProtection): ReplayProtection { |
| 34 | + return new ReplayProtection(wasm); |
| 35 | + } |
| 36 | + |
| 37 | + /** |
| 38 | + * Convert ReplayProtectionArg to ReplayProtection instance |
| 39 | + * @param arg - The replay protection in various formats |
| 40 | + * @param network - Optional network string (required for addresses variant) |
| 41 | + * @returns ReplayProtection instance |
| 42 | + */ |
| 43 | + static from(arg: ReplayProtectionArg, network?: string): ReplayProtection { |
| 44 | + // Short-circuit if already a ReplayProtection instance |
| 45 | + if (arg instanceof ReplayProtection) { |
| 46 | + return arg; |
| 47 | + } |
| 48 | + // If it's a WasmReplayProtection instance, wrap it |
| 49 | + if (arg instanceof WasmReplayProtection) { |
| 50 | + return new ReplayProtection(arg); |
| 51 | + } |
| 52 | + |
| 53 | + // Handle object variants |
| 54 | + if ("publicKeys" in arg) { |
| 55 | + // Convert ECPairArg to public key bytes |
| 56 | + const publicKeyBytes = arg.publicKeys.map((key) => ECPair.from(key).publicKey); |
| 57 | + const wasm = WasmReplayProtection.from_public_keys(publicKeyBytes); |
| 58 | + return new ReplayProtection(wasm); |
| 59 | + } |
| 60 | + |
| 61 | + if ("outputScripts" in arg) { |
| 62 | + const wasm = WasmReplayProtection.from_output_scripts(arg.outputScripts); |
| 63 | + return new ReplayProtection(wasm); |
| 64 | + } |
| 65 | + |
| 66 | + if ("addresses" in arg) { |
| 67 | + if (!network) { |
| 68 | + throw new Error("Network is required when using addresses variant"); |
| 69 | + } |
| 70 | + const wasm = WasmReplayProtection.from_addresses(arg.addresses, network); |
| 71 | + return new ReplayProtection(wasm); |
| 72 | + } |
| 73 | + |
| 74 | + throw new Error("Invalid ReplayProtectionArg type"); |
| 75 | + } |
| 76 | + |
| 77 | + /** |
| 78 | + * Create from public keys (derives P2SH-P2PK output scripts) |
| 79 | + * @param publicKeys - Array of ECPair instances or arguments |
| 80 | + * @returns ReplayProtection instance |
| 81 | + */ |
| 82 | + static fromPublicKeys(publicKeys: ECPairArg[]): ReplayProtection { |
| 83 | + return ReplayProtection.from({ publicKeys }); |
| 84 | + } |
| 85 | + |
| 86 | + /** |
| 87 | + * Create from output scripts |
| 88 | + * @param outputScripts - Array of output script buffers |
| 89 | + * @returns ReplayProtection instance |
| 90 | + */ |
| 91 | + static fromOutputScripts(outputScripts: Uint8Array[]): ReplayProtection { |
| 92 | + return ReplayProtection.from({ outputScripts }); |
| 93 | + } |
| 94 | + |
| 95 | + /** |
| 96 | + * Create from addresses |
| 97 | + * @param addresses - Array of address strings |
| 98 | + * @param network - Network string (e.g., "bitcoin", "testnet", "btc", "tbtc") |
| 99 | + * @returns ReplayProtection instance |
| 100 | + */ |
| 101 | + static fromAddresses(addresses: string[], network: string): ReplayProtection { |
| 102 | + return ReplayProtection.from({ addresses }, network); |
| 103 | + } |
| 104 | + |
| 105 | + /** |
| 106 | + * Get the underlying WASM instance (internal use only) |
| 107 | + * @internal |
| 108 | + */ |
| 109 | + get wasm(): WasmReplayProtection { |
| 110 | + return this._wasm; |
| 111 | + } |
| 112 | +} |
0 commit comments