* Don't use move semantics if not needed (#8793) * SDK: Deboilerplate `TransportError` with thiserror * Enable interchange between `TransportError` and `ClientError` * SDK: Retval consistency between `Client` and `AsyncClient` traits * Client: Introduce/use `Result` type * Client: Remove unused `RpcResponseIn` type * Client: Rename `RpcResponse` to more appropriate `RpcResult` * Client: Death to `io::Result` return types * Client: Struct-ify `ClientError` * Client: Add optional `command` parameter to `ClientError` * RpcClient: Stop abusing `io::Error` (low-fruit) * ClientError: Use `thiserror`'s `Display` impl * Extend `RpcError`'s utility * RpcClient: Stop abusing `io::Error` (the rest) * CLI: Shim `main()` so we can `Display` format errors * claputils: format input validator errors with `Display` They are intended to be displayed to users * SDK: `thiserror` for hash and sig parse erros * Keygen: Shim main to format errors with `Display` * SDK: `thiserror` for `InstructionError` * CLI: `thiserror` for `CliError` * CLI: Format user messages with `Display` * Client: Tweak `Display` for `ClientError` * RpcClient: Improve messaging when TX cannot be confirmed * fu death io res retval * CLI/Keygen - fix shell return value on error * Tweak `InstructionError` `Display` messages as per review * Cleanup hackjob return code fix * Embrace that which you hate most * Too much... Co-authored-by: Jack May <jack@solana.com>
162 lines
3.9 KiB
Rust
162 lines
3.9 KiB
Rust
use crate::rpc_request;
|
|
use solana_sdk::{
|
|
signature::SignerError, transaction::TransactionError, transport::TransportError,
|
|
};
|
|
use std::io;
|
|
use thiserror::Error;
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum ClientErrorKind {
|
|
#[error(transparent)]
|
|
Io(#[from] io::Error),
|
|
#[error(transparent)]
|
|
Reqwest(#[from] reqwest::Error),
|
|
#[error(transparent)]
|
|
RpcError(#[from] rpc_request::RpcError),
|
|
#[error(transparent)]
|
|
SerdeJson(#[from] serde_json::error::Error),
|
|
#[error(transparent)]
|
|
SigningError(#[from] SignerError),
|
|
#[error(transparent)]
|
|
TransactionError(#[from] TransactionError),
|
|
#[error("Custom: {0}")]
|
|
Custom(String),
|
|
}
|
|
|
|
impl From<TransportError> for ClientErrorKind {
|
|
fn from(err: TransportError) -> Self {
|
|
match err {
|
|
TransportError::IoError(err) => Self::Io(err),
|
|
TransportError::TransactionError(err) => Self::TransactionError(err),
|
|
TransportError::Custom(err) => Self::Custom(err),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Into<TransportError> for ClientErrorKind {
|
|
fn into(self) -> TransportError {
|
|
match self {
|
|
Self::Io(err) => TransportError::IoError(err),
|
|
Self::TransactionError(err) => TransportError::TransactionError(err),
|
|
Self::Reqwest(err) => TransportError::Custom(format!("{:?}", err)),
|
|
Self::RpcError(err) => TransportError::Custom(format!("{:?}", err)),
|
|
Self::SerdeJson(err) => TransportError::Custom(format!("{:?}", err)),
|
|
Self::SigningError(err) => TransportError::Custom(format!("{:?}", err)),
|
|
Self::Custom(err) => TransportError::Custom(format!("{:?}", err)),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Error, Debug)]
|
|
#[error("{kind}")]
|
|
pub struct ClientError {
|
|
command: Option<&'static str>,
|
|
#[source]
|
|
#[error(transparent)]
|
|
kind: ClientErrorKind,
|
|
}
|
|
|
|
impl ClientError {
|
|
pub fn new_with_command(kind: ClientErrorKind, command: &'static str) -> Self {
|
|
Self {
|
|
command: Some(command),
|
|
kind,
|
|
}
|
|
}
|
|
|
|
pub fn into_with_command(self, command: &'static str) -> Self {
|
|
Self {
|
|
command: Some(command),
|
|
..self
|
|
}
|
|
}
|
|
|
|
pub fn command(&self) -> Option<&'static str> {
|
|
self.command
|
|
}
|
|
|
|
pub fn kind(&self) -> &ClientErrorKind {
|
|
&self.kind
|
|
}
|
|
}
|
|
|
|
impl From<ClientErrorKind> for ClientError {
|
|
fn from(kind: ClientErrorKind) -> Self {
|
|
Self {
|
|
command: None,
|
|
kind,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<TransportError> for ClientError {
|
|
fn from(err: TransportError) -> Self {
|
|
Self {
|
|
command: None,
|
|
kind: err.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Into<TransportError> for ClientError {
|
|
fn into(self) -> TransportError {
|
|
self.kind.into()
|
|
}
|
|
}
|
|
|
|
impl From<std::io::Error> for ClientError {
|
|
fn from(err: std::io::Error) -> Self {
|
|
Self {
|
|
command: None,
|
|
kind: err.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<reqwest::Error> for ClientError {
|
|
fn from(err: reqwest::Error) -> Self {
|
|
Self {
|
|
command: None,
|
|
kind: err.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<rpc_request::RpcError> for ClientError {
|
|
fn from(err: rpc_request::RpcError) -> Self {
|
|
Self {
|
|
command: None,
|
|
kind: err.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<serde_json::error::Error> for ClientError {
|
|
fn from(err: serde_json::error::Error) -> Self {
|
|
Self {
|
|
command: None,
|
|
kind: err.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<SignerError> for ClientError {
|
|
fn from(err: SignerError) -> Self {
|
|
Self {
|
|
command: None,
|
|
kind: err.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<TransactionError> for ClientError {
|
|
fn from(err: TransactionError) -> Self {
|
|
Self {
|
|
command: None,
|
|
kind: err.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub type Result<T> = std::result::Result<T, ClientError>;
|