1use crate::{defaults, follow, tempo_cmd};
4use reth_ethereum_cli::Cli;
5use reth_rpc_server_types::{RethRpcModule, RpcModuleSelection, RpcModuleValidator};
6use tempo_chainspec::spec::TempoChainSpecParser;
7use tempo_faucet::args::FaucetArgs;
8use tempo_node::TempoNodeArgs;
9
10pub type TempoCli =
11 Cli<TempoChainSpecParser, TempoArgs, TempoRpcModuleValidator, tempo_cmd::TempoSubcommand>;
12
13pub(crate) const TEMPO_CUSTOM_RPC_MODULES: &[&str] = &["consensus", "operator", "tempo", "token"];
14
15#[derive(Debug, Clone, Copy)]
16pub struct TempoRpcModuleValidator;
17
18impl RpcModuleValidator for TempoRpcModuleValidator {
19 fn parse_selection(s: &str) -> Result<RpcModuleSelection, String> {
20 let selection = s
21 .parse::<RpcModuleSelection>()
22 .map_err(|e| format!("Failed to parse RPC modules: {e}"))?;
23
24 if let RpcModuleSelection::Selection(modules) = &selection {
25 for module in modules {
26 let RethRpcModule::Other(name) = module else {
27 continue;
28 };
29
30 if !TEMPO_CUSTOM_RPC_MODULES.contains(&name.as_str()) {
31 return Err(format!("Unknown RPC module: '{name}'"));
32 }
33 }
34 }
35
36 Ok(selection)
37 }
38}
39
40#[derive(Debug, Clone, clap::Args)]
42pub struct TempoArgs {
43 #[arg(long, value_name = "WEBSOCKET_URL", default_missing_value = "auto", num_args(0..=1), env = "TEMPO_FOLLOW")]
46 pub(crate) follow: Option<follow::FollowMode>,
47
48 #[arg(long = "follow.nocertify", requires = "follow")]
52 pub(crate) follow_nocertify: bool,
53
54 #[arg(long = "follow.experimental.certify", requires = "follow", hide = true)]
57 pub(crate) follow_experimental_certify: bool,
58
59 #[arg(
68 long = "tempo.bootnodes-endpoint",
69 value_name = "URL",
70 default_value = "https://peers.tempo.xyz",
71 env = "TEMPO_BOOTNODES_ENDPOINT"
72 )]
73 pub(crate) bootnodes_endpoint: String,
74
75 #[command(flatten)]
76 pub(crate) telemetry: defaults::TelemetryArgs,
77
78 #[command(flatten)]
79 pub(crate) consensus: tempo_consensus::Args,
80
81 #[command(flatten)]
82 pub(crate) faucet_args: FaucetArgs,
83
84 #[command(flatten)]
85 pub(crate) node_args: TempoNodeArgs,
86
87 #[command(flatten)]
88 #[cfg(feature = "pyroscope")]
89 pub(crate) pyroscope_args: PyroscopeArgs,
90}
91
92impl TempoArgs {
93 pub(crate) fn is_following_uncertified(&self) -> bool {
94 self.follow.is_some() && self.follow_nocertify
95 }
96
97 pub fn has_consensus_engine(&self, dev: bool) -> bool {
101 !dev && !self.is_following_uncertified()
102 }
103}
104
105#[cfg(feature = "pyroscope")]
107#[derive(Debug, Clone, PartialEq, Eq, clap::Args)]
108pub(crate) struct PyroscopeArgs {
109 #[arg(long = "pyroscope.enabled", default_value_t = false)]
111 pub(crate) pyroscope_enabled: bool,
112
113 #[arg(long = "pyroscope.server-url", default_value = "http://localhost:4040")]
115 pub(crate) server_url: String,
116
117 #[arg(long = "pyroscope.application-name", default_value = "tempo")]
119 pub(crate) application_name: String,
120
121 #[arg(long = "pyroscope.sample-rate", default_value_t = 100)]
123 pub(crate) sample_rate: u32,
124}