Skip to content

Commit c8dde9b

Browse files
OttoAllmendingerllm-git
andcommitted
feat(wasm-utxo): refactor transaction parsing API
Refactor the PSBT transaction parsing interface to use structured options objects instead of individual parameters. This improves readability and makes the API more maintainable for future extensions. Specifically: - Add `ParseTransactionOptions` and `ParseOutputsOptions` types - Update `parseTransactionWithWalletKeys` and `parseOutputsWithWalletKeys` to use these option objects - Update all call sites to use the new API pattern Issue: BTC-2650 Co-authored-by: llm-git <llm-git@ttll.de>
1 parent 8348d4b commit c8dde9b

9 files changed

Lines changed: 39 additions & 23 deletions

File tree

packages/wasm-utxo/js/fixedScriptWallet/BitGoPsbt.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,15 @@ export type AddWalletOutputOptions = {
115115
value: bigint;
116116
};
117117

118+
export type ParseTransactionOptions = {
119+
replayProtection: ReplayProtectionArg;
120+
payGoPubkeys?: ECPairArg[];
121+
};
122+
123+
export type ParseOutputsOptions = {
124+
payGoPubkeys?: ECPairArg[];
125+
};
126+
118127
export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
119128
protected constructor(protected _wasm: WasmBitGoPsbt) {}
120129

@@ -424,18 +433,18 @@ export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
424433
/**
425434
* Parse transaction with wallet keys to identify wallet inputs/outputs
426435
* @param walletKeys - The wallet keys to use for identification
427-
* @param replayProtection - Scripts that are allowed as inputs without wallet validation
428-
* @param payGoPubkeys - Optional public keys for PayGo attestation verification
436+
* @param options - Options for parsing
437+
* @param options.replayProtection - Scripts that are allowed as inputs without wallet validation
438+
* @param options.payGoPubkeys - Optional public keys for PayGo attestation verification
429439
* @returns Parsed transaction information
430440
*/
431441
parseTransactionWithWalletKeys(
432442
walletKeys: WalletKeysArg,
433-
replayProtection: ReplayProtectionArg,
434-
payGoPubkeys?: ECPairArg[],
443+
options: ParseTransactionOptions,
435444
): ParsedTransaction {
436445
const keys = RootWalletKeys.from(walletKeys);
437-
const rp = ReplayProtection.from(replayProtection, this._wasm.network());
438-
const pubkeys = payGoPubkeys?.map((arg) => ECPair.from(arg).wasm);
446+
const rp = ReplayProtection.from(options.replayProtection, this._wasm.network());
447+
const pubkeys = options.payGoPubkeys?.map((arg) => ECPair.from(arg).wasm);
439448
return this._wasm.parse_transaction_with_wallet_keys(
440449
keys.wasm,
441450
rp.wasm,
@@ -451,16 +460,17 @@ export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
451460
* wallet than the inputs.
452461
*
453462
* @param walletKeys - The wallet keys to use for identification
454-
* @param payGoPubkeys - Optional public keys for PayGo attestation verification
463+
* @param options - Optional options for parsing
464+
* @param options.payGoPubkeys - Optional public keys for PayGo attestation verification
455465
* @returns Array of parsed outputs
456466
* @note This method does NOT validate wallet inputs. It only parses outputs.
457467
*/
458468
parseOutputsWithWalletKeys(
459469
walletKeys: WalletKeysArg,
460-
payGoPubkeys?: ECPairArg[],
470+
options?: ParseOutputsOptions,
461471
): ParsedOutput[] {
462472
const keys = RootWalletKeys.from(walletKeys);
463-
const pubkeys = payGoPubkeys?.map((arg) => ECPair.from(arg).wasm);
473+
const pubkeys = options?.payGoPubkeys?.map((arg) => ECPair.from(arg).wasm);
464474
return this._wasm.parse_outputs_with_wallet_keys(keys.wasm, pubkeys) as ParsedOutput[];
465475
}
466476

@@ -719,7 +729,7 @@ export class BitGoPsbt implements IPsbtIntrospectionWithAddress {
719729
* const counterpartyPsbt = BitGoPsbt.fromBytes(counterpartyPsbtBytes, network);
720730
* psbt.combineMusig2Nonces(counterpartyPsbt);
721731
* // Sign MuSig2 key path inputs
722-
* const parsed = psbt.parseTransactionWithWalletKeys(walletKeys, replayProtection);
732+
* const parsed = psbt.parseTransactionWithWalletKeys(walletKeys, { replayProtection });
723733
* for (let i = 0; i < parsed.inputs.length; i++) {
724734
* if (parsed.inputs[i].scriptType === "p2trMusig2KeyPath") {
725735
* psbt.sign(i, userXpriv);

packages/wasm-utxo/js/fixedScriptWallet/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export {
2828
type AddOutputOptions,
2929
type AddWalletInputOptions,
3030
type AddWalletOutputOptions,
31+
type ParseTransactionOptions,
32+
type ParseOutputsOptions,
3133
} from "./BitGoPsbt.js";
3234

3335
// Zcash-specific PSBT subclass

packages/wasm-utxo/test/acid-test/acidTest.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ describe("AcidTest", function () {
9595
// Verify no signatures present
9696
const rpKey = test.getReplayProtectionKey();
9797
const replayProtection = { publicKeys: [rpKey.publicKey] };
98-
const parsed = psbt.parseTransactionWithWalletKeys(test.rootWalletKeys, replayProtection);
98+
const parsed = psbt.parseTransactionWithWalletKeys(test.rootWalletKeys, { replayProtection });
9999
const user = test.rootWalletKeys.userKey();
100100
const backup = test.rootWalletKeys.backupKey();
101101
const bitgo = test.rootWalletKeys.bitgoKey();
@@ -128,7 +128,7 @@ describe("AcidTest", function () {
128128
// Verify one signature per input (user only)
129129
const rpKey = test.getReplayProtectionKey();
130130
const replayProtection = { publicKeys: [rpKey.publicKey] };
131-
const parsed = psbt.parseTransactionWithWalletKeys(test.rootWalletKeys, replayProtection);
131+
const parsed = psbt.parseTransactionWithWalletKeys(test.rootWalletKeys, { replayProtection });
132132
const user = test.rootWalletKeys.userKey();
133133
const backup = test.rootWalletKeys.backupKey();
134134
const bitgo = test.rootWalletKeys.bitgoKey();
@@ -175,7 +175,7 @@ describe("AcidTest", function () {
175175
// Verify two signatures per input (user + bitgo or user + backup)
176176
const rpKey = test.getReplayProtectionKey();
177177
const replayProtection = { publicKeys: [rpKey.publicKey] };
178-
const parsed = psbt.parseTransactionWithWalletKeys(test.rootWalletKeys, replayProtection);
178+
const parsed = psbt.parseTransactionWithWalletKeys(test.rootWalletKeys, { replayProtection });
179179
const user = test.rootWalletKeys.userKey();
180180
const backup = test.rootWalletKeys.backupKey();
181181
const bitgo = test.rootWalletKeys.bitgoKey();

packages/wasm-utxo/test/benchmark/signing.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,9 @@ function benchmarkPerInputSign(
173173
// Clone PSBT for this benchmark
174174
const testPsbt = BitGoPsbt.fromBytes(psbt.serialize(), "bitcoin");
175175

176-
const parsed = testPsbt.parseTransactionWithWalletKeys(walletKeys, { publicKeys: [] });
176+
const parsed = testPsbt.parseTransactionWithWalletKeys(walletKeys, {
177+
replayProtection: { publicKeys: [] },
178+
});
177179

178180
// For MuSig2, generate nonces first (not timed)
179181
if (scriptType.isMuSig2KeyPath) {

packages/wasm-utxo/test/fixedScript/dogecoinLOLAmount.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ describe("Dogecoin large output limit amount (LOL amounts) (1-in/1-out)", functi
3333
psbt.addWalletInput({ txid, vout: 0, value }, walletKeys, { scriptId: { chain: 0, index: 0 } });
3434
psbt.addWalletOutput(walletKeys, { chain: 0, index: 0, value });
3535

36-
const parsed = psbt.parseTransactionWithWalletKeys(walletKeys, { publicKeys: [] });
36+
const parsed = psbt.parseTransactionWithWalletKeys(walletKeys, {
37+
replayProtection: { publicKeys: [] },
38+
});
3739
assert.strictEqual(parsed.inputs.length, 1);
3840
assert.strictEqual(parsed.outputs.length, 1);
3941
assert.strictEqual(parsed.inputs[0].value, value);

packages/wasm-utxo/test/fixedScript/parseTransactionWithWalletKeys.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ describe("parseTransactionWithWalletKeys", function () {
6868

6969
it("should parse transaction and identify internal/external outputs", function () {
7070
const parsed = bitgoPsbt.parseTransactionWithWalletKeys(rootWalletKeys, {
71-
publicKeys: [replayProtectionKey],
71+
replayProtection: { publicKeys: [replayProtectionKey] },
7272
});
7373

7474
// Verify all inputs have addresses and values
@@ -190,7 +190,7 @@ describe("parseTransactionWithWalletKeys", function () {
190190

191191
it("should parse inputs with correct scriptType", function () {
192192
const parsed = bitgoPsbt.parseTransactionWithWalletKeys(rootWalletKeys, {
193-
publicKeys: [replayProtectionKey],
193+
replayProtection: { publicKeys: [replayProtectionKey] },
194194
});
195195

196196
// Verify all inputs have scriptType matching fixture
@@ -245,7 +245,7 @@ describe("parseTransactionWithWalletKeys", function () {
245245
assert.throws(
246246
() => {
247247
bitgoPsbt.parseTransactionWithWalletKeys(getOtherWalletKeys(), {
248-
publicKeys: [replayProtectionKey],
248+
replayProtection: { publicKeys: [replayProtectionKey] },
249249
});
250250
},
251251
(error: Error) => {

packages/wasm-utxo/test/fixedScript/paygoAttestation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ describe("PayGo Attestation", function () {
129129
"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
130130
"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
131131
],
132-
[pubkey],
132+
{ payGoPubkeys: [pubkey] },
133133
);
134134

135135
assert.strictEqual(outputs.length, 1);

packages/wasm-utxo/test/fixedScript/psbtReconstruction.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ describe("PSBT reconstruction", function () {
8282
// Parse the original PSBT to get inputs/outputs
8383
const replayProtectionKey = loadReplayProtectionKeyFromFixture(fixture);
8484
const parsedTx = originalPsbt.parseTransactionWithWalletKeys(rootWalletKeys, {
85-
publicKeys: [replayProtectionKey],
85+
replayProtection: { publicKeys: [replayProtectionKey] },
8686
});
8787

8888
// Parse outputs with other wallet keys to detect outputs from different wallet
@@ -211,7 +211,7 @@ describe("PSBT reconstruction", function () {
211211
it("should include sequence in parsed inputs", function () {
212212
const replayProtectionKey = loadReplayProtectionKeyFromFixture(fixture);
213213
const parsedTx = originalPsbt.parseTransactionWithWalletKeys(rootWalletKeys, {
214-
publicKeys: [replayProtectionKey],
214+
replayProtection: { publicKeys: [replayProtectionKey] },
215215
});
216216

217217
// Verify all inputs have sequence field
@@ -237,7 +237,7 @@ describe("PSBT reconstruction", function () {
237237

238238
const replayProtectionKey = loadReplayProtectionKeyFromFixture(fixture);
239239
const parsedTx = originalPsbt.parseTransactionWithWalletKeys(rootWalletKeys, {
240-
publicKeys: [replayProtectionKey],
240+
replayProtection: { publicKeys: [replayProtectionKey] },
241241
});
242242
const parsedOutputsOther = originalPsbt.parseOutputsWithWalletKeys(otherWalletKeys);
243243

packages/wasm-utxo/test/fixedScript/signAndVerifySignature.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ function verifyAllInputSignatures(
163163
signatureStage: SignatureStage,
164164
): void {
165165
const parsed = bitgoPsbt.parseTransactionWithWalletKeys(rootWalletKeys, {
166-
publicKeys: [replayProtectionKey],
166+
replayProtection: { publicKeys: [replayProtectionKey] },
167167
});
168168

169169
fixture.psbtInputs.forEach((input, index) => {

0 commit comments

Comments
 (0)