1use crate::error::{
2 AddressParseError, Bip32Error, ExtractTxError, FeeRateError, FromScriptError, HashParseError,
3 PsbtError, PsbtParseError, TransactionError,
4};
5use crate::error::{ParseAmountError, PsbtFinalizeError};
6use crate::keys::DerivationPath;
7
8use crate::{impl_from_core_type, impl_hash_like, impl_into_core_type};
9use bdk_wallet::bitcoin::address::NetworkChecked;
10use bdk_wallet::bitcoin::address::NetworkUnchecked;
11use bdk_wallet::bitcoin::address::{Address as BdkAddress, AddressData as BdkAddressData};
12use bdk_wallet::bitcoin::bip32::ChildNumber as BdkChildNumber;
13use bdk_wallet::bitcoin::blockdata::block::Block as BdkBlock;
14use bdk_wallet::bitcoin::blockdata::block::Header as BdkHeader;
15use bdk_wallet::bitcoin::consensus::encode::deserialize;
16use bdk_wallet::bitcoin::consensus::encode::serialize;
17use bdk_wallet::bitcoin::hashes::sha256::Hash as BitcoinSha256Hash;
18use bdk_wallet::bitcoin::hashes::sha256d::Hash as BitcoinDoubleSha256Hash;
19use bdk_wallet::bitcoin::psbt::Input as BdkInput;
20use bdk_wallet::bitcoin::psbt::Output as BdkOutput;
21use bdk_wallet::bitcoin::secp256k1::Secp256k1;
22use bdk_wallet::bitcoin::taproot::LeafNode as BdkLeafNode;
23use bdk_wallet::bitcoin::taproot::NodeInfo as BdkNodeInfo;
24use bdk_wallet::bitcoin::taproot::TapTree as BdkTapTree;
25use bdk_wallet::bitcoin::Amount as BdkAmount;
26use bdk_wallet::bitcoin::BlockHash as BitcoinBlockHash;
27use bdk_wallet::bitcoin::FeeRate as BdkFeeRate;
28use bdk_wallet::bitcoin::OutPoint as BdkOutPoint;
29use bdk_wallet::bitcoin::Psbt as BdkPsbt;
30use bdk_wallet::bitcoin::ScriptBuf as BdkScriptBuf;
31use bdk_wallet::bitcoin::Transaction as BdkTransaction;
32use bdk_wallet::bitcoin::TxIn as BdkTxIn;
33use bdk_wallet::bitcoin::TxOut as BdkTxOut;
34use bdk_wallet::bitcoin::Txid as BitcoinTxid;
35use bdk_wallet::bitcoin::Weight;
36use bdk_wallet::bitcoin::Wtxid as BitcoinWtxid;
37use bdk_wallet::miniscript::psbt::PsbtExt;
38use bdk_wallet::serde_json;
39
40use std::collections::HashMap;
41use std::convert::TryFrom;
42use std::fmt::Display;
43use std::fs::File;
44use std::io::{BufReader, BufWriter};
45use std::ops::Deref;
46use std::str::FromStr;
47use std::sync::{Arc, Mutex};
48
49pub type DescriptorType = bdk_wallet::miniscript::descriptor::DescriptorType;
50pub type Network = bdk_wallet::bitcoin::Network;
51pub(crate) type NetworkKind = bdk_wallet::bitcoin::NetworkKind;
52
53#[uniffi::remote(Enum)]
55pub enum NetworkKind {
56 Main,
58 Test,
60}
61
62#[derive(Debug, Clone, Eq, PartialEq, std::hash::Hash, uniffi:: Record)]
64pub struct OutPoint {
65 pub txid: Arc<Txid>,
67 pub vout: u32,
69}
70
71impl From<&BdkOutPoint> for OutPoint {
72 fn from(outpoint: &BdkOutPoint) -> Self {
73 OutPoint {
74 txid: Arc::new(Txid(outpoint.txid)),
75 vout: outpoint.vout,
76 }
77 }
78}
79
80impl From<BdkOutPoint> for OutPoint {
81 fn from(value: BdkOutPoint) -> Self {
82 Self {
83 txid: Arc::new(Txid(value.txid)),
84 vout: value.vout,
85 }
86 }
87}
88
89impl From<OutPoint> for BdkOutPoint {
90 fn from(outpoint: OutPoint) -> Self {
91 BdkOutPoint {
92 txid: BitcoinTxid::from_raw_hash(outpoint.txid.0.to_raw_hash()),
93 vout: outpoint.vout,
94 }
95 }
96}
97
98#[uniffi::remote(Enum)]
108pub enum Network {
109 Bitcoin,
110 Testnet,
111 Testnet4,
112 Signet,
113 Regtest,
114}
115
116#[derive(Debug, PartialEq, Eq, std::hash::Hash, uniffi::Object)]
121#[uniffi::export(Debug, Eq, Hash)]
122pub struct HashableOutPoint(pub(crate) OutPoint);
123
124#[uniffi::export]
125impl HashableOutPoint {
126 #[uniffi::constructor]
128 pub fn new(outpoint: OutPoint) -> Self {
129 Self(outpoint)
130 }
131
132 pub fn outpoint(&self) -> OutPoint {
134 self.0.clone()
135 }
136}
137
138#[derive(Clone, Debug, uniffi::Object)]
143#[uniffi::export(Display)]
144pub struct FeeRate(pub(crate) BdkFeeRate);
145
146#[uniffi::export]
147impl FeeRate {
148 #[uniffi::constructor]
150 pub fn from_sat_per_vb(sat_vb: u64) -> Result<Self, FeeRateError> {
151 let fee_rate: Option<BdkFeeRate> = BdkFeeRate::from_sat_per_vb(sat_vb);
152 match fee_rate {
153 Some(fee_rate) => Ok(FeeRate(fee_rate)),
154 None => Err(FeeRateError::ArithmeticOverflow),
155 }
156 }
157
158 #[uniffi::constructor]
160 pub fn from_sat_per_kwu(sat_kwu: u64) -> Self {
161 FeeRate(BdkFeeRate::from_sat_per_kwu(sat_kwu))
162 }
163
164 pub fn to_sat_per_vb_ceil(&self) -> u64 {
166 self.0.to_sat_per_vb_ceil()
167 }
168
169 pub fn to_sat_per_vb_floor(&self) -> u64 {
171 self.0.to_sat_per_vb_floor()
172 }
173
174 pub fn to_sat_per_kwu(&self) -> u64 {
176 self.0.to_sat_per_kwu()
177 }
178
179 pub fn fee_vb(&self, vb: u64) -> Option<Arc<Amount>> {
183 let rust_amount: BdkAmount = self.0.fee_vb(vb)?;
184 let amount: Amount = rust_amount.into();
185 Some(Arc::new(amount))
186
187 }
192
193 pub fn fee_wu(&self, wu: u64) -> Option<Arc<Amount>> {
197 let weight: Weight = Weight::from_wu(wu);
198 let rust_amount: BdkAmount = self.0.fee_wu(weight)?;
199 let amount: Amount = rust_amount.into();
200 Some(Arc::new(amount))
201 }
202}
203
204impl Display for FeeRate {
205 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
206 write!(f, "{:#}", self.0)
207 }
208}
209
210impl_from_core_type!(BdkFeeRate, FeeRate);
211impl_into_core_type!(FeeRate, BdkFeeRate);
212
213#[derive(Debug, Clone, PartialEq, Eq, uniffi::Object)]
218#[uniffi::export(Display)]
219pub struct Amount(pub(crate) BdkAmount);
220
221#[uniffi::export]
222impl Amount {
223 #[uniffi::constructor]
225 pub fn from_sat(satoshi: u64) -> Self {
226 Amount(BdkAmount::from_sat(satoshi))
227 }
228
229 #[uniffi::constructor]
231 pub fn from_btc(btc: f64) -> Result<Self, ParseAmountError> {
232 let bitcoin_amount = BdkAmount::from_btc(btc).map_err(ParseAmountError::from)?;
233 Ok(Amount(bitcoin_amount))
234 }
235
236 pub fn to_sat(&self) -> u64 {
238 self.0.to_sat()
239 }
240
241 pub fn to_btc(&self) -> f64 {
244 self.0.to_btc()
245 }
246}
247
248impl_from_core_type!(BdkAmount, Amount);
249impl_into_core_type!(Amount, BdkAmount);
250
251impl Display for Amount {
252 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
253 write!(f, "{}", self.0)
254 }
255}
256
257#[derive(Clone, Debug, uniffi::Object)]
259#[uniffi::export(Display)]
260pub struct Script(pub(crate) BdkScriptBuf);
261
262#[uniffi::export]
263impl Script {
264 #[uniffi::constructor]
266 pub fn new(raw_output_script: Vec<u8>) -> Self {
267 let script: BdkScriptBuf = raw_output_script.into();
268 Script(script)
269 }
270
271 pub fn to_bytes(&self) -> Vec<u8> {
273 self.0.to_bytes()
274 }
275}
276
277impl_from_core_type!(BdkScriptBuf, Script);
278impl_into_core_type!(Script, BdkScriptBuf);
279
280impl Display for Script {
281 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
282 self.0.fmt_asm(f)
283 }
284}
285
286#[derive(uniffi::Record)]
290pub struct Header {
291 pub version: i32,
293 pub prev_blockhash: Arc<BlockHash>,
295 pub merkle_root: Arc<TxMerkleNode>,
297 pub time: u32,
299 pub bits: u32,
301 pub nonce: u32,
303}
304
305impl From<BdkHeader> for Header {
306 fn from(bdk_header: BdkHeader) -> Self {
307 Header {
308 version: bdk_header.version.to_consensus(),
309 prev_blockhash: Arc::new(BlockHash(bdk_header.prev_blockhash)),
310 merkle_root: Arc::new(TxMerkleNode(bdk_header.merkle_root.to_raw_hash())),
311 time: bdk_header.time,
312 bits: bdk_header.bits.to_consensus(),
313 nonce: bdk_header.nonce,
314 }
315 }
316}
317
318#[derive(uniffi::Record)]
321pub struct Block {
322 pub header: Header,
323 pub txdata: Vec<Arc<Transaction>>,
324}
325
326impl From<BdkBlock> for Block {
327 fn from(bdk_block: BdkBlock) -> Self {
328 Block {
329 header: bdk_block.header.into(),
330 txdata: bdk_block
331 .txdata
332 .into_iter()
333 .map(|tx| Arc::new(tx.into()))
334 .collect(),
335 }
336 }
337}
338
339#[derive(Debug, uniffi::Enum)]
341pub enum AddressData {
342 P2pkh { pubkey_hash: String },
344 P2sh { script_hash: String },
346 Segwit { witness_program: WitnessProgram },
348}
349
350#[derive(Debug, uniffi::Record)]
352pub struct WitnessProgram {
353 pub version: u8,
355 pub program: Vec<u8>,
357}
358
359#[derive(Debug, PartialEq, Eq, uniffi::Object)]
361#[uniffi::export(Eq, Display)]
362pub struct Address(pub(crate) BdkAddress<NetworkChecked>);
363
364#[uniffi::export]
365impl Address {
366 #[uniffi::constructor]
368 pub fn new(address: String, network: Network) -> Result<Self, AddressParseError> {
369 let parsed_address = address.parse::<bdk_wallet::bitcoin::Address<NetworkUnchecked>>()?;
370 let network_checked_address = parsed_address.require_network(network)?;
371
372 Ok(Address(network_checked_address))
373 }
374
375 #[uniffi::constructor]
377 pub fn from_script(script: Arc<Script>, network: Network) -> Result<Self, FromScriptError> {
378 let address = BdkAddress::from_script(&script.0.clone(), network)?;
379
380 Ok(Address(address))
381 }
382
383 pub fn script_pubkey(&self) -> Arc<Script> {
385 Arc::new(Script(self.0.script_pubkey()))
386 }
387
388 pub fn to_qr_uri(&self) -> String {
390 self.0.to_qr_uri()
391 }
392
393 pub fn is_valid_for_network(&self, network: Network) -> bool {
395 let address_str = self.0.to_string();
396 if let Ok(unchecked_address) = address_str.parse::<BdkAddress<NetworkUnchecked>>() {
397 unchecked_address.is_valid_for_network(network)
398 } else {
399 false
400 }
401 }
402
403 pub fn to_address_data(&self) -> AddressData {
405 match self.0.to_address_data() {
406 BdkAddressData::P2pkh { pubkey_hash } => AddressData::P2pkh {
407 pubkey_hash: pubkey_hash.to_string(),
408 },
409 BdkAddressData::P2sh { script_hash } => AddressData::P2sh {
410 script_hash: script_hash.to_string(),
411 },
412 BdkAddressData::Segwit { witness_program } => AddressData::Segwit {
413 witness_program: WitnessProgram {
414 version: witness_program.version().to_num(),
415 program: witness_program.program().as_bytes().to_vec(),
416 },
417 },
418 _ => unimplemented!("Unsupported address type"),
420 }
421 }
422}
423
424impl Display for Address {
425 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
426 write!(f, "{}", self.0)
427 }
428}
429
430impl_from_core_type!(BdkAddress, Address);
431impl_into_core_type!(Address, BdkAddress);
432
433#[derive(Debug, Clone, PartialEq, Eq, uniffi::Object)]
436#[uniffi::export(Eq, Display)]
437pub struct Transaction(BdkTransaction);
438
439#[uniffi::export]
440impl Transaction {
441 #[uniffi::constructor]
443 pub fn new(transaction_bytes: Vec<u8>) -> Result<Self, TransactionError> {
444 let tx: BdkTransaction = deserialize(&transaction_bytes)?;
445 Ok(Transaction(tx))
446 }
447
448 pub fn compute_txid(&self) -> Arc<Txid> {
451 Arc::new(Txid(self.0.compute_txid()))
452 }
453
454 pub fn compute_wtxid(&self) -> Arc<Wtxid> {
456 Arc::new(Wtxid(self.0.compute_wtxid()))
457 }
458
459 #[inline]
478 pub fn weight(&self) -> u64 {
479 self.0.weight().to_wu()
480 }
481
482 pub fn total_size(&self) -> u64 {
487 self.0.total_size() as u64
488 }
489
490 #[inline]
498 pub fn vsize(&self) -> u64 {
499 self.0.vsize() as u64
500 }
501
502 pub fn is_coinbase(&self) -> bool {
507 self.0.is_coinbase()
508 }
509
510 pub fn is_explicitly_rbf(&self) -> bool {
520 self.0.is_explicitly_rbf()
521 }
522
523 pub fn is_lock_time_enabled(&self) -> bool {
527 self.0.is_lock_time_enabled()
528 }
529
530 pub fn version(&self) -> i32 {
532 self.0.version.0
533 }
534
535 pub fn serialize(&self) -> Vec<u8> {
537 serialize(&self.0)
538 }
539
540 pub fn input(&self) -> Vec<TxIn> {
542 self.0.input.iter().map(|tx_in| tx_in.into()).collect()
543 }
544
545 pub fn output(&self) -> Vec<TxOut> {
547 self.0.output.iter().map(|tx_out| tx_out.into()).collect()
548 }
549
550 pub fn lock_time(&self) -> u32 {
557 self.0.lock_time.to_consensus_u32()
558 }
559}
560
561impl From<BdkTransaction> for Transaction {
562 fn from(tx: BdkTransaction) -> Self {
563 Transaction(tx)
564 }
565}
566
567impl From<&BdkTransaction> for Transaction {
568 fn from(tx: &BdkTransaction) -> Self {
569 Transaction(tx.clone())
570 }
571}
572
573impl From<&Transaction> for BdkTransaction {
574 fn from(tx: &Transaction) -> Self {
575 tx.0.clone()
576 }
577}
578
579impl Display for Transaction {
580 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
581 write!(f, "{:?}", self.0)
582 }
583}
584
585#[derive(Clone, Debug, uniffi::Record)]
586pub struct TapScriptEntry {
587 pub script: Arc<Script>,
589 pub leaf_version: u8,
591}
592
593#[derive(Clone, Debug, uniffi::Record)]
594pub struct TapKeyOrigin {
595 pub tap_leaf_hashes: Vec<String>,
597 pub key_source: KeySource,
599}
600
601#[derive(Clone, Debug, uniffi::Record)]
602pub struct KeySource {
603 pub fingerprint: String,
605 pub path: Arc<DerivationPath>,
607}
608
609#[derive(Clone, Debug, Hash, Eq, PartialEq, uniffi::Record)]
610pub struct Key {
611 pub type_value: u8,
613 pub key: Vec<u8>,
616}
617
618#[derive(Clone, Debug, Hash, Eq, PartialEq, uniffi::Record)]
619pub struct ProprietaryKey {
620 pub prefix: Vec<u8>,
623 pub subtype: u8,
625 pub key: Vec<u8>,
627}
628
629#[derive(Clone, Debug, Hash, Eq, PartialEq, uniffi::Record)]
630pub struct ControlBlock {
631 pub internal_key: Vec<u8>,
633 pub merkle_branch: Vec<String>,
635 pub output_key_parity: u8,
637 pub leaf_version: u8,
639}
640
641#[derive(Clone, Debug, Hash, Eq, PartialEq, uniffi::Record)]
642pub struct TapScriptSigKey {
643 pub xonly_pubkey: String,
645 pub tap_leaf_hash: String,
648}
649
650#[derive(Clone, Debug, uniffi::Record)]
652pub struct Input {
653 pub non_witness_utxo: Option<Arc<Transaction>>,
657 pub witness_utxo: Option<TxOut>,
661 pub partial_sigs: HashMap<String, Vec<u8>>,
664 pub sighash_type: Option<String>,
667 pub redeem_script: Option<Arc<Script>>,
669 pub witness_script: Option<Arc<Script>>,
671 pub bip32_derivation: HashMap<String, KeySource>,
674
675 pub final_script_sig: Option<Arc<Script>>,
678
679 pub final_script_witness: Option<Vec<Vec<u8>>>,
682 pub ripemd160_preimages: HashMap<String, Vec<u8>>,
684 pub sha256_preimages: HashMap<String, Vec<u8>>,
686 pub hash160_preimages: HashMap<String, Vec<u8>>,
688 pub hash256_preimages: HashMap<String, Vec<u8>>,
690 pub tap_key_sig: Option<Vec<u8>>,
692 pub tap_script_sigs: HashMap<TapScriptSigKey, Vec<u8>>,
694 pub tap_scripts: HashMap<ControlBlock, TapScriptEntry>,
696 pub tap_key_origins: HashMap<String, TapKeyOrigin>,
698 pub tap_internal_key: Option<String>,
700 pub tap_merkle_root: Option<String>,
702 pub proprietary: HashMap<ProprietaryKey, Vec<u8>>,
704 pub unknown: HashMap<Key, Vec<u8>>,
706}
707
708use crate::error::AddForeignUtxoError;
709
710impl From<&BdkInput> for Input {
711 fn from(input: &BdkInput) -> Self {
712 Input {
713 non_witness_utxo: input
714 .non_witness_utxo
715 .as_ref()
716 .map(|tx| Arc::new(Transaction(tx.clone()))),
717 witness_utxo: input.witness_utxo.as_ref().map(TxOut::from),
718 partial_sigs: input
719 .partial_sigs
720 .iter()
721 .map(|(k, v)| (k.to_string(), v.to_vec()))
722 .collect(),
723 sighash_type: input.sighash_type.as_ref().map(|s| s.to_string()),
724 redeem_script: input
725 .redeem_script
726 .as_ref()
727 .map(|s| Arc::new(Script(s.clone()))),
728 witness_script: input
729 .witness_script
730 .as_ref()
731 .map(|s| Arc::new(Script(s.clone()))),
732 bip32_derivation: input
733 .bip32_derivation
734 .iter()
735 .map(|(pk, (fingerprint, deriv_path))| {
736 (
737 pk.to_string(),
738 KeySource {
739 fingerprint: fingerprint.to_string(),
740 path: Arc::new(deriv_path.clone().into()),
741 },
742 )
743 })
744 .collect(),
745 final_script_sig: input
746 .final_script_sig
747 .as_ref()
748 .map(|s| Arc::new(Script(s.clone()))),
749 final_script_witness: input.final_script_witness.as_ref().map(|w| w.to_vec()),
750 ripemd160_preimages: input
751 .ripemd160_preimages
752 .iter()
753 .map(|(k, v)| (k.to_string(), v.clone()))
754 .collect(),
755 sha256_preimages: input
756 .sha256_preimages
757 .iter()
758 .map(|(k, v)| (k.to_string(), v.clone()))
759 .collect(),
760 hash160_preimages: input
761 .hash160_preimages
762 .iter()
763 .map(|(k, v)| (k.to_string(), v.clone()))
764 .collect(),
765 hash256_preimages: input
766 .hash256_preimages
767 .iter()
768 .map(|(k, v)| (k.to_string(), v.clone()))
769 .collect(),
770 tap_key_sig: input.tap_key_sig.as_ref().map(|s| s.serialize().to_vec()),
771 tap_script_sigs: input
772 .tap_script_sigs
773 .iter()
774 .map(|(k, v)| {
775 let key = TapScriptSigKey {
776 xonly_pubkey: k.0.to_string(),
777 tap_leaf_hash: k.1.to_string(),
778 };
779 (key, v.to_vec())
780 })
781 .collect(),
782 tap_scripts: input
783 .tap_scripts
784 .iter()
785 .map(|(k, v)| {
786 let key = ControlBlock {
787 internal_key: k.internal_key.serialize().to_vec(),
788 merkle_branch: k.merkle_branch.iter().map(|h| h.to_string()).collect(),
789 output_key_parity: k.output_key_parity.to_u8(),
790 leaf_version: k.leaf_version.to_consensus(),
791 };
792 let entry = TapScriptEntry {
793 script: Arc::new(v.0.clone().into()),
794 leaf_version: v.1.to_consensus(),
795 };
796 (key, entry)
797 })
798 .collect(),
799 tap_key_origins: input
800 .tap_key_origins
801 .iter()
802 .map(|(k, v)| {
803 let key = k.to_string();
804 let value = TapKeyOrigin {
805 tap_leaf_hashes: v.0.iter().map(|h| h.to_string()).collect(),
806 key_source: KeySource {
807 #[rustfmt::skip]
809 fingerprint: v.1.0.to_string(),
810 #[rustfmt::skip]
811 path: Arc::new(v.1.1.clone().into()),
812 },
813 };
814 (key, value)
815 })
816 .collect(),
817 tap_internal_key: input.tap_internal_key.as_ref().map(|k| k.to_string()),
818 tap_merkle_root: input.tap_merkle_root.as_ref().map(|k| k.to_string()),
819 proprietary: input
820 .proprietary
821 .iter()
822 .map(|(k, v)| {
823 (
824 ProprietaryKey {
825 prefix: k.prefix.clone(),
826 subtype: k.subtype,
827 key: k.key.clone(),
828 },
829 v.to_vec(),
830 )
831 })
832 .collect(),
833 unknown: input
834 .unknown
835 .iter()
836 .map(|(k, v)| {
837 (
838 Key {
839 key: k.key.clone(),
840 type_value: k.type_value,
841 },
842 v.to_vec(),
843 )
844 })
845 .collect(),
846 }
847 }
848}
849
850impl TryFrom<Input> for BdkInput {
851 type Error = AddForeignUtxoError;
852
853 fn try_from(input: Input) -> Result<Self, Self::Error> {
854 use bdk_wallet::bitcoin::ecdsa;
855 use bdk_wallet::bitcoin::hashes::Hash as HashTrait;
856 use bdk_wallet::bitcoin::key::PublicKey as Secp256k1PublicKey;
857 use bdk_wallet::bitcoin::psbt::PsbtSighashType;
858 use bdk_wallet::bitcoin::secp256k1::XOnlyPublicKey;
859 use bdk_wallet::bitcoin::taproot::{
860 ControlBlock as BdkControlBlock, LeafVersion, TapLeafHash, TapNodeHash,
861 };
862 use std::str::FromStr;
863
864 let non_witness_utxo = input.non_witness_utxo.map(|tx| tx.0.clone());
865
866 let witness_utxo = input.witness_utxo.map(|txout| txout.into());
867
868 let partial_sigs = input
869 .partial_sigs
870 .into_iter()
871 .map(|(k, v)| {
872 let pubkey = Secp256k1PublicKey::from_str(&k).map_err(|e| {
873 AddForeignUtxoError::InputConversionError {
874 error_message: format!("invalid public key in partial_sigs: {}", e),
875 }
876 })?;
877 let sig = ecdsa::Signature::from_slice(&v).map_err(|e| {
878 AddForeignUtxoError::InputConversionError {
879 error_message: format!("invalid signature in partial_sigs: {}", e),
880 }
881 })?;
882 Ok((pubkey, sig))
883 })
884 .collect::<Result<std::collections::BTreeMap<_, _>, AddForeignUtxoError>>()?;
885
886 let sighash_type = input
887 .sighash_type
888 .map(|s| {
889 PsbtSighashType::from_str(&s).map_err(|e| {
890 AddForeignUtxoError::InputConversionError {
891 error_message: format!("invalid sighash type: {}", e),
892 }
893 })
894 })
895 .transpose()?;
896
897 let redeem_script = input.redeem_script.map(|s| s.0.clone());
898 let witness_script = input.witness_script.map(|s| s.0.clone());
899
900 let bip32_derivation = input
901 .bip32_derivation
902 .into_iter()
903 .map(|(k, v)| {
904 use bdk_wallet::bitcoin::bip32::{DerivationPath, Fingerprint};
905 use bdk_wallet::bitcoin::secp256k1::PublicKey as Secp256k1RawPublicKey;
906 let pubkey = Secp256k1RawPublicKey::from_str(&k).map_err(|e| {
907 AddForeignUtxoError::InputConversionError {
908 error_message: format!("invalid public key in bip32_derivation: {}", e),
909 }
910 })?;
911 let fingerprint = Fingerprint::from_str(&v.fingerprint).map_err(|e| {
912 AddForeignUtxoError::InputConversionError {
913 error_message: format!("invalid fingerprint: {}", e),
914 }
915 })?;
916 let path: DerivationPath = v.path.0.clone();
917 Ok((pubkey, (fingerprint, path)))
918 })
919 .collect::<Result<std::collections::BTreeMap<_, _>, AddForeignUtxoError>>()?;
920
921 let final_script_sig = input.final_script_sig.map(|s| s.0.clone());
922
923 let final_script_witness = input.final_script_witness.map(|w| {
924 use bdk_wallet::bitcoin::Witness;
925 Witness::from_slice(&w)
926 });
927
928 let ripemd160_preimages = input
929 .ripemd160_preimages
930 .into_iter()
931 .map(|(k, v)| {
932 use bdk_wallet::bitcoin::hashes::ripemd160;
933 let hash = ripemd160::Hash::from_str(&k).map_err(|e| {
934 AddForeignUtxoError::InputConversionError {
935 error_message: format!("invalid ripemd160 hash: {}", e),
936 }
937 })?;
938 Ok((hash, v))
939 })
940 .collect::<Result<_, AddForeignUtxoError>>()?;
941
942 let sha256_preimages = input
943 .sha256_preimages
944 .into_iter()
945 .map(|(k, v)| {
946 use bdk_wallet::bitcoin::hashes::sha256;
947 let hash = sha256::Hash::from_str(&k).map_err(|e| {
948 AddForeignUtxoError::InputConversionError {
949 error_message: format!("invalid sha256 hash: {}", e),
950 }
951 })?;
952 Ok((hash, v))
953 })
954 .collect::<Result<_, AddForeignUtxoError>>()?;
955
956 let hash160_preimages = input
957 .hash160_preimages
958 .into_iter()
959 .map(|(k, v)| {
960 use bdk_wallet::bitcoin::hashes::hash160;
961 let hash = hash160::Hash::from_str(&k).map_err(|e| {
962 AddForeignUtxoError::InputConversionError {
963 error_message: format!("invalid hash160: {}", e),
964 }
965 })?;
966 Ok((hash, v))
967 })
968 .collect::<Result<_, AddForeignUtxoError>>()?;
969
970 let hash256_preimages = input
971 .hash256_preimages
972 .into_iter()
973 .map(|(k, v)| {
974 use bdk_wallet::bitcoin::hashes::sha256d;
975 let hash = sha256d::Hash::from_str(&k).map_err(|e| {
976 AddForeignUtxoError::InputConversionError {
977 error_message: format!("invalid hash256: {}", e),
978 }
979 })?;
980 Ok((hash, v))
981 })
982 .collect::<Result<_, AddForeignUtxoError>>()?;
983
984 let tap_key_sig = input
985 .tap_key_sig
986 .map(|s| {
987 use bdk_wallet::bitcoin::taproot::Signature;
988 Signature::from_slice(&s).map_err(|e| AddForeignUtxoError::InputConversionError {
989 error_message: format!("invalid taproot signature: {}", e),
990 })
991 })
992 .transpose()?;
993
994 let tap_script_sigs = input
995 .tap_script_sigs
996 .into_iter()
997 .map(|(k, v)| {
998 use bdk_wallet::bitcoin::taproot::Signature;
999 let xonly = XOnlyPublicKey::from_str(&k.xonly_pubkey).map_err(|e| {
1000 AddForeignUtxoError::InputConversionError {
1001 error_message: format!("invalid xonly pubkey: {}", e),
1002 }
1003 })?;
1004 let leaf_hash = TapLeafHash::from_str(&k.tap_leaf_hash).map_err(|e| {
1005 AddForeignUtxoError::InputConversionError {
1006 error_message: format!("invalid tap leaf hash: {}", e),
1007 }
1008 })?;
1009 let sig = Signature::from_slice(&v).map_err(|e| {
1010 AddForeignUtxoError::InputConversionError {
1011 error_message: format!("invalid taproot script signature: {}", e),
1012 }
1013 })?;
1014 Ok(((xonly, leaf_hash), sig))
1015 })
1016 .collect::<Result<_, AddForeignUtxoError>>()?;
1017
1018 let tap_scripts = input
1019 .tap_scripts
1020 .into_iter()
1021 .map(|(k, v)| {
1022 use bdk_wallet::bitcoin::key::XOnlyPublicKey as BdkXOnlyPublicKey;
1023 use bdk_wallet::bitcoin::taproot::TapNodeHash;
1024
1025 let internal_key = BdkXOnlyPublicKey::from_slice(&k.internal_key).map_err(|e| {
1026 AddForeignUtxoError::InputConversionError {
1027 error_message: format!("invalid internal key: {}", e),
1028 }
1029 })?;
1030
1031 let output_key_parity = k.output_key_parity;
1032 let leaf_version_u8 = k.leaf_version;
1033
1034 let merkle_branch: Vec<TapNodeHash> = k
1035 .merkle_branch
1036 .into_iter()
1037 .map(|h| {
1038 TapNodeHash::from_str(&h).map_err(|e| {
1039 AddForeignUtxoError::InputConversionError {
1040 error_message: format!("invalid merkle branch hash: {}", e),
1041 }
1042 })
1043 })
1044 .collect::<Result<_, AddForeignUtxoError>>()?;
1045
1046 let mut control_block_bytes = vec![output_key_parity | leaf_version_u8];
1047 control_block_bytes.extend_from_slice(&internal_key.serialize());
1048 for hash in &merkle_branch {
1049 control_block_bytes.extend_from_slice(&hash.to_byte_array());
1050 }
1051
1052 let control_block = BdkControlBlock::decode(&control_block_bytes).map_err(|e| {
1053 AddForeignUtxoError::InputConversionError {
1054 error_message: format!("invalid control block: {}", e),
1055 }
1056 })?;
1057
1058 let leaf_version = LeafVersion::from_consensus(leaf_version_u8).map_err(|_| {
1059 AddForeignUtxoError::InputConversionError {
1060 error_message: format!("invalid leaf version: {}", leaf_version_u8),
1061 }
1062 })?;
1063
1064 Ok((control_block, (v.script.0.clone(), leaf_version)))
1065 })
1066 .collect::<Result<_, AddForeignUtxoError>>()?;
1067
1068 let tap_key_origins = input
1069 .tap_key_origins
1070 .into_iter()
1071 .map(|(k, v)| {
1072 use bdk_wallet::bitcoin::bip32::{DerivationPath, Fingerprint};
1073
1074 let xonly = XOnlyPublicKey::from_str(&k).map_err(|e| {
1075 AddForeignUtxoError::InputConversionError {
1076 error_message: format!("invalid xonly pubkey in tap_key_origins: {}", e),
1077 }
1078 })?;
1079
1080 let leaf_hashes: Vec<TapLeafHash> = v
1081 .tap_leaf_hashes
1082 .into_iter()
1083 .map(|h| {
1084 TapLeafHash::from_str(&h).map_err(|e| {
1085 AddForeignUtxoError::InputConversionError {
1086 error_message: format!("invalid tap leaf hash: {}", e),
1087 }
1088 })
1089 })
1090 .collect::<Result<_, AddForeignUtxoError>>()?;
1091
1092 let fingerprint =
1093 Fingerprint::from_str(&v.key_source.fingerprint).map_err(|e| {
1094 AddForeignUtxoError::InputConversionError {
1095 error_message: format!("invalid fingerprint in tap_key_origins: {}", e),
1096 }
1097 })?;
1098
1099 let path: DerivationPath = v.key_source.path.0.clone();
1100
1101 Ok((xonly, (leaf_hashes, (fingerprint, path))))
1102 })
1103 .collect::<Result<_, AddForeignUtxoError>>()?;
1104
1105 let tap_internal_key = input
1106 .tap_internal_key
1107 .map(|k| {
1108 XOnlyPublicKey::from_str(&k).map_err(|e| {
1109 AddForeignUtxoError::InputConversionError {
1110 error_message: format!("invalid tap internal key: {}", e),
1111 }
1112 })
1113 })
1114 .transpose()?;
1115
1116 let tap_merkle_root = input
1117 .tap_merkle_root
1118 .map(|k| {
1119 TapNodeHash::from_str(&k).map_err(|e| AddForeignUtxoError::InputConversionError {
1120 error_message: format!("invalid tap merkle root: {}", e),
1121 })
1122 })
1123 .transpose()?;
1124
1125 let proprietary = input
1126 .proprietary
1127 .into_iter()
1128 .map(|(k, v)| {
1129 use bdk_wallet::bitcoin::psbt::raw::ProprietaryKey as BdkProprietaryKey;
1130 (
1131 BdkProprietaryKey {
1132 prefix: k.prefix,
1133 subtype: k.subtype,
1134 key: k.key,
1135 },
1136 v,
1137 )
1138 })
1139 .collect();
1140
1141 let unknown = input
1142 .unknown
1143 .into_iter()
1144 .map(|(k, v)| {
1145 use bdk_wallet::bitcoin::psbt::raw::Key as BdkKey;
1146 (
1147 BdkKey {
1148 type_value: k.type_value,
1149 key: k.key,
1150 },
1151 v,
1152 )
1153 })
1154 .collect();
1155
1156 Ok(BdkInput {
1157 non_witness_utxo,
1158 witness_utxo,
1159 partial_sigs,
1160 sighash_type,
1161 redeem_script,
1162 witness_script,
1163 bip32_derivation,
1164 final_script_sig,
1165 final_script_witness,
1166 ripemd160_preimages,
1167 sha256_preimages,
1168 hash160_preimages,
1169 hash256_preimages,
1170 tap_key_sig,
1171 tap_script_sigs,
1172 tap_scripts,
1173 tap_key_origins,
1174 tap_internal_key,
1175 tap_merkle_root,
1176 proprietary,
1177 unknown,
1178 })
1179 }
1180}
1181
1182#[derive(Debug, uniffi::Object)]
1184#[uniffi::export(Display)]
1185pub struct LeafNode(BdkLeafNode);
1186
1187#[uniffi::export]
1188impl LeafNode {
1189 pub fn depth(&self) -> u8 {
1191 self.0.depth()
1192 }
1193
1194 pub fn leaf_hash(&self) -> Option<String> {
1198 self.0.leaf_hash().map(|h| h.to_string())
1199 }
1200
1201 pub fn node_hash(&self) -> String {
1206 self.0.node_hash().to_string()
1207 }
1208
1209 pub fn script(&self) -> Option<Arc<Script>> {
1211 self.0.script().map(|s| Arc::new(Script(s.to_owned())))
1212 }
1213
1214 pub fn leaf_version(&self) -> Option<u8> {
1216 self.0.leaf_version().map(|n| n.to_consensus())
1217 }
1218
1219 pub fn merkle_branch(&self) -> Vec<String> {
1222 self.0
1223 .merkle_branch()
1224 .to_vec()
1225 .iter()
1226 .map(|h| h.to_string())
1227 .collect()
1228 }
1229}
1230
1231impl Display for LeafNode {
1232 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1233 write!(f, "{:?}", self)
1234 }
1235}
1236
1237#[derive(Debug, uniffi::Object)]
1241#[uniffi::export(Display)]
1242pub struct TapTree(BdkTapTree);
1243
1244#[uniffi::export]
1245impl TapTree {
1246 pub fn root_hash(&self) -> String {
1248 self.0.root_hash().to_string()
1249 }
1250
1251 pub fn node_info(&self) -> Arc<NodeInfo> {
1253 Arc::new(NodeInfo(self.0.node_info().clone()))
1254 }
1255}
1256
1257impl Display for TapTree {
1258 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1259 write!(f, "{:?}", self)
1260 }
1261}
1262
1263#[derive(Debug, uniffi::Object)]
1268#[uniffi::export(Display)]
1269pub struct NodeInfo(BdkNodeInfo);
1270
1271#[uniffi::export]
1272impl NodeInfo {
1273 pub fn leaf_nodes(&self) -> Vec<Arc<LeafNode>> {
1275 self.0
1276 .leaf_nodes()
1277 .map(|ln| Arc::new(LeafNode(ln.clone())))
1278 .collect()
1279 }
1280
1281 pub fn node_hash(&self) -> String {
1283 self.0.node_hash().to_string()
1284 }
1285}
1286
1287impl Display for NodeInfo {
1288 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1289 write!(f, "{:?}", self)
1290 }
1291}
1292
1293#[derive(Debug, uniffi::Record)]
1296pub struct Output {
1297 pub redeem_script: Option<Arc<Script>>,
1299 pub witness_script: Option<Arc<Script>>,
1301 pub bip32_derivation: HashMap<String, KeySource>,
1304 pub tap_internal_key: Option<String>,
1306 pub tap_tree: Option<Arc<TapTree>>,
1308 pub tap_key_origins: HashMap<String, TapKeyOrigin>,
1310 pub proprietary: HashMap<ProprietaryKey, Vec<u8>>,
1312 pub unknown: HashMap<Key, Vec<u8>>,
1314}
1315
1316impl From<&BdkOutput> for Output {
1317 fn from(output: &BdkOutput) -> Self {
1318 Output {
1319 redeem_script: output
1320 .redeem_script
1321 .as_ref()
1322 .map(|s| Arc::new(Script(s.clone()))),
1323 witness_script: output
1324 .witness_script
1325 .as_ref()
1326 .map(|s| Arc::new(Script(s.clone()))),
1327 bip32_derivation: output
1328 .bip32_derivation
1329 .iter()
1330 .map(|(pk, (fingerprint, deriv_path))| {
1331 (
1332 pk.to_string(),
1333 KeySource {
1334 fingerprint: fingerprint.to_string(),
1335 path: Arc::new(deriv_path.clone().into()),
1336 },
1337 )
1338 })
1339 .collect(),
1340 tap_internal_key: output.tap_internal_key.as_ref().map(|k| k.to_string()),
1341 tap_tree: output
1342 .tap_tree
1343 .as_ref()
1344 .map(|t| Arc::new(TapTree(t.clone()))),
1345 tap_key_origins: output
1346 .tap_key_origins
1347 .iter()
1348 .map(|(k, v)| {
1349 let key = k.to_string();
1350 let value = TapKeyOrigin {
1351 tap_leaf_hashes: v.0.iter().map(|h| h.to_string()).collect(),
1352 key_source: KeySource {
1353 #[rustfmt::skip]
1355 fingerprint: v.1.0.to_string(),
1356 #[rustfmt::skip]
1357 path: Arc::new(v.1.1.clone().into()),
1358 },
1359 };
1360 (key, value)
1361 })
1362 .collect(),
1363 proprietary: output
1364 .proprietary
1365 .iter()
1366 .map(|(k, v)| {
1367 (
1368 ProprietaryKey {
1369 prefix: k.prefix.clone(),
1370 subtype: k.subtype,
1371 key: k.key.clone(),
1372 },
1373 v.to_vec(),
1374 )
1375 })
1376 .collect(),
1377 unknown: output
1378 .unknown
1379 .iter()
1380 .map(|(k, v)| {
1381 (
1382 Key {
1383 key: k.key.clone(),
1384 type_value: k.type_value,
1385 },
1386 v.to_vec(),
1387 )
1388 })
1389 .collect(),
1390 }
1391 }
1392}
1393
1394#[derive(uniffi::Object)]
1396#[uniffi::export(Display)]
1397pub struct Psbt(pub(crate) Mutex<BdkPsbt>);
1398
1399#[uniffi::export]
1400impl Psbt {
1401 #[uniffi::constructor]
1403 pub fn new(psbt_base64: String) -> Result<Self, PsbtParseError> {
1404 let psbt: BdkPsbt = BdkPsbt::from_str(&psbt_base64)?;
1405 Ok(Psbt(Mutex::new(psbt)))
1406 }
1407
1408 #[uniffi::constructor]
1414 pub fn from_unsigned_tx(tx: Arc<Transaction>) -> Result<Arc<Psbt>, PsbtError> {
1415 let psbt: BdkPsbt = BdkPsbt::from_unsigned_tx(tx.0.clone())?;
1416 Ok(Arc::new(Psbt(Mutex::new(psbt))))
1417 }
1418
1419 #[uniffi::constructor]
1421 pub fn from_file(path: String) -> Result<Self, PsbtError> {
1422 let file = File::open(path)?;
1423 let mut buf_read = BufReader::new(file);
1424 let psbt: BdkPsbt = BdkPsbt::deserialize_from_reader(&mut buf_read)?;
1425 Ok(Psbt(Mutex::new(psbt)))
1426 }
1427
1428 pub fn serialize(&self) -> String {
1430 let psbt = self.0.lock().unwrap().clone();
1431 psbt.to_string()
1432 }
1433
1434 pub fn extract_tx(&self) -> Result<Arc<Transaction>, ExtractTxError> {
1442 let tx: BdkTransaction = self.0.lock().unwrap().clone().extract_tx()?;
1443 let transaction: Transaction = tx.into();
1444 Ok(Arc::new(transaction))
1445 }
1446
1447 pub fn extract_tx_with_fee_rate_limit(
1453 &self,
1454 max_fee_rate: Arc<FeeRate>,
1455 ) -> Result<Arc<Transaction>, ExtractTxError> {
1456 let tx: BdkTransaction = self
1457 .0
1458 .lock()
1459 .unwrap()
1460 .clone()
1461 .extract_tx_with_fee_rate_limit(max_fee_rate.0)?;
1462 let transaction: Transaction = tx.into();
1463 Ok(Arc::new(transaction))
1464 }
1465
1466 pub fn extract_tx_unchecked_fee_rate(&self) -> Arc<Transaction> {
1470 let tx: BdkTransaction = self
1471 .0
1472 .lock()
1473 .unwrap()
1474 .clone()
1475 .extract_tx_unchecked_fee_rate();
1476 Arc::new(tx.into())
1477 }
1478
1479 pub fn fee(&self) -> Result<u64, PsbtError> {
1490 self.0
1491 .lock()
1492 .unwrap()
1493 .fee()
1494 .map(|fee| fee.to_sat())
1495 .map_err(PsbtError::from)
1496 }
1497
1498 pub fn combine(&self, other: Arc<Psbt>) -> Result<Arc<Psbt>, PsbtError> {
1502 let mut original_psbt = self.0.lock().unwrap().clone();
1503 let other_psbt = other.0.lock().unwrap().clone();
1504 original_psbt.combine(other_psbt)?;
1505 Ok(Arc::new(Psbt(Mutex::new(original_psbt))))
1506 }
1507
1508 pub fn finalize(&self) -> FinalizedPsbtResult {
1512 let curve = Secp256k1::verification_only();
1513 let finalized = self.0.lock().unwrap().clone().finalize(&curve);
1514 match finalized {
1515 Ok(psbt) => FinalizedPsbtResult {
1516 psbt: Arc::new(psbt.into()),
1517 could_finalize: true,
1518 errors: None,
1519 },
1520 Err((psbt, errors)) => {
1521 let errors = errors.into_iter().map(|e| e.into()).collect();
1522 FinalizedPsbtResult {
1523 psbt: Arc::new(psbt.into()),
1524 could_finalize: false,
1525 errors: Some(errors),
1526 }
1527 }
1528 }
1529 }
1530
1531 pub fn write_to_file(&self, path: String) -> Result<(), PsbtError> {
1533 let file = File::create_new(path)?;
1534 let mut writer = BufWriter::new(file);
1535 let psbt = self.0.lock().unwrap();
1536 psbt.serialize_to_writer(&mut writer)?;
1537 Ok(())
1538 }
1539
1540 pub fn json_serialize(&self) -> String {
1542 let psbt = self.0.lock().unwrap();
1543 serde_json::to_string(psbt.deref()).unwrap()
1544 }
1545
1546 pub fn spend_utxo(&self, input_index: u64) -> String {
1548 let psbt = self.0.lock().unwrap();
1549 let utxo = psbt.spend_utxo(input_index as usize).unwrap();
1550 serde_json::to_string(&utxo).unwrap()
1551 }
1552
1553 pub fn input(&self) -> Vec<Input> {
1555 let psbt = self.0.lock().unwrap();
1556 psbt.inputs.iter().map(|input| input.into()).collect()
1557 }
1558
1559 pub fn output(&self) -> Vec<Output> {
1561 let psbt = self.0.lock().unwrap();
1562 psbt.outputs.iter().map(|o| o.into()).collect()
1563 }
1564}
1565
1566impl From<BdkPsbt> for Psbt {
1567 fn from(psbt: BdkPsbt) -> Self {
1568 Psbt(Mutex::new(psbt))
1569 }
1570}
1571
1572impl Display for Psbt {
1573 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1574 write!(f, "{}", self.0.lock().unwrap())
1575 }
1576}
1577
1578#[derive(uniffi::Record)]
1579pub struct FinalizedPsbtResult {
1580 pub psbt: Arc<Psbt>,
1581 pub could_finalize: bool,
1582 pub errors: Option<Vec<PsbtFinalizeError>>,
1583}
1584
1585#[derive(Debug, Clone, uniffi::Record)]
1587pub struct TxIn {
1588 pub previous_output: OutPoint,
1590 pub script_sig: Arc<Script>,
1592 pub sequence: u32,
1594 pub witness: Vec<Vec<u8>>,
1596}
1597
1598impl From<&BdkTxIn> for TxIn {
1599 fn from(tx_in: &BdkTxIn) -> Self {
1600 TxIn {
1601 previous_output: OutPoint {
1602 txid: Arc::new(Txid(tx_in.previous_output.txid)),
1603 vout: tx_in.previous_output.vout,
1604 },
1605 script_sig: Arc::new(Script(tx_in.script_sig.clone())),
1606 sequence: tx_in.sequence.0,
1607 witness: tx_in.witness.to_vec(),
1608 }
1609 }
1610}
1611
1612#[derive(Debug, Clone, uniffi::Record)]
1620pub struct TxOut {
1621 pub value: Arc<Amount>,
1623 pub script_pubkey: Arc<Script>,
1625}
1626
1627impl From<&BdkTxOut> for TxOut {
1628 fn from(tx_out: &BdkTxOut) -> Self {
1629 TxOut {
1630 value: Arc::new(Amount(tx_out.value)),
1631 script_pubkey: Arc::new(Script(tx_out.script_pubkey.clone())),
1632 }
1633 }
1634}
1635
1636impl From<BdkTxOut> for TxOut {
1637 fn from(tx_out: BdkTxOut) -> Self {
1638 Self {
1639 value: Arc::new(Amount(tx_out.value)),
1640 script_pubkey: Arc::new(Script(tx_out.script_pubkey)),
1641 }
1642 }
1643}
1644
1645impl From<TxOut> for BdkTxOut {
1646 fn from(tx_out: TxOut) -> Self {
1647 Self {
1648 value: tx_out.value.0,
1649 script_pubkey: tx_out.script_pubkey.0.clone(),
1650 }
1651 }
1652}
1653
1654#[derive(Copy, Clone, uniffi::Enum)]
1656pub enum ChildNumber {
1657 Normal {
1659 index: u32,
1661 },
1662 Hardened {
1664 index: u32,
1666 },
1667}
1668
1669impl From<BdkChildNumber> for ChildNumber {
1670 fn from(value: BdkChildNumber) -> Self {
1671 match value {
1672 BdkChildNumber::Normal { index } => ChildNumber::Normal { index },
1673 BdkChildNumber::Hardened { index } => ChildNumber::Hardened { index },
1674 }
1675 }
1676}
1677
1678impl TryFrom<ChildNumber> for BdkChildNumber {
1679 type Error = Bip32Error;
1680
1681 fn try_from(value: ChildNumber) -> Result<Self, Self::Error> {
1682 match value {
1683 ChildNumber::Normal { index } => {
1684 BdkChildNumber::from_normal_idx(index).map_err(Bip32Error::from)
1685 }
1686 ChildNumber::Hardened { index } => {
1687 BdkChildNumber::from_hardened_idx(index).map_err(Bip32Error::from)
1688 }
1689 }
1690 }
1691}
1692
1693#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, std::hash::Hash, uniffi::Object)]
1695#[uniffi::export(Display, Eq, Hash, Ord)]
1696pub struct BlockHash(pub(crate) BitcoinBlockHash);
1697
1698impl_hash_like!(BlockHash, BitcoinBlockHash);
1699
1700#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, std::hash::Hash, uniffi::Object)]
1702#[uniffi::export(Display, Eq, Hash, Ord)]
1703pub struct Txid(pub(crate) BitcoinTxid);
1704
1705impl_hash_like!(Txid, BitcoinTxid);
1706
1707#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, std::hash::Hash, uniffi::Object)]
1710#[uniffi::export(Display, Eq, Hash, Ord)]
1711pub struct Wtxid(pub(crate) BitcoinWtxid);
1712
1713impl_hash_like!(Wtxid, BitcoinWtxid);
1714
1715#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, std::hash::Hash, uniffi::Object)]
1717#[uniffi::export(Display, Eq, Hash, Ord)]
1718pub struct DescriptorId(pub(crate) BitcoinSha256Hash);
1719
1720impl_hash_like!(DescriptorId, BitcoinSha256Hash);
1721
1722#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, std::hash::Hash, uniffi::Object)]
1724#[uniffi::export(Display, Eq, Hash, Ord)]
1725pub struct TxMerkleNode(pub(crate) BitcoinDoubleSha256Hash);
1726
1727impl_hash_like!(TxMerkleNode, BitcoinDoubleSha256Hash);
1728
1729#[uniffi::remote(Enum)]
1731pub enum DescriptorType {
1732 Bare,
1734 Sh,
1736 Pkh,
1738 Wpkh,
1740 Wsh,
1742 ShWsh,
1744 ShWpkh,
1746 ShSortedMulti,
1748 WshSortedMulti,
1750 ShWshSortedMulti,
1752 Tr,
1754}