From 8df3eca70bef1c88ac8d18c882f2440c3885919d Mon Sep 17 00:00:00 2001 From: 0xDmtri <0xDmtri@protonmail.com> Date: Wed, 24 Jan 2024 01:17:03 +0000 Subject: [PATCH] Make response's data field 'optional' (#76) --- src/jsonrpc.rs | 14 ++++++++--- src/middleware.rs | 55 ++++++++++++++++++++++++++++++++----------- src/pending_bundle.rs | 8 +++---- src/relay.rs | 4 ++-- 4 files changed, 58 insertions(+), 23 deletions(-) diff --git a/src/jsonrpc.rs b/src/jsonrpc.rs index 1f441a2..88358cb 100644 --- a/src/jsonrpc.rs +++ b/src/jsonrpc.rs @@ -80,12 +80,12 @@ pub struct Response { #[serde(untagged)] pub enum ResponseData { Error { error: JsonRpcError }, - Success { result: R }, + Success { result: Option }, } impl ResponseData { /// Consume response and return value - pub fn into_result(self) -> Result { + pub fn into_result(self) -> Result, JsonRpcError> { match self { ResponseData::Success { result } => Ok(result), ResponseData::Error { error } => Err(error), @@ -102,7 +102,15 @@ mod tests { let response: Response = serde_json::from_str(r#"{"jsonrpc": "2.0", "result": 19, "id": 1}"#).unwrap(); assert_eq!(response.id, 1); - assert_eq!(response.data.into_result().unwrap(), 19); + assert_eq!(response.data.into_result().unwrap(), Some(19)); + } + + #[test] + fn deser_response_without_result() { + let response: Response = + serde_json::from_str(r#"{"jsonrpc": "2.0", "id": 1, "result": null}"#).unwrap(); + assert_eq!(response.id, 1); + assert_eq!(response.data.into_result().unwrap(), None); } #[test] diff --git a/src/middleware.rs b/src/middleware.rs index b755054..30d73f3 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -40,6 +40,15 @@ pub enum FlashbotsMiddlewareError { /// An error occured in one of the middlewares. #[error("{0}")] MiddlewareError(M::Error), + /// Empty data for bundle simulation request. + #[error("Bundle simulation is not available")] + BundleSimError, + /// Empty data for bundle stats request. + #[error("Bundle stats are not available")] + BundleStatsError, + /// Empty data for user stats request. + #[error("User stats are not available")] + UserStatsError, } impl MiddlewareError for FlashbotsMiddlewareError { @@ -170,7 +179,8 @@ impl FlashbotsMiddleware { .unwrap_or(&self.relay) .request("eth_callBundle", [bundle]) .await - .map_err(FlashbotsMiddlewareError::RelayError) + .map_err(FlashbotsMiddlewareError::RelayError)? + .ok_or(FlashbotsMiddlewareError::BundleSimError) } /// Send a bundle to the relayer. @@ -193,18 +203,26 @@ impl FlashbotsMiddleware { return Err(FlashbotsMiddlewareError::MissingParameters); } - let response: SendBundleResponse = self + let response: Option = self .relay .request("eth_sendBundle", [bundle]) .await .map_err(FlashbotsMiddlewareError::RelayError)?; - Ok(PendingBundle::new( - response.bundle_hash, - bundle.block().unwrap(), - bundle.transaction_hashes(), - self.provider(), - )) + match response { + Some(r) => Ok(PendingBundle::new( + r.bundle_hash, + bundle.block().unwrap(), + bundle.transaction_hashes(), + self.provider(), + )), + None => Ok(PendingBundle::new( + None, + bundle.block().unwrap(), + bundle.transaction_hashes(), + self.provider(), + )), + } } /// Get stats for a particular bundle. @@ -222,7 +240,8 @@ impl FlashbotsMiddleware { }], ) .await - .map_err(FlashbotsMiddlewareError::RelayError) + .map_err(FlashbotsMiddlewareError::RelayError)? + .ok_or(FlashbotsMiddlewareError::BundleStatsError) } /// Get stats for your searcher identity. @@ -244,7 +263,8 @@ impl FlashbotsMiddleware { }], ) .await - .map_err(FlashbotsMiddlewareError::RelayError) + .map_err(FlashbotsMiddlewareError::RelayError)? + .ok_or(FlashbotsMiddlewareError::UserStatsError) } } @@ -407,7 +427,8 @@ impl BroadcasterMiddleware { self.simulation_relay .request("eth_callBundle", [bundle]) .await - .map_err(FlashbotsMiddlewareError::RelayError) + .map_err(FlashbotsMiddlewareError::RelayError)? + .ok_or(FlashbotsMiddlewareError::BundleSimError) } /// Broadcast a bundle to the builders. @@ -438,13 +459,19 @@ impl BroadcasterMiddleware { .map(|relay| async move { let response = relay.request("eth_sendBundle", [bundle]).await; response - .map(|r: SendBundleResponse| { - PendingBundle::new( + .map(|response: Option| match response { + Some(r) => PendingBundle::new( r.bundle_hash, bundle.block().unwrap(), bundle.transaction_hashes(), self.provider(), - ) + ), + None => PendingBundle::new( + None, + bundle.block().unwrap(), + bundle.transaction_hashes(), + self.provider(), + ), }) .map_err(FlashbotsMiddlewareError::RelayError) }) diff --git a/src/pending_bundle.rs b/src/pending_bundle.rs index d7c62d9..46b2167 100644 --- a/src/pending_bundle.rs +++ b/src/pending_bundle.rs @@ -28,7 +28,7 @@ use thiserror::Error; /// [fb_debug]: https://docs.flashbots.net/flashbots-auction/searchers/faq/#why-didnt-my-transaction-get-included #[pin_project] pub struct PendingBundle<'a, P> { - pub bundle_hash: BundleHash, + pub bundle_hash: Option, pub block: U64, pub transactions: Vec, provider: &'a Provider

, @@ -38,7 +38,7 @@ pub struct PendingBundle<'a, P> { impl<'a, P: JsonRpcClient> PendingBundle<'a, P> { pub fn new( - bundle_hash: BundleHash, + bundle_hash: Option, block: U64, transactions: Vec, provider: &'a Provider

, @@ -55,13 +55,13 @@ impl<'a, P: JsonRpcClient> PendingBundle<'a, P> { /// Get the bundle hash for this pending bundle. #[deprecated(note = "use the bundle_hash field instead")] - pub fn bundle_hash(&self) -> BundleHash { + pub fn bundle_hash(&self) -> Option { self.bundle_hash } } impl<'a, P: JsonRpcClient> Future for PendingBundle<'a, P> { - type Output = Result; + type Output = Result, PendingBundleError>; fn poll(self: Pin<&mut Self>, ctx: &mut Context) -> Poll { let this = self.project(); diff --git a/src/relay.rs b/src/relay.rs index 714b4f9..3582954 100644 --- a/src/relay.rs +++ b/src/relay.rs @@ -72,7 +72,7 @@ impl Relay { &self, method: &str, params: T, - ) -> Result> { + ) -> Result, RelayError> { let next_id = self.id.load(Ordering::SeqCst) + 1; self.id.store(next_id, Ordering::SeqCst); @@ -139,7 +139,7 @@ impl Clone for Relay { #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub(crate) struct SendBundleResponse { - pub(crate) bundle_hash: BundleHash, + pub(crate) bundle_hash: Option, } #[derive(Serialize)]