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