1use std::{fmt, str::FromStr, sync::Arc};
2
3use crate::{types::SecretKey, Chain, LwkError, Script};
4
5#[derive(uniffi::Object)]
7#[uniffi::export(Display)]
8pub struct WolletDescriptor {
9 inner: lwk_wollet::WolletDescriptor,
10}
11
12impl AsRef<lwk_wollet::WolletDescriptor> for WolletDescriptor {
13 fn as_ref(&self) -> &lwk_wollet::WolletDescriptor {
14 &self.inner
15 }
16}
17
18impl From<lwk_wollet::WolletDescriptor> for WolletDescriptor {
19 fn from(inner: lwk_wollet::WolletDescriptor) -> Self {
20 Self { inner }
21 }
22}
23
24impl From<&WolletDescriptor> for lwk_wollet::WolletDescriptor {
25 fn from(desc: &WolletDescriptor) -> Self {
26 desc.inner.clone()
27 }
28}
29
30#[uniffi::export]
31impl WolletDescriptor {
32 #[uniffi::constructor]
34 pub fn new(descriptor: &str) -> Result<Arc<Self>, LwkError> {
35 let inner = lwk_wollet::WolletDescriptor::from_str(descriptor)?;
36 Ok(Arc::new(WolletDescriptor { inner }))
37 }
38
39 pub fn is_mainnet(&self) -> bool {
41 self.inner.is_mainnet()
42 }
43
44 pub fn derive_blinding_key(&self, script_pubkey: &Script) -> Option<Arc<SecretKey>> {
46 lwk_common::derive_blinding_key(self.inner.as_ref(), &script_pubkey.into())
47 .map(Into::into)
48 .map(Arc::new)
49 }
50
51 pub fn script_pubkey(&self, ext_int: Chain, index: u32) -> Result<Arc<Script>, LwkError> {
53 self.inner
54 .script_pubkey(ext_int.into(), index)
55 .map_err(Into::into)
56 .map(Into::into)
57 .map(Arc::new)
58 }
59
60 pub fn is_amp0(&self) -> bool {
62 self.inner.is_amp0()
63 }
64}
65
66impl fmt::Display for WolletDescriptor {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 write!(f, "{}", self.inner)
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use lwk_wollet::ElementsNetwork;
75
76 use crate::{Chain, Mnemonic, Signer, WolletDescriptor};
77 use std::str::FromStr;
78
79 #[test]
80 fn wpkh_slip77_descriptor() {
81 let mnemonic_str = lwk_test_util::TEST_MNEMONIC;
82 let mnemonic = Mnemonic::new(mnemonic_str).unwrap();
83 let network: crate::Network = ElementsNetwork::default_regtest().into();
84
85 let signer = Signer::new(&mnemonic, &network).unwrap();
86 let exp = "ct(slip77(9c8e4f05c7711a98c838be228bcb84924d4570ca53f35fa1c793e58841d47023),elwpkh([73c5da0a/84'/1'/0']tpubDC8msFGeGuwnKG9Upg7DM2b4DaRqg3CUZa5g8v2SRQ6K4NSkxUgd7HsL2XVWbVm39yBA4LAxysQAm397zwQSQoQgewGiYZqrA9DsP4zbQ1M/<0;1>/*))#2e4n992d";
87 assert_eq!(signer.wpkh_slip77_descriptor().unwrap().to_string(), exp);
88
89 let wollet_desc = lwk_wollet::WolletDescriptor::from_str(exp).unwrap();
90 let desc: WolletDescriptor = wollet_desc.into();
91 assert_eq!(desc.to_string(), exp);
92
93 assert!(!desc.is_mainnet());
94
95 assert_eq!(
96 desc.script_pubkey(Chain::External, 0).unwrap().to_string(),
97 "0014d0c4a3ef09e997b6e99e397e518fe3e41a118ca1"
98 );
99
100 assert_eq!(
101 desc.script_pubkey(Chain::Internal, 0).unwrap().to_string(),
102 "00142f34aa1cf00a53b055a291a03a7d45f0a6988b52"
103 );
104 }
105}