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 {
63 self.with_wallet
64 .as_ref()
65 .map(|x| format!("_{x}"))
66 .unwrap_or_default()
67 }
68
69 pub fn storage_config(&self) -> Result<StorageConfig, Error> {
70 if let Some(config) = &self.storage_config {
71 return config.parse();
72 }
73 let suffix = self.suffix();
74 let storage_env_var = env::var(format!("LINERA_STORAGE{suffix}")).ok();
75 if let Some(config) = storage_env_var {
76 return config.parse();
77 }
78 cfg_if::cfg_if! {
79 if #[cfg(feature = "rocksdb")] {
80 let spawn_mode =
81 linera_views::rocks_db::RocksDbSpawnMode::get_spawn_mode_from_runtime();
82 let inner_storage_config = crate::storage::InnerStorageConfig::RocksDb {
83 path: linera_wallet_json::paths::config_dir()?.join("wallet.db"),
84 spawn_mode,
85 };
86 let namespace = linera_storage::DEFAULT_NAMESPACE.to_string();
87 Ok(StorageConfig {
88 inner_storage_config,
89 namespace,
90 })
91 } else {
92 bail!("Cannot apply default storage because the feature 'rocksdb' was not selected");
93 }
94 }
95 }
96
97 pub fn wallet_path(&self) -> Result<PathBuf, Error> {
98 linera_wallet_json::paths::wallet_path(self.wallet_state_path.as_ref(), &self.suffix())
99 }
100
101 pub fn keystore_path(&self) -> Result<PathBuf, Error> {
102 linera_wallet_json::paths::keystore_path(self.keystore_path.as_ref(), &self.suffix())
103 }
104
105 pub fn wallet(&self) -> Result<Wallet, Error> {
106 Ok(Wallet::read(&self.wallet_path()?)?)
107 }
108
109 pub fn keystore(&self) -> Result<linera_wallet_json::Keystore, Error> {
110 Ok(linera_wallet_json::Keystore::read(&self.keystore_path()?)?)
111 }
112
113 pub fn create_wallet(&self, genesis_config: GenesisConfig) -> Result<Wallet, Error> {
114 let wallet_path = self.wallet_path()?;
115 if wallet_path.exists() {
116 bail!("Wallet already exists: {}", wallet_path.display());
117 }
118 let wallet = Wallet::create(&wallet_path, genesis_config)?;
119 wallet.save()?;
120 Ok(wallet)
121 }
122
123 pub fn create_keystore(
124 &self,
125 testing_prng_seed: Option<u64>,
126 ) -> Result<linera_wallet_json::Keystore, Error> {
127 let keystore_path = self.keystore_path()?;
128 if keystore_path.exists() {
129 bail!("Keystore already exists: {}", keystore_path.display());
130 }
131 Ok(linera_wallet_json::Keystore::create(
132 &keystore_path,
133 testing_prng_seed,
134 )?)
135 }
136}