Skip to content

Commit 7fc61e9

Browse files
committed
refactor: type the json-rpc in the flashbots rpc
1 parent 97e5030 commit 7fc61e9

File tree

3 files changed

+37
-39
lines changed

3 files changed

+37
-39
lines changed

src/tasks/submit/flashbots/provider.rs

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
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
};
8-
use eyre::Context as _;
913
use init4_bin_base::utils::signer::LocalOrAws;
1014
use reqwest::header::CONTENT_TYPE;
1115
use serde_json::json;
1216

13-
/// A wrapper over a `Provider` that adds Flashbots MEV bundle helpers.
17+
/// An RPC connection to relevant Flashbots endpoints.
1418
#[derive(Debug)]
1519
pub struct Flashbots {
1620
/// The base URL for the Flashbots API.
@@ -34,48 +38,43 @@ impl Flashbots {
3438
}
3539

3640
/// 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)
41+
pub async fn send_bundle(&self, bundle: &MevSendBundle) -> eyre::Result<EthBundleHash> {
42+
self.raw_call("mev_sendBundle", &[bundle]).await
4343
}
4444

4545
/// 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))?;
46+
pub async fn simulate_bundle(&self, bundle: &MevSendBundle) -> eyre::Result<()> {
47+
let resp: SimBundleResponse = self.raw_call("mev_simBundle", &[bundle]).await?;
5148
dbg!("successfully simulated bundle", &resp);
5249
Ok(())
5350
}
5451

5552
/// Fetches the bundle status by hash
5653
pub async fn bundle_status(
5754
&self,
58-
_hash: EthBundleHash,
55+
hash: EthBundleHash,
5956
block_number: BlockNumber,
6057
) -> eyre::Result<()> {
61-
let params = json!({ "bundleHash": _hash, "blockNumber": block_number });
62-
let _ = self.raw_call("flashbots_getBundleStatsV2", params).await?;
58+
let params = json!({ "bundleHash": hash, "blockNumber": block_number });
59+
let _resp: serde_json::Value =
60+
self.raw_call("flashbots_getBundleStatsV2", &[params]).await?;
61+
6362
Ok(())
6463
}
6564

6665
/// Makes a raw JSON-RPC call with the Flashbots signature header to the method with the given params.
67-
async fn raw_call(
66+
async fn raw_call<Params: RpcSend, Payload: RpcRecv>(
6867
&self,
6968
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)?;
69+
params: &Params,
70+
) -> eyre::Result<Payload> {
71+
let req = alloy::rpc::json_rpc::Request::new(
72+
Cow::Owned(method.to_string()),
73+
Id::Number(1),
74+
params,
75+
);
76+
let body_bz = serde_json::to_vec(&req)?;
77+
drop(req);
7978

8079
let value = self.compute_signature(&body_bz).await?;
8180

@@ -88,18 +87,19 @@ impl Flashbots {
8887
.send()
8988
.await?;
9089

91-
let text = resp.text().await?;
92-
let v: serde_json::Value =
93-
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}");
90+
let resp: Response<Payload> = resp.json().await?;
91+
92+
match resp.payload {
93+
ResponsePayload::Success(payload) => Ok(payload),
94+
ResponsePayload::Failure(err) => {
95+
eyre::bail!("flashbots error: {err}");
96+
}
9697
}
97-
Ok(v)
9898
}
9999

100100
/// Builds an EIP-191 signature for the given body bytes.
101101
async fn compute_signature(&self, body_bz: &[u8]) -> Result<String, eyre::Error> {
102-
let payload = format!("0x{:x}", keccak256(body_bz));
102+
let payload = keccak256(body_bz).to_string();
103103
let signature = self.signer.sign_message(payload.as_ref()).await?;
104104
dbg!(signature.to_string());
105105
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| {

tests/flashbots_provider_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ async fn test_simulate_valid_bundle_sepolia() {
4040
dbg!("submitting bundle with 1 tx", &bundle_body);
4141
let bundle = MevSendBundle::new(latest_block, Some(0), ProtocolVersion::V0_1, bundle_body);
4242

43-
flashbots.simulate_bundle(bundle).await.expect("failed to simulate bundle");
43+
flashbots.simulate_bundle(&bundle).await.expect("failed to simulate bundle");
4444
}
4545

4646
async fn get_test_provider() -> Flashbots {

0 commit comments

Comments
 (0)