1use crate::{
2 commands::{
3 policy::PolicyCommand, policy_client::PolicyClientCommand, policy_data::PolicyDataCommand,
4 policy_files::PolicyFilesCommand, task::TaskCommand,
5 },
6 config::NewtonCliConfig,
7};
8use clap::{Parser, Subcommand};
9use newton_cli_runner::NewtonRunner;
10use newton_prover_core::config::{
11 log::{init_logger, LogFormat, LoggerConfig},
12 NewtonAvsConfigBuilder,
13};
14use std::{ffi::OsString, path::PathBuf};
15use tracing::info;
16
17#[derive(Debug, Parser)]
19#[command(author, about = "Newton protocol cli", long_about = None)]
20pub struct NewtonCli {
21 #[arg(long, value_name = "CHAIN_ID", global = true, env = "CHAIN_ID")]
23 chain_id: Option<u64>,
24
25 #[arg(long, value_name = "FILE", global = true)]
27 config_path: Option<PathBuf>,
28
29 #[arg(
31 long,
32 value_enum,
33 default_value = "minimal",
34 global = true,
35 help = "Log format: full, compact, pretty, json, or minimal"
36 )]
37 log_format: LogFormat,
38
39 #[arg(long, global = true)]
41 quiet: bool,
42
43 #[command(subcommand)]
44 command: Commands,
45}
46
47impl NewtonCli {
48 pub fn parse_args() -> Self {
50 Self::parse()
51 }
52
53 pub fn try_parse_args_from<I, T>(itr: I) -> Result<Self, clap::error::Error>
55 where
56 I: IntoIterator<Item = T>,
57 T: Into<OsString> + Clone,
58 {
59 Self::try_parse_from(itr)
60 }
61
62 fn load_config_or_minimal(&self, chain_id: u64) -> newton_prover_core::config::NewtonAvsConfig<NewtonCliConfig> {
66 let mut builder = NewtonAvsConfigBuilder::new(chain_id);
67 if let Some(config_path) = &self.config_path {
68 info!("Loading cli config from: {:?}", config_path);
69 builder = builder.with_service_path(config_path.clone());
70 }
71
72 match builder.build::<NewtonCliConfig>() {
74 Ok(config) => config,
75 Err(e) => {
76 tracing::debug!("Service config loading failed, using defaults: {}", e);
79 let env = std::env::var("DEPLOYMENT_ENV").unwrap_or_else(|_| "stagef".to_string());
80 let service = NewtonCliConfig {
81 eth_rpc_url: "http://127.0.0.1:8545".to_string(),
82 newton_rpc_url: "http://127.0.0.1:8545".to_string(),
83 signer: newton_prover_core::config::key::EcdsaKey {
84 private_key: None,
85 keystore_path: None,
86 keystore_password: None,
87 },
88 };
89 use newton_prover_core::config::{contracts::*, ipfs::IpfsConfig, rpc::RpcProviderConfig};
91 #[allow(clippy::unnecessary_lazy_evaluations)]
94 let contracts = ContractsConfig::load(chain_id, env.clone()).unwrap_or_else(|_| {
95 ContractsConfig {
97 avs: NewtonAvsContractsConfig {
98 newton_prover_service_manager: alloy::primitives::Address::ZERO,
99 newton_prover_task_manager: alloy::primitives::Address::ZERO,
100 challenge_verifier: alloy::primitives::Address::ZERO,
101 rego_verifier: alloy::primitives::Address::ZERO,
102 attestation_validator: alloy::primitives::Address::ZERO,
103 operator_registry: alloy::primitives::Address::ZERO,
104 operator_state_retriever: alloy::primitives::Address::ZERO,
105 bls_apk_registry: alloy::primitives::Address::ZERO,
106 index_registry: alloy::primitives::Address::ZERO,
107 stake_registry: alloy::primitives::Address::ZERO,
108 socket_registry: alloy::primitives::Address::ZERO,
109 strategy: alloy::primitives::Address::ZERO,
110 },
111 eigenlayer: EigenlayerContractsConfig {
112 delegation_manager: alloy::primitives::Address::ZERO,
113 avs_directory: alloy::primitives::Address::ZERO,
114 strategy_manager: alloy::primitives::Address::ZERO,
115 allocation_manager: alloy::primitives::Address::ZERO,
116 rewards_coordinator: alloy::primitives::Address::ZERO,
117 strategy_factory: alloy::primitives::Address::ZERO,
118 permission_controller: alloy::primitives::Address::ZERO,
119 },
120 policy: NewtonPolicyContractsConfig {
121 policy_factory: alloy::primitives::Address::ZERO,
122 policy_data_factory: alloy::primitives::Address::ZERO,
123 },
124 }
125 });
126 newton_prover_core::config::NewtonAvsConfig {
128 env: env.clone(),
129 chain_id,
130 rpc: RpcProviderConfig::load(chain_id).unwrap_or(RpcProviderConfig {
131 http: "http://127.0.0.1:8545".to_string(),
132 ws: "ws://127.0.0.1:8545".to_string(),
133 }),
134 ipfs: IpfsConfig::default(),
135 contracts,
136 service,
137 }
138 }
139 }
140 }
141
142 fn load_config_required(
145 &self,
146 chain_id: u64,
147 ) -> eyre::Result<newton_prover_core::config::NewtonAvsConfig<NewtonCliConfig>> {
148 let mut builder = NewtonAvsConfigBuilder::new(chain_id);
149 if let Some(config_path) = &self.config_path {
150 info!("Loading cli config from: {:?}", config_path);
151 builder = builder.with_service_path(config_path.clone());
152 }
153 builder.build::<NewtonCliConfig>().map_err(|e| {
154 eyre::eyre!(
155 "Failed to load configuration: {}. \
156 Make sure deployment files exist for chain_id {} or set DEPLOYMENT_ENV environment variable.",
157 e,
158 chain_id
159 )
160 })
161 }
162
163 pub fn run(self) -> eyre::Result<()> {
165 let env_filter = "warn,newton_cli=info".to_string();
167
168 init_logger(LoggerConfig::new(self.log_format).with_env_filter(env_filter));
170
171 let runner = NewtonRunner::default();
172
173 let commands_that_dont_need_config =
176 matches!(&self.command, Commands::PolicyFiles(_) | Commands::PolicyClient(_));
177
178 let chain_id = if commands_that_dont_need_config {
180 self.chain_id.unwrap_or(1)
181 } else {
182 self.chain_id.ok_or_else(|| eyre::eyre!("chain id is required"))?
183 };
184
185 let config = if commands_that_dont_need_config {
191 self.load_config_or_minimal(chain_id)
192 } else {
193 self.load_config_required(chain_id)?
195 };
196
197 match self.command {
198 Commands::Task(command) => runner.run_blocking_until_ctrl_c(Box::new(command).execute(config))?,
199 Commands::PolicyData(command) => runner.run_blocking_until_ctrl_c(Box::new(command).execute(config))?,
200 Commands::Policy(command) => runner.run_blocking_until_ctrl_c(Box::new(command).execute(config))?,
201 Commands::PolicyFiles(command) => runner.run_blocking_until_ctrl_c(Box::new(command).execute(config))?,
202 Commands::PolicyClient(command) => runner.run_blocking_until_ctrl_c(Box::new(command).execute(config))?,
203 }
204
205 Ok(())
206 }
207}
208
209#[derive(Debug, Subcommand)]
211pub enum Commands {
212 Task(TaskCommand),
214
215 PolicyData(PolicyDataCommand),
217
218 Policy(PolicyCommand),
220
221 PolicyFiles(PolicyFilesCommand),
223
224 #[command(name = "policy-client")]
226 PolicyClient(PolicyClientCommand),
227}