Cli: Fix create-with-seed (#8706)
* Add failing test * Fix create-address-with-seed regression * Add apis to enable generating a pubkey from all various signers * Enable other signers as --from in create-with-seed
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
use crate::keypair::{
|
use crate::keypair::{
|
||||||
keypair_from_seed_phrase, signer_from_path, ASK_KEYWORD, SKIP_SEED_PHRASE_VALIDATION_ARG,
|
keypair_from_seed_phrase, pubkey_from_path, signer_from_path, ASK_KEYWORD,
|
||||||
|
SKIP_SEED_PHRASE_VALIDATION_ARG,
|
||||||
};
|
};
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
@ -111,6 +112,23 @@ pub fn signer_of(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pubkey_of_signer(
|
||||||
|
matches: &ArgMatches<'_>,
|
||||||
|
name: &str,
|
||||||
|
wallet_manager: Option<&Arc<RemoteWalletManager>>,
|
||||||
|
) -> Result<Option<Pubkey>, Box<dyn std::error::Error>> {
|
||||||
|
if let Some(location) = matches.value_of(name) {
|
||||||
|
Ok(Some(pubkey_from_path(
|
||||||
|
matches,
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
wallet_manager,
|
||||||
|
)?))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn lamports_of_sol(matches: &ArgMatches<'_>, name: &str) -> Option<u64> {
|
pub fn lamports_of_sol(matches: &ArgMatches<'_>, name: &str) -> Option<u64> {
|
||||||
value_of(matches, name).map(sol_to_lamports)
|
value_of(matches, name).map(sol_to_lamports)
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,18 @@ pub fn signer_from_path(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pubkey_from_path(
|
||||||
|
matches: &ArgMatches,
|
||||||
|
path: &str,
|
||||||
|
keypair_name: &str,
|
||||||
|
wallet_manager: Option<&Arc<RemoteWalletManager>>,
|
||||||
|
) -> Result<Pubkey, Box<dyn error::Error>> {
|
||||||
|
match parse_keypair_path(path) {
|
||||||
|
KeypairUrl::Pubkey(pubkey) => Ok(pubkey),
|
||||||
|
_ => Ok(signer_from_path(matches, path, keypair_name, wallet_manager)?.pubkey()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Keyword used to indicate that the user should be asked for a keypair seed phrase
|
// Keyword used to indicate that the user should be asked for a keypair seed phrase
|
||||||
pub const ASK_KEYWORD: &str = "ASK";
|
pub const ASK_KEYWORD: &str = "ASK";
|
||||||
|
|
||||||
|
@ -590,7 +590,9 @@ pub fn parse_command(
|
|||||||
command: CliCommand::ClusterVersion,
|
command: CliCommand::ClusterVersion,
|
||||||
signers: vec![],
|
signers: vec![],
|
||||||
}),
|
}),
|
||||||
("create-address-with-seed", Some(matches)) => parse_create_address_with_seed(matches),
|
("create-address-with-seed", Some(matches)) => {
|
||||||
|
parse_create_address_with_seed(matches, default_signer_path, wallet_manager)
|
||||||
|
}
|
||||||
("fees", Some(_matches)) => Ok(CliCommandInfo {
|
("fees", Some(_matches)) => Ok(CliCommandInfo {
|
||||||
command: CliCommand::Fees,
|
command: CliCommand::Fees,
|
||||||
signers: vec![],
|
signers: vec![],
|
||||||
@ -1036,8 +1038,20 @@ pub fn return_signers(tx: &Transaction) -> ProcessResult {
|
|||||||
|
|
||||||
pub fn parse_create_address_with_seed(
|
pub fn parse_create_address_with_seed(
|
||||||
matches: &ArgMatches<'_>,
|
matches: &ArgMatches<'_>,
|
||||||
|
default_signer_path: &str,
|
||||||
|
wallet_manager: Option<&Arc<RemoteWalletManager>>,
|
||||||
) -> Result<CliCommandInfo, CliError> {
|
) -> Result<CliCommandInfo, CliError> {
|
||||||
let from_pubkey = pubkey_of(matches, "from");
|
let from_pubkey = pubkey_of_signer(matches, "from", wallet_manager)?;
|
||||||
|
let signers = if from_pubkey.is_some() {
|
||||||
|
vec![]
|
||||||
|
} else {
|
||||||
|
vec![signer_from_path(
|
||||||
|
matches,
|
||||||
|
default_signer_path,
|
||||||
|
"keypair",
|
||||||
|
wallet_manager,
|
||||||
|
)?]
|
||||||
|
};
|
||||||
|
|
||||||
let program_id = match matches.value_of("program_id").unwrap() {
|
let program_id = match matches.value_of("program_id").unwrap() {
|
||||||
"STAKE" => solana_stake_program::id(),
|
"STAKE" => solana_stake_program::id(),
|
||||||
@ -1060,7 +1074,7 @@ pub fn parse_create_address_with_seed(
|
|||||||
seed,
|
seed,
|
||||||
program_id,
|
program_id,
|
||||||
},
|
},
|
||||||
signers: vec![],
|
signers,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1070,9 +1084,12 @@ fn process_create_address_with_seed(
|
|||||||
seed: &str,
|
seed: &str,
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
let config_pubkey = config.pubkey()?;
|
let from_pubkey = if let Some(pubkey) = from_pubkey {
|
||||||
let from_pubkey = from_pubkey.unwrap_or(&config_pubkey);
|
*pubkey
|
||||||
let address = create_address_with_seed(from_pubkey, seed, program_id)?;
|
} else {
|
||||||
|
config.pubkey()?
|
||||||
|
};
|
||||||
|
let address = create_address_with_seed(&from_pubkey, seed, program_id)?;
|
||||||
Ok(address.to_string())
|
Ok(address.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2288,7 +2305,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
|
|||||||
.value_name("PUBKEY")
|
.value_name("PUBKEY")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.required(false)
|
.required(false)
|
||||||
.validator(is_pubkey_or_keypair)
|
.validator(is_valid_signer)
|
||||||
.help("From (base) key, defaults to client keypair."),
|
.help("From (base) key, defaults to client keypair."),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -2721,14 +2738,14 @@ mod tests {
|
|||||||
"STAKE",
|
"STAKE",
|
||||||
]);
|
]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_command(&test_create_address_with_seed, "", None).unwrap(),
|
parse_command(&test_create_address_with_seed, &keypair_file, None).unwrap(),
|
||||||
CliCommandInfo {
|
CliCommandInfo {
|
||||||
command: CliCommand::CreateAddressWithSeed {
|
command: CliCommand::CreateAddressWithSeed {
|
||||||
from_pubkey: None,
|
from_pubkey: None,
|
||||||
seed: "seed".to_string(),
|
seed: "seed".to_string(),
|
||||||
program_id: solana_stake_program::id(),
|
program_id: solana_stake_program::id(),
|
||||||
},
|
},
|
||||||
signers: vec![],
|
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -3332,8 +3349,22 @@ mod tests {
|
|||||||
let signature = process_command(&config);
|
let signature = process_command(&config);
|
||||||
assert_eq!(signature.unwrap(), SIGNATURE.to_string());
|
assert_eq!(signature.unwrap(), SIGNATURE.to_string());
|
||||||
|
|
||||||
|
// CreateAddressWithSeed
|
||||||
|
let from_pubkey = Pubkey::new_rand();
|
||||||
|
config.signers = vec![];
|
||||||
|
config.command = CliCommand::CreateAddressWithSeed {
|
||||||
|
from_pubkey: Some(from_pubkey),
|
||||||
|
seed: "seed".to_string(),
|
||||||
|
program_id: solana_stake_program::id(),
|
||||||
|
};
|
||||||
|
let address = process_command(&config);
|
||||||
|
let expected_address =
|
||||||
|
create_address_with_seed(&from_pubkey, "seed", &solana_stake_program::id()).unwrap();
|
||||||
|
assert_eq!(address.unwrap(), expected_address.to_string());
|
||||||
|
|
||||||
// Need airdrop cases
|
// Need airdrop cases
|
||||||
let to = Pubkey::new_rand();
|
let to = Pubkey::new_rand();
|
||||||
|
config.signers = vec![&keypair];
|
||||||
config.command = CliCommand::Airdrop {
|
config.command = CliCommand::Airdrop {
|
||||||
faucet_host: None,
|
faucet_host: None,
|
||||||
faucet_port: 1234,
|
faucet_port: 1234,
|
||||||
|
Reference in New Issue
Block a user