breez_sdk_liquid/
error.rs1use anyhow::Error;
2use lwk_wollet::secp256k1;
3use sdk_common::{
4 lightning_with_bolt12::offers::parse::Bolt12SemanticError,
5 prelude::{LnUrlAuthError, LnUrlPayError, LnUrlWithdrawError},
6};
7
8use crate::payjoin::error::PayjoinError;
9
10pub type SdkResult<T, E = SdkError> = Result<T, E>;
11
12#[macro_export]
13macro_rules! ensure_sdk {
14 ($cond:expr, $err:expr) => {
15 if !$cond {
16 return Err($err);
17 }
18 };
19}
20
21#[derive(Debug, thiserror::Error)]
23pub enum SdkError {
24 #[error("Liquid SDK instance is already running")]
25 AlreadyStarted,
26
27 #[error("Error: {err}")]
28 Generic { err: String },
29
30 #[error("Liquid SDK instance is not running")]
31 NotStarted,
32
33 #[error("Service connectivity: {err}")]
34 ServiceConnectivity { err: String },
35}
36impl SdkError {
37 pub fn generic<T: AsRef<str>>(err: T) -> Self {
38 Self::Generic {
39 err: err.as_ref().to_string(),
40 }
41 }
42}
43
44impl From<anyhow::Error> for SdkError {
45 fn from(e: Error) -> Self {
46 SdkError::generic(e.to_string())
47 }
48}
49
50impl From<boltz_client::error::Error> for SdkError {
51 fn from(err: boltz_client::error::Error) -> Self {
52 match err {
53 boltz_client::error::Error::HTTP(e) => {
54 SdkError::generic(format!("Could not contact servers: {e:?}"))
55 }
56 _ => SdkError::generic(format!("{err:?}")),
57 }
58 }
59}
60
61impl From<secp256k1::Error> for SdkError {
62 fn from(err: secp256k1::Error) -> Self {
63 SdkError::generic(format!("{err:?}"))
64 }
65}
66
67#[derive(thiserror::Error, Debug)]
68pub enum PaymentError {
69 #[error("The specified funds have already been claimed")]
70 AlreadyClaimed,
71
72 #[error("The specified funds have already been sent")]
73 AlreadyPaid,
74
75 #[error("The payment is already in progress")]
76 PaymentInProgress,
77
78 #[error("Amount must be between {min} and {max}")]
79 AmountOutOfRange { min: u64, max: u64 },
80
81 #[error("Amount is missing: {err}")]
82 AmountMissing { err: String },
83
84 #[error("Asset error: {err}")]
85 AssetError { err: String },
86
87 #[error("Invalid network: {err}")]
88 InvalidNetwork { err: String },
89
90 #[error("Generic error: {err}")]
91 Generic { err: String },
92
93 #[error("The provided fees have expired")]
94 InvalidOrExpiredFees,
95
96 #[error("Cannot pay: not enough funds")]
97 InsufficientFunds,
98
99 #[error("Invalid description: {err}")]
100 InvalidDescription { err: String },
101
102 #[error("The specified invoice is not valid: {err}")]
103 InvalidInvoice { err: String },
104
105 #[error("The generated preimage is not valid")]
106 InvalidPreimage,
107
108 #[error("Boltz did not return any pairs from the request")]
109 PairsNotFound,
110
111 #[error("The payment timed out")]
112 PaymentTimeout,
113
114 #[error("Could not store the swap details locally")]
115 PersistError,
116
117 #[error("Could not process the Receive Payment: {err}")]
118 ReceiveError { err: String },
119
120 #[error("The payment has been refunded. Reason for failure: {err}")]
121 Refunded { err: String, refund_tx_id: String },
122
123 #[error("The payment is a self-transfer, which is not supported")]
124 SelfTransferNotSupported,
125
126 #[error("Could not process the Send Payment: {err}")]
127 SendError { err: String },
128
129 #[error("Could not sign the transaction: {err}")]
130 SignerError { err: String },
131}
132impl PaymentError {
133 pub(crate) fn asset_error<S: AsRef<str>>(err: S) -> Self {
134 Self::AssetError {
135 err: err.as_ref().to_string(),
136 }
137 }
138
139 pub(crate) fn generic<S: AsRef<str>>(err: S) -> Self {
140 Self::Generic {
141 err: err.as_ref().to_string(),
142 }
143 }
144
145 pub(crate) fn invalid_invoice<S: AsRef<str>>(err: S) -> Self {
146 Self::InvalidInvoice {
147 err: err.as_ref().to_string(),
148 }
149 }
150
151 pub(crate) fn invalid_network<S: AsRef<str>>(err: S) -> Self {
152 Self::InvalidNetwork {
153 err: err.as_ref().to_string(),
154 }
155 }
156
157 pub(crate) fn receive_error<S: AsRef<str>>(err: S) -> Self {
158 Self::ReceiveError {
159 err: err.as_ref().to_string(),
160 }
161 }
162
163 pub(crate) fn amount_missing<S: AsRef<str>>(err: S) -> Self {
164 Self::AmountMissing {
165 err: err.as_ref().to_string(),
166 }
167 }
168}
169
170impl From<Bolt12SemanticError> for PaymentError {
171 fn from(err: Bolt12SemanticError) -> Self {
172 PaymentError::Generic {
173 err: format!("Failed to create BOLT12 invoice: {err:?}"),
174 }
175 }
176}
177
178impl From<boltz_client::error::Error> for PaymentError {
179 fn from(err: boltz_client::error::Error) -> Self {
180 match err {
181 boltz_client::error::Error::HTTP(e) => PaymentError::Generic {
182 err: format!("Could not contact servers: {e:?}"),
183 },
184 _ => PaymentError::Generic {
185 err: format!("{err:?}"),
186 },
187 }
188 }
189}
190
191impl From<boltz_client::bitcoin::hex::HexToArrayError> for PaymentError {
192 fn from(err: boltz_client::bitcoin::hex::HexToArrayError) -> Self {
193 PaymentError::Generic {
194 err: format!("{err:?}"),
195 }
196 }
197}
198
199impl From<lwk_wollet::Error> for PaymentError {
200 fn from(err: lwk_wollet::Error) -> Self {
201 match err {
202 lwk_wollet::Error::InsufficientFunds => PaymentError::InsufficientFunds,
203 _ => PaymentError::Generic {
204 err: format!("{err:?}"),
205 },
206 }
207 }
208}
209
210#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
211impl From<lwk_wollet::UrlError> for PaymentError {
212 fn from(err: lwk_wollet::UrlError) -> Self {
213 PaymentError::Generic {
214 err: format!("{err:?}"),
215 }
216 }
217}
218
219impl From<lwk_signer::SignerError> for PaymentError {
220 fn from(err: lwk_signer::SignerError) -> Self {
221 PaymentError::SignerError {
222 err: format!("{err:?}"),
223 }
224 }
225}
226
227impl From<anyhow::Error> for PaymentError {
228 fn from(err: anyhow::Error) -> Self {
229 Self::Generic {
230 err: err.to_string(),
231 }
232 }
233}
234
235impl From<PayjoinError> for PaymentError {
236 fn from(err: PayjoinError) -> Self {
237 match err {
238 PayjoinError::InsufficientFunds => PaymentError::InsufficientFunds,
239 _ => PaymentError::Generic {
240 err: format!("{err:?}"),
241 },
242 }
243 }
244}
245
246impl From<rusqlite::Error> for PaymentError {
247 fn from(_: rusqlite::Error) -> Self {
248 Self::PersistError
249 }
250}
251
252impl From<SdkError> for PaymentError {
253 fn from(err: SdkError) -> Self {
254 Self::Generic {
255 err: err.to_string(),
256 }
257 }
258}
259
260impl From<sdk_common::bitcoin::util::bip32::Error> for PaymentError {
261 fn from(err: sdk_common::bitcoin::util::bip32::Error) -> Self {
262 Self::SignerError {
263 err: err.to_string(),
264 }
265 }
266}
267
268impl From<secp256k1::Error> for PaymentError {
269 fn from(err: secp256k1::Error) -> Self {
270 Self::Generic {
271 err: err.to_string(),
272 }
273 }
274}
275
276impl From<PaymentError> for LnUrlAuthError {
277 fn from(err: PaymentError) -> Self {
278 Self::Generic {
279 err: err.to_string(),
280 }
281 }
282}
283
284impl From<PaymentError> for LnUrlPayError {
285 fn from(err: PaymentError) -> Self {
286 Self::Generic {
287 err: err.to_string(),
288 }
289 }
290}
291
292impl From<PaymentError> for LnUrlWithdrawError {
293 fn from(err: PaymentError) -> Self {
294 Self::Generic {
295 err: err.to_string(),
296 }
297 }
298}