Skip to content

Commit 1850074

Browse files
feat(wasm-utxo): add ScriptType enum and supportsScriptType function
Add standalone ScriptType API for fixed-script wallets: - Add ScriptType enum (p2sh, p2shP2wsh, p2wsh, p2tr, p2trMusig2) - Add supports_script_type method to OutputScriptSupport - Expose supportsScriptType via WASM and TypeScript This enables abstract-utxo to check network support for script types without depending on utxo-lib.
1 parent 0c79108 commit 1850074

4 files changed

Lines changed: 131 additions & 0 deletions

File tree

packages/wasm-utxo/js/fixedScriptWallet/index.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { FixedScriptWalletNamespace } from "../wasm/wasm_utxo.js";
2+
import type { CoinName } from "../coinName.js";
3+
14
export { RootWalletKeys, type WalletKeysArg, type IWalletKeys } from "./RootWalletKeys.js";
25
export { ReplayProtection, type ReplayProtectionArg } from "./ReplayProtection.js";
36
export { outputScript, address } from "./address.js";
@@ -26,3 +29,36 @@ export {
2629
type ZcashNetworkName,
2730
type CreateEmptyZcashOptions,
2831
} from "./ZcashBitGoPsbt.js";
32+
33+
/**
34+
* Fixed-script wallet script types (2-of-3 multisig)
35+
*
36+
* This type represents the abstract script type, independent of chain (external/internal).
37+
* Use this for checking network support or when you need the script type without derivation info.
38+
*/
39+
export type ScriptType = "p2sh" | "p2shP2wsh" | "p2wsh" | "p2tr" | "p2trMusig2";
40+
41+
/**
42+
* Check if a network supports a given fixed-script wallet script type
43+
*
44+
* @param coin - Coin name (e.g., "btc", "ltc", "doge")
45+
* @param scriptType - Script type to check
46+
* @returns `true` if the network supports the script type, `false` otherwise
47+
*
48+
* @example
49+
* ```typescript
50+
* // Bitcoin supports all script types
51+
* supportsScriptType("btc", "p2tr"); // true
52+
*
53+
* // Litecoin supports segwit but not taproot
54+
* supportsScriptType("ltc", "p2wsh"); // true
55+
* supportsScriptType("ltc", "p2tr"); // false
56+
*
57+
* // Dogecoin only supports legacy scripts
58+
* supportsScriptType("doge", "p2sh"); // true
59+
* supportsScriptType("doge", "p2wsh"); // false
60+
* ```
61+
*/
62+
export function supportsScriptType(coin: CoinName, scriptType: ScriptType): boolean {
63+
return FixedScriptWalletNamespace.supports_script_type(coin, scriptType);
64+
}

packages/wasm-utxo/src/address/networks.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use super::{
1313
ZCASH_TEST,
1414
};
1515
use crate::bitcoin::Script;
16+
use crate::fixed_script_wallet::wallet_scripts::ScriptType;
1617
use crate::networks::Network;
1718
use miniscript::bitcoin::WitnessVersion;
1819

@@ -120,6 +121,15 @@ impl OutputScriptSupport {
120121
}
121122
Ok(())
122123
}
124+
125+
/// Check if the network supports a given fixed-script wallet script type
126+
pub fn supports_script_type(&self, script_type: ScriptType) -> bool {
127+
match script_type {
128+
ScriptType::P2sh => true, // all networks support legacy scripts
129+
ScriptType::P2shP2wsh | ScriptType::P2wsh => self.segwit,
130+
ScriptType::P2tr | ScriptType::P2trMusig2 => self.taproot,
131+
}
132+
}
123133
}
124134

125135
impl Network {

packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/mod.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,69 @@ impl FromStr for Chain {
177177
}
178178
}
179179

180+
/// Fixed-script wallet script types (2-of-3 multisig)
181+
///
182+
/// This enum represents the abstract script type, independent of chain (external/internal).
183+
/// Use this for checking network support or when you need the script type without derivation info.
184+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
185+
pub enum ScriptType {
186+
/// Legacy Pay-To-Script-Hash (chains 0, 1)
187+
P2sh,
188+
/// Wrapped-Segwit Pay-To-Script-Hash (chains 10, 11)
189+
P2shP2wsh,
190+
/// Native Segwit Pay-To-Witness-Script-Hash (chains 20, 21)
191+
P2wsh,
192+
/// Legacy Taproot, script-path only (chains 30, 31)
193+
P2tr,
194+
/// Taproot with MuSig2 key-path support (chains 40, 41)
195+
P2trMusig2,
196+
}
197+
198+
impl ScriptType {
199+
/// Parse a script type from a string
200+
pub fn from_str(s: &str) -> Result<Self, String> {
201+
match s {
202+
"p2sh" => Ok(ScriptType::P2sh),
203+
"p2shP2wsh" => Ok(ScriptType::P2shP2wsh),
204+
"p2wsh" => Ok(ScriptType::P2wsh),
205+
"p2tr" => Ok(ScriptType::P2tr),
206+
"p2trMusig2" => Ok(ScriptType::P2trMusig2),
207+
_ => Err(format!(
208+
"Unknown script type '{}'. Expected: p2sh, p2shP2wsh, p2wsh, p2tr, p2trMusig2",
209+
s
210+
)),
211+
}
212+
}
213+
214+
/// Get the script type for a given chain
215+
pub fn from_chain(chain: Chain) -> Self {
216+
match chain {
217+
Chain::P2shExternal | Chain::P2shInternal => ScriptType::P2sh,
218+
Chain::P2shP2wshExternal | Chain::P2shP2wshInternal => ScriptType::P2shP2wsh,
219+
Chain::P2wshExternal | Chain::P2wshInternal => ScriptType::P2wsh,
220+
Chain::P2trInternal | Chain::P2trExternal => ScriptType::P2tr,
221+
Chain::P2trMusig2Internal | Chain::P2trMusig2External => ScriptType::P2trMusig2,
222+
}
223+
}
224+
225+
/// Get the string representation of the script type
226+
pub fn as_str(&self) -> &'static str {
227+
match self {
228+
ScriptType::P2sh => "p2sh",
229+
ScriptType::P2shP2wsh => "p2shP2wsh",
230+
ScriptType::P2wsh => "p2wsh",
231+
ScriptType::P2tr => "p2tr",
232+
ScriptType::P2trMusig2 => "p2trMusig2",
233+
}
234+
}
235+
}
236+
237+
impl std::fmt::Display for ScriptType {
238+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
239+
write!(f, "{}", self.as_str())
240+
}
241+
}
242+
180243
/// Return derived WalletKeys. All keys are derived with the same path.
181244
#[allow(dead_code)]
182245
pub fn derive_xpubs_with_path(

packages/wasm-utxo/src/wasm/fixed_script_wallet/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use wasm_bindgen::JsValue;
88

99
use crate::address::networks::AddressFormat;
1010
use crate::error::WasmUtxoError;
11+
use crate::fixed_script_wallet::wallet_scripts::ScriptType;
1112
use crate::fixed_script_wallet::{Chain, WalletScripts};
1213
use crate::utxolib_compat::UtxolibNetwork;
1314
use crate::wasm::bip32::WasmBIP32;
@@ -84,6 +85,27 @@ impl FixedScriptWalletNamespace {
8485
.map_err(|e| WasmUtxoError::new(&format!("Failed to generate address: {}", e)))?;
8586
Ok(address)
8687
}
88+
89+
/// Check if a network supports a given fixed-script wallet script type
90+
///
91+
/// # Arguments
92+
/// * `coin` - Coin name (e.g., "btc", "ltc", "doge")
93+
/// * `script_type` - Script type name: "p2sh", "p2shP2wsh", "p2wsh", "p2tr", "p2trMusig2"
94+
///
95+
/// # Returns
96+
/// `true` if the network supports the script type, `false` otherwise
97+
///
98+
/// # Examples
99+
/// - Bitcoin supports all script types (p2sh, p2shP2wsh, p2wsh, p2tr, p2trMusig2)
100+
/// - Litecoin supports segwit but not taproot (p2sh, p2shP2wsh, p2wsh)
101+
/// - Dogecoin only supports legacy scripts (p2sh)
102+
#[wasm_bindgen]
103+
pub fn supports_script_type(coin: &str, script_type: &str) -> Result<bool, WasmUtxoError> {
104+
let network = crate::networks::Network::from_coin_name(coin)
105+
.ok_or_else(|| WasmUtxoError::new(&format!("Unknown coin: {}", coin)))?;
106+
let st = ScriptType::from_str(script_type).map_err(|e| WasmUtxoError::new(&e))?;
107+
Ok(network.output_script_support().supports_script_type(st))
108+
}
87109
}
88110
#[wasm_bindgen]
89111
pub struct BitGoPsbt {

0 commit comments

Comments
 (0)