diff --git a/clap-v3-utils/src/input_parsers.rs b/clap-v3-utils/src/input_parsers.rs index a8f18e204..03b3ba3be 100644 --- a/clap-v3-utils/src/input_parsers.rs +++ b/clap-v3-utils/src/input_parsers.rs @@ -14,7 +14,7 @@ use { pubkey::Pubkey, signature::{read_keypair_file, Keypair, Signature, Signer}, }, - std::{rc::Rc, str::FromStr}, + std::{error, rc::Rc, str::FromStr}, }; // Sentinel value used to indicate to write to screen instead of file @@ -69,6 +69,15 @@ pub fn keypair_of(matches: &ArgMatches, name: &str) -> Option { } } +// Return the keypair for an argument with filename `name` or `None` if not present wrapped inside `Result`. +pub fn try_keypair_of( + matches: &ArgMatches, + name: &str, +) -> Result, Box> { + matches.try_contains_id(name)?; + Ok(keypair_of(matches, name)) +} + pub fn keypairs_of(matches: &ArgMatches, name: &str) -> Option> { matches.values_of(name).map(|values| { values @@ -84,12 +93,30 @@ pub fn keypairs_of(matches: &ArgMatches, name: &str) -> Option> { }) } +pub fn try_keypairs_of( + matches: &ArgMatches, + name: &str, +) -> Result>, Box> { + matches.try_contains_id(name)?; + Ok(keypairs_of(matches, name)) +} + // Return a pubkey for an argument that can itself be parsed into a pubkey, // or is a filename that can be read as a keypair pub fn pubkey_of(matches: &ArgMatches, name: &str) -> Option { value_of(matches, name).or_else(|| keypair_of(matches, name).map(|keypair| keypair.pubkey())) } +// Return a `Result` wrapped pubkey for an argument that can itself be parsed into a pubkey, +// or is a filename that can be read as a keypair +pub fn try_pubkey_of( + matches: &ArgMatches, + name: &str, +) -> Result, Box> { + matches.try_contains_id(name)?; + Ok(pubkey_of(matches, name)) +} + pub fn pubkeys_of(matches: &ArgMatches, name: &str) -> Option> { matches.values_of(name).map(|values| { values @@ -104,6 +131,14 @@ pub fn pubkeys_of(matches: &ArgMatches, name: &str) -> Option> { }) } +pub fn try_pubkeys_of( + matches: &ArgMatches, + name: &str, +) -> Result>, Box> { + matches.try_contains_id(name)?; + Ok(pubkeys_of(matches, name)) +} + // Return pubkey/signature pairs for a string of the form pubkey=signature pub fn pubkeys_sigs_of(matches: &ArgMatches, name: &str) -> Option> { matches.values_of(name).map(|values| { @@ -118,6 +153,16 @@ pub fn pubkeys_sigs_of(matches: &ArgMatches, name: &str) -> Option Result>, Box> { + matches.try_contains_id(name)?; + Ok(pubkeys_sigs_of(matches, name)) +} + // Return a signer from matches at `name` #[allow(clippy::type_complexity)] pub fn signer_of( @@ -125,7 +170,7 @@ pub fn signer_of( name: &str, wallet_manager: &mut Option>, ) -> Result<(Option>, Option), Box> { - if let Some(location) = matches.value_of(name) { + if let Some(location) = matches.try_get_one::(name)? { let signer = signer_from_path(matches, location, name, wallet_manager)?; let signer_pubkey = signer.pubkey(); Ok((Some(signer), Some(signer_pubkey))) @@ -139,7 +184,7 @@ pub fn pubkey_of_signer( name: &str, wallet_manager: &mut Option>, ) -> Result, Box> { - if let Some(location) = matches.value_of(name) { + if let Some(location) = matches.try_get_one::(name)? { Ok(Some(pubkey_from_path( matches, location, @@ -156,7 +201,7 @@ pub fn pubkeys_of_multiple_signers( name: &str, wallet_manager: &mut Option>, ) -> Result>, Box> { - if let Some(pubkey_matches) = matches.values_of(name) { + if let Some(pubkey_matches) = matches.try_get_many::(name)? { let mut pubkeys: Vec = vec![]; for signer in pubkey_matches { pubkeys.push(pubkey_from_path(matches, signer, name, wallet_manager)?); @@ -174,7 +219,7 @@ pub fn resolve_signer( ) -> Result, Box> { resolve_signer_from_path( matches, - matches.value_of(name).unwrap(), + matches.try_get_one::(name)?.unwrap(), name, wallet_manager, ) diff --git a/clap-v3-utils/src/keygen/derivation_path.rs b/clap-v3-utils/src/keygen/derivation_path.rs index 9c57323d0..5e0d79a1c 100644 --- a/clap-v3-utils/src/keygen/derivation_path.rs +++ b/clap-v3-utils/src/keygen/derivation_path.rs @@ -22,10 +22,11 @@ pub fn derivation_path_arg<'a>() -> Arg<'a> { pub fn acquire_derivation_path( matches: &ArgMatches, ) -> Result, Box> { - if matches.is_present("derivation_path") { + if matches.try_contains_id("derivation_path")? { Ok(Some(DerivationPath::from_absolute_path_str( matches - .value_of("derivation_path") + .try_get_one::("derivation_path")? + .map(|path| path.as_str()) .unwrap_or(DEFAULT_DERIVATION_PATH), )?)) } else { diff --git a/clap-v3-utils/src/keygen/mnemonic.rs b/clap-v3-utils/src/keygen/mnemonic.rs index c7c1d4d08..5813e5350 100644 --- a/clap-v3-utils/src/keygen/mnemonic.rs +++ b/clap-v3-utils/src/keygen/mnemonic.rs @@ -62,7 +62,11 @@ pub fn no_passphrase_arg<'a>() -> Arg<'a> { } pub fn acquire_language(matches: &ArgMatches) -> Language { - match matches.value_of(LANGUAGE_ARG.name).unwrap() { + match matches + .get_one::(LANGUAGE_ARG.name) + .unwrap() + .as_str() + { "english" => Language::English, "chinese-simplified" => Language::ChineseSimplified, "chinese-traditional" => Language::ChineseTraditional, @@ -82,7 +86,7 @@ pub fn no_passphrase_and_message() -> (String, String) { pub fn acquire_passphrase_and_message( matches: &ArgMatches, ) -> Result<(String, String), Box> { - if matches.is_present(NO_PASSPHRASE_ARG.name) { + if matches.try_contains_id(NO_PASSPHRASE_ARG.name)? { Ok(no_passphrase_and_message()) } else { match prompt_passphrase( diff --git a/clap-v3-utils/src/keygen/mod.rs b/clap-v3-utils/src/keygen/mod.rs index ec74df382..f73700517 100644 --- a/clap-v3-utils/src/keygen/mod.rs +++ b/clap-v3-utils/src/keygen/mod.rs @@ -38,7 +38,7 @@ pub fn check_for_overwrite( outfile: &str, matches: &ArgMatches, ) -> Result<(), Box> { - let force = matches.is_present("force"); + let force = matches.try_contains_id("force")?; if !force && Path::new(outfile).exists() { let err_msg = format!("Refusing to overwrite {outfile} without --force flag"); return Err(err_msg.into()); diff --git a/clap-v3-utils/src/keypair.rs b/clap-v3-utils/src/keypair.rs index 7ab48621b..886deabfb 100644 --- a/clap-v3-utils/src/keypair.rs +++ b/clap-v3-utils/src/keypair.rs @@ -765,7 +765,7 @@ pub fn signer_from_path_with_config( } = parse_signer_source(path)?; match kind { SignerSourceKind::Prompt => { - let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name); + let skip_validation = matches.try_contains_id(SKIP_SEED_PHRASE_VALIDATION_ARG.name)?; Ok(Box::new(keypair_from_seed_phrase( keypair_name, skip_validation, @@ -809,7 +809,7 @@ pub fn signer_from_path_with_config( .and_then(|presigners| presigner_from_pubkey_sigs(&pubkey, presigners)); if let Some(presigner) = presigner { Ok(Box::new(presigner)) - } else if config.allow_null_signer || matches.is_present(SIGN_ONLY_ARG.name) { + } else if config.allow_null_signer || matches.try_contains_id(SIGN_ONLY_ARG.name)? { Ok(Box::new(NullSigner::new(&pubkey))) } else { Err(std::io::Error::new( @@ -885,7 +885,7 @@ pub fn resolve_signer_from_path( } = parse_signer_source(path)?; match kind { SignerSourceKind::Prompt => { - let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name); + let skip_validation = matches.try_contains_id(SKIP_SEED_PHRASE_VALIDATION_ARG.name)?; // This method validates the seed phrase, but returns `None` because there is no path // on disk or to a device keypair_from_seed_phrase( @@ -1004,7 +1004,7 @@ pub fn keypair_from_path( keypair_name: &str, confirm_pubkey: bool, ) -> Result> { - let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name); + let skip_validation = matches.try_contains_id(SKIP_SEED_PHRASE_VALIDATION_ARG.name)?; let keypair = encodable_key_from_path(path, keypair_name, skip_validation)?; if confirm_pubkey { confirm_encodable_keypair_pubkey(&keypair, "pubkey"); @@ -1052,7 +1052,7 @@ pub fn elgamal_keypair_from_path( elgamal_keypair_name: &str, confirm_pubkey: bool, ) -> Result> { - let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name); + let skip_validation = matches.try_contains_id(SKIP_SEED_PHRASE_VALIDATION_ARG.name)?; let elgamal_keypair = encodable_key_from_path(path, elgamal_keypair_name, skip_validation)?; if confirm_pubkey { confirm_encodable_keypair_pubkey(&elgamal_keypair, "ElGamal pubkey"); @@ -1107,7 +1107,7 @@ pub fn ae_key_from_path( path: &str, key_name: &str, ) -> Result> { - let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name); + let skip_validation = matches.try_contains_id(SKIP_SEED_PHRASE_VALIDATION_ARG.name)?; encodable_key_from_path(path, key_name, skip_validation) }