use serde_json::Value;
pub type Result<T, E = Error> = std::result::Result<T, E>;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error("transport error: {0}")]
Transport(String),
#[error("rpc error {code}: {message}{}", fmt_data(.data))]
Rpc {
code: i64,
message: String,
data: Option<Value>,
},
#[error("failed to decode `{context}`: {source}")]
Decode {
context: String,
#[source]
source: serde_json::Error,
},
#[error("normalize error: {0}")]
Normalize(String),
#[error("chain mismatch: expected chain id {expected}, but the RPC serves {actual}")]
ChainMismatch { expected: u64, actual: u64 },
#[error("unsupported: {0}")]
Unsupported(String),
}
impl Error {
pub(crate) fn decode(context: impl Into<String>, source: serde_json::Error) -> Self {
Error::Decode {
context: context.into(),
source,
}
}
pub fn is_transport(&self) -> bool {
matches!(self, Error::Transport(_))
}
}
fn fmt_data(data: &Option<Value>) -> String {
match data {
None | Some(Value::Null) => String::new(),
Some(Value::String(s)) => format!(" ({s})"),
Some(other) => format!(" ({other})"),
}
}