breez_sdk_core/
error.rs

1use std::time::SystemTimeError;
2
3use anyhow::Result;
4use sdk_common::prelude::*;
5use thiserror::Error;
6
7use crate::{
8    bitcoin::util::bip32, node_api::NodeError, persist::error::PersistError,
9    swap_in::ReceiveSwapError, swap_out::error::ReverseSwapError,
10};
11
12pub type SdkResult<T, E = SdkError> = Result<T, E>;
13
14/// Error returned by [crate::breez_services::BreezServices::connect]
15#[derive(Debug, Error)]
16pub enum ConnectError {
17    /// This error is raised when a general error occurs not specific to other error variants
18    /// in this enum.
19    #[error("Generic: {err}")]
20    Generic { err: String },
21
22    /// This error is raised when [crate::models::ConnectRequest::restore_only] is set to true
23    /// and no node exists for [crate::models::ConnectRequest::seed].
24    #[error("Restore only: {err}")]
25    RestoreOnly { err: String },
26
27    /// This error is raised when a connection to an external service fails.
28    #[error("Service connectivity: {err}")]
29    ServiceConnectivity { err: String },
30}
31
32impl From<bip32::Error> for ConnectError {
33    fn from(err: bip32::Error) -> Self {
34        Self::Generic {
35            err: err.to_string(),
36        }
37    }
38}
39
40impl From<NodeError> for ConnectError {
41    fn from(value: NodeError) -> Self {
42        match value {
43            NodeError::RestoreOnly(err) => Self::RestoreOnly { err },
44            NodeError::ServiceConnectivity(err) => Self::ServiceConnectivity { err },
45            _ => Self::Generic {
46                err: value.to_string(),
47            },
48        }
49    }
50}
51
52impl From<PersistError> for ConnectError {
53    fn from(err: PersistError) -> Self {
54        Self::Generic {
55            err: err.to_string(),
56        }
57    }
58}
59
60impl From<ServiceConnectivityError> for ConnectError {
61    fn from(value: ServiceConnectivityError) -> Self {
62        Self::ServiceConnectivity { err: value.err }
63    }
64}
65
66impl From<SdkError> for ConnectError {
67    fn from(value: SdkError) -> Self {
68        match value {
69            SdkError::Generic { err } => Self::Generic { err },
70            SdkError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
71        }
72    }
73}
74
75impl From<SdkError> for LnUrlAuthError {
76    fn from(value: SdkError) -> Self {
77        match value {
78            SdkError::Generic { err } => Self::Generic { err },
79            SdkError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
80        }
81    }
82}
83
84impl From<PersistError> for LnUrlPayError {
85    fn from(err: PersistError) -> Self {
86        Self::Generic {
87            err: err.to_string(),
88        }
89    }
90}
91
92impl From<SdkError> for LnUrlPayError {
93    fn from(value: SdkError) -> Self {
94        match value {
95            SdkError::Generic { err } => Self::Generic { err },
96            SdkError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
97        }
98    }
99}
100
101impl From<SendPaymentError> for LnUrlPayError {
102    fn from(value: SendPaymentError) -> Self {
103        match value {
104            SendPaymentError::AlreadyPaid => Self::AlreadyPaid,
105            SendPaymentError::Generic { err } => Self::Generic { err },
106            SendPaymentError::InvalidAmount { err } => Self::InvalidAmount { err },
107            SendPaymentError::InvalidInvoice { err } => Self::InvalidInvoice { err },
108            SendPaymentError::InvalidNetwork { err } => Self::InvalidNetwork { err },
109            SendPaymentError::InvoiceExpired { err } => Self::InvoiceExpired { err },
110            SendPaymentError::PaymentFailed { err } => Self::PaymentFailed { err },
111            SendPaymentError::PaymentTimeout { err } => Self::PaymentTimeout { err },
112            SendPaymentError::RouteNotFound { err } => Self::RouteNotFound { err },
113            SendPaymentError::RouteTooExpensive { err } => Self::RouteTooExpensive { err },
114            SendPaymentError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
115            SendPaymentError::InsufficientBalance { err } => Self::InsufficientBalance { err },
116        }
117    }
118}
119
120impl From<PersistError> for LnUrlWithdrawError {
121    fn from(err: PersistError) -> Self {
122        Self::Generic {
123            err: err.to_string(),
124        }
125    }
126}
127
128impl From<ReceivePaymentError> for LnUrlWithdrawError {
129    fn from(value: ReceivePaymentError) -> Self {
130        match value {
131            ReceivePaymentError::Generic { err }
132            | ReceivePaymentError::InvoiceExpired { err }
133            | ReceivePaymentError::InvoiceNoDescription { err }
134            | ReceivePaymentError::InvoicePreimageAlreadyExists { err } => Self::Generic { err },
135            ReceivePaymentError::InvalidAmount { err } => Self::InvalidAmount { err },
136            ReceivePaymentError::InvalidInvoice { err } => Self::InvalidInvoice { err },
137            ReceivePaymentError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
138            ReceivePaymentError::InvoiceNoRoutingHints { err } => {
139                Self::InvoiceNoRoutingHints { err }
140            }
141        }
142    }
143}
144
145impl From<SdkError> for LnUrlWithdrawError {
146    fn from(value: SdkError) -> Self {
147        match value {
148            SdkError::Generic { err } => Self::Generic { err },
149            SdkError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
150        }
151    }
152}
153
154pub type ReceiveOnchainResult<T, E = ReceiveOnchainError> = Result<T, E>;
155
156/// Error returned by [crate::breez_services::BreezServices::receive_onchain] and
157/// [crate::breez_services::BreezServices::buy_bitcoin]
158#[derive(Debug, Error)]
159pub enum ReceiveOnchainError {
160    /// This error is raised when a general error occurs not specific to other error variants
161    /// in this enum.
162    #[error("Generic: {err}")]
163    Generic { err: String },
164
165    /// This error is raised when a connection to an external service fails.
166    #[error("Service connectivity: {err}")]
167    ServiceConnectivity { err: String },
168
169    /// This error is raised when there is already an in progress swap when trying to
170    /// receive an onchain payment.
171    #[error("Swap in progress: {err}")]
172    SwapInProgress { err: String },
173}
174
175impl From<anyhow::Error> for ReceiveOnchainError {
176    fn from(err: anyhow::Error) -> Self {
177        Self::Generic {
178            err: err.to_string(),
179        }
180    }
181}
182
183impl From<SdkError> for ReceiveOnchainError {
184    fn from(value: SdkError) -> Self {
185        match value {
186            SdkError::Generic { err } => Self::Generic { err },
187            SdkError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
188        }
189    }
190}
191
192impl From<ReceiveSwapError> for ReceiveOnchainError {
193    fn from(value: ReceiveSwapError) -> Self {
194        match value {
195            ReceiveSwapError::ServiceConnectivity(err) => Self::ServiceConnectivity { err },
196            _ => Self::Generic {
197                err: value.to_string(),
198            },
199        }
200    }
201}
202
203impl From<PersistError> for ReceiveOnchainError {
204    fn from(err: PersistError) -> Self {
205        Self::Generic {
206            err: err.to_string(),
207        }
208    }
209}
210
211pub type RedeemOnchainResult<T, E = RedeemOnchainError> = Result<T, E>;
212
213#[derive(Debug, Error)]
214pub enum RedeemOnchainError {
215    /// This error is raised when a general error occurs not specific to other error variants
216    /// in this enum.
217    #[error("Generic: {err}")]
218    Generic { err: String },
219
220    /// This error is raised when a connection to an external service fails.
221    #[error("Service connectivity: {err}")]
222    ServiceConnectivity { err: String },
223
224    /// This error is raised when the node does not have enough funds to redeem the onchain balance.
225    #[error("{err}")]
226    InsufficientFunds { err: String },
227}
228
229impl From<NodeError> for RedeemOnchainError {
230    fn from(value: NodeError) -> Self {
231        match value {
232            NodeError::InsufficientFunds(err) => Self::InsufficientFunds { err },
233            NodeError::ServiceConnectivity(err) => Self::ServiceConnectivity { err },
234            _ => Self::Generic {
235                err: value.to_string(),
236            },
237        }
238    }
239}
240
241impl From<anyhow::Error> for RedeemOnchainError {
242    fn from(err: anyhow::Error) -> Self {
243        Self::Generic {
244            err: err.to_string(),
245        }
246    }
247}
248
249impl From<SdkError> for RedeemOnchainError {
250    fn from(value: SdkError) -> Self {
251        match value {
252            SdkError::Generic { err } => Self::Generic { err },
253            SdkError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
254        }
255    }
256}
257
258/// Error returned by [crate::breez_services::BreezServices::receive_payment]
259#[derive(Debug, Error)]
260pub enum ReceivePaymentError {
261    /// This error is raised when a general error occurs not specific to other error variants
262    /// in this enum.
263    #[error("Generic: {err}")]
264    Generic { err: String },
265
266    /// This error is raised when the amount is zero or the amount does not cover
267    /// the cost to open a new channel.
268    #[error("Invalid amount: {err}")]
269    InvalidAmount { err: String },
270
271    /// This error is raised when the lightning invoice cannot be parsed.
272    #[error("Invalid invoice: {err}")]
273    InvalidInvoice { err: String },
274
275    /// This error is raised when the lightning invoice has passed it's expiry time.
276    #[error("Invoice expired: {err}")]
277    InvoiceExpired { err: String },
278
279    /// This error is raised by the node when no description has been set for the invoice.
280    #[error("Invoice no description: {err}")]
281    InvoiceNoDescription { err: String },
282
283    /// This error is raised when no routing hints were able to be added to the invoice
284    /// while trying to receive a payment.
285    #[error("No routing hints: {err}")]
286    InvoiceNoRoutingHints { err: String },
287
288    /// This error is raised by the node when an invoice is has already being created
289    /// using the same preimage.
290    #[error("Invoice preimage already exists: {err}")]
291    InvoicePreimageAlreadyExists { err: String },
292
293    /// This error is raised when a connection to an external service fails.
294    #[error("Service connectivity: {err}")]
295    ServiceConnectivity { err: String },
296}
297
298impl From<anyhow::Error> for ReceivePaymentError {
299    fn from(err: anyhow::Error) -> Self {
300        Self::Generic {
301            err: err.to_string(),
302        }
303    }
304}
305
306impl From<InvoiceError> for ReceivePaymentError {
307    fn from(value: InvoiceError) -> Self {
308        match value {
309            InvoiceError::Validation(err) => Self::InvalidInvoice { err },
310            _ => Self::Generic {
311                err: value.to_string(),
312            },
313        }
314    }
315}
316
317impl From<NodeError> for ReceivePaymentError {
318    fn from(value: NodeError) -> Self {
319        match value {
320            NodeError::InvoiceExpired(err) => Self::InvoiceExpired { err },
321            NodeError::InvoiceNoDescription(err) => Self::InvoiceNoDescription { err },
322            NodeError::InvoicePreimageAlreadyExists(err) => {
323                Self::InvoicePreimageAlreadyExists { err }
324            }
325            NodeError::ServiceConnectivity(err) => Self::ServiceConnectivity { err },
326            _ => Self::Generic {
327                err: value.to_string(),
328            },
329        }
330    }
331}
332
333impl From<PersistError> for ReceivePaymentError {
334    fn from(err: PersistError) -> Self {
335        Self::Generic {
336            err: err.to_string(),
337        }
338    }
339}
340
341impl From<SdkError> for ReceivePaymentError {
342    fn from(value: SdkError) -> Self {
343        match value {
344            SdkError::Generic { err } => Self::Generic { err },
345            SdkError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
346        }
347    }
348}
349
350/// General error returned by the SDK
351#[derive(Debug, Error)]
352pub enum SdkError {
353    /// This error is raised when a general error occurs not specific to other error variants
354    /// in this enum.
355    #[error("Generic: {err}")]
356    Generic { err: String },
357
358    /// This error is raised when a connection to an external service fails.
359    #[error("Service connectivity: {err}")]
360    ServiceConnectivity { err: String },
361}
362
363impl SdkError {
364    pub(crate) fn generic(err: &str) -> Self {
365        Self::Generic {
366            err: err.to_string(),
367        }
368    }
369
370    pub(crate) fn service_connectivity(err: &str) -> Self {
371        Self::ServiceConnectivity {
372            err: err.to_string(),
373        }
374    }
375}
376
377impl From<ServiceConnectivityError> for SdkError {
378    fn from(value: ServiceConnectivityError) -> Self {
379        Self::ServiceConnectivity { err: value.err }
380    }
381}
382
383impl From<anyhow::Error> for SdkError {
384    fn from(err: anyhow::Error) -> Self {
385        Self::Generic {
386            err: err.to_string(),
387        }
388    }
389}
390
391impl From<crate::bitcoin::hashes::hex::Error> for SdkError {
392    fn from(err: crate::bitcoin::hashes::hex::Error) -> Self {
393        Self::Generic {
394            err: err.to_string(),
395        }
396    }
397}
398
399impl From<InvoiceError> for SdkError {
400    fn from(err: InvoiceError) -> Self {
401        Self::Generic {
402            err: err.to_string(),
403        }
404    }
405}
406
407impl From<LnUrlError> for SdkError {
408    fn from(err: LnUrlError) -> Self {
409        SdkError::Generic {
410            err: err.to_string(),
411        }
412    }
413}
414
415impl From<NodeError> for SdkError {
416    fn from(value: NodeError) -> Self {
417        match value {
418            NodeError::ServiceConnectivity(err) => Self::ServiceConnectivity { err },
419            _ => Self::Generic {
420                err: value.to_string(),
421            },
422        }
423    }
424}
425
426impl From<PersistError> for SdkError {
427    fn from(err: PersistError) -> Self {
428        Self::Generic {
429            err: err.to_string(),
430        }
431    }
432}
433
434impl From<ReverseSwapError> for SdkError {
435    fn from(value: ReverseSwapError) -> Self {
436        match value {
437            ReverseSwapError::ServiceConnectivity(err) => Self::ServiceConnectivity { err },
438            _ => Self::Generic {
439                err: value.to_string(),
440            },
441        }
442    }
443}
444
445impl From<serde_json::Error> for SdkError {
446    fn from(err: serde_json::Error) -> Self {
447        Self::Generic {
448            err: err.to_string(),
449        }
450    }
451}
452
453impl From<tonic::transport::Error> for SdkError {
454    fn from(err: tonic::transport::Error) -> Self {
455        Self::ServiceConnectivity {
456            err: sdk_common::tonic_wrap::TransportError(err).to_string(),
457        }
458    }
459}
460
461impl From<tonic::Status> for SdkError {
462    fn from(err: tonic::Status) -> Self {
463        Self::Generic {
464            err: sdk_common::tonic_wrap::Status(err).to_string(),
465        }
466    }
467}
468
469impl From<SendPaymentError> for SdkError {
470    fn from(value: SendPaymentError) -> Self {
471        match value {
472            SendPaymentError::AlreadyPaid => Self::Generic {
473                err: value.to_string(),
474            },
475            SendPaymentError::Generic { err }
476            | SendPaymentError::InvalidAmount { err }
477            | SendPaymentError::InvalidInvoice { err }
478            | SendPaymentError::InvalidNetwork { err }
479            | SendPaymentError::InvoiceExpired { err }
480            | SendPaymentError::PaymentFailed { err }
481            | SendPaymentError::PaymentTimeout { err }
482            | SendPaymentError::RouteNotFound { err }
483            | SendPaymentError::RouteTooExpensive { err }
484            | SendPaymentError::InsufficientBalance { err } => Self::Generic { err },
485            SendPaymentError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
486        }
487    }
488}
489
490impl From<ReceiveSwapError> for SdkError {
491    fn from(value: ReceiveSwapError) -> Self {
492        match value {
493            ReceiveSwapError::ServiceConnectivity(err) => Self::ServiceConnectivity { err },
494            _ => Self::Generic {
495                err: value.to_string(),
496            },
497        }
498    }
499}
500
501/// Error returned by [crate::breez_services::BreezServices::send_onchain]
502#[derive(Debug, Error)]
503pub enum SendOnchainError {
504    /// This error is raised when a general error occurs not specific to other error variants
505    /// in this enum.
506    #[error("Generic: {err}")]
507    Generic { err: String },
508
509    /// This error is raised when the [crate::models::SendOnchainRequest::onchain_recipient_address]
510    /// is invalid.
511    #[error("Invalid destination address: {err}")]
512    InvalidDestinationAddress { err: String },
513
514    /// This error is raised when a reverse swap is attempted with a send amount that is not
515    /// in the [crate::BreezServices::onchain_payment_limits] range.
516    #[error("Send amount is out of range")]
517    OutOfRange,
518
519    /// This error is raised when attempting to make a pay the HODL invoice by the node fails.
520    #[error("Payment failed: {err}")]
521    PaymentFailed { err: String },
522
523    /// This error is raised when attempting to pay the HODL invoice takes too long.
524    #[error("Payment timeout: {err}")]
525    PaymentTimeout { err: String },
526
527    /// This error is raised when a connection to an external service fails.
528    #[error("Service connectivity: {err}")]
529    ServiceConnectivity { err: String },
530}
531impl SendOnchainError {
532    pub(crate) fn generic(err: &str) -> Self {
533        Self::Generic {
534            err: err.to_string(),
535        }
536    }
537}
538
539impl From<anyhow::Error> for SendOnchainError {
540    fn from(err: anyhow::Error) -> Self {
541        Self::Generic {
542            err: err.to_string(),
543        }
544    }
545}
546
547impl From<NodeError> for SendOnchainError {
548    fn from(value: NodeError) -> Self {
549        match value {
550            NodeError::PaymentFailed(err) => Self::PaymentFailed { err },
551            NodeError::PaymentTimeout(err) => Self::PaymentTimeout { err },
552            NodeError::ServiceConnectivity(err) => Self::ServiceConnectivity { err },
553            _ => Self::Generic {
554                err: value.to_string(),
555            },
556        }
557    }
558}
559
560impl From<SdkError> for SendOnchainError {
561    fn from(value: SdkError) -> Self {
562        match value {
563            SdkError::Generic { err } => Self::Generic { err },
564            SdkError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
565        }
566    }
567}
568
569impl From<ReverseSwapError> for SendOnchainError {
570    fn from(value: ReverseSwapError) -> Self {
571        match value {
572            ReverseSwapError::InvalidDestinationAddress(err) => {
573                Self::InvalidDestinationAddress { err }
574            }
575            ReverseSwapError::ServiceConnectivity(err) => Self::ServiceConnectivity { err },
576            ReverseSwapError::Node(err) => err.into(),
577            _ => Self::Generic {
578                err: value.to_string(),
579            },
580        }
581    }
582}
583
584impl From<PersistError> for SendOnchainError {
585    fn from(err: PersistError) -> Self {
586        Self::Generic {
587            err: err.to_string(),
588        }
589    }
590}
591
592/// Error returned by [crate::breez_services::BreezServices::send_payment] and [crate::breez_services::BreezServices::send_spontaneous_payment]
593#[derive(Clone, Debug, Error)]
594pub enum SendPaymentError {
595    /// This error is raised when attempting to pay an invoice that has already being paid.
596    #[error("Invoice already paid")]
597    AlreadyPaid,
598
599    /// This error is raised when a general error occurs not specific to other error variants
600    /// in this enum.
601    #[error("Generic: {err}")]
602    Generic { err: String },
603
604    /// This error is raised when the amount from the parsed invoice is not set and there is
605    /// no provided amount in [crate::models::SendPaymentRequest::amount_msat].
606    #[error("Invalid amount: {err}")]
607    InvalidAmount { err: String },
608
609    /// This error is raised when the lightning invoice cannot be parsed.
610    #[error("Invalid invoice: {err}")]
611    InvalidInvoice { err: String },
612
613    /// This error is raised when the lightning invoice is for a different Bitcoin network.
614    #[error("Invalid network: {err}")]
615    InvalidNetwork { err: String },
616
617    /// This error is raised when the lightning invoice has passed it's expiry time.
618    #[error("Invoice expired: {err}")]
619    InvoiceExpired { err: String },
620
621    /// This error is raised when attempting to make a payment by the node fails.
622    #[error("Payment failed: {err}")]
623    PaymentFailed { err: String },
624
625    /// This error is raised when attempting to make a payment takes too long.
626    #[error("Payment timeout: {err}")]
627    PaymentTimeout { err: String },
628
629    /// This error is raised when no route can be found when attempting to make a
630    /// payment by the node.
631    #[error("Route not found: {err}")]
632    RouteNotFound { err: String },
633
634    /// This error is raised when the route is considered too expensive when
635    /// attempting to make a payment by the node.
636    #[error("Route too expensive: {err}")]
637    RouteTooExpensive { err: String },
638
639    /// This error is raised when a connection to an external service fails.
640    #[error("Service connectivity: {err}")]
641    ServiceConnectivity { err: String },
642
643    /// This error is raised when the node does not have enough funds to make the payment.
644    #[error("Insufficient balance: {err}")]
645    InsufficientBalance { err: String },
646}
647
648impl From<anyhow::Error> for SendPaymentError {
649    fn from(err: anyhow::Error) -> Self {
650        Self::Generic {
651            err: err.to_string(),
652        }
653    }
654}
655
656impl From<InvoiceError> for SendPaymentError {
657    fn from(value: InvoiceError) -> Self {
658        match value {
659            InvoiceError::InvalidNetwork(err) => Self::InvalidNetwork { err },
660            InvoiceError::Validation(err) => Self::InvalidInvoice { err },
661            InvoiceError::Generic(err) => Self::Generic { err },
662        }
663    }
664}
665
666impl From<NodeError> for SendPaymentError {
667    fn from(value: NodeError) -> Self {
668        match value {
669            NodeError::InvoiceExpired(err) => Self::InvoiceExpired { err },
670            NodeError::PaymentFailed(err) => Self::PaymentFailed { err },
671            NodeError::PaymentTimeout(err) => Self::PaymentTimeout { err },
672            NodeError::RouteNotFound(err) => Self::RouteNotFound { err },
673            NodeError::RouteTooExpensive(err) => Self::RouteTooExpensive { err },
674            NodeError::ServiceConnectivity(err) => Self::ServiceConnectivity { err },
675            _ => Self::Generic {
676                err: value.to_string(),
677            },
678        }
679    }
680}
681
682impl From<PersistError> for SendPaymentError {
683    fn from(err: PersistError) -> Self {
684        Self::Generic {
685            err: err.to_string(),
686        }
687    }
688}
689
690impl From<SdkError> for SendPaymentError {
691    fn from(value: SdkError) -> Self {
692        match value {
693            SdkError::Generic { err } => Self::Generic { err },
694            SdkError::ServiceConnectivity { err } => Self::ServiceConnectivity { err },
695        }
696    }
697}
698
699impl From<SystemTimeError> for SendPaymentError {
700    fn from(err: SystemTimeError) -> Self {
701        Self::Generic {
702            err: err.to_string(),
703        }
704    }
705}