fedimint_wallet_client/
error.rs1use bitcoin::Network;
7use fedimint_api_client::api::FederationError;
8use fedimint_bitcoind::BitcoinRpcError;
9use fedimint_client_module::error::{
10 OperationAlreadyExistsError, OperationLookupError, TransactionSubmitError,
11};
12use fedimint_core::core::OperationId;
13use fedimint_core::db::{AutocommitError, DatabaseError};
14#[cfg(feature = "uniffi")]
15use fedimint_core::util::FmtCompact as _;
16use thiserror::Error;
17
18use crate::client_db::TweakIdx;
19
20#[derive(Debug, Error)]
27#[non_exhaustive]
28pub enum PegInError {
29 #[error("The address is not one of this client's deposit addresses")]
31 AddressNotDerived,
32
33 #[error("No deposit address belongs to operation {}", .operation_id.fmt_short())]
35 NoAddressForOperation {
36 operation_id: OperationId,
38 },
39
40 #[error("No deposit address is recorded for {tweak_idx}")]
42 TweakIdxNotFound {
43 tweak_idx: TweakIdx,
45 },
46
47 #[error("Database error")]
49 Database(#[from] DatabaseError),
50
51 #[error("The transaction claiming the deposit was rejected: {reason}")]
57 TransactionRejected {
58 reason: String,
60 },
61
62 #[error("The peg-in monitor is no longer running")]
64 MonitorStopped,
65}
66
67impl From<AutocommitError<PegInError>> for PegInError {
68 fn from(e: AutocommitError<Self>) -> Self {
69 match e {
70 AutocommitError::ClosureError { error, .. } => error,
71 AutocommitError::CommitFailed { last_error, .. } => Self::Database(last_error),
72 }
73 }
74}
75
76#[derive(Debug, Error)]
81#[non_exhaustive]
82pub enum DepositAddressError {
83 #[error("The federation was not verified to support safe deposits")]
86 SafeDepositUnverified,
87
88 #[error("The deposit address's operation already exists")]
90 OperationAlreadyExists(#[from] OperationAlreadyExistsError),
91
92 #[error("The bitcoin backend could not watch the deposit address")]
95 BitcoinRpc(#[from] BitcoinRpcError),
96
97 #[error("Database error")]
99 Database(#[from] DatabaseError),
100
101 #[error("The pooled deposit address {tweak_idx} disappeared while it was being reused")]
104 PooledAddressDisappeared {
105 tweak_idx: TweakIdx,
107 },
108
109 #[error("The pooled deposit address {tweak_idx} was used while it was being reused")]
112 PooledAddressUsed {
113 tweak_idx: TweakIdx,
115 },
116}
117
118impl From<AutocommitError<DepositAddressError>> for DepositAddressError {
119 fn from(e: AutocommitError<Self>) -> Self {
120 match e {
121 AutocommitError::ClosureError { error, .. } => error,
122 AutocommitError::CommitFailed { last_error, .. } => Self::Database(last_error),
123 }
124 }
125}
126
127#[cfg(feature = "uniffi")]
128impl From<DepositAddressError> for fedimint_core::util::ffi::UniffiError {
129 fn from(e: DepositAddressError) -> Self {
130 Self::General(e.fmt_compact().to_string())
131 }
132}
133
134#[derive(Debug, Error)]
136#[non_exhaustive]
137pub enum SubscribeDepositError {
138 #[error("The deposit operation could not be looked up")]
140 Operation(#[from] OperationLookupError),
141
142 #[error("The operation is not a deposit")]
145 NotADeposit,
146
147 #[error("The deposit address is not valid on {expected}")]
150 WrongNetwork {
151 expected: Network,
153 },
154
155 #[error("An old pending deposit cannot be subscribed to")]
158 OldPendingDeposit,
159
160 #[error("The recorded outcome of an old deposit is not final")]
163 NonFinalOutcome,
164}
165
166#[cfg(feature = "uniffi")]
167impl From<SubscribeDepositError> for fedimint_core::util::ffi::UniffiError {
168 fn from(e: SubscribeDepositError) -> Self {
169 Self::General(e.fmt_compact().to_string())
170 }
171}
172
173#[derive(Debug, Error)]
175#[non_exhaustive]
176pub enum WithdrawFeesError {
177 #[error("The peg-out fees could not be fetched")]
179 Federation(#[source] Box<FederationError>),
180
181 #[error("The federation did not quote peg-out fees")]
184 NoQuote,
185}
186
187impl From<FederationError> for WithdrawFeesError {
188 fn from(source: FederationError) -> Self {
189 Self::Federation(Box::new(source))
190 }
191}
192
193#[derive(Debug, Error)]
196#[non_exhaustive]
197pub enum MaxWithdrawableAmountError {
198 #[error("The peg-out fees could not be quoted")]
200 Fees(#[from] WithdrawFeesError),
201
202 #[error("The balance {balance} is too low to cover the dust limit {dust_limit} and fees")]
205 BalanceTooLow {
206 balance: fedimint_core::Amount,
208 dust_limit: bitcoin::Amount,
210 },
211
212 #[error("The fee quote for the withdrawal failed")]
214 Quote(#[source] TransactionSubmitError),
215}
216
217#[derive(Debug, Error)]
219#[non_exhaustive]
220pub enum PegOutError {
221 #[error("The destination address is not valid on {expected}")]
224 WrongNetwork {
225 expected: Network,
227 },
228
229 #[error("The peg-out fees could not be quoted")]
231 Fees(#[from] WithdrawFeesError),
232
233 #[error("The withdrawal transaction could not be submitted")]
235 Transaction(#[from] TransactionSubmitError),
236}
237
238#[cfg(feature = "uniffi")]
239impl From<PegOutError> for fedimint_core::util::ffi::UniffiError {
240 fn from(e: PegOutError) -> Self {
241 Self::General(e.fmt_compact().to_string())
242 }
243}
244
245#[derive(Debug, Error)]
247#[non_exhaustive]
248pub enum SubscribeWithdrawError {
249 #[error("The withdrawal operation could not be looked up")]
251 Operation(#[from] OperationLookupError),
252
253 #[error("The operation is not a withdrawal")]
256 NotAWithdrawal,
257}
258
259#[cfg(feature = "uniffi")]
260impl From<SubscribeWithdrawError> for fedimint_core::util::ffi::UniffiError {
261 fn from(e: SubscribeWithdrawError) -> Self {
262 Self::General(e.fmt_compact().to_string())
263 }
264}
265
266#[derive(Debug, Error)]
268#[non_exhaustive]
269pub enum ConsensusVersionVotingError {
270 #[error("Admin auth is not set")]
273 AdminAuthMissing,
274
275 #[error("The vote could not be submitted to the federation")]
277 Federation(#[source] Box<FederationError>),
278}
279
280impl From<FederationError> for ConsensusVersionVotingError {
281 fn from(source: FederationError) -> Self {
282 Self::Federation(Box::new(source))
283 }
284}