Skip to content

Commit 7d39f45

Browse files
OttoAllmendingerllm-git
andcommitted
feat(wasm-utxo): add BitGoPsbt class for transaction parsing
Implements a new BitGoPsbt class that allows parsing PSBT transactions to identify wallet inputs and outputs. This implementation provides: - PSBT deserialization with network-specific handling - Transaction parsing with wallet script identification - Input validation with replay protection support - Output classification (internal vs external) - Fee and spend amount calculations The implementation extracts derivation info from PSBT inputs/outputs to match against wallet keys, providing a structured view of transactions for wallet UIs and validation purposes. Added comprehensive tests for the new functionality across all supported networks. Includes TypeScript definitions and integration with existing fixed script wallet functionality. Issue: BTC-2652 Co-authored-by: llm-git <[email protected]>
1 parent 5eaa41b commit 7d39f45

File tree

9 files changed

+1120
-34
lines changed

9 files changed

+1120
-34
lines changed

packages/wasm-utxo/js/fixedScriptWallet.ts

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { FixedScriptWalletNamespace } from "./wasm/wasm_utxo";
2-
import type { UtxolibNetwork, UtxolibRootWalletKeys } from "./utxolibCompat";
2+
import type { UtxolibName, UtxolibNetwork, UtxolibRootWalletKeys } from "./utxolibCompat";
3+
import type { CoinName } from "./coinName";
34
import { Triple } from "./triple";
45
import { AddressFormat } from "./address";
56

7+
export type NetworkName = UtxolibName | CoinName;
8+
69
export type WalletKeys =
710
/** Just an xpub triple, will assume default derivation prefixes */
811
| Triple<string>
@@ -42,3 +45,65 @@ export function address(
4245
): string {
4346
return FixedScriptWalletNamespace.address(keys, chain, index, network, addressFormat);
4447
}
48+
49+
type ReplayProtection =
50+
| {
51+
outputScripts: Uint8Array[];
52+
}
53+
| {
54+
addresses: string[];
55+
};
56+
57+
export type ScriptId = { chain: number; index: number };
58+
59+
export type ParsedInput = {
60+
address?: string;
61+
script: Uint8Array;
62+
value: bigint;
63+
scriptId: ScriptId | undefined;
64+
};
65+
66+
export type ParsedOutput = {
67+
address?: string;
68+
script: Uint8Array;
69+
value: bigint;
70+
scriptId?: ScriptId;
71+
};
72+
73+
export type ParsedTransaction = {
74+
inputs: ParsedInput[];
75+
outputs: ParsedOutput[];
76+
spendAmount: bigint;
77+
minerFee: bigint;
78+
virtualSize: number;
79+
};
80+
81+
import { BitGoPsbt as WasmBitGoPsbt } from "./wasm/wasm_utxo";
82+
83+
export class BitGoPsbt {
84+
private constructor(private wasm: WasmBitGoPsbt) {}
85+
86+
/**
87+
* Deserialize a PSBT from bytes
88+
* @param bytes - The PSBT bytes
89+
* @param network - The network to use for deserialization (either utxolib name like "bitcoin" or coin name like "btc")
90+
* @returns A BitGoPsbt instance
91+
*/
92+
static fromBytes(bytes: Uint8Array, network: NetworkName): BitGoPsbt {
93+
const wasm = WasmBitGoPsbt.fromBytes(bytes, network);
94+
return new BitGoPsbt(wasm);
95+
}
96+
97+
/**
98+
* Parse transaction with wallet keys to identify wallet inputs/outputs
99+
* @param walletKeys - The wallet keys to use for identification
100+
* @param replayProtection - Scripts that are allowed as inputs without wallet validation
101+
* @returns Parsed transaction information
102+
*/
103+
parseTransactionWithWalletKeys(
104+
walletKeys: WalletKeys,
105+
replayProtection: ReplayProtection,
106+
): ParsedTransaction {
107+
return this.wasm.parseTransactionWithWalletKeys(walletKeys, replayProtection);
108+
}
109+
}

packages/wasm-utxo/js/utxolibCompat.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,29 @@ import type { AddressFormat } from "./address";
22
import { Triple } from "./triple";
33
import { UtxolibCompatNamespace } from "./wasm/wasm_utxo";
44

5+
export type UtxolibName =
6+
| "bitcoin"
7+
| "testnet"
8+
| "bitcoinTestnet4"
9+
| "bitcoinPublicSignet"
10+
| "bitcoinBitGoSignet"
11+
| "bitcoincash"
12+
| "bitcoincashTestnet"
13+
| "ecash"
14+
| "ecashTest"
15+
| "bitcoingold"
16+
| "bitcoingoldTestnet"
17+
| "bitcoinsv"
18+
| "bitcoinsvTestnet"
19+
| "dash"
20+
| "dashTest"
21+
| "dogecoin"
22+
| "dogecoinTest"
23+
| "litecoin"
24+
| "litecoinTest"
25+
| "zcash"
26+
| "zcashTest";
27+
528
export type BIP32Interface = {
629
network: {
730
bip32: {

0 commit comments

Comments
 (0)