From 8916d5de20e19e94fe04100e1893b014f5874a1f Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 19 Oct 2022 18:19:44 +0300 Subject: [PATCH 1/4] error: `RpcError` with custom client error Signed-off-by: Alexandru Vasile --- subxt/src/client/online_client.rs | 2 +- subxt/src/error.rs | 11 +++++++++-- subxt/src/rpc/jsonrpsee_impl.rs | 8 ++++---- subxt/src/tx/tx_progress.rs | 4 ++-- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/subxt/src/client/online_client.rs b/subxt/src/client/online_client.rs index 5fa9b3c898..b70d103db1 100644 --- a/subxt/src/client/online_client.rs +++ b/subxt/src/client/online_client.rs @@ -74,7 +74,7 @@ impl OnlineClient { pub async fn from_url(url: impl AsRef) -> Result, Error> { let client = jsonrpsee_helpers::ws_client(url.as_ref()) .await - .map_err(|e| crate::error::RpcError(e.to_string()))?; + .map_err(|e| crate::error::RpcError::ClientError(Box::new(e)))?; OnlineClient::from_rpc_client(Arc::new(client)).await } } diff --git a/subxt/src/error.rs b/subxt/src/error.rs index 04f1ed9134..b7445e4932 100644 --- a/subxt/src/error.rs +++ b/subxt/src/error.rs @@ -102,10 +102,17 @@ impl From for Error { } /// An RPC error. Since we are generic over the RPC client that is used, -/// the error is any custom string. +/// the error is boxed and could be casted. #[derive(Debug, thiserror::Error)] #[error("RPC error: {0}")] -pub struct RpcError(pub String); +pub enum RpcError { + // Dev note: We need the error to be safely sent between threads + // for `subscribe_to_block_headers_filling_in_gaps` and friends. + /// Error related to the RPC client. + ClientError(Box), + /// Custom error. + Custom(String), +} /// This is our attempt to decode a runtime DispatchError. We either /// successfully decode it into a [`ModuleError`], or we fail and keep diff --git a/subxt/src/rpc/jsonrpsee_impl.rs b/subxt/src/rpc/jsonrpsee_impl.rs index 6133faabf1..6327f010b8 100644 --- a/subxt/src/rpc/jsonrpsee_impl.rs +++ b/subxt/src/rpc/jsonrpsee_impl.rs @@ -35,7 +35,7 @@ impl RpcClientT for Client { let params = prep_params_for_jsonrpsee(params)?; let res = ClientT::request(self, method, Some(params)) .await - .map_err(|e| RpcError(e.to_string()))?; + .map_err(|e| RpcError::ClientError(Box::new(e)))?; Ok(res) }) } @@ -55,8 +55,8 @@ impl RpcClientT for Client { unsub, ) .await - .map_err(|e| RpcError(e.to_string()))? - .map_err(|e| RpcError(e.to_string())) + .map_err(|e| RpcError::ClientError(Box::new(e)))? + .map_err(|e| RpcError::ClientError(Box::new(e))) .boxed(); Ok(sub) }) @@ -77,7 +77,7 @@ fn prep_params_for_jsonrpsee( let arr = match val { Value::Array(arr) => Ok(arr), _ => { - Err(RpcError(format!( + Err(RpcError::Custom(format!( "RPC Params are expected to be an array but got {params}" ))) } diff --git a/subxt/src/tx/tx_progress.rs b/subxt/src/tx/tx_progress.rs index 9cbf752164..8f1e14bb5a 100644 --- a/subxt/src/tx/tx_progress.rs +++ b/subxt/src/tx/tx_progress.rs @@ -107,7 +107,7 @@ where _ => continue, } } - Err(RpcError("RPC subscription dropped".to_string()).into()) + Err(RpcError::Custom("RPC subscription dropped".into()).into()) } /// Wait for the transaction to be finalized, and return a [`TxInBlock`] @@ -133,7 +133,7 @@ where _ => continue, } } - Err(RpcError("RPC subscription dropped".to_string()).into()) + Err(RpcError::Custom("RPC subscription dropped".into()).into()) } /// Wait for the transaction to be finalized, and for the transaction events to indicate From 357725ae14a5306e15938b9e7319db444c654838 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 19 Oct 2022 19:04:45 +0300 Subject: [PATCH 2/4] error: Add `SubscriptionDropped` and panic on param errors Signed-off-by: Alexandru Vasile --- subxt/src/error.rs | 6 +++--- subxt/src/rpc/jsonrpsee_impl.rs | 20 ++++++++------------ subxt/src/rpc/rpc_client_t.rs | 5 +++++ subxt/src/tx/tx_progress.rs | 4 ++-- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/subxt/src/error.rs b/subxt/src/error.rs index b7445e4932..4e848b15a0 100644 --- a/subxt/src/error.rs +++ b/subxt/src/error.rs @@ -104,14 +104,14 @@ impl From for Error { /// An RPC error. Since we are generic over the RPC client that is used, /// the error is boxed and could be casted. #[derive(Debug, thiserror::Error)] -#[error("RPC error: {0}")] +#[error("RPC error")] pub enum RpcError { // Dev note: We need the error to be safely sent between threads // for `subscribe_to_block_headers_filling_in_gaps` and friends. /// Error related to the RPC client. ClientError(Box), - /// Custom error. - Custom(String), + /// The RPC subscription dropped. + SubscriptionDropped, } /// This is our attempt to decode a runtime DispatchError. We either diff --git a/subxt/src/rpc/jsonrpsee_impl.rs b/subxt/src/rpc/jsonrpsee_impl.rs index 6327f010b8..52b9a3e61e 100644 --- a/subxt/src/rpc/jsonrpsee_impl.rs +++ b/subxt/src/rpc/jsonrpsee_impl.rs @@ -32,7 +32,7 @@ impl RpcClientT for Client { params: Option>, ) -> RpcFuture<'a, Box> { Box::pin(async move { - let params = prep_params_for_jsonrpsee(params)?; + let params = prep_params_for_jsonrpsee(params); let res = ClientT::request(self, method, Some(params)) .await .map_err(|e| RpcError::ClientError(Box::new(e)))?; @@ -47,7 +47,7 @@ impl RpcClientT for Client { unsub: &'a str, ) -> RpcFuture<'a, RpcSubscription> { Box::pin(async move { - let params = prep_params_for_jsonrpsee(params)?; + let params = prep_params_for_jsonrpsee(params); let sub = SubscriptionClientT::subscribe::>( self, sub, @@ -65,22 +65,18 @@ impl RpcClientT for Client { // This is ugly; we have to encode to Value's to be compat with the jsonrpc interface. // Remove and simplify this once something like https://github.com/paritytech/jsonrpsee/issues/862 is in: -fn prep_params_for_jsonrpsee( - params: Option>, -) -> Result, RpcError> { +fn prep_params_for_jsonrpsee(params: Option>) -> ParamsSer<'static> { let params = match params { Some(params) => params, // No params? avoid any work and bail early. - None => return Ok(ParamsSer::Array(Vec::new())), + None => return ParamsSer::Array(Vec::new()), }; let val = serde_json::to_value(¶ms).expect("RawValue guarantees valid JSON"); let arr = match val { - Value::Array(arr) => Ok(arr), + Value::Array(arr) => arr, _ => { - Err(RpcError::Custom(format!( - "RPC Params are expected to be an array but got {params}" - ))) + panic!("RPC Params are expected to be an array but got {params}"); } - }?; - Ok(ParamsSer::Array(arr)) + }; + ParamsSer::Array(arr) } diff --git a/subxt/src/rpc/rpc_client_t.rs b/subxt/src/rpc/rpc_client_t.rs index 17f4ec9ab9..a92ec4b29d 100644 --- a/subxt/src/rpc/rpc_client_t.rs +++ b/subxt/src/rpc/rpc_client_t.rs @@ -20,6 +20,11 @@ pub use serde_json::value::RawValue; /// the caller. This is the case because we want the methods to be object-safe (which prohibits /// generics), and want to avoid any unnecessary allocations in serializing/deserializing /// parameters. +/// +/// # Note +/// +/// Implementations are free to panic if the provided parameters are not a valid +/// JSON Array. pub trait RpcClientT: Send + Sync + 'static { /// Make a raw request for which we expect a single response back from. Implementations /// should expect that the params will either be `None`, or be an already-serialized diff --git a/subxt/src/tx/tx_progress.rs b/subxt/src/tx/tx_progress.rs index 8f1e14bb5a..45d409b474 100644 --- a/subxt/src/tx/tx_progress.rs +++ b/subxt/src/tx/tx_progress.rs @@ -107,7 +107,7 @@ where _ => continue, } } - Err(RpcError::Custom("RPC subscription dropped".into()).into()) + Err(RpcError::SubscriptionDropped.into()) } /// Wait for the transaction to be finalized, and return a [`TxInBlock`] @@ -133,7 +133,7 @@ where _ => continue, } } - Err(RpcError::Custom("RPC subscription dropped".into()).into()) + Err(RpcError::SubscriptionDropped.into()) } /// Wait for the transaction to be finalized, and for the transaction events to indicate From 07b5cdc3d19579e92e439ee0ae1eaabf4119271f Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Wed, 19 Oct 2022 19:15:07 +0300 Subject: [PATCH 3/4] Update subxt/src/rpc/rpc_client_t.rs Co-authored-by: James Wilson --- subxt/src/rpc/rpc_client_t.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subxt/src/rpc/rpc_client_t.rs b/subxt/src/rpc/rpc_client_t.rs index a92ec4b29d..95a6157ae6 100644 --- a/subxt/src/rpc/rpc_client_t.rs +++ b/subxt/src/rpc/rpc_client_t.rs @@ -21,10 +21,10 @@ pub use serde_json::value::RawValue; /// generics), and want to avoid any unnecessary allocations in serializing/deserializing /// parameters. /// -/// # Note +/// # Panics /// -/// Implementations are free to panic if the provided parameters are not a valid -/// JSON Array. +/// Implementations are free to panic if the `RawValue`'s passed to `request_raw` or +/// `subscribe_raw` are not JSON arrays. Internally, we ensure that this is always the case. pub trait RpcClientT: Send + Sync + 'static { /// Make a raw request for which we expect a single response back from. Implementations /// should expect that the params will either be `None`, or be an already-serialized From 01802b68a2f11934479061629557101ed8eb9f06 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 19 Oct 2022 19:23:55 +0300 Subject: [PATCH 4/4] Apply rustfmt Signed-off-by: Alexandru Vasile --- subxt/src/rpc/rpc_client_t.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subxt/src/rpc/rpc_client_t.rs b/subxt/src/rpc/rpc_client_t.rs index 95a6157ae6..d32924ffbe 100644 --- a/subxt/src/rpc/rpc_client_t.rs +++ b/subxt/src/rpc/rpc_client_t.rs @@ -23,7 +23,7 @@ pub use serde_json::value::RawValue; /// /// # Panics /// -/// Implementations are free to panic if the `RawValue`'s passed to `request_raw` or +/// Implementations are free to panic if the `RawValue`'s passed to `request_raw` or /// `subscribe_raw` are not JSON arrays. Internally, we ensure that this is always the case. pub trait RpcClientT: Send + Sync + 'static { /// Make a raw request for which we expect a single response back from. Implementations