linera_service/cli/
common_options.rs1use std::{env, path::PathBuf};
7
8use anyhow::{bail, Error};
9use linera_client::config::GenesisConfig;
10use linera_execution::WasmRuntime;
11
12use crate::{
13 storage::{CommonStorageOptions, StorageConfig},
14 Wallet,
15};
16
17#[derive(Clone, clap::Parser)]
19pub struct CommonCliOptions {
20 #[arg(long = "wallet")]
23 pub wallet_state_path: Option<PathBuf>,
24
25 #[arg(long = "keystore")]
27 pub keystore_path: Option<PathBuf>,
28
29 #[arg(long, short = 'w', value_parser = crate::util::parse_ascii_alphanumeric_string)]
34 pub with_wallet: Option<String>,
35
36 #[arg(long = "storage", global = true)]
38 pub storage_config: Option<String>,
39
40 #[command(flatten)]
42 pub common_storage_options: CommonStorageOptions,
43
44 #[arg(long)]
46 pub wasm_runtime: Option<WasmRuntime>,
47
48 #[arg(long = "with-application-logs", env = "LINERA_APPLICATION_LOGS")]
50 pub application_logs: bool,
51
52 #[arg(long, env = "LINERA_CLIENT_TOKIO_THREADS")]
54 pub tokio_threads: Option<usize>,
55
56 #[arg(long, env = "LINERA_CLIENT_TOKIO_BLOCKING_THREADS")]
58 pub tokio_blocking_threads: Option<usize>,
59}
60
61impl CommonCliOptions {
62 pub fn suffix(&self) -> String {
64 self.with_wallet
65 .as_ref()
66 .map(|x| format!("_{x}"))
67 .unwrap_or_default()
68 }
69
70 pub fn storage_config(&self) -> Result<StorageConfig, Error> {
72 if let Some(config) = &self.storage_config {
73 return config.parse();
74 }
75 let suffix = self.suffix();
76 let storage_env_var = env::var(format!("LINERA_STORAGE{suffix}")).ok();
77 if let Some(config) = storage_env_var {
78 return config.parse();
79 }
80 cfg_if::cfg_if! {
81 if #[cfg(feature = "rocksdb")] {
82 let spawn_mode =
83 linera_views::rocks_db::RocksDbSpawnMode::get_spawn_mode_from_runtime();
84 let inner_storage_config = crate::storage::InnerStorageConfig::RocksDb {
85 path: linera_wallet_json::paths::config_dir()?.join("wallet.db"),
86 spawn_mode,
87 };
88 let namespace = linera_storage::DEFAULT_NAMESPACE.to_string();
89 Ok(StorageConfig {
90 inner_storage_config,
91 namespace,
92 })
93 } else {
94 bail!("Cannot apply default storage because the feature 'rocksdb' was not selected");
95 }
96 }
97 }
98
99 pub fn wallet_path(&self) -> Result<PathBuf, Error> {
101 linera_wallet_json::paths::wallet_path(self.wallet_state_path.as_ref(), &self.suffix())
102 }
103
104 pub fn keystore_path(&self) -> Result<PathBuf, Error> {
106 linera_wallet_json::paths::keystore_path(self.keystore_path.as_ref(), &self.suffix())
107 }
108
109 pub fn wallet(&self) -> Result<Wallet, Error> {
111 Ok(Wallet::read(&self.wallet_path()?)?)
112 }
113
114 pub fn keystore(&self) -> Result<linera_wallet_json::Keystore, Error> {
116 Ok(linera_wallet_json::Keystore::read(&self.keystore_path()?)?)
117 }
118
119 pub fn create_wallet(&self, genesis_config: GenesisConfig) -> Result<Wallet, Error> {
121 let wallet_path = self.wallet_path()?;
122 if wallet_path.exists() {
123 bail!("Wallet already exists: {}", wallet_path.display());
124 }
125 let wallet = Wallet::create(&wallet_path, genesis_config)?;
126 wallet.save()?;
127 Ok(wallet)
128 }
129
130 pub fn create_keystore(
132 &self,
133 testing_prng_seed: Option<u64>,
134 ) -> Result<linera_wallet_json::Keystore, Error> {
135 let keystore_path = self.keystore_path()?;
136 if keystore_path.exists() {
137 bail!("Keystore already exists: {}", keystore_path.display());
138 }
139 Ok(linera_wallet_json::Keystore::create(
140 &keystore_path,
141 testing_prng_seed,
142 )?)
143 }
144}