use crate::types;
use derive_more::From;
use thiserror::Error;
use tonic::metadata::errors::InvalidMetadataValue;
pub use tonic::transport::{Endpoint, Error};
#[derive(Error, Debug)]
pub enum RPCError {
#[error("Call failed: {0}")]
CallError(#[from] tonic::Status),
#[error(transparent)]
InvalidMetadata(#[from] InvalidMetadataValue),
#[error("Error parsing JSON result: {0}")]
ParseError(#[from] anyhow::Error),
}
impl From<serde_json::Error> for RPCError {
fn from(x: serde_json::Error) -> Self {
Self::ParseError(x.into())
}
}
impl From<semver::Error> for RPCError {
fn from(x: semver::Error) -> Self {
Self::ParseError(x.into())
}
}
impl RPCError {
pub fn is_invalid_argument(&self) -> bool {
match self {
RPCError::CallError(e) => {
matches!(e.code(), tonic::Code::InvalidArgument)
}
RPCError::InvalidMetadata(_) => false,
RPCError::ParseError(_) => false,
}
}
pub fn is_duplicate(&self) -> bool {
match self {
RPCError::CallError(e) => {
matches!(e.code(), tonic::Code::AlreadyExists)
}
RPCError::InvalidMetadata(_) => false,
RPCError::ParseError(_) => false,
}
}
}
#[derive(Error, Debug)]
pub enum QueryError {
#[error("RPC error: {0}")]
RPCError(#[from] RPCError),
#[error("Requested object not found.")]
NotFound,
}
impl QueryError {
pub fn is_not_found(&self) -> bool {
match self {
QueryError::RPCError(c) => {
if let RPCError::CallError(ce) = c {
ce.code() == tonic::Code::NotFound
} else {
false
}
}
QueryError::NotFound => true,
}
}
}
impl From<tonic::Status> for QueryError {
fn from(s: tonic::Status) -> Self {
Self::RPCError(s.into())
}
}
impl From<InvalidMetadataValue> for QueryError {
fn from(s: InvalidMetadataValue) -> Self {
Self::RPCError(s.into())
}
}
pub type RPCResult<A> = Result<A, RPCError>;
pub type QueryResult<A> = Result<A, QueryError>;
#[derive(Clone, Copy, Debug, From)]
pub enum BlocksAtHeightInput {
Absolute {
height: types::AbsoluteBlockHeight,
},
Relative {
genesis_index: types::GenesisIndex,
height: types::BlockHeight,
restrict: bool,
},
}