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#[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 #[error("Invalid input: {0}")]
28 InvalidInput(String),
29
30 #[error("Network error: {0}")]
32 NetworkError(String),
33
34 #[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}