diff --git a/clap-utils/src/input_validators.rs b/clap-utils/src/input_validators.rs index c3355ef038..cad78a723f 100644 --- a/clap-utils/src/input_validators.rs +++ b/clap-utils/src/input_validators.rs @@ -148,6 +148,33 @@ where } } +pub fn is_url_or_moniker(string: T) -> Result<(), String> +where + T: AsRef + Display, +{ + match url::Url::parse(&normalize_to_url_if_moniker(string.as_ref())) { + Ok(url) => { + if url.has_host() { + Ok(()) + } else { + Err("no host provided".to_string()) + } + } + Err(err) => Err(format!("{}", err)), + } +} + +pub fn normalize_to_url_if_moniker(url_or_moniker: &str) -> String { + match url_or_moniker { + "m" | "mainnet-beta" => "https://api.mainnet-beta.solana.com", + "t" | "testnet" => "https://testnet.solana.com", + "d" | "devnet" => "https://devnet.solana.com", + "l" | "localhost" => "http://localhost:8899", + url => url, + } + .to_string() +} + pub fn is_epoch(epoch: T) -> Result<(), String> where T: AsRef + Display, diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 0ed0d5345f..602aa6d7d6 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -465,11 +465,12 @@ impl CliConfig<'_> { json_rpc_cmd_url: &str, json_rpc_cfg_url: &str, ) -> (SettingType, String) { - Self::first_nonempty_setting(vec![ + 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( diff --git a/cli/src/main.rs b/cli/src/main.rs index df4523b3b1..26f993954e 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -7,7 +7,7 @@ use console::style; use solana_clap_utils::{ commitment::COMMITMENT_ARG, input_parsers::commitment_of, - input_validators::is_url, + input_validators::{is_url, is_url_or_moniker}, keypair::{CliSigners, DefaultSigner, SKIP_SEED_PHRASE_VALIDATION_ARG}, DisplayError, }; @@ -246,11 +246,14 @@ fn main() -> Result<(), Box> { Arg::with_name("json_rpc_url") .short("u") .long("url") - .value_name("URL") + .value_name("URL_OR_MONIKER") .takes_value(true) .global(true) - .validator(is_url) - .help("JSON RPC URL for the solana cluster"), + .validator(is_url_or_moniker) + .help( + "URL for Solana's JSON RPC or moniker (or their first letter): \ + [mainnet-beta, testnet, devnet, localhost]", + ), ) .arg( Arg::with_name("websocket_url")