Skip to content

Commit aee57f8

Browse files
committed
refactor: type the json-rpc in the flashbots rpc
1 parent 42ac350 commit aee57f8

2 files changed

Lines changed: 37 additions & 35 deletions

File tree

‎src/tasks/submit/flashbots/provider.rs‎

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
//! A generic Flashbots bundle API wrapper.
2+
use std::borrow::Cow;
3+
24
use crate::config::BuilderConfig;
35
use alloy::{
46
primitives::{BlockNumber, keccak256},
5-
rpc::types::mev::{EthBundleHash, MevSendBundle, SimBundleResponse},
7+
rpc::{
8+
json_rpc::{Id, Response, ResponsePayload, RpcRecv, RpcSend},
9+
types::mev::{EthBundleHash, MevSendBundle, SimBundleResponse},
10+
},
611
signers::Signer,
712
};
813
use eyre::Context as _;
914
use init4_bin_base::utils::signer::LocalOrAws;
1015
use reqwest::header::CONTENT_TYPE;
1116
use serde_json::json;
1217

13-
/// A wrapper over a `Provider` that adds Flashbots MEV bundle helpers.
18+
/// An RPC connection to relevant Flashbots endpoints.
1419
#[derive(Debug)]
1520
pub struct Flashbots {
1621
/// The base URL for the Flashbots API.
@@ -34,48 +39,43 @@ impl Flashbots {
3439
}
3540

3641
/// Sends a bundle via `mev_sendBundle`.
37-
pub async fn send_bundle(&self, bundle: MevSendBundle) -> eyre::Result<EthBundleHash> {
38-
let params = serde_json::to_value(bundle)?;
39-
let v = self.raw_call("mev_sendBundle", params).await?;
40-
let hash: EthBundleHash =
41-
serde_json::from_value(v.get("result").cloned().unwrap_or(serde_json::Value::Null))?;
42-
Ok(hash)
42+
pub async fn send_bundle(&self, bundle: &MevSendBundle) -> eyre::Result<EthBundleHash> {
43+
self.raw_call("mev_sendBundle", &[bundle]).await
4344
}
4445

4546
/// Simulate a bundle via `mev_simBundle`.
46-
pub async fn simulate_bundle(&self, bundle: MevSendBundle) -> eyre::Result<()> {
47-
let params = serde_json::to_value(bundle)?;
48-
let v = self.raw_call("mev_simBundle", params).await?;
49-
let resp: SimBundleResponse =
50-
serde_json::from_value(v.get("result").cloned().unwrap_or(serde_json::Value::Null))?;
47+
pub async fn simulate_bundle(&self, bundle: &MevSendBundle) -> eyre::Result<()> {
48+
let resp: SimBundleResponse = self.raw_call("mev_simBundle", &[bundle]).await?;
5149
dbg!("successfully simulated bundle", &resp);
5250
Ok(())
5351
}
5452

5553
/// Fetches the bundle status by hash
5654
pub async fn bundle_status(
5755
&self,
58-
_hash: EthBundleHash,
56+
hash: EthBundleHash,
5957
block_number: BlockNumber,
6058
) -> eyre::Result<()> {
61-
let params = json!({ "bundleHash": _hash, "blockNumber": block_number });
62-
let _ = self.raw_call("flashbots_getBundleStatsV2", params).await?;
59+
let params = json!({ "bundleHash": hash, "blockNumber": block_number });
60+
let _resp: serde_json::Value =
61+
self.raw_call("flashbots_getBundleStatsV2", &[params]).await?;
62+
6363
Ok(())
6464
}
6565

6666
/// Makes a raw JSON-RPC call with the Flashbots signature header to the method with the given params.
67-
async fn raw_call(
67+
async fn raw_call<Params: RpcSend, Payload: RpcRecv>(
6868
&self,
6969
method: &str,
70-
params: serde_json::Value,
71-
) -> eyre::Result<serde_json::Value> {
72-
let params = match params {
73-
serde_json::Value::Array(_) => params,
74-
other => serde_json::Value::Array(vec![other]),
75-
};
76-
77-
let body = json!({"jsonrpc":"2.0","id":1,"method":method,"params":params});
78-
let body_bz = serde_json::to_vec(&body)?;
70+
params: &Params,
71+
) -> eyre::Result<Payload> {
72+
let req = alloy::rpc::json_rpc::Request::new(
73+
Cow::Owned(method.to_string()),
74+
Id::Number(1),
75+
params,
76+
);
77+
let body_bz = serde_json::to_vec(&req)?;
78+
drop(req);
7979

8080
let value = self.compute_signature(&body_bz).await?;
8181

@@ -89,17 +89,21 @@ impl Flashbots {
8989
.await?;
9090

9191
let text = resp.text().await?;
92-
let v: serde_json::Value =
92+
93+
let resp: Response<Payload> =
9394
serde_json::from_str(&text).wrap_err("failed to parse flashbots JSON")?;
94-
if let Some(err) = v.get("error") {
95-
eyre::bail!("flashbots error: {err}");
95+
96+
match resp.payload {
97+
ResponsePayload::Success(payload) => Ok(payload),
98+
ResponsePayload::Failure(err) => {
99+
eyre::bail!("flashbots error: {err}");
100+
}
96101
}
97-
Ok(v)
98102
}
99103

100104
/// Builds an EIP-191 signature for the given body bytes.
101105
async fn compute_signature(&self, body_bz: &[u8]) -> Result<String, eyre::Error> {
102-
let payload = format!("0x{:x}", keccak256(body_bz));
106+
let payload = keccak256(body_bz).to_string();
103107
let signature = self.signer.sign_message(payload.as_ref()).await?;
104108
dbg!(signature.to_string());
105109
let address = self.signer.address();

‎src/tasks/submit/flashbots/task.rs‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,15 +236,13 @@ impl FlashbotsTask {
236236
};
237237

238238
// simulate the bundle against Flashbots then send the bundle
239-
if let Err(err) =
240-
flashbots.simulate_bundle(bundle.clone()).instrument(span.clone()).await
241-
{
239+
if let Err(err) = flashbots.simulate_bundle(&bundle).instrument(span.clone()).await {
242240
span_scoped!(span, debug!(%err, "bundle simulation failed"));
243241
continue;
244242
}
245243

246244
let _ = flashbots
247-
.send_bundle(bundle)
245+
.send_bundle(&bundle)
248246
.instrument(span.clone())
249247
.await
250248
.inspect(|bundle_hash| {

0 commit comments

Comments
 (0)