1use crate::bitcoin::DescriptorId;
2use crate::bitcoin::DescriptorType;
3use crate::bitcoin::{Address, NetworkKind};
4use crate::error::DescriptorError;
5use crate::error::MiniscriptError;
6use crate::keys::DescriptorPublicKey;
7use crate::keys::DescriptorSecretKey;
8use crate::types::KeychainKind;
9
10use bdk_wallet::bitcoin::bip32::Fingerprint;
11use bdk_wallet::bitcoin::key::Secp256k1;
12use bdk_wallet::bitcoin::Network;
13use bdk_wallet::chain::DescriptorExt;
14use bdk_wallet::descriptor::{ExtendedDescriptor, IntoWalletDescriptor};
15use bdk_wallet::keys::DescriptorPublicKey as BdkDescriptorPublicKey;
16use bdk_wallet::keys::{DescriptorSecretKey as BdkDescriptorSecretKey, KeyMap};
17use bdk_wallet::miniscript::descriptor::ConversionError;
18use bdk_wallet::miniscript::Miniscript as BDKMiniscript;
19use bdk_wallet::template::{
20 Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, Bip86, Bip86Public,
21 DescriptorTemplate,
22};
23
24use std::fmt::Display;
25use std::str::FromStr;
26use std::sync::Arc;
27
28#[derive(Debug, uniffi::Object)]
30#[uniffi::export(Debug, Display)]
31pub struct Descriptor {
32 pub extended_descriptor: ExtendedDescriptor,
33 pub key_map: KeyMap,
34}
35
36#[uniffi::export]
37impl Descriptor {
38 #[uniffi::constructor]
40 pub fn new(descriptor: String, network_kind: NetworkKind) -> Result<Self, DescriptorError> {
41 let secp = Secp256k1::new();
42 let (extended_descriptor, key_map) =
43 descriptor.into_wallet_descriptor(&secp, network_kind)?;
44 Ok(Self {
45 extended_descriptor,
46 key_map,
47 })
48 }
49
50 #[uniffi::constructor]
52 pub fn new_bip44(
53 secret_key: &DescriptorSecretKey,
54 keychain_kind: KeychainKind,
55 network_kind: NetworkKind,
56 ) -> Self {
57 let derivable_key = &secret_key.0;
58
59 match derivable_key {
60 BdkDescriptorSecretKey::Single(_) => {
61 unreachable!()
62 }
63 BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
64 let derivable_key = descriptor_x_key.xkey;
65 let (extended_descriptor, key_map, _) = Bip44(derivable_key, keychain_kind)
66 .build(network_kind)
67 .unwrap();
68 Self {
69 extended_descriptor,
70 key_map,
71 }
72 }
73 BdkDescriptorSecretKey::MultiXPrv(_) => {
74 unreachable!()
75 }
76 }
77 }
78
79 #[uniffi::constructor]
81 pub fn new_bip44_public(
82 public_key: &DescriptorPublicKey,
83 fingerprint: String,
84 keychain_kind: KeychainKind,
85 network_kind: NetworkKind,
86 ) -> Result<Self, DescriptorError> {
87 let fingerprint = Fingerprint::from_str(fingerprint.as_str()).map_err(|error| {
88 DescriptorError::Bip32 {
89 error_message: error.to_string(),
90 }
91 })?;
92 let derivable_key = &public_key.0;
93
94 match derivable_key {
95 BdkDescriptorPublicKey::Single(_) => {
96 unreachable!()
97 }
98 BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
99 let derivable_key = descriptor_x_key.xkey;
100 let (extended_descriptor, key_map, _) =
101 Bip44Public(derivable_key, fingerprint, keychain_kind)
102 .build(network_kind)
103 .map_err(DescriptorError::from)?;
104
105 Ok(Self {
106 extended_descriptor,
107 key_map,
108 })
109 }
110 BdkDescriptorPublicKey::MultiXPub(_) => {
111 unreachable!()
112 }
113 }
114 }
115
116 #[uniffi::constructor]
118 pub fn new_bip49(
119 secret_key: &DescriptorSecretKey,
120 keychain_kind: KeychainKind,
121 network_kind: NetworkKind,
122 ) -> Self {
123 let derivable_key = &secret_key.0;
124
125 match derivable_key {
126 BdkDescriptorSecretKey::Single(_) => {
127 unreachable!()
128 }
129 BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
130 let derivable_key = descriptor_x_key.xkey;
131 let (extended_descriptor, key_map, _) = Bip49(derivable_key, keychain_kind)
132 .build(network_kind)
133 .unwrap();
134 Self {
135 extended_descriptor,
136 key_map,
137 }
138 }
139 BdkDescriptorSecretKey::MultiXPrv(_) => {
140 unreachable!()
141 }
142 }
143 }
144
145 #[uniffi::constructor]
147 pub fn new_bip49_public(
148 public_key: &DescriptorPublicKey,
149 fingerprint: String,
150 keychain_kind: KeychainKind,
151 network_kind: NetworkKind,
152 ) -> Result<Self, DescriptorError> {
153 let fingerprint = Fingerprint::from_str(fingerprint.as_str()).map_err(|error| {
154 DescriptorError::Bip32 {
155 error_message: error.to_string(),
156 }
157 })?;
158 let derivable_key = &public_key.0;
159
160 match derivable_key {
161 BdkDescriptorPublicKey::Single(_) => {
162 unreachable!()
163 }
164 BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
165 let derivable_key = descriptor_x_key.xkey;
166 let (extended_descriptor, key_map, _) =
167 Bip49Public(derivable_key, fingerprint, keychain_kind)
168 .build(network_kind)
169 .map_err(DescriptorError::from)?;
170
171 Ok(Self {
172 extended_descriptor,
173 key_map,
174 })
175 }
176 BdkDescriptorPublicKey::MultiXPub(_) => {
177 unreachable!()
178 }
179 }
180 }
181
182 #[uniffi::constructor]
184 pub fn new_bip84(
185 secret_key: &DescriptorSecretKey,
186 keychain_kind: KeychainKind,
187 network_kind: NetworkKind,
188 ) -> Self {
189 let derivable_key = &secret_key.0;
190
191 match derivable_key {
192 BdkDescriptorSecretKey::Single(_) => {
193 unreachable!()
194 }
195 BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
196 let derivable_key = descriptor_x_key.xkey;
197 let (extended_descriptor, key_map, _) = Bip84(derivable_key, keychain_kind)
198 .build(network_kind)
199 .unwrap();
200 Self {
201 extended_descriptor,
202 key_map,
203 }
204 }
205 BdkDescriptorSecretKey::MultiXPrv(_) => {
206 unreachable!()
207 }
208 }
209 }
210
211 #[uniffi::constructor]
213 pub fn new_bip84_public(
214 public_key: &DescriptorPublicKey,
215 fingerprint: String,
216 keychain_kind: KeychainKind,
217 network_kind: NetworkKind,
218 ) -> Result<Self, DescriptorError> {
219 let fingerprint = Fingerprint::from_str(fingerprint.as_str()).map_err(|error| {
220 DescriptorError::Bip32 {
221 error_message: error.to_string(),
222 }
223 })?;
224 let derivable_key = &public_key.0;
225
226 match derivable_key {
227 BdkDescriptorPublicKey::Single(_) => {
228 unreachable!()
229 }
230 BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
231 let derivable_key = descriptor_x_key.xkey;
232 let (extended_descriptor, key_map, _) =
233 Bip84Public(derivable_key, fingerprint, keychain_kind)
234 .build(network_kind)
235 .map_err(DescriptorError::from)?;
236
237 Ok(Self {
238 extended_descriptor,
239 key_map,
240 })
241 }
242 BdkDescriptorPublicKey::MultiXPub(_) => {
243 unreachable!()
244 }
245 }
246 }
247
248 #[uniffi::constructor]
250 pub fn new_bip86(
251 secret_key: &DescriptorSecretKey,
252 keychain_kind: KeychainKind,
253 network_kind: NetworkKind,
254 ) -> Self {
255 let derivable_key = &secret_key.0;
256
257 match derivable_key {
258 BdkDescriptorSecretKey::Single(_) => {
259 unreachable!()
260 }
261 BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
262 let derivable_key = descriptor_x_key.xkey;
263 let (extended_descriptor, key_map, _) = Bip86(derivable_key, keychain_kind)
264 .build(network_kind)
265 .unwrap();
266 Self {
267 extended_descriptor,
268 key_map,
269 }
270 }
271 BdkDescriptorSecretKey::MultiXPrv(_) => {
272 unreachable!()
273 }
274 }
275 }
276
277 #[uniffi::constructor]
279 pub fn new_bip86_public(
280 public_key: &DescriptorPublicKey,
281 fingerprint: String,
282 keychain_kind: KeychainKind,
283 network_kind: NetworkKind,
284 ) -> Result<Self, DescriptorError> {
285 let fingerprint = Fingerprint::from_str(fingerprint.as_str()).map_err(|error| {
286 DescriptorError::Bip32 {
287 error_message: error.to_string(),
288 }
289 })?;
290 let derivable_key = &public_key.0;
291
292 match derivable_key {
293 BdkDescriptorPublicKey::Single(_) => {
294 unreachable!()
295 }
296 BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
297 let derivable_key = descriptor_x_key.xkey;
298 let (extended_descriptor, key_map, _) =
299 Bip86Public(derivable_key, fingerprint, keychain_kind)
300 .build(network_kind)
301 .map_err(DescriptorError::from)?;
302
303 Ok(Self {
304 extended_descriptor,
305 key_map,
306 })
307 }
308 BdkDescriptorPublicKey::MultiXPub(_) => {
309 unreachable!()
310 }
311 }
312 }
313
314 #[uniffi::constructor]
317 pub fn new_wsh_sortedmulti(k: u32, pks: Vec<String>) -> Result<Self, DescriptorError> {
318 let bdk_pks: Vec<BdkDescriptorPublicKey> = pks
319 .iter()
320 .map(|pk| {
321 BdkDescriptorPublicKey::from_str(pk).map_err(|e| DescriptorError::Key {
322 error_message: e.to_string(),
323 })
324 })
325 .collect::<Result<Vec<BdkDescriptorPublicKey>, DescriptorError>>()?;
326 let miniscript_descriptor =
327 match bdk_wallet::miniscript::Descriptor::new_wsh_sortedmulti(k as usize, bdk_pks) {
328 Ok(descriptor) => descriptor,
329 Err(e) => {
330 return Err(DescriptorError::Miniscript {
331 error_message: e.to_string(),
332 })
333 }
334 };
335 let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
336
337 Ok(Self {
338 extended_descriptor,
339 key_map: KeyMap::new(),
340 })
341 }
342
343 #[uniffi::constructor]
346 pub fn new_sh_sortedmulti(k: u32, pks: Vec<String>) -> Result<Self, DescriptorError> {
347 let bdk_pks: Vec<BdkDescriptorPublicKey> = pks
348 .iter()
349 .map(|pk| {
350 BdkDescriptorPublicKey::from_str(pk).map_err(|e| DescriptorError::Key {
351 error_message: e.to_string(),
352 })
353 })
354 .collect::<Result<Vec<BdkDescriptorPublicKey>, DescriptorError>>()?;
355 let miniscript_descriptor =
356 match bdk_wallet::miniscript::Descriptor::new_sh_sortedmulti(k as usize, bdk_pks) {
357 Ok(descriptor) => descriptor,
358 Err(e) => {
359 return Err(DescriptorError::Miniscript {
360 error_message: e.to_string(),
361 })
362 }
363 };
364 let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
365
366 Ok(Self {
367 extended_descriptor,
368 key_map: KeyMap::new(),
369 })
370 }
371
372 #[uniffi::constructor]
375 pub fn new_sh_wsh_sortedmulti(k: u32, pks: Vec<String>) -> Result<Self, DescriptorError> {
376 let bdk_pks: Vec<BdkDescriptorPublicKey> = pks
377 .iter()
378 .map(|pk| {
379 BdkDescriptorPublicKey::from_str(pk).map_err(|e| DescriptorError::Key {
380 error_message: e.to_string(),
381 })
382 })
383 .collect::<Result<Vec<BdkDescriptorPublicKey>, DescriptorError>>()?;
384 let miniscript_descriptor =
385 match bdk_wallet::miniscript::Descriptor::new_sh_wsh_sortedmulti(k as usize, bdk_pks) {
386 Ok(descriptor) => descriptor,
387 Err(e) => {
388 return Err(DescriptorError::Miniscript {
389 error_message: e.to_string(),
390 })
391 }
392 };
393 let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
394
395 Ok(Self {
396 extended_descriptor,
397 key_map: KeyMap::new(),
398 })
399 }
400
401 #[uniffi::constructor]
403 pub fn new_pk(pk: String) -> Result<Self, DescriptorError> {
404 let key = BdkDescriptorPublicKey::from_str(&pk).map_err(|e| DescriptorError::Key {
405 error_message: e.to_string(),
406 })?;
407
408 let miniscript_descriptor = bdk_wallet::miniscript::Descriptor::new_pk(key);
409 let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
410
411 Ok(Self {
412 extended_descriptor,
413 key_map: KeyMap::new(),
414 })
415 }
416
417 #[uniffi::constructor]
419 pub fn new_pkh(pk: String) -> Result<Self, DescriptorError> {
420 let key = BdkDescriptorPublicKey::from_str(&pk).map_err(|e| DescriptorError::Key {
421 error_message: e.to_string(),
422 })?;
423
424 let miniscript_descriptor = match bdk_wallet::miniscript::Descriptor::new_pkh(key) {
425 Ok(descriptor) => descriptor,
426 Err(e) => {
427 return Err(DescriptorError::Miniscript {
428 error_message: e.to_string(),
429 })
430 }
431 };
432 let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
433
434 Ok(Self {
435 extended_descriptor,
436 key_map: KeyMap::new(),
437 })
438 }
439
440 #[uniffi::constructor]
442 pub fn new_wpkh(pk: String) -> Result<Self, DescriptorError> {
443 let key = BdkDescriptorPublicKey::from_str(&pk).map_err(|e| DescriptorError::Key {
444 error_message: e.to_string(),
445 })?;
446
447 let miniscript_descriptor = match bdk_wallet::miniscript::Descriptor::new_wpkh(key) {
448 Ok(descriptor) => descriptor,
449 Err(e) => {
450 return Err(DescriptorError::Miniscript {
451 error_message: e.to_string(),
452 })
453 }
454 };
455 let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
456
457 Ok(Self {
458 extended_descriptor,
459 key_map: KeyMap::new(),
460 })
461 }
462
463 #[uniffi::constructor]
465 pub fn new_sh_wpkh(pk: String) -> Result<Self, DescriptorError> {
466 let key = BdkDescriptorPublicKey::from_str(&pk).map_err(|e| DescriptorError::Key {
467 error_message: e.to_string(),
468 })?;
469
470 let miniscript_descriptor = match bdk_wallet::miniscript::Descriptor::new_sh_wpkh(key) {
471 Ok(descriptor) => descriptor,
472 Err(e) => {
473 return Err(DescriptorError::Miniscript {
474 error_message: e.to_string(),
475 })
476 }
477 };
478 let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
479
480 Ok(Self {
481 extended_descriptor,
482 key_map: KeyMap::new(),
483 })
484 }
485
486 #[uniffi::constructor]
489 pub fn new_wsh(mini_script: String) -> Result<Self, DescriptorError> {
490 let parsed_miniscript = match BDKMiniscript::from_str(&mini_script) {
491 Ok(miniscript) => miniscript,
492 Err(e) => {
493 return Err(DescriptorError::Miniscript {
494 error_message: e.to_string(),
495 });
496 }
497 };
498
499 let miniscript_descriptor =
500 match bdk_wallet::miniscript::Descriptor::new_wsh(parsed_miniscript) {
501 Ok(descriptor) => descriptor,
502 Err(e) => {
503 return Err(DescriptorError::Miniscript {
504 error_message: e.to_string(),
505 })
506 }
507 };
508 let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
509
510 Ok(Self {
511 extended_descriptor,
512 key_map: KeyMap::new(),
513 })
514 }
515
516 #[uniffi::constructor]
519 pub fn new_sh_wsh(mini_script: String) -> Result<Self, DescriptorError> {
520 let parsed_miniscript = match BDKMiniscript::from_str(&mini_script) {
521 Ok(miniscript) => miniscript,
522 Err(e) => {
523 return Err(DescriptorError::Miniscript {
524 error_message: e.to_string(),
525 });
526 }
527 };
528
529 let miniscript_descriptor =
530 match bdk_wallet::miniscript::Descriptor::new_sh_wsh(parsed_miniscript) {
531 Ok(descriptor) => descriptor,
532 Err(e) => {
533 return Err(DescriptorError::Miniscript {
534 error_message: e.to_string(),
535 })
536 }
537 };
538 let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
539
540 Ok(Self {
541 extended_descriptor,
542 key_map: KeyMap::new(),
543 })
544 }
545
546 #[uniffi::constructor]
548 pub fn new_sh(mini_script: String) -> Result<Self, DescriptorError> {
549 let parsed_miniscript = match BDKMiniscript::from_str(&mini_script) {
550 Ok(miniscript) => miniscript,
551 Err(e) => {
552 return Err(DescriptorError::Miniscript {
553 error_message: e.to_string(),
554 });
555 }
556 };
557
558 let miniscript_descriptor =
559 match bdk_wallet::miniscript::Descriptor::new_sh(parsed_miniscript) {
560 Ok(descriptor) => descriptor,
561 Err(e) => {
562 return Err(DescriptorError::Miniscript {
563 error_message: e.to_string(),
564 })
565 }
566 };
567 let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
568
569 Ok(Self {
570 extended_descriptor,
571 key_map: KeyMap::new(),
572 })
573 }
574
575 #[uniffi::constructor]
578 pub fn new_bare(mini_script: String) -> Result<Self, DescriptorError> {
579 let parsed_miniscript = match BDKMiniscript::from_str(&mini_script) {
580 Ok(miniscript) => miniscript,
581 Err(e) => {
582 return Err(DescriptorError::Miniscript {
583 error_message: e.to_string(),
584 });
585 }
586 };
587
588 let miniscript_descriptor =
589 match bdk_wallet::miniscript::Descriptor::new_bare(parsed_miniscript) {
590 Ok(descriptor) => descriptor,
591 Err(e) => {
592 return Err(DescriptorError::Miniscript {
593 error_message: e.to_string(),
594 })
595 }
596 };
597 let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
598
599 Ok(Self {
600 extended_descriptor,
601 key_map: KeyMap::new(),
602 })
603 }
604
605 pub fn to_string_with_secret(&self) -> String {
607 let descriptor = &self.extended_descriptor;
608 let key_map = &self.key_map;
609 descriptor.to_string_with_secret(key_map)
610 }
611
612 pub fn is_multipath(&self) -> bool {
614 self.extended_descriptor.is_multipath()
615 }
616
617 pub fn descriptor_id(&self) -> Arc<DescriptorId> {
619 let d_id = self.extended_descriptor.descriptor_id();
620 Arc::new(DescriptorId(d_id.0))
621 }
622
623 pub fn to_single_descriptors(&self) -> Result<Vec<Arc<Descriptor>>, MiniscriptError> {
625 self.extended_descriptor
626 .clone()
627 .into_single_descriptors()
628 .map_err(MiniscriptError::from)
629 .map(|descriptors| {
630 descriptors
631 .into_iter()
632 .map(|desc| {
633 Arc::new(Descriptor {
634 extended_descriptor: desc,
635 key_map: self.key_map.clone(),
636 })
637 })
638 .collect()
639 })
640 }
641
642 pub fn max_weight_to_satisfy(&self) -> Result<u64, DescriptorError> {
645 let weight = self
646 .extended_descriptor
647 .max_weight_to_satisfy()
648 .map_err(|e| DescriptorError::Miniscript {
649 error_message: e.to_string(),
650 })?;
651 Ok(weight.to_wu())
652 }
653
654 pub fn desc_type(&self) -> DescriptorType {
655 self.extended_descriptor.desc_type()
656 }
657
658 pub fn derive_address(
659 &self,
660 index: u32,
661 network: Network,
662 ) -> Result<Arc<Address>, DescriptorError> {
663 if self.extended_descriptor.is_multipath() {
664 return Err(DescriptorError::MultiPath);
665 }
666
667 let derived_descriptor = self
668 .extended_descriptor
669 .at_derivation_index(index)
670 .map_err(|error| match error {
671 ConversionError::HardenedChild => DescriptorError::HardenedDerivationXpub,
672 ConversionError::MultiKey => DescriptorError::MultiPath,
673 })?;
674
675 let address = derived_descriptor
676 .address(network)
677 .map_err(|error| DescriptorError::Miniscript {
678 error_message: error.to_string(),
679 })?
680 .into();
681
682 Ok(Arc::new(address))
683 }
684
685 pub fn has_wildcard(&self) -> bool {
687 self.extended_descriptor.has_wildcard()
688 }
689
690 pub fn sanity_check(&self) -> Result<(), DescriptorError> {
700 self.extended_descriptor
701 .sanity_check()
702 .map_err(|e| DescriptorError::Miniscript {
703 error_message: e.to_string(),
704 })
705 }
706}
707
708impl Display for Descriptor {
709 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
710 write!(f, "{}", self.extended_descriptor)
711 }
712}