Skip to content

Commit c5dd9b2

Browse files
Merge pull request #71 from BitGo/BTC-2786.add-previousOutput
feat(wasm-utxo): add previousOutput field to ParsedInput
2 parents 40e0e1d + 1891484 commit c5dd9b2

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)