alloy_provider/ext/
erc4337.rs1use crate::Provider;
2use alloy_network::Network;
3use alloy_primitives::{Address, Bytes};
4use alloy_rpc_types_eth::erc4337::{
5 SendUserOperation, SendUserOperationResponse, UserOperationGasEstimation, UserOperationReceipt,
6};
7use alloy_transport::TransportResult;
8
9#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
14#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
15pub trait Erc4337Api<N>: Send + Sync {
16 async fn send_user_operation(
20 &self,
21 user_op: SendUserOperation,
22 entry_point: Address,
23 ) -> TransportResult<SendUserOperationResponse>;
24
25 async fn supported_entry_points(&self) -> TransportResult<Vec<Address>>;
27
28 async fn get_user_operation_receipt(
32 &self,
33 user_op_hash: Bytes,
34 ) -> TransportResult<UserOperationReceipt>;
35
36 async fn estimate_user_operation_gas(
40 &self,
41 user_op: SendUserOperation,
42 entry_point: Address,
43 ) -> TransportResult<UserOperationGasEstimation>;
44}
45
46#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
47#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
48impl<N, P> Erc4337Api<N> for P
49where
50 N: Network,
51 P: Provider<N>,
52{
53 async fn send_user_operation(
54 &self,
55 user_op: SendUserOperation,
56 entry_point: Address,
57 ) -> TransportResult<SendUserOperationResponse> {
58 match user_op {
59 SendUserOperation::EntryPointV06(user_op) => {
60 self.client().request("eth_sendUserOperation", (user_op, entry_point)).await
61 }
62 SendUserOperation::EntryPointV07(packed_user_op) => {
63 self.client().request("eth_sendUserOperation", (packed_user_op, entry_point)).await
64 }
65 }
66 }
67
68 async fn supported_entry_points(&self) -> TransportResult<Vec<Address>> {
69 self.client().request("eth_supportedEntryPoints", ()).await
70 }
71
72 async fn get_user_operation_receipt(
73 &self,
74 user_op_hash: Bytes,
75 ) -> TransportResult<UserOperationReceipt> {
76 self.client().request("eth_getUserOperationReceipt", (user_op_hash,)).await
77 }
78
79 async fn estimate_user_operation_gas(
80 &self,
81 user_op: SendUserOperation,
82 entry_point: Address,
83 ) -> TransportResult<UserOperationGasEstimation> {
84 match user_op {
85 SendUserOperation::EntryPointV06(user_op) => {
86 self.client().request("eth_estimateUserOperationGas", (user_op, entry_point)).await
87 }
88 SendUserOperation::EntryPointV07(packed_user_op) => {
89 self.client()
90 .request("eth_estimateUserOperationGas", (packed_user_op, entry_point))
91 .await
92 }
93 }
94 }
95}