diff --git a/packages/wasm-utxo/js/fixedScriptWallet/ZcashV6Transaction.ts b/packages/wasm-utxo/js/fixedScriptWallet/ZcashV6Transaction.ts index 5d1e15d3bd8..b945e885196 100644 --- a/packages/wasm-utxo/js/fixedScriptWallet/ZcashV6Transaction.ts +++ b/packages/wasm-utxo/js/fixedScriptWallet/ZcashV6Transaction.ts @@ -1,4 +1,5 @@ import { ZcashV6Transaction as WasmZcashV6Transaction } from "../wasm/wasm_utxo.js"; +import type { TxInputData } from "../wasm/wasm_utxo.js"; /** * A parsed Zcash v6 (Ironwood / NU6.3) transaction — for inspection and txid. @@ -91,6 +92,15 @@ export class ZcashV6Transaction { ); } + /** + * The transparent inputs of this transaction, in input order — e.g. each input's + * `previousOutput` (display-order txid + vout) for looking up the spent UTXOs of a broadcast + * shielding transaction. Empty for a fully shielded transaction. + */ + getInputs(): TxInputData[] { + return this._wasm.getInputs(); + } + /** @internal */ get wasm(): WasmZcashV6Transaction { return this._wasm; diff --git a/packages/wasm-utxo/src/wasm/zcash.rs b/packages/wasm-utxo/src/wasm/zcash.rs index d11c543acb1..95b379810d7 100644 --- a/packages/wasm-utxo/src/wasm/zcash.rs +++ b/packages/wasm-utxo/src/wasm/zcash.rs @@ -5,6 +5,7 @@ //! generic fixed-script-wallet bindings. use crate::error::WasmUtxoError; +use crate::wasm::try_into_js_value::TryIntoJsValue; use wasm_bindgen::prelude::*; /// Return the Zcash consensus branch ID active at `height` on `network`. @@ -436,4 +437,12 @@ impl ZcashV6Transaction { .map(|h| h.to_vec()) .map_err(|e| WasmUtxoError::new(&e.to_string())) } + + /// The transparent inputs of this transaction, in input order — each input's + /// `previousOutput` (display-order txid + vout), sequence, scriptSig, and witness, carried + /// verbatim from the wire. Empty for a fully shielded transaction. + #[wasm_bindgen(js_name = getInputs, unchecked_return_type = "TxInputData[]")] + pub fn get_inputs(&self) -> Result { + super::transaction::tx_inputs_from(&self.inner.transparent).try_to_js_value() + } } diff --git a/packages/wasm-utxo/test/fixedScript/zcashV6Transaction.ts b/packages/wasm-utxo/test/fixedScript/zcashV6Transaction.ts index ab8fb8e6a1d..a2515c2b942 100644 --- a/packages/wasm-utxo/test/fixedScript/zcashV6Transaction.ts +++ b/packages/wasm-utxo/test/fixedScript/zcashV6Transaction.ts @@ -43,6 +43,34 @@ describe("ZcashV6Transaction", function () { assert.strictEqual(typeof tx.ironwoodValueBalance, "bigint"); }); + it("exposes the transparent inputs' prevouts of the reference shield tx", function () { + const tx = ZcashV6Transaction.fromBytes(Buffer.from(readFixture("v6_shield_rawtx.hex"), "hex")); + assert.deepStrictEqual( + tx.getInputs().map((input) => input.previousOutput), + [ + { txid: "bb9a0ed8e980f02273fae80adfb462594ace1c620780c39e5e86b3900d1eebbe", vout: 0 }, + { txid: "ac0e368c750f878ea1c4b07986e21d28472716367fd9aa8027fdf623801a5843", vout: 0 }, + ], + ); + }); + + it("exposes the transparent input's prevout of the multisig shield tx", function () { + const tx = ZcashV6Transaction.fromBytes( + Buffer.from(readFixture("v6_shield_multisig_rawtx.hex"), "hex"), + ); + assert.deepStrictEqual( + tx.getInputs().map((input) => input.previousOutput), + [{ txid: "1ebd1da314f021d7c7b2ced6c0340067ebf3ce422bf8c53daa626d72cbd9fe73", vout: 1 }], + ); + }); + + it("has no transparent inputs for the fully shielded self-send", function () { + const tx = ZcashV6Transaction.fromBytes( + Buffer.from(readFixture("v6_selfsend_rawtx.hex"), "hex"), + ); + assert.deepStrictEqual(tx.getInputs(), []); + }); + it("throws on non-v6 bytes", function () { assert.throws(() => ZcashV6Transaction.fromBytes(Buffer.from("00010203", "hex"))); });