1use crate::Provider;
2use alloy_eips::eip7685::RequestsOrHash;
3use alloy_network::Network;
4use alloy_primitives::{BlockHash, Bytes, B256, U64};
5use alloy_rpc_types_engine::{
6 BlobAndProofV1, BlobAndProofV2, ClientVersionV1, ExecutionPayloadBodiesV1,
7 ExecutionPayloadBodiesV2, ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3,
8 ExecutionPayloadEnvelopeV4, ExecutionPayloadEnvelopeV5, ExecutionPayloadEnvelopeV6,
9 ExecutionPayloadInputV2, ExecutionPayloadV1, ExecutionPayloadV3, ExecutionPayloadV4,
10 ForkchoiceState, ForkchoiceUpdated, PayloadAttributes, PayloadId, PayloadStatus,
11};
12use alloy_transport::TransportResult;
13
14#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
16#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
17pub trait EngineApi<N>: Send + Sync {
18 async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> TransportResult<PayloadStatus>;
24
25 async fn new_payload_v2(
29 &self,
30 payload: ExecutionPayloadInputV2,
31 ) -> TransportResult<PayloadStatus>;
32
33 async fn new_payload_v3(
37 &self,
38 payload: ExecutionPayloadV3,
39 versioned_hashes: Vec<B256>,
40 parent_beacon_block_root: B256,
41 ) -> TransportResult<PayloadStatus>;
42
43 async fn new_payload_v4(
47 &self,
48 payload: ExecutionPayloadV3,
49 versioned_hashes: Vec<B256>,
50 parent_beacon_block_root: B256,
51 execution_requests: Vec<Bytes>,
52 ) -> TransportResult<PayloadStatus>;
53
54 async fn new_payload_v4_requests(
61 &self,
62 payload: ExecutionPayloadV3,
63 versioned_hashes: Vec<B256>,
64 parent_beacon_block_root: B256,
65 execution_requests: RequestsOrHash,
66 ) -> TransportResult<PayloadStatus>;
67
68 async fn new_payload_v5(
72 &self,
73 payload: ExecutionPayloadV4,
74 versioned_hashes: Vec<B256>,
75 parent_beacon_block_root: B256,
76 execution_requests: RequestsOrHash,
77 ) -> TransportResult<PayloadStatus>;
78
79 async fn fork_choice_updated_v1(
86 &self,
87 fork_choice_state: ForkchoiceState,
88 payload_attributes: Option<PayloadAttributes>,
89 ) -> TransportResult<ForkchoiceUpdated>;
90
91 async fn fork_choice_updated_v2(
98 &self,
99 fork_choice_state: ForkchoiceState,
100 payload_attributes: Option<PayloadAttributes>,
101 ) -> TransportResult<ForkchoiceUpdated>;
102
103 async fn fork_choice_updated_v3(
108 &self,
109 fork_choice_state: ForkchoiceState,
110 payload_attributes: Option<PayloadAttributes>,
111 ) -> TransportResult<ForkchoiceUpdated>;
112
113 async fn fork_choice_updated_v4(
118 &self,
119 fork_choice_state: ForkchoiceState,
120 payload_attributes: Option<PayloadAttributes>,
121 ) -> TransportResult<ForkchoiceUpdated>;
122
123 async fn get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1>;
133
134 async fn get_payload_v2(
142 &self,
143 payload_id: PayloadId,
144 ) -> TransportResult<ExecutionPayloadEnvelopeV2>;
145
146 async fn get_payload_v3(
154 &self,
155 payload_id: PayloadId,
156 ) -> TransportResult<ExecutionPayloadEnvelopeV3>;
157
158 async fn get_payload_v4(
166 &self,
167 payload_id: PayloadId,
168 ) -> TransportResult<ExecutionPayloadEnvelopeV4>;
169
170 async fn get_payload_v5(
178 &self,
179 payload_id: PayloadId,
180 ) -> TransportResult<ExecutionPayloadEnvelopeV5>;
181
182 async fn get_payload_v6(
190 &self,
191 payload_id: PayloadId,
192 ) -> TransportResult<ExecutionPayloadEnvelopeV6>;
193
194 async fn get_payload_bodies_by_hash_v1(
198 &self,
199 block_hashes: Vec<BlockHash>,
200 ) -> TransportResult<ExecutionPayloadBodiesV1>;
201
202 async fn get_payload_bodies_by_range_v1(
215 &self,
216 start: u64,
217 count: u64,
218 ) -> TransportResult<ExecutionPayloadBodiesV1>;
219
220 async fn get_payload_bodies_by_hash_v2(
226 &self,
227 block_hashes: Vec<BlockHash>,
228 ) -> TransportResult<ExecutionPayloadBodiesV2>;
229
230 async fn get_payload_bodies_by_range_v2(
245 &self,
246 start: u64,
247 count: u64,
248 ) -> TransportResult<ExecutionPayloadBodiesV2>;
249
250 async fn get_blobs_v1(
256 &self,
257 versioned_hashes: Vec<B256>,
258 ) -> TransportResult<Vec<Option<BlobAndProofV1>>>;
259
260 async fn get_blobs_v2(
267 &self,
268 versioned_hashes: Vec<B256>,
269 ) -> TransportResult<Vec<Option<BlobAndProofV2>>>;
270
271 async fn get_client_version_v1(
278 &self,
279 client_version: ClientVersionV1,
280 ) -> TransportResult<Vec<ClientVersionV1>>;
281
282 async fn exchange_capabilities(
286 &self,
287 capabilities: Vec<String>,
288 ) -> TransportResult<Vec<String>>;
289}
290
291#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
292#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
293impl<N, P> EngineApi<N> for P
294where
295 N: Network,
296 P: Provider<N>,
297{
298 async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> TransportResult<PayloadStatus> {
299 self.client().request("engine_newPayloadV1", (payload,)).await
300 }
301
302 async fn new_payload_v2(
303 &self,
304 payload: ExecutionPayloadInputV2,
305 ) -> TransportResult<PayloadStatus> {
306 self.client().request("engine_newPayloadV2", (payload,)).await
307 }
308
309 async fn new_payload_v3(
310 &self,
311 payload: ExecutionPayloadV3,
312 versioned_hashes: Vec<B256>,
313 parent_beacon_block_root: B256,
314 ) -> TransportResult<PayloadStatus> {
315 self.client()
316 .request("engine_newPayloadV3", (payload, versioned_hashes, parent_beacon_block_root))
317 .await
318 }
319
320 async fn new_payload_v4(
321 &self,
322 payload: ExecutionPayloadV3,
323 versioned_hashes: Vec<B256>,
324 parent_beacon_block_root: B256,
325 execution_requests: Vec<Bytes>,
326 ) -> TransportResult<PayloadStatus> {
327 self.client()
328 .request(
329 "engine_newPayloadV4",
330 (payload, versioned_hashes, parent_beacon_block_root, execution_requests),
331 )
332 .await
333 }
334
335 async fn new_payload_v4_requests(
336 &self,
337 payload: ExecutionPayloadV3,
338 versioned_hashes: Vec<B256>,
339 parent_beacon_block_root: B256,
340 execution_requests: RequestsOrHash,
341 ) -> TransportResult<PayloadStatus> {
342 self.client()
343 .request(
344 "engine_newPayloadV4",
345 (payload, versioned_hashes, parent_beacon_block_root, execution_requests),
346 )
347 .await
348 }
349
350 async fn new_payload_v5(
351 &self,
352 payload: ExecutionPayloadV4,
353 versioned_hashes: Vec<B256>,
354 parent_beacon_block_root: B256,
355 execution_requests: RequestsOrHash,
356 ) -> TransportResult<PayloadStatus> {
357 self.client()
358 .request(
359 "engine_newPayloadV5",
360 (payload, versioned_hashes, parent_beacon_block_root, execution_requests),
361 )
362 .await
363 }
364
365 async fn fork_choice_updated_v1(
366 &self,
367 fork_choice_state: ForkchoiceState,
368 payload_attributes: Option<PayloadAttributes>,
369 ) -> TransportResult<ForkchoiceUpdated> {
370 self.client()
371 .request("engine_forkchoiceUpdatedV1", (fork_choice_state, payload_attributes))
372 .await
373 }
374
375 async fn fork_choice_updated_v2(
376 &self,
377 fork_choice_state: ForkchoiceState,
378 payload_attributes: Option<PayloadAttributes>,
379 ) -> TransportResult<ForkchoiceUpdated> {
380 self.client()
381 .request("engine_forkchoiceUpdatedV2", (fork_choice_state, payload_attributes))
382 .await
383 }
384
385 async fn fork_choice_updated_v3(
386 &self,
387 fork_choice_state: ForkchoiceState,
388 payload_attributes: Option<PayloadAttributes>,
389 ) -> TransportResult<ForkchoiceUpdated> {
390 self.client()
391 .request("engine_forkchoiceUpdatedV3", (fork_choice_state, payload_attributes))
392 .await
393 }
394
395 async fn fork_choice_updated_v4(
396 &self,
397 fork_choice_state: ForkchoiceState,
398 payload_attributes: Option<PayloadAttributes>,
399 ) -> TransportResult<ForkchoiceUpdated> {
400 self.client()
401 .request("engine_forkchoiceUpdatedV4", (fork_choice_state, payload_attributes))
402 .await
403 }
404
405 async fn get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1> {
406 self.client().request("engine_getPayloadV1", (payload_id,)).await
407 }
408
409 async fn get_payload_v2(
410 &self,
411 payload_id: PayloadId,
412 ) -> TransportResult<ExecutionPayloadEnvelopeV2> {
413 self.client().request("engine_getPayloadV2", (payload_id,)).await
414 }
415
416 async fn get_payload_v3(
417 &self,
418 payload_id: PayloadId,
419 ) -> TransportResult<ExecutionPayloadEnvelopeV3> {
420 self.client().request("engine_getPayloadV3", (payload_id,)).await
421 }
422
423 async fn get_payload_v4(
424 &self,
425 payload_id: PayloadId,
426 ) -> TransportResult<ExecutionPayloadEnvelopeV4> {
427 self.client().request("engine_getPayloadV4", (payload_id,)).await
428 }
429
430 async fn get_payload_v5(
431 &self,
432 payload_id: PayloadId,
433 ) -> TransportResult<ExecutionPayloadEnvelopeV5> {
434 self.client().request("engine_getPayloadV5", (payload_id,)).await
435 }
436
437 async fn get_payload_v6(
438 &self,
439 payload_id: PayloadId,
440 ) -> TransportResult<ExecutionPayloadEnvelopeV6> {
441 self.client().request("engine_getPayloadV6", (payload_id,)).await
442 }
443
444 async fn get_payload_bodies_by_hash_v1(
445 &self,
446 block_hashes: Vec<BlockHash>,
447 ) -> TransportResult<ExecutionPayloadBodiesV1> {
448 self.client().request("engine_getPayloadBodiesByHashV1", (block_hashes,)).await
449 }
450
451 async fn get_payload_bodies_by_range_v1(
452 &self,
453 start: u64,
454 count: u64,
455 ) -> TransportResult<ExecutionPayloadBodiesV1> {
456 self.client()
457 .request("engine_getPayloadBodiesByRangeV1", (U64::from(start), U64::from(count)))
458 .await
459 }
460
461 async fn get_payload_bodies_by_hash_v2(
462 &self,
463 block_hashes: Vec<BlockHash>,
464 ) -> TransportResult<ExecutionPayloadBodiesV2> {
465 self.client().request("engine_getPayloadBodiesByHashV2", (block_hashes,)).await
466 }
467
468 async fn get_payload_bodies_by_range_v2(
469 &self,
470 start: u64,
471 count: u64,
472 ) -> TransportResult<ExecutionPayloadBodiesV2> {
473 self.client()
474 .request("engine_getPayloadBodiesByRangeV2", (U64::from(start), U64::from(count)))
475 .await
476 }
477
478 async fn get_blobs_v1(
479 &self,
480 versioned_hashes: Vec<B256>,
481 ) -> TransportResult<Vec<Option<BlobAndProofV1>>> {
482 self.client().request("engine_getBlobsV1", (versioned_hashes,)).await
483 }
484
485 async fn get_blobs_v2(
486 &self,
487 versioned_hashes: Vec<B256>,
488 ) -> TransportResult<Vec<Option<BlobAndProofV2>>> {
489 self.client().request("engine_getBlobsV2", (versioned_hashes,)).await
490 }
491
492 async fn get_client_version_v1(
493 &self,
494 client_version: ClientVersionV1,
495 ) -> TransportResult<Vec<ClientVersionV1>> {
496 self.client().request("engine_getClientVersionV1", (client_version,)).await
497 }
498
499 async fn exchange_capabilities(
500 &self,
501 capabilities: Vec<String>,
502 ) -> TransportResult<Vec<String>> {
503 self.client().request("engine_exchangeCapabilities", (capabilities,)).await
504 }
505}