Skip to content

Commit

Permalink
feat(sender): update sender configuration to be able to choose from e…
Browse files Browse the repository at this point in the history
…nums and add validation
  • Loading branch information
0xfourzerofour committed Sep 26, 2023
1 parent c6bc33c commit a3ff608
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 89 deletions.
35 changes: 16 additions & 19 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bin/rundler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ rundler-utils = { path = "../../crates/utils" }

# CLI dependencies
anyhow.workspace = true
clap = { version = "4.2.4", features = ["derive", "env"] }
clap = { version = "4.4.4", features = ["derive", "env"] }
dotenv = "0.15.0"
ethers.workspace = true
itertools = "0.11.0"
Expand Down
21 changes: 11 additions & 10 deletions bin/rundler/src/cli/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use clap::Args;
use ethers::types::H256;
use rundler_builder::{
self, BuilderEvent, BuilderEventKind, BuilderTask, BuilderTaskArgs, LocalBuilderBuilder,
TransactionSenderType,
};
use rundler_pool::RemotePoolClient;
use rundler_sim::{MempoolConfig, PriorityFeeMode};
Expand Down Expand Up @@ -107,17 +108,17 @@ pub struct BuilderArgs {
)]
pub submit_url: Option<String>,

/// If true, will use the provider's `eth_sendRawTransactionConditional`
/// method instead `eth_sendRawTransaction`, passing in expected storage
/// values determined through simulation. Must not be set on networks
/// which do not support this method.
/// Choice of what sender type to to use for transaction submission.
/// Defaults to the value of `raw`. Other options inclue `flashbots`,
/// `conditional` and `polygon_bloxroute`
#[arg(
long = "builder.use_conditional_send_transaction",
name = "builder.use_conditional_send_transaction",
env = "BUILDER_USE_CONDITIONAL_SEND_TRANSACTION",
default_value = "false"
long = "builder.sender",
name = "builder.sender",
env = "BUILDER_SENDER",
value_enum,
default_value = "raw"
)]
use_conditional_send_transaction: bool,
pub sender_type: TransactionSenderType,

/// After submitting a bundle transaction, the maximum number of blocks to
/// wait for that transaction to mine before we try resending with higher
Expand Down Expand Up @@ -218,7 +219,7 @@ impl BuilderArgs {
use_bundle_priority_fee: common.use_bundle_priority_fee,
bundle_priority_fee_overhead_percent: common.bundle_priority_fee_overhead_percent,
priority_fee_mode,
use_conditional_send_transaction: self.use_conditional_send_transaction,
sender_type: self.sender_type,
eth_poll_interval: Duration::from_millis(common.eth_poll_interval_millis),
sim_settings: common.try_into()?,
mempool_configs,
Expand Down
1 change: 1 addition & 0 deletions crates/builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod emit;
pub use emit::{BuilderEvent, BuilderEventKind};

mod sender;
pub use sender::TransactionSenderType;

mod server;
pub use server::{
Expand Down
72 changes: 56 additions & 16 deletions crates/builder/src/sender/flashbots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,28 @@ use std::{
task::{Context as TaskContext, Poll},
};

use anyhow::{bail, Context};
use anyhow::{bail, Context, Result};
use ethers::{
middleware::SignerMiddleware,
providers::{interval, JsonRpcClient, Middleware, Provider},
types::{transaction::eip2718::TypedTransaction, Address, TransactionReceipt, H256, U256, U64},
types::{
transaction::eip2718::TypedTransaction, Address, Bytes, TransactionReceipt, TxHash, H256,
U256, U64,
},
};
use ethers_signers::Signer;
use futures_timer::Delay;
use futures_util::{Stream, StreamExt, TryFutureExt};
use jsonrpsee::{
core::{client::ClientT, traits::ToRpcParams},
http_client::{transport::HttpBackend, HttpClient, HttpClientBuilder},
};
use pin_project::pin_project;
use rundler_sim::ExpectedStorage;
use serde::{de, Deserialize};
use serde_json::Value;
use serde::{de, Deserialize, Serialize};
use serde_json::{value::RawValue, Value};
use tonic::async_trait;

use crate::sender::{fill_and_sign, SentTxInfo, TransactionSender, TxStatus};
use super::{fill_and_sign, ExpectedStorage, SentTxInfo, TransactionSender, TxStatus};

#[derive(Debug)]
pub(crate) struct FlashbotsTransactionSender<C, S>
Expand All @@ -62,9 +68,8 @@ where
let (raw_tx, nonce) = fill_and_sign(&self.provider, tx).await?;

let tx_hash = self
.provider
.provider()
.request("eth_sendRawTransaction", (raw_tx,))
.client
.send_transaction(raw_tx)
.await
.context("should send raw transaction to node")?;

Expand Down Expand Up @@ -117,11 +122,11 @@ where
C: JsonRpcClient + 'static,
S: Signer + 'static,
{
pub(crate) fn new(provider: Arc<Provider<C>>, signer: S) -> Self {
Self {
pub(crate) fn new(provider: Arc<Provider<C>>, signer: S) -> Result<Self> {
Ok(Self {
provider: SignerMiddleware::new(provider, signer),
client: FlashbotsClient::default(),
}
client: FlashbotsClient::new()?,
})
}
}

Expand Down Expand Up @@ -167,17 +172,52 @@ struct FlashbotsAPIResponse {
seen_in_mempool: bool,
}

#[derive(Debug, Default)]
struct FlashbotsClient {}
#[derive(Debug)]
struct FlashbotsClient {
client: HttpClient<HttpBackend>,
}

impl FlashbotsClient {
async fn status(&self, tx_hash: H256) -> anyhow::Result<FlashbotsAPIResponse> {
fn new() -> Result<Self> {
let client = HttpClientBuilder::default().build("https://rpc.flashbots.net")?;
Ok(Self { client })
}

async fn status(&self, tx_hash: H256) -> Result<FlashbotsAPIResponse> {
let url = format!("https://protect.flashbots.net/tx/{:?}", tx_hash);
let resp = reqwest::get(&url).await?;
resp.json::<FlashbotsAPIResponse>()
.await
.context("should deserialize FlashbotsAPIResponse")
}

async fn send_transaction(&self, raw_tx: Bytes) -> anyhow::Result<TxHash> {
let response: FlashbotsResponse = self
.client
.request("eth_sendRawTransaction", (raw_tx,))
.await?;
Ok(response.tx_hash)
}
}

#[derive(Serialize)]
struct FlashbotsRequest {
transaction: String,
}

impl ToRpcParams for FlashbotsRequest {
fn to_rpc_params(self) -> Result<Option<Box<RawValue>>, jsonrpsee::core::Error> {
let s = String::from_utf8(serde_json::to_vec(&self)?).expect("Valid UTF8 format");
RawValue::from_string(s)
.map(Some)
.map_err(jsonrpsee::core::Error::ParseError)
}
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
struct FlashbotsResponse {
tx_hash: TxHash,
}

type PinBoxFut<'a, T> = Pin<Box<dyn Future<Output = anyhow::Result<T>> + Send + 'a>>;
Expand Down
Loading

0 comments on commit a3ff608

Please sign in to comment.