|
1 | 1 | use crate::error::WasmUtxoError; |
| 2 | +use crate::wasm::try_from_js_value::get_field; |
2 | 3 | use crate::wasm::try_into_js_value::TryIntoJsValue; |
3 | 4 | use miniscript::bitcoin::secp256k1::{Secp256k1, Signing}; |
4 | 5 | use miniscript::bitcoin::ScriptBuf; |
@@ -156,6 +157,83 @@ impl WrapDescriptor { |
156 | 157 | } |
157 | 158 | } |
158 | 159 |
|
| 160 | + fn from_string_definite_ext( |
| 161 | + descriptor: &str, |
| 162 | + ext_params: &miniscript::miniscript::analyzable::ExtParams, |
| 163 | + ) -> Result<WrapDescriptor, WasmUtxoError> { |
| 164 | + let desc = Descriptor::<DefiniteDescriptorKey>::from_str_ext(descriptor, ext_params)?; |
| 165 | + Ok(WrapDescriptor(WrapDescriptorEnum::Definite(desc))) |
| 166 | + } |
| 167 | + |
| 168 | + /// Parse a descriptor string with custom ExtParams for taproot leaf validation. |
| 169 | + /// |
| 170 | + /// This allows control over which miniscript analysis checks are applied to |
| 171 | + /// taproot leaves. All options default to false (sane behavior). |
| 172 | + /// |
| 173 | + /// # Arguments |
| 174 | + /// * `descriptor` - A string containing the descriptor to parse |
| 175 | + /// * `pk_type` - The type of public key ("definite" only for now) |
| 176 | + /// * `ext_params_config` - JavaScript object with optional boolean flags: |
| 177 | + /// - `drop`: Allow drop operations (r: wrapper) |
| 178 | + /// - `topUnsafe`: Allow scripts without signatures on all paths |
| 179 | + /// - `resourceLimitations`: Allow scripts exceeding resource limits |
| 180 | + /// - `timelockMixing`: Allow CSV + CLTV mixing |
| 181 | + /// - `malleability`: Allow malleable scripts |
| 182 | + /// - `repeatedPk`: Allow repeated public keys |
| 183 | + /// - `rawPkh`: Allow raw pubkey hash fragments |
| 184 | + /// |
| 185 | + /// # Example |
| 186 | + /// ```javascript |
| 187 | + /// // Allow r:older() only (for sBTC) |
| 188 | + /// Descriptor.fromStringExt(desc, "definite", { drop: true }) |
| 189 | + /// |
| 190 | + /// // Allow multiple extensions |
| 191 | + /// Descriptor.fromStringExt(desc, "definite", { drop: true, malleability: true }) |
| 192 | + /// |
| 193 | + /// // All sane (default) |
| 194 | + /// Descriptor.fromStringExt(desc, "definite", {}) |
| 195 | + /// ``` |
| 196 | + #[wasm_bindgen(js_name = fromStringExt, skip_typescript)] |
| 197 | + pub fn from_string_ext( |
| 198 | + descriptor: &str, |
| 199 | + pk_type: &str, |
| 200 | + ext_params_config: JsValue, |
| 201 | + ) -> Result<WrapDescriptor, WasmUtxoError> { |
| 202 | + let flag = |key| -> Result<bool, WasmUtxoError> { |
| 203 | + Ok(get_field::<Option<bool>>(&ext_params_config, key)?.unwrap_or(false)) |
| 204 | + }; |
| 205 | + |
| 206 | + let mut params = miniscript::miniscript::analyzable::ExtParams::sane(); |
| 207 | + if flag("drop")? { |
| 208 | + params = params.drop(); |
| 209 | + } |
| 210 | + if flag("topUnsafe")? { |
| 211 | + params = params.top_unsafe(); |
| 212 | + } |
| 213 | + if flag("resourceLimitations")? { |
| 214 | + params = params.exceed_resource_limitations(); |
| 215 | + } |
| 216 | + if flag("timelockMixing")? { |
| 217 | + params = params.timelock_mixing(); |
| 218 | + } |
| 219 | + if flag("malleability")? { |
| 220 | + params = params.malleability(); |
| 221 | + } |
| 222 | + if flag("repeatedPk")? { |
| 223 | + params = params.repeated_pk(); |
| 224 | + } |
| 225 | + if flag("rawPkh")? { |
| 226 | + params = params.raw_pkh(); |
| 227 | + } |
| 228 | + |
| 229 | + match pk_type { |
| 230 | + "definite" => WrapDescriptor::from_string_definite_ext(descriptor, ¶ms), |
| 231 | + _ => Err(WasmUtxoError::new( |
| 232 | + "fromStringExt only supports 'definite' pk_type", |
| 233 | + )), |
| 234 | + } |
| 235 | + } |
| 236 | + |
159 | 237 | /// Parse a descriptor string, automatically detecting the appropriate public key type. |
160 | 238 | /// This will check if the descriptor contains wildcards to determine if it should be |
161 | 239 | /// parsed as derivable or definite. |
|
0 commit comments