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 get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1>;
123
124 async fn get_payload_v2(
132 &self,
133 payload_id: PayloadId,
134 ) -> TransportResult<ExecutionPayloadEnvelopeV2>;
135
136 async fn get_payload_v3(
144 &self,
145 payload_id: PayloadId,
146 ) -> TransportResult<ExecutionPayloadEnvelopeV3>;
147
148 async fn get_payload_v4(
156 &self,
157 payload_id: PayloadId,
158 ) -> TransportResult<ExecutionPayloadEnvelopeV4>;
159
160 async fn get_payload_v5(
168 &self,
169 payload_id: PayloadId,
170 ) -> TransportResult<ExecutionPayloadEnvelopeV5>;
171
172 async fn get_payload_v6(
180 &self,
181 payload_id: PayloadId,
182 ) -> TransportResult<ExecutionPayloadEnvelopeV6>;
183
184 async fn get_payload_bodies_by_hash_v1(
188 &self,
189 block_hashes: Vec<BlockHash>,
190 ) -> TransportResult<ExecutionPayloadBodiesV1>;
191
192 async fn get_payload_bodies_by_range_v1(
205 &self,
206 start: u64,
207 count: u64,
208 ) -> TransportResult<ExecutionPayloadBodiesV1>;
209
210 async fn get_payload_bodies_by_hash_v2(
216 &self,
217 block_hashes: Vec<BlockHash>,
218 ) -> TransportResult<ExecutionPayloadBodiesV2>;
219
220 async fn get_payload_bodies_by_range_v2(
235 &self,
236 start: u64,
237 count: u64,
238 ) -> TransportResult<ExecutionPayloadBodiesV2>;
239
240 async fn get_bals_by_hash_v1(
244 &self,
245 block_hashes: Vec<BlockHash>,
246 ) -> TransportResult<Vec<Bytes>>;
247
248 async fn get_bals_by_range_v1(&self, start: u64, count: u64) -> TransportResult<Vec<Bytes>>;
252
253 async fn get_blobs_v1(
259 &self,
260 versioned_hashes: Vec<B256>,
261 ) -> TransportResult<Vec<Option<BlobAndProofV1>>>;
262
263 async fn get_blobs_v2(
270 &self,
271 versioned_hashes: Vec<B256>,
272 ) -> TransportResult<Vec<Option<BlobAndProofV2>>>;
273
274 async fn get_client_version_v1(
281 &self,
282 client_version: ClientVersionV1,
283 ) -> TransportResult<Vec<ClientVersionV1>>;
284
285 async fn exchange_capabilities(
289 &self,
290 capabilities: Vec<String>,
291 ) -> TransportResult<Vec<String>>;
292}
293
294#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
295#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
296impl<N, P> EngineApi<N> for P
297where
298 N: Network,
299 P: Provider<N>,
300{
301 async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> TransportResult<PayloadStatus> {
302 self.client().request("engine_newPayloadV1", (payload,)).await
303 }
304
305 async fn new_payload_v2(
306 &self,
307 payload: ExecutionPayloadInputV2,
308 ) -> TransportResult<PayloadStatus> {
309 self.client().request("engine_newPayloadV2", (payload,)).await
310 }
311
312 async fn new_payload_v3(
313 &self,
314 payload: ExecutionPayloadV3,
315 versioned_hashes: Vec<B256>,
316 parent_beacon_block_root: B256,
317 ) -> TransportResult<PayloadStatus> {
318 self.client()
319 .request("engine_newPayloadV3", (payload, versioned_hashes, parent_beacon_block_root))
320 .await
321 }
322
323 async fn new_payload_v4(
324 &self,
325 payload: ExecutionPayloadV3,
326 versioned_hashes: Vec<B256>,
327 parent_beacon_block_root: B256,
328 execution_requests: Vec<Bytes>,
329 ) -> TransportResult<PayloadStatus> {
330 self.client()
331 .request(
332 "engine_newPayloadV4",
333 (payload, versioned_hashes, parent_beacon_block_root, execution_requests),
334 )
335 .await
336 }
337
338 async fn new_payload_v4_requests(
339 &self,
340 payload: ExecutionPayloadV3,
341 versioned_hashes: Vec<B256>,
342 parent_beacon_block_root: B256,
343 execution_requests: RequestsOrHash,
344 ) -> TransportResult<PayloadStatus> {
345 self.client()
346 .request(
347 "engine_newPayloadV4",
348 (payload, versioned_hashes, parent_beacon_block_root, execution_requests),
349 )
350 .await
351 }
352
353 async fn new_payload_v5(
354 &self,
355 payload: ExecutionPayloadV4,
356 versioned_hashes: Vec<B256>,
357 parent_beacon_block_root: B256,
358 execution_requests: RequestsOrHash,
359 ) -> TransportResult<PayloadStatus> {
360 self.client()
361 .request(
362 "engine_newPayloadV5",
363 (payload, versioned_hashes, parent_beacon_block_root, execution_requests),
364 )
365 .await
366 }
367
368 async fn fork_choice_updated_v1(
369 &self,
370 fork_choice_state: ForkchoiceState,
371 payload_attributes: Option<PayloadAttributes>,
372 ) -> TransportResult<ForkchoiceUpdated> {
373 self.client()
374 .request("engine_forkchoiceUpdatedV1", (fork_choice_state, payload_attributes))
375 .await
376 }
377
378 async fn fork_choice_updated_v2(
379 &self,
380 fork_choice_state: ForkchoiceState,
381 payload_attributes: Option<PayloadAttributes>,
382 ) -> TransportResult<ForkchoiceUpdated> {
383 self.client()
384 .request("engine_forkchoiceUpdatedV2", (fork_choice_state, payload_attributes))
385 .await
386 }
387
388 async fn fork_choice_updated_v3(
389 &self,
390 fork_choice_state: ForkchoiceState,
391 payload_attributes: Option<PayloadAttributes>,
392 ) -> TransportResult<ForkchoiceUpdated> {
393 self.client()
394 .request("engine_forkchoiceUpdatedV3", (fork_choice_state, payload_attributes))
395 .await
396 }
397
398 async fn get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1> {
399 self.client().request("engine_getPayloadV1", (payload_id,)).await
400 }
401
402 async fn get_payload_v2(
403 &self,
404 payload_id: PayloadId,
405 ) -> TransportResult<ExecutionPayloadEnvelopeV2> {
406 self.client().request("engine_getPayloadV2", (payload_id,)).await
407 }
408
409 async fn get_payload_v3(
410 &self,
411 payload_id: PayloadId,
412 ) -> TransportResult<ExecutionPayloadEnvelopeV3> {
413 self.client().request("engine_getPayloadV3", (payload_id,)).await
414 }
415
416 async fn get_payload_v4(
417 &self,
418 payload_id: PayloadId,
419 ) -> TransportResult<ExecutionPayloadEnvelopeV4> {
420 self.client().request("engine_getPayloadV4", (payload_id,)).await
421 }
422
423 async fn get_payload_v5(
424 &self,
425 payload_id: PayloadId,
426 ) -> TransportResult<ExecutionPayloadEnvelopeV5> {
427 self.client().request("engine_getPayloadV5", (payload_id,)).await
428 }
429
430 async fn get_payload_v6(
431 &self,
432 payload_id: PayloadId,
433 ) -> TransportResult<ExecutionPayloadEnvelopeV6> {
434 self.client().request("engine_getPayloadV6", (payload_id,)).await
435 }
436
437 async fn get_payload_bodies_by_hash_v1(
438 &self,
439 block_hashes: Vec<BlockHash>,
440 ) -> TransportResult<ExecutionPayloadBodiesV1> {
441 self.client().request("engine_getPayloadBodiesByHashV1", (block_hashes,)).await
442 }
443
444 async fn get_payload_bodies_by_range_v1(
445 &self,
446 start: u64,
447 count: u64,
448 ) -> TransportResult<ExecutionPayloadBodiesV1> {
449 self.client()
450 .request("engine_getPayloadBodiesByRangeV1", (U64::from(start), U64::from(count)))
451 .await
452 }
453
454 async fn get_payload_bodies_by_hash_v2(
455 &self,
456 block_hashes: Vec<BlockHash>,
457 ) -> TransportResult<ExecutionPayloadBodiesV2> {
458 self.client().request("engine_getPayloadBodiesByHashV2", (block_hashes,)).await
459 }
460
461 async fn get_payload_bodies_by_range_v2(
462 &self,
463 start: u64,
464 count: u64,
465 ) -> TransportResult<ExecutionPayloadBodiesV2> {
466 self.client()
467 .request("engine_getPayloadBodiesByRangeV2", (U64::from(start), U64::from(count)))
468 .await
469 }
470
471 async fn get_bals_by_hash_v1(
472 &self,
473 block_hashes: Vec<BlockHash>,
474 ) -> TransportResult<Vec<Bytes>> {
475 self.client().request("engine_getBALsByHashV1", (block_hashes,)).await
476 }
477
478 async fn get_bals_by_range_v1(&self, start: u64, count: u64) -> TransportResult<Vec<Bytes>> {
479 self.client().request("engine_getBALsByRangeV1", (U64::from(start), U64::from(count))).await
480 }
481
482 async fn get_blobs_v1(
483 &self,
484 versioned_hashes: Vec<B256>,
485 ) -> TransportResult<Vec<Option<BlobAndProofV1>>> {
486 self.client().request("engine_getBlobsV1", (versioned_hashes,)).await
487 }
488
489 async fn get_blobs_v2(
490 &self,
491 versioned_hashes: Vec<B256>,
492 ) -> TransportResult<Vec<Option<BlobAndProofV2>>> {
493 self.client().request("engine_getBlobsV2", (versioned_hashes,)).await
494 }
495
496 async fn get_client_version_v1(
497 &self,
498 client_version: ClientVersionV1,
499 ) -> TransportResult<Vec<ClientVersionV1>> {
500 self.client().request("engine_getClientVersionV1", (client_version,)).await
501 }
502
503 async fn exchange_capabilities(
504 &self,
505 capabilities: Vec<String>,
506 ) -> TransportResult<Vec<String>> {
507 self.client().request("engine_exchangeCapabilities", (capabilities,)).await
508 }
509}