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 ..
483 } = self;
484 RpcConverter {
485 receipt_converter,
486 header_converter,
487 mapper,
488 network,
489 evm,
490 sim_tx_converter,
491 rpc_tx_converter,
492 tx_env_converter,
493 }
494 }
495
496 pub fn with_header_converter<HeaderNew>(
498 self,
499 header_converter: HeaderNew,
500 ) -> RpcConverter<Network, Evm, Receipt, HeaderNew, Map, SimTx, RpcTx, TxEnv> {
501 let Self {
502 receipt_converter,
503 header_converter: _,
504 mapper,
505 network,
506 evm,
507 sim_tx_converter,
508 rpc_tx_converter,
509 tx_env_converter,
510 } = self;
511 RpcConverter {
512 receipt_converter,
513 header_converter,
514 mapper,
515 network,
516 evm,
517 sim_tx_converter,
518 rpc_tx_converter,
519 tx_env_converter,
520 }
521 }
522
523 pub fn with_mapper<MapNew>(
525 self,
526 mapper: MapNew,
527 ) -> RpcConverter<Network, Evm, Receipt, Header, MapNew, SimTx, RpcTx, TxEnv> {
528 let Self {
529 receipt_converter,
530 header_converter,
531 mapper: _,
532 network,
533 evm,
534 sim_tx_converter,
535 rpc_tx_converter,
536 tx_env_converter,
537 } = self;
538 RpcConverter {
539 receipt_converter,
540 header_converter,
541 mapper,
542 network,
543 evm,
544 sim_tx_converter,
545 rpc_tx_converter,
546 tx_env_converter,
547 }
548 }
549
550 pub fn with_sim_tx_converter<SimTxNew>(
552 self,
553 sim_tx_converter: SimTxNew,
554 ) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTxNew, RpcTx, TxEnv> {
555 let Self {
556 receipt_converter,
557 header_converter,
558 mapper,
559 network,
560 evm,
561 rpc_tx_converter,
562 tx_env_converter,
563 ..
564 } = self;
565 RpcConverter {
566 receipt_converter,
567 header_converter,
568 mapper,
569 network,
570 evm,
571 sim_tx_converter,
572 rpc_tx_converter,
573 tx_env_converter,
574 }
575 }
576
577 pub fn with_rpc_tx_converter<RpcTxNew>(
579 self,
580 rpc_tx_converter: RpcTxNew,
581 ) -> RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTxNew, TxEnv> {
582 let Self {
583 receipt_converter,
584 header_converter,
585 mapper,
586 network,
587 evm,
588 sim_tx_converter,
589 tx_env_converter,
590 ..
591 } = self;
592 RpcConverter {
593 receipt_converter,
594 header_converter,
595 mapper,
596 network,
597 evm,
598 sim_tx_converter,
599 rpc_tx_converter,
600 tx_env_converter,
601 }
602 }
603
604 pub fn erased(
606 self,
607 ) -> Box<
608 dyn RpcConvert<
609 Primitives = <Self as RpcConvert>::Primitives,
610 Network = <Self as RpcConvert>::Network,
611 Error = <Self as RpcConvert>::Error,
612 Evm = <Self as RpcConvert>::Evm,
613 >,
614 >
615 where
616 Self: RpcConvert,
617 {
618 Box::new(self)
619 }
620}
621
622impl<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> Default
623 for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
624where
625 Receipt: Default,
626 Header: Default,
627 Map: Default,
628 SimTx: Default,
629 RpcTx: Default,
630 TxEnv: Default,
631{
632 fn default() -> Self {
633 Self {
634 network: Default::default(),
635 evm: Default::default(),
636 receipt_converter: Default::default(),
637 header_converter: Default::default(),
638 mapper: Default::default(),
639 sim_tx_converter: Default::default(),
640 rpc_tx_converter: Default::default(),
641 tx_env_converter: Default::default(),
642 }
643 }
644}
645
646impl<
647 Network,
648 Evm,
649 Receipt: Clone,
650 Header: Clone,
651 Map: Clone,
652 SimTx: Clone,
653 RpcTx: Clone,
654 TxEnv: Clone,
655 > Clone for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
656{
657 fn clone(&self) -> Self {
658 Self {
659 network: Default::default(),
660 evm: Default::default(),
661 receipt_converter: self.receipt_converter.clone(),
662 header_converter: self.header_converter.clone(),
663 mapper: self.mapper.clone(),
664 sim_tx_converter: self.sim_tx_converter.clone(),
665 rpc_tx_converter: self.rpc_tx_converter.clone(),
666 tx_env_converter: self.tx_env_converter.clone(),
667 }
668 }
669}
670
671impl<N, Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv> RpcConvert
672 for RpcConverter<Network, Evm, Receipt, Header, Map, SimTx, RpcTx, TxEnv>
673where
674 N: NodePrimitives,
675 Network: RpcTypes<TransactionRequest: SignableTxRequest<N::SignedTx>>,
676 Evm: ConfigureEvm<Primitives = N> + 'static,
677 Receipt: ReceiptConverter<
678 N,
679 RpcReceipt = RpcReceipt<Network>,
680 Error: From<TransactionConversionError>
681 + From<TxEnv::Error>
682 + From<<Map as TxInfoMapper<TxTy<N>>>::Err>
683 + From<RpcTx::Err>
684 + From<Header::Err>
685 + Error
686 + Unpin
687 + Sync
688 + Send
689 + Into<jsonrpsee_types::ErrorObject<'static>>,
690 > + Send
691 + Sync
692 + Unpin
693 + Clone
694 + Debug,
695 Header: HeaderConverter<HeaderTy<N>, RpcHeader<Network>>,
696 Map: TxInfoMapper<TxTy<N>> + Clone + Debug + Unpin + Send + Sync + 'static,
697 SimTx: SimTxConverter<RpcTxReq<Network>, TxTy<N>>,
698 RpcTx:
699 RpcTxConverter<TxTy<N>, Network::TransactionResponse, <Map as TxInfoMapper<TxTy<N>>>::Out>,
700 TxEnv: TxEnvConverter<RpcTxReq<Network>, Evm>,
701{
702 type Primitives = N;
703 type Evm = Evm;
704 type Network = Network;
705 type Error = Receipt::Error;
706
707 fn fill(
708 &self,
709 tx: Recovered<TxTy<N>>,
710 tx_info: TransactionInfo,
711 ) -> Result<Network::TransactionResponse, Self::Error> {
712 let (tx, signer) = tx.into_parts();
713 let tx_info = self.mapper.try_map(&tx, tx_info)?;
714
715 self.rpc_tx_converter.convert_rpc_tx(tx, signer, tx_info).map_err(Into::into)
716 }
717
718 fn build_simulate_v1_transaction(
719 &self,
720 request: RpcTxReq<Network>,
721 ) -> Result<TxTy<N>, Self::Error> {
722 Ok(self
723 .sim_tx_converter
724 .convert_sim_tx(request)
725 .map_err(|e| TransactionConversionError::FromTxReq(e.to_string()))?)
726 }
727
728 fn tx_env(
729 &self,
730 request: RpcTxReq<Network>,
731 evm_env: &EvmEnvFor<Evm>,
732 ) -> Result<TxEnvFor<Evm>, Self::Error> {
733 self.tx_env_converter.convert_tx_env(request, evm_env).map_err(Into::into)
734 }
735
736 fn convert_receipts(
737 &self,
738 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
739 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error> {
740 self.receipt_converter.convert_receipts(receipts)
741 }
742
743 fn convert_receipts_with_block(
744 &self,
745 receipts: Vec<ConvertReceiptInput<'_, Self::Primitives>>,
746 block: &SealedBlock<BlockTy<Self::Primitives>>,
747 ) -> Result<Vec<RpcReceipt<Self::Network>>, Self::Error> {
748 self.receipt_converter.convert_receipts_with_block(receipts, block)
749 }
750
751 fn convert_header(
752 &self,
753 header: SealedHeaderFor<Self::Primitives>,
754 block_size: usize,
755 ) -> Result<RpcHeader<Self::Network>, Self::Error> {
756 Ok(self.header_converter.convert_header(header, block_size)?)
757 }
758}