1use crate::{
3 RpcHeader, RpcLog, RpcReceipt, RpcTransaction, RpcTxReq, RpcTypes, SignableTxRequest,
4 TryIntoTxEnv,
5};
6use alloy_consensus::{error::ValueError, transaction::Recovered};
7use alloy_primitives::Address;
8use alloy_rpc_types_eth::{Log, TransactionInfo};
9use core::error;
10use dyn_clone::DynClone;
11use reth_evm::{BlockEnvFor, ConfigureEvm, EvmEnvFor, SpecFor, TxEnvFor};
12use reth_primitives_traits::{
13 BlockTy, HeaderTy, NodePrimitives, SealedBlock, SealedHeader, SealedHeaderFor, TransactionMeta,
14 TxTy,
15};
16use reth_rpc_traits::{FromConsensusHeader, FromConsensusTx, TryIntoSimTx, TxInfoMapper};
17use std::{convert::Infallible, error::Error, fmt, fmt::Debug, marker::PhantomData};
18
19#[derive(Debug, Clone)]
21pub struct ConvertReceiptInput<'a, N: NodePrimitives> {
22 pub receipt: N::Receipt,
24 pub tx: Recovered<&'a N::SignedTx>,
26 pub gas_used: u64,
28 pub next_log_index: usize,
30 pub meta: TransactionMeta,
32}
33
34pub trait ReceiptConverter<N: NodePrimitives>: Debug + 'static {
36 type RpcReceipt;
38
39 type RpcLog;
41
42 type Error;
44
45 fn convert_log(
47 &self,
48 log: Log,
49 receipt: &N::Receipt,
50 header: &SealedHeaderFor<N>,
51 ) -> Result<Self::RpcLog, Self::Error>;
52
53 fn convert_receipts(
56 &self,
57 receipts: Vec<ConvertReceiptInput<'_, N>>,
58 ) -> Result<Vec<Self::RpcReceipt>, Self::Error>;
59
60 fn convert_receipts_with_block(
62 &self,
63 receipts: Vec<ConvertReceiptInput<'_, N>>,
64 _block: &SealedBlock<N::Block>,
65 ) -> Result<Vec<Self::RpcReceipt>, Self::Error> {
66 self.convert_receipts(receipts)
67 }
68}
69
70pub trait HeaderConverter<Consensus, Rpc>: Send + Sync + Unpin + Clone + 'static {
72 type Err: error::Error;
74
75 fn convert_header(
77 &self,
78 header: SealedHeader<Consensus>,
79 block_size: Option<usize>,
80 ) -> Result<Rpc, Self::Err>;
81}
82
83impl<Consensus, Rpc> HeaderConverter<Consensus, Rpc> for ()
86where
87 Rpc: FromConsensusHeader<Consensus>,
88{
89 type Err = Infallible;
90
91 fn convert_header(
92 &self,
93 header: SealedHeader<Consensus>,
94 block_size: Option<usize>,
95 ) -> Result<Rpc, Self::Err> {
96 Ok(Rpc::from_consensus_header(header, block_size))
97 }
98}
99
100impl<Consensus, Rpc, F> HeaderConverter<Consensus, Rpc> for F
101where
102 F: Fn(SealedHeader<Consensus>, Option<usize>) -> Rpc + Send + Sync + Unpin + Clone + 'static,
103{
104 type Err = Infallible;
105
106 fn convert_header(
107 &self,
108 header: SealedHeader<Consensus>,
109 block_size: Option<usize>,
110 ) -> Result<Rpc, Self::Err> {
111 Ok(self(header, block_size))
112 }
113}
114
115#[auto_impl::auto_impl(&, Box, Arc)]
124pub trait RpcConvert: Send + Sync + Unpin + Debug + DynClone + 'static {
125 type Primitives: NodePrimitives;
127
128 type Evm: ConfigureEvm<Primitives = Self::Primitives>;
130
131 type Network: RpcTypes<TransactionRequest: SignableTxRequest<TxTy<Self::Primitives>>>;
134
135 type Error: error::Error + Into<jsonrpsee_types::ErrorObject<'static>>;
137
138 fn fill_pending(
142 &self,
143 tx: Recovered<TxTy<Self::Primitives>>,
144 ) -> Result<RpcTransaction<Self::Network>, Self::Error> {
145 self.fill(tx, TransactionInfo::default())
146 }
147
148 fn fill(
154 &self,
155 tx: Recovered<TxTy<Self::Primitives>>,
156 tx_info: TransactionInfo,
157 ) -> Result<RpcTransaction<Self::Network>, Self::Error>;
158
159 fn build_simulate_v1_transaction(
162 &self,
163 request: RpcTxReq<Self::Network>,
164 ) -> Result<TxTy<Self::Primitives>, Self::Error>;
165
166 fn tx_env(
169 &self,
170 request: RpcTxReq<Self::Network>,
171 evm_env: &EvmEnvFor<Self::Evm>,
172 ) -> Result<TxEnvFor<Self::Evm>, Self::Error>;
173
174 fn convert_log(
176 &self,
177 log: Log,
178 receipt: &<Self::Primitives as NodePrimitives>::Receipt,
179 header: &SealedHeaderFor<Self::Primitives>,
180 ) -> Result<RpcLog<Self::Network>, Self::Error>;
181
182 fn convert_receipts(
185 &self,
186 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
187 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error>;
188
189 fn convert_receipts_with_block(
191 &self,
192 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
193 block: &SealedBlock<BlockTy<Self::Primitives>>,
194 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error>;
195
196 fn convert_header(
198 &self,
199 header: SealedHeaderFor<Self::Primitives>,
200 block_size: Option<usize>,
201 ) -> Result<RpcHeader<Self::Network>, Self::Error>;
202}
203
204dyn_clone::clone_trait_object!(
205 <Primitives, Network, Error, Evm>
206 RpcConvert<Primitives = Primitives, Network = Network, Error = Error, Evm = Evm>
207);
208
209pub trait RpcTxConverter<Tx, RpcTx, TxInfo>: Clone + Unpin + Send + Sync + 'static {
229 type Err;
231
232 fn convert_rpc_tx(&self, tx: Tx, signer: Address, tx_info: TxInfo) -> Result<RpcTx, Self::Err>;
236}
237
238impl<Tx, RpcTx> RpcTxConverter<Tx, RpcTx, <RpcTx as FromConsensusTx<Tx>>::TxInfo> for ()
239where
240 RpcTx: FromConsensusTx<Tx>,
241{
242 type Err = RpcTx::Err;
243
244 fn convert_rpc_tx(
245 &self,
246 tx: Tx,
247 signer: Address,
248 tx_info: <RpcTx as FromConsensusTx<Tx>>::TxInfo,
249 ) -> Result<RpcTx, Self::Err> {
250 RpcTx::from_consensus_tx(tx, signer, tx_info)
251 }
252}
253
254impl<Tx, RpcTx, F, TxInfo, E> RpcTxConverter<Tx, RpcTx, TxInfo> for F
255where
256 F: Fn(Tx, Address, TxInfo) -> Result<RpcTx, E> + Clone + Unpin + Send + Sync + 'static,
257{
258 type Err = E;
259
260 fn convert_rpc_tx(&self, tx: Tx, signer: Address, tx_info: TxInfo) -> Result<RpcTx, Self::Err> {
261 self(tx, signer, tx_info)
262 }
263}
264
265pub trait SimTxConverter<TxReq, SimTx>: Clone + Unpin + Send + Sync + 'static {
281 type Err: Error;
283
284 fn convert_sim_tx(&self, tx_req: TxReq) -> Result<SimTx, Self::Err>;
288}
289
290impl<TxReq, SimTx> SimTxConverter<TxReq, SimTx> for ()
291where
292 TxReq: TryIntoSimTx<SimTx> + Debug,
293{
294 type Err = ValueError<TxReq>;
295
296 fn convert_sim_tx(&self, tx_req: TxReq) -> Result<SimTx, Self::Err> {
297 tx_req.try_into_sim_tx()
298 }
299}
300
301impl<TxReq, SimTx, F, E> SimTxConverter<TxReq, SimTx> for F
302where
303 TxReq: Debug,
304 E: Error,
305 F: Fn(TxReq) -> Result<SimTx, E> + Clone + Unpin + Send + Sync + 'static,
306{
307 type Err = E;
308
309 fn convert_sim_tx(&self, tx_req: TxReq) -> Result<SimTx, Self::Err> {
310 self(tx_req)
311 }
312}
313
314pub trait TxEnvConverter<TxReq, Evm: ConfigureEvm>:
330 Debug + Send + Sync + Unpin + Clone + 'static
331{
332 type Error;
334
335 fn convert_tx_env(
339 &self,
340 tx_req: TxReq,
341 evm_env: &EvmEnvFor<Evm>,
342 ) -> Result<TxEnvFor<Evm>, Self::Error>;
343}
344
345impl<TxReq, Evm> TxEnvConverter<TxReq, Evm> for ()
346where
347 TxReq: TryIntoTxEnv<TxEnvFor<Evm>, SpecFor<Evm>, BlockEnvFor<Evm>>,
348 Evm: ConfigureEvm,
349{
350 type Error = TxReq::Err;
351
352 fn convert_tx_env(
353 &self,
354 tx_req: TxReq,
355 evm_env: &EvmEnvFor<Evm>,
356 ) -> Result<TxEnvFor<Evm>, Self::Error> {
357 tx_req.try_into_tx_env(evm_env)
358 }
359}
360
361impl<F, TxReq, E, Evm> TxEnvConverter<TxReq, Evm> for F
363where
364 F: Fn(TxReq, &EvmEnvFor<Evm>) -> Result<TxEnvFor<Evm>, E>
365 + Debug
366 + Send
367 + Sync
368 + Unpin
369 + Clone
370 + 'static,
371 TxReq: Clone,
372 Evm: ConfigureEvm,
373 E: error::Error + Send + Sync + 'static,
374{
375 type Error = E;
376
377 fn convert_tx_env(
378 &self,
379 tx_req: TxReq,
380 evm_env: &EvmEnvFor<Evm>,
381 ) -> Result<TxEnvFor<Evm>, Self::Error> {
382 self(tx_req, evm_env)
383 }
384}
385
386#[derive(Debug, thiserror::Error)]
388pub enum TransactionConversionError {
389 #[error("Failed to convert transaction into RPC response: {0}")]
391 FromTxReq(String),
392
393 #[error("{0}")]
395 Other(String),
396}
397pub struct RpcConverter<
413 Network,
414 Evm,
415 Receipt,
416 Header = (),
417 Map = (),
418 SimTx = (),
419 RpcTx = (),
420 TxEnv = (),
421> {
422 network: PhantomData<Network>,
423 evm: PhantomData<Evm>,
424 receipt_converter: Receipt,
425 header_converter: Header,
426 mapper: Map,
427 tx_env_converter: TxEnv,
428 sim_tx_converter: SimTx,
429 rpc_tx_converter: RpcTx,
430}
431
432impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> fmt::Debug
433 for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
434{
435 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
436 f.debug_struct("RpcConverter").finish_non_exhaustive()
437 }
438}
439
440impl<Network, Evm, Receipt> RpcConverter<Network, Evm, Receipt> {
441 pub const fn new(receipt_converter: Receipt) -> Self {
443 Self {
444 network: PhantomData,
445 evm: PhantomData,
446 receipt_converter,
447 header_converter: (),
448 mapper: (),
449 tx_env_converter: (),
450 sim_tx_converter: (),
451 rpc_tx_converter: (),
452 }
453 }
454}
455
456impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
457 RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
458{
459 pub fn with_network<N>(
461 self,
462 ) -> RpcConverter<N, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> {
463 let Self {
464 receipt_converter,
465 header_converter,
466 mapper,
467 evm,
468 sim_tx_converter,
469 rpc_tx_converter,
470 tx_env_converter,
471 ..
472 } = self;
473 RpcConverter {
474 receipt_converter,
475 header_converter,
476 mapper,
477 network: Default::default(),
478 evm,
479 sim_tx_converter,
480 rpc_tx_converter,
481 tx_env_converter,
482 }
483 }
484
485 pub fn with_tx_env_converter<TxEnvNew>(
487 self,
488 tx_env_converter: TxEnvNew,
489 ) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnvNew> {
490 let Self {
491 receipt_converter,
492 header_converter,
493 mapper,
494 network,
495 evm,
496 sim_tx_converter,
497 rpc_tx_converter,
498 ..
499 } = self;
500 RpcConverter {
501 receipt_converter,
502 header_converter,
503 mapper,
504 network,
505 evm,
506 sim_tx_converter,
507 rpc_tx_converter,
508 tx_env_converter,
509 }
510 }
511
512 pub fn with_header_converter<HeaderNew>(
514 self,
515 header_converter: HeaderNew,
516 ) -> RpcConverter<Network, Evm, Receipt, HeaderNew, Map, SimTx, RpcTx, TxEnv> {
517 let Self {
518 receipt_converter,
519 header_converter: _,
520 mapper,
521 network,
522 evm,
523 sim_tx_converter,
524 rpc_tx_converter,
525 tx_env_converter,
526 } = self;
527 RpcConverter {
528 receipt_converter,
529 header_converter,
530 mapper,
531 network,
532 evm,
533 sim_tx_converter,
534 rpc_tx_converter,
535 tx_env_converter,
536 }
537 }
538
539 pub fn with_mapper<MapNew>(
541 self,
542 mapper: MapNew,
543 ) -> RpcConverter<Network, Evm, Receipt, Header, MapNew, SimTx, RpcTx, TxEnv> {
544 let Self {
545 receipt_converter,
546 header_converter,
547 mapper: _,
548 network,
549 evm,
550 sim_tx_converter,
551 rpc_tx_converter,
552 tx_env_converter,
553 } = self;
554 RpcConverter {
555 receipt_converter,
556 header_converter,
557 mapper,
558 network,
559 evm,
560 sim_tx_converter,
561 rpc_tx_converter,
562 tx_env_converter,
563 }
564 }
565
566 pub fn with_sim_tx_converter<SimTxNew>(
568 self,
569 sim_tx_converter: SimTxNew,
570 ) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTxNew, RpcTx, TxEnv> {
571 let Self {
572 receipt_converter,
573 header_converter,
574 mapper,
575 network,
576 evm,
577 rpc_tx_converter,
578 tx_env_converter,
579 ..
580 } = self;
581 RpcConverter {
582 receipt_converter,
583 header_converter,
584 mapper,
585 network,
586 evm,
587 sim_tx_converter,
588 rpc_tx_converter,
589 tx_env_converter,
590 }
591 }
592
593 pub fn with_rpc_tx_converter<RpcTxNew>(
595 self,
596 rpc_tx_converter: RpcTxNew,
597 ) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTxNew, TxEnv> {
598 let Self {
599 receipt_converter,
600 header_converter,
601 mapper,
602 network,
603 evm,
604 sim_tx_converter,
605 tx_env_converter,
606 ..
607 } = self;
608 RpcConverter {
609 receipt_converter,
610 header_converter,
611 mapper,
612 network,
613 evm,
614 sim_tx_converter,
615 rpc_tx_converter,
616 tx_env_converter,
617 }
618 }
619
620 pub fn erased(
622 self,
623 ) -> Box<
624 dyn RpcConvert<
625 Primitives = <Self as RpcConvert>::Primitives,
626 Network = <Self as RpcConvert>::Network,
627 Error = <Self as RpcConvert>::Error,
628 Evm = <Self as RpcConvert>::Evm,
629 >,
630 >
631 where
632 Self: RpcConvert,
633 {
634 Box::new(self)
635 }
636}
637
638impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> Default
639 for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
640where
641 Receipt: Default,
642 Header: Default,
643 Map: Default,
644 SimTx: Default,
645 RpcTx: Default,
646 TxEnv: Default,
647{
648 fn default() -> Self {
649 Self {
650 network: Default::default(),
651 evm: Default::default(),
652 receipt_converter: Default::default(),
653 header_converter: Default::default(),
654 mapper: Default::default(),
655 sim_tx_converter: Default::default(),
656 rpc_tx_converter: Default::default(),
657 tx_env_converter: Default::default(),
658 }
659 }
660}
661
662impl<
663 Network,
664 Evm,
665 Receipt: Clone,
666 Header: Clone,
667 Map: Clone,
668 SimTx: Clone,
669 RpcTx: Clone,
670 TxEnv: Clone,
671 > Clone for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
672{
673 fn clone(&self) -> Self {
674 Self {
675 network: Default::default(),
676 evm: Default::default(),
677 receipt_converter: self.receipt_converter.clone(),
678 header_converter: self.header_converter.clone(),
679 mapper: self.mapper.clone(),
680 sim_tx_converter: self.sim_tx_converter.clone(),
681 rpc_tx_converter: self.rpc_tx_converter.clone(),
682 tx_env_converter: self.tx_env_converter.clone(),
683 }
684 }
685}
686
687impl<N, Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> RpcConvert
688 for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
689where
690 N: NodePrimitives,
691 Network: RpcTypes<TransactionRequest: SignableTxRequest<N::SignedTx>>,
692 Evm: ConfigureEvm<Primitives = N> + 'static,
693 Receipt: ReceiptConverter<
694 N,
695 RpcReceipt = RpcReceipt<Network>,
696 RpcLog = RpcLog<Network>,
697 Error: From<TransactionConversionError>
698 + From<TxEnv::Error>
699 + From<<Map as TxInfoMapper<TxTy<N>>>::Err>
700 + From<RpcTx::Err>
701 + From<Header::Err>
702 + Error
703 + Unpin
704 + Sync
705 + Send
706 + Into<jsonrpsee_types::ErrorObject<'static>>,
707 > + Send
708 + Sync
709 + Unpin
710 + Clone,
711 Header: HeaderConverter<HeaderTy<N>, RpcHeader<Network>>,
712 Map: TxInfoMapper<TxTy<N>> + Clone + Debug + Unpin + Send + Sync + 'static,
713 SimTx: SimTxConverter<RpcTxReq<Network>, TxTy<N>>,
714 RpcTx:
715 RpcTxConverter<TxTy<N>, Network::TransactionResponse, <Map as TxInfoMapper<TxTy<N>>>::Out>,
716 TxEnv: TxEnvConverter<RpcTxReq<Network>, Evm>,
717{
718 type Primitives = N;
719 type Evm = Evm;
720 type Network = Network;
721 type Error = Receipt::Error;
722
723 fn fill(
724 &self,
725 tx: Recovered<TxTy<N>>,
726 tx_info: TransactionInfo,
727 ) -> Result<Network::TransactionResponse, Self::Error> {
728 let (tx, signer) = tx.into_parts();
729 let tx_info = self.mapper.try_map(&tx, tx_info)?;
730
731 self.rpc_tx_converter.convert_rpc_tx(tx, signer, tx_info).map_err(Into::into)
732 }
733
734 fn build_simulate_v1_transaction(
735 &self,
736 request: RpcTxReq<Network>,
737 ) -> Result<TxTy<N>, Self::Error> {
738 Ok(self
739 .sim_tx_converter
740 .convert_sim_tx(request)
741 .map_err(|e| TransactionConversionError::FromTxReq(e.to_string()))?)
742 }
743
744 fn tx_env(
745 &self,
746 request: RpcTxReq<Network>,
747 evm_env: &EvmEnvFor<Evm>,
748 ) -> Result<TxEnvFor<Evm>, Self::Error> {
749 self.tx_env_converter.convert_tx_env(request, evm_env).map_err(Into::into)
750 }
751
752 fn convert_log(
753 &self,
754 log: Log,
755 receipt: &<Self::Primitives as NodePrimitives>::Receipt,
756 header: &SealedHeaderFor<Self::Primitives>,
757 ) -> Result<RpcLog<Self::Network>, Self::Error> {
758 self.receipt_converter.convert_log(log, receipt, header)
759 }
760
761 fn convert_receipts(
762 &self,
763 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
764 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error> {
765 self.receipt_converter.convert_receipts(receipts)
766 }
767
768 fn convert_receipts_with_block(
769 &self,
770 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
771 block: &SealedBlock<BlockTy<Self::Primitives>>,
772 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error> {
773 self.receipt_converter.convert_receipts_with_block(receipts, block)
774 }
775
776 fn convert_header(
777 &self,
778 header: SealedHeaderFor<Self::Primitives>,
779 block_size: Option<usize>,
780 ) -> Result<RpcHeader<Self::Network>, Self::Error> {
781 Ok(self.header_converter.convert_header(header, block_size)?)
782 }
783}