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, ExecutionPayloadEnvelopeV5,
7 ExecutionPayloadInputV2, ExecutionPayloadV1, ExecutionPayloadV3, ForkchoiceState,
8 ForkchoiceUpdated, PayloadAttributes, PayloadId, PayloadStatus,
9};
10use alloy_transport::TransportResult;
11
12#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
14#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
15pub trait EngineApi<N>: Send + Sync {
16 async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> TransportResult<PayloadStatus>;
22
23 async fn new_payload_v2(
27 &self,
28 payload: ExecutionPayloadInputV2,
29 ) -> TransportResult<PayloadStatus>;
30
31 async fn new_payload_v3(
35 &self,
36 payload: ExecutionPayloadV3,
37 versioned_hashes: Vec<B256>,
38 parent_beacon_block_root: B256,
39 ) -> TransportResult<PayloadStatus>;
40
41 async fn new_payload_v4(
45 &self,
46 payload: ExecutionPayloadV3,
47 versioned_hashes: Vec<B256>,
48 parent_beacon_block_root: B256,
49 execution_requests: Vec<Bytes>,
50 ) -> TransportResult<PayloadStatus>;
51
52 async fn fork_choice_updated_v1(
59 &self,
60 fork_choice_state: ForkchoiceState,
61 payload_attributes: Option<PayloadAttributes>,
62 ) -> TransportResult<ForkchoiceUpdated>;
63
64 async fn fork_choice_updated_v2(
71 &self,
72 fork_choice_state: ForkchoiceState,
73 payload_attributes: Option<PayloadAttributes>,
74 ) -> TransportResult<ForkchoiceUpdated>;
75
76 async fn fork_choice_updated_v3(
81 &self,
82 fork_choice_state: ForkchoiceState,
83 payload_attributes: Option<PayloadAttributes>,
84 ) -> TransportResult<ForkchoiceUpdated>;
85
86 async fn get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1>;
96
97 async fn get_payload_v2(
105 &self,
106 payload_id: PayloadId,
107 ) -> TransportResult<ExecutionPayloadEnvelopeV2>;
108
109 async fn get_payload_v3(
117 &self,
118 payload_id: PayloadId,
119 ) -> TransportResult<ExecutionPayloadEnvelopeV3>;
120
121 async fn get_payload_v4(
129 &self,
130 payload_id: PayloadId,
131 ) -> TransportResult<ExecutionPayloadEnvelopeV4>;
132
133 async fn get_payload_v5(
141 &self,
142 payload_id: PayloadId,
143 ) -> TransportResult<ExecutionPayloadEnvelopeV5>;
144
145 async fn get_payload_bodies_by_hash_v1(
149 &self,
150 block_hashes: Vec<BlockHash>,
151 ) -> TransportResult<ExecutionPayloadBodiesV1>;
152
153 async fn get_payload_bodies_by_range_v1(
166 &self,
167 start: u64,
168 count: u64,
169 ) -> TransportResult<ExecutionPayloadBodiesV1>;
170
171 async fn get_client_version_v1(
178 &self,
179 client_version: ClientVersionV1,
180 ) -> TransportResult<Vec<ClientVersionV1>>;
181
182 async fn exchange_capabilities(
186 &self,
187 capabilities: Vec<String>,
188 ) -> TransportResult<Vec<String>>;
189}
190
191#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
192#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
193impl<N, P> EngineApi<N> for P
194where
195 N: Network,
196 P: Provider<N>,
197{
198 async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> TransportResult<PayloadStatus> {
199 self.client().request("engine_newPayloadV1", (payload,)).await
200 }
201
202 async fn new_payload_v2(
203 &self,
204 payload: ExecutionPayloadInputV2,
205 ) -> TransportResult<PayloadStatus> {
206 self.client().request("engine_newPayloadV2", (payload,)).await
207 }
208
209 async fn new_payload_v3(
210 &self,
211 payload: ExecutionPayloadV3,
212 versioned_hashes: Vec<B256>,
213 parent_beacon_block_root: B256,
214 ) -> TransportResult<PayloadStatus> {
215 self.client()
216 .request("engine_newPayloadV3", (payload, versioned_hashes, parent_beacon_block_root))
217 .await
218 }
219
220 async fn new_payload_v4(
221 &self,
222 payload: ExecutionPayloadV3,
223 versioned_hashes: Vec<B256>,
224 parent_beacon_block_root: B256,
225 execution_requests: Vec<Bytes>,
226 ) -> TransportResult<PayloadStatus> {
227 self.client()
228 .request(
229 "engine_newPayloadV4",
230 (payload, versioned_hashes, parent_beacon_block_root, execution_requests),
231 )
232 .await
233 }
234
235 async fn fork_choice_updated_v1(
236 &self,
237 fork_choice_state: ForkchoiceState,
238 payload_attributes: Option<PayloadAttributes>,
239 ) -> TransportResult<ForkchoiceUpdated> {
240 self.client()
241 .request("engine_forkchoiceUpdatedV1", (fork_choice_state, payload_attributes))
242 .await
243 }
244
245 async fn fork_choice_updated_v2(
246 &self,
247 fork_choice_state: ForkchoiceState,
248 payload_attributes: Option<PayloadAttributes>,
249 ) -> TransportResult<ForkchoiceUpdated> {
250 self.client()
251 .request("engine_forkchoiceUpdatedV2", (fork_choice_state, payload_attributes))
252 .await
253 }
254
255 async fn fork_choice_updated_v3(
256 &self,
257 fork_choice_state: ForkchoiceState,
258 payload_attributes: Option<PayloadAttributes>,
259 ) -> TransportResult<ForkchoiceUpdated> {
260 self.client()
261 .request("engine_forkchoiceUpdatedV3", (fork_choice_state, payload_attributes))
262 .await
263 }
264
265 async fn get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1> {
266 self.client().request("engine_getPayloadV1", (payload_id,)).await
267 }
268
269 async fn get_payload_v2(
270 &self,
271 payload_id: PayloadId,
272 ) -> TransportResult<ExecutionPayloadEnvelopeV2> {
273 self.client().request("engine_getPayloadV2", (payload_id,)).await
274 }
275
276 async fn get_payload_v3(
277 &self,
278 payload_id: PayloadId,
279 ) -> TransportResult<ExecutionPayloadEnvelopeV3> {
280 self.client().request("engine_getPayloadV3", (payload_id,)).await
281 }
282
283 async fn get_payload_v4(
284 &self,
285 payload_id: PayloadId,
286 ) -> TransportResult<ExecutionPayloadEnvelopeV4> {
287 self.client().request("engine_getPayloadV4", (payload_id,)).await
288 }
289
290 async fn get_payload_v5(
291 &self,
292 payload_id: PayloadId,
293 ) -> TransportResult<ExecutionPayloadEnvelopeV5> {
294 self.client().request("engine_getPayloadV5", (payload_id,)).await
295 }
296
297 async fn get_payload_bodies_by_hash_v1(
298 &self,
299 block_hashes: Vec<BlockHash>,
300 ) -> TransportResult<ExecutionPayloadBodiesV1> {
301 self.client().request("engine_getPayloadBodiesByHashV1", (block_hashes,)).await
302 }
303
304 async fn get_payload_bodies_by_range_v1(
305 &self,
306 start: u64,
307 count: u64,
308 ) -> TransportResult<ExecutionPayloadBodiesV1> {
309 self.client().request("engine_getPayloadBodiesByRangeV1", (start, count)).await
310 }
311
312 async fn get_client_version_v1(
313 &self,
314 client_version: ClientVersionV1,
315 ) -> TransportResult<Vec<ClientVersionV1>> {
316 self.client().request("engine_getClientVersionV1", (client_version,)).await
317 }
318
319 async fn exchange_capabilities(
320 &self,
321 capabilities: Vec<String>,
322 ) -> TransportResult<Vec<String>> {
323 self.client().request("engine_exchangeCapabilities", (capabilities,)).await
324 }
325}