1use crate::Provider;
2use alloy_eips::eip7685::RequestsOrHash;
3use alloy_network::Network;
4use alloy_primitives::{BlockHash, Bytes, B128, 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, ForkchoiceUpdatedResponseV2, PayloadAttributes, PayloadId,
11 PayloadStatus, PayloadStatusV2,
12};
13use alloy_transport::TransportResult;
14
15#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
17#[cfg_attr(not(target_family = "wasm"), 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 new_payload_v4_requests(
62 &self,
63 payload: ExecutionPayloadV3,
64 versioned_hashes: Vec<B256>,
65 parent_beacon_block_root: B256,
66 execution_requests: RequestsOrHash,
67 ) -> TransportResult<PayloadStatus>;
68
69 async fn new_payload_v5(
73 &self,
74 payload: ExecutionPayloadV4,
75 versioned_hashes: Vec<B256>,
76 parent_beacon_block_root: B256,
77 execution_requests: RequestsOrHash,
78 ) -> TransportResult<PayloadStatus>;
79
80 async fn new_payload_v6(
84 &self,
85 payload: ExecutionPayloadV4,
86 versioned_hashes: Vec<B256>,
87 parent_beacon_block_root: B256,
88 execution_requests: RequestsOrHash,
89 inclusion_list_transactions: Vec<Bytes>,
90 ) -> TransportResult<PayloadStatusV2>;
91
92 async fn fork_choice_updated_v1(
99 &self,
100 fork_choice_state: ForkchoiceState,
101 payload_attributes: Option<PayloadAttributes>,
102 ) -> TransportResult<ForkchoiceUpdated>;
103
104 async fn fork_choice_updated_v2(
111 &self,
112 fork_choice_state: ForkchoiceState,
113 payload_attributes: Option<PayloadAttributes>,
114 ) -> TransportResult<ForkchoiceUpdated>;
115
116 async fn fork_choice_updated_v3(
121 &self,
122 fork_choice_state: ForkchoiceState,
123 payload_attributes: Option<PayloadAttributes>,
124 ) -> TransportResult<ForkchoiceUpdated>;
125
126 async fn fork_choice_updated_v4(
131 &self,
132 fork_choice_state: ForkchoiceState,
133 payload_attributes: Option<PayloadAttributes>,
134 ) -> TransportResult<ForkchoiceUpdated>;
135
136 async fn fork_choice_updated_v5(
146 &self,
147 fork_choice_state: ForkchoiceState,
148 payload_attributes: Option<PayloadAttributes>,
149 custody_columns: Option<B128>,
150 ) -> TransportResult<ForkchoiceUpdatedResponseV2>;
151
152 async fn get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1>;
162
163 async fn get_payload_v2(
171 &self,
172 payload_id: PayloadId,
173 ) -> TransportResult<ExecutionPayloadEnvelopeV2>;
174
175 async fn get_payload_v3(
183 &self,
184 payload_id: PayloadId,
185 ) -> TransportResult<ExecutionPayloadEnvelopeV3>;
186
187 async fn get_payload_v4(
195 &self,
196 payload_id: PayloadId,
197 ) -> TransportResult<ExecutionPayloadEnvelopeV4>;
198
199 async fn get_payload_v5(
207 &self,
208 payload_id: PayloadId,
209 ) -> TransportResult<ExecutionPayloadEnvelopeV5>;
210
211 async fn get_payload_v6(
219 &self,
220 payload_id: PayloadId,
221 ) -> TransportResult<ExecutionPayloadEnvelopeV6>;
222
223 async fn get_payload_bodies_by_hash_v1(
227 &self,
228 block_hashes: Vec<BlockHash>,
229 ) -> TransportResult<ExecutionPayloadBodiesV1>;
230
231 async fn get_payload_bodies_by_range_v1(
244 &self,
245 start: u64,
246 count: u64,
247 ) -> TransportResult<ExecutionPayloadBodiesV1>;
248
249 async fn get_payload_bodies_by_hash_v2(
255 &self,
256 block_hashes: Vec<BlockHash>,
257 ) -> TransportResult<ExecutionPayloadBodiesV2>;
258
259 async fn get_payload_bodies_by_range_v2(
274 &self,
275 start: u64,
276 count: u64,
277 ) -> TransportResult<ExecutionPayloadBodiesV2>;
278
279 async fn get_blobs_v1(
285 &self,
286 versioned_hashes: Vec<B256>,
287 ) -> TransportResult<Vec<Option<BlobAndProofV1>>>;
288
289 async fn get_blobs_v2(
296 &self,
297 versioned_hashes: Vec<B256>,
298 ) -> TransportResult<Vec<Option<BlobAndProofV2>>>;
299
300 async fn get_client_version_v1(
307 &self,
308 client_version: ClientVersionV1,
309 ) -> TransportResult<Vec<ClientVersionV1>>;
310
311 async fn exchange_capabilities(
315 &self,
316 capabilities: Vec<String>,
317 ) -> TransportResult<Vec<String>>;
318}
319
320#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
321#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
322impl<N, P> EngineApi<N> for P
323where
324 N: Network,
325 P: Provider<N>,
326{
327 async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> TransportResult<PayloadStatus> {
328 self.client().request("engine_newPayloadV1", (payload,)).await
329 }
330
331 async fn new_payload_v2(
332 &self,
333 payload: ExecutionPayloadInputV2,
334 ) -> TransportResult<PayloadStatus> {
335 self.client().request("engine_newPayloadV2", (payload,)).await
336 }
337
338 async fn new_payload_v3(
339 &self,
340 payload: ExecutionPayloadV3,
341 versioned_hashes: Vec<B256>,
342 parent_beacon_block_root: B256,
343 ) -> TransportResult<PayloadStatus> {
344 self.client()
345 .request("engine_newPayloadV3", (payload, versioned_hashes, parent_beacon_block_root))
346 .await
347 }
348
349 async fn new_payload_v4(
350 &self,
351 payload: ExecutionPayloadV3,
352 versioned_hashes: Vec<B256>,
353 parent_beacon_block_root: B256,
354 execution_requests: Vec<Bytes>,
355 ) -> TransportResult<PayloadStatus> {
356 self.client()
357 .request(
358 "engine_newPayloadV4",
359 (payload, versioned_hashes, parent_beacon_block_root, execution_requests),
360 )
361 .await
362 }
363
364 async fn new_payload_v4_requests(
365 &self,
366 payload: ExecutionPayloadV3,
367 versioned_hashes: Vec<B256>,
368 parent_beacon_block_root: B256,
369 execution_requests: RequestsOrHash,
370 ) -> TransportResult<PayloadStatus> {
371 self.client()
372 .request(
373 "engine_newPayloadV4",
374 (payload, versioned_hashes, parent_beacon_block_root, execution_requests),
375 )
376 .await
377 }
378
379 async fn new_payload_v5(
380 &self,
381 payload: ExecutionPayloadV4,
382 versioned_hashes: Vec<B256>,
383 parent_beacon_block_root: B256,
384 execution_requests: RequestsOrHash,
385 ) -> TransportResult<PayloadStatus> {
386 self.client()
387 .request(
388 "engine_newPayloadV5",
389 (payload, versioned_hashes, parent_beacon_block_root, execution_requests),
390 )
391 .await
392 }
393
394 async fn new_payload_v6(
395 &self,
396 payload: ExecutionPayloadV4,
397 versioned_hashes: Vec<B256>,
398 parent_beacon_block_root: B256,
399 execution_requests: RequestsOrHash,
400 inclusion_list_transactions: Vec<Bytes>,
401 ) -> TransportResult<PayloadStatusV2> {
402 self.client()
403 .request(
404 "engine_newPayloadV6",
405 (
406 payload,
407 versioned_hashes,
408 parent_beacon_block_root,
409 execution_requests,
410 inclusion_list_transactions,
411 ),
412 )
413 .await
414 }
415
416 async fn fork_choice_updated_v1(
417 &self,
418 fork_choice_state: ForkchoiceState,
419 payload_attributes: Option<PayloadAttributes>,
420 ) -> TransportResult<ForkchoiceUpdated> {
421 self.client()
422 .request("engine_forkchoiceUpdatedV1", (fork_choice_state, payload_attributes))
423 .await
424 }
425
426 async fn fork_choice_updated_v2(
427 &self,
428 fork_choice_state: ForkchoiceState,
429 payload_attributes: Option<PayloadAttributes>,
430 ) -> TransportResult<ForkchoiceUpdated> {
431 self.client()
432 .request("engine_forkchoiceUpdatedV2", (fork_choice_state, payload_attributes))
433 .await
434 }
435
436 async fn fork_choice_updated_v3(
437 &self,
438 fork_choice_state: ForkchoiceState,
439 payload_attributes: Option<PayloadAttributes>,
440 ) -> TransportResult<ForkchoiceUpdated> {
441 self.client()
442 .request("engine_forkchoiceUpdatedV3", (fork_choice_state, payload_attributes))
443 .await
444 }
445
446 async fn fork_choice_updated_v4(
447 &self,
448 fork_choice_state: ForkchoiceState,
449 payload_attributes: Option<PayloadAttributes>,
450 ) -> TransportResult<ForkchoiceUpdated> {
451 self.client()
452 .request("engine_forkchoiceUpdatedV4", (fork_choice_state, payload_attributes))
453 .await
454 }
455
456 async fn fork_choice_updated_v5(
457 &self,
458 fork_choice_state: ForkchoiceState,
459 payload_attributes: Option<PayloadAttributes>,
460 custody_columns: Option<B128>,
461 ) -> TransportResult<ForkchoiceUpdatedResponseV2> {
462 self.client()
463 .request(
464 "engine_forkchoiceUpdatedV5",
465 (fork_choice_state, payload_attributes, custody_columns),
466 )
467 .await
468 }
469
470 async fn get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1> {
471 self.client().request("engine_getPayloadV1", (payload_id,)).await
472 }
473
474 async fn get_payload_v2(
475 &self,
476 payload_id: PayloadId,
477 ) -> TransportResult<ExecutionPayloadEnvelopeV2> {
478 self.client().request("engine_getPayloadV2", (payload_id,)).await
479 }
480
481 async fn get_payload_v3(
482 &self,
483 payload_id: PayloadId,
484 ) -> TransportResult<ExecutionPayloadEnvelopeV3> {
485 self.client().request("engine_getPayloadV3", (payload_id,)).await
486 }
487
488 async fn get_payload_v4(
489 &self,
490 payload_id: PayloadId,
491 ) -> TransportResult<ExecutionPayloadEnvelopeV4> {
492 self.client().request("engine_getPayloadV4", (payload_id,)).await
493 }
494
495 async fn get_payload_v5(
496 &self,
497 payload_id: PayloadId,
498 ) -> TransportResult<ExecutionPayloadEnvelopeV5> {
499 self.client().request("engine_getPayloadV5", (payload_id,)).await
500 }
501
502 async fn get_payload_v6(
503 &self,
504 payload_id: PayloadId,
505 ) -> TransportResult<ExecutionPayloadEnvelopeV6> {
506 self.client().request("engine_getPayloadV6", (payload_id,)).await
507 }
508
509 async fn get_payload_bodies_by_hash_v1(
510 &self,
511 block_hashes: Vec<BlockHash>,
512 ) -> TransportResult<ExecutionPayloadBodiesV1> {
513 self.client().request("engine_getPayloadBodiesByHashV1", (block_hashes,)).await
514 }
515
516 async fn get_payload_bodies_by_range_v1(
517 &self,
518 start: u64,
519 count: u64,
520 ) -> TransportResult<ExecutionPayloadBodiesV1> {
521 self.client()
522 .request("engine_getPayloadBodiesByRangeV1", (U64::from(start), U64::from(count)))
523 .await
524 }
525
526 async fn get_payload_bodies_by_hash_v2(
527 &self,
528 block_hashes: Vec<BlockHash>,
529 ) -> TransportResult<ExecutionPayloadBodiesV2> {
530 self.client().request("engine_getPayloadBodiesByHashV2", (block_hashes,)).await
531 }
532
533 async fn get_payload_bodies_by_range_v2(
534 &self,
535 start: u64,
536 count: u64,
537 ) -> TransportResult<ExecutionPayloadBodiesV2> {
538 self.client()
539 .request("engine_getPayloadBodiesByRangeV2", (U64::from(start), U64::from(count)))
540 .await
541 }
542
543 async fn get_blobs_v1(
544 &self,
545 versioned_hashes: Vec<B256>,
546 ) -> TransportResult<Vec<Option<BlobAndProofV1>>> {
547 self.client().request("engine_getBlobsV1", (versioned_hashes,)).await
548 }
549
550 async fn get_blobs_v2(
551 &self,
552 versioned_hashes: Vec<B256>,
553 ) -> TransportResult<Vec<Option<BlobAndProofV2>>> {
554 self.client().request("engine_getBlobsV2", (versioned_hashes,)).await
555 }
556
557 async fn get_client_version_v1(
558 &self,
559 client_version: ClientVersionV1,
560 ) -> TransportResult<Vec<ClientVersionV1>> {
561 self.client().request("engine_getClientVersionV1", (client_version,)).await
562 }
563
564 async fn exchange_capabilities(
565 &self,
566 capabilities: Vec<String>,
567 ) -> TransportResult<Vec<String>> {
568 self.client().request("engine_exchangeCapabilities", (capabilities,)).await
569 }
570}