diff --git a/Cargo.lock b/Cargo.lock index 16e4dac957..ae4ca34df8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4598,6 +4598,8 @@ dependencies = [ "serde", "serde_derive", "serde_yaml", + "solana-clap-utils", + "solana-sdk", "url 2.2.2", ] @@ -4619,6 +4621,7 @@ dependencies = [ "serde_json", "solana-account-decoder", "solana-clap-utils", + "solana-cli-config", "solana-client", "solana-sdk", "solana-transaction-status", diff --git a/cli-config/Cargo.toml b/cli-config/Cargo.toml index 07f4c32401..76e24c8e5c 100644 --- a/cli-config/Cargo.toml +++ b/cli-config/Cargo.toml @@ -15,6 +15,8 @@ lazy_static = "1.4.0" serde = "1.0.136" serde_derive = "1.0.103" serde_yaml = "0.8.23" +solana-clap-utils = { path = "../clap-utils", version = "=1.11.0" } +solana-sdk = { path = "../sdk", version = "=1.11.0" } url = "2.2.2" [dev-dependencies] diff --git a/cli-config/src/config_input.rs b/cli-config/src/config_input.rs new file mode 100644 index 0000000000..aa88a6da30 --- /dev/null +++ b/cli-config/src/config_input.rs @@ -0,0 +1,126 @@ +use { + crate::Config, solana_clap_utils::input_validators::normalize_to_url_if_moniker, + solana_sdk::commitment_config::CommitmentConfig, std::str::FromStr, +}; + +pub enum SettingType { + Explicit, + Computed, + SystemDefault, +} + +pub struct ConfigInput { + pub json_rpc_url: String, + pub websocket_url: String, + pub keypair_path: String, + pub commitment: CommitmentConfig, +} + +impl ConfigInput { + fn default_keypair_path() -> String { + Config::default().keypair_path + } + + fn default_json_rpc_url() -> String { + Config::default().json_rpc_url + } + + fn default_websocket_url() -> String { + Config::default().websocket_url + } + + fn default_commitment() -> CommitmentConfig { + CommitmentConfig::confirmed() + } + + fn first_nonempty_setting( + settings: std::vec::Vec<(SettingType, String)>, + ) -> (SettingType, String) { + settings + .into_iter() + .find(|(_, value)| !value.is_empty()) + .expect("no nonempty setting") + } + + fn first_setting_is_some( + settings: std::vec::Vec<(SettingType, Option)>, + ) -> (SettingType, T) { + let (setting_type, setting_option) = settings + .into_iter() + .find(|(_, value)| value.is_some()) + .expect("all settings none"); + (setting_type, setting_option.unwrap()) + } + + pub fn compute_websocket_url_setting( + websocket_cmd_url: &str, + websocket_cfg_url: &str, + json_rpc_cmd_url: &str, + json_rpc_cfg_url: &str, + ) -> (SettingType, String) { + Self::first_nonempty_setting(vec![ + (SettingType::Explicit, websocket_cmd_url.to_string()), + (SettingType::Explicit, websocket_cfg_url.to_string()), + ( + SettingType::Computed, + Config::compute_websocket_url(&normalize_to_url_if_moniker(json_rpc_cmd_url)), + ), + ( + SettingType::Computed, + Config::compute_websocket_url(&normalize_to_url_if_moniker(json_rpc_cfg_url)), + ), + (SettingType::SystemDefault, Self::default_websocket_url()), + ]) + } + + pub fn compute_json_rpc_url_setting( + json_rpc_cmd_url: &str, + json_rpc_cfg_url: &str, + ) -> (SettingType, String) { + let (setting_type, url_or_moniker) = Self::first_nonempty_setting(vec![ + (SettingType::Explicit, json_rpc_cmd_url.to_string()), + (SettingType::Explicit, json_rpc_cfg_url.to_string()), + (SettingType::SystemDefault, Self::default_json_rpc_url()), + ]); + (setting_type, normalize_to_url_if_moniker(&url_or_moniker)) + } + + pub fn compute_keypair_path_setting( + keypair_cmd_path: &str, + keypair_cfg_path: &str, + ) -> (SettingType, String) { + Self::first_nonempty_setting(vec![ + (SettingType::Explicit, keypair_cmd_path.to_string()), + (SettingType::Explicit, keypair_cfg_path.to_string()), + (SettingType::SystemDefault, Self::default_keypair_path()), + ]) + } + + pub fn compute_commitment_config( + commitment_cmd: &str, + commitment_cfg: &str, + ) -> (SettingType, CommitmentConfig) { + Self::first_setting_is_some(vec![ + ( + SettingType::Explicit, + CommitmentConfig::from_str(commitment_cmd).ok(), + ), + ( + SettingType::Explicit, + CommitmentConfig::from_str(commitment_cfg).ok(), + ), + (SettingType::SystemDefault, Some(Self::default_commitment())), + ]) + } +} + +impl Default for ConfigInput { + fn default() -> ConfigInput { + ConfigInput { + json_rpc_url: Self::default_json_rpc_url(), + websocket_url: Self::default_websocket_url(), + keypair_path: Self::default_keypair_path(), + commitment: CommitmentConfig::confirmed(), + } + } +} diff --git a/cli-config/src/lib.rs b/cli-config/src/lib.rs index 687a0a526f..0073262eb1 100644 --- a/cli-config/src/lib.rs +++ b/cli-config/src/lib.rs @@ -55,12 +55,16 @@ extern crate lazy_static; mod config; -pub use config::{Config, CONFIG_FILE}; +mod config_input; use std::{ fs::{create_dir_all, File}, io::{self, Write}, path::Path, }; +pub use { + config::{Config, CONFIG_FILE}, + config_input::{ConfigInput, SettingType}, +}; /// Load a value from a file in YAML format. /// diff --git a/cli-output/Cargo.toml b/cli-output/Cargo.toml index 9b285db101..3848b34865 100644 --- a/cli-output/Cargo.toml +++ b/cli-output/Cargo.toml @@ -23,6 +23,7 @@ serde = "1.0.136" serde_json = "1.0.79" solana-account-decoder = { path = "../account-decoder", version = "=1.11.0" } solana-clap-utils = { path = "../clap-utils", version = "=1.11.0" } +solana-cli-config = { path = "../cli-config", version = "=1.11.0" } solana-client = { path = "../client", version = "=1.11.0" } solana-sdk = { path = "../sdk", version = "=1.11.0" } solana-transaction-status = { path = "../transaction-status", version = "=1.11.0" } diff --git a/cli-output/src/display.rs b/cli-output/src/display.rs index 430fdeed2e..08d272721b 100644 --- a/cli-output/src/display.rs +++ b/cli-output/src/display.rs @@ -3,6 +3,7 @@ use { chrono::{DateTime, Local, NaiveDateTime, SecondsFormat, TimeZone, Utc}, console::style, indicatif::{ProgressBar, ProgressStyle}, + solana_cli_config::SettingType, solana_sdk::{ clock::UnixTimestamp, hash::Hash, @@ -104,6 +105,21 @@ pub fn writeln_name_value(f: &mut dyn fmt::Write, name: &str, value: &str) -> fm writeln!(f, "{} {}", style(name).bold(), styled_value) } +pub fn println_name_value_or(name: &str, value: &str, setting_type: SettingType) { + let description = match setting_type { + SettingType::Explicit => "", + SettingType::Computed => "(computed)", + SettingType::SystemDefault => "(default)", + }; + + println!( + "{} {} {}", + style(name).bold(), + style(value), + style(description).italic(), + ); +} + pub fn format_labeled_address(pubkey: &str, address_labels: &HashMap) -> String { let label = address_labels.get(pubkey); match label { diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 40b900b98f..697535826c 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -7,7 +7,8 @@ use { log::*, num_traits::FromPrimitive, serde_json::{self, Value}, - solana_clap_utils::{self, input_parsers::*, input_validators::*, keypair::*}, + solana_clap_utils::{self, input_parsers::*, keypair::*}, + solana_cli_config::ConfigInput, solana_cli_output::{ display::println_name_value, CliSignature, CliValidatorsSortOrder, OutputFormat, }, @@ -456,129 +457,23 @@ impl From for CliError { } } -pub enum SettingType { - Explicit, - Computed, - SystemDefault, -} - pub struct CliConfig<'a> { pub command: CliCommand, pub json_rpc_url: String, pub websocket_url: String, - pub signers: Vec<&'a dyn Signer>, pub keypair_path: String, + pub commitment: CommitmentConfig, + pub signers: Vec<&'a dyn Signer>, pub rpc_client: Option>, pub rpc_timeout: Duration, pub verbose: bool, pub output_format: OutputFormat, - pub commitment: CommitmentConfig, pub send_transaction_config: RpcSendTransactionConfig, pub confirm_transaction_initial_timeout: Duration, pub address_labels: HashMap, } impl CliConfig<'_> { - fn default_keypair_path() -> String { - solana_cli_config::Config::default().keypair_path - } - - fn default_json_rpc_url() -> String { - solana_cli_config::Config::default().json_rpc_url - } - - fn default_websocket_url() -> String { - solana_cli_config::Config::default().websocket_url - } - - fn default_commitment() -> CommitmentConfig { - CommitmentConfig::confirmed() - } - - fn first_nonempty_setting( - settings: std::vec::Vec<(SettingType, String)>, - ) -> (SettingType, String) { - settings - .into_iter() - .find(|(_, value)| !value.is_empty()) - .expect("no nonempty setting") - } - - fn first_setting_is_some( - settings: std::vec::Vec<(SettingType, Option)>, - ) -> (SettingType, T) { - let (setting_type, setting_option) = settings - .into_iter() - .find(|(_, value)| value.is_some()) - .expect("all settings none"); - (setting_type, setting_option.unwrap()) - } - - pub fn compute_websocket_url_setting( - websocket_cmd_url: &str, - websocket_cfg_url: &str, - json_rpc_cmd_url: &str, - json_rpc_cfg_url: &str, - ) -> (SettingType, String) { - Self::first_nonempty_setting(vec![ - (SettingType::Explicit, websocket_cmd_url.to_string()), - (SettingType::Explicit, websocket_cfg_url.to_string()), - ( - SettingType::Computed, - solana_cli_config::Config::compute_websocket_url(&normalize_to_url_if_moniker( - json_rpc_cmd_url, - )), - ), - ( - SettingType::Computed, - solana_cli_config::Config::compute_websocket_url(&normalize_to_url_if_moniker( - json_rpc_cfg_url, - )), - ), - (SettingType::SystemDefault, Self::default_websocket_url()), - ]) - } - - pub fn compute_json_rpc_url_setting( - json_rpc_cmd_url: &str, - json_rpc_cfg_url: &str, - ) -> (SettingType, String) { - let (setting_type, url_or_moniker) = Self::first_nonempty_setting(vec![ - (SettingType::Explicit, json_rpc_cmd_url.to_string()), - (SettingType::Explicit, json_rpc_cfg_url.to_string()), - (SettingType::SystemDefault, Self::default_json_rpc_url()), - ]); - (setting_type, normalize_to_url_if_moniker(&url_or_moniker)) - } - - pub fn compute_keypair_path_setting( - keypair_cmd_path: &str, - keypair_cfg_path: &str, - ) -> (SettingType, String) { - Self::first_nonempty_setting(vec![ - (SettingType::Explicit, keypair_cmd_path.to_string()), - (SettingType::Explicit, keypair_cfg_path.to_string()), - (SettingType::SystemDefault, Self::default_keypair_path()), - ]) - } - - pub fn compute_commitment_config( - commitment_cmd: &str, - commitment_cfg: &str, - ) -> (SettingType, CommitmentConfig) { - Self::first_setting_is_some(vec![ - ( - SettingType::Explicit, - CommitmentConfig::from_str(commitment_cmd).ok(), - ), - ( - SettingType::Explicit, - CommitmentConfig::from_str(commitment_cfg).ok(), - ), - (SettingType::SystemDefault, Some(Self::default_commitment())), - ]) - } - pub(crate) fn pubkey(&self) -> Result { if !self.signers.is_empty() { self.signers[0].try_pubkey() @@ -609,15 +504,15 @@ impl Default for CliConfig<'_> { pubkey: Some(Pubkey::default()), use_lamports_unit: false, }, - json_rpc_url: Self::default_json_rpc_url(), - websocket_url: Self::default_websocket_url(), + json_rpc_url: ConfigInput::default().json_rpc_url, + websocket_url: ConfigInput::default().websocket_url, + keypair_path: ConfigInput::default().keypair_path, + commitment: ConfigInput::default().commitment, signers: Vec::new(), - keypair_path: Self::default_keypair_path(), rpc_client: None, rpc_timeout: Duration::from_secs(u64::from_str(DEFAULT_RPC_TIMEOUT_SECONDS).unwrap()), verbose: false, output_format: OutputFormat::Display, - commitment: CommitmentConfig::confirmed(), send_transaction_config: RpcSendTransactionConfig::default(), confirm_transaction_initial_timeout: Duration::from_secs( u64::from_str(DEFAULT_CONFIRM_TX_TIMEOUT_SECONDS).unwrap(), diff --git a/cli/src/main.rs b/cli/src/main.rs index e98c176127..e80ac7c2aa 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -8,30 +8,18 @@ use { }, solana_cli::{ clap_app::get_clap_app, - cli::{parse_command, process_command, CliCommandInfo, CliConfig, SettingType}, + cli::{parse_command, process_command, CliCommandInfo, CliConfig}, + }, + solana_cli_config::{Config, ConfigInput}, + solana_cli_output::{ + display::{println_name_value, println_name_value_or}, + OutputFormat, }, - solana_cli_config::Config, - solana_cli_output::{display::println_name_value, OutputFormat}, solana_client::rpc_config::RpcSendTransactionConfig, solana_remote_wallet::remote_wallet::RemoteWalletManager, std::{collections::HashMap, error, path::PathBuf, sync::Arc, time::Duration}, }; -pub fn println_name_value_or(name: &str, value: &str, setting_type: SettingType) { - let description = match setting_type { - SettingType::Explicit => "", - SettingType::Computed => "(computed)", - SettingType::SystemDefault => "(default)", - }; - - println!( - "{} {} {}", - style(name).bold(), - style(value), - style(description).italic(), - ); -} - fn parse_settings(matches: &ArgMatches<'_>) -> Result> { let parse_args = match matches.subcommand() { ("config", Some(matches)) => { @@ -50,17 +38,18 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result { let (url_setting_type, json_rpc_url) = - CliConfig::compute_json_rpc_url_setting("", &config.json_rpc_url); - let (ws_setting_type, websocket_url) = CliConfig::compute_websocket_url_setting( - "", - &config.websocket_url, - "", - &config.json_rpc_url, - ); + ConfigInput::compute_json_rpc_url_setting("", &config.json_rpc_url); + let (ws_setting_type, websocket_url) = + ConfigInput::compute_websocket_url_setting( + "", + &config.websocket_url, + "", + &config.json_rpc_url, + ); let (keypair_setting_type, keypair_path) = - CliConfig::compute_keypair_path_setting("", &config.keypair_path); + ConfigInput::compute_keypair_path_setting("", &config.keypair_path); let (commitment_setting_type, commitment) = - CliConfig::compute_commitment_config("", &config.commitment); + ConfigInput::compute_commitment_config("", &config.commitment); if let Some(field) = subcommand_matches.value_of("specific_setting") { let (field_name, value, setting_type) = match field { @@ -107,17 +96,18 @@ fn parse_settings(matches: &ArgMatches<'_>) -> Result( } else { Config::default() }; - let (_, json_rpc_url) = CliConfig::compute_json_rpc_url_setting( + let (_, json_rpc_url) = ConfigInput::compute_json_rpc_url_setting( matches.value_of("json_rpc_url").unwrap_or(""), &config.json_rpc_url, ); @@ -171,14 +161,14 @@ pub fn parse_args<'a>( let confirm_transaction_initial_timeout = Duration::from_secs(confirm_transaction_initial_timeout); - let (_, websocket_url) = CliConfig::compute_websocket_url_setting( + let (_, websocket_url) = ConfigInput::compute_websocket_url_setting( matches.value_of("websocket_url").unwrap_or(""), &config.websocket_url, matches.value_of("json_rpc_url").unwrap_or(""), &config.json_rpc_url, ); let default_signer_arg_name = "keypair".to_string(); - let (_, default_signer_path) = CliConfig::compute_keypair_path_setting( + let (_, default_signer_path) = ConfigInput::compute_keypair_path_setting( matches.value_of(&default_signer_arg_name).unwrap_or(""), &config.keypair_path, ); @@ -201,7 +191,7 @@ pub fn parse_args<'a>( let verbose = matches.is_present("verbose"); let output_format = OutputFormat::from_matches(matches, "output_format", verbose); - let (_, commitment) = CliConfig::compute_commitment_config( + let (_, commitment) = ConfigInput::compute_commitment_config( matches.value_of("commitment").unwrap_or(""), &config.commitment, ); diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index 2e83adae2b..8f211ed3c2 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -3312,6 +3312,8 @@ dependencies = [ "serde", "serde_derive", "serde_yaml", + "solana-clap-utils", + "solana-sdk", "url", ] @@ -3332,6 +3334,7 @@ dependencies = [ "serde_json", "solana-account-decoder", "solana-clap-utils", + "solana-cli-config", "solana-client", "solana-sdk", "solana-transaction-status",