1use crate::{
3 RpcHeader, RpcReceipt, RpcTransaction, RpcTxReq, RpcTypes, SignableTxRequest, TryIntoTxEnv,
4};
5use alloy_consensus::{error::ValueError, transaction::Recovered};
6use alloy_primitives::Address;
7use alloy_rpc_types_eth::TransactionInfo;
8use core::error;
9use dyn_clone::DynClone;
10use reth_evm::{BlockEnvFor, ConfigureEvm, EvmEnvFor, SpecFor, TxEnvFor};
11use reth_primitives_traits::{
12 BlockTy, HeaderTy, NodePrimitives, SealedBlock, SealedHeader, SealedHeaderFor, TransactionMeta,
13 TxTy,
14};
15use reth_rpc_traits::{FromConsensusHeader, FromConsensusTx, TryIntoSimTx, TxInfoMapper};
16use std::{convert::Infallible, error::Error, fmt, fmt::Debug, marker::PhantomData};
17
18#[derive(Debug, Clone)]
20pub struct ConvertReceiptInput<'a, N: NodePrimitives> {
21 pub receipt: N::Receipt,
23 pub tx: Recovered<&'a N::SignedTx>,
25 pub gas_used: u64,
27 pub next_log_index: usize,
29 pub meta: TransactionMeta,
31}
32
33pub trait ReceiptConverter<N: NodePrimitives>: Debug + 'static {
35 type RpcReceipt;
37
38 type Error;
40
41 fn convert_receipts(
44 &self,
45 receipts: Vec<ConvertReceiptInput<'_, N>>,
46 ) -> Result<Vec<Self::RpcReceipt>, Self::Error>;
47
48 fn convert_receipts_with_block(
51 &self,
52 receipts: Vec<ConvertReceiptInput<'_, N>>,
53 _block: &SealedBlock<N::Block>,
54 ) -> Result<Vec<Self::RpcReceipt>, Self::Error> {
55 self.convert_receipts(receipts)
56 }
57}
58
59pub trait HeaderConverter<Consensus, Rpc>: Send + Sync + Unpin + Clone + 'static {
61 type Err: error::Error;
63
64 fn convert_header(
66 &self,
67 header: SealedHeader<Consensus>,
68 block_size: usize,
69 ) -> Result<Rpc, Self::Err>;
70}
71
72impl<Consensus, Rpc> HeaderConverter<Consensus, Rpc> for ()
75where
76 Rpc: FromConsensusHeader<Consensus>,
77{
78 type Err = Infallible;
79
80 fn convert_header(
81 &self,
82 header: SealedHeader<Consensus>,
83 block_size: usize,
84 ) -> Result<Rpc, Self::Err> {
85 Ok(Rpc::from_consensus_header(header, block_size))
86 }
87}
88
89impl<Consensus, Rpc, F> HeaderConverter<Consensus, Rpc> for F
90where
91 F: Fn(SealedHeader<Consensus>, usize) -> Rpc + Send + Sync + Unpin + Clone + 'static,
92{
93 type Err = Infallible;
94
95 fn convert_header(
96 &self,
97 header: SealedHeader<Consensus>,
98 block_size: usize,
99 ) -> Result<Rpc, Self::Err> {
100 Ok(self(header, block_size))
101 }
102}
103
104#[auto_impl::auto_impl(&, Box, Arc)]
113pub trait RpcConvert: Send + Sync + Unpin + Debug + DynClone + 'static {
114 type Primitives: NodePrimitives;
116
117 type Evm: ConfigureEvm<Primitives = Self::Primitives>;
119
120 type Network: RpcTypes<TransactionRequest: SignableTxRequest<TxTy<Self::Primitives>>>;
123
124 type Error: error::Error + Into<jsonrpsee_types::ErrorObject<'static>>;
126
127 fn fill_pending(
131 &self,
132 tx: Recovered<TxTy<Self::Primitives>>,
133 ) -> Result<RpcTransaction<Self::Network>, Self::Error> {
134 self.fill(tx, TransactionInfo::default())
135 }
136
137 fn fill(
143 &self,
144 tx: Recovered<TxTy<Self::Primitives>>,
145 tx_info: TransactionInfo,
146 ) -> Result<RpcTransaction<Self::Network>, Self::Error>;
147
148 fn build_simulate_v1_transaction(
151 &self,
152 request: RpcTxReq<Self::Network>,
153 ) -> Result<TxTy<Self::Primitives>, Self::Error>;
154
155 fn tx_env(
158 &self,
159 request: RpcTxReq<Self::Network>,
160 evm_env: &EvmEnvFor<Self::Evm>,
161 ) -> Result<TxEnvFor<Self::Evm>, Self::Error>;
162
163 fn convert_receipts(
166 &self,
167 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
168 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error>;
169
170 fn convert_receipts_with_block(
175 &self,
176 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
177 block: &SealedBlock<BlockTy<Self::Primitives>>,
178 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error>;
179
180 fn convert_header(
182 &self,
183 header: SealedHeaderFor<Self::Primitives>,
184 block_size: usize,
185 ) -> Result<RpcHeader<Self::Network>, Self::Error>;
186}
187
188dyn_clone::clone_trait_object!(
189 <Primitives, Network, Error, Evm>
190 RpcConvert<Primitives = Primitives, Network = Network, Error = Error, Evm = Evm>
191);
192
193pub trait RpcTxConverter<Tx, RpcTx, TxInfo>: Clone + Unpin + Send + Sync + 'static {
213 type Err;
215
216 fn convert_rpc_tx(&self, tx: Tx, signer: Address, tx_info: TxInfo) -> Result<RpcTx, Self::Err>;
220}
221
222impl<Tx, RpcTx> RpcTxConverter<Tx, RpcTx, <RpcTx as FromConsensusTx<Tx>>::TxInfo> for ()
223where
224 RpcTx: FromConsensusTx<Tx>,
225{
226 type Err = RpcTx::Err;
227
228 fn convert_rpc_tx(
229 &self,
230 tx: Tx,
231 signer: Address,
232 tx_info: <RpcTx as FromConsensusTx<Tx>>::TxInfo,
233 ) -> Result<RpcTx, Self::Err> {
234 RpcTx::from_consensus_tx(tx, signer, tx_info)
235 }
236}
237
238impl<Tx, RpcTx, F, TxInfo, E> RpcTxConverter<Tx, RpcTx, TxInfo> for F
239where
240 F: Fn(Tx, Address, TxInfo) -> Result<RpcTx, E> + Clone + Unpin + Send + Sync + 'static,
241{
242 type Err = E;
243
244 fn convert_rpc_tx(&self, tx: Tx, signer: Address, tx_info: TxInfo) -> Result<RpcTx, Self::Err> {
245 self(tx, signer, tx_info)
246 }
247}
248
249pub trait SimTxConverter<TxReq, SimTx>: Clone + Unpin + Send + Sync + 'static {
265 type Err: Error;
267
268 fn convert_sim_tx(&self, tx_req: TxReq) -> Result<SimTx, Self::Err>;
272}
273
274impl<TxReq, SimTx> SimTxConverter<TxReq, SimTx> for ()
275where
276 TxReq: TryIntoSimTx<SimTx> + Debug,
277{
278 type Err = ValueError<TxReq>;
279
280 fn convert_sim_tx(&self, tx_req: TxReq) -> Result<SimTx, Self::Err> {
281 tx_req.try_into_sim_tx()
282 }
283}
284
285impl<TxReq, SimTx, F, E> SimTxConverter<TxReq, SimTx> for F
286where
287 TxReq: Debug,
288 E: Error,
289 F: Fn(TxReq) -> Result<SimTx, E> + Clone + Unpin + Send + Sync + 'static,
290{
291 type Err = E;
292
293 fn convert_sim_tx(&self, tx_req: TxReq) -> Result<SimTx, Self::Err> {
294 self(tx_req)
295 }
296}
297
298pub trait TxEnvConverter<TxReq, Evm: ConfigureEvm>:
314 Debug + Send + Sync + Unpin + Clone + 'static
315{
316 type Error;
318
319 fn convert_tx_env(
323 &self,
324 tx_req: TxReq,
325 evm_env: &EvmEnvFor<Evm>,
326 ) -> Result<TxEnvFor<Evm>, Self::Error>;
327}
328
329impl<TxReq, Evm> TxEnvConverter<TxReq, Evm> for ()
330where
331 TxReq: TryIntoTxEnv<TxEnvFor<Evm>, SpecFor<Evm>, BlockEnvFor<Evm>>,
332 Evm: ConfigureEvm,
333{
334 type Error = TxReq::Err;
335
336 fn convert_tx_env(
337 &self,
338 tx_req: TxReq,
339 evm_env: &EvmEnvFor<Evm>,
340 ) -> Result<TxEnvFor<Evm>, Self::Error> {
341 tx_req.try_into_tx_env(evm_env)
342 }
343}
344
345impl<F, TxReq, E, Evm> TxEnvConverter<TxReq, Evm> for F
347where
348 F: Fn(TxReq, &EvmEnvFor<Evm>) -> Result<TxEnvFor<Evm>, E>
349 + Debug
350 + Send
351 + Sync
352 + Unpin
353 + Clone
354 + 'static,
355 TxReq: Clone,
356 Evm: ConfigureEvm,
357 E: error::Error + Send + Sync + 'static,
358{
359 type Error = E;
360
361 fn convert_tx_env(
362 &self,
363 tx_req: TxReq,
364 evm_env: &EvmEnvFor<Evm>,
365 ) -> Result<TxEnvFor<Evm>, Self::Error> {
366 self(tx_req, evm_env)
367 }
368}
369
370#[derive(Debug, thiserror::Error)]
372pub enum TransactionConversionError {
373 #[error("Failed to convert transaction into RPC response: {0}")]
375 FromTxReq(String),
376
377 #[error("{0}")]
379 Other(String),
380}
381pub struct RpcConverter<
397 Network,
398 Evm,
399 Receipt,
400 Header = (),
401 Map = (),
402 SimTx = (),
403 RpcTx = (),
404 TxEnv = (),
405> {
406 network: PhantomData<Network>,
407 evm: PhantomData<Evm>,
408 receipt_converter: Receipt,
409 header_converter: Header,
410 mapper: Map,
411 tx_env_converter: TxEnv,
412 sim_tx_converter: SimTx,
413 rpc_tx_converter: RpcTx,
414}
415
416impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> fmt::Debug
417 for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
418{
419 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
420 f.debug_struct("RpcConverter").finish_non_exhaustive()
421 }
422}
423
424impl<Network, Evm, Receipt> RpcConverter<Network, Evm, Receipt> {
425 pub const fn new(receipt_converter: Receipt) -> Self {
427 Self {
428 network: PhantomData,
429 evm: PhantomData,
430 receipt_converter,
431 header_converter: (),
432 mapper: (),
433 tx_env_converter: (),
434 sim_tx_converter: (),
435 rpc_tx_converter: (),
436 }
437 }
438}
439
440impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
441 RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
442{
443 pub fn with_network<N>(
445 self,
446 ) -> RpcConverter<N, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> {
447 let Self {
448 receipt_converter,
449 header_converter,
450 mapper,
451 evm,
452 sim_tx_converter,
453 rpc_tx_converter,
454 tx_env_converter,
455 ..
456 } = self;
457 RpcConverter {
458 receipt_converter,
459 header_converter,
460 mapper,
461 network: Default::default(),
462 evm,
463 sim_tx_converter,
464 rpc_tx_converter,
465 tx_env_converter,
466 }
467 }
468
469 pub fn with_tx_env_converter<TxEnvNew>(
471 self,
472 tx_env_converter: TxEnvNew,
473 ) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnvNew> {
474 let Self {
475 receipt_converter,
476 header_converter,
477 mapper,
478 network,
479 evm,
480 sim_tx_converter,
481 rpc_tx_converter,
482 tx_env_converter: _,
483 ..
484 } = self;
485 RpcConverter {
486 receipt_converter,
487 header_converter,
488 mapper,
489 network,
490 evm,
491 sim_tx_converter,
492 rpc_tx_converter,
493 tx_env_converter,
494 }
495 }
496
497 pub fn with_header_converter<HeaderNew>(
499 self,
500 header_converter: HeaderNew,
501 ) -> RpcConverter<Network, Evm, Receipt, HeaderNew, Map, SimTx, RpcTx, TxEnv> {
502 let Self {
503 receipt_converter,
504 header_converter: _,
505 mapper,
506 network,
507 evm,
508 sim_tx_converter,
509 rpc_tx_converter,
510 tx_env_converter,
511 } = self;
512 RpcConverter {
513 receipt_converter,
514 header_converter,
515 mapper,
516 network,
517 evm,
518 sim_tx_converter,
519 rpc_tx_converter,
520 tx_env_converter,
521 }
522 }
523
524 pub fn with_mapper<MapNew>(
526 self,
527 mapper: MapNew,
528 ) -> RpcConverter<Network, Evm, Receipt, Header, MapNew, SimTx, RpcTx, TxEnv> {
529 let Self {
530 receipt_converter,
531 header_converter,
532 mapper: _,
533 network,
534 evm,
535 sim_tx_converter,
536 rpc_tx_converter,
537 tx_env_converter,
538 } = self;
539 RpcConverter {
540 receipt_converter,
541 header_converter,
542 mapper,
543 network,
544 evm,
545 sim_tx_converter,
546 rpc_tx_converter,
547 tx_env_converter,
548 }
549 }
550
551 pub fn with_sim_tx_converter<SimTxNew>(
553 self,
554 sim_tx_converter: SimTxNew,
555 ) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTxNew, RpcTx, TxEnv> {
556 let Self {
557 receipt_converter,
558 header_converter,
559 mapper,
560 network,
561 evm,
562 rpc_tx_converter,
563 tx_env_converter,
564 ..
565 } = self;
566 RpcConverter {
567 receipt_converter,
568 header_converter,
569 mapper,
570 network,
571 evm,
572 sim_tx_converter,
573 rpc_tx_converter,
574 tx_env_converter,
575 }
576 }
577
578 pub fn with_rpc_tx_converter<RpcTxNew>(
580 self,
581 rpc_tx_converter: RpcTxNew,
582 ) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTxNew, TxEnv> {
583 let Self {
584 receipt_converter,
585 header_converter,
586 mapper,
587 network,
588 evm,
589 sim_tx_converter,
590 tx_env_converter,
591 ..
592 } = self;
593 RpcConverter {
594 receipt_converter,
595 header_converter,
596 mapper,
597 network,
598 evm,
599 sim_tx_converter,
600 rpc_tx_converter,
601 tx_env_converter,
602 }
603 }
604
605 pub fn erased(
607 self,
608 ) -> Box<
609 dyn RpcConvert<
610 Primitives = <Self as RpcConvert>::Primitives,
611 Network = <Self as RpcConvert>::Network,
612 Error = <Self as RpcConvert>::Error,
613 Evm = <Self as RpcConvert>::Evm,
614 >,
615 >
616 where
617 Self: RpcConvert,
618 {
619 Box::new(self)
620 }
621}
622
623impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> Default
624 for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
625where
626 Receipt: Default,
627 Header: Default,
628 Map: Default,
629 SimTx: Default,
630 RpcTx: Default,
631 TxEnv: Default,
632{
633 fn default() -> Self {
634 Self {
635 network: Default::default(),
636 evm: Default::default(),
637 receipt_converter: Default::default(),
638 header_converter: Default::default(),
639 mapper: Default::default(),
640 sim_tx_converter: Default::default(),
641 rpc_tx_converter: Default::default(),
642 tx_env_converter: Default::default(),
643 }
644 }
645}
646
647impl<
648 Network,
649 Evm,
650 Receipt: Clone,
651 Header: Clone,
652 Map: Clone,
653 SimTx: Clone,
654 RpcTx: Clone,
655 TxEnv: Clone,
656 > Clone for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
657{
658 fn clone(&self) -> Self {
659 Self {
660 network: Default::default(),
661 evm: Default::default(),
662 receipt_converter: self.receipt_converter.clone(),
663 header_converter: self.header_converter.clone(),
664 mapper: self.mapper.clone(),
665 sim_tx_converter: self.sim_tx_converter.clone(),
666 rpc_tx_converter: self.rpc_tx_converter.clone(),
667 tx_env_converter: self.tx_env_converter.clone(),
668 }
669 }
670}
671
672impl<N, Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> RpcConvert
673 for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
674where
675 N: NodePrimitives,
676 Network: RpcTypes<TransactionRequest: SignableTxRequest<N::SignedTx>>,
677 Evm: ConfigureEvm<Primitives = N> + 'static,
678 Receipt: ReceiptConverter<
679 N,
680 RpcReceipt = RpcReceipt<Network>,
681 Error: From<TransactionConversionError>
682 + From<TxEnv::Error>
683 + From<<Map as TxInfoMapper<TxTy<N>>>::Err>
684 + From<RpcTx::Err>
685 + From<Header::Err>
686 + Error
687 + Unpin
688 + Sync
689 + Send
690 + Into<jsonrpsee_types::ErrorObject<'static>>,
691 > + Send
692 + Sync
693 + Unpin
694 + Clone
695 + Debug,
696 Header: HeaderConverter<HeaderTy<N>, RpcHeader<Network>>,
697 Map: TxInfoMapper<TxTy<N>> + Clone + Debug + Unpin + Send + Sync + 'static,
698 SimTx: SimTxConverter<RpcTxReq<Network>, TxTy<N>>,
699 RpcTx:
700 RpcTxConverter<TxTy<N>, Network::TransactionResponse, <Map as TxInfoMapper<TxTy<N>>>::Out>,
701 TxEnv: TxEnvConverter<RpcTxReq<Network>, Evm>,
702{
703 type Primitives = N;
704 type Evm = Evm;
705 type Network = Network;
706 type Error = Receipt::Error;
707
708 fn fill(
709 &self,
710 tx: Recovered<TxTy<N>>,
711 tx_info: TransactionInfo,
712 ) -> Result<Network::TransactionResponse, Self::Error> {
713 let (tx, signer) = tx.into_parts();
714 let tx_info = self.mapper.try_map(&tx, tx_info)?;
715
716 self.rpc_tx_converter.convert_rpc_tx(tx, signer, tx_info).map_err(Into::into)
717 }
718
719 fn build_simulate_v1_transaction(
720 &self,
721 request: RpcTxReq<Network>,
722 ) -> Result<TxTy<N>, Self::Error> {
723 Ok(self
724 .sim_tx_converter
725 .convert_sim_tx(request)
726 .map_err(|e| TransactionConversionError::FromTxReq(e.to_string()))?)
727 }
728
729 fn tx_env(
730 &self,
731 request: RpcTxReq<Network>,
732 evm_env: &EvmEnvFor<Evm>,
733 ) -> Result<TxEnvFor<Evm>, Self::Error> {
734 self.tx_env_converter.convert_tx_env(request, evm_env).map_err(Into::into)
735 }
736
737 fn convert_receipts(
738 &self,
739 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
740 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error> {
741 self.receipt_converter.convert_receipts(receipts)
742 }
743
744 fn convert_receipts_with_block(
745 &self,
746 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
747 block: &SealedBlock<BlockTy<Self::Primitives>>,
748 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error> {
749 self.receipt_converter.convert_receipts_with_block(receipts, block)
750 }
751
752 fn convert_header(
753 &self,
754 header: SealedHeaderFor<Self::Primitives>,
755 block_size: usize,
756 ) -> Result<RpcHeader<Self::Network>, Self::Error> {
757 Ok(self.header_converter.convert_header(header, block_size)?)
758 }
759}