breez_sdk_spark/
error.rs

1use crate::{
2    Fee,
3    lnurl::{LnurlServerError, ReqwestLnurlServerClientError},
4    nostr::NostrError,
5    persist::{self},
6};
7use bitcoin::consensus::encode::FromHexError;
8use breez_sdk_common::error::ServiceConnectivityError;
9use serde::{Deserialize, Serialize};
10use spark_wallet::SparkWalletError;
11use std::{convert::Infallible, num::TryFromIntError};
12use thiserror::Error;
13use tracing_subscriber::util::TryInitError;
14use web_time::SystemTimeError;
15
16/// Error type for the `BreezSdk`
17#[derive(Debug, Error, Clone)]
18#[cfg_attr(feature = "uniffi", derive(uniffi::Error))]
19pub enum SdkError {
20    #[error("SparkSdkError: {0}")]
21    SparkError(String),
22
23    #[error("Insufficient funds")]
24    InsufficientFunds,
25
26    #[error("Invalid UUID: {0}")]
27    InvalidUuid(String),
28
29    /// Invalid input error
30    #[error("Invalid input: {0}")]
31    InvalidInput(String),
32
33    /// Network error
34    #[error("Network error: {0}")]
35    NetworkError(String),
36
37    /// Storage error
38    #[error("Storage error: {0}")]
39    StorageError(String),
40
41    #[error("Chain service error: {0}")]
42    ChainServiceError(String),
43
44    #[error(
45        "Max deposit claim fee exceeded for utxo: {tx}:{vout} with max fee: {max_fee:?} and required fee: {required_fee_sats} sats or {required_fee_rate_sat_per_vbyte} sats/vbyte"
46    )]
47    MaxDepositClaimFeeExceeded {
48        tx: String,
49        vout: u32,
50        max_fee: Option<Fee>,
51        required_fee_sats: u64,
52        required_fee_rate_sat_per_vbyte: u64,
53    },
54
55    #[error("Missing utxo: {tx}:{vout}")]
56    MissingUtxo { tx: String, vout: u32 },
57
58    #[error("Lnurl error: {0}")]
59    LnurlError(String),
60
61    #[error("Signer error: {0}")]
62    Signer(String),
63
64    #[error("Error: {0}")]
65    Generic(String),
66}
67
68impl From<crate::chain::ChainServiceError> for SdkError {
69    fn from(e: crate::chain::ChainServiceError) -> Self {
70        SdkError::ChainServiceError(e.to_string())
71    }
72}
73
74impl From<breez_sdk_common::lnurl::error::LnurlError> for SdkError {
75    fn from(e: breez_sdk_common::lnurl::error::LnurlError) -> Self {
76        SdkError::LnurlError(e.to_string())
77    }
78}
79
80impl From<breez_sdk_common::input::ParseError> for SdkError {
81    fn from(e: breez_sdk_common::input::ParseError) -> Self {
82        SdkError::InvalidInput(e.to_string())
83    }
84}
85
86impl From<bitcoin::address::ParseError> for SdkError {
87    fn from(e: bitcoin::address::ParseError) -> Self {
88        SdkError::InvalidInput(e.to_string())
89    }
90}
91
92impl From<flashnet::FlashnetError> for SdkError {
93    fn from(e: flashnet::FlashnetError) -> Self {
94        match e {
95            flashnet::FlashnetError::Network { reason, code } => {
96                let code = match code {
97                    Some(c) => format!(" (code: {c})"),
98                    None => String::new(),
99                };
100                SdkError::NetworkError(format!("{reason}{code}"))
101            }
102            _ => SdkError::Generic(e.to_string()),
103        }
104    }
105}
106
107impl From<persist::StorageError> for SdkError {
108    fn from(e: persist::StorageError) -> Self {
109        SdkError::StorageError(e.to_string())
110    }
111}
112
113impl From<Infallible> for SdkError {
114    fn from(value: Infallible) -> Self {
115        SdkError::Generic(value.to_string())
116    }
117}
118
119impl From<String> for SdkError {
120    fn from(s: String) -> Self {
121        Self::Generic(s)
122    }
123}
124
125impl From<&str> for SdkError {
126    fn from(s: &str) -> Self {
127        Self::Generic(s.to_string())
128    }
129}
130
131impl From<SystemTimeError> for SdkError {
132    fn from(e: SystemTimeError) -> Self {
133        SdkError::Generic(e.to_string())
134    }
135}
136
137impl From<TryFromIntError> for SdkError {
138    fn from(e: TryFromIntError) -> Self {
139        SdkError::Generic(e.to_string())
140    }
141}
142
143impl From<serde_json::Error> for SdkError {
144    fn from(e: serde_json::Error) -> Self {
145        SdkError::Generic(e.to_string())
146    }
147}
148
149impl From<SparkWalletError> for SdkError {
150    fn from(e: SparkWalletError) -> Self {
151        match e {
152            SparkWalletError::InsufficientFunds => SdkError::InsufficientFunds,
153            _ => SdkError::SparkError(e.to_string()),
154        }
155    }
156}
157
158impl From<FromHexError> for SdkError {
159    fn from(e: FromHexError) -> Self {
160        SdkError::Generic(e.to_string())
161    }
162}
163
164impl From<uuid::Error> for SdkError {
165    fn from(e: uuid::Error) -> Self {
166        SdkError::InvalidUuid(e.to_string())
167    }
168}
169
170impl From<ServiceConnectivityError> for SdkError {
171    fn from(value: ServiceConnectivityError) -> Self {
172        SdkError::NetworkError(value.to_string())
173    }
174}
175
176impl From<LnurlServerError> for SdkError {
177    fn from(value: LnurlServerError) -> Self {
178        match value {
179            LnurlServerError::InvalidApiKey => {
180                SdkError::InvalidInput("Invalid api key".to_string())
181            }
182            LnurlServerError::Network {
183                statuscode,
184                message,
185            } => SdkError::NetworkError(format!(
186                "network request failed with status {statuscode}: {}",
187                message.unwrap_or(String::new())
188            )),
189            LnurlServerError::RequestFailure(e) => SdkError::NetworkError(e),
190            LnurlServerError::SigningError(e) => {
191                SdkError::Generic(format!("Failed to sign message: {e}"))
192            }
193        }
194    }
195}
196
197impl From<ReqwestLnurlServerClientError> for SdkError {
198    fn from(value: ReqwestLnurlServerClientError) -> Self {
199        SdkError::Generic(value.to_string())
200    }
201}
202
203impl From<TryInitError> for SdkError {
204    fn from(_value: TryInitError) -> Self {
205        SdkError::Generic("Logging can only be initialized once".to_string())
206    }
207}
208
209impl From<NostrError> for SdkError {
210    fn from(value: NostrError) -> Self {
211        match value {
212            NostrError::KeyDerivationError(e) => {
213                SdkError::Generic(format!("Nostr key derivation error: {e}"))
214            }
215            NostrError::ZapReceiptCreationError(e) => {
216                SdkError::Generic(format!("Nostr zap receipt creation error: {e}"))
217            }
218        }
219    }
220}
221
222#[derive(Debug, Clone, Serialize, Deserialize, Error, PartialEq)]
223#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
224pub enum DepositClaimError {
225    #[error(
226        "Max deposit claim fee exceeded for utxo: {tx}:{vout} with max fee: {max_fee:?} and required fee: {required_fee_sats} sats or {required_fee_rate_sat_per_vbyte} sats/vbyte"
227    )]
228    MaxDepositClaimFeeExceeded {
229        tx: String,
230        vout: u32,
231        max_fee: Option<Fee>,
232        required_fee_sats: u64,
233        required_fee_rate_sat_per_vbyte: u64,
234    },
235
236    #[error("Missing utxo: {tx}:{vout}")]
237    MissingUtxo { tx: String, vout: u32 },
238
239    #[error("Generic error: {message}")]
240    Generic { message: String },
241}
242
243impl From<SdkError> for DepositClaimError {
244    fn from(value: SdkError) -> Self {
245        match value {
246            SdkError::MaxDepositClaimFeeExceeded {
247                tx,
248                vout,
249                max_fee,
250                required_fee_sats,
251                required_fee_rate_sat_per_vbyte,
252            } => DepositClaimError::MaxDepositClaimFeeExceeded {
253                tx,
254                vout,
255                max_fee,
256                required_fee_sats,
257                required_fee_rate_sat_per_vbyte,
258            },
259            SdkError::MissingUtxo { tx, vout } => DepositClaimError::MissingUtxo { tx, vout },
260            SdkError::Generic(e) => DepositClaimError::Generic { message: e },
261            _ => DepositClaimError::Generic {
262                message: value.to_string(),
263            },
264        }
265    }
266}
267
268/// Error type for signer operations
269#[derive(Debug, Error, Clone)]
270#[cfg_attr(feature = "uniffi", derive(uniffi::Error))]
271pub enum SignerError {
272    #[error("Key derivation error: {0}")]
273    KeyDerivation(String),
274
275    #[error("Signing error: {0}")]
276    Signing(String),
277
278    #[error("Encryption error: {0}")]
279    Encryption(String),
280
281    #[error("Decryption error: {0}")]
282    Decryption(String),
283
284    #[error("FROST error: {0}")]
285    Frost(String),
286
287    #[error("Invalid input: {0}")]
288    InvalidInput(String),
289
290    #[error("Generic signer error: {0}")]
291    Generic(String),
292}
293
294impl From<String> for SignerError {
295    fn from(s: String) -> Self {
296        SignerError::Generic(s)
297    }
298}
299
300impl From<&str> for SignerError {
301    fn from(s: &str) -> Self {
302        SignerError::Generic(s.to_string())
303    }
304}