From 76f5da85e4accb84b8749150acab041ce32951c3 Mon Sep 17 00:00:00 2001 From: samkim-crypto Date: Fri, 15 Nov 2024 11:17:23 +0900 Subject: [PATCH 1/7] update `Config::pubkey_or_default` --- token/cli/src/clap_app.rs | 43 ++++++++++++++++++++++++--------------- token/cli/src/config.rs | 9 ++++---- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/token/cli/src/clap_app.rs b/token/cli/src/clap_app.rs index 814c1c18c67..ad8c0762a10 100644 --- a/token/cli/src/clap_app.rs +++ b/token/cli/src/clap_app.rs @@ -6,7 +6,7 @@ use { }, solana_clap_v3_utils::{ fee_payer::fee_payer_arg, - input_parsers::Amount, + input_parsers::{signer::SignerSourceParserBuilder, Amount}, input_validators::{is_pubkey, is_url_or_moniker, is_valid_pubkey, is_valid_signer}, memo::memo_arg, nonce::*, @@ -282,6 +282,17 @@ pub fn owner_address_arg<'a>() -> Arg<'a> { .help(OWNER_ADDRESS_ARG.help) } +// Temporary function that uses proper parsing to minimize commit size +// TODO: use this to replace `owner_address_arg` +pub fn owner_address_arg_temp<'a>() -> Arg<'a> { + Arg::with_name(OWNER_ADDRESS_ARG.name) + .long(OWNER_ADDRESS_ARG.long) + .takes_value(true) + .value_name("OWNER_ADDRESS") + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) + .help(OWNER_ADDRESS_ARG.help) +} + pub fn owner_keypair_arg_with_value_name<'a>(value_name: &'static str) -> Arg<'a> { Arg::with_name(OWNER_KEYPAIR_ARG.name) .long(OWNER_KEYPAIR_ARG.long) @@ -1228,7 +1239,7 @@ pub fn app<'a>( "Lock the owner of this token account from ever being changed" ), ) - .arg(owner_address_arg()) + .arg(owner_address_arg_temp()) .nonce_args(true) ) .subcommand( @@ -1759,7 +1770,7 @@ pub fn app<'a>( .arg( Arg::with_name("recipient") .long("recipient") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("REFUND_ACCOUNT_ADDRESS") .takes_value(true) .help("The address of the account to receive remaining SOL [default: --owner]"), @@ -1807,7 +1818,7 @@ pub fn app<'a>( .arg( Arg::with_name("recipient") .long("recipient") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("REFUND_ACCOUNT_ADDRESS") .takes_value(true) .help("The address of the account to receive remaining SOL [default: --owner]"), @@ -1834,17 +1845,17 @@ pub fn app<'a>( .about("Get token account balance") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) .required_unless("address") .help("Token of associated account. To query a specific account, use the `--address` parameter instead"), ) - .arg(owner_address_arg().conflicts_with("address")) + .arg(owner_address_arg_temp().conflicts_with("address")) .arg( Arg::with_name("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .long("address") @@ -1905,7 +1916,7 @@ pub fn app<'a>( "Print token account addresses only" ), ) - .arg(owner_address_arg()) + .arg(owner_address_arg_temp()) ) .subcommand( SubCommand::with_name(CommandName::Address.into()) @@ -1921,7 +1932,7 @@ pub fn app<'a>( [Default: return the client keypair address]") ) .arg( - owner_address_arg() + owner_address_arg_temp() .requires("token") .help("Return the associated token address for the given owner. \ [Default: return the associated token address for the client keypair]"), @@ -1933,7 +1944,7 @@ pub fn app<'a>( .setting(AppSettings::Hidden) .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2028,7 +2039,7 @@ pub fn app<'a>( .about("Enable required transfer memos for token account") .arg( Arg::with_name("account") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -2046,7 +2057,7 @@ pub fn app<'a>( .about("Disable required transfer memos for token account") .arg( Arg::with_name("account") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -2064,7 +2075,7 @@ pub fn app<'a>( .about("Enable CPI Guard for token account") .arg( Arg::with_name("account") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -2082,7 +2093,7 @@ pub fn app<'a>( .about("Disable CPI Guard for token account") .arg( Arg::with_name("account") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -2357,7 +2368,7 @@ pub fn app<'a>( .about("Withdraw lamports from a Token Program owned account") .arg( Arg::with_name("from") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("SOURCE_ACCOUNT_ADDRESS") .takes_value(true) .required(true) @@ -2365,7 +2376,7 @@ pub fn app<'a>( ) .arg( Arg::with_name("recipient") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("REFUND_ACCOUNT_ADDRESS") .takes_value(true) .required(true) diff --git a/token/cli/src/config.rs b/token/cli/src/config.rs index 0ea6284bb78..fba2f830a28 100644 --- a/token/cli/src/config.rs +++ b/token/cli/src/config.rs @@ -2,7 +2,7 @@ use { crate::clap_app::{Error, COMPUTE_UNIT_LIMIT_ARG, COMPUTE_UNIT_PRICE_ARG, MULTISIG_SIGNER_ARG}, clap::ArgMatches, solana_clap_v3_utils::{ - input_parsers::pubkey_of_signer, + input_parsers::{pubkey_of_signer, signer::SignerSource}, input_validators::normalize_to_url_if_moniker, keypair::SignerFromPathConfig, nonce::{NONCE_ARG, NONCE_AUTHORITY_ARG}, @@ -398,7 +398,7 @@ impl<'a> Config<'a> { override_name: &str, wallet_manager: &mut Option>, ) -> Result { - let token = pubkey_of_signer(arg_matches, "token", wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", wallet_manager) .map_err(|e| -> Error { e.to_string().into() })?; self.associated_token_address_for_token_or_override( arg_matches, @@ -449,8 +449,9 @@ impl<'a> Config<'a> { address_name: &str, wallet_manager: &mut Option>, ) -> Result { - if let Some(address) = pubkey_of_signer(arg_matches, address_name, wallet_manager) - .map_err(|e| -> Error { e.to_string().into() })? + if let Some(address) = + SignerSource::try_get_pubkey(arg_matches, address_name, wallet_manager) + .map_err(|e| -> Error { e.to_string().into() })? { return Ok(address); } From 58e0441e809da1184f6431af5f4119374af33333 Mon Sep 17 00:00:00 2001 From: samkim-crypto Date: Fri, 22 Nov 2024 11:04:41 +0900 Subject: [PATCH 2/7] update `Config::new_with_clients_and_ws_url` to parse owner from source --- token/cli/src/clap_app.rs | 6 ++--- token/cli/src/command.rs | 6 +---- token/cli/src/config.rs | 51 ++++++++++++++++++++++++++++++++------- token/cli/src/lib.rs | 5 ++++ 4 files changed, 51 insertions(+), 17 deletions(-) diff --git a/token/cli/src/clap_app.rs b/token/cli/src/clap_app.rs index ad8c0762a10..39f079f14da 100644 --- a/token/cli/src/clap_app.rs +++ b/token/cli/src/clap_app.rs @@ -298,7 +298,7 @@ pub fn owner_keypair_arg_with_value_name<'a>(value_name: &'static str) -> Arg<'a .long(OWNER_KEYPAIR_ARG.long) .takes_value(true) .value_name(value_name) - .validator(|s| is_valid_signer(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .help(OWNER_KEYPAIR_ARG.help) } @@ -1798,7 +1798,7 @@ pub fn app<'a>( .help("Specify the token account to close \ [default: owner's associated token account]"), ) - .arg(owner_address_arg()) + .arg(owner_address_arg_temp()) .arg(multisig_signer_arg()) .nonce_args(true) .offline_args(), @@ -2382,7 +2382,7 @@ pub fn app<'a>( .required(true) .help("Specify the address of the account to send lamports to"), ) - .arg(owner_address_arg()) + .arg(owner_address_arg_temp()) .arg(multisig_signer_arg()) ) .subcommand( diff --git a/token/cli/src/command.rs b/token/cli/src/command.rs index 8a7cf30b5dd..7170c1734af 100644 --- a/token/cli/src/command.rs +++ b/token/cli/src/command.rs @@ -6,6 +6,7 @@ use { config::{Config, MintInfo}, encryption_keypair::*, output::*, + print_error_and_exit, sort::{sort_and_parse_token_accounts, AccountFilter}, }, clap::{value_t, value_t_or_exit, ArgMatches}, @@ -79,11 +80,6 @@ use { std::{collections::HashMap, fmt::Display, process::exit, rc::Rc, str::FromStr, sync::Arc}, }; -fn print_error_and_exit(e: E) -> T { - eprintln!("error: {}", e); - exit(1) -} - fn amount_to_raw_amount(amount: Amount, decimals: u8, all_amount: Option, name: &str) -> u64 { match amount { Amount::Raw(ui_amount) => ui_amount, diff --git a/token/cli/src/config.rs b/token/cli/src/config.rs index fba2f830a28..65c20dd5f76 100644 --- a/token/cli/src/config.rs +++ b/token/cli/src/config.rs @@ -1,8 +1,14 @@ use { - crate::clap_app::{Error, COMPUTE_UNIT_LIMIT_ARG, COMPUTE_UNIT_PRICE_ARG, MULTISIG_SIGNER_ARG}, + crate::{ + clap_app::{Error, COMPUTE_UNIT_LIMIT_ARG, COMPUTE_UNIT_PRICE_ARG, MULTISIG_SIGNER_ARG}, + print_error_and_exit, + }, clap::ArgMatches, solana_clap_v3_utils::{ - input_parsers::{pubkey_of_signer, signer::SignerSource}, + input_parsers::{ + pubkey_of_signer, + signer::{SignerSource, SignerSourceKind}, + }, input_validators::normalize_to_url_if_moniker, keypair::SignerFromPathConfig, nonce::{NONCE_ARG, NONCE_AUTHORITY_ARG}, @@ -181,23 +187,23 @@ impl<'a> Config<'a> { }; let default_keypair = cli_config.keypair_path.clone(); - + let default_keypair_source = + SignerSource::parse(&default_keypair).unwrap_or_else(print_error_and_exit); let default_signer: Option> = { - if let Some(owner_path) = matches.try_get_one::("owner").ok().flatten() { - signer_from_path_with_config(matches, owner_path, "owner", wallet_manager, &config) + if let Some(source) = matches.try_get_one::("owner").ok().flatten() { + signer_from_source_with_config(matches, source, "owner", wallet_manager, &config) .ok() } else { - signer_from_path_with_config( + signer_from_source_with_config( matches, - &default_keypair, + &default_keypair_source, "default", wallet_manager, &config, ) .map_err(|e| { if std::fs::metadata(&default_keypair).is_ok() { - eprintln!("error: {}", e); - exit(1); + print_error_and_exit(e) } else { e } @@ -616,3 +622,30 @@ fn signer_from_path_with_config( config, ) } + +/// A wrapper function around the `solana_clap_v3_utils` `signer_from_source +/// with_config` function. If the signer source is a pubkey, then it checks for +/// signing-only or if null signer is allowed and creates a null signer. +/// Otherwise, it invokes the `solana_clap_v3_utils` version of the function. +fn signer_from_source_with_config( + matches: &ArgMatches, + source: &SignerSource, + keypair_name: &str, + wallet_manager: &mut Option>, + config: &SignerFromPathConfig, +) -> Result, Box> { + if let SignerSourceKind::Pubkey(pubkey) = source.kind { + if matches.try_contains_id(SIGNER_ARG.name).is_err() + && (config.allow_null_signer || matches.try_contains_id(SIGN_ONLY_ARG.name)?) + { + return Ok(Box::new(NullSigner::new(&pubkey))); + } + } + solana_clap_v3_utils::keypair::signer_from_source_with_config( + matches, + source, + keypair_name, + wallet_manager, + config, + ) +} diff --git a/token/cli/src/lib.rs b/token/cli/src/lib.rs index b38c26b44fd..d78b11215c7 100644 --- a/token/cli/src/lib.rs +++ b/token/cli/src/lib.rs @@ -5,3 +5,8 @@ pub mod config; mod encryption_keypair; mod output; mod sort; + +fn print_error_and_exit(e: E) -> T { + eprintln!("error: {}", e); + std::process::exit(1) +} From dc311a77a04fa0f7f17fe47158131e16004cd260 Mon Sep 17 00:00:00 2001 From: samkim-crypto Date: Fri, 22 Nov 2024 11:28:35 +0900 Subject: [PATCH 3/7] update `owner_address_arg` to use parser instead of validator --- token/cli/src/clap_app.rs | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/token/cli/src/clap_app.rs b/token/cli/src/clap_app.rs index 39f079f14da..4d64372ad03 100644 --- a/token/cli/src/clap_app.rs +++ b/token/cli/src/clap_app.rs @@ -274,17 +274,6 @@ impl TryFrom for AuthorityType { } pub fn owner_address_arg<'a>() -> Arg<'a> { - Arg::with_name(OWNER_ADDRESS_ARG.name) - .long(OWNER_ADDRESS_ARG.long) - .takes_value(true) - .value_name("OWNER_ADDRESS") - .validator(|s| is_valid_pubkey(s)) - .help(OWNER_ADDRESS_ARG.help) -} - -// Temporary function that uses proper parsing to minimize commit size -// TODO: use this to replace `owner_address_arg` -pub fn owner_address_arg_temp<'a>() -> Arg<'a> { Arg::with_name(OWNER_ADDRESS_ARG.name) .long(OWNER_ADDRESS_ARG.long) .takes_value(true) @@ -1239,7 +1228,7 @@ pub fn app<'a>( "Lock the owner of this token account from ever being changed" ), ) - .arg(owner_address_arg_temp()) + .arg(owner_address_arg()) .nonce_args(true) ) .subcommand( @@ -1798,7 +1787,7 @@ pub fn app<'a>( .help("Specify the token account to close \ [default: owner's associated token account]"), ) - .arg(owner_address_arg_temp()) + .arg(owner_address_arg()) .arg(multisig_signer_arg()) .nonce_args(true) .offline_args(), @@ -1852,7 +1841,7 @@ pub fn app<'a>( .required_unless("address") .help("Token of associated account. To query a specific account, use the `--address` parameter instead"), ) - .arg(owner_address_arg_temp().conflicts_with("address")) + .arg(owner_address_arg().conflicts_with("address")) .arg( Arg::with_name("address") .value_parser(SignerSourceParserBuilder::default().allow_all().build()) @@ -1916,7 +1905,7 @@ pub fn app<'a>( "Print token account addresses only" ), ) - .arg(owner_address_arg_temp()) + .arg(owner_address_arg()) ) .subcommand( SubCommand::with_name(CommandName::Address.into()) @@ -1932,7 +1921,7 @@ pub fn app<'a>( [Default: return the client keypair address]") ) .arg( - owner_address_arg_temp() + owner_address_arg() .requires("token") .help("Return the associated token address for the given owner. \ [Default: return the associated token address for the client keypair]"), @@ -2382,7 +2371,7 @@ pub fn app<'a>( .required(true) .help("Specify the address of the account to send lamports to"), ) - .arg(owner_address_arg_temp()) + .arg(owner_address_arg()) .arg(multisig_signer_arg()) ) .subcommand( From 8d27503c39ff24620b18d47fcbf62b62fd3cbeae Mon Sep 17 00:00:00 2001 From: samkim-crypto Date: Fri, 22 Nov 2024 11:28:47 +0900 Subject: [PATCH 4/7] remove instances of `is_valid_pubkey` --- token/cli/src/bench.rs | 14 +-- token/cli/src/clap_app.rs | 179 +++++++++++++++----------------- token/cli/src/command.rs | 213 +++++++++++++++++++++++--------------- token/cli/src/config.rs | 15 ++- 4 files changed, 228 insertions(+), 193 deletions(-) diff --git a/token/cli/src/bench.rs b/token/cli/src/bench.rs index 209591cefdd..bd91f0d3e60 100644 --- a/token/cli/src/bench.rs +++ b/token/cli/src/bench.rs @@ -2,7 +2,7 @@ use { crate::{clap_app::Error, command::CommandResult, config::Config}, clap::ArgMatches, - solana_clap_v3_utils::input_parsers::{pubkey_of_signer, Amount}, + solana_clap_v3_utils::input_parsers::{pubkey_of_signer, signer::SignerSource, Amount}, solana_client::{ nonblocking::rpc_client::RpcClient, rpc_client::RpcClient as BlockingRpcClient, tpu_client::TpuClient, tpu_client::TpuClientConfig, @@ -31,7 +31,7 @@ pub(crate) async fn bench_process_command( match matches.subcommand() { Some(("create-accounts", arg_matches)) => { - let token = pubkey_of_signer(arg_matches, "token", wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", wallet_manager) .unwrap() .unwrap(); let n = *arg_matches.get_one::("n").unwrap(); @@ -43,7 +43,7 @@ pub(crate) async fn bench_process_command( command_create_accounts(config, signers, &token, n, &owner).await?; } Some(("close-accounts", arg_matches)) => { - let token = pubkey_of_signer(arg_matches, "token", wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", wallet_manager) .unwrap() .unwrap(); let n = *arg_matches.get_one::("n").unwrap(); @@ -54,7 +54,7 @@ pub(crate) async fn bench_process_command( command_close_accounts(config, signers, &token, n, &owner).await?; } Some(("deposit-into", arg_matches)) => { - let token = pubkey_of_signer(arg_matches, "token", wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", wallet_manager) .unwrap() .unwrap(); let n = *arg_matches.get_one::("n").unwrap(); @@ -62,14 +62,14 @@ pub(crate) async fn bench_process_command( let (owner_signer, owner) = config.signer_or_default(arg_matches, "owner", wallet_manager); signers.push(owner_signer); - let from = pubkey_of_signer(arg_matches, "from", wallet_manager).unwrap(); + let from = SignerSource::try_get_pubkey(arg_matches, "from", wallet_manager).unwrap(); command_deposit_into_or_withdraw_from( config, signers, &token, n, &owner, ui_amount, from, true, ) .await?; } Some(("withdraw-from", arg_matches)) => { - let token = pubkey_of_signer(arg_matches, "token", wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", wallet_manager) .unwrap() .unwrap(); let n = *arg_matches.get_one::("n").unwrap(); @@ -77,7 +77,7 @@ pub(crate) async fn bench_process_command( let (owner_signer, owner) = config.signer_or_default(arg_matches, "owner", wallet_manager); signers.push(owner_signer); - let to = pubkey_of_signer(arg_matches, "to", wallet_manager).unwrap(); + let to = SignerSource::try_get_pubkey(arg_matches, "to", wallet_manager).unwrap(); command_deposit_into_or_withdraw_from( config, signers, &token, n, &owner, ui_amount, to, false, ) diff --git a/token/cli/src/clap_app.rs b/token/cli/src/clap_app.rs index 4d64372ad03..4a040de9af0 100644 --- a/token/cli/src/clap_app.rs +++ b/token/cli/src/clap_app.rs @@ -1,6 +1,7 @@ #![allow(deprecated)] use { + crate::print_error_and_exit, clap::{ crate_description, crate_name, crate_version, App, AppSettings, Arg, ArgGroup, SubCommand, }, @@ -300,7 +301,7 @@ pub fn mint_address_arg<'a>() -> Arg<'a> { .long(MINT_ADDRESS_ARG.long) .takes_value(true) .value_name("MINT_ADDRESS") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .help(MINT_ADDRESS_ARG.help) } @@ -329,7 +330,7 @@ pub fn delegate_address_arg<'a>() -> Arg<'a> { .long(DELEGATE_ADDRESS_ARG.long) .takes_value(true) .value_name("DELEGATE_ADDRESS") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .help(DELEGATE_ADDRESS_ARG.help) } @@ -365,20 +366,12 @@ fn is_multisig_minimum_signers(string: &str) -> Result<(), String> { } } -fn is_valid_token_program_id(string: T) -> Result<(), String> -where - T: AsRef + fmt::Display, -{ - match is_pubkey(string.as_ref()) { - Ok(()) => { - let program_id = string.as_ref().parse::().unwrap(); - if VALID_TOKEN_PROGRAM_IDS.contains(&program_id) { - Ok(()) - } else { - Err(format!("Unrecognized token program id: {}", program_id)) - } - } - Err(e) => Err(e), +fn parse_token_program_id(arg: &str) -> Result { + let program_id = arg.parse::().unwrap_or_else(print_error_and_exit); + if VALID_TOKEN_PROGRAM_IDS.contains(&program_id) { + Ok(program_id) + } else { + Err(format!("Unrecognized token program id: {}", program_id)) } } @@ -462,7 +455,7 @@ impl BenchSubCommand for App<'_> { .about("Create multiple token accounts for benchmarking") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ADDRESS") .takes_value(true) .index(1) @@ -485,7 +478,7 @@ impl BenchSubCommand for App<'_> { .about("Close multiple token accounts used for benchmarking") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ADDRESS") .takes_value(true) .index(1) @@ -508,7 +501,7 @@ impl BenchSubCommand for App<'_> { .about("Deposit tokens into multiple accounts") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ADDRESS") .takes_value(true) .index(1) @@ -536,7 +529,7 @@ impl BenchSubCommand for App<'_> { .arg( Arg::with_name("from") .long("from") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("SOURCE_TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .help("The source token account address [default: associated token account for --owner]") @@ -548,7 +541,7 @@ impl BenchSubCommand for App<'_> { .about("Withdraw tokens from multiple accounts") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ADDRESS") .takes_value(true) .index(1) @@ -576,7 +569,7 @@ impl BenchSubCommand for App<'_> { .arg( Arg::with_name("to") .long("to") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("RECIPIENT_TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .help("The recipient token account address [default: associated token account for --owner]") @@ -638,7 +631,7 @@ pub fn app<'a>( .takes_value(true) .global(true) .conflicts_with("program_2022") - .validator(|s| is_valid_token_program_id(s)) + .value_parser(parse_token_program_id) .help("SPL Token program id"), ) .arg( @@ -701,7 +694,7 @@ pub fn app<'a>( .long("mint-authority") .alias("owner") .value_name("ADDRESS") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .takes_value(true) .help( "Specify the mint authority address. \ @@ -747,7 +740,7 @@ pub fn app<'a>( Arg::with_name("metadata_address") .long("metadata-address") .value_name("ADDRESS") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .takes_value(true) .conflicts_with("enable_metadata") .help( @@ -758,7 +751,7 @@ pub fn app<'a>( Arg::with_name("group_address") .long("group-address") .value_name("ADDRESS") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_pubkey().build()) .takes_value(true) .conflicts_with("enable_group") .help( @@ -769,7 +762,7 @@ pub fn app<'a>( Arg::with_name("member_address") .long("member-address") .value_name("ADDRESS") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_pubkey().build()) .takes_value(true) .conflicts_with("enable_member") .help( @@ -865,7 +858,7 @@ pub fn app<'a>( Arg::with_name("transfer_hook") .long("transfer-hook") .value_name("TRANSFER_HOOK_PROGRAM_ID") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .takes_value(true) .help("Enable the mint authority to set the transfer hook program for this mint"), ) @@ -899,7 +892,7 @@ pub fn app<'a>( .about("Set the interest rate for an interest-bearing token") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .required(true) @@ -929,7 +922,7 @@ pub fn app<'a>( .about("Set the transfer hook program id for a token") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .required(true) @@ -938,7 +931,7 @@ pub fn app<'a>( ) .arg( Arg::with_name("new_program_id") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("NEW_PROGRAM_ID") .takes_value(true) .required_unless("disable") @@ -967,7 +960,7 @@ pub fn app<'a>( .about("Initialize metadata extension on a token mint") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .required(true) @@ -1015,7 +1008,7 @@ pub fn app<'a>( Arg::with_name("update_authority") .long("update-authority") .value_name("ADDRESS") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .takes_value(true) .help( "Specify the update authority address. \ @@ -1028,7 +1021,7 @@ pub fn app<'a>( .about("Update metadata on a token mint that has the extension") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .required(true) @@ -1075,7 +1068,7 @@ pub fn app<'a>( .about("Initialize group extension on a token mint") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .required(true) @@ -1108,7 +1101,7 @@ pub fn app<'a>( Arg::with_name("update_authority") .long("update-authority") .value_name("ADDRESS") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .takes_value(true) .help( "Specify the update authority address. \ @@ -1121,7 +1114,7 @@ pub fn app<'a>( .about("Updates the maximum number of members for a group.") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .required(true) @@ -1154,7 +1147,7 @@ pub fn app<'a>( .about("Initialize group member extension on a token mint") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .required(true) @@ -1163,7 +1156,7 @@ pub fn app<'a>( ) .arg( Arg::with_name("group_token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("GROUP_TOKEN_ADDRESS") .takes_value(true) .required(true) @@ -1201,7 +1194,7 @@ pub fn app<'a>( .about("Create a new token account") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -1246,7 +1239,7 @@ pub fn app<'a>( .arg( Arg::with_name("multisig_member") .value_name("MULTISIG_MEMBER_PUBKEY") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .takes_value(true) .index(2) .required(true) @@ -1273,7 +1266,7 @@ pub fn app<'a>( .about("Authorize a new signing keypair to a token or token account") .arg( Arg::with_name("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ADDRESS") .takes_value(true) .index(1) @@ -1294,7 +1287,7 @@ pub fn app<'a>( ) .arg( Arg::with_name("new_authority") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("AUTHORITY_ADDRESS") .takes_value(true) .index(3) @@ -1335,7 +1328,7 @@ pub fn app<'a>( .about("Transfer tokens between accounts") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -1353,7 +1346,7 @@ pub fn app<'a>( ) .arg( Arg::with_name("recipient") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("RECIPIENT_WALLET_ADDRESS or RECIPIENT_TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(3) @@ -1364,7 +1357,7 @@ pub fn app<'a>( ) .arg( Arg::with_name("from") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("SENDER_TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .long("from") @@ -1465,7 +1458,7 @@ pub fn app<'a>( .about("Burn tokens from an account") .arg( Arg::with_name("account") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -1499,7 +1492,7 @@ pub fn app<'a>( .about("Mint new tokens") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -1517,7 +1510,7 @@ pub fn app<'a>( ) .arg( Arg::with_name("recipient") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("RECIPIENT_TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .conflicts_with("recipient_owner") @@ -1528,7 +1521,7 @@ pub fn app<'a>( .arg( Arg::with_name("recipient_owner") .long("recipient-owner") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("RECIPIENT_WALLET_ADDRESS") .takes_value(true) .conflicts_with("recipient") @@ -1558,7 +1551,7 @@ pub fn app<'a>( .about("Freeze a token account") .arg( Arg::with_name("account") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -1588,7 +1581,7 @@ pub fn app<'a>( .about("Thaw a token account") .arg( Arg::with_name("account") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -1661,7 +1654,7 @@ pub fn app<'a>( .about("Unwrap a SOL token account") .arg( Arg::with_name("account") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -1691,7 +1684,7 @@ pub fn app<'a>( .about("Approve a delegate for a token account") .arg( Arg::with_name("account") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -1709,7 +1702,7 @@ pub fn app<'a>( ) .arg( Arg::with_name("delegate") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("DELEGATE_TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(3) @@ -1729,7 +1722,7 @@ pub fn app<'a>( .about("Revoke a delegate's authority") .arg( Arg::with_name("account") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -1748,7 +1741,7 @@ pub fn app<'a>( .about("Close a token account") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -1780,7 +1773,7 @@ pub fn app<'a>( .arg( Arg::with_name("address") .long("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .conflicts_with("token") @@ -1797,7 +1790,7 @@ pub fn app<'a>( .about("Close a token mint") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -1858,7 +1851,7 @@ pub fn app<'a>( .about("Get token supply") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -1871,7 +1864,7 @@ pub fn app<'a>( .about("List all token accounts by owner") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -1912,7 +1905,7 @@ pub fn app<'a>( .about("Get wallet address") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .long("token") @@ -1956,7 +1949,7 @@ pub fn app<'a>( ) .arg( Arg::with_name("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .long("address") @@ -1970,7 +1963,7 @@ pub fn app<'a>( .setting(AppSettings::Hidden) .arg( Arg::with_name("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("MULTISIG_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -1983,7 +1976,7 @@ pub fn app<'a>( .about("Query details of an SPL Token mint, account, or multisig by address") .arg( Arg::with_name("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ADDRESS") .takes_value(true) .index(1) @@ -2015,7 +2008,7 @@ pub fn app<'a>( ) .arg( Arg::with_name("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .long("address") @@ -2100,7 +2093,7 @@ pub fn app<'a>( .about("Updates default account state for the mint. Requires the default account state extension.") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2138,7 +2131,7 @@ pub fn app<'a>( .about("Updates metadata pointer address for the mint. Requires the metadata pointer extension.") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2148,7 +2141,7 @@ pub fn app<'a>( .arg( Arg::with_name("metadata_address") .index(2) - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_pubkey().build()) .value_name("METADATA_ADDRESS") .takes_value(true) .required_unless("disable") @@ -2181,7 +2174,7 @@ pub fn app<'a>( .about("Updates group pointer address for the mint. Requires the group pointer extension.") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2191,7 +2184,7 @@ pub fn app<'a>( .arg( Arg::with_name("group_address") .index(2) - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_pubkey().build()) .value_name("GROUP_ADDRESS") .takes_value(true) .required_unless("disable") @@ -2224,7 +2217,7 @@ pub fn app<'a>( .about("Updates group member pointer address for the mint. Requires the group member pointer extension.") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2234,7 +2227,7 @@ pub fn app<'a>( .arg( Arg::with_name("member_address") .index(2) - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_pubkey().build()) .value_name("MEMBER_ADDRESS") .takes_value(true) .required_unless("disable") @@ -2267,7 +2260,7 @@ pub fn app<'a>( .about("Withdraw withheld transfer fee tokens from mint and / or account(s)") .arg( Arg::with_name("account") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .index(1) @@ -2276,7 +2269,7 @@ pub fn app<'a>( ) .arg( Arg::with_name("source") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("ACCOUNT_ADDRESS") .takes_value(true) .multiple(true) @@ -2317,7 +2310,7 @@ pub fn app<'a>( .about("Set the transfer fee for a token with a configured transfer fee") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .required(true) @@ -2379,7 +2372,7 @@ pub fn app<'a>( .about("Update confidential transfer configuration for a token") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2439,7 +2432,7 @@ pub fn app<'a>( .about("Configure confidential transfers for token account") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2449,7 +2442,7 @@ pub fn app<'a>( .arg( Arg::with_name("address") .long("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .conflicts_with("token") @@ -2480,7 +2473,7 @@ pub fn app<'a>( for the first time, use `configure-confidential-transfer-account` instead.") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2490,7 +2483,7 @@ pub fn app<'a>( .arg( Arg::with_name("address") .long("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .conflicts_with("token") @@ -2508,7 +2501,7 @@ pub fn app<'a>( .about("Disable confidential transfers for token account") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2518,7 +2511,7 @@ pub fn app<'a>( .arg( Arg::with_name("address") .long("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .conflicts_with("token") @@ -2536,7 +2529,7 @@ pub fn app<'a>( .about("Enable non-confidential transfers for token account.") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2546,7 +2539,7 @@ pub fn app<'a>( .arg( Arg::with_name("address") .long("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .conflicts_with("token") @@ -2564,7 +2557,7 @@ pub fn app<'a>( .about("Disable non-confidential transfers for token account") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2574,7 +2567,7 @@ pub fn app<'a>( .arg( Arg::with_name("address") .long("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .conflicts_with("token") @@ -2592,7 +2585,7 @@ pub fn app<'a>( .about("Deposit amounts for confidential transfers") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2611,7 +2604,7 @@ pub fn app<'a>( .arg( Arg::with_name("address") .long("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .help("The address of the token account to configure confidential transfers for \ @@ -2629,7 +2622,7 @@ pub fn app<'a>( .about("Withdraw amounts for confidential transfers") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2648,7 +2641,7 @@ pub fn app<'a>( .arg( Arg::with_name("address") .long("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .help("The address of the token account to configure confidential transfers for \ @@ -2666,7 +2659,7 @@ pub fn app<'a>( .about("Collect confidential tokens from pending to available balance") .arg( Arg::with_name("token") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_MINT_ADDRESS") .takes_value(true) .index(1) @@ -2676,7 +2669,7 @@ pub fn app<'a>( .arg( Arg::with_name("address") .long("address") - .validator(|s| is_valid_pubkey(s)) + .value_parser(SignerSourceParserBuilder::default().allow_all().build()) .value_name("TOKEN_ACCOUNT_ADDRESS") .takes_value(true) .help("The address of the token account to configure confidential transfers for \ diff --git a/token/cli/src/command.rs b/token/cli/src/command.rs index 7170c1734af..27f7d41983c 100644 --- a/token/cli/src/command.rs +++ b/token/cli/src/command.rs @@ -18,7 +18,9 @@ use { UiAccountData, }, solana_clap_v3_utils::{ - input_parsers::{pubkey_of_signer, pubkeys_of_multiple_signers, Amount}, + input_parsers::{ + pubkey_of_signer, pubkeys_of_multiple_signers, signer::SignerSource, Amount, + }, keypair::signer_from_path, }, solana_cli_output::{ @@ -3562,9 +3564,15 @@ pub async fn process_command<'a>( config.pubkey_or_default(arg_matches, "mint_authority", &mut wallet_manager)?; let memo = value_t!(arg_matches, "memo", String).ok(); let rate_bps = value_t!(arg_matches, "interest_rate", i16).ok(); - let metadata_address = value_t!(arg_matches, "metadata_address", Pubkey).ok(); - let group_address = value_t!(arg_matches, "group_address", Pubkey).ok(); - let member_address = value_t!(arg_matches, "member_address", Pubkey).ok(); + let metadata_address = + SignerSource::try_get_pubkey(arg_matches, "metadata_address", &mut wallet_manager) + .unwrap(); + let group_address = + SignerSource::try_get_pubkey(arg_matches, "group_address", &mut wallet_manager) + .unwrap(); + let member_address = + SignerSource::try_get_pubkey(arg_matches, "member_address", &mut wallet_manager) + .unwrap(); let transfer_fee = arg_matches.values_of("transfer_fee").map(|mut v| { println_display(config,"transfer-fee has been deprecated and will be removed in a future release. Please specify --transfer-fee-basis-points and --transfer-fee-maximum-fee with a UI amount".to_string()); @@ -3601,7 +3609,8 @@ pub async fn process_command<'a>( _ => unreachable!(), }); let transfer_hook_program_id = - pubkey_of_signer(arg_matches, "transfer_hook", &mut wallet_manager).unwrap(); + SignerSource::try_get_pubkey(arg_matches, "transfer_hook", &mut wallet_manager) + .unwrap(); let confidential_transfer_auto_approve = arg_matches .value_of("enable_confidential_transfers") @@ -3633,9 +3642,10 @@ pub async fn process_command<'a>( .await } (CommandName::SetInterestRate, arg_matches) => { - let token_pubkey = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) - .unwrap() - .unwrap(); + let token_pubkey = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) + .unwrap() + .unwrap(); let rate_bps = value_t_or_exit!(arg_matches, "rate", i16); let (rate_authority_signer, rate_authority_pubkey) = config.signer_or_default(arg_matches, "rate_authority", &mut wallet_manager); @@ -3651,11 +3661,13 @@ pub async fn process_command<'a>( .await } (CommandName::SetTransferHook, arg_matches) => { - let token_pubkey = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) - .unwrap() - .unwrap(); + let token_pubkey = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) + .unwrap() + .unwrap(); let new_program_id = - pubkey_of_signer(arg_matches, "new_program_id", &mut wallet_manager).unwrap(); + SignerSource::try_get_pubkey(arg_matches, "new_program_id", &mut wallet_manager) + .unwrap(); let (authority_signer, authority_pubkey) = config.signer_or_default(arg_matches, "authority", &mut wallet_manager); let bulk_signers = vec![authority_signer]; @@ -3670,9 +3682,10 @@ pub async fn process_command<'a>( .await } (CommandName::InitializeMetadata, arg_matches) => { - let token_pubkey = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) - .unwrap() - .unwrap(); + let token_pubkey = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) + .unwrap() + .unwrap(); let name = arg_matches.value_of("name").unwrap().to_string(); let symbol = arg_matches.value_of("symbol").unwrap().to_string(); let uri = arg_matches.value_of("uri").unwrap().to_string(); @@ -3695,9 +3708,10 @@ pub async fn process_command<'a>( .await } (CommandName::UpdateMetadata, arg_matches) => { - let token_pubkey = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) - .unwrap() - .unwrap(); + let token_pubkey = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) + .unwrap() + .unwrap(); let (authority_signer, authority) = config.signer_or_default(arg_matches, "authority", &mut wallet_manager); let field = arg_matches.value_of("field").unwrap(); @@ -3725,9 +3739,10 @@ pub async fn process_command<'a>( .await } (CommandName::InitializeGroup, arg_matches) => { - let token_pubkey = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) - .unwrap() - .unwrap(); + let token_pubkey = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) + .unwrap() + .unwrap(); let max_size = *arg_matches.get_one::("max_size").unwrap(); let (mint_authority_signer, mint_authority) = config.signer_or_default(arg_matches, "mint_authority", &mut wallet_manager); @@ -3746,9 +3761,10 @@ pub async fn process_command<'a>( .await } (CommandName::UpdateGroupMaxSize, arg_matches) => { - let token_pubkey = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) - .unwrap() - .unwrap(); + let token_pubkey = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) + .unwrap() + .unwrap(); let new_max_size = *arg_matches.get_one::("new_max_size").unwrap(); let (update_authority_signer, update_authority) = config.signer_or_default(arg_matches, "update_authority", &mut wallet_manager); @@ -3764,11 +3780,12 @@ pub async fn process_command<'a>( .await } (CommandName::InitializeMember, arg_matches) => { - let member_token_pubkey = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) - .unwrap() - .unwrap(); + let member_token_pubkey = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) + .unwrap() + .unwrap(); let group_token_pubkey = - pubkey_of_signer(arg_matches, "group_token", &mut wallet_manager) + SignerSource::try_get_pubkey(arg_matches, "group_token", &mut wallet_manager) .unwrap() .unwrap(); let (mint_authority_signer, mint_authority) = @@ -3792,7 +3809,7 @@ pub async fn process_command<'a>( .await } (CommandName::CreateAccount, arg_matches) => { - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) .unwrap() .unwrap(); @@ -3821,9 +3838,9 @@ pub async fn process_command<'a>( .map(|v: &String| v.parse::().unwrap()) .unwrap(); let multisig_members = - pubkeys_of_multiple_signers(arg_matches, "multisig_member", &mut wallet_manager) + SignerSource::try_get_pubkeys(arg_matches, "multisig_member", &mut wallet_manager) .unwrap_or_else(print_error_and_exit) - .unwrap(); + .unwrap_or_default(); if minimum_signers as usize > multisig_members.len() { eprintln!( "error: MINIMUM_SIGNERS cannot be greater than the number \ @@ -3838,7 +3855,7 @@ pub async fn process_command<'a>( command_create_multisig(config, signer, minimum_signers, multisig_members).await } (CommandName::Authorize, arg_matches) => { - let address = pubkey_of_signer(arg_matches, "address", &mut wallet_manager) + let address = SignerSource::try_get_pubkey(arg_matches, "address", &mut wallet_manager) .unwrap() .unwrap(); let authority_type = arg_matches.value_of("authority_type").unwrap(); @@ -3851,7 +3868,8 @@ pub async fn process_command<'a>( } let new_authority = - pubkey_of_signer(arg_matches, "new_authority", &mut wallet_manager).unwrap(); + SignerSource::try_get_pubkey(arg_matches, "new_authority", &mut wallet_manager) + .unwrap(); let force_authorize = arg_matches.is_present("force"); command_authorize( config, @@ -3865,14 +3883,16 @@ pub async fn process_command<'a>( .await } (CommandName::Transfer, arg_matches) => { - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) .unwrap() .unwrap(); let amount = *arg_matches.get_one::("amount").unwrap(); - let recipient = pubkey_of_signer(arg_matches, "recipient", &mut wallet_manager) - .unwrap() - .unwrap(); - let sender = pubkey_of_signer(arg_matches, "from", &mut wallet_manager).unwrap(); + let recipient = + SignerSource::try_get_pubkey(arg_matches, "recipient", &mut wallet_manager) + .unwrap() + .unwrap(); + let sender = + SignerSource::try_get_pubkey(arg_matches, "from", &mut wallet_manager).unwrap(); let (owner_signer, owner) = config.signer_or_default(arg_matches, "owner", &mut wallet_manager); @@ -3946,7 +3966,7 @@ pub async fn process_command<'a>( .await } (CommandName::Burn, arg_matches) => { - let account = pubkey_of_signer(arg_matches, "account", &mut wallet_manager) + let account = SignerSource::try_get_pubkey(arg_matches, "account", &mut wallet_manager) .unwrap() .unwrap(); @@ -3984,18 +4004,19 @@ pub async fn process_command<'a>( push_signer_with_dedup(mint_authority_signer, &mut bulk_signers); } - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) .unwrap() .unwrap(); let amount = *arg_matches.get_one::("amount").unwrap(); let mint_decimals = arg_matches.get_one::(MINT_DECIMALS_ARG.name).copied(); let mint_info = config.get_mint_info(&token, mint_decimals).await?; let recipient = if let Some(address) = - pubkey_of_signer(arg_matches, "recipient", &mut wallet_manager).unwrap() + SignerSource::try_get_pubkey(arg_matches, "recipient", &mut wallet_manager).unwrap() { address } else if let Some(address) = - pubkey_of_signer(arg_matches, "recipient_owner", &mut wallet_manager).unwrap() + SignerSource::try_get_pubkey(arg_matches, "recipient_owner", &mut wallet_manager) + .unwrap() { get_associated_token_address_with_program_id(&address, &token, &config.program_id) } else { @@ -4029,7 +4050,7 @@ pub async fn process_command<'a>( push_signer_with_dedup(freeze_authority_signer, &mut bulk_signers); } - let account = pubkey_of_signer(arg_matches, "account", &mut wallet_manager) + let account = SignerSource::try_get_pubkey(arg_matches, "account", &mut wallet_manager) .unwrap() .unwrap(); let mint_address = @@ -4050,7 +4071,7 @@ pub async fn process_command<'a>( push_signer_with_dedup(freeze_authority_signer, &mut bulk_signers); } - let account = pubkey_of_signer(arg_matches, "account", &mut wallet_manager) + let account = SignerSource::try_get_pubkey(arg_matches, "account", &mut wallet_manager) .unwrap() .unwrap(); let mint_address = @@ -4094,7 +4115,8 @@ pub async fn process_command<'a>( config.signer_or_default(arg_matches, "wallet_keypair", &mut wallet_manager); push_signer_with_dedup(wallet_signer, &mut bulk_signers); - let account = pubkey_of_signer(arg_matches, "account", &mut wallet_manager).unwrap(); + let account = + SignerSource::try_get_pubkey(arg_matches, "account", &mut wallet_manager).unwrap(); command_unwrap(config, wallet_address, account, bulk_signers).await } (CommandName::Approve, arg_matches) => { @@ -4104,15 +4126,20 @@ pub async fn process_command<'a>( push_signer_with_dedup(owner_signer, &mut bulk_signers); } - let account = pubkey_of_signer(arg_matches, "account", &mut wallet_manager) + let account = SignerSource::try_get_pubkey(arg_matches, "account", &mut wallet_manager) .unwrap() .unwrap(); let amount = *arg_matches.get_one::("amount").unwrap(); - let delegate = pubkey_of_signer(arg_matches, "delegate", &mut wallet_manager) - .unwrap() - .unwrap(); - let mint_address = - pubkey_of_signer(arg_matches, MINT_ADDRESS_ARG.name, &mut wallet_manager).unwrap(); + let delegate = + SignerSource::try_get_pubkey(arg_matches, "delegate", &mut wallet_manager) + .unwrap() + .unwrap(); + let mint_address = SignerSource::try_get_pubkey( + arg_matches, + MINT_ADDRESS_ARG.name, + &mut wallet_manager, + ) + .unwrap(); let mint_decimals = arg_matches .get_one(MINT_DECIMALS_ARG.name) .map(|v: &String| v.parse::().unwrap()); @@ -4137,7 +4164,7 @@ pub async fn process_command<'a>( push_signer_with_dedup(owner_signer, &mut bulk_signers); } - let account = pubkey_of_signer(arg_matches, "account", &mut wallet_manager) + let account = SignerSource::try_get_pubkey(arg_matches, "account", &mut wallet_manager) .unwrap() .unwrap(); let delegate_address = @@ -4167,7 +4194,7 @@ pub async fn process_command<'a>( command_close(config, address, close_authority, recipient, bulk_signers).await } (CommandName::CloseMint, arg_matches) => { - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) .unwrap() .unwrap(); let (close_authority_signer, close_authority) = @@ -4187,13 +4214,14 @@ pub async fn process_command<'a>( command_balance(config, address).await } (CommandName::Supply, arg_matches) => { - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) .unwrap() .unwrap(); command_supply(config, token).await } (CommandName::Accounts, arg_matches) => { - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager).unwrap(); + let token = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager).unwrap(); let owner = config.pubkey_or_default(arg_matches, "owner", &mut wallet_manager)?; let filter = if arg_matches.is_present("delegated") { AccountFilter::Delegated @@ -4213,7 +4241,8 @@ pub async fn process_command<'a>( .await } (CommandName::Address, arg_matches) => { - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager).unwrap(); + let token = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager).unwrap(); let owner = config.pubkey_or_default(arg_matches, "owner", &mut wallet_manager)?; command_address(config, token, owner).await } @@ -4224,13 +4253,13 @@ pub async fn process_command<'a>( command_display(config, address).await } (CommandName::MultisigInfo, arg_matches) => { - let address = pubkey_of_signer(arg_matches, "address", &mut wallet_manager) + let address = SignerSource::try_get_pubkey(arg_matches, "address", &mut wallet_manager) .unwrap() .unwrap(); command_display(config, address).await } (CommandName::Display, arg_matches) => { - let address = pubkey_of_signer(arg_matches, "address", &mut wallet_manager) + let address = SignerSource::try_get_pubkey(arg_matches, "address", &mut wallet_manager) .unwrap() .unwrap(); command_display(config, address).await @@ -4321,7 +4350,7 @@ pub async fn process_command<'a>( } (CommandName::UpdateDefaultAccountState, arg_matches) => { // Since account is required argument it will always be present - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) .unwrap() .unwrap(); let (freeze_authority_signer, freeze_authority) = @@ -4346,7 +4375,7 @@ pub async fn process_command<'a>( } (CommandName::UpdateMetadataAddress, arg_matches) => { // Since account is required argument it will always be present - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) .unwrap() .unwrap(); @@ -4355,7 +4384,9 @@ pub async fn process_command<'a>( if config.multisigner_pubkeys.is_empty() { push_signer_with_dedup(authority_signer, &mut bulk_signers); } - let metadata_address = value_t!(arg_matches, "metadata_address", Pubkey).ok(); + let metadata_address = + SignerSource::try_get_pubkey(arg_matches, "metadata_address", &mut wallet_manager) + .unwrap(); command_update_pointer_address( config, @@ -4369,7 +4400,7 @@ pub async fn process_command<'a>( } (CommandName::UpdateGroupAddress, arg_matches) => { // Since account is required argument it will always be present - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) .unwrap() .unwrap(); @@ -4378,7 +4409,9 @@ pub async fn process_command<'a>( if config.multisigner_pubkeys.is_empty() { push_signer_with_dedup(authority_signer, &mut bulk_signers); } - let group_address = value_t!(arg_matches, "group_address", Pubkey).ok(); + let group_address = + SignerSource::try_get_pubkey(arg_matches, "group_address", &mut wallet_manager) + .unwrap(); command_update_pointer_address( config, @@ -4392,7 +4425,7 @@ pub async fn process_command<'a>( } (CommandName::UpdateMemberAddress, arg_matches) => { // Since account is required argument it will always be present - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) .unwrap() .unwrap(); @@ -4401,7 +4434,9 @@ pub async fn process_command<'a>( if config.multisigner_pubkeys.is_empty() { push_signer_with_dedup(authority_signer, &mut bulk_signers); } - let member_address = value_t!(arg_matches, "member_address", Pubkey).ok(); + let member_address = + SignerSource::try_get_pubkey(arg_matches, "member_address", &mut wallet_manager) + .unwrap(); command_update_pointer_address( config, @@ -4424,15 +4459,14 @@ pub async fn process_command<'a>( } // Since destination is required it will always be present let destination_token_account = - pubkey_of_signer(arg_matches, "account", &mut wallet_manager) + SignerSource::try_get_pubkey(arg_matches, "account", &mut wallet_manager) .unwrap() .unwrap(); let include_mint = arg_matches.is_present("include_mint"); - let source_accounts = arg_matches - .values_of("source") - .unwrap_or_default() - .map(|s| Pubkey::from_str(s).unwrap_or_else(print_error_and_exit)) - .collect::>(); + let source_accounts = + SignerSource::try_get_pubkeys(arg_matches, "source", &mut wallet_manager) + .unwrap() + .unwrap_or_default(); command_withdraw_withheld_tokens( config, destination_token_account, @@ -4444,9 +4478,10 @@ pub async fn process_command<'a>( .await } (CommandName::SetTransferFee, arg_matches) => { - let token_pubkey = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) - .unwrap() - .unwrap(); + let token_pubkey = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) + .unwrap() + .unwrap(); let transfer_fee_basis_points = value_t_or_exit!(arg_matches, "transfer_fee_basis_points", u16); let maximum_fee = *arg_matches.get_one::("maximum_fee").unwrap(); @@ -4481,9 +4516,10 @@ pub async fn process_command<'a>( .await } (CommandName::UpdateConfidentialTransferSettings, arg_matches) => { - let token_pubkey = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) - .unwrap() - .unwrap(); + let token_pubkey = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) + .unwrap() + .unwrap(); let auto_approve = arg_matches.value_of("approve_policy").map(|b| b == "auto"); @@ -4511,12 +4547,14 @@ pub async fn process_command<'a>( .await } (CommandName::ConfigureConfidentialTransferAccount, arg_matches) => { - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager).unwrap(); + let token = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager).unwrap(); let (owner_signer, owner) = config.signer_or_default(arg_matches, "owner", &mut wallet_manager); - let account = pubkey_of_signer(arg_matches, "address", &mut wallet_manager).unwrap(); + let account = + SignerSource::try_get_pubkey(arg_matches, "address", &mut wallet_manager).unwrap(); // Deriving ElGamal and AES key from signer. Custom ElGamal and AES keys will be // supported in the future once upgrading to clap-v3. @@ -4557,12 +4595,14 @@ pub async fn process_command<'a>( | (c @ CommandName::DisableConfidentialCredits, arg_matches) | (c @ CommandName::EnableNonConfidentialCredits, arg_matches) | (c @ CommandName::DisableNonConfidentialCredits, arg_matches) => { - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager).unwrap(); + let token = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager).unwrap(); let (owner_signer, owner) = config.signer_or_default(arg_matches, "owner", &mut wallet_manager); - let account = pubkey_of_signer(arg_matches, "address", &mut wallet_manager).unwrap(); + let account = + SignerSource::try_get_pubkey(arg_matches, "address", &mut wallet_manager).unwrap(); if config.multisigner_pubkeys.is_empty() { push_signer_with_dedup(owner_signer, &mut bulk_signers); @@ -4589,11 +4629,12 @@ pub async fn process_command<'a>( } (c @ CommandName::DepositConfidentialTokens, arg_matches) | (c @ CommandName::WithdrawConfidentialTokens, arg_matches) => { - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager) + let token = SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager) .unwrap() .unwrap(); let amount = *arg_matches.get_one::("amount").unwrap(); - let account = pubkey_of_signer(arg_matches, "address", &mut wallet_manager).unwrap(); + let account = + SignerSource::try_get_pubkey(arg_matches, "address", &mut wallet_manager).unwrap(); let (owner_signer, owner) = config.signer_or_default(arg_matches, "owner", &mut wallet_manager); @@ -4641,12 +4682,14 @@ pub async fn process_command<'a>( .await } (CommandName::ApplyPendingBalance, arg_matches) => { - let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager).unwrap(); + let token = + SignerSource::try_get_pubkey(arg_matches, "token", &mut wallet_manager).unwrap(); let (owner_signer, owner) = config.signer_or_default(arg_matches, "owner", &mut wallet_manager); - let account = pubkey_of_signer(arg_matches, "address", &mut wallet_manager).unwrap(); + let account = + SignerSource::try_get_pubkey(arg_matches, "address", &mut wallet_manager).unwrap(); // Deriving ElGamal and AES key from signer. Custom ElGamal and AES keys will be // supported in the future once upgrading to clap-v3. diff --git a/token/cli/src/config.rs b/token/cli/src/config.rs index 65c20dd5f76..72be7f30495 100644 --- a/token/cli/src/config.rs +++ b/token/cli/src/config.rs @@ -281,19 +281,17 @@ impl<'a> Config<'a> { .try_contains_id(DUMP_TRANSACTION_MESSAGE.name) .unwrap_or(false); - let pubkey_from_matches = |name| { - matches - .try_get_one::(name) + let mut pubkey_from_matches = |name| { + SignerSource::try_get_pubkey(matches, name, wallet_manager) .ok() .flatten() - .and_then(|pubkey| Pubkey::from_str(pubkey).ok()) }; let default_program_id = spl_token::id(); let (program_id, restrict_to_program_id) = if matches.is_present("program_2022") { (spl_token_2022::id(), true) - } else if let Some(program_id) = pubkey_from_matches("program_id") { - (program_id, true) + } else if let Some(program_id) = matches.get_one::("program_id") { + (*program_id, true) } else if !sign_only { if let Some(address) = pubkey_from_matches("token") .or_else(|| pubkey_from_matches("account")) @@ -424,8 +422,9 @@ impl<'a> Config<'a> { wallet_manager: &mut Option>, token: Option, ) -> Result { - if let Some(address) = pubkey_of_signer(arg_matches, override_name, wallet_manager) - .map_err(|e| -> Error { e.to_string().into() })? + if let Some(address) = + SignerSource::try_get_pubkey(arg_matches, override_name, wallet_manager) + .map_err(|e| -> Error { e.to_string().into() })? { return Ok(address); } From 1210f98be7be37924efd43bec891569465a0c109 Mon Sep 17 00:00:00 2001 From: samkim-crypto Date: Fri, 22 Nov 2024 11:28:56 +0900 Subject: [PATCH 5/7] clean up transfer hook account validator and parser --- token/cli/src/clap_app.rs | 53 +++++++++++++++++++-------------------- token/cli/src/command.rs | 12 +++++---- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/token/cli/src/clap_app.rs b/token/cli/src/clap_app.rs index 4a040de9af0..2a513812367 100644 --- a/token/cli/src/clap_app.rs +++ b/token/cli/src/clap_app.rs @@ -188,38 +188,37 @@ impl fmt::Display for AccountMetaRole { write!(f, "{:?}", self) } } -pub fn parse_transfer_hook_account(string: T) -> Result -where - T: AsRef + fmt::Display, -{ - match string.as_ref().split(':').collect::>().as_slice() { - [address, role] => { - let address = Pubkey::from_str(address).map_err(|e| format!("{e}"))?; - let meta = match AccountMetaRole::from_str(role).map_err(|e| format!("{e}"))? { - AccountMetaRole::Readonly => AccountMeta::new_readonly(address, false), - AccountMetaRole::Writable => AccountMeta::new(address, false), - AccountMetaRole::ReadonlySigner => AccountMeta::new_readonly(address, true), - AccountMetaRole::WritableSigner => AccountMeta::new(address, true), - }; - Ok(meta) + +#[derive(Clone, Copy)] +pub(crate) struct TransferHookAccount { + address: Pubkey, + role: AccountMetaRole, +} +impl FromStr for TransferHookAccount { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.split(':').collect::>().as_slice() { + [address, role] => { + let address = Pubkey::from_str(address).map_err(|e| format!("{e}"))?; + let role = AccountMetaRole::from_str(role).map_err(|e| format!("{e}"))?; + Ok(Self { address, role }) + } + _ => Err("Transfer hook account must be present as
:".to_string()), } - _ => Err("Transfer hook account must be present as
:".to_string()), } } -fn validate_transfer_hook_account(string: T) -> Result<(), String> -where - T: AsRef + fmt::Display, -{ - match string.as_ref().split(':').collect::>().as_slice() { - [address, role] => { - is_valid_pubkey(address)?; - AccountMetaRole::from_str(role) - .map(|_| ()) - .map_err(|e| format!("{e}")) +impl TransferHookAccount { + pub(crate) fn create_account_meta(&self) -> AccountMeta { + match self.role { + AccountMetaRole::Readonly => AccountMeta::new_readonly(self.address, false), + AccountMetaRole::Writable => AccountMeta::new(self.address, false), + AccountMetaRole::ReadonlySigner => AccountMeta::new_readonly(self.address, true), + AccountMetaRole::WritableSigner => AccountMeta::new(self.address, true), } - _ => Err("Transfer hook account must be present as
:".to_string()), } } + #[derive(Debug, Clone, PartialEq, EnumIter, EnumString, IntoStaticStr)] #[strum(serialize_all = "kebab-case")] pub enum CliAuthorityType { @@ -1429,7 +1428,7 @@ pub fn app<'a>( .arg( Arg::with_name("transfer_hook_account") .long("transfer-hook-account") - .validator(|s| validate_transfer_hook_account(s)) + .value_parser(clap::value_parser!(TransferHookAccount)) .value_name("PUBKEY:ROLE") .takes_value(true) .multiple(true) diff --git a/token/cli/src/command.rs b/token/cli/src/command.rs index 27f7d41983c..ab141b81fa5 100644 --- a/token/cli/src/command.rs +++ b/token/cli/src/command.rs @@ -3937,11 +3937,13 @@ pub async fn process_command<'a>( let use_unchecked_instruction = arg_matches.is_present("use_unchecked_instruction"); let expected_fee = arg_matches.get_one::("expected_fee").copied(); let memo = value_t!(arg_matches, "memo", String).ok(); - let transfer_hook_accounts = arg_matches.values_of("transfer_hook_account").map(|v| { - v.into_iter() - .map(|s| parse_transfer_hook_account(s).unwrap()) - .collect::>() - }); + let transfer_hook_accounts = arg_matches + .get_many::("transfer_hook_account") + .map(|v| { + v.into_iter() + .map(|account| account.create_account_meta()) + .collect::>() + }); command_transfer( config, From 92d4006fd99e140ed81f4c4c6335847971814227 Mon Sep 17 00:00:00 2001 From: samkim-crypto Date: Fri, 22 Nov 2024 11:29:07 +0900 Subject: [PATCH 6/7] remove unnecessary imports --- token/cli/src/bench.rs | 2 +- token/cli/src/clap_app.rs | 2 +- token/cli/src/command.rs | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/token/cli/src/bench.rs b/token/cli/src/bench.rs index bd91f0d3e60..54328cc1e8d 100644 --- a/token/cli/src/bench.rs +++ b/token/cli/src/bench.rs @@ -2,7 +2,7 @@ use { crate::{clap_app::Error, command::CommandResult, config::Config}, clap::ArgMatches, - solana_clap_v3_utils::input_parsers::{pubkey_of_signer, signer::SignerSource, Amount}, + solana_clap_v3_utils::input_parsers::{signer::SignerSource, Amount}, solana_client::{ nonblocking::rpc_client::RpcClient, rpc_client::RpcClient as BlockingRpcClient, tpu_client::TpuClient, tpu_client::TpuClientConfig, diff --git a/token/cli/src/clap_app.rs b/token/cli/src/clap_app.rs index 2a513812367..ff7abb32a7a 100644 --- a/token/cli/src/clap_app.rs +++ b/token/cli/src/clap_app.rs @@ -8,7 +8,7 @@ use { solana_clap_v3_utils::{ fee_payer::fee_payer_arg, input_parsers::{signer::SignerSourceParserBuilder, Amount}, - input_validators::{is_pubkey, is_url_or_moniker, is_valid_pubkey, is_valid_signer}, + input_validators::{is_url_or_moniker, is_valid_signer}, memo::memo_arg, nonce::*, offline::{self, *}, diff --git a/token/cli/src/command.rs b/token/cli/src/command.rs index ab141b81fa5..670a76d66c6 100644 --- a/token/cli/src/command.rs +++ b/token/cli/src/command.rs @@ -18,9 +18,7 @@ use { UiAccountData, }, solana_clap_v3_utils::{ - input_parsers::{ - pubkey_of_signer, pubkeys_of_multiple_signers, signer::SignerSource, Amount, - }, + input_parsers::{pubkey_of_signer, signer::SignerSource, Amount}, keypair::signer_from_path, }, solana_cli_output::{ From ae6082da60c21f7f6a8cc79ad0a24ff5081df7a5 Mon Sep 17 00:00:00 2001 From: samkim-crypto Date: Fri, 22 Nov 2024 12:27:46 +0900 Subject: [PATCH 7/7] only parse default keypair source when necessary --- token/cli/src/config.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/token/cli/src/config.rs b/token/cli/src/config.rs index 72be7f30495..d8e6ae57d08 100644 --- a/token/cli/src/config.rs +++ b/token/cli/src/config.rs @@ -186,17 +186,15 @@ impl<'a> Config<'a> { allow_null_signer: !multisigner_pubkeys.is_empty(), }; - let default_keypair = cli_config.keypair_path.clone(); - let default_keypair_source = - SignerSource::parse(&default_keypair).unwrap_or_else(print_error_and_exit); let default_signer: Option> = { if let Some(source) = matches.try_get_one::("owner").ok().flatten() { signer_from_source_with_config(matches, source, "owner", wallet_manager, &config) .ok() } else { - signer_from_source_with_config( + let default_keypair = cli_config.keypair_path.clone(); + signer_from_path_with_config( matches, - &default_keypair_source, + &default_keypair, "default", wallet_manager, &config,