1use crate::{
2 Fee,
3 lnurl::{LnurlServerError, ReqwestLnurlServerClientError},
4 persist::{self},
5};
6use bitcoin::consensus::encode::FromHexError;
7use breez_sdk_common::error::ServiceConnectivityError;
8use serde::{Deserialize, Serialize};
9use spark_wallet::SparkWalletError;
10use std::{convert::Infallible, num::TryFromIntError};
11use thiserror::Error;
12use tracing_subscriber::util::TryInitError;
13use web_time::SystemTimeError;
14
15#[derive(Debug, Error, Clone)]
17#[cfg_attr(feature = "uniffi", derive(uniffi::Error))]
18pub enum SdkError {
19 #[error("SparkSdkError: {0}")]
20 SparkError(String),
21
22 #[error("Invalid UUID: {0}")]
23 InvalidUuid(String),
24
25 #[error("Invalid input: {0}")]
27 InvalidInput(String),
28
29 #[error("Network error: {0}")]
31 NetworkError(String),
32
33 #[error("Storage error: {0}")]
35 StorageError(String),
36
37 #[error("Chain service error: {0}")]
38 ChainServiceError(String),
39
40 #[error(
41 "Deposit claim fee exceeds for utxo: {tx}:{vout} with max fee: {max_fee:?} and actual fee: {actual_fee} sats"
42 )]
43 DepositClaimFeeExceeded {
44 tx: String,
45 vout: u32,
46 max_fee: Option<Fee>,
47 actual_fee: u64,
48 },
49
50 #[error("Missing utxo: {tx}:{vout}")]
51 MissingUtxo { tx: String, vout: u32 },
52
53 #[error("Lnurl error: {0}")]
54 LnurlError(String),
55
56 #[error("Error: {0}")]
57 Generic(String),
58}
59
60impl From<crate::chain::ChainServiceError> for SdkError {
61 fn from(e: crate::chain::ChainServiceError) -> Self {
62 SdkError::ChainServiceError(e.to_string())
63 }
64}
65
66impl From<breez_sdk_common::lnurl::error::LnurlError> for SdkError {
67 fn from(e: breez_sdk_common::lnurl::error::LnurlError) -> Self {
68 SdkError::LnurlError(e.to_string())
69 }
70}
71
72impl From<breez_sdk_common::input::ParseError> for SdkError {
73 fn from(e: breez_sdk_common::input::ParseError) -> Self {
74 SdkError::InvalidInput(e.to_string())
75 }
76}
77
78impl From<bitcoin::address::ParseError> for SdkError {
79 fn from(e: bitcoin::address::ParseError) -> Self {
80 SdkError::InvalidInput(e.to_string())
81 }
82}
83
84impl From<persist::StorageError> for SdkError {
85 fn from(e: persist::StorageError) -> Self {
86 SdkError::StorageError(e.to_string())
87 }
88}
89
90impl From<Infallible> for SdkError {
91 fn from(value: Infallible) -> Self {
92 SdkError::Generic(value.to_string())
93 }
94}
95
96impl From<String> for SdkError {
97 fn from(s: String) -> Self {
98 Self::Generic(s)
99 }
100}
101
102impl From<&str> for SdkError {
103 fn from(s: &str) -> Self {
104 Self::Generic(s.to_string())
105 }
106}
107
108impl From<SystemTimeError> for SdkError {
109 fn from(e: SystemTimeError) -> Self {
110 SdkError::Generic(e.to_string())
111 }
112}
113
114impl From<TryFromIntError> for SdkError {
115 fn from(e: TryFromIntError) -> Self {
116 SdkError::Generic(e.to_string())
117 }
118}
119
120impl From<serde_json::Error> for SdkError {
121 fn from(e: serde_json::Error) -> Self {
122 SdkError::Generic(e.to_string())
123 }
124}
125
126impl From<SparkWalletError> for SdkError {
127 fn from(e: SparkWalletError) -> Self {
128 SdkError::SparkError(e.to_string())
129 }
130}
131
132impl From<FromHexError> for SdkError {
133 fn from(e: FromHexError) -> Self {
134 SdkError::Generic(e.to_string())
135 }
136}
137
138impl From<uuid::Error> for SdkError {
139 fn from(e: uuid::Error) -> Self {
140 SdkError::InvalidUuid(e.to_string())
141 }
142}
143
144impl From<ServiceConnectivityError> for SdkError {
145 fn from(value: ServiceConnectivityError) -> Self {
146 SdkError::NetworkError(value.to_string())
147 }
148}
149
150impl From<LnurlServerError> for SdkError {
151 fn from(value: LnurlServerError) -> Self {
152 match value {
153 LnurlServerError::InvalidApiKey => {
154 SdkError::InvalidInput("Invalid api key".to_string())
155 }
156 LnurlServerError::Network {
157 statuscode,
158 message,
159 } => SdkError::NetworkError(format!(
160 "network request failed with status {statuscode}: {}",
161 message.unwrap_or(String::new())
162 )),
163 LnurlServerError::RequestFailure(e) => SdkError::NetworkError(e),
164 LnurlServerError::SigningError(e) => {
165 SdkError::Generic(format!("Failed to sign message: {e}"))
166 }
167 }
168 }
169}
170
171impl From<ReqwestLnurlServerClientError> for SdkError {
172 fn from(value: ReqwestLnurlServerClientError) -> Self {
173 SdkError::Generic(value.to_string())
174 }
175}
176
177impl From<TryInitError> for SdkError {
178 fn from(_value: TryInitError) -> Self {
179 SdkError::Generic("Logging can only be initialized once".to_string())
180 }
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize, Error, PartialEq)]
184#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
185pub enum DepositClaimError {
186 #[error(
187 "Deposit claim fee exceeds for utxo: {tx}:{vout} with max fee: {max_fee:?} and actual fee: {actual_fee} sats"
188 )]
189 DepositClaimFeeExceeded {
190 tx: String,
191 vout: u32,
192 max_fee: Option<Fee>,
193 actual_fee: u64,
194 },
195
196 #[error("Missing utxo: {tx}:{vout}")]
197 MissingUtxo { tx: String, vout: u32 },
198
199 #[error("Generic error: {message}")]
200 Generic { message: String },
201}
202
203impl From<SdkError> for DepositClaimError {
204 fn from(value: SdkError) -> Self {
205 match value {
206 SdkError::DepositClaimFeeExceeded {
207 tx,
208 vout,
209 max_fee,
210 actual_fee,
211 } => DepositClaimError::DepositClaimFeeExceeded {
212 tx,
213 vout,
214 max_fee,
215 actual_fee,
216 },
217 SdkError::MissingUtxo { tx, vout } => DepositClaimError::MissingUtxo { tx, vout },
218 SdkError::Generic(e) => DepositClaimError::Generic { message: e },
219 _ => DepositClaimError::Generic {
220 message: value.to_string(),
221 },
222 }
223 }
224}