diff --git a/packages/wasm-utxo/js/psbt.ts b/packages/wasm-utxo/js/psbt.ts index 5a0666d8995..dc6fd35727d 100644 --- a/packages/wasm-utxo/js/psbt.ts +++ b/packages/wasm-utxo/js/psbt.ts @@ -20,10 +20,13 @@ export interface IPsbt extends ITransactionCommon removeOutput(index: number): void; setKV(key: PsbtKvKey, value: Uint8Array): void; getKV(key: PsbtKvKey): Uint8Array | undefined; + deleteKV(key: PsbtKvKey): void; setInputKV(index: number, key: PsbtKvKey, value: Uint8Array): void; getInputKV(index: number, key: PsbtKvKey): Uint8Array | undefined; + deleteInputKV(index: number, key: PsbtKvKey): void; setOutputKV(index: number, key: PsbtKvKey, value: Uint8Array): void; getOutputKV(index: number, key: PsbtKvKey): Uint8Array | undefined; + deleteOutputKV(index: number, key: PsbtKvKey): void; } /** Extended PSBT with address resolution (no coin parameter needed) */ diff --git a/packages/wasm-utxo/js/psbtBase.ts b/packages/wasm-utxo/js/psbtBase.ts index cd370396b30..d4e58bf1c62 100644 --- a/packages/wasm-utxo/js/psbtBase.ts +++ b/packages/wasm-utxo/js/psbtBase.ts @@ -16,10 +16,13 @@ interface WasmPsbtBase { remove_output(index: number): void; set_kv(key: unknown, value: Uint8Array): void; get_kv(key: unknown): Uint8Array | null | undefined; + delete_kv(key: unknown): void; set_input_kv(index: number, key: unknown, value: Uint8Array): void; get_input_kv(index: number, key: unknown): Uint8Array | null | undefined; + delete_input_kv(index: number, key: unknown): void; set_output_kv(index: number, key: unknown, value: Uint8Array): void; get_output_kv(index: number, key: unknown): Uint8Array | null | undefined; + delete_output_kv(index: number, key: unknown): void; } export abstract class PsbtBase { @@ -80,4 +83,13 @@ export abstract class PsbtBase { getOutputKV(index: number, key: PsbtKvKey): Uint8Array | undefined { return this._wasm.get_output_kv(index, key) ?? undefined; } + deleteKV(key: PsbtKvKey): void { + this._wasm.delete_kv(key); + } + deleteInputKV(index: number, key: PsbtKvKey): void { + this._wasm.delete_input_kv(index, key); + } + deleteOutputKV(index: number, key: PsbtKvKey): void { + this._wasm.delete_output_kv(index, key); + } } diff --git a/packages/wasm-utxo/src/psbt_ops.rs b/packages/wasm-utxo/src/psbt_ops.rs index 63fa9d2f9b4..dc8bb238da5 100644 --- a/packages/wasm-utxo/src/psbt_ops.rs +++ b/packages/wasm-utxo/src/psbt_ops.rs @@ -48,6 +48,14 @@ pub trait PsbtAccess { self.psbt().proprietary.get(key).cloned() } + fn delete_global_unknown_kv(&mut self, key: raw::Key) { + self.psbt_mut().unknown.remove(&key); + } + + fn delete_global_proprietary_kv(&mut self, key: raw::ProprietaryKey) { + self.psbt_mut().proprietary.remove(&key); + } + // ------------------------------------------------------------------------- // Per-input KV accessors // ------------------------------------------------------------------------- @@ -112,6 +120,32 @@ pub trait PsbtAccess { Ok(self.psbt().inputs[index].proprietary.get(key).cloned()) } + fn delete_input_unknown_kv(&mut self, index: usize, key: raw::Key) -> Result<(), String> { + let len = self.psbt().inputs.len(); + if index >= len { + return Err(format!( + "input index {index} out of bounds (have {len} inputs)" + )); + } + self.psbt_mut().inputs[index].unknown.remove(&key); + Ok(()) + } + + fn delete_input_proprietary_kv( + &mut self, + index: usize, + key: raw::ProprietaryKey, + ) -> Result<(), String> { + let len = self.psbt().inputs.len(); + if index >= len { + return Err(format!( + "input index {index} out of bounds (have {len} inputs)" + )); + } + self.psbt_mut().inputs[index].proprietary.remove(&key); + Ok(()) + } + // ------------------------------------------------------------------------- // Per-output KV accessors // ------------------------------------------------------------------------- @@ -178,6 +212,32 @@ pub trait PsbtAccess { Ok(self.psbt().outputs[index].proprietary.get(key).cloned()) } + fn delete_output_unknown_kv(&mut self, index: usize, key: raw::Key) -> Result<(), String> { + let len = self.psbt().outputs.len(); + if index >= len { + return Err(format!( + "output index {index} out of bounds (have {len} outputs)" + )); + } + self.psbt_mut().outputs[index].unknown.remove(&key); + Ok(()) + } + + fn delete_output_proprietary_kv( + &mut self, + index: usize, + key: raw::ProprietaryKey, + ) -> Result<(), String> { + let len = self.psbt().outputs.len(); + if index >= len { + return Err(format!( + "output index {index} out of bounds (have {len} outputs)" + )); + } + self.psbt_mut().outputs[index].proprietary.remove(&key); + Ok(()) + } + fn remove_input(&mut self, index: usize) -> Result<(), String> { let psbt = self.psbt_mut(); if index >= psbt.inputs.len() { diff --git a/packages/wasm-utxo/src/wasm/psbt.rs b/packages/wasm-utxo/src/wasm/psbt.rs index 00bf88cd30d..128c5bc6b5b 100644 --- a/packages/wasm-utxo/src/wasm/psbt.rs +++ b/packages/wasm-utxo/src/wasm/psbt.rs @@ -833,6 +833,26 @@ macro_rules! impl_wasm_psbt_ops { ) -> Result>, $crate::error::WasmUtxoError> { self.wasm_get_output_kv(index, key) } + pub fn delete_kv( + &mut self, + key: ::wasm_bindgen::JsValue, + ) -> Result<(), $crate::error::WasmUtxoError> { + self.wasm_delete_kv(key) + } + pub fn delete_input_kv( + &mut self, + index: usize, + key: ::wasm_bindgen::JsValue, + ) -> Result<(), $crate::error::WasmUtxoError> { + self.wasm_delete_input_kv(index, key) + } + pub fn delete_output_kv( + &mut self, + index: usize, + key: ::wasm_bindgen::JsValue, + ) -> Result<(), $crate::error::WasmUtxoError> { + self.wasm_delete_output_kv(index, key) + } } }; ($type:ty, $field:ident) => { @@ -921,6 +941,26 @@ macro_rules! impl_wasm_psbt_ops { ) -> Result>, $crate::error::WasmUtxoError> { self.$field.wasm_get_output_kv(index, key) } + pub fn delete_kv( + &mut self, + key: ::wasm_bindgen::JsValue, + ) -> Result<(), $crate::error::WasmUtxoError> { + self.$field.wasm_delete_kv(key) + } + pub fn delete_input_kv( + &mut self, + index: usize, + key: ::wasm_bindgen::JsValue, + ) -> Result<(), $crate::error::WasmUtxoError> { + self.$field.wasm_delete_input_kv(index, key) + } + pub fn delete_output_kv( + &mut self, + index: usize, + key: ::wasm_bindgen::JsValue, + ) -> Result<(), $crate::error::WasmUtxoError> { + self.$field.wasm_delete_output_kv(index, key) + } } }; } diff --git a/packages/wasm-utxo/src/wasm/psbt_ops.rs b/packages/wasm-utxo/src/wasm/psbt_ops.rs index 5294e3d709c..4a4fbabbb5c 100644 --- a/packages/wasm-utxo/src/wasm/psbt_ops.rs +++ b/packages/wasm-utxo/src/wasm/psbt_ops.rs @@ -114,6 +114,30 @@ pub(crate) trait WasmPsbtOps: PsbtAccess { } .map_err(|e| WasmUtxoError::new(&e)) } + + fn wasm_delete_kv(&mut self, key: JsValue) -> Result<(), WasmUtxoError> { + match PsbtKvKey::try_from_js_value(&key)? { + PsbtKvKey::Unknown(k) => PsbtAccess::delete_global_unknown_kv(self, k), + PsbtKvKey::Proprietary(k) => PsbtAccess::delete_global_proprietary_kv(self, k), + } + Ok(()) + } + + fn wasm_delete_input_kv(&mut self, index: usize, key: JsValue) -> Result<(), WasmUtxoError> { + match PsbtKvKey::try_from_js_value(&key)? { + PsbtKvKey::Unknown(k) => PsbtAccess::delete_input_unknown_kv(self, index, k), + PsbtKvKey::Proprietary(k) => PsbtAccess::delete_input_proprietary_kv(self, index, k), + } + .map_err(|e| WasmUtxoError::new(&e)) + } + + fn wasm_delete_output_kv(&mut self, index: usize, key: JsValue) -> Result<(), WasmUtxoError> { + match PsbtKvKey::try_from_js_value(&key)? { + PsbtKvKey::Unknown(k) => PsbtAccess::delete_output_unknown_kv(self, index, k), + PsbtKvKey::Proprietary(k) => PsbtAccess::delete_output_proprietary_kv(self, index, k), + } + .map_err(|e| WasmUtxoError::new(&e)) + } } impl WasmPsbtOps for T {}