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("Invalid UUID: {0}")]
24    InvalidUuid(String),
25
26    /// Invalid input error
27    #[error("Invalid input: {0}")]
28    InvalidInput(String),
29
30    /// Network error
31    #[error("Network error: {0}")]
32    NetworkError(String),
33
34    /// Storage error
35    #[error("Storage error: {0}")]
36    StorageError(String),
37
38    #[error("Chain service error: {0}")]
39    ChainServiceError(String),
40
41    #[error(
42        "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"
43    )]
44    MaxDepositClaimFeeExceeded {
45        tx: String,
46        vout: u32,
47        max_fee: Option<Fee>,
48        required_fee_sats: u64,
49        required_fee_rate_sat_per_vbyte: u64,
50    },
51
52    #[error("Missing utxo: {tx}:{vout}")]
53    MissingUtxo { tx: String, vout: u32 },
54
55    #[error("Lnurl error: {0}")]
56    LnurlError(String),
57
58    #[error("Error: {0}")]
59    Generic(String),
60}
61
62impl From<crate::chain::ChainServiceError> for SdkError {
63    fn from(e: crate::chain::ChainServiceError) -> Self {
64        SdkError::ChainServiceError(e.to_string())
65    }
66}
67
68impl From<breez_sdk_common::lnurl::error::LnurlError> for SdkError {
69    fn from(e: breez_sdk_common::lnurl::error::LnurlError) -> Self {
70        SdkError::LnurlError(e.to_string())
71    }
72}
73
74impl From<breez_sdk_common::input::ParseError> for SdkError {
75    fn from(e: breez_sdk_common::input::ParseError) -> Self {
76        SdkError::InvalidInput(e.to_string())
77    }
78}
79
80impl From<bitcoin::address::ParseError> for SdkError {
81    fn from(e: bitcoin::address::ParseError) -> Self {
82        SdkError::InvalidInput(e.to_string())
83    }
84}
85
86impl From<persist::StorageError> for SdkError {
87    fn from(e: persist::StorageError) -> Self {
88        SdkError::StorageError(e.to_string())
89    }
90}
91
92impl From<Infallible> for SdkError {
93    fn from(value: Infallible) -> Self {
94        SdkError::Generic(value.to_string())
95    }
96}
97
98impl From<String> for SdkError {
99    fn from(s: String) -> Self {
100        Self::Generic(s)
101    }
102}
103
104impl From<&str> for SdkError {
105    fn from(s: &str) -> Self {
106        Self::Generic(s.to_string())
107    }
108}
109
110impl From<SystemTimeError> for SdkError {
111    fn from(e: SystemTimeError) -> Self {
112        SdkError::Generic(e.to_string())
113    }
114}
115
116impl From<TryFromIntError> for SdkError {
117    fn from(e: TryFromIntError) -> Self {
118        SdkError::Generic(e.to_string())
119    }
120}
121
122impl From<serde_json::Error> for SdkError {
123    fn from(e: serde_json::Error) -> Self {
124        SdkError::Generic(e.to_string())
125    }
126}
127
128impl From<SparkWalletError> for SdkError {
129    fn from(e: SparkWalletError) -> Self {
130        SdkError::SparkError(e.to_string())
131    }
132}
133
134impl From<FromHexError> for SdkError {
135    fn from(e: FromHexError) -> Self {
136        SdkError::Generic(e.to_string())
137    }
138}
139
140impl From<uuid::Error> for SdkError {
141    fn from(e: uuid::Error) -> Self {
142        SdkError::InvalidUuid(e.to_string())
143    }
144}
145
146impl From<ServiceConnectivityError> for SdkError {
147    fn from(value: ServiceConnectivityError) -> Self {
148        SdkError::NetworkError(value.to_string())
149    }
150}
151
152impl From<LnurlServerError> for SdkError {
153    fn from(value: LnurlServerError) -> Self {
154        match value {
155            LnurlServerError::InvalidApiKey => {
156                SdkError::InvalidInput("Invalid api key".to_string())
157            }
158            LnurlServerError::Network {
159                statuscode,
160                message,
161            } => SdkError::NetworkError(format!(
162                "network request failed with status {statuscode}: {}",
163                message.unwrap_or(String::new())
164            )),
165            LnurlServerError::RequestFailure(e) => SdkError::NetworkError(e),
166            LnurlServerError::SigningError(e) => {
167                SdkError::Generic(format!("Failed to sign message: {e}"))
168            }
169        }
170    }
171}
172
173impl From<ReqwestLnurlServerClientError> for SdkError {
174    fn from(value: ReqwestLnurlServerClientError) -> Self {
175        SdkError::Generic(value.to_string())
176    }
177}
178
179impl From<TryInitError> for SdkError {
180    fn from(_value: TryInitError) -> Self {
181        SdkError::Generic("Logging can only be initialized once".to_string())
182    }
183}
184
185impl From<NostrError> for SdkError {
186    fn from(value: NostrError) -> Self {
187        match value {
188            NostrError::KeyDerivationError(e) => {
189                SdkError::Generic(format!("Nostr key derivation error: {e}"))
190            }
191            NostrError::ZapReceiptCreationError(e) => {
192                SdkError::Generic(format!("Nostr zap receipt creation error: {e}"))
193            }
194        }
195    }
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize, Error, PartialEq)]
199#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
200pub enum DepositClaimError {
201    #[error(
202        "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"
203    )]
204    MaxDepositClaimFeeExceeded {
205        tx: String,
206        vout: u32,
207        max_fee: Option<Fee>,
208        required_fee_sats: u64,
209        required_fee_rate_sat_per_vbyte: u64,
210    },
211
212    #[error("Missing utxo: {tx}:{vout}")]
213    MissingUtxo { tx: String, vout: u32 },
214
215    #[error("Generic error: {message}")]
216    Generic { message: String },
217}
218
219impl From<SdkError> for DepositClaimError {
220    fn from(value: SdkError) -> Self {
221        match value {
222            SdkError::MaxDepositClaimFeeExceeded {
223                tx,
224                vout,
225                max_fee,
226                required_fee_sats,
227                required_fee_rate_sat_per_vbyte,
228            } => DepositClaimError::MaxDepositClaimFeeExceeded {
229                tx,
230                vout,
231                max_fee,
232                required_fee_sats,
233                required_fee_rate_sat_per_vbyte,
234            },
235            SdkError::MissingUtxo { tx, vout } => DepositClaimError::MissingUtxo { tx, vout },
236            SdkError::Generic(e) => DepositClaimError::Generic { message: e },
237            _ => DepositClaimError::Generic {
238                message: value.to_string(),
239            },
240        }
241    }
242}