use alloy::rpc::types::state::StateOverride;
use crate::{
builder::UserOperationBuilder,
signable_user_operation::SignableUserOperation,
signed_user_operation::SignedUserOperation,
user_operation::{UserOperationGasEstimate, UserOperationHash, UserOperationReceipt},
};
pub mod pimlico;
mod rpc_client;
pub trait BundlerExt: Sized {
fn with_gas_estimate<B: Bundler + ?Sized>(
self,
bundler: &B,
state_override: Option<&StateOverride>,
) -> impl Future<Output = Result<Self, BundlerError>>;
}
#[cfg_attr(native, async_trait::async_trait)]
#[cfg_attr(wasm, async_trait::async_trait(?Send))]
pub trait Bundler {
async fn estimate_gas(
&self,
op: &SignableUserOperation,
state_override: Option<&StateOverride>,
) -> Result<UserOperationGasEstimate, BundlerError>;
async fn send_user_operation(
&self,
op: &SignedUserOperation,
) -> Result<UserOperationHash, BundlerError>;
async fn receipt(
&self,
hash: UserOperationHash,
) -> Result<Option<UserOperationReceipt>, BundlerError>;
async fn wait_for_receipt(
&self,
hash: UserOperationHash,
) -> Result<UserOperationReceipt, BundlerError>;
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum BundlerError {
#[error("Timeout")]
Timeout,
#[error("Other: {0}")]
Other(#[from] Box<dyn std::error::Error + Send + Sync>),
}
impl<S> BundlerExt for UserOperationBuilder<S> {
async fn with_gas_estimate<B: Bundler + ?Sized>(
self,
bundler: &B,
state_override: Option<&StateOverride>,
) -> Result<Self, BundlerError> {
let op = self.build();
let est = bundler.estimate_gas(&op, state_override).await?;
Ok(self.with_gas(est))
}
}