1use crate::dto::WebAppErrorResponse;
2use aelf_crypto::CryptoError;
3use std::fmt;
4use thiserror::Error;
5
6#[derive(Debug, Error)]
7#[error("{message}")]
8pub struct RequestError {
9 pub message: String,
10 pub request_id: Option<String>,
11 pub endpoint: Option<String>,
12 pub status: Option<u16>,
13 pub chain_code: Option<String>,
14 pub details: Option<String>,
15}
16
17#[derive(Debug, Error)]
18pub enum AElfError {
19 #[error(transparent)]
20 Request(Box<RequestError>),
21 #[error("unexpected response: {0}")]
22 UnexpectedResponse(String),
23 #[error("invalid config: {0}")]
24 InvalidConfig(String),
25 #[error("missing field: {0}")]
26 MissingField(&'static str),
27 #[error("crypto error: {0}")]
28 Crypto(#[from] CryptoError),
29 #[error("hex error: {0}")]
30 Hex(#[from] hex::FromHexError),
31 #[error("base64 decode error: {0}")]
32 Base64(#[from] base64::DecodeError),
33 #[error("json error: {0}")]
34 Json(#[from] serde_json::Error),
35 #[cfg(feature = "native-http")]
36 #[error("http error: {0}")]
37 Http(#[from] reqwest::Error),
38 #[error("protobuf encode error: {0}")]
39 ProtobufEncode(#[from] prost::EncodeError),
40 #[error("protobuf decode error: {0}")]
41 ProtobufDecode(#[from] prost::DecodeError),
42}
43
44impl AElfError {
45 pub fn request(message: impl Into<String>, endpoint: Option<String>) -> Self {
46 Self::Request(Box::new(RequestError {
47 message: message.into(),
48 request_id: None,
49 endpoint,
50 status: None,
51 chain_code: None,
52 details: None,
53 }))
54 }
55
56 #[cfg(feature = "native-http")]
57 pub(crate) fn from_response(
58 endpoint: String,
59 status: reqwest::StatusCode,
60 request_id: Option<String>,
61 raw_body: &str,
62 ) -> Self {
63 let parsed = serde_json::from_str::<WebAppErrorResponse>(raw_body).ok();
64 let (message, chain_code, details) = match parsed {
65 Some(error) => (
66 error.error.message,
67 Some(error.error.code),
68 error.error.details,
69 ),
70 None => (
71 format!("request failed with status {}: {raw_body}", status),
72 None,
73 None,
74 ),
75 };
76
77 Self::Request(Box::new(RequestError {
78 message,
79 request_id,
80 endpoint: Some(endpoint),
81 status: Some(status.as_u16()),
82 chain_code,
83 details,
84 }))
85 }
86}
87
88impl fmt::Display for WebAppErrorResponse {
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 write!(f, "{} ({})", self.error.message, self.error.code)
91 }
92}