ethers_ccip_read/
errors.rs

1use ethers_core::utils::hex::FromHexError;
2use std::collections::HashMap;
3use std::fmt::Display;
4
5use ethers_providers::{Middleware, MiddlewareError};
6use thiserror::Error;
7
8#[allow(clippy::enum_variant_names)]
9#[derive(Error, Debug)]
10pub enum CCIPRequestError {
11    // gateway supplied error
12    #[error("Gateway error: {0}")]
13    GatewayError(String),
14
15    // when gateway either fails to respond with an expected format
16    #[error("Gateway format error: {0}")]
17    GatewayFormatError(String),
18
19    #[error("HTTP error: {0}")]
20    HTTPError(#[from] reqwest::Error),
21}
22
23#[derive(Debug)]
24pub struct CCIPFetchError(pub(crate) HashMap<String, Vec<String>>);
25
26/// Handle CCIP-Read middlware specific errors.
27#[derive(Error, Debug)]
28pub enum CCIPReadMiddlewareError<M: Middleware> {
29    /// Thrown when the internal middleware errors
30    #[error("{0}")]
31    MiddlewareError(M::Error),
32
33    #[error("Error(s) during CCIP fetch: {0}")]
34    FetchError(CCIPFetchError),
35
36    #[error("CCIP Read sender did not match {}", sender)]
37    SenderError { sender: String },
38
39    #[error("CCIP Read no provided URLs")]
40    GatewayNotFoundError,
41
42    #[error("CCIP Read exceeded maximum redirections")]
43    MaxRedirectionError,
44
45    /// Invalid reverse ENS name
46    #[error("Reversed ens name not pointing to itself: {0}")]
47    EnsNotOwned(String),
48
49    #[error("Error(s) during parsing avatar url: {0}")]
50    URLParseError(String),
51
52    #[error("Error(s) during NFT ownership verification: {0}")]
53    NFTOwnerError(String),
54
55    #[error("Error(s) decoding revert bytes: {0}")]
56    HexDecodeError(#[from] FromHexError),
57
58    #[error("Error(s) decoding abi: {0}")]
59    AbiDecodeError(#[from] ethers_core::abi::Error),
60
61    #[error("Unsupported URL scheme")]
62    UnsupportedURLSchemeError,
63}
64
65impl<M: Middleware> MiddlewareError for CCIPReadMiddlewareError<M> {
66    type Inner = M::Error;
67
68    fn from_err(src: M::Error) -> Self {
69        CCIPReadMiddlewareError::MiddlewareError(src)
70    }
71
72    fn as_inner(&self) -> Option<&Self::Inner> {
73        match self {
74            CCIPReadMiddlewareError::MiddlewareError(e) => Some(e),
75            _ => None,
76        }
77    }
78}
79
80impl Display for CCIPFetchError {
81    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
82        let mut errors = f.debug_struct("CCIPFetchError");
83
84        for (url, messages) in self.0.iter() {
85            errors.field(url, messages);
86        }
87
88        errors.finish()
89    }
90}