1use crate::Provider;
2use alloy_network::Network;
3use alloy_primitives::{BlockHash, Bytes, B256};
4use alloy_rpc_types_engine::{
5 ClientVersionV1, ExecutionPayloadBodiesV1, ExecutionPayloadEnvelopeV2,
6 ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4, ExecutionPayloadInputV2,
7 ExecutionPayloadV1, ExecutionPayloadV3, ForkchoiceState, ForkchoiceUpdated, PayloadAttributes,
8 PayloadId, PayloadStatus,
9};
10use alloy_transport::TransportResult;
11
12#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
17#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
18pub trait EngineApi<N>: Send + Sync {
19 async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> TransportResult<PayloadStatus>;
25
26 async fn new_payload_v2(
30 &self,
31 payload: ExecutionPayloadInputV2,
32 ) -> TransportResult<PayloadStatus>;
33
34 async fn new_payload_v3(
38 &self,
39 payload: ExecutionPayloadV3,
40 versioned_hashes: Vec<B256>,
41 parent_beacon_block_root: B256,
42 ) -> TransportResult<PayloadStatus>;
43
44 async fn new_payload_v4(
48 &self,
49 payload: ExecutionPayloadV3,
50 versioned_hashes: Vec<B256>,
51 parent_beacon_block_root: B256,
52 execution_requests: Vec<Bytes>,
53 ) -> TransportResult<PayloadStatus>;
54
55 async fn fork_choice_updated_v1(
62 &self,
63 fork_choice_state: ForkchoiceState,
64 payload_attributes: Option<PayloadAttributes>,
65 ) -> TransportResult<ForkchoiceUpdated>;
66
67 async fn fork_choice_updated_v2(
74 &self,
75 fork_choice_state: ForkchoiceState,
76 payload_attributes: Option<PayloadAttributes>,
77 ) -> TransportResult<ForkchoiceUpdated>;
78
79 async fn fork_choice_updated_v3(
84 &self,
85 fork_choice_state: ForkchoiceState,
86 payload_attributes: Option<PayloadAttributes>,
87 ) -> TransportResult<ForkchoiceUpdated>;
88
89 async fn get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1>;
99
100 async fn get_payload_v2(
108 &self,
109 payload_id: PayloadId,
110 ) -> TransportResult<ExecutionPayloadEnvelopeV2>;
111
112 async fn get_payload_v3(
120 &self,
121 payload_id: PayloadId,
122 ) -> TransportResult<ExecutionPayloadEnvelopeV3>;
123
124 async fn get_payload_v4(
132 &self,
133 payload_id: PayloadId,
134 ) -> TransportResult<ExecutionPayloadEnvelopeV4>;
135
136 async fn get_payload_bodies_by_hash_v1(
140 &self,
141 block_hashes: Vec<BlockHash>,
142 ) -> TransportResult<ExecutionPayloadBodiesV1>;
143
144 async fn get_payload_bodies_by_range_v1(
157 &self,
158 start: u64,
159 count: u64,
160 ) -> TransportResult<ExecutionPayloadBodiesV1>;
161
162 async fn get_client_version_v1(
169 &self,
170 client_version: ClientVersionV1,
171 ) -> TransportResult<Vec<ClientVersionV1>>;
172
173 async fn exchange_capabilities(
177 &self,
178 capabilities: Vec<String>,
179 ) -> TransportResult<Vec<String>>;
180}
181
182#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
183#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
184impl<N, P> EngineApi<N> for P
185where
186 N: Network,
187 P: Provider<N>,
188{
189 async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> TransportResult<PayloadStatus> {
190 self.client().request("engine_newPayloadV1", (payload,)).await
191 }
192
193 async fn new_payload_v2(
194 &self,
195 payload: ExecutionPayloadInputV2,
196 ) -> TransportResult<PayloadStatus> {
197 self.client().request("engine_newPayloadV2", (payload,)).await
198 }
199
200 async fn new_payload_v3(
201 &self,
202 payload: ExecutionPayloadV3,
203 versioned_hashes: Vec<B256>,
204 parent_beacon_block_root: B256,
205 ) -> TransportResult<PayloadStatus> {
206 self.client()
207 .request("engine_newPayloadV3", (payload, versioned_hashes, parent_beacon_block_root))
208 .await
209 }
210
211 async fn new_payload_v4(
212 &self,
213 payload: ExecutionPayloadV3,
214 versioned_hashes: Vec<B256>,
215 parent_beacon_block_root: B256,
216 execution_requests: Vec<Bytes>,
217 ) -> TransportResult<PayloadStatus> {
218 self.client()
219 .request(
220 "engine_newPayloadV4",
221 (payload, versioned_hashes, parent_beacon_block_root, execution_requests),
222 )
223 .await
224 }
225
226 async fn fork_choice_updated_v1(
227 &self,
228 fork_choice_state: ForkchoiceState,
229 payload_attributes: Option<PayloadAttributes>,
230 ) -> TransportResult<ForkchoiceUpdated> {
231 self.client()
232 .request("engine_forkchoiceUpdatedV1", (fork_choice_state, payload_attributes))
233 .await
234 }
235
236 async fn fork_choice_updated_v2(
237 &self,
238 fork_choice_state: ForkchoiceState,
239 payload_attributes: Option<PayloadAttributes>,
240 ) -> TransportResult<ForkchoiceUpdated> {
241 self.client()
242 .request("engine_forkchoiceUpdatedV2", (fork_choice_state, payload_attributes))
243 .await
244 }
245
246 async fn fork_choice_updated_v3(
247 &self,
248 fork_choice_state: ForkchoiceState,
249 payload_attributes: Option<PayloadAttributes>,
250 ) -> TransportResult<ForkchoiceUpdated> {
251 self.client()
252 .request("engine_forkchoiceUpdatedV3", (fork_choice_state, payload_attributes))
253 .await
254 }
255
256 async fn get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1> {
257 self.client().request("engine_getPayloadV1", (payload_id,)).await
258 }
259
260 async fn get_payload_v2(
261 &self,
262 payload_id: PayloadId,
263 ) -> TransportResult<ExecutionPayloadEnvelopeV2> {
264 self.client().request("engine_getPayloadV2", (payload_id,)).await
265 }
266
267 async fn get_payload_v3(
268 &self,
269 payload_id: PayloadId,
270 ) -> TransportResult<ExecutionPayloadEnvelopeV3> {
271 self.client().request("engine_getPayloadV3", (payload_id,)).await
272 }
273
274 async fn get_payload_v4(
275 &self,
276 payload_id: PayloadId,
277 ) -> TransportResult<ExecutionPayloadEnvelopeV4> {
278 self.client().request("engine_getPayloadV4", (payload_id,)).await
279 }
280
281 async fn get_payload_bodies_by_hash_v1(
282 &self,
283 block_hashes: Vec<BlockHash>,
284 ) -> TransportResult<ExecutionPayloadBodiesV1> {
285 self.client().request("engine_getPayloadBodiesByHashV1", (block_hashes,)).await
286 }
287
288 async fn get_payload_bodies_by_range_v1(
289 &self,
290 start: u64,
291 count: u64,
292 ) -> TransportResult<ExecutionPayloadBodiesV1> {
293 self.client().request("engine_getPayloadBodiesByRangeV1", (start, count)).await
294 }
295
296 async fn get_client_version_v1(
297 &self,
298 client_version: ClientVersionV1,
299 ) -> TransportResult<Vec<ClientVersionV1>> {
300 self.client().request("engine_getClientVersionV1", (client_version,)).await
301 }
302
303 async fn exchange_capabilities(
304 &self,
305 capabilities: Vec<String>,
306 ) -> TransportResult<Vec<String>> {
307 self.client().request("engine_exchangeCapabilities", (capabilities,)).await
308 }
309}