1#![doc(
201 html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
202 html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
203 issue_tracker_base_url = "https://github.com/SeismicSystems/seismic-reth/issues/"
204)]
205#![cfg_attr(not(test), warn(unused_crate_dependencies))]
206#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
207
208use std::{
209 collections::HashMap,
210 fmt::Debug,
211 net::{Ipv4Addr, SocketAddr, SocketAddrV4},
212 sync::Arc,
213 time::{Duration, SystemTime, UNIX_EPOCH},
214};
215
216use crate::{auth::AuthRpcModule, error::WsHttpSamePortError, metrics::RpcRequestMetrics};
217use error::{ConflictingModules, RpcError, ServerKind};
218use eth::DynEthApiBuilder;
219use http::{header::AUTHORIZATION, HeaderMap};
220use jsonrpsee::{
221 core::RegisterMethodError,
222 server::{
223 middleware::rpc::{RpcService, RpcServiceT},
224 AlreadyStoppedError, IdProvider, RpcServiceBuilder, ServerHandle,
225 },
226 Methods, RpcModule,
227};
228use reth_chainspec::EthereumHardforks;
229use reth_consensus::FullConsensus;
230use reth_engine_primitives::{EngineTypes, PayloadValidator};
231use reth_evm::{execute::BlockExecutorProvider, ConfigureEvm};
232use reth_network_api::{noop::NoopNetwork, NetworkInfo, Peers};
233use reth_primitives::{NodePrimitives, PooledTransactionsElement};
234use reth_provider::{
235 AccountReader, BlockReader, CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader,
236 EvmEnvProvider, FullRpcProvider, ProviderBlock, ProviderHeader, ProviderReceipt,
237 StateProviderFactory,
238};
239use reth_rpc::{
240 AdminApi, DebugApi, EngineEthApi, EthBundle, MinerApi, NetApi, OtterscanApi, RPCApi, RethApi,
241 TraceApi, TxPoolApi, ValidationApi, ValidationApiConfig, Web3Api,
242};
243use reth_rpc_api::servers::*;
244use reth_rpc_eth_api::{
245 helpers::{Call, EthApiSpec, EthTransactions, LoadPendingBlock, TraceExt},
246 EthApiServer, EthApiTypes, FullEthApiServer, RpcBlock, RpcHeader, RpcReceipt, RpcTransaction,
247};
248use reth_rpc_eth_types::{EthConfig, EthStateCache, EthSubscriptionIdProvider};
249use reth_rpc_layer::{AuthLayer, Claims, CompressionLayer, JwtAuthValidator, JwtSecret};
250use reth_tasks::{pool::BlockingTaskGuard, TaskSpawner, TokioTaskExecutor};
251use reth_transaction_pool::{noop::NoopTransactionPool, PoolTransaction, TransactionPool};
252use serde::{Deserialize, Serialize};
253use tower::Layer;
254use tower_http::cors::CorsLayer;
255
256pub use cors::CorsDomainError;
257
258pub use jsonrpsee::server::ServerBuilder;
260pub use reth_ipc::server::{
261 Builder as IpcServerBuilder, RpcServiceBuilder as IpcRpcServiceBuilder,
262};
263pub use reth_rpc_server_types::{constants, RethRpcModule, RpcModuleSelection};
264pub use tower::layer::util::{Identity, Stack};
265
266pub mod auth;
268
269pub mod config;
271
272mod cors;
274
275pub mod error;
277
278pub mod eth;
280pub use eth::EthHandlers;
281
282mod metrics;
284pub use metrics::{MeteredRequestFuture, RpcRequestMetricsService};
285
286pub mod rate_limiter;
288
289#[allow(clippy::too_many_arguments)]
291pub async fn launch<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi, BlockExecutor>(
292 provider: Provider,
293 pool: Pool,
294 network: Network,
295 module_config: impl Into<TransportRpcModuleConfig>,
296 server_config: impl Into<RpcServerConfig>,
297 executor: Tasks,
298 events: Events,
299 evm_config: EvmConfig,
300 eth: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
301 block_executor: BlockExecutor,
302 consensus: Arc<dyn FullConsensus<BlockExecutor::Primitives>>,
303 payload_validator: Arc<dyn PayloadValidator<Block = Provider::Block>>,
304) -> Result<RpcServerHandle, RpcError>
305where
306 Provider: FullRpcProvider<
307 Block = ProviderBlock<EthApi::Provider>,
308 Receipt = ProviderReceipt<EthApi::Provider>,
309 Header = ProviderHeader<EthApi::Provider>,
310 > + AccountReader
311 + ChangeSetReader,
312 Pool: TransactionPool<Transaction = <EthApi::Pool as TransactionPool>::Transaction> + 'static,
313 Network: NetworkInfo + Peers + Clone + 'static,
314 Tasks: TaskSpawner + Clone + 'static,
315 Events: CanonStateSubscriptions<Primitives = BlockExecutor::Primitives> + Clone + 'static,
316 EvmConfig: ConfigureEvm<
317 Header = <BlockExecutor::Primitives as NodePrimitives>::BlockHeader,
318 Transaction = <BlockExecutor::Primitives as NodePrimitives>::SignedTx,
319 >,
320 EthApi: FullEthApiServer<
321 Provider: BlockReader<
322 Block = <BlockExecutor::Primitives as NodePrimitives>::Block,
323 Receipt = <BlockExecutor::Primitives as NodePrimitives>::Receipt,
324 Header = <BlockExecutor::Primitives as NodePrimitives>::BlockHeader,
325 >,
326 Pool: TransactionPool<Transaction: PoolTransaction<Pooled = PooledTransactionsElement>>,
327 >,
328 BlockExecutor: BlockExecutorProvider,
329{
330 let module_config = module_config.into();
331 server_config
332 .into()
333 .start(
334 &RpcModuleBuilder::new(
335 provider,
336 pool,
337 network,
338 executor,
339 events,
340 evm_config,
341 block_executor,
342 consensus,
343 )
344 .build(module_config, eth, payload_validator),
345 )
346 .await
347}
348
349#[derive(Debug, Clone)]
353pub struct RpcModuleBuilder<
354 Provider,
355 Pool,
356 Network,
357 Tasks,
358 Events,
359 EvmConfig,
360 BlockExecutor,
361 Consensus,
362> {
363 provider: Provider,
365 pool: Pool,
367 network: Network,
369 executor: Tasks,
371 events: Events,
373 evm_config: EvmConfig,
375 block_executor: BlockExecutor,
377 consensus: Consensus,
379}
380
381impl<Provider, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor, Consensus>
384 RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor, Consensus>
385{
386 #[allow(clippy::too_many_arguments)]
388 pub const fn new(
389 provider: Provider,
390 pool: Pool,
391 network: Network,
392 executor: Tasks,
393 events: Events,
394 evm_config: EvmConfig,
395 block_executor: BlockExecutor,
396 consensus: Consensus,
397 ) -> Self {
398 Self { provider, pool, network, executor, events, evm_config, block_executor, consensus }
399 }
400
401 pub fn with_provider<P>(
403 self,
404 provider: P,
405 ) -> RpcModuleBuilder<P, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor, Consensus>
406 where
407 P: BlockReader + StateProviderFactory + EvmEnvProvider + 'static,
408 {
409 let Self { pool, network, executor, events, evm_config, block_executor, consensus, .. } =
410 self;
411 RpcModuleBuilder {
412 provider,
413 network,
414 pool,
415 executor,
416 events,
417 evm_config,
418 block_executor,
419 consensus,
420 }
421 }
422
423 pub fn with_pool<P>(
425 self,
426 pool: P,
427 ) -> RpcModuleBuilder<Provider, P, Network, Tasks, Events, EvmConfig, BlockExecutor, Consensus>
428 where
429 P: TransactionPool + 'static,
430 {
431 let Self {
432 provider, network, executor, events, evm_config, block_executor, consensus, ..
433 } = self;
434 RpcModuleBuilder {
435 provider,
436 network,
437 pool,
438 executor,
439 events,
440 evm_config,
441 block_executor,
442 consensus,
443 }
444 }
445
446 pub fn with_noop_pool(
452 self,
453 ) -> RpcModuleBuilder<
454 Provider,
455 NoopTransactionPool,
456 Network,
457 Tasks,
458 Events,
459 EvmConfig,
460 BlockExecutor,
461 Consensus,
462 > {
463 let Self {
464 provider, executor, events, network, evm_config, block_executor, consensus, ..
465 } = self;
466 RpcModuleBuilder {
467 provider,
468 executor,
469 events,
470 network,
471 evm_config,
472 block_executor,
473 pool: NoopTransactionPool::default(),
474 consensus,
475 }
476 }
477
478 pub fn with_network<N>(
480 self,
481 network: N,
482 ) -> RpcModuleBuilder<Provider, Pool, N, Tasks, Events, EvmConfig, BlockExecutor, Consensus>
483 where
484 N: NetworkInfo + Peers + 'static,
485 {
486 let Self {
487 provider, pool, executor, events, evm_config, block_executor, consensus, ..
488 } = self;
489 RpcModuleBuilder {
490 provider,
491 network,
492 pool,
493 executor,
494 events,
495 evm_config,
496 block_executor,
497 consensus,
498 }
499 }
500
501 pub fn with_noop_network(
507 self,
508 ) -> RpcModuleBuilder<
509 Provider,
510 Pool,
511 NoopNetwork,
512 Tasks,
513 Events,
514 EvmConfig,
515 BlockExecutor,
516 Consensus,
517 > {
518 let Self {
519 provider, pool, executor, events, evm_config, block_executor, consensus, ..
520 } = self;
521 RpcModuleBuilder {
522 provider,
523 pool,
524 executor,
525 events,
526 network: NoopNetwork::default(),
527 evm_config,
528 block_executor,
529 consensus,
530 }
531 }
532
533 pub fn with_executor<T>(
535 self,
536 executor: T,
537 ) -> RpcModuleBuilder<Provider, Pool, Network, T, Events, EvmConfig, BlockExecutor, Consensus>
538 where
539 T: TaskSpawner + 'static,
540 {
541 let Self { pool, network, provider, events, evm_config, block_executor, consensus, .. } =
542 self;
543 RpcModuleBuilder {
544 provider,
545 network,
546 pool,
547 executor,
548 events,
549 evm_config,
550 block_executor,
551 consensus,
552 }
553 }
554
555 pub fn with_tokio_executor(
560 self,
561 ) -> RpcModuleBuilder<
562 Provider,
563 Pool,
564 Network,
565 TokioTaskExecutor,
566 Events,
567 EvmConfig,
568 BlockExecutor,
569 Consensus,
570 > {
571 let Self { pool, network, provider, events, evm_config, block_executor, consensus, .. } =
572 self;
573 RpcModuleBuilder {
574 provider,
575 network,
576 pool,
577 events,
578 executor: TokioTaskExecutor::default(),
579 evm_config,
580 block_executor,
581 consensus,
582 }
583 }
584
585 pub fn with_events<E>(
587 self,
588 events: E,
589 ) -> RpcModuleBuilder<Provider, Pool, Network, Tasks, E, EvmConfig, BlockExecutor, Consensus>
590 where
591 E: CanonStateSubscriptions + 'static,
592 {
593 let Self {
594 provider, pool, executor, network, evm_config, block_executor, consensus, ..
595 } = self;
596 RpcModuleBuilder {
597 provider,
598 network,
599 pool,
600 executor,
601 events,
602 evm_config,
603 block_executor,
604 consensus,
605 }
606 }
607
608 pub fn with_evm_config<E>(
610 self,
611 evm_config: E,
612 ) -> RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, E, BlockExecutor, Consensus>
613 where
614 E: ConfigureEvm + 'static,
615 {
616 let Self { provider, pool, executor, network, events, block_executor, consensus, .. } =
617 self;
618 RpcModuleBuilder {
619 provider,
620 network,
621 pool,
622 executor,
623 events,
624 evm_config,
625 block_executor,
626 consensus,
627 }
628 }
629
630 pub fn with_block_executor<BE>(
632 self,
633 block_executor: BE,
634 ) -> RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, BE, Consensus>
635 where
636 BE: BlockExecutorProvider,
637 {
638 let Self { provider, network, pool, executor, events, evm_config, consensus, .. } = self;
639 RpcModuleBuilder {
640 provider,
641 network,
642 pool,
643 executor,
644 events,
645 evm_config,
646 block_executor,
647 consensus,
648 }
649 }
650
651 pub fn with_consensus<C>(
653 self,
654 consensus: C,
655 ) -> RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor, C> {
656 let Self { provider, network, pool, executor, events, evm_config, block_executor, .. } =
657 self;
658 RpcModuleBuilder {
659 provider,
660 network,
661 pool,
662 executor,
663 events,
664 evm_config,
665 block_executor,
666 consensus,
667 }
668 }
669}
670
671impl<Provider, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor, Consensus>
672 RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor, Consensus>
673where
674 Provider: FullRpcProvider<
675 Block = <Events::Primitives as NodePrimitives>::Block,
676 Receipt = <Events::Primitives as NodePrimitives>::Receipt,
677 Header = <Events::Primitives as NodePrimitives>::BlockHeader,
678 > + AccountReader
679 + ChangeSetReader,
680 Pool: TransactionPool + 'static,
681 Network: NetworkInfo + Peers + Clone + 'static,
682 Tasks: TaskSpawner + Clone + 'static,
683 Events: CanonStateSubscriptions<Primitives = BlockExecutor::Primitives> + Clone + 'static,
684 EvmConfig: ConfigureEvm<
685 Header = <BlockExecutor::Primitives as NodePrimitives>::BlockHeader,
686 Transaction = <BlockExecutor::Primitives as NodePrimitives>::SignedTx,
687 >,
688 BlockExecutor: BlockExecutorProvider,
689 Consensus: reth_consensus::FullConsensus<BlockExecutor::Primitives> + Clone + 'static,
690{
691 #[allow(clippy::type_complexity)]
698 pub fn build_with_auth_server<EngineApi, EngineT, EthApi>(
699 self,
700 module_config: TransportRpcModuleConfig,
701 engine: EngineApi,
702 eth: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
703 payload_validator: Arc<dyn PayloadValidator<Block = Provider::Block>>,
704 ) -> (
705 TransportRpcModules,
706 AuthRpcModule,
707 RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>,
708 )
709 where
710 EngineT: EngineTypes,
711 EngineApi: EngineApiServer<EngineT>,
712 EthApi: FullEthApiServer<
713 Provider: BlockReader<
714 Block = <Events::Primitives as NodePrimitives>::Block,
715 Receipt = <Events::Primitives as NodePrimitives>::Receipt,
716 Header = <Events::Primitives as NodePrimitives>::BlockHeader,
717 >,
718 Pool: TransactionPool<Transaction: PoolTransaction<Pooled = PooledTransactionsElement>>,
719 >,
720 {
721 let Self {
722 provider,
723 pool,
724 network,
725 executor,
726 events,
727 evm_config,
728 block_executor,
729 consensus,
730 } = self;
731
732 let config = module_config.config.clone().unwrap_or_default();
733
734 let mut registry = RpcRegistryInner::new(
735 provider,
736 pool,
737 network,
738 executor,
739 events,
740 consensus,
741 config,
742 evm_config,
743 eth,
744 block_executor,
745 payload_validator,
746 );
747
748 let modules = registry.create_transport_rpc_modules(module_config);
749
750 let auth_module = registry.create_auth_module(engine);
751
752 (modules, auth_module, registry)
753 }
754
755 pub fn into_registry<EthApi>(
796 self,
797 config: RpcModuleConfig,
798 eth: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
799 payload_validator: Arc<dyn PayloadValidator<Block = Provider::Block>>,
800 ) -> RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
801 where
802 EthApi: EthApiTypes + 'static,
803 {
804 let Self {
805 provider,
806 pool,
807 network,
808 executor,
809 events,
810 evm_config,
811 block_executor,
812 consensus,
813 } = self;
814 RpcRegistryInner::new(
815 provider,
816 pool,
817 network,
818 executor,
819 events,
820 consensus,
821 config,
822 evm_config,
823 eth,
824 block_executor,
825 payload_validator,
826 )
827 }
828
829 pub fn build<EthApi>(
832 self,
833 module_config: TransportRpcModuleConfig,
834 eth: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
835 payload_validator: Arc<dyn PayloadValidator<Block = Provider::Block>>,
836 ) -> TransportRpcModules<()>
837 where
838 EthApi: FullEthApiServer<
839 Provider: BlockReader<
840 Receipt = <Events::Primitives as NodePrimitives>::Receipt,
841 Block = <Events::Primitives as NodePrimitives>::Block,
842 Header = <Events::Primitives as NodePrimitives>::BlockHeader,
843 >,
844 Pool: TransactionPool<Transaction: PoolTransaction<Pooled = PooledTransactionsElement>>,
845 >,
846 Pool: TransactionPool<Transaction = <EthApi::Pool as TransactionPool>::Transaction>,
847 {
848 let mut modules = TransportRpcModules::default();
849
850 let Self {
851 provider,
852 pool,
853 network,
854 executor,
855 events,
856 evm_config,
857 block_executor,
858 consensus,
859 } = self;
860
861 if !module_config.is_empty() {
862 let TransportRpcModuleConfig { http, ws, ipc, config } = module_config.clone();
863
864 let mut registry = RpcRegistryInner::new(
865 provider,
866 pool,
867 network,
868 executor,
869 events,
870 consensus,
871 config.unwrap_or_default(),
872 evm_config,
873 eth,
874 block_executor,
875 payload_validator,
876 );
877
878 modules.config = module_config;
879 modules.http = registry.maybe_module(http.as_ref());
880 modules.ws = registry.maybe_module(ws.as_ref());
881 modules.ipc = registry.maybe_module(ipc.as_ref());
882 }
883
884 modules
885 }
886}
887
888impl Default for RpcModuleBuilder<(), (), (), (), (), (), (), ()> {
889 fn default() -> Self {
890 Self::new((), (), (), (), (), (), (), ())
891 }
892}
893
894#[derive(Debug, Default, Clone, Eq, PartialEq, Serialize, Deserialize)]
896pub struct RpcModuleConfig {
897 eth: EthConfig,
899 flashbots: ValidationApiConfig,
901}
902
903impl RpcModuleConfig {
906 pub fn builder() -> RpcModuleConfigBuilder {
908 RpcModuleConfigBuilder::default()
909 }
910
911 pub const fn new(eth: EthConfig, flashbots: ValidationApiConfig) -> Self {
913 Self { eth, flashbots }
914 }
915
916 pub const fn eth(&self) -> &EthConfig {
918 &self.eth
919 }
920
921 pub fn eth_mut(&mut self) -> &mut EthConfig {
923 &mut self.eth
924 }
925}
926
927#[derive(Clone, Debug, Default)]
929pub struct RpcModuleConfigBuilder {
930 eth: Option<EthConfig>,
931 flashbots: Option<ValidationApiConfig>,
932}
933
934impl RpcModuleConfigBuilder {
937 pub const fn eth(mut self, eth: EthConfig) -> Self {
939 self.eth = Some(eth);
940 self
941 }
942
943 pub fn flashbots(mut self, flashbots: ValidationApiConfig) -> Self {
945 self.flashbots = Some(flashbots);
946 self
947 }
948
949 pub fn build(self) -> RpcModuleConfig {
951 let Self { eth, flashbots } = self;
952 RpcModuleConfig { eth: eth.unwrap_or_default(), flashbots: flashbots.unwrap_or_default() }
953 }
954
955 pub const fn get_eth(&self) -> Option<&EthConfig> {
957 self.eth.as_ref()
958 }
959
960 pub fn eth_mut(&mut self) -> &mut Option<EthConfig> {
962 &mut self.eth
963 }
964
965 pub fn eth_mut_or_default(&mut self) -> &mut EthConfig {
967 self.eth.get_or_insert_with(EthConfig::default)
968 }
969}
970
971#[derive(Debug, Clone)]
973pub struct RpcRegistryInner<
974 Provider: BlockReader,
975 Pool,
976 Network,
977 Tasks,
978 Events,
979 EthApi: EthApiTypes,
980 BlockExecutor,
981 Consensus,
982> {
983 provider: Provider,
984 pool: Pool,
985 network: Network,
986 executor: Tasks,
987 events: Events,
988 block_executor: BlockExecutor,
989 consensus: Consensus,
990 payload_validator: Arc<dyn PayloadValidator<Block = Provider::Block>>,
991 config: RpcModuleConfig,
993 eth: EthHandlers<Provider, Events, EthApi>,
995 blocking_pool_guard: BlockingTaskGuard,
997 modules: HashMap<RethRpcModule, Methods>,
999}
1000
1001impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1004 RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1005where
1006 Provider: StateProviderFactory
1007 + BlockReader<
1008 Block = <Events::Primitives as NodePrimitives>::Block,
1009 Receipt = <Events::Primitives as NodePrimitives>::Receipt,
1010 > + EvmEnvProvider
1011 + Clone
1012 + Unpin
1013 + 'static,
1014 Pool: Send + Sync + Clone + 'static,
1015 Network: Clone + 'static,
1016 Events: CanonStateSubscriptions + Clone + 'static,
1017 Tasks: TaskSpawner + Clone + 'static,
1018 EthApi: EthApiTypes + 'static,
1019 BlockExecutor: BlockExecutorProvider,
1020{
1021 #[allow(clippy::too_many_arguments)]
1023 pub fn new<EvmConfig>(
1024 provider: Provider,
1025 pool: Pool,
1026 network: Network,
1027 executor: Tasks,
1028 events: Events,
1029 consensus: Consensus,
1030 config: RpcModuleConfig,
1031 evm_config: EvmConfig,
1032 eth_api_builder: DynEthApiBuilder<
1033 Provider,
1034 Pool,
1035 EvmConfig,
1036 Network,
1037 Tasks,
1038 Events,
1039 EthApi,
1040 >,
1041 block_executor: BlockExecutor,
1042 payload_validator: Arc<dyn PayloadValidator<Block = Provider::Block>>,
1043 ) -> Self
1044 where
1045 EvmConfig: ConfigureEvm<Header = Provider::Header>,
1046 {
1047 let blocking_pool_guard = BlockingTaskGuard::new(config.eth.max_tracing_requests);
1048
1049 let eth = EthHandlers::bootstrap(
1050 provider.clone(),
1051 pool.clone(),
1052 network.clone(),
1053 evm_config,
1054 config.eth,
1055 executor.clone(),
1056 events.clone(),
1057 eth_api_builder,
1058 );
1059
1060 Self {
1061 provider,
1062 pool,
1063 network,
1064 eth,
1065 executor,
1066 consensus,
1067 config,
1068 modules: Default::default(),
1069 blocking_pool_guard,
1070 events,
1071 block_executor,
1072 payload_validator,
1073 }
1074 }
1075}
1076
1077impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1078 RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1079where
1080 Provider: BlockReader,
1081 EthApi: EthApiTypes,
1082{
1083 pub const fn eth_api(&self) -> &EthApi {
1085 &self.eth.api
1086 }
1087
1088 pub const fn eth_handlers(&self) -> &EthHandlers<Provider, Events, EthApi> {
1090 &self.eth
1091 }
1092
1093 pub const fn eth_cache(&self) -> &EthStateCache<Provider::Block, Provider::Receipt> {
1098 &self.eth.cache
1099 }
1100
1101 pub const fn pool(&self) -> &Pool {
1103 &self.pool
1104 }
1105
1106 pub const fn events(&self) -> &Events {
1108 &self.events
1109 }
1110
1111 pub const fn tasks(&self) -> &Tasks {
1113 &self.executor
1114 }
1115
1116 pub const fn provider(&self) -> &Provider {
1118 &self.provider
1119 }
1120
1121 pub fn methods(&self) -> Vec<Methods> {
1123 self.modules.values().cloned().collect()
1124 }
1125
1126 pub fn module(&self) -> RpcModule<()> {
1128 let mut module = RpcModule::new(());
1129 for methods in self.modules.values().cloned() {
1130 module.merge(methods).expect("No conflicts");
1131 }
1132 module
1133 }
1134}
1135
1136impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1137 RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1138where
1139 Network: NetworkInfo + Clone + 'static,
1140 EthApi: EthApiTypes,
1141 Provider: BlockReader + ChainSpecProvider<ChainSpec: EthereumHardforks>,
1142 BlockExecutor: BlockExecutorProvider,
1143{
1144 pub fn admin_api(&self) -> AdminApi<Network, Provider::ChainSpec>
1146 where
1147 Network: Peers,
1148 {
1149 AdminApi::new(self.network.clone(), self.provider.chain_spec())
1150 }
1151
1152 pub fn web3_api(&self) -> Web3Api<Network> {
1154 Web3Api::new(self.network.clone())
1155 }
1156
1157 pub fn register_admin(&mut self) -> &mut Self
1159 where
1160 Network: Peers,
1161 {
1162 let adminapi = self.admin_api();
1163 self.modules.insert(RethRpcModule::Admin, adminapi.into_rpc().into());
1164 self
1165 }
1166
1167 pub fn register_web3(&mut self) -> &mut Self {
1169 let web3api = self.web3_api();
1170 self.modules.insert(RethRpcModule::Web3, web3api.into_rpc().into());
1171 self
1172 }
1173}
1174
1175impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1176 RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1177where
1178 Provider: FullRpcProvider + AccountReader + ChangeSetReader,
1179 Network: NetworkInfo + Peers + Clone + 'static,
1180 Tasks: TaskSpawner + Clone + 'static,
1181 EthApi: EthApiServer<
1182 RpcTransaction<EthApi::NetworkTypes>,
1183 RpcBlock<EthApi::NetworkTypes>,
1184 RpcReceipt<EthApi::NetworkTypes>,
1185 RpcHeader<EthApi::NetworkTypes>,
1186 > + EthApiTypes,
1187 BlockExecutor: BlockExecutorProvider,
1188{
1189 pub fn register_eth(&mut self) -> &mut Self {
1195 let eth_api = self.eth_api().clone();
1196 self.modules.insert(RethRpcModule::Eth, eth_api.into_rpc().into());
1197 self
1198 }
1199
1200 pub fn register_ots(&mut self) -> &mut Self
1206 where
1207 EthApi: TraceExt + EthTransactions,
1208 {
1209 let otterscan_api = self.otterscan_api();
1210 self.modules.insert(RethRpcModule::Ots, otterscan_api.into_rpc().into());
1211 self
1212 }
1213
1214 pub fn register_debug(&mut self) -> &mut Self
1220 where
1221 EthApi: EthApiSpec + EthTransactions + TraceExt,
1222 BlockExecutor::Primitives: NodePrimitives<Block = ProviderBlock<EthApi::Provider>>,
1223 {
1224 let debug_api = self.debug_api();
1225 self.modules.insert(RethRpcModule::Debug, debug_api.into_rpc().into());
1226 self
1227 }
1228
1229 pub fn register_trace(&mut self) -> &mut Self
1235 where
1236 EthApi: TraceExt,
1237 {
1238 let trace_api = self.trace_api();
1239 self.modules.insert(RethRpcModule::Trace, trace_api.into_rpc().into());
1240 self
1241 }
1242
1243 pub fn register_net(&mut self) -> &mut Self
1251 where
1252 EthApi: EthApiSpec + 'static,
1253 {
1254 let netapi = self.net_api();
1255 self.modules.insert(RethRpcModule::Net, netapi.into_rpc().into());
1256 self
1257 }
1258
1259 pub fn register_reth(&mut self) -> &mut Self {
1267 let rethapi = self.reth_api();
1268 self.modules.insert(RethRpcModule::Reth, rethapi.into_rpc().into());
1269 self
1270 }
1271
1272 pub fn otterscan_api(&self) -> OtterscanApi<EthApi> {
1278 let eth_api = self.eth_api().clone();
1279 OtterscanApi::new(eth_api)
1280 }
1281}
1282
1283impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1284 RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1285where
1286 Provider: FullRpcProvider + AccountReader + ChangeSetReader,
1287 Network: NetworkInfo + Peers + Clone + 'static,
1288 Tasks: TaskSpawner + Clone + 'static,
1289 EthApi: EthApiTypes,
1290 BlockExecutor: BlockExecutorProvider,
1291{
1292 pub fn trace_api(&self) -> TraceApi<EthApi>
1298 where
1299 EthApi: TraceExt,
1300 {
1301 TraceApi::new(self.eth_api().clone(), self.blocking_pool_guard.clone())
1302 }
1303
1304 pub fn bundle_api(&self) -> EthBundle<EthApi>
1310 where
1311 EthApi: EthTransactions + LoadPendingBlock + Call,
1312 {
1313 let eth_api = self.eth_api().clone();
1314 EthBundle::new(eth_api, self.blocking_pool_guard.clone())
1315 }
1316
1317 pub fn debug_api(&self) -> DebugApi<EthApi, BlockExecutor>
1323 where
1324 EthApi: EthApiSpec + EthTransactions + TraceExt,
1325 BlockExecutor::Primitives: NodePrimitives<Block = ProviderBlock<EthApi::Provider>>,
1326 {
1327 DebugApi::new(
1328 self.eth_api().clone(),
1329 self.blocking_pool_guard.clone(),
1330 self.block_executor.clone(),
1331 )
1332 }
1333
1334 pub fn net_api(&self) -> NetApi<Network, EthApi>
1340 where
1341 EthApi: EthApiSpec + 'static,
1342 {
1343 let eth_api = self.eth_api().clone();
1344 NetApi::new(self.network.clone(), eth_api)
1345 }
1346
1347 pub fn reth_api(&self) -> RethApi<Provider> {
1349 RethApi::new(self.provider.clone(), Box::new(self.executor.clone()))
1350 }
1351
1352 pub fn validation_api(&self) -> ValidationApi<Provider, BlockExecutor>
1354 where
1355 Consensus: reth_consensus::FullConsensus<BlockExecutor::Primitives> + Clone + 'static,
1356 Provider: BlockReader<Block = <BlockExecutor::Primitives as NodePrimitives>::Block>,
1357 {
1358 ValidationApi::new(
1359 self.provider.clone(),
1360 Arc::new(self.consensus.clone()),
1361 self.block_executor.clone(),
1362 self.config.flashbots.clone(),
1363 Box::new(self.executor.clone()),
1364 self.payload_validator.clone(),
1365 )
1366 }
1367}
1368
1369impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1370 RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor, Consensus>
1371where
1372 Provider: FullRpcProvider<Block = <BlockExecutor::Primitives as NodePrimitives>::Block>
1373 + AccountReader
1374 + ChangeSetReader,
1375 Pool: TransactionPool + 'static,
1376 Network: NetworkInfo + Peers + Clone + 'static,
1377 Tasks: TaskSpawner + Clone + 'static,
1378 Events: CanonStateSubscriptions<Primitives = BlockExecutor::Primitives> + Clone + 'static,
1379 EthApi: FullEthApiServer<
1380 Provider: BlockReader<
1381 Block = <BlockExecutor::Primitives as NodePrimitives>::Block,
1382 Receipt = <BlockExecutor::Primitives as NodePrimitives>::Receipt,
1383 Header = <BlockExecutor::Primitives as NodePrimitives>::BlockHeader,
1384 >,
1385 Pool: TransactionPool<Transaction: PoolTransaction<Pooled = PooledTransactionsElement>>,
1386 >,
1387 BlockExecutor: BlockExecutorProvider,
1388 Consensus: reth_consensus::FullConsensus<BlockExecutor::Primitives> + Clone + 'static,
1389{
1390 pub fn create_auth_module<EngineApi, EngineT>(&self, engine_api: EngineApi) -> AuthRpcModule
1396 where
1397 EngineT: EngineTypes,
1398 EngineApi: EngineApiServer<EngineT>,
1399 {
1400 let mut module = RpcModule::new(());
1401
1402 module.merge(engine_api.into_rpc()).expect("No conflicting methods");
1403
1404 let eth_handlers = self.eth_handlers();
1406 let engine_eth = EngineEthApi::new(eth_handlers.api.clone(), eth_handlers.filter.clone());
1407
1408 module.merge(engine_eth.into_rpc()).expect("No conflicting methods");
1409
1410 AuthRpcModule { inner: module }
1411 }
1412
1413 fn maybe_module(&mut self, config: Option<&RpcModuleSelection>) -> Option<RpcModule<()>> {
1415 config.map(|config| self.module_for(config))
1416 }
1417
1418 pub fn create_transport_rpc_modules(
1422 &mut self,
1423 config: TransportRpcModuleConfig,
1424 ) -> TransportRpcModules<()> {
1425 let mut modules = TransportRpcModules::default();
1426 let http = self.maybe_module(config.http.as_ref());
1427 let ws = self.maybe_module(config.ws.as_ref());
1428 let ipc = self.maybe_module(config.ipc.as_ref());
1429
1430 modules.config = config;
1431 modules.http = http;
1432 modules.ws = ws;
1433 modules.ipc = ipc;
1434 modules
1435 }
1436
1437 pub fn module_for(&mut self, config: &RpcModuleSelection) -> RpcModule<()> {
1440 let mut module = RpcModule::new(());
1441 let all_methods = self.reth_methods(config.iter_selection());
1442 for methods in all_methods {
1443 module.merge(methods).expect("No conflicts");
1444 }
1445 module
1446 }
1447
1448 pub fn reth_methods(
1457 &mut self,
1458 namespaces: impl Iterator<Item = RethRpcModule>,
1459 ) -> Vec<Methods> {
1460 let EthHandlers { api: eth_api, filter: eth_filter, pubsub: eth_pubsub, .. } =
1461 self.eth_handlers().clone();
1462
1463 let namespaces: Vec<_> = namespaces.collect();
1465 namespaces
1466 .iter()
1467 .copied()
1468 .map(|namespace| {
1469 self.modules
1470 .entry(namespace)
1471 .or_insert_with(|| match namespace {
1472 RethRpcModule::Admin => {
1473 AdminApi::new(self.network.clone(), self.provider.chain_spec())
1474 .into_rpc()
1475 .into()
1476 }
1477 RethRpcModule::Debug => DebugApi::new(
1478 eth_api.clone(),
1479 self.blocking_pool_guard.clone(),
1480 self.block_executor.clone(),
1481 )
1482 .into_rpc()
1483 .into(),
1484 RethRpcModule::Eth => {
1485 let mut module = eth_api.clone().into_rpc();
1487 module.merge(eth_filter.clone().into_rpc()).expect("No conflicts");
1488 module.merge(eth_pubsub.clone().into_rpc()).expect("No conflicts");
1489 module
1490 .merge(
1491 EthBundle::new(
1492 eth_api.clone(),
1493 self.blocking_pool_guard.clone(),
1494 )
1495 .into_rpc(),
1496 )
1497 .expect("No conflicts");
1498
1499 module.into()
1500 }
1501 RethRpcModule::Net => {
1502 NetApi::new(self.network.clone(), eth_api.clone()).into_rpc().into()
1503 }
1504 RethRpcModule::Trace => {
1505 TraceApi::new(eth_api.clone(), self.blocking_pool_guard.clone())
1506 .into_rpc()
1507 .into()
1508 }
1509 RethRpcModule::Web3 => Web3Api::new(self.network.clone()).into_rpc().into(),
1510 RethRpcModule::Txpool => TxPoolApi::new(
1511 self.eth.api.pool().clone(),
1512 self.eth.api.tx_resp_builder().clone(),
1513 )
1514 .into_rpc()
1515 .into(),
1516 RethRpcModule::Rpc => RPCApi::new(
1517 namespaces
1518 .iter()
1519 .map(|module| (module.to_string(), "1.0".to_string()))
1520 .collect(),
1521 )
1522 .into_rpc()
1523 .into(),
1524 RethRpcModule::Ots => OtterscanApi::new(eth_api.clone()).into_rpc().into(),
1525 RethRpcModule::Reth => {
1526 RethApi::new(self.provider.clone(), Box::new(self.executor.clone()))
1527 .into_rpc()
1528 .into()
1529 }
1530 RethRpcModule::Flashbots => ValidationApi::new(
1531 eth_api.provider().clone(),
1532 Arc::new(self.consensus.clone()),
1533 self.block_executor.clone(),
1534 self.config.flashbots.clone(),
1535 Box::new(self.executor.clone()),
1536 self.payload_validator.clone(),
1537 )
1538 .into_rpc()
1539 .into(),
1540 RethRpcModule::Miner => MinerApi::default().into_rpc().into(),
1541 })
1542 .clone()
1543 })
1544 .collect::<Vec<_>>()
1545 }
1546}
1547
1548#[derive(Debug)]
1560pub struct RpcServerConfig<RpcMiddleware = Identity> {
1561 http_server_config: Option<ServerBuilder<Identity, Identity>>,
1563 http_cors_domains: Option<String>,
1565 http_addr: Option<SocketAddr>,
1567 ws_server_config: Option<ServerBuilder<Identity, Identity>>,
1569 ws_cors_domains: Option<String>,
1571 ws_addr: Option<SocketAddr>,
1573 ipc_server_config: Option<IpcServerBuilder<Identity, Identity>>,
1575 ipc_endpoint: Option<String>,
1577 jwt_secret: Option<JwtSecret>,
1579 rpc_middleware: RpcServiceBuilder<RpcMiddleware>,
1581}
1582
1583impl Default for RpcServerConfig<Identity> {
1586 fn default() -> Self {
1588 Self {
1589 http_server_config: None,
1590 http_cors_domains: None,
1591 http_addr: None,
1592 ws_server_config: None,
1593 ws_cors_domains: None,
1594 ws_addr: None,
1595 ipc_server_config: None,
1596 ipc_endpoint: None,
1597 jwt_secret: None,
1598 rpc_middleware: RpcServiceBuilder::new(),
1599 }
1600 }
1601}
1602
1603impl RpcServerConfig {
1604 pub fn http(config: ServerBuilder<Identity, Identity>) -> Self {
1606 Self::default().with_http(config)
1607 }
1608
1609 pub fn ws(config: ServerBuilder<Identity, Identity>) -> Self {
1611 Self::default().with_ws(config)
1612 }
1613
1614 pub fn ipc(config: IpcServerBuilder<Identity, Identity>) -> Self {
1616 Self::default().with_ipc(config)
1617 }
1618
1619 pub fn with_http(mut self, config: ServerBuilder<Identity, Identity>) -> Self {
1624 self.http_server_config =
1625 Some(config.set_id_provider(EthSubscriptionIdProvider::default()));
1626 self
1627 }
1628
1629 pub fn with_ws(mut self, config: ServerBuilder<Identity, Identity>) -> Self {
1634 self.ws_server_config = Some(config.set_id_provider(EthSubscriptionIdProvider::default()));
1635 self
1636 }
1637
1638 pub fn with_ipc(mut self, config: IpcServerBuilder<Identity, Identity>) -> Self {
1643 self.ipc_server_config = Some(config.set_id_provider(EthSubscriptionIdProvider::default()));
1644 self
1645 }
1646}
1647
1648impl<RpcMiddleware> RpcServerConfig<RpcMiddleware> {
1649 pub fn set_rpc_middleware<T>(self, rpc_middleware: RpcServiceBuilder<T>) -> RpcServerConfig<T> {
1651 RpcServerConfig {
1652 http_server_config: self.http_server_config,
1653 http_cors_domains: self.http_cors_domains,
1654 http_addr: self.http_addr,
1655 ws_server_config: self.ws_server_config,
1656 ws_cors_domains: self.ws_cors_domains,
1657 ws_addr: self.ws_addr,
1658 ipc_server_config: self.ipc_server_config,
1659 ipc_endpoint: self.ipc_endpoint,
1660 jwt_secret: self.jwt_secret,
1661 rpc_middleware,
1662 }
1663 }
1664
1665 pub fn with_cors(self, cors_domain: Option<String>) -> Self {
1667 self.with_http_cors(cors_domain.clone()).with_ws_cors(cors_domain)
1668 }
1669
1670 pub fn with_ws_cors(mut self, cors_domain: Option<String>) -> Self {
1672 self.ws_cors_domains = cors_domain;
1673 self
1674 }
1675
1676 pub fn with_http_cors(mut self, cors_domain: Option<String>) -> Self {
1678 self.http_cors_domains = cors_domain;
1679 self
1680 }
1681
1682 pub const fn with_http_address(mut self, addr: SocketAddr) -> Self {
1687 self.http_addr = Some(addr);
1688 self
1689 }
1690
1691 pub const fn with_ws_address(mut self, addr: SocketAddr) -> Self {
1696 self.ws_addr = Some(addr);
1697 self
1698 }
1699
1700 pub fn with_id_provider<I>(mut self, id_provider: I) -> Self
1704 where
1705 I: IdProvider + Clone + 'static,
1706 {
1707 if let Some(http) = self.http_server_config {
1708 self.http_server_config = Some(http.set_id_provider(id_provider.clone()));
1709 }
1710 if let Some(ws) = self.ws_server_config {
1711 self.ws_server_config = Some(ws.set_id_provider(id_provider.clone()));
1712 }
1713 if let Some(ipc) = self.ipc_server_config {
1714 self.ipc_server_config = Some(ipc.set_id_provider(id_provider));
1715 }
1716
1717 self
1718 }
1719
1720 pub fn with_ipc_endpoint(mut self, path: impl Into<String>) -> Self {
1724 self.ipc_endpoint = Some(path.into());
1725 self
1726 }
1727
1728 pub const fn with_jwt_secret(mut self, secret: Option<JwtSecret>) -> Self {
1730 self.jwt_secret = secret;
1731 self
1732 }
1733
1734 pub const fn has_server(&self) -> bool {
1738 self.http_server_config.is_some() ||
1739 self.ws_server_config.is_some() ||
1740 self.ipc_server_config.is_some()
1741 }
1742
1743 pub const fn http_address(&self) -> Option<SocketAddr> {
1745 self.http_addr
1746 }
1747
1748 pub const fn ws_address(&self) -> Option<SocketAddr> {
1750 self.ws_addr
1751 }
1752
1753 pub fn ipc_endpoint(&self) -> Option<String> {
1755 self.ipc_endpoint.clone()
1756 }
1757
1758 fn maybe_cors_layer(cors: Option<String>) -> Result<Option<CorsLayer>, CorsDomainError> {
1760 cors.as_deref().map(cors::create_cors_layer).transpose()
1761 }
1762
1763 fn maybe_jwt_layer(jwt_secret: Option<JwtSecret>) -> Option<AuthLayer<JwtAuthValidator>> {
1765 jwt_secret.map(|secret| AuthLayer::new(JwtAuthValidator::new(secret)))
1766 }
1767
1768 fn maybe_compression_layer() -> Option<CompressionLayer> {
1771 Some(CompressionLayer::new())
1772 }
1773
1774 pub async fn start(self, modules: &TransportRpcModules) -> Result<RpcServerHandle, RpcError>
1780 where
1781 RpcMiddleware: Layer<RpcRequestMetricsService<RpcService>> + Clone + Send + 'static,
1782 for<'a> <RpcMiddleware as Layer<RpcRequestMetricsService<RpcService>>>::Service:
1783 Send + Sync + 'static + RpcServiceT<'a>,
1784 {
1785 let mut http_handle = None;
1786 let mut ws_handle = None;
1787 let mut ipc_handle = None;
1788
1789 let http_socket_addr = self.http_addr.unwrap_or(SocketAddr::V4(SocketAddrV4::new(
1790 Ipv4Addr::LOCALHOST,
1791 constants::DEFAULT_HTTP_RPC_PORT,
1792 )));
1793
1794 let ws_socket_addr = self.ws_addr.unwrap_or(SocketAddr::V4(SocketAddrV4::new(
1795 Ipv4Addr::LOCALHOST,
1796 constants::DEFAULT_WS_RPC_PORT,
1797 )));
1798
1799 let metrics = modules.ipc.as_ref().map(RpcRequestMetrics::ipc).unwrap_or_default();
1800 let ipc_path =
1801 self.ipc_endpoint.clone().unwrap_or_else(|| constants::DEFAULT_IPC_ENDPOINT.into());
1802
1803 if let Some(builder) = self.ipc_server_config {
1804 let ipc = builder
1805 .set_rpc_middleware(IpcRpcServiceBuilder::new().layer(metrics))
1806 .build(ipc_path);
1807 ipc_handle = Some(ipc.start(modules.ipc.clone().expect("ipc server error")).await?);
1808 }
1809
1810 if self.http_addr == self.ws_addr &&
1812 self.http_server_config.is_some() &&
1813 self.ws_server_config.is_some()
1814 {
1815 let cors = match (self.ws_cors_domains.as_ref(), self.http_cors_domains.as_ref()) {
1816 (Some(ws_cors), Some(http_cors)) => {
1817 if ws_cors.trim() != http_cors.trim() {
1818 return Err(WsHttpSamePortError::ConflictingCorsDomains {
1819 http_cors_domains: Some(http_cors.clone()),
1820 ws_cors_domains: Some(ws_cors.clone()),
1821 }
1822 .into());
1823 }
1824 Some(ws_cors)
1825 }
1826 (a, b) => a.or(b),
1827 }
1828 .cloned();
1829
1830 modules.config.ensure_ws_http_identical()?;
1832
1833 if let Some(builder) = self.http_server_config {
1834 let server = builder
1835 .set_http_middleware(
1836 tower::ServiceBuilder::new()
1837 .option_layer(Self::maybe_cors_layer(cors)?)
1838 .option_layer(Self::maybe_jwt_layer(self.jwt_secret))
1839 .option_layer(Self::maybe_compression_layer()),
1840 )
1841 .set_rpc_middleware(
1842 self.rpc_middleware.clone().layer(
1843 modules
1844 .http
1845 .as_ref()
1846 .or(modules.ws.as_ref())
1847 .map(RpcRequestMetrics::same_port)
1848 .unwrap_or_default(),
1849 ),
1850 )
1851 .build(http_socket_addr)
1852 .await
1853 .map_err(|err| {
1854 RpcError::server_error(err, ServerKind::WsHttp(http_socket_addr))
1855 })?;
1856 let addr = server.local_addr().map_err(|err| {
1857 RpcError::server_error(err, ServerKind::WsHttp(http_socket_addr))
1858 })?;
1859 if let Some(module) = modules.http.as_ref().or(modules.ws.as_ref()) {
1860 let handle = server.start(module.clone());
1861 http_handle = Some(handle.clone());
1862 ws_handle = Some(handle);
1863 }
1864 return Ok(RpcServerHandle {
1865 http_local_addr: Some(addr),
1866 ws_local_addr: Some(addr),
1867 http: http_handle,
1868 ws: ws_handle,
1869 ipc_endpoint: self.ipc_endpoint.clone(),
1870 ipc: ipc_handle,
1871 jwt_secret: self.jwt_secret,
1872 });
1873 }
1874 }
1875
1876 let mut ws_local_addr = None;
1877 let mut ws_server = None;
1878 let mut http_local_addr = None;
1879 let mut http_server = None;
1880
1881 if let Some(builder) = self.ws_server_config {
1882 let server = builder
1883 .ws_only()
1884 .set_http_middleware(
1885 tower::ServiceBuilder::new()
1886 .option_layer(Self::maybe_cors_layer(self.ws_cors_domains.clone())?)
1887 .option_layer(Self::maybe_jwt_layer(self.jwt_secret)),
1888 )
1889 .set_rpc_middleware(
1890 self.rpc_middleware
1891 .clone()
1892 .layer(modules.ws.as_ref().map(RpcRequestMetrics::ws).unwrap_or_default()),
1893 )
1894 .build(ws_socket_addr)
1895 .await
1896 .map_err(|err| RpcError::server_error(err, ServerKind::WS(ws_socket_addr)))?;
1897
1898 let addr = server
1899 .local_addr()
1900 .map_err(|err| RpcError::server_error(err, ServerKind::WS(ws_socket_addr)))?;
1901
1902 ws_local_addr = Some(addr);
1903 ws_server = Some(server);
1904 }
1905
1906 if let Some(builder) = self.http_server_config {
1907 let server = builder
1908 .http_only()
1909 .set_http_middleware(
1910 tower::ServiceBuilder::new()
1911 .option_layer(Self::maybe_cors_layer(self.ws_cors_domains.clone())?)
1912 .option_layer(Self::maybe_jwt_layer(self.jwt_secret))
1913 .option_layer(Self::maybe_compression_layer()),
1914 )
1915 .set_rpc_middleware(
1916 self.rpc_middleware.clone().layer(
1917 modules.http.as_ref().map(RpcRequestMetrics::http).unwrap_or_default(),
1918 ),
1919 )
1920 .build(http_socket_addr)
1921 .await
1922 .map_err(|err| RpcError::server_error(err, ServerKind::Http(http_socket_addr)))?;
1923 let local_addr = server
1924 .local_addr()
1925 .map_err(|err| RpcError::server_error(err, ServerKind::Http(http_socket_addr)))?;
1926 http_local_addr = Some(local_addr);
1927 http_server = Some(server);
1928 }
1929
1930 http_handle = http_server
1931 .map(|http_server| http_server.start(modules.http.clone().expect("http server error")));
1932 ws_handle = ws_server
1933 .map(|ws_server| ws_server.start(modules.ws.clone().expect("ws server error")));
1934 Ok(RpcServerHandle {
1935 http_local_addr,
1936 ws_local_addr,
1937 http: http_handle,
1938 ws: ws_handle,
1939 ipc_endpoint: self.ipc_endpoint.clone(),
1940 ipc: ipc_handle,
1941 jwt_secret: self.jwt_secret,
1942 })
1943 }
1944}
1945
1946#[derive(Debug, Clone, Default, Eq, PartialEq)]
1958pub struct TransportRpcModuleConfig {
1959 http: Option<RpcModuleSelection>,
1961 ws: Option<RpcModuleSelection>,
1963 ipc: Option<RpcModuleSelection>,
1965 config: Option<RpcModuleConfig>,
1967}
1968
1969impl TransportRpcModuleConfig {
1972 pub fn set_http(http: impl Into<RpcModuleSelection>) -> Self {
1974 Self::default().with_http(http)
1975 }
1976
1977 pub fn set_ws(ws: impl Into<RpcModuleSelection>) -> Self {
1979 Self::default().with_ws(ws)
1980 }
1981
1982 pub fn set_ipc(ipc: impl Into<RpcModuleSelection>) -> Self {
1984 Self::default().with_ipc(ipc)
1985 }
1986
1987 pub fn with_http(mut self, http: impl Into<RpcModuleSelection>) -> Self {
1989 self.http = Some(http.into());
1990 self
1991 }
1992
1993 pub fn with_ws(mut self, ws: impl Into<RpcModuleSelection>) -> Self {
1995 self.ws = Some(ws.into());
1996 self
1997 }
1998
1999 pub fn with_ipc(mut self, ipc: impl Into<RpcModuleSelection>) -> Self {
2001 self.ipc = Some(ipc.into());
2002 self
2003 }
2004
2005 pub fn with_config(mut self, config: RpcModuleConfig) -> Self {
2007 self.config = Some(config);
2008 self
2009 }
2010
2011 pub fn http_mut(&mut self) -> &mut Option<RpcModuleSelection> {
2013 &mut self.http
2014 }
2015
2016 pub fn ws_mut(&mut self) -> &mut Option<RpcModuleSelection> {
2018 &mut self.ws
2019 }
2020
2021 pub fn ipc_mut(&mut self) -> &mut Option<RpcModuleSelection> {
2023 &mut self.ipc
2024 }
2025
2026 pub fn config_mut(&mut self) -> &mut Option<RpcModuleConfig> {
2028 &mut self.config
2029 }
2030
2031 pub const fn is_empty(&self) -> bool {
2033 self.http.is_none() && self.ws.is_none() && self.ipc.is_none()
2034 }
2035
2036 pub const fn http(&self) -> Option<&RpcModuleSelection> {
2038 self.http.as_ref()
2039 }
2040
2041 pub const fn ws(&self) -> Option<&RpcModuleSelection> {
2043 self.ws.as_ref()
2044 }
2045
2046 pub const fn ipc(&self) -> Option<&RpcModuleSelection> {
2048 self.ipc.as_ref()
2049 }
2050
2051 pub const fn config(&self) -> Option<&RpcModuleConfig> {
2053 self.config.as_ref()
2054 }
2055
2056 pub fn contains_any(&self, module: &RethRpcModule) -> bool {
2058 self.contains_http(module) || self.contains_ws(module) || self.contains_ipc(module)
2059 }
2060
2061 pub fn contains_http(&self, module: &RethRpcModule) -> bool {
2063 self.http.as_ref().is_some_and(|http| http.contains(module))
2064 }
2065
2066 pub fn contains_ws(&self, module: &RethRpcModule) -> bool {
2068 self.ws.as_ref().is_some_and(|ws| ws.contains(module))
2069 }
2070
2071 pub fn contains_ipc(&self, module: &RethRpcModule) -> bool {
2073 self.ipc.as_ref().is_some_and(|ipc| ipc.contains(module))
2074 }
2075
2076 fn ensure_ws_http_identical(&self) -> Result<(), WsHttpSamePortError> {
2079 if RpcModuleSelection::are_identical(self.http.as_ref(), self.ws.as_ref()) {
2080 Ok(())
2081 } else {
2082 let http_modules =
2083 self.http.as_ref().map(RpcModuleSelection::to_selection).unwrap_or_default();
2084 let ws_modules =
2085 self.ws.as_ref().map(RpcModuleSelection::to_selection).unwrap_or_default();
2086
2087 let http_not_ws = http_modules.difference(&ws_modules).copied().collect();
2088 let ws_not_http = ws_modules.difference(&http_modules).copied().collect();
2089 let overlap = http_modules.intersection(&ws_modules).copied().collect();
2090
2091 Err(WsHttpSamePortError::ConflictingModules(Box::new(ConflictingModules {
2092 overlap,
2093 http_not_ws,
2094 ws_not_http,
2095 })))
2096 }
2097 }
2098}
2099
2100#[derive(Debug, Clone, Default)]
2102pub struct TransportRpcModules<Context = ()> {
2103 config: TransportRpcModuleConfig,
2105 http: Option<RpcModule<Context>>,
2107 ws: Option<RpcModule<Context>>,
2109 ipc: Option<RpcModule<Context>>,
2111}
2112
2113impl TransportRpcModules {
2116 pub const fn module_config(&self) -> &TransportRpcModuleConfig {
2118 &self.config
2119 }
2120
2121 pub fn merge_if_module_configured(
2126 &mut self,
2127 module: RethRpcModule,
2128 other: impl Into<Methods>,
2129 ) -> Result<(), RegisterMethodError> {
2130 let other = other.into();
2131 if self.module_config().contains_http(&module) {
2132 self.merge_http(other.clone())?;
2133 }
2134 if self.module_config().contains_ws(&module) {
2135 self.merge_ws(other.clone())?;
2136 }
2137 if self.module_config().contains_ipc(&module) {
2138 self.merge_ipc(other)?;
2139 }
2140
2141 Ok(())
2142 }
2143
2144 pub fn merge_http(&mut self, other: impl Into<Methods>) -> Result<bool, RegisterMethodError> {
2150 if let Some(ref mut http) = self.http {
2151 return http.merge(other.into()).map(|_| true)
2152 }
2153 Ok(false)
2154 }
2155
2156 pub fn merge_ws(&mut self, other: impl Into<Methods>) -> Result<bool, RegisterMethodError> {
2162 if let Some(ref mut ws) = self.ws {
2163 return ws.merge(other.into()).map(|_| true)
2164 }
2165 Ok(false)
2166 }
2167
2168 pub fn merge_ipc(&mut self, other: impl Into<Methods>) -> Result<bool, RegisterMethodError> {
2174 if let Some(ref mut ipc) = self.ipc {
2175 return ipc.merge(other.into()).map(|_| true)
2176 }
2177 Ok(false)
2178 }
2179
2180 pub fn merge_configured(
2184 &mut self,
2185 other: impl Into<Methods>,
2186 ) -> Result<(), RegisterMethodError> {
2187 let other = other.into();
2188 self.merge_http(other.clone())?;
2189 self.merge_ws(other.clone())?;
2190 self.merge_ipc(other)?;
2191 Ok(())
2192 }
2193
2194 pub fn remove_http_method(&mut self, method_name: &'static str) -> bool {
2202 if let Some(http_module) = &mut self.http {
2203 http_module.remove_method(method_name).is_some()
2204 } else {
2205 false
2206 }
2207 }
2208
2209 pub fn remove_http_methods(&mut self, methods: impl IntoIterator<Item = &'static str>) {
2211 for name in methods {
2212 self.remove_http_method(name);
2213 }
2214 }
2215
2216 pub fn remove_ws_method(&mut self, method_name: &'static str) -> bool {
2224 if let Some(ws_module) = &mut self.ws {
2225 ws_module.remove_method(method_name).is_some()
2226 } else {
2227 false
2228 }
2229 }
2230
2231 pub fn remove_ws_methods(&mut self, methods: impl IntoIterator<Item = &'static str>) {
2233 for name in methods {
2234 self.remove_ws_method(name);
2235 }
2236 }
2237
2238 pub fn remove_ipc_method(&mut self, method_name: &'static str) -> bool {
2246 if let Some(ipc_module) = &mut self.ipc {
2247 ipc_module.remove_method(method_name).is_some()
2248 } else {
2249 false
2250 }
2251 }
2252
2253 pub fn remove_ipc_methods(&mut self, methods: impl IntoIterator<Item = &'static str>) {
2255 for name in methods {
2256 self.remove_ipc_method(name);
2257 }
2258 }
2259
2260 pub fn remove_method_from_configured(&mut self, method_name: &'static str) -> bool {
2264 let http_removed = self.remove_http_method(method_name);
2265 let ws_removed = self.remove_ws_method(method_name);
2266 let ipc_removed = self.remove_ipc_method(method_name);
2267
2268 http_removed || ws_removed || ipc_removed
2269 }
2270
2271 pub fn rename(
2275 &mut self,
2276 old_name: &'static str,
2277 new_method: impl Into<Methods>,
2278 ) -> Result<(), RegisterMethodError> {
2279 self.remove_method_from_configured(old_name);
2281
2282 self.merge_configured(new_method)
2284 }
2285
2286 pub fn replace_http(&mut self, other: impl Into<Methods>) -> Result<bool, RegisterMethodError> {
2293 let other = other.into();
2294 self.remove_http_methods(other.method_names());
2295 self.merge_http(other)
2296 }
2297
2298 pub fn replace_ipc(&mut self, other: impl Into<Methods>) -> Result<bool, RegisterMethodError> {
2305 let other = other.into();
2306 self.remove_ipc_methods(other.method_names());
2307 self.merge_ipc(other)
2308 }
2309
2310 pub fn replace_ws(&mut self, other: impl Into<Methods>) -> Result<bool, RegisterMethodError> {
2317 let other = other.into();
2318 self.remove_ws_methods(other.method_names());
2319 self.merge_ws(other)
2320 }
2321
2322 pub fn replace_configured(
2326 &mut self,
2327 other: impl Into<Methods>,
2328 ) -> Result<bool, RegisterMethodError> {
2329 let other = other.into();
2330 self.replace_http(other.clone())?;
2331 self.replace_ws(other.clone())?;
2332 self.replace_ipc(other)?;
2333 Ok(true)
2334 }
2335}
2336
2337#[derive(Clone, Debug)]
2342#[must_use = "Server stops if dropped"]
2343pub struct RpcServerHandle {
2344 http_local_addr: Option<SocketAddr>,
2346 ws_local_addr: Option<SocketAddr>,
2347 http: Option<ServerHandle>,
2348 ws: Option<ServerHandle>,
2349 ipc_endpoint: Option<String>,
2350 ipc: Option<jsonrpsee::server::ServerHandle>,
2351 jwt_secret: Option<JwtSecret>,
2352}
2353
2354impl RpcServerHandle {
2357 fn bearer_token(&self) -> Option<String> {
2359 self.jwt_secret.as_ref().map(|secret| {
2360 format!(
2361 "Bearer {}",
2362 secret
2363 .encode(&Claims {
2364 iat: (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() +
2365 Duration::from_secs(60))
2366 .as_secs(),
2367 exp: None,
2368 })
2369 .unwrap()
2370 )
2371 })
2372 }
2373 pub const fn http_local_addr(&self) -> Option<SocketAddr> {
2375 self.http_local_addr
2376 }
2377
2378 pub const fn ws_local_addr(&self) -> Option<SocketAddr> {
2380 self.ws_local_addr
2381 }
2382
2383 pub fn stop(self) -> Result<(), AlreadyStoppedError> {
2385 if let Some(handle) = self.http {
2386 handle.stop()?
2387 }
2388
2389 if let Some(handle) = self.ws {
2390 handle.stop()?
2391 }
2392
2393 if let Some(handle) = self.ipc {
2394 handle.stop()?
2395 }
2396
2397 Ok(())
2398 }
2399
2400 pub fn ipc_endpoint(&self) -> Option<String> {
2402 self.ipc_endpoint.clone()
2403 }
2404
2405 pub fn http_url(&self) -> Option<String> {
2407 self.http_local_addr.map(|addr| format!("http://{addr}"))
2408 }
2409
2410 pub fn ws_url(&self) -> Option<String> {
2412 self.ws_local_addr.map(|addr| format!("ws://{addr}"))
2413 }
2414
2415 pub fn http_client(&self) -> Option<jsonrpsee::http_client::HttpClient> {
2417 let url = self.http_url()?;
2418
2419 let client = if let Some(token) = self.bearer_token() {
2420 jsonrpsee::http_client::HttpClientBuilder::default()
2421 .set_headers(HeaderMap::from_iter([(AUTHORIZATION, token.parse().unwrap())]))
2422 .build(url)
2423 } else {
2424 jsonrpsee::http_client::HttpClientBuilder::default().build(url)
2425 };
2426
2427 client.expect("failed to create http client").into()
2428 }
2429
2430 pub async fn ws_client(&self) -> Option<jsonrpsee::ws_client::WsClient> {
2432 let url = self.ws_url()?;
2433 let mut builder = jsonrpsee::ws_client::WsClientBuilder::default();
2434
2435 if let Some(token) = self.bearer_token() {
2436 let headers = HeaderMap::from_iter([(AUTHORIZATION, token.parse().unwrap())]);
2437 builder = builder.set_headers(headers);
2438 }
2439
2440 let client = builder.build(url).await.expect("failed to create ws client");
2441 Some(client)
2442 }
2443}
2444
2445#[cfg(test)]
2446mod tests {
2447 use super::*;
2448
2449 #[test]
2450 fn parse_eth_call_bundle_selection() {
2451 let selection = "eth,admin,debug".parse::<RpcModuleSelection>().unwrap();
2452 assert_eq!(
2453 selection,
2454 RpcModuleSelection::Selection(
2455 [RethRpcModule::Eth, RethRpcModule::Admin, RethRpcModule::Debug,].into()
2456 )
2457 );
2458 }
2459
2460 #[test]
2461 fn parse_rpc_module_selection() {
2462 let selection = "all".parse::<RpcModuleSelection>().unwrap();
2463 assert_eq!(selection, RpcModuleSelection::All);
2464 }
2465
2466 #[test]
2467 fn parse_rpc_module_selection_none() {
2468 let selection = "none".parse::<RpcModuleSelection>().unwrap();
2469 assert_eq!(selection, RpcModuleSelection::Selection(Default::default()));
2470 }
2471
2472 #[test]
2473 fn parse_rpc_unique_module_selection() {
2474 let selection = "eth,admin,eth,net".parse::<RpcModuleSelection>().unwrap();
2475 assert_eq!(
2476 selection,
2477 RpcModuleSelection::Selection(
2478 [RethRpcModule::Eth, RethRpcModule::Admin, RethRpcModule::Net,].into()
2479 )
2480 );
2481 }
2482
2483 #[test]
2484 fn identical_selection() {
2485 assert!(RpcModuleSelection::are_identical(
2486 Some(&RpcModuleSelection::All),
2487 Some(&RpcModuleSelection::All),
2488 ));
2489 assert!(!RpcModuleSelection::are_identical(
2490 Some(&RpcModuleSelection::All),
2491 Some(&RpcModuleSelection::Standard),
2492 ));
2493 assert!(RpcModuleSelection::are_identical(
2494 Some(&RpcModuleSelection::Selection(RpcModuleSelection::Standard.to_selection())),
2495 Some(&RpcModuleSelection::Standard),
2496 ));
2497 assert!(RpcModuleSelection::are_identical(
2498 Some(&RpcModuleSelection::Selection([RethRpcModule::Eth].into())),
2499 Some(&RpcModuleSelection::Selection([RethRpcModule::Eth].into())),
2500 ));
2501 assert!(RpcModuleSelection::are_identical(
2502 None,
2503 Some(&RpcModuleSelection::Selection(Default::default())),
2504 ));
2505 assert!(RpcModuleSelection::are_identical(
2506 Some(&RpcModuleSelection::Selection(Default::default())),
2507 None,
2508 ));
2509 assert!(RpcModuleSelection::are_identical(None, None));
2510 }
2511
2512 #[test]
2513 fn test_rpc_module_str() {
2514 macro_rules! assert_rpc_module {
2515 ($($s:expr => $v:expr,)*) => {
2516 $(
2517 let val: RethRpcModule = $s.parse().unwrap();
2518 assert_eq!(val, $v);
2519 assert_eq!(val.to_string().as_str(), $s);
2520 )*
2521 };
2522 }
2523 assert_rpc_module!
2524 (
2525 "admin" => RethRpcModule::Admin,
2526 "debug" => RethRpcModule::Debug,
2527 "eth" => RethRpcModule::Eth,
2528 "net" => RethRpcModule::Net,
2529 "trace" => RethRpcModule::Trace,
2530 "web3" => RethRpcModule::Web3,
2531 "rpc" => RethRpcModule::Rpc,
2532 "ots" => RethRpcModule::Ots,
2533 "reth" => RethRpcModule::Reth,
2534 );
2535 }
2536
2537 #[test]
2538 fn test_default_selection() {
2539 let selection = RpcModuleSelection::Standard.to_selection();
2540 assert_eq!(selection, [RethRpcModule::Eth, RethRpcModule::Net, RethRpcModule::Web3].into())
2541 }
2542
2543 #[test]
2544 fn test_create_rpc_module_config() {
2545 let selection = vec!["eth", "admin"];
2546 let config = RpcModuleSelection::try_from_selection(selection).unwrap();
2547 assert_eq!(
2548 config,
2549 RpcModuleSelection::Selection([RethRpcModule::Eth, RethRpcModule::Admin].into())
2550 );
2551 }
2552
2553 #[test]
2554 fn test_configure_transport_config() {
2555 let config = TransportRpcModuleConfig::default()
2556 .with_http([RethRpcModule::Eth, RethRpcModule::Admin]);
2557 assert_eq!(
2558 config,
2559 TransportRpcModuleConfig {
2560 http: Some(RpcModuleSelection::Selection(
2561 [RethRpcModule::Eth, RethRpcModule::Admin].into()
2562 )),
2563 ws: None,
2564 ipc: None,
2565 config: None,
2566 }
2567 )
2568 }
2569
2570 #[test]
2571 fn test_configure_transport_config_none() {
2572 let config = TransportRpcModuleConfig::default().with_http(Vec::<RethRpcModule>::new());
2573 assert_eq!(
2574 config,
2575 TransportRpcModuleConfig {
2576 http: Some(RpcModuleSelection::Selection(Default::default())),
2577 ws: None,
2578 ipc: None,
2579 config: None,
2580 }
2581 )
2582 }
2583
2584 fn create_test_module() -> RpcModule<()> {
2585 let mut module = RpcModule::new(());
2586 module.register_method("anything", |_, _, _| "succeed").unwrap();
2587 module
2588 }
2589
2590 #[test]
2591 fn test_remove_http_method() {
2592 let mut modules =
2593 TransportRpcModules { http: Some(create_test_module()), ..Default::default() };
2594 assert!(modules.remove_http_method("anything"));
2596
2597 assert!(!modules.remove_http_method("non_existent_method"));
2599
2600 assert!(modules.http.as_ref().unwrap().method("anything").is_none());
2602 }
2603
2604 #[test]
2605 fn test_remove_ws_method() {
2606 let mut modules =
2607 TransportRpcModules { ws: Some(create_test_module()), ..Default::default() };
2608
2609 assert!(modules.remove_ws_method("anything"));
2611
2612 assert!(!modules.remove_ws_method("non_existent_method"));
2614
2615 assert!(modules.ws.as_ref().unwrap().method("anything").is_none());
2617 }
2618
2619 #[test]
2620 fn test_remove_ipc_method() {
2621 let mut modules =
2622 TransportRpcModules { ipc: Some(create_test_module()), ..Default::default() };
2623
2624 assert!(modules.remove_ipc_method("anything"));
2626
2627 assert!(!modules.remove_ipc_method("non_existent_method"));
2629
2630 assert!(modules.ipc.as_ref().unwrap().method("anything").is_none());
2632 }
2633
2634 #[test]
2635 fn test_remove_method_from_configured() {
2636 let mut modules = TransportRpcModules {
2637 http: Some(create_test_module()),
2638 ws: Some(create_test_module()),
2639 ipc: Some(create_test_module()),
2640 ..Default::default()
2641 };
2642
2643 assert!(modules.remove_method_from_configured("anything"));
2645
2646 assert!(!modules.remove_method_from_configured("anything"));
2648
2649 assert!(!modules.remove_method_from_configured("non_existent_method"));
2651
2652 assert!(modules.http.as_ref().unwrap().method("anything").is_none());
2654 assert!(modules.ws.as_ref().unwrap().method("anything").is_none());
2655 assert!(modules.ipc.as_ref().unwrap().method("anything").is_none());
2656 }
2657
2658 #[test]
2659 fn test_transport_rpc_module_rename() {
2660 let mut modules = TransportRpcModules {
2661 http: Some(create_test_module()),
2662 ws: Some(create_test_module()),
2663 ipc: Some(create_test_module()),
2664 ..Default::default()
2665 };
2666
2667 assert!(modules.http.as_ref().unwrap().method("anything").is_some());
2669 assert!(modules.ws.as_ref().unwrap().method("anything").is_some());
2670 assert!(modules.ipc.as_ref().unwrap().method("anything").is_some());
2671
2672 assert!(modules.http.as_ref().unwrap().method("something").is_none());
2674 assert!(modules.ws.as_ref().unwrap().method("something").is_none());
2675 assert!(modules.ipc.as_ref().unwrap().method("something").is_none());
2676
2677 let mut other_module = RpcModule::new(());
2679 other_module.register_method("something", |_, _, _| "fails").unwrap();
2680
2681 modules.rename("anything", other_module).expect("rename failed");
2683
2684 assert!(modules.http.as_ref().unwrap().method("anything").is_none());
2686 assert!(modules.ws.as_ref().unwrap().method("anything").is_none());
2687 assert!(modules.ipc.as_ref().unwrap().method("anything").is_none());
2688
2689 assert!(modules.http.as_ref().unwrap().method("something").is_some());
2691 assert!(modules.ws.as_ref().unwrap().method("something").is_some());
2692 assert!(modules.ipc.as_ref().unwrap().method("something").is_some());
2693 }
2694
2695 #[test]
2696 fn test_replace_http_method() {
2697 let mut modules =
2698 TransportRpcModules { http: Some(create_test_module()), ..Default::default() };
2699
2700 let mut other_module = RpcModule::new(());
2701 other_module.register_method("something", |_, _, _| "fails").unwrap();
2702
2703 assert!(modules.replace_http(other_module.clone()).unwrap());
2704
2705 assert!(modules.http.as_ref().unwrap().method("something").is_some());
2706
2707 other_module.register_method("anything", |_, _, _| "fails").unwrap();
2708 assert!(modules.replace_http(other_module.clone()).unwrap());
2709
2710 assert!(modules.http.as_ref().unwrap().method("anything").is_some());
2711 }
2712 #[test]
2713 fn test_replace_ipc_method() {
2714 let mut modules =
2715 TransportRpcModules { ipc: Some(create_test_module()), ..Default::default() };
2716
2717 let mut other_module = RpcModule::new(());
2718 other_module.register_method("something", |_, _, _| "fails").unwrap();
2719
2720 assert!(modules.replace_ipc(other_module.clone()).unwrap());
2721
2722 assert!(modules.ipc.as_ref().unwrap().method("something").is_some());
2723
2724 other_module.register_method("anything", |_, _, _| "fails").unwrap();
2725 assert!(modules.replace_ipc(other_module.clone()).unwrap());
2726
2727 assert!(modules.ipc.as_ref().unwrap().method("anything").is_some());
2728 }
2729 #[test]
2730 fn test_replace_ws_method() {
2731 let mut modules =
2732 TransportRpcModules { ws: Some(create_test_module()), ..Default::default() };
2733
2734 let mut other_module = RpcModule::new(());
2735 other_module.register_method("something", |_, _, _| "fails").unwrap();
2736
2737 assert!(modules.replace_ws(other_module.clone()).unwrap());
2738
2739 assert!(modules.ws.as_ref().unwrap().method("something").is_some());
2740
2741 other_module.register_method("anything", |_, _, _| "fails").unwrap();
2742 assert!(modules.replace_ws(other_module.clone()).unwrap());
2743
2744 assert!(modules.ws.as_ref().unwrap().method("anything").is_some());
2745 }
2746
2747 #[test]
2748 fn test_replace_configured() {
2749 let mut modules = TransportRpcModules {
2750 http: Some(create_test_module()),
2751 ws: Some(create_test_module()),
2752 ipc: Some(create_test_module()),
2753 ..Default::default()
2754 };
2755 let mut other_module = RpcModule::new(());
2756 other_module.register_method("something", |_, _, _| "fails").unwrap();
2757
2758 assert!(modules.replace_configured(other_module).unwrap());
2759
2760 assert!(modules.http.as_ref().unwrap().method("something").is_some());
2762 assert!(modules.ipc.as_ref().unwrap().method("something").is_some());
2763 assert!(modules.ws.as_ref().unwrap().method("something").is_some());
2764
2765 assert!(modules.http.as_ref().unwrap().method("anything").is_some());
2766 assert!(modules.ipc.as_ref().unwrap().method("anything").is_some());
2767 assert!(modules.ws.as_ref().unwrap().method("anything").is_some());
2768 }
2769}