switchgear_service/components/pool/
error.rs1use crate::api::service::{HasServiceErrorSource, ServiceErrorSource};
2use std::borrow::Cow;
3use std::fmt::{Display, Formatter};
4use thiserror::Error;
5
6#[derive(Error, Debug)]
7pub enum LnPoolErrorSourceKind {
8 #[error("CLN tonic gRPC error: {0}")]
9 ClnTonicError(crate::components::pool::cln::grpc::client::tonic::Status),
10 #[error("LND tonic gRPC error: {0}")]
11 LndTonicError(crate::components::pool::lnd::grpc::client::tonic::Status),
12 #[error("CLN transport connection error: {0}")]
13 ClnTransportError(crate::components::pool::cln::grpc::client::tonic::transport::Error),
14 #[error("LND transport connection error: {0}")]
15 LndTransportError(crate::components::pool::lnd::grpc::client::tonic::transport::Error),
16 #[error("LND connection error: {0}")]
17 LndConnectError(fedimint_tonic_lnd::ConnectError),
18 #[error("Generic Lightning pool operation failed")]
19 Generic,
20 #[error("invalid configuration for: {0}")]
21 InvalidConfiguration(String),
22 #[error("invalid credentials for {0}")]
23 InvalidCredentials(String),
24 #[error("invalid endpoint URI: {0}")]
25 InvalidEndpointUri(
26 crate::components::pool::cln::grpc::client::tonic::codegen::http::uri::InvalidUri,
27 ),
28 #[error("operation timed out")]
29 Timeout,
30}
31
32#[derive(Error, Debug)]
33pub struct LnPoolError {
34 context: Cow<'static, str>,
35 #[source]
36 source: LnPoolErrorSourceKind,
37 esource: ServiceErrorSource,
38}
39
40impl Display for LnPoolError {
41 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
42 write!(
43 f,
44 "LnPoolError: while {}: {}",
45 self.context.as_ref(),
46 self.source
47 )
48 }
49}
50
51impl LnPoolError {
52 pub fn new<C: Into<Cow<'static, str>>>(
53 source: LnPoolErrorSourceKind,
54 esource: ServiceErrorSource,
55 context: C,
56 ) -> Self {
57 Self {
58 context: context.into(),
59 source,
60 esource,
61 }
62 }
63
64 pub fn from_invalid_configuration<C: Into<Cow<'static, str>>>(
65 source: C,
66 esource: ServiceErrorSource,
67 context: C,
68 ) -> Self {
69 Self::new(
70 LnPoolErrorSourceKind::InvalidConfiguration(source.into().to_string()),
71 esource,
72 context.into(),
73 )
74 }
75
76 pub fn from_invalid_credentials<C: Into<Cow<'static, str>>>(
77 source: C,
78 esource: ServiceErrorSource,
79 context: C,
80 ) -> Self {
81 Self::new(
82 LnPoolErrorSourceKind::InvalidCredentials(source.into().to_string()),
83 esource,
84 context.into(),
85 )
86 }
87
88 pub fn from_cln_invalid_endpoint_uri<C: Into<Cow<'static, str>>>(
89 invalid_uri: crate::components::pool::cln::grpc::client::tonic::codegen::http::uri::InvalidUri,
90 esource: ServiceErrorSource,
91 context: C,
92 ) -> Self {
93 Self::new(
94 LnPoolErrorSourceKind::InvalidEndpointUri(invalid_uri),
95 esource,
96 context.into(),
97 )
98 }
99
100 pub fn from_cln_tonic_error<C: Into<Cow<'static, str>>>(
101 source: crate::components::pool::cln::grpc::client::tonic::Status,
102 context: C,
103 ) -> Self {
104 let esource = Self::from_cln_tonic_code(source.code());
105 Self::new(
106 LnPoolErrorSourceKind::ClnTonicError(source),
107 esource,
108 context,
109 )
110 }
111
112 pub fn from_cln_tonic_error_with_esource<C: Into<Cow<'static, str>>>(
113 source: crate::components::pool::cln::grpc::client::tonic::Status,
114 esource: ServiceErrorSource,
115 context: C,
116 ) -> Self {
117 Self::new(
118 LnPoolErrorSourceKind::ClnTonicError(source),
119 esource,
120 context,
121 )
122 }
123
124 pub fn from_lnd_tonic_error<C: Into<Cow<'static, str>>>(
125 source: crate::components::pool::lnd::grpc::client::tonic::Status,
126 context: C,
127 ) -> Self {
128 let esource = Self::from_lnd_tonic_code(source.code());
129
130 Self::new(
131 LnPoolErrorSourceKind::LndTonicError(source),
132 esource,
133 context,
134 )
135 }
136
137 pub fn from_lnd_tonic_error_with_esource<C: Into<Cow<'static, str>>>(
138 source: crate::components::pool::lnd::grpc::client::tonic::Status,
139 esource: ServiceErrorSource,
140 context: C,
141 ) -> Self {
142 Self::new(
143 LnPoolErrorSourceKind::LndTonicError(source),
144 esource,
145 context,
146 )
147 }
148
149 pub fn from_cln_transport_error<C: Into<Cow<'static, str>>>(
150 source: crate::components::pool::cln::grpc::client::tonic::transport::Error,
151 esource: ServiceErrorSource,
152 context: C,
153 ) -> Self {
154 Self::new(
155 LnPoolErrorSourceKind::ClnTransportError(source),
156 esource,
157 context,
158 )
159 }
160
161 pub fn from_lnd_connect_error<C: Into<Cow<'static, str>>>(
162 source: fedimint_tonic_lnd::ConnectError,
163 esource: ServiceErrorSource,
164 context: C,
165 ) -> Self {
166 Self::new(
167 LnPoolErrorSourceKind::LndConnectError(source),
168 esource,
169 context,
170 )
171 }
172
173 pub fn from_timeout_error<C: Into<Cow<'static, str>>>(
174 esource: ServiceErrorSource,
175 context: C,
176 ) -> Self {
177 Self::new(LnPoolErrorSourceKind::Timeout, esource, context)
178 }
179
180 pub fn context(&self) -> &str {
181 self.context.as_ref()
182 }
183
184 pub fn source(&self) -> &LnPoolErrorSourceKind {
185 &self.source
186 }
187
188 pub fn esource(&self) -> ServiceErrorSource {
189 self.esource
190 }
191
192 pub fn from_cln_tonic_code(
193 code: crate::components::pool::cln::grpc::client::tonic::Code,
194 ) -> ServiceErrorSource {
195 match code {
196 crate::components::pool::cln::grpc::client::tonic::Code::InvalidArgument
197 | crate::components::pool::cln::grpc::client::tonic::Code::OutOfRange => {
198 ServiceErrorSource::Downstream
199 }
200
201 _ => ServiceErrorSource::Upstream,
202 }
203 }
204
205 pub fn from_lnd_tonic_code(
206 code: crate::components::pool::lnd::grpc::client::tonic::Code,
207 ) -> ServiceErrorSource {
208 match code {
209 crate::components::pool::lnd::grpc::client::tonic::Code::OutOfRange
210 | crate::components::pool::lnd::grpc::client::tonic::Code::AlreadyExists => {
211 ServiceErrorSource::Downstream
212 }
213
214 _ => ServiceErrorSource::Upstream,
215 }
216 }
217}
218
219impl HasServiceErrorSource for LnPoolError {
220 fn get_service_error_source(&self) -> ServiceErrorSource {
221 self.esource
222 }
223}