Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/wasm-utxo/js/fixedScriptWallet/BitGoPsbt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ export type InputScriptType =
| "p2trMusig2ScriptPath"
| "p2trMusig2KeyPath";

export type OutPoint = {
txid: string;
vout: number;
};

export type ParsedInput = {
previousOutput: OutPoint;
address: string;
script: Uint8Array;
value: bigint;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ impl InputScriptType {
/// Parsed input from a PSBT transaction
#[derive(Debug, Clone)]
pub struct ParsedInput {
pub previous_output: OutPoint,
pub address: String,
pub script: Vec<u8>,
pub value: u64,
Expand Down Expand Up @@ -627,6 +628,7 @@ impl ParsedInput {
.map_err(ParseInputError::ScriptTypeDetection)?;

Ok(Self {
previous_output: tx_input.previous_output,
address,
script: output_script.to_bytes(),
value: value.to_sat(),
Expand Down
1 change: 1 addition & 0 deletions packages/wasm-utxo/src/wasm/try_into_js_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ impl TryIntoJsValue for crate::fixed_script_wallet::bitgo_psbt::InputScriptType
impl TryIntoJsValue for crate::fixed_script_wallet::bitgo_psbt::ParsedInput {
fn try_to_js_value(&self) -> Result<JsValue, WasmUtxoError> {
js_obj!(
"previousOutput" => js_obj!("txid" => self.previous_output.txid.to_string(), "vout" => self.previous_output.vout)?,
"address" => self.address.clone(),
"value" => self.value,
"scriptId" => self.script_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,59 @@ describe("parseTransactionWithWalletKeys", function () {

// Verify all inputs have addresses and values
parsed.inputs.forEach((input, i) => {
// Verify previousOutput structure
assert.ok(input.previousOutput, `Input ${i} should have previousOutput`);
assert.ok(
typeof input.previousOutput === "object",
`Input ${i} previousOutput should be an object`,
);
assert.ok(
typeof input.previousOutput.txid === "string",
`Input ${i} previousOutput.txid should be string`,
);
assert.strictEqual(
input.previousOutput.txid.length,
64,
`Input ${i} previousOutput.txid should be 64 chars (32 bytes hex)`,
);
assert.ok(
typeof input.previousOutput.vout === "number",
`Input ${i} previousOutput.vout should be number`,
);
assert.ok(
input.previousOutput.vout >= 0,
`Input ${i} previousOutput.vout should be >= 0`,
);

// Verify address
assert.ok(input.address, `Input ${i} should have an address`);
assert.ok(typeof input.address === "string", `Input ${i} address should be string`);

// Verify value
assert.ok(typeof input.value === "bigint", `Input ${i} value should be bigint`);
assert.ok(input.value > 0n, `Input ${i} value should be > 0`);

// Verify scriptId structure (can be null for replay protection inputs)
if (input.scriptId !== null) {
assert.ok(
typeof input.scriptId === "object",
`Input ${i} scriptId should be an object when present`,
);
assert.ok(
typeof input.scriptId.chain === "number",
`Input ${i} scriptId.chain should be number`,
);
assert.ok(
typeof input.scriptId.index === "number",
`Input ${i} scriptId.index should be number`,
);
assert.ok(input.scriptId.chain >= 0, `Input ${i} scriptId.chain should be >= 0`);
assert.ok(input.scriptId.index >= 0, `Input ${i} scriptId.index should be >= 0`);
}

// Verify scriptType is present
assert.ok(input.scriptType, `Input ${i} should have scriptType`);
assert.ok(typeof input.scriptType === "string", `Input ${i} scriptType should be string`);
});

// Validate outputs
Expand Down Expand Up @@ -157,6 +207,42 @@ describe("parseTransactionWithWalletKeys", function () {
expectedScriptType,
`Input ${i} scriptType should be ${expectedScriptType}, got ${input.scriptType}`,
);

// Verify previousOutput is present and structured correctly
assert.ok(input.previousOutput, `Input ${i} should have previousOutput`);
assert.ok(
typeof input.previousOutput === "object",
`Input ${i} previousOutput should be an object`,
);
assert.ok(
typeof input.previousOutput.txid === "string",
`Input ${i} previousOutput.txid should be string`,
);
assert.strictEqual(
input.previousOutput.txid.length,
64,
`Input ${i} previousOutput.txid should be 64 chars`,
);
assert.ok(
typeof input.previousOutput.vout === "number",
`Input ${i} previousOutput.vout should be number`,
);

// Verify scriptId structure when present (can be null for replay protection inputs)
if (input.scriptId !== null) {
assert.ok(
typeof input.scriptId === "object",
`Input ${i} scriptId should be an object when present`,
);
assert.ok(
typeof input.scriptId.chain === "number",
`Input ${i} scriptId.chain should be number`,
);
assert.ok(
typeof input.scriptId.index === "number",
`Input ${i} scriptId.index should be number`,
);
}
});
});

Expand Down