Skip to content

Commit 1891484

Browse files
OttoAllmendingerllm-git
andcommitted
feat(wasm-utxo): add previousOutput field to ParsedInput
Add OutPoint type and previousOutput field to ParsedInput to expose transaction input's previous output information. This allows clients to access the txid and vout of the input directly from the parsed PSBT. Extended tests to verify the new field structure and data types. Issue: BTC-2786 Co-authored-by: llm-git <[email protected]>
1 parent 39dafdf commit 1891484

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ export type InputScriptType =
1919
| "p2trMusig2ScriptPath"
2020
| "p2trMusig2KeyPath";
2121

22+
export type OutPoint = {
23+
txid: string;
24+
vout: number;
25+
};
26+
2227
export type ParsedInput = {
28+
previousOutput: OutPoint;
2329
address: string;
2430
script: Uint8Array;
2531
value: bigint;

packages/wasm-utxo/src/fixed_script_wallet/bitgo_psbt/psbt_wallet_input.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ impl InputScriptType {
565565
/// Parsed input from a PSBT transaction
566566
#[derive(Debug, Clone)]
567567
pub struct ParsedInput {
568+
pub previous_output: OutPoint,
568569
pub address: String,
569570
pub script: Vec<u8>,
570571
pub value: u64,
@@ -627,6 +628,7 @@ impl ParsedInput {
627628
.map_err(ParseInputError::ScriptTypeDetection)?;
628629

629630
Ok(Self {
631+
previous_output: tx_input.previous_output,
630632
address,
631633
script: output_script.to_bytes(),
632634
value: value.to_sat(),

packages/wasm-utxo/src/wasm/try_into_js_value.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ impl TryIntoJsValue for crate::fixed_script_wallet::bitgo_psbt::InputScriptType
336336
impl TryIntoJsValue for crate::fixed_script_wallet::bitgo_psbt::ParsedInput {
337337
fn try_to_js_value(&self) -> Result<JsValue, WasmUtxoError> {
338338
js_obj!(
339+
"previousOutput" => js_obj!("txid" => self.previous_output.txid.to_string(), "vout" => self.previous_output.vout)?,
339340
"address" => self.address.clone(),
340341
"value" => self.value,
341342
"scriptId" => self.script_id,

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

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,59 @@ describe("parseTransactionWithWalletKeys", function () {
8383

8484
// Verify all inputs have addresses and values
8585
parsed.inputs.forEach((input, i) => {
86+
// Verify previousOutput structure
87+
assert.ok(input.previousOutput, `Input ${i} should have previousOutput`);
88+
assert.ok(
89+
typeof input.previousOutput === "object",
90+
`Input ${i} previousOutput should be an object`,
91+
);
92+
assert.ok(
93+
typeof input.previousOutput.txid === "string",
94+
`Input ${i} previousOutput.txid should be string`,
95+
);
96+
assert.strictEqual(
97+
input.previousOutput.txid.length,
98+
64,
99+
`Input ${i} previousOutput.txid should be 64 chars (32 bytes hex)`,
100+
);
101+
assert.ok(
102+
typeof input.previousOutput.vout === "number",
103+
`Input ${i} previousOutput.vout should be number`,
104+
);
105+
assert.ok(
106+
input.previousOutput.vout >= 0,
107+
`Input ${i} previousOutput.vout should be >= 0`,
108+
);
109+
110+
// Verify address
86111
assert.ok(input.address, `Input ${i} should have an address`);
112+
assert.ok(typeof input.address === "string", `Input ${i} address should be string`);
113+
114+
// Verify value
87115
assert.ok(typeof input.value === "bigint", `Input ${i} value should be bigint`);
88116
assert.ok(input.value > 0n, `Input ${i} value should be > 0`);
117+
118+
// Verify scriptId structure (can be null for replay protection inputs)
119+
if (input.scriptId !== null) {
120+
assert.ok(
121+
typeof input.scriptId === "object",
122+
`Input ${i} scriptId should be an object when present`,
123+
);
124+
assert.ok(
125+
typeof input.scriptId.chain === "number",
126+
`Input ${i} scriptId.chain should be number`,
127+
);
128+
assert.ok(
129+
typeof input.scriptId.index === "number",
130+
`Input ${i} scriptId.index should be number`,
131+
);
132+
assert.ok(input.scriptId.chain >= 0, `Input ${i} scriptId.chain should be >= 0`);
133+
assert.ok(input.scriptId.index >= 0, `Input ${i} scriptId.index should be >= 0`);
134+
}
135+
136+
// Verify scriptType is present
137+
assert.ok(input.scriptType, `Input ${i} should have scriptType`);
138+
assert.ok(typeof input.scriptType === "string", `Input ${i} scriptType should be string`);
89139
});
90140

91141
// Validate outputs
@@ -157,6 +207,42 @@ describe("parseTransactionWithWalletKeys", function () {
157207
expectedScriptType,
158208
`Input ${i} scriptType should be ${expectedScriptType}, got ${input.scriptType}`,
159209
);
210+
211+
// Verify previousOutput is present and structured correctly
212+
assert.ok(input.previousOutput, `Input ${i} should have previousOutput`);
213+
assert.ok(
214+
typeof input.previousOutput === "object",
215+
`Input ${i} previousOutput should be an object`,
216+
);
217+
assert.ok(
218+
typeof input.previousOutput.txid === "string",
219+
`Input ${i} previousOutput.txid should be string`,
220+
);
221+
assert.strictEqual(
222+
input.previousOutput.txid.length,
223+
64,
224+
`Input ${i} previousOutput.txid should be 64 chars`,
225+
);
226+
assert.ok(
227+
typeof input.previousOutput.vout === "number",
228+
`Input ${i} previousOutput.vout should be number`,
229+
);
230+
231+
// Verify scriptId structure when present (can be null for replay protection inputs)
232+
if (input.scriptId !== null) {
233+
assert.ok(
234+
typeof input.scriptId === "object",
235+
`Input ${i} scriptId should be an object when present`,
236+
);
237+
assert.ok(
238+
typeof input.scriptId.chain === "number",
239+
`Input ${i} scriptId.chain should be number`,
240+
);
241+
assert.ok(
242+
typeof input.scriptId.index === "number",
243+
`Input ${i} scriptId.index should be number`,
244+
);
245+
}
160246
});
161247
});
162248

0 commit comments

Comments
 (0)