bdkffi/
error.rs

1use crate::OutPoint;
2
3use bdk_electrum::electrum_client::Error as BdkElectrumError;
4use bdk_esplora::esplora_client::Error as BdkEsploraError;
5use bdk_wallet::bitcoin::address::ParseError as BdkParseError;
6use bdk_wallet::bitcoin::address::{FromScriptError as BdkFromScriptError, ParseError};
7use bdk_wallet::bitcoin::amount::ParseAmountError as BdkParseAmountError;
8use bdk_wallet::bitcoin::bip32::Error as BdkBip32Error;
9use bdk_wallet::bitcoin::consensus::encode::Error as BdkEncodeError;
10use bdk_wallet::bitcoin::hashes::hex::HexToArrayError as BdkHexToArrayError;
11use bdk_wallet::bitcoin::hex::DisplayHex;
12use bdk_wallet::bitcoin::psbt::Error as BdkPsbtError;
13use bdk_wallet::bitcoin::psbt::ExtractTxError as BdkExtractTxError;
14use bdk_wallet::bitcoin::psbt::PsbtParseError as BdkPsbtParseError;
15use bdk_wallet::bitcoin::script::PushBytesError;
16use bdk_wallet::chain::local_chain::CannotConnectError as BdkCannotConnectError;
17use bdk_wallet::chain::rusqlite::Error as BdkSqliteError;
18use bdk_wallet::chain::tx_graph::CalculateFeeError as BdkCalculateFeeError;
19use bdk_wallet::descriptor::DescriptorError as BdkDescriptorError;
20use bdk_wallet::error::BuildFeeBumpError;
21use bdk_wallet::error::CreateTxError as BdkCreateTxError;
22use bdk_wallet::keys::bip39::Error as BdkBip39Error;
23use bdk_wallet::migration::PreV1MigrationError as BdkPreV1MigrationError;
24use bdk_wallet::miniscript::descriptor::DescriptorKeyParseError as BdkDescriptorKeyParseError;
25use bdk_wallet::miniscript::psbt::Error as BdkPsbtFinalizeError;
26#[allow(deprecated)]
27use bdk_wallet::signer::SignerError as BdkSignerError;
28use bdk_wallet::tx_builder::AddForeignUtxoError as BdkAddForeignUtxoError;
29use bdk_wallet::tx_builder::AddUtxoError;
30use bdk_wallet::LoadWithPersistError as BdkLoadWithPersistError;
31use bdk_wallet::{chain, CreateWithPersistError as BdkCreateWithPersistError};
32
33use std::convert::TryInto;
34
35// ------------------------------------------------------------------------
36// error definitions
37// ------------------------------------------------------------------------
38
39#[derive(Debug, thiserror::Error, uniffi::Error)]
40pub enum AddForeignUtxoError {
41    #[error("foreign utxo outpoint txid does not match PSBT input txid")]
42    InvalidTxid,
43
44    #[error("requested outpoint doesn't exist in the tx: {outpoint}")]
45    InvalidOutpoint { outpoint: String },
46
47    #[error("foreign utxo missing witness_utxo or non_witness_utxo")]
48    MissingUtxo,
49
50    #[error("failed to convert Input to BdkInput: {error_message}")]
51    InputConversionError { error_message: String },
52}
53
54#[derive(Debug, thiserror::Error, uniffi::Error)]
55pub enum AddressParseError {
56    #[error("base58 address encoding error")]
57    Base58,
58
59    #[error("bech32 address encoding error")]
60    Bech32,
61
62    #[error("witness version conversion/parsing error: {error_message}")]
63    WitnessVersion { error_message: String },
64
65    #[error("witness program error: {error_message}")]
66    WitnessProgram { error_message: String },
67
68    #[error("tried to parse an unknown hrp")]
69    UnknownHrp,
70
71    #[error("legacy address base58 string")]
72    LegacyAddressTooLong,
73
74    #[error("legacy address base58 data")]
75    InvalidBase58PayloadLength,
76
77    #[error("segwit address bech32 string")]
78    InvalidLegacyPrefix,
79
80    #[error("validation error")]
81    NetworkValidation,
82
83    // This error is required because the bdk::bitcoin::address::ParseError is non-exhaustive
84    #[error("other address parse error")]
85    OtherAddressParseErr,
86}
87
88#[derive(Debug, thiserror::Error, uniffi::Error)]
89pub enum Bip32Error {
90    #[error("cannot derive from a hardened key")]
91    CannotDeriveFromHardenedKey,
92
93    #[error("secp256k1 error: {error_message}")]
94    Secp256k1 { error_message: String },
95
96    #[error("invalid child number: {child_number}")]
97    InvalidChildNumber { child_number: u32 },
98
99    #[error("invalid format for child number")]
100    InvalidChildNumberFormat,
101
102    #[error("invalid derivation path format")]
103    InvalidDerivationPathFormat,
104
105    #[error("unknown version: {version}")]
106    UnknownVersion { version: String },
107
108    #[error("wrong extended key length: {length}")]
109    WrongExtendedKeyLength { length: u32 },
110
111    #[error("base58 error: {error_message}")]
112    Base58 { error_message: String },
113
114    #[error("hexadecimal conversion error: {error_message}")]
115    Hex { error_message: String },
116
117    #[error("invalid public key hex length: {length}")]
118    InvalidPublicKeyHexLength { length: u32 },
119
120    #[error("unknown error: {error_message}")]
121    UnknownError { error_message: String },
122}
123
124#[derive(Debug, thiserror::Error, uniffi::Error)]
125pub enum Bip39Error {
126    #[error("the word count {word_count} is not supported")]
127    BadWordCount { word_count: u64 },
128
129    #[error("unknown word at index {index}")]
130    UnknownWord { index: u64 },
131
132    #[error("entropy bit count {bit_count} is invalid")]
133    BadEntropyBitCount { bit_count: u64 },
134
135    #[error("checksum is invalid")]
136    InvalidChecksum,
137
138    #[error("ambiguous languages detected: {languages}")]
139    AmbiguousLanguages { languages: String },
140}
141
142#[derive(Debug, thiserror::Error, uniffi::Error)]
143pub enum CalculateFeeError {
144    #[error("missing transaction output: {out_points:?}")]
145    MissingTxOut { out_points: Vec<OutPoint> },
146
147    #[error("negative fee value: {amount}")]
148    NegativeFee { amount: String },
149}
150
151#[derive(Debug, thiserror::Error, uniffi::Error)]
152pub enum CannotConnectError {
153    #[error("cannot include height: {height}")]
154    Include { height: u32 },
155}
156
157#[derive(Debug, thiserror::Error, uniffi::Error)]
158pub enum CreateTxError {
159    #[error("descriptor error: {error_message}")]
160    Descriptor { error_message: String },
161
162    #[error("policy error: {error_message}")]
163    Policy { error_message: String },
164
165    #[error("spending policy required for {kind}")]
166    SpendingPolicyRequired { kind: String },
167
168    #[error("unsupported version 0")]
169    Version0,
170
171    #[error("unsupported version 1 with csv")]
172    Version1Csv,
173
174    #[error("lock time conflict: requested {requested}, but required {required}")]
175    LockTime { requested: String, required: String },
176
177    #[error("rbf sequence: {sequence}, csv sequence: {csv}")]
178    RbfSequenceCsv { sequence: String, csv: String },
179
180    #[error("fee too low: required {required}")]
181    FeeTooLow { required: String },
182
183    #[error("fee rate too low: {required}")]
184    FeeRateTooLow { required: String },
185
186    #[error("no utxos selected for the transaction")]
187    NoUtxosSelected,
188
189    #[error("output value below dust limit at index {index}")]
190    OutputBelowDustLimit { index: u64 },
191
192    #[error("change policy descriptor error")]
193    ChangePolicyDescriptor,
194
195    #[error("coin selection failed: {error_message}")]
196    CoinSelection { error_message: String },
197
198    #[error("insufficient funds: needed {needed} sat, available {available} sat")]
199    InsufficientFunds { needed: u64, available: u64 },
200
201    #[error("transaction has no recipients")]
202    NoRecipients,
203
204    #[error("psbt creation error: {error_message}")]
205    Psbt { error_message: String },
206
207    #[error("missing key origin for: {key}")]
208    MissingKeyOrigin { key: String },
209
210    #[error("reference to an unknown utxo: {outpoint}")]
211    UnknownUtxo { outpoint: String },
212
213    #[error("missing non-witness utxo for outpoint: {outpoint}")]
214    MissingNonWitnessUtxo { outpoint: String },
215
216    #[error("miniscript psbt error: {error_message}")]
217    MiniscriptPsbt { error_message: String },
218
219    #[error("attempt to prepare too many bytes to be pushed into script")]
220    PushBytesError,
221
222    #[error("invalid lock time value")]
223    LockTimeConversionError,
224}
225
226#[derive(Debug, thiserror::Error, uniffi::Error)]
227pub enum CreateWithPersistError {
228    #[error("sqlite persistence error: {error_message}")]
229    Persist { error_message: String },
230
231    #[error("the wallet has already been created")]
232    DataAlreadyExists,
233
234    #[error("the loaded changeset cannot construct wallet: {error_message}")]
235    Descriptor { error_message: String },
236}
237
238#[derive(Debug, thiserror::Error, uniffi::Error)]
239pub enum DescriptorError {
240    #[error("invalid hd key path")]
241    InvalidHdKeyPath,
242
243    #[error("the provided descriptor doesn't match its checksum")]
244    InvalidDescriptorChecksum,
245
246    #[error("the descriptor contains hardened derivation steps on public extended keys")]
247    HardenedDerivationXpub,
248
249    #[error("the descriptor contains multipath keys, which are not supported yet")]
250    MultiPath,
251
252    #[error("key error: {error_message}")]
253    Key { error_message: String },
254
255    #[error("policy error: {error_message}")]
256    Policy { error_message: String },
257
258    #[error("invalid descriptor character: {char}")]
259    InvalidDescriptorCharacter { char: String },
260
261    #[error("bip32 error: {error_message}")]
262    Bip32 { error_message: String },
263
264    #[error("base58 error: {error_message}")]
265    Base58 { error_message: String },
266
267    #[error("key-related error: {error_message}")]
268    Pk { error_message: String },
269
270    #[error("miniscript error: {error_message}")]
271    Miniscript { error_message: String },
272
273    #[error("hex decoding error: {error_message}")]
274    Hex { error_message: String },
275
276    #[error("external and internal descriptors are the same")]
277    ExternalAndInternalAreTheSame,
278}
279
280#[derive(Debug, thiserror::Error, uniffi::Error)]
281pub enum DescriptorKeyError {
282    #[error("error parsing descriptor key: {error_message}")]
283    Parse { error_message: String },
284
285    #[error("error invalid key type")]
286    InvalidKeyType,
287
288    #[error("error bip 32 related: {error_message}")]
289    Bip32 { error_message: String },
290
291    #[error("you cannot change a wildcard from hardened to unhardened or the opposite")]
292    CannotChangeWildcardType,
293}
294
295#[derive(Debug, thiserror::Error, uniffi::Error)]
296pub enum ElectrumError {
297    #[error("{error_message}")]
298    IOError { error_message: String },
299
300    #[error("{error_message}")]
301    Json { error_message: String },
302
303    #[error("{error_message}")]
304    Hex { error_message: String },
305
306    #[error("electrum server error: {error_message}")]
307    Protocol { error_message: String },
308
309    #[error("{error_message}")]
310    Bitcoin { error_message: String },
311
312    #[error("already subscribed to the notifications of an address")]
313    AlreadySubscribed,
314
315    #[error("not subscribed to the notifications of an address")]
316    NotSubscribed,
317
318    #[error("error during the deserialization of a response from the server: {error_message}")]
319    InvalidResponse { error_message: String },
320
321    #[error("{error_message}")]
322    Message { error_message: String },
323
324    #[error("invalid domain name {domain} not matching SSL certificate")]
325    InvalidDNSNameError { domain: String },
326
327    #[error("missing domain while it was explicitly asked to validate it")]
328    MissingDomain,
329
330    #[error("made one or multiple attempts, all errored")]
331    AllAttemptsErrored,
332
333    #[error("{error_message}")]
334    SharedIOError { error_message: String },
335
336    #[error("couldn't take a lock on the reader mutex. This means that there's already another reader thread is running")]
337    CouldntLockReader,
338
339    #[error("broken IPC communication channel: the other thread probably has exited")]
340    Mpsc,
341
342    #[error("{error_message}")]
343    CouldNotCreateConnection { error_message: String },
344
345    #[error("the request has already been consumed")]
346    RequestAlreadyConsumed,
347}
348
349#[derive(Debug, thiserror::Error, uniffi::Error)]
350pub enum EsploraError {
351    #[error("minreq error: {error_message}")]
352    Minreq { error_message: String },
353
354    #[error("http error with status code {status} and message {error_message}")]
355    HttpResponse { status: u16, error_message: String },
356
357    #[error("parsing error: {error_message}")]
358    Parsing { error_message: String },
359
360    #[error("invalid status code, unable to convert to u16: {error_message}")]
361    StatusCode { error_message: String },
362
363    #[error("bitcoin encoding error: {error_message}")]
364    BitcoinEncoding { error_message: String },
365
366    #[error("invalid hex data returned: {error_message}")]
367    HexToArray { error_message: String },
368
369    #[error("invalid hex data returned: {error_message}")]
370    HexToBytes { error_message: String },
371
372    #[error("transaction not found")]
373    TransactionNotFound,
374
375    #[error("header height {height} not found")]
376    HeaderHeightNotFound { height: u32 },
377
378    #[error("header hash not found")]
379    HeaderHashNotFound,
380
381    #[error("invalid http header name: {name}")]
382    InvalidHttpHeaderName { name: String },
383
384    #[error("invalid http header value: {value}")]
385    InvalidHttpHeaderValue { value: String },
386
387    #[error("the request has already been consumed")]
388    RequestAlreadyConsumed,
389
390    #[error("the server sent an invalid response")]
391    InvalidResponse,
392}
393
394#[derive(Debug, thiserror::Error, uniffi::Error)]
395pub enum ExtractTxError {
396    #[error("an absurdly high fee rate of {fee_rate} sat/vbyte")]
397    AbsurdFeeRate { fee_rate: u64 },
398
399    #[error("one of the inputs lacked value information (witness_utxo or non_witness_utxo)")]
400    MissingInputValue,
401
402    #[error("transaction would be invalid due to output value being greater than input value")]
403    SendingTooMuch,
404
405    #[error(
406        "this error is required because the bdk::bitcoin::psbt::ExtractTxError is non-exhaustive"
407    )]
408    OtherExtractTxErr,
409}
410#[derive(Debug, thiserror::Error, uniffi::Error)]
411pub enum FeeRateError {
412    #[error("arithmetic overflow")]
413    ArithmeticOverflow,
414}
415
416#[derive(Debug, thiserror::Error, uniffi::Error)]
417pub enum FromScriptError {
418    #[error("script is not a p2pkh, p2sh or witness program")]
419    UnrecognizedScript,
420
421    #[error("witness program error: {error_message}")]
422    WitnessProgram { error_message: String },
423
424    #[error("witness version construction error: {error_message}")]
425    WitnessVersion { error_message: String },
426
427    // This error is required because the bdk::bitcoin::address::FromScriptError is non-exhaustive
428    #[error("other from script error")]
429    OtherFromScriptErr,
430}
431
432#[derive(Debug, thiserror::Error, uniffi::Error)]
433pub enum RequestBuilderError {
434    #[error("the request has already been consumed")]
435    RequestAlreadyConsumed,
436}
437
438#[derive(Debug, thiserror::Error, uniffi::Error)]
439pub enum LoadWithPersistError {
440    #[error("sqlite persistence error: {error_message}")]
441    Persist { error_message: String },
442
443    #[error("the loaded changeset cannot construct wallet: {error_message}")]
444    InvalidChangeSet { error_message: String },
445
446    #[error("could not load")]
447    CouldNotLoad,
448}
449
450#[derive(Debug, thiserror::Error, uniffi::Error)]
451pub enum MiniscriptError {
452    #[error("absolute locktime error")]
453    AbsoluteLockTime,
454
455    #[error("address error: {error_message}")]
456    AddrError { error_message: String },
457
458    #[error("p2sh address error: {error_message}")]
459    AddrP2shError { error_message: String },
460
461    #[error("analysis error: {error_message}")]
462    AnalysisError { error_message: String },
463
464    #[error("@ found outside of OR")]
465    AtOutsideOr,
466
467    #[error("bad descriptor: {error_message}")]
468    BadDescriptor { error_message: String },
469
470    #[error("bare descriptor address")]
471    BareDescriptorAddr,
472
473    #[error("too many keys in checkmultisig: {keys}")]
474    CmsTooManyKeys { keys: u32 },
475
476    #[error("context error: {error_message}")]
477    ContextError { error_message: String },
478
479    #[error("could not satisfy")]
480    CouldNotSatisfy,
481
482    #[error("expected character: {char}")]
483    ExpectedChar { char: String },
484
485    #[error("impossible satisfaction")]
486    ImpossibleSatisfaction,
487
488    #[error("invalid opcode")]
489    InvalidOpcode,
490
491    #[error("invalid push")]
492    InvalidPush,
493
494    #[error("lift error: {error_message}")]
495    LiftError { error_message: String },
496
497    #[error("maximum recursive depth exceeded")]
498    MaxRecursiveDepthExceeded,
499
500    #[error("missing signature")]
501    MissingSig,
502
503    #[error("too many keys in multi-a: {keys}")]
504    MultiATooManyKeys { keys: u64 },
505
506    #[error("multiple colons in fragment name")]
507    MultiColon,
508
509    #[error("multipath descriptor length mismatch")]
510    MultipathDescLenMismatch,
511
512    #[error("non-minimal verify: {error_message}")]
513    NonMinimalVerify { error_message: String },
514
515    #[error("non-standard bare script")]
516    NonStandardBareScript,
517
518    #[error("non top-level: {error_message}")]
519    NonTopLevel { error_message: String },
520
521    #[error("parse threshold error")]
522    ParseThreshold,
523
524    #[error("policy error: {error_message}")]
525    PolicyError { error_message: String },
526
527    #[error("pubkey context error")]
528    PubKeyCtxError,
529
530    #[error("relative locktime error")]
531    RelativeLockTime,
532
533    #[error("script error: {error_message}")]
534    Script { error_message: String },
535
536    #[error("secp256k1 error: {error_message}")]
537    Secp { error_message: String },
538
539    #[error("threshold error")]
540    Threshold,
541
542    #[error("no script code for taproot")]
543    TrNoScriptCode,
544
545    #[error("trailing data: {error_message}")]
546    Trailing { error_message: String },
547
548    #[error("type check error: {error_message}")]
549    TypeCheck { error_message: String },
550
551    #[error("unexpected: {error_message}")]
552    Unexpected { error_message: String },
553
554    #[error("unexpected start")]
555    UnexpectedStart,
556
557    #[error("unknown wrapper: {char}")]
558    UnknownWrapper { char: String },
559
560    #[error("unprintable character: {byte}")]
561    Unprintable { byte: u8 },
562}
563
564#[derive(Debug, thiserror::Error, uniffi::Error)]
565pub enum ParseAmountError {
566    #[error("amount out of range")]
567    OutOfRange,
568
569    #[error("amount has a too high precision")]
570    TooPrecise,
571
572    #[error("the input has too few digits")]
573    MissingDigits,
574
575    #[error("the input is too large")]
576    InputTooLarge,
577
578    #[error("invalid character: {error_message}")]
579    InvalidCharacter { error_message: String },
580
581    // Has to handle non-exhaustive
582    #[error("unknown parse amount error")]
583    OtherParseAmountErr,
584}
585
586#[derive(Debug, thiserror::Error, uniffi::Error)]
587pub enum PersistenceError {
588    #[error("persistence error: {error_message}")]
589    Reason { error_message: String },
590}
591
592#[derive(Debug, thiserror::Error, uniffi::Error)]
593pub enum PreV1MigrationError {
594    #[error("migration helper is only available for sqlite-backed persisters")]
595    SqliteOnly,
596
597    #[error("sqlite migration error: {error_message}")]
598    Sqlite { error_message: String },
599
600    #[error("invalid keychain: {keychain}")]
601    InvalidKeychain { keychain: String },
602
603    #[error("invalid checksum: {error_message}")]
604    InvalidChecksum { error_message: String },
605}
606
607#[derive(Debug, thiserror::Error, uniffi::Error)]
608pub enum PsbtError {
609    #[error("invalid magic")]
610    InvalidMagic,
611
612    #[error("UTXO information is not present in PSBT")]
613    MissingUtxo,
614
615    #[error("invalid separator")]
616    InvalidSeparator,
617
618    #[error("output index is out of bounds of non witness script output array")]
619    PsbtUtxoOutOfBounds,
620
621    #[error("invalid key: {key}")]
622    InvalidKey { key: String },
623
624    #[error("non-proprietary key type found when proprietary key was expected")]
625    InvalidProprietaryKey,
626
627    #[error("duplicate key: {key}")]
628    DuplicateKey { key: String },
629
630    #[error("the unsigned transaction has script sigs")]
631    UnsignedTxHasScriptSigs,
632
633    #[error("the unsigned transaction has script witnesses")]
634    UnsignedTxHasScriptWitnesses,
635
636    #[error("partially signed transactions must have an unsigned transaction")]
637    MustHaveUnsignedTx,
638
639    #[error("no more key-value pairs for this psbt map")]
640    NoMorePairs,
641
642    // Note: this error would be nice to unpack and provide the two transactions
643    #[error("different unsigned transaction")]
644    UnexpectedUnsignedTx,
645
646    #[error("non-standard sighash type: {sighash}")]
647    NonStandardSighashType { sighash: u32 },
648
649    #[error("invalid hash when parsing slice: {hash}")]
650    InvalidHash { hash: String },
651
652    // Note: to provide the data returned in Rust, we need to dereference the fields
653    #[error("preimage does not match")]
654    InvalidPreimageHashPair,
655
656    #[error("combine conflict: {xpub}")]
657    CombineInconsistentKeySources { xpub: String },
658
659    #[error("bitcoin consensus encoding error: {encoding_error}")]
660    ConsensusEncoding { encoding_error: String },
661
662    #[error("PSBT has a negative fee which is not allowed")]
663    NegativeFee,
664
665    #[error("integer overflow in fee calculation")]
666    FeeOverflow,
667
668    #[error("invalid public key {error_message}")]
669    InvalidPublicKey { error_message: String },
670
671    #[error("invalid secp256k1 public key: {secp256k1_error}")]
672    InvalidSecp256k1PublicKey { secp256k1_error: String },
673
674    #[error("invalid xonly public key")]
675    InvalidXOnlyPublicKey,
676
677    #[error("invalid ECDSA signature: {error_message}")]
678    InvalidEcdsaSignature { error_message: String },
679
680    #[error("invalid taproot signature: {error_message}")]
681    InvalidTaprootSignature { error_message: String },
682
683    #[error("invalid control block")]
684    InvalidControlBlock,
685
686    #[error("invalid leaf version")]
687    InvalidLeafVersion,
688
689    #[error("taproot error")]
690    Taproot,
691
692    #[error("taproot tree error: {error_message}")]
693    TapTree { error_message: String },
694
695    #[error("xpub key error")]
696    XPubKey,
697
698    #[error("version error: {error_message}")]
699    Version { error_message: String },
700
701    #[error("data not consumed entirely when explicitly deserializing")]
702    PartialDataConsumption,
703
704    #[error("I/O error: {error_message}")]
705    Io { error_message: String },
706
707    #[error("other PSBT error")]
708    OtherPsbtErr,
709}
710
711#[derive(Debug, thiserror::Error, uniffi::Error)]
712pub enum PsbtParseError {
713    #[error("error in internal psbt data structure: {error_message}")]
714    PsbtEncoding { error_message: String },
715
716    #[error("error in psbt base64 encoding: {error_message}")]
717    Base64Encoding { error_message: String },
718}
719
720#[derive(Debug, thiserror::Error, uniffi::Error)]
721pub enum SighashParseError {
722    #[error("invalid sighash type: {error_message}")]
723    Invalid { error_message: String },
724}
725
726#[derive(Debug, thiserror::Error, uniffi::Error)]
727pub enum PsbtFinalizeError {
728    #[error("an input at index {index} is invalid: {reason}")]
729    InputError { reason: String, index: u32 },
730    #[error("wrong input count; expected: {in_tx}, got: {in_map}")]
731    WrongInputCount { in_tx: u32, in_map: u32 },
732    #[error("input index out of bounds; inputs: {psbt_inp}, requested: {requested}")]
733    InputIdxOutofBounds { psbt_inp: u32, requested: u32 },
734}
735
736#[derive(Debug, thiserror::Error, uniffi::Error)]
737pub enum SignerError {
738    #[error("missing key for signing")]
739    MissingKey,
740
741    #[error("invalid key provided")]
742    InvalidKey,
743
744    #[error("user canceled operation")]
745    UserCanceled,
746
747    #[error("input index out of range")]
748    InputIndexOutOfRange,
749
750    #[error("missing non-witness utxo information")]
751    MissingNonWitnessUtxo,
752
753    #[error("invalid non-witness utxo information provided")]
754    InvalidNonWitnessUtxo,
755
756    #[error("missing witness utxo")]
757    MissingWitnessUtxo,
758
759    #[error("missing witness script")]
760    MissingWitnessScript,
761
762    #[error("missing hd keypath")]
763    MissingHdKeypath,
764
765    #[error("non-standard sighash type used")]
766    NonStandardSighash,
767
768    #[error("invalid sighash type provided")]
769    InvalidSighash,
770
771    #[error("error while computing the hash to sign a P2WPKH input: {error_message}")]
772    SighashP2wpkh { error_message: String },
773
774    #[error("error while computing the hash to sign a taproot input: {error_message}")]
775    SighashTaproot { error_message: String },
776
777    #[error("Error while computing the hash, out of bounds access on the transaction inputs: {error_message}")]
778    TxInputsIndexError { error_message: String },
779
780    #[error("miniscript psbt error: {error_message}")]
781    MiniscriptPsbt { error_message: String },
782
783    #[error("external error: {error_message}")]
784    External { error_message: String },
785
786    #[error("Psbt error: {error_message}")]
787    Psbt { error_message: String },
788}
789
790#[derive(Debug, thiserror::Error, uniffi::Error)]
791pub enum TransactionError {
792    #[error("io error")]
793    Io,
794
795    #[error("allocation of oversized vector")]
796    OversizedVectorAllocation,
797
798    #[error("invalid checksum: expected={expected} actual={actual}")]
799    InvalidChecksum { expected: String, actual: String },
800
801    #[error("non-minimal var int")]
802    NonMinimalVarInt,
803
804    #[error("parse failed")]
805    ParseFailed,
806
807    #[error("unsupported segwit version: {flag}")]
808    UnsupportedSegwitFlag { flag: u8 },
809
810    // This is required because the bdk::bitcoin::consensus::encode::Error is non-exhaustive
811    #[error("other transaction error")]
812    OtherTransactionErr,
813}
814
815#[derive(Debug, thiserror::Error, uniffi::Error)]
816pub enum TxidParseError {
817    #[error("invalid txid: {txid}")]
818    InvalidTxid { txid: String },
819}
820
821#[derive(Debug, thiserror::Error, uniffi::Error)]
822pub enum CbfError {
823    #[error("the node is no longer running")]
824    NodeStopped,
825}
826
827// ------------------------------------------------------------------------
828// error conversions
829// ------------------------------------------------------------------------
830
831impl From<AddForeignUtxoError> for CreateTxError {
832    fn from(error: AddForeignUtxoError) -> Self {
833        match error {
834            AddForeignUtxoError::InvalidTxid => CreateTxError::Descriptor {
835                error_message: "foreign utxo outpoint txid does not match PSBT input txid"
836                    .to_string(),
837            },
838            AddForeignUtxoError::InvalidOutpoint { outpoint } => {
839                CreateTxError::UnknownUtxo { outpoint }
840            }
841            AddForeignUtxoError::MissingUtxo => CreateTxError::Descriptor {
842                error_message: "foreign utxo missing witness_utxo or non_witness_utxo".to_string(),
843            },
844            AddForeignUtxoError::InputConversionError { error_message } => {
845                CreateTxError::Descriptor { error_message }
846            }
847        }
848    }
849}
850
851impl From<BdkAddForeignUtxoError> for AddForeignUtxoError {
852    fn from(error: BdkAddForeignUtxoError) -> Self {
853        match error {
854            BdkAddForeignUtxoError::InvalidTxid { .. } => AddForeignUtxoError::InvalidTxid,
855            BdkAddForeignUtxoError::InvalidOutpoint(outpoint) => {
856                AddForeignUtxoError::InvalidOutpoint {
857                    outpoint: outpoint.to_string(),
858                }
859            }
860            BdkAddForeignUtxoError::MissingUtxo => AddForeignUtxoError::MissingUtxo,
861        }
862    }
863}
864
865impl From<BdkElectrumError> for ElectrumError {
866    fn from(error: BdkElectrumError) -> Self {
867        match error {
868            BdkElectrumError::IOError(e) => ElectrumError::IOError {
869                error_message: e.to_string(),
870            },
871            BdkElectrumError::JSON(e) => ElectrumError::Json {
872                error_message: e.to_string(),
873            },
874            BdkElectrumError::Hex(e) => ElectrumError::Hex {
875                error_message: e.to_string(),
876            },
877            BdkElectrumError::Protocol(e) => ElectrumError::Protocol {
878                error_message: e.to_string(),
879            },
880            BdkElectrumError::Bitcoin(e) => ElectrumError::Bitcoin {
881                error_message: e.to_string(),
882            },
883            BdkElectrumError::AlreadySubscribed(_) => ElectrumError::AlreadySubscribed,
884            BdkElectrumError::NotSubscribed(_) => ElectrumError::NotSubscribed,
885            BdkElectrumError::InvalidResponse(e) => ElectrumError::InvalidResponse {
886                error_message: e.to_string(),
887            },
888            BdkElectrumError::Message(e) => ElectrumError::Message {
889                error_message: e.to_string(),
890            },
891            BdkElectrumError::InvalidDNSNameError(domain) => {
892                ElectrumError::InvalidDNSNameError { domain }
893            }
894            BdkElectrumError::MissingDomain => ElectrumError::MissingDomain,
895            BdkElectrumError::AllAttemptsErrored(_) => ElectrumError::AllAttemptsErrored,
896            BdkElectrumError::SharedIOError(e) => ElectrumError::SharedIOError {
897                error_message: e.to_string(),
898            },
899            BdkElectrumError::CouldntLockReader => ElectrumError::CouldntLockReader,
900            BdkElectrumError::Mpsc => ElectrumError::Mpsc,
901            BdkElectrumError::CouldNotCreateConnection(error_message) => {
902                ElectrumError::CouldNotCreateConnection {
903                    error_message: error_message.to_string(),
904                }
905            }
906        }
907    }
908}
909
910impl From<BdkParseError> for AddressParseError {
911    fn from(error: BdkParseError) -> Self {
912        match error {
913            BdkParseError::Base58(_) => AddressParseError::Base58,
914            BdkParseError::Bech32(_) => AddressParseError::Bech32,
915            BdkParseError::WitnessVersion(e) => AddressParseError::WitnessVersion {
916                error_message: e.to_string(),
917            },
918            BdkParseError::WitnessProgram(e) => AddressParseError::WitnessProgram {
919                error_message: e.to_string(),
920            },
921            ParseError::UnknownHrp(_) => AddressParseError::UnknownHrp,
922            ParseError::LegacyAddressTooLong(_) => AddressParseError::LegacyAddressTooLong,
923            ParseError::InvalidBase58PayloadLength(_) => {
924                AddressParseError::InvalidBase58PayloadLength
925            }
926            ParseError::InvalidLegacyPrefix(_) => AddressParseError::InvalidLegacyPrefix,
927            ParseError::NetworkValidation(_) => AddressParseError::NetworkValidation,
928            _ => AddressParseError::OtherAddressParseErr,
929        }
930    }
931}
932
933impl From<BdkBip32Error> for Bip32Error {
934    fn from(error: BdkBip32Error) -> Self {
935        match error {
936            BdkBip32Error::CannotDeriveFromHardenedKey => Bip32Error::CannotDeriveFromHardenedKey,
937            BdkBip32Error::Secp256k1(e) => Bip32Error::Secp256k1 {
938                error_message: e.to_string(),
939            },
940            BdkBip32Error::InvalidChildNumber(num) => {
941                Bip32Error::InvalidChildNumber { child_number: num }
942            }
943            BdkBip32Error::InvalidChildNumberFormat => Bip32Error::InvalidChildNumberFormat,
944            BdkBip32Error::InvalidDerivationPathFormat => Bip32Error::InvalidDerivationPathFormat,
945            BdkBip32Error::UnknownVersion(bytes) => Bip32Error::UnknownVersion {
946                version: bytes.to_lower_hex_string(),
947            },
948            BdkBip32Error::WrongExtendedKeyLength(len) => {
949                Bip32Error::WrongExtendedKeyLength { length: len as u32 }
950            }
951            BdkBip32Error::Base58(e) => Bip32Error::Base58 {
952                error_message: e.to_string(),
953            },
954            BdkBip32Error::Hex(e) => Bip32Error::Hex {
955                error_message: e.to_string(),
956            },
957            BdkBip32Error::InvalidPublicKeyHexLength(len) => {
958                Bip32Error::InvalidPublicKeyHexLength { length: len as u32 }
959            }
960            _ => Bip32Error::UnknownError {
961                error_message: format!("Unhandled error: {error:?}"),
962            },
963        }
964    }
965}
966
967impl From<BdkBip39Error> for Bip39Error {
968    fn from(error: BdkBip39Error) -> Self {
969        match error {
970            BdkBip39Error::BadWordCount(word_count) => Bip39Error::BadWordCount {
971                word_count: word_count.try_into().expect("word count exceeds u64"),
972            },
973            BdkBip39Error::UnknownWord(index) => Bip39Error::UnknownWord {
974                index: index.try_into().expect("index exceeds u64"),
975            },
976            BdkBip39Error::BadEntropyBitCount(bit_count) => Bip39Error::BadEntropyBitCount {
977                bit_count: bit_count.try_into().expect("bit count exceeds u64"),
978            },
979            BdkBip39Error::InvalidChecksum => Bip39Error::InvalidChecksum,
980            BdkBip39Error::AmbiguousLanguages(info) => Bip39Error::AmbiguousLanguages {
981                languages: format!("{info:?}"),
982            },
983        }
984    }
985}
986
987impl From<BdkCalculateFeeError> for CalculateFeeError {
988    fn from(error: BdkCalculateFeeError) -> Self {
989        match error {
990            BdkCalculateFeeError::MissingTxOut(out_points) => {
991                let out_points = out_points.iter().map(OutPoint::from).collect();
992                CalculateFeeError::MissingTxOut { out_points }
993            }
994            BdkCalculateFeeError::NegativeFee(signed_amount) => CalculateFeeError::NegativeFee {
995                amount: signed_amount.to_string(),
996            },
997        }
998    }
999}
1000
1001impl From<BdkCannotConnectError> for CannotConnectError {
1002    fn from(error: BdkCannotConnectError) -> Self {
1003        CannotConnectError::Include {
1004            height: error.try_include_height,
1005        }
1006    }
1007}
1008
1009impl From<BdkCreateTxError> for CreateTxError {
1010    fn from(error: BdkCreateTxError) -> Self {
1011        match error {
1012            BdkCreateTxError::Descriptor(e) => CreateTxError::Descriptor {
1013                error_message: e.to_string(),
1014            },
1015            BdkCreateTxError::Policy(e) => CreateTxError::Policy {
1016                error_message: e.to_string(),
1017            },
1018            BdkCreateTxError::SpendingPolicyRequired(kind) => {
1019                CreateTxError::SpendingPolicyRequired {
1020                    kind: format!("{kind:?}"),
1021                }
1022            }
1023            BdkCreateTxError::Version0 => CreateTxError::Version0,
1024            BdkCreateTxError::Version1Csv => CreateTxError::Version1Csv,
1025            BdkCreateTxError::LockTime {
1026                requested,
1027                required,
1028            } => CreateTxError::LockTime {
1029                requested: requested.to_string(),
1030                required: required.to_string(),
1031            },
1032            BdkCreateTxError::RbfSequenceCsv { sequence, csv } => CreateTxError::RbfSequenceCsv {
1033                sequence: sequence.to_string(),
1034                csv: csv.to_string(),
1035            },
1036            BdkCreateTxError::FeeTooLow { required } => CreateTxError::FeeTooLow {
1037                required: required.to_string(),
1038            },
1039            BdkCreateTxError::FeeRateTooLow { required } => CreateTxError::FeeRateTooLow {
1040                required: required.to_string(),
1041            },
1042            BdkCreateTxError::NoUtxosSelected => CreateTxError::NoUtxosSelected,
1043            BdkCreateTxError::OutputBelowDustLimit(index) => CreateTxError::OutputBelowDustLimit {
1044                index: index as u64,
1045            },
1046            BdkCreateTxError::CoinSelection(e) => CreateTxError::CoinSelection {
1047                error_message: e.to_string(),
1048            },
1049            BdkCreateTxError::NoRecipients => CreateTxError::NoRecipients,
1050            BdkCreateTxError::Psbt(e) => CreateTxError::Psbt {
1051                error_message: e.to_string(),
1052            },
1053            BdkCreateTxError::MissingKeyOrigin(key) => CreateTxError::MissingKeyOrigin { key },
1054            BdkCreateTxError::UnknownUtxo => CreateTxError::UnknownUtxo {
1055                outpoint: "Unknown".to_string(),
1056            },
1057            BdkCreateTxError::MissingNonWitnessUtxo(outpoint) => {
1058                CreateTxError::MissingNonWitnessUtxo {
1059                    outpoint: outpoint.to_string(),
1060                }
1061            }
1062            BdkCreateTxError::MiniscriptPsbt(e) => CreateTxError::MiniscriptPsbt {
1063                error_message: e.to_string(),
1064            },
1065        }
1066    }
1067}
1068
1069impl From<PushBytesError> for CreateTxError {
1070    fn from(_: PushBytesError) -> Self {
1071        CreateTxError::PushBytesError
1072    }
1073}
1074
1075impl From<BdkCreateWithPersistError<chain::rusqlite::Error>> for CreateWithPersistError {
1076    fn from(error: BdkCreateWithPersistError<chain::rusqlite::Error>) -> Self {
1077        match error {
1078            BdkCreateWithPersistError::Persist(e) => CreateWithPersistError::Persist {
1079                error_message: e.to_string(),
1080            },
1081            BdkCreateWithPersistError::Descriptor(e) => CreateWithPersistError::Descriptor {
1082                error_message: e.to_string(),
1083            },
1084            // Objects cannot currently be used in enumerations
1085            BdkCreateWithPersistError::DataAlreadyExists(_e) => {
1086                CreateWithPersistError::DataAlreadyExists
1087            }
1088        }
1089    }
1090}
1091
1092impl From<BdkCreateWithPersistError<PersistenceError>> for CreateWithPersistError {
1093    fn from(error: BdkCreateWithPersistError<PersistenceError>) -> Self {
1094        match error {
1095            BdkCreateWithPersistError::Persist(e) => CreateWithPersistError::Persist {
1096                error_message: e.to_string(),
1097            },
1098            BdkCreateWithPersistError::Descriptor(e) => CreateWithPersistError::Descriptor {
1099                error_message: e.to_string(),
1100            },
1101            // Objects cannot currently be used in enumerations
1102            BdkCreateWithPersistError::DataAlreadyExists(_e) => {
1103                CreateWithPersistError::DataAlreadyExists
1104            }
1105        }
1106    }
1107}
1108
1109impl From<AddUtxoError> for CreateTxError {
1110    fn from(error: AddUtxoError) -> Self {
1111        match error {
1112            AddUtxoError::UnknownUtxo(outpoint) => CreateTxError::UnknownUtxo {
1113                outpoint: outpoint.to_string(),
1114            },
1115        }
1116    }
1117}
1118
1119impl From<BuildFeeBumpError> for CreateTxError {
1120    fn from(error: BuildFeeBumpError) -> Self {
1121        match error {
1122            BuildFeeBumpError::UnknownUtxo(outpoint) => CreateTxError::UnknownUtxo {
1123                outpoint: outpoint.to_string(),
1124            },
1125            BuildFeeBumpError::TransactionNotFound(txid) => CreateTxError::UnknownUtxo {
1126                outpoint: txid.to_string(),
1127            },
1128            BuildFeeBumpError::TransactionConfirmed(txid) => CreateTxError::UnknownUtxo {
1129                outpoint: txid.to_string(),
1130            },
1131            BuildFeeBumpError::IrreplaceableTransaction(txid) => CreateTxError::UnknownUtxo {
1132                outpoint: txid.to_string(),
1133            },
1134            BuildFeeBumpError::FeeRateUnavailable => CreateTxError::FeeRateTooLow {
1135                required: "unavailable".to_string(),
1136            },
1137            BuildFeeBumpError::InvalidOutputIndex(outpoint) => CreateTxError::UnknownUtxo {
1138                outpoint: outpoint.to_string(),
1139            },
1140        }
1141    }
1142}
1143
1144impl From<BdkDescriptorError> for DescriptorError {
1145    fn from(error: BdkDescriptorError) -> Self {
1146        match error {
1147            BdkDescriptorError::InvalidHdKeyPath => DescriptorError::InvalidHdKeyPath,
1148            BdkDescriptorError::InvalidDescriptorChecksum => {
1149                DescriptorError::InvalidDescriptorChecksum
1150            }
1151            BdkDescriptorError::HardenedDerivationXpub => DescriptorError::HardenedDerivationXpub,
1152            BdkDescriptorError::MultiPath => DescriptorError::MultiPath,
1153            BdkDescriptorError::Key(e) => DescriptorError::Key {
1154                error_message: e.to_string(),
1155            },
1156            BdkDescriptorError::Policy(e) => DescriptorError::Policy {
1157                error_message: e.to_string(),
1158            },
1159            BdkDescriptorError::InvalidDescriptorCharacter(char) => {
1160                DescriptorError::InvalidDescriptorCharacter {
1161                    char: char.to_string(),
1162                }
1163            }
1164            BdkDescriptorError::Bip32(e) => DescriptorError::Bip32 {
1165                error_message: e.to_string(),
1166            },
1167            BdkDescriptorError::Base58(e) => DescriptorError::Base58 {
1168                error_message: e.to_string(),
1169            },
1170            BdkDescriptorError::Pk(e) => DescriptorError::Pk {
1171                error_message: e.to_string(),
1172            },
1173            BdkDescriptorError::Miniscript(e) => DescriptorError::Miniscript {
1174                error_message: e.to_string(),
1175            },
1176            BdkDescriptorError::Hex(e) => DescriptorError::Hex {
1177                error_message: e.to_string(),
1178            },
1179            BdkDescriptorError::ExternalAndInternalAreTheSame => {
1180                DescriptorError::ExternalAndInternalAreTheSame
1181            }
1182        }
1183    }
1184}
1185
1186impl From<BdkDescriptorKeyParseError> for DescriptorKeyError {
1187    fn from(err: BdkDescriptorKeyParseError) -> DescriptorKeyError {
1188        DescriptorKeyError::Parse {
1189            error_message: format!("DescriptorKeyError error: {err:?}"),
1190        }
1191    }
1192}
1193
1194impl From<BdkBip32Error> for DescriptorKeyError {
1195    fn from(error: BdkBip32Error) -> DescriptorKeyError {
1196        DescriptorKeyError::Bip32 {
1197            error_message: format!("BIP32 derivation error: {error:?}"),
1198        }
1199    }
1200}
1201
1202impl From<BdkEsploraError> for EsploraError {
1203    fn from(error: BdkEsploraError) -> Self {
1204        match error {
1205            BdkEsploraError::Minreq(e) => EsploraError::Minreq {
1206                error_message: e.to_string(),
1207            },
1208            BdkEsploraError::HttpResponse { status, message } => EsploraError::HttpResponse {
1209                status,
1210                error_message: message,
1211            },
1212            BdkEsploraError::Parsing(e) => EsploraError::Parsing {
1213                error_message: e.to_string(),
1214            },
1215            BdkEsploraError::StatusCode(e) => EsploraError::StatusCode {
1216                error_message: e.to_string(),
1217            },
1218            BdkEsploraError::BitcoinEncoding(e) => EsploraError::BitcoinEncoding {
1219                error_message: e.to_string(),
1220            },
1221            BdkEsploraError::HexToArray(e) => EsploraError::HexToArray {
1222                error_message: e.to_string(),
1223            },
1224            BdkEsploraError::HexToBytes(e) => EsploraError::HexToBytes {
1225                error_message: e.to_string(),
1226            },
1227            BdkEsploraError::TransactionNotFound(_) => EsploraError::TransactionNotFound,
1228            BdkEsploraError::HeaderHeightNotFound(height) => {
1229                EsploraError::HeaderHeightNotFound { height }
1230            }
1231            BdkEsploraError::HeaderHashNotFound(_) => EsploraError::HeaderHashNotFound,
1232            BdkEsploraError::InvalidHttpHeaderName(name) => {
1233                EsploraError::InvalidHttpHeaderName { name }
1234            }
1235            BdkEsploraError::InvalidHttpHeaderValue(value) => {
1236                EsploraError::InvalidHttpHeaderValue { value }
1237            }
1238            BdkEsploraError::InvalidResponse => EsploraError::InvalidResponse,
1239        }
1240    }
1241}
1242
1243impl From<Box<BdkEsploraError>> for EsploraError {
1244    fn from(error: Box<BdkEsploraError>) -> Self {
1245        match *error {
1246            BdkEsploraError::Minreq(e) => EsploraError::Minreq {
1247                error_message: e.to_string(),
1248            },
1249            BdkEsploraError::HttpResponse { status, message } => EsploraError::HttpResponse {
1250                status,
1251                error_message: message,
1252            },
1253            BdkEsploraError::Parsing(e) => EsploraError::Parsing {
1254                error_message: e.to_string(),
1255            },
1256            BdkEsploraError::StatusCode(e) => EsploraError::StatusCode {
1257                error_message: e.to_string(),
1258            },
1259            BdkEsploraError::BitcoinEncoding(e) => EsploraError::BitcoinEncoding {
1260                error_message: e.to_string(),
1261            },
1262            BdkEsploraError::HexToArray(e) => EsploraError::HexToArray {
1263                error_message: e.to_string(),
1264            },
1265            BdkEsploraError::HexToBytes(e) => EsploraError::HexToBytes {
1266                error_message: e.to_string(),
1267            },
1268            BdkEsploraError::TransactionNotFound(_) => EsploraError::TransactionNotFound,
1269            BdkEsploraError::HeaderHeightNotFound(height) => {
1270                EsploraError::HeaderHeightNotFound { height }
1271            }
1272            BdkEsploraError::HeaderHashNotFound(_) => EsploraError::HeaderHashNotFound,
1273            BdkEsploraError::InvalidHttpHeaderName(name) => {
1274                EsploraError::InvalidHttpHeaderName { name }
1275            }
1276            BdkEsploraError::InvalidHttpHeaderValue(value) => {
1277                EsploraError::InvalidHttpHeaderValue { value }
1278            }
1279            BdkEsploraError::InvalidResponse => EsploraError::InvalidResponse,
1280        }
1281    }
1282}
1283
1284impl From<BdkHexToArrayError> for EsploraError {
1285    fn from(error: BdkHexToArrayError) -> Self {
1286        EsploraError::Parsing {
1287            error_message: error.to_string(),
1288        }
1289    }
1290}
1291
1292impl From<BdkExtractTxError> for ExtractTxError {
1293    fn from(error: BdkExtractTxError) -> Self {
1294        match error {
1295            BdkExtractTxError::AbsurdFeeRate { fee_rate, .. } => {
1296                let sat_per_vbyte = fee_rate.to_sat_per_vb_ceil();
1297                ExtractTxError::AbsurdFeeRate {
1298                    fee_rate: sat_per_vbyte,
1299                }
1300            }
1301            BdkExtractTxError::MissingInputValue { .. } => ExtractTxError::MissingInputValue,
1302            BdkExtractTxError::SendingTooMuch { .. } => ExtractTxError::SendingTooMuch,
1303            _ => ExtractTxError::OtherExtractTxErr,
1304        }
1305    }
1306}
1307
1308impl From<BdkFromScriptError> for FromScriptError {
1309    fn from(error: BdkFromScriptError) -> Self {
1310        match error {
1311            BdkFromScriptError::UnrecognizedScript => FromScriptError::UnrecognizedScript,
1312            BdkFromScriptError::WitnessProgram(e) => FromScriptError::WitnessProgram {
1313                error_message: e.to_string(),
1314            },
1315            BdkFromScriptError::WitnessVersion(e) => FromScriptError::WitnessVersion {
1316                error_message: e.to_string(),
1317            },
1318            _ => FromScriptError::OtherFromScriptErr,
1319        }
1320    }
1321}
1322
1323impl From<BdkLoadWithPersistError<chain::rusqlite::Error>> for LoadWithPersistError {
1324    fn from(error: BdkLoadWithPersistError<chain::rusqlite::Error>) -> Self {
1325        match error {
1326            BdkLoadWithPersistError::Persist(e) => LoadWithPersistError::Persist {
1327                error_message: e.to_string(),
1328            },
1329            BdkLoadWithPersistError::InvalidChangeSet(e) => {
1330                LoadWithPersistError::InvalidChangeSet {
1331                    error_message: e.to_string(),
1332                }
1333            }
1334        }
1335    }
1336}
1337
1338impl From<BdkLoadWithPersistError<PersistenceError>> for LoadWithPersistError {
1339    fn from(error: BdkLoadWithPersistError<PersistenceError>) -> Self {
1340        match error {
1341            BdkLoadWithPersistError::Persist(e) => LoadWithPersistError::Persist {
1342                error_message: e.to_string(),
1343            },
1344            BdkLoadWithPersistError::InvalidChangeSet(e) => {
1345                LoadWithPersistError::InvalidChangeSet {
1346                    error_message: e.to_string(),
1347                }
1348            }
1349        }
1350    }
1351}
1352
1353impl From<BdkSqliteError> for PersistenceError {
1354    fn from(error: BdkSqliteError) -> Self {
1355        PersistenceError::Reason {
1356            error_message: error.to_string(),
1357        }
1358    }
1359}
1360
1361impl From<BdkPreV1MigrationError> for PreV1MigrationError {
1362    fn from(error: BdkPreV1MigrationError) -> Self {
1363        match error {
1364            BdkPreV1MigrationError::RusqliteError(error) => PreV1MigrationError::Sqlite {
1365                error_message: error.to_string(),
1366            },
1367            BdkPreV1MigrationError::InvalidKeychain(keychain) => {
1368                PreV1MigrationError::InvalidKeychain { keychain }
1369            }
1370            BdkPreV1MigrationError::InvalidChecksum(error) => {
1371                PreV1MigrationError::InvalidChecksum {
1372                    error_message: error.to_string(),
1373                }
1374            }
1375        }
1376    }
1377}
1378
1379impl From<bdk_wallet::miniscript::Error> for MiniscriptError {
1380    fn from(error: bdk_wallet::miniscript::Error) -> Self {
1381        use bdk_wallet::miniscript::Error as BdkMiniscriptError;
1382        match error {
1383            BdkMiniscriptError::AbsoluteLockTime(_) => MiniscriptError::AbsoluteLockTime,
1384            BdkMiniscriptError::AddrError(e) => MiniscriptError::AddrError {
1385                error_message: e.to_string(),
1386            },
1387            BdkMiniscriptError::AddrP2shError(e) => MiniscriptError::AddrP2shError {
1388                error_message: e.to_string(),
1389            },
1390            BdkMiniscriptError::AnalysisError(e) => MiniscriptError::AnalysisError {
1391                error_message: e.to_string(),
1392            },
1393            BdkMiniscriptError::AtOutsideOr(_) => MiniscriptError::AtOutsideOr,
1394            BdkMiniscriptError::BadDescriptor(s) => {
1395                MiniscriptError::BadDescriptor { error_message: s }
1396            }
1397            BdkMiniscriptError::BareDescriptorAddr => MiniscriptError::BareDescriptorAddr,
1398            BdkMiniscriptError::CmsTooManyKeys(n) => MiniscriptError::CmsTooManyKeys { keys: n },
1399            BdkMiniscriptError::ContextError(e) => MiniscriptError::ContextError {
1400                error_message: e.to_string(),
1401            },
1402            BdkMiniscriptError::CouldNotSatisfy => MiniscriptError::CouldNotSatisfy,
1403            BdkMiniscriptError::ExpectedChar(c) => MiniscriptError::ExpectedChar {
1404                char: c.to_string(),
1405            },
1406            BdkMiniscriptError::ImpossibleSatisfaction => MiniscriptError::ImpossibleSatisfaction,
1407            BdkMiniscriptError::InvalidOpcode(_) => MiniscriptError::InvalidOpcode,
1408            BdkMiniscriptError::InvalidPush(_) => MiniscriptError::InvalidPush,
1409            BdkMiniscriptError::LiftError(e) => MiniscriptError::LiftError {
1410                error_message: e.to_string(),
1411            },
1412            BdkMiniscriptError::MaxRecursiveDepthExceeded => {
1413                MiniscriptError::MaxRecursiveDepthExceeded
1414            }
1415            BdkMiniscriptError::MissingSig(_) => MiniscriptError::MissingSig,
1416            BdkMiniscriptError::MultiATooManyKeys(n) => {
1417                MiniscriptError::MultiATooManyKeys { keys: n }
1418            }
1419            BdkMiniscriptError::MultiColon(_) => MiniscriptError::MultiColon,
1420            BdkMiniscriptError::MultipathDescLenMismatch => {
1421                MiniscriptError::MultipathDescLenMismatch
1422            }
1423            BdkMiniscriptError::NonMinimalVerify(s) => {
1424                MiniscriptError::NonMinimalVerify { error_message: s }
1425            }
1426            BdkMiniscriptError::NonStandardBareScript => MiniscriptError::NonStandardBareScript,
1427            BdkMiniscriptError::NonTopLevel(s) => MiniscriptError::NonTopLevel { error_message: s },
1428            BdkMiniscriptError::ParseThreshold(_) => MiniscriptError::ParseThreshold,
1429            BdkMiniscriptError::PolicyError(e) => MiniscriptError::PolicyError {
1430                error_message: e.to_string(),
1431            },
1432            BdkMiniscriptError::PubKeyCtxError(_, _) => MiniscriptError::PubKeyCtxError,
1433            BdkMiniscriptError::RelativeLockTime(_) => MiniscriptError::RelativeLockTime,
1434            BdkMiniscriptError::Script(e) => MiniscriptError::Script {
1435                error_message: e.to_string(),
1436            },
1437            BdkMiniscriptError::Secp(e) => MiniscriptError::Secp {
1438                error_message: e.to_string(),
1439            },
1440            BdkMiniscriptError::Threshold(_) => MiniscriptError::Threshold,
1441            BdkMiniscriptError::TrNoScriptCode => MiniscriptError::TrNoScriptCode,
1442            BdkMiniscriptError::Trailing(s) => MiniscriptError::Trailing { error_message: s },
1443            BdkMiniscriptError::TypeCheck(s) => MiniscriptError::TypeCheck { error_message: s },
1444            BdkMiniscriptError::Unexpected(s) => MiniscriptError::Unexpected { error_message: s },
1445            BdkMiniscriptError::UnexpectedStart => MiniscriptError::UnexpectedStart,
1446            BdkMiniscriptError::UnknownWrapper(c) => MiniscriptError::UnknownWrapper {
1447                char: c.to_string(),
1448            },
1449            BdkMiniscriptError::Unprintable(b) => MiniscriptError::Unprintable { byte: b },
1450        }
1451    }
1452}
1453
1454impl From<BdkParseAmountError> for ParseAmountError {
1455    fn from(error: BdkParseAmountError) -> Self {
1456        match error {
1457            BdkParseAmountError::OutOfRange(_) => ParseAmountError::OutOfRange,
1458            BdkParseAmountError::TooPrecise(_) => ParseAmountError::TooPrecise,
1459            BdkParseAmountError::MissingDigits(_) => ParseAmountError::MissingDigits,
1460            BdkParseAmountError::InputTooLarge(_) => ParseAmountError::InputTooLarge,
1461            BdkParseAmountError::InvalidCharacter(c) => ParseAmountError::InvalidCharacter {
1462                error_message: c.to_string(),
1463            },
1464            _ => ParseAmountError::OtherParseAmountErr,
1465        }
1466    }
1467}
1468
1469impl From<std::io::Error> for PersistenceError {
1470    fn from(error: std::io::Error) -> Self {
1471        PersistenceError::Reason {
1472            error_message: error.to_string(),
1473        }
1474    }
1475}
1476
1477impl From<BdkPsbtError> for PsbtError {
1478    fn from(error: BdkPsbtError) -> Self {
1479        match error {
1480            BdkPsbtError::InvalidMagic => PsbtError::InvalidMagic,
1481            BdkPsbtError::MissingUtxo => PsbtError::MissingUtxo,
1482            BdkPsbtError::InvalidSeparator => PsbtError::InvalidSeparator,
1483            BdkPsbtError::PsbtUtxoOutOfbounds => PsbtError::PsbtUtxoOutOfBounds,
1484            BdkPsbtError::InvalidKey(key) => PsbtError::InvalidKey {
1485                key: key.to_string(),
1486            },
1487            BdkPsbtError::InvalidProprietaryKey => PsbtError::InvalidProprietaryKey,
1488            BdkPsbtError::DuplicateKey(key) => PsbtError::DuplicateKey {
1489                key: key.to_string(),
1490            },
1491            BdkPsbtError::UnsignedTxHasScriptSigs => PsbtError::UnsignedTxHasScriptSigs,
1492            BdkPsbtError::UnsignedTxHasScriptWitnesses => PsbtError::UnsignedTxHasScriptWitnesses,
1493            BdkPsbtError::MustHaveUnsignedTx => PsbtError::MustHaveUnsignedTx,
1494            BdkPsbtError::NoMorePairs => PsbtError::NoMorePairs,
1495            BdkPsbtError::UnexpectedUnsignedTx { .. } => PsbtError::UnexpectedUnsignedTx,
1496            BdkPsbtError::NonStandardSighashType(sighash) => {
1497                PsbtError::NonStandardSighashType { sighash }
1498            }
1499            BdkPsbtError::InvalidHash(hash) => PsbtError::InvalidHash {
1500                hash: hash.to_string(),
1501            },
1502            BdkPsbtError::InvalidPreimageHashPair { .. } => PsbtError::InvalidPreimageHashPair,
1503            BdkPsbtError::CombineInconsistentKeySources(xpub) => {
1504                PsbtError::CombineInconsistentKeySources {
1505                    xpub: xpub.to_string(),
1506                }
1507            }
1508            BdkPsbtError::ConsensusEncoding(encoding_error) => PsbtError::ConsensusEncoding {
1509                encoding_error: encoding_error.to_string(),
1510            },
1511            BdkPsbtError::NegativeFee => PsbtError::NegativeFee,
1512            BdkPsbtError::FeeOverflow => PsbtError::FeeOverflow,
1513            BdkPsbtError::InvalidPublicKey(e) => PsbtError::InvalidPublicKey {
1514                error_message: e.to_string(),
1515            },
1516            BdkPsbtError::InvalidSecp256k1PublicKey(e) => PsbtError::InvalidSecp256k1PublicKey {
1517                secp256k1_error: e.to_string(),
1518            },
1519            BdkPsbtError::InvalidXOnlyPublicKey => PsbtError::InvalidXOnlyPublicKey,
1520            BdkPsbtError::InvalidEcdsaSignature(e) => PsbtError::InvalidEcdsaSignature {
1521                error_message: e.to_string(),
1522            },
1523            BdkPsbtError::InvalidTaprootSignature(e) => PsbtError::InvalidTaprootSignature {
1524                error_message: e.to_string(),
1525            },
1526            BdkPsbtError::InvalidControlBlock => PsbtError::InvalidControlBlock,
1527            BdkPsbtError::InvalidLeafVersion => PsbtError::InvalidLeafVersion,
1528            BdkPsbtError::Taproot(_) => PsbtError::Taproot,
1529            BdkPsbtError::TapTree(e) => PsbtError::TapTree {
1530                error_message: e.to_string(),
1531            },
1532            BdkPsbtError::XPubKey(_) => PsbtError::XPubKey,
1533            BdkPsbtError::Version(e) => PsbtError::Version {
1534                error_message: e.to_string(),
1535            },
1536            BdkPsbtError::PartialDataConsumption => PsbtError::PartialDataConsumption,
1537            BdkPsbtError::Io(e) => PsbtError::Io {
1538                error_message: e.to_string(),
1539            },
1540            _ => PsbtError::OtherPsbtErr,
1541        }
1542    }
1543}
1544
1545impl From<BdkPsbtParseError> for PsbtParseError {
1546    fn from(error: BdkPsbtParseError) -> Self {
1547        match error {
1548            BdkPsbtParseError::PsbtEncoding(e) => PsbtParseError::PsbtEncoding {
1549                error_message: e.to_string(),
1550            },
1551            BdkPsbtParseError::Base64Encoding(e) => PsbtParseError::Base64Encoding {
1552                error_message: e.to_string(),
1553            },
1554            _ => {
1555                unreachable!("this is required because of the non-exhaustive enum in rust-bitcoin")
1556            }
1557        }
1558    }
1559}
1560
1561impl From<std::io::Error> for PsbtError {
1562    fn from(error: std::io::Error) -> Self {
1563        PsbtError::Io {
1564            error_message: error.to_string(),
1565        }
1566    }
1567}
1568
1569impl From<bdk_wallet::bitcoin::io::Error> for PsbtError {
1570    fn from(error: bdk_wallet::bitcoin::io::Error) -> Self {
1571        PsbtError::Io {
1572            error_message: error.to_string(),
1573        }
1574    }
1575}
1576
1577impl From<BdkPsbtFinalizeError> for PsbtFinalizeError {
1578    fn from(value: BdkPsbtFinalizeError) -> Self {
1579        match value {
1580            BdkPsbtFinalizeError::InputError(input_error, index) => PsbtFinalizeError::InputError {
1581                reason: input_error.to_string(),
1582                index: index as u32,
1583            },
1584            BdkPsbtFinalizeError::WrongInputCount { in_tx, in_map } => {
1585                PsbtFinalizeError::WrongInputCount {
1586                    in_tx: in_tx as u32,
1587                    in_map: in_map as u32,
1588                }
1589            }
1590            BdkPsbtFinalizeError::InputIdxOutofBounds { psbt_inp, index } => {
1591                PsbtFinalizeError::InputIdxOutofBounds {
1592                    psbt_inp: psbt_inp as u32,
1593                    requested: index as u32,
1594                }
1595            }
1596        }
1597    }
1598}
1599
1600#[allow(deprecated)]
1601impl From<BdkSignerError> for SignerError {
1602    fn from(error: BdkSignerError) -> Self {
1603        match error {
1604            BdkSignerError::MissingKey => SignerError::MissingKey,
1605            BdkSignerError::InvalidKey => SignerError::InvalidKey,
1606            BdkSignerError::UserCanceled => SignerError::UserCanceled,
1607            BdkSignerError::InputIndexOutOfRange(_) => SignerError::InputIndexOutOfRange,
1608            BdkSignerError::MissingNonWitnessUtxo => SignerError::MissingNonWitnessUtxo,
1609            BdkSignerError::InvalidNonWitnessUtxo => SignerError::InvalidNonWitnessUtxo,
1610            BdkSignerError::MissingWitnessUtxo => SignerError::MissingWitnessUtxo,
1611            BdkSignerError::MissingWitnessScript => SignerError::MissingWitnessScript,
1612            BdkSignerError::MissingHdKeypath => SignerError::MissingHdKeypath,
1613            BdkSignerError::NonStandardSighash => SignerError::NonStandardSighash,
1614            BdkSignerError::InvalidSighash => SignerError::InvalidSighash,
1615            BdkSignerError::SighashTaproot(e) => SignerError::SighashTaproot {
1616                error_message: e.to_string(),
1617            },
1618            BdkSignerError::MiniscriptPsbt(e) => SignerError::MiniscriptPsbt {
1619                error_message: e.to_string(),
1620            },
1621            BdkSignerError::External(e) => SignerError::External { error_message: e },
1622            BdkSignerError::Psbt(e) => SignerError::Psbt {
1623                error_message: e.to_string(),
1624            },
1625        }
1626    }
1627}
1628
1629impl From<BdkEncodeError> for TransactionError {
1630    fn from(error: BdkEncodeError) -> Self {
1631        match error {
1632            BdkEncodeError::Io(_) => TransactionError::Io,
1633            BdkEncodeError::OversizedVectorAllocation { .. } => {
1634                TransactionError::OversizedVectorAllocation
1635            }
1636            BdkEncodeError::InvalidChecksum { expected, actual } => {
1637                TransactionError::InvalidChecksum {
1638                    expected: DisplayHex::to_lower_hex_string(&expected),
1639                    actual: DisplayHex::to_lower_hex_string(&actual),
1640                }
1641            }
1642            BdkEncodeError::NonMinimalVarInt => TransactionError::NonMinimalVarInt,
1643            BdkEncodeError::ParseFailed(_) => TransactionError::ParseFailed,
1644            BdkEncodeError::UnsupportedSegwitFlag(flag) => {
1645                TransactionError::UnsupportedSegwitFlag { flag }
1646            }
1647            _ => TransactionError::OtherTransactionErr,
1648        }
1649    }
1650}
1651
1652#[derive(Debug, thiserror::Error, uniffi::Error)]
1653pub enum HashParseError {
1654    #[error("invalid hash: expected length 32 bytes, got {len} bytes")]
1655    InvalidHash { len: u32 },
1656
1657    #[error("invalid hex string: {hex}")]
1658    InvalidHexString { hex: String },
1659}
1660
1661impl From<bdk_kyoto::bip157::ClientError> for CbfError {
1662    fn from(_value: bdk_kyoto::bip157::ClientError) -> Self {
1663        CbfError::NodeStopped
1664    }
1665}