Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

feature: bubble up jsonrpc error response via trait #2122

Closed
wants to merge 10 commits into from

Conversation

prestwich
Copy link
Collaborator

Motivation

Currently there's no way to get JSON-RPC error response out of the provider or middleware error. They're type-erased in the ProviderError.

Solution

This adds a ClientError trait which helps cast ProviderError to JsonRpcError.

I consider this to be a bit of an unpleasant kludge. I'm not sure it should be merged. Hypothetically this would allow us to access and decode revert data from contracts tho, which is definitely a big user need.

PR Checklist

  • Added Tests
  • Added Documentation
  • Updated the changelog
  • Breaking changes

@prestwich prestwich added the enhancement New feature or request label Feb 7, 2023
@prestwich prestwich self-assigned this Feb 7, 2023
@prestwich
Copy link
Collaborator Author

okay this now provides 2 traits:

  • RpcError, which covers ProviderError and all transports
    • exposes as_error_response for possible downcast to JsonRpcError
  • MiddlewareError which covers ProviderError and up
    • replaces FromErr
    • provides functions for converting to/from Inner
    • provides functions for converting to/from ProviderError
    • provides functions for downcasting to an error response

the core idea here is that ProviderError is a hingepoint in the lib. everything below it (except JsonRpcError responses) is implementation details and should be hidden. everything above it is MiddlewareError, and should be stacked like middleware are stacked

if the direction is good, I'll go through and update all the docs

@prestwich
Copy link
Collaborator Author

CI failures are unrelated. This is ready for review cc @gakonst @mattsse

@prestwich prestwich marked this pull request as ready for review February 16, 2023 23:45
@gakonst gakonst force-pushed the prestwich/client-error-kludge branch from cfdaad6 to a6e592b Compare February 16, 2023 23:55
Copy link
Owner

@gakonst gakonst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice and useful, basically the same pattern that middleware uses to give access to inner layers but for errors, to avoid the nested match abomination...

(We could/shoudl've done the refactor in a separate PR but OK w/ me)

Comment on lines 6 to 65
pub trait RpcError: Error + Debug + Send + Sync {
fn as_error_response(&self) -> Option<&JsonRpcError>;
}

pub trait MiddlewareError: Error + Sized + Send + Sync {
type Inner: MiddlewareError;

fn from_err(e: Self::Inner) -> Self;

fn as_inner(&self) -> Option<&Self::Inner>;

fn as_provider_error(&self) -> Option<&ProviderError> {
self.as_inner()?.as_provider_error()
}

fn from_provider_err(p: ProviderError) -> Self {
Self::from_err(Self::Inner::from_provider_err(p))
}

fn as_error_response(&self) -> Option<&JsonRpcError> {
MiddlewareError::as_error_response(self.as_inner()?)
}
}

#[derive(Debug, Error)]
/// An error thrown when making a call to the provider
pub enum ProviderError {
/// An internal error in the JSON RPC Client
#[error("{0}")]
JsonRpcClientError(Box<dyn crate::RpcError + Send + Sync>),

/// An error during ENS name resolution
#[error("ens name not found: {0}")]
EnsError(String),

/// Invalid reverse ENS name
#[error("reverse ens name not pointing to itself: {0}")]
EnsNotOwned(String),

#[error(transparent)]
SerdeJson(#[from] serde_json::Error),

#[error(transparent)]
HexError(#[from] hex::FromHexError),

#[error(transparent)]
HTTPError(#[from] reqwest::Error),

#[error("custom error: {0}")]
CustomError(String),

#[error("unsupported RPC")]
UnsupportedRPC,

#[error("unsupported node client")]
UnsupportedNodeClient,

#[error("Attempted to sign a transaction with no available signer. Hint: did you mean to use a SignerMiddleware?")]
SignerUnavailable,
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

amazing

@gakonst
Copy link
Owner

gakonst commented Feb 17, 2023

Main question is: what breaking changes does this have? Seems like..none? If so, let's go ahead

@prestwich
Copy link
Collaborator Author

(We could/shoudl've done the refactor in a separate PR but OK w/ me)

I can break these into 2 if you want, shoulda done that in the first place tbh

Main question is: what breaking changes does this have? Seems like..none? If so, let's go ahead

the breaking changes are

  • 3rd-party custom transports need to implement RpcError for their errors
  • 3rd-party custom middleware need to change FromErr impls to MiddlewareError impls

@gakonst
Copy link
Owner

gakonst commented Feb 17, 2023

3rd-party custom transports need to implement RpcError for their errors
3rd-party custom middleware need to change FromErr impls to MiddlewareError impls

Sounds good. We'll need to update ethers-flashbots and ethers-fireblocks but otherwise should be good. Let's send it once @mattsse also takes a look. No need for splitting the refactor as it will generate conflicts.NVM sounds good.

@prestwich
Copy link
Collaborator Author

re-organization has been moved into #2159

@prestwich
Copy link
Collaborator Author

I went ahead and split, as it won't generate conflicts because that branch is based on this one 👍

I can also easily clean up any conflicts so lfg

Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, does this affect how the RetryProvider needs to check for serde/reqwest error?

@prestwich
Copy link
Collaborator Author

lgtm, does this affect how the RetryProvider needs to check for serde/reqwest error?

it really doesn't affect it at all. But now that you mention it, we could add as_serde_error() -> Option<&serde_json::Error> 🤔

@prestwich
Copy link
Collaborator Author

okay I added as_serde_error() and is_*_error() and a bunch of docs for the traits :)

@prestwich
Copy link
Collaborator Author

failures are unrelated and this is good to go 🎉

like other recent PRs, this is a breaking change, and will require action from 3rd-party crates

@gakonst
Copy link
Owner

gakonst commented Feb 20, 2023

supreseded #2159

@gakonst gakonst closed this Feb 20, 2023
@gakonst gakonst deleted the prestwich/client-error-kludge branch February 20, 2023 23:56
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants