lwk_wollet/
error.rs

1use elements::OutPoint;
2
3/// Error type for the whole crate.
4#[derive(thiserror::Error, Debug)]
5#[allow(missing_docs)]
6pub enum Error {
7    #[error("{0}")]
8    Generic(String),
9
10    #[error("Aes {0}")]
11    Aes(String),
12
13    #[error("Blinding bare key unsupported")]
14    BlindingBareUnsupported,
15
16    #[error("Blinding view key with wildcard unsupported")]
17    BlindingViewWildcardUnsupported,
18
19    #[error("Blinding view key with multipath unsupported")]
20    BlindingViewMultiUnsupported,
21
22    #[error(transparent)]
23    BitcoinBIP32Error(#[from] crate::bitcoin::bip32::Error),
24
25    #[error(transparent)]
26    JsonFrom(#[from] serde_json::Error),
27
28    #[error(transparent)]
29    StdIOError(#[from] std::io::Error),
30
31    #[cfg(feature = "electrum")]
32    #[error(transparent)]
33    ClientError(#[from] electrum_client::Error),
34
35    #[cfg(feature = "elements_rpc")]
36    #[error(transparent)]
37    ElementsRpcError(#[from] bitcoincore_rpc::Error),
38
39    #[cfg(feature = "elements_rpc")]
40    #[error("Elements RPC returned an unexpected value for call {0}")]
41    ElementsRpcUnexpectedReturn(String),
42
43    #[error(transparent)]
44    ElementsEncode(#[from] crate::elements::encode::Error),
45
46    #[error("Hex Error: {0}")]
47    ElementsHex(crate::elements::hex::Error),
48
49    #[error(transparent)]
50    Hashes(#[from] crate::elements::hashes::FromSliceError),
51
52    #[error(transparent)]
53    ElementsPset(#[from] crate::elements::pset::Error),
54
55    #[error(transparent)]
56    ElementsPsetParse(#[from] crate::elements::pset::ParseError),
57
58    #[error(transparent)]
59    PsetBlindError(#[from] crate::elements::pset::PsetBlindError),
60
61    #[error(transparent)]
62    Secp256k1(#[from] crate::secp256k1::Error),
63
64    #[error(transparent)]
65    HexToBytesError(#[from] crate::hashes::hex::HexToBytesError),
66
67    #[error(transparent)]
68    HexToArrayError(#[from] crate::hashes::hex::HexToArrayError),
69
70    #[error(transparent)]
71    ElementsMiniscript(#[from] elements_miniscript::Error),
72
73    #[error(transparent)]
74    ElementsMiniscriptPset(#[from] elements_miniscript::psbt::Error),
75
76    #[error(transparent)]
77    DescConversion(#[from] elements_miniscript::descriptor::ConversionError),
78
79    #[error(transparent)]
80    Unblind(#[from] crate::elements::UnblindError),
81
82    #[error(transparent)]
83    AddressError(#[from] crate::elements::AddressError),
84
85    #[error(transparent)]
86    SecpZkpError(#[from] crate::elements::secp256k1_zkp::Error),
87
88    #[error(transparent)]
89    PsetDetailsError(#[from] lwk_common::Error),
90
91    #[error(transparent)]
92    InvalidKeyOriginXpubError(#[from] lwk_common::InvalidKeyOriginXpub),
93
94    #[error(transparent)]
95    UtxoUpdateError(#[from] elements_miniscript::psbt::UtxoUpdateError),
96
97    #[error(transparent)]
98    OutputUpdateError(#[from] elements_miniscript::psbt::OutputUpdateError),
99
100    #[error(transparent)]
101    ParseInt(#[from] std::num::ParseIntError),
102
103    #[cfg(feature = "esplora")]
104    #[error(transparent)]
105    Reqwest(#[from] reqwest::Error),
106
107    #[error(transparent)]
108    PersistError(#[from] crate::persister::PersistError),
109
110    #[error("Address must be explicit")]
111    NotExplicitAddress,
112
113    #[error("Address must be confidential")]
114    NotConfidentialAddress,
115
116    #[error("Input must be confidential")]
117    NotConfidentialInput,
118
119    #[error("Insufficient funds: missing {missing_sats} units for {} {asset_id}",
120        .is_token.then(|| "reissuance token").unwrap_or("asset"))]
121    InsufficientFunds {
122        missing_sats: u64,
123        asset_id: crate::elements::AssetId,
124        is_token: bool,
125    },
126
127    #[error("Missing issuance")]
128    MissingIssuance,
129
130    #[error("Missing transaction")]
131    MissingTransaction,
132
133    #[error("Missing vin")]
134    MissingVin,
135
136    #[error("Missing vout")]
137    MissingVout,
138
139    #[error("Missing keyorigin")]
140    MissingKeyorigin,
141
142    #[error("Invalid amount")]
143    InvalidAmount,
144
145    #[error("The script is not owned by this wallet")]
146    ScriptNotMine,
147
148    #[error("Invalid domain")]
149    InvalidDomain,
150
151    #[error("Invalid version")]
152    InvalidVersion,
153
154    #[error("Invalid precision")]
155    InvalidPrecision,
156
157    #[error("Invalid name")]
158    InvalidName,
159
160    #[error("Invalid ticker")]
161    InvalidTicker,
162
163    #[error("Invalid issuer pubkey")]
164    InvalidIssuerPubkey,
165
166    #[error("Descriptor without wildcard not supported")]
167    UnsupportedDescriptorWithoutWildcard,
168
169    #[error(
170        "Multipath descriptor must have only the external/internal multipath (eg '.../<0;1>/*')"
171    )]
172    UnsupportedMultipathDescriptor,
173
174    #[error("Descriptor with segwit not v0 is not supported")]
175    UnsupportedDescriptorNonV0, // TODO add non supported descriptor type as field or split it further: UnsupportedDescriptorPreSegwit, UnsupportedDescriptorTaproot, UnsupportedDescriptorUnknownSegwitVersion
176
177    #[error("Missing PSET")]
178    MissingPset,
179
180    #[error("Send many cannot be called with an empty addressee list")]
181    SendManyEmptyAddressee,
182
183    #[error("Private blinding key not available")]
184    MissingPrivateBlindingKey,
185
186    #[error("Contract does not commit to asset id")]
187    ContractDoesNotCommitToAssetId,
188
189    #[error("Update height {update_tip_height} too old (internal height {store_tip_height})")]
190    UpdateHeightTooOld {
191        update_tip_height: u32,
192        store_tip_height: u32,
193    },
194
195    #[error("Update created on a wallet with status {update_status} while current wallet has {wollet_status}")]
196    UpdateOnDifferentStatus {
197        wollet_status: u64,
198        update_status: u64,
199    },
200
201    #[error("An issuance has already being set on this tx builder")]
202    IssuanceAlreadySet,
203
204    #[error("Blockchain backend have not implemented waterfalls method")]
205    WaterfallsUnimplemented,
206
207    #[error("Cannot use waterfalls scan with elip151 because it would reveal the blinding key to the server")]
208    UsingWaterfallsWithElip151,
209
210    #[error("Cannot encrypt")]
211    CannotEncrypt,
212
213    #[error("Cannot parse server recipient key")]
214    CannotParseRecipientKey,
215
216    #[cfg(feature = "electrum")]
217    #[error(transparent)]
218    Url(#[from] crate::clients::blocking::electrum_client::UrlError),
219
220    #[error("Manual coin selection is not allowed when assets are involved (this limitation will be removed in the future)")]
221    ManualCoinSelectionOnlyLbtc,
222
223    #[error("Missing wallet UTXO {0}")]
224    MissingWalletUtxo(OutPoint),
225
226    #[error("Transaction has empty witness, did you forget to sign and finalize?")]
227    EmptyWitness,
228
229    #[error(transparent)]
230    LiquidexError(#[from] crate::liquidex::LiquidexError),
231
232    #[error("Issuance amount greater than 21M*10^8 are not allowed")]
233    IssuanceAmountGreaterThanBtcMax,
234
235    #[error("Number of transaction inputs ({0}) exceeds maximum allowed input count of 256")]
236    TooManyInputs(usize),
237
238    #[error("Cannot use derivation index when the descriptor has no wildcard")]
239    IndexWithoutWildcard,
240
241    #[error("Given contract does not commit to asset '{0}'")]
242    InvalidContractForAsset(String),
243
244    #[error("Given transaction does not contain issuance of asset '{0}'")]
245    InvalidIssuanceTxtForAsset(String),
246
247    #[cfg(feature = "test_wallet")]
248    #[error(transparent)]
249    SignerError(#[from] lwk_signer::NewError),
250
251    #[error(transparent)]
252    RmpvDecodeError(#[from] rmpv::decode::Error),
253
254    #[error(transparent)]
255    RmpvEncodeError(#[from] rmpv::encode::Error),
256
257    #[error(transparent)]
258    RmpvExtError(#[from] rmpv::ext::Error),
259
260    #[error(transparent)]
261    RmpSerdeDecodeError(#[from] rmp_serde::decode::Error),
262
263    #[error(transparent)]
264    RmpSerdeEncodeError(#[from] rmp_serde::encode::Error),
265
266    #[cfg(feature = "amp0")]
267    #[error("Cannot generate address for AMP0 wallets using this call, use Amp0::address()")]
268    Amp0AddressError,
269}
270
271// cannot derive automatically with this error because of trait bound
272impl From<aes_gcm_siv::aead::Error> for Error {
273    fn from(err: aes_gcm_siv::aead::Error) -> Self {
274        Self::Aes(err.to_string())
275    }
276}
277
278impl From<elements::hex::Error> for Error {
279    fn from(err: elements::hex::Error) -> Self {
280        Self::ElementsHex(err)
281    }
282}