Cli: transfer ALL; check spend+fee in client (#10012)
* lamports->SOL in user-facing error msg * Check for sufficient balance for spend and fee * Add ALL option to solana transfer * Rework TransferAmount to check for sign_only in parse * Refactor TransferAmount & fee-check handling to be more general * Add addl checks mechanism * Move checks out of cli.rs * Rename to SpendAmount to be more general & move * Impl ALL/spend helpers for create-nonce-account * Impl spend helpers for create-vote-account * Impl ALL/spend helpers for create-stake-account * Impl spend helpers for ping * Impl ALL/spend helpers for pay * Impl spend helpers for validator-info * Remove unused fns * Remove retry_get_balance * Add a couple unit tests * Rework send_util fn signatures
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
use crate::{
|
||||
checks::{check_account_for_fee, check_unique_pubkeys},
|
||||
cli::{
|
||||
check_account_for_fee, check_unique_pubkeys, generate_unique_signers,
|
||||
log_instruction_custom_error, CliCommand, CliCommandInfo, CliConfig, CliError,
|
||||
ProcessResult, SignerIndex,
|
||||
generate_unique_signers, log_instruction_custom_error, CliCommand, CliCommandInfo,
|
||||
CliConfig, CliError, ProcessResult, SignerIndex,
|
||||
},
|
||||
cli_output::{CliEpochVotingHistory, CliLockout, CliVoteAccount},
|
||||
spend_utils::{resolve_spend_tx_and_check_account_balance, SpendAmount},
|
||||
};
|
||||
use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand};
|
||||
use solana_clap_utils::{
|
||||
@@ -386,6 +387,39 @@ pub fn process_create_vote_account(
|
||||
(&identity_pubkey, "identity_pubkey".to_string()),
|
||||
)?;
|
||||
|
||||
let required_balance = rpc_client
|
||||
.get_minimum_balance_for_rent_exemption(VoteState::size_of())?
|
||||
.max(1);
|
||||
let amount = SpendAmount::Some(required_balance);
|
||||
|
||||
let build_message = |lamports| {
|
||||
let vote_init = VoteInit {
|
||||
node_pubkey: identity_pubkey,
|
||||
authorized_voter: authorized_voter.unwrap_or(identity_pubkey),
|
||||
authorized_withdrawer: authorized_withdrawer.unwrap_or(identity_pubkey),
|
||||
commission,
|
||||
};
|
||||
|
||||
let ixs = if let Some(seed) = seed {
|
||||
vote_instruction::create_account_with_seed(
|
||||
&config.signers[0].pubkey(), // from
|
||||
&vote_account_address, // to
|
||||
&vote_account_pubkey, // base
|
||||
seed, // seed
|
||||
&vote_init,
|
||||
lamports,
|
||||
)
|
||||
} else {
|
||||
vote_instruction::create_account(
|
||||
&config.signers[0].pubkey(),
|
||||
&vote_account_pubkey,
|
||||
&vote_init,
|
||||
lamports,
|
||||
)
|
||||
};
|
||||
Message::new(&ixs)
|
||||
};
|
||||
|
||||
if let Ok(vote_account) = rpc_client.get_account(&vote_account_address) {
|
||||
let err_msg = if vote_account.owner == solana_vote_program::id() {
|
||||
format!("Vote account {} already exists", vote_account_address)
|
||||
@@ -398,45 +432,18 @@ pub fn process_create_vote_account(
|
||||
return Err(CliError::BadParameter(err_msg).into());
|
||||
}
|
||||
|
||||
let required_balance = rpc_client
|
||||
.get_minimum_balance_for_rent_exemption(VoteState::size_of())?
|
||||
.max(1);
|
||||
|
||||
let vote_init = VoteInit {
|
||||
node_pubkey: identity_pubkey,
|
||||
authorized_voter: authorized_voter.unwrap_or(identity_pubkey),
|
||||
authorized_withdrawer: authorized_withdrawer.unwrap_or(identity_pubkey),
|
||||
commission,
|
||||
};
|
||||
|
||||
let ixs = if let Some(seed) = seed {
|
||||
vote_instruction::create_account_with_seed(
|
||||
&config.signers[0].pubkey(), // from
|
||||
&vote_account_address, // to
|
||||
&vote_account_pubkey, // base
|
||||
seed, // seed
|
||||
&vote_init,
|
||||
required_balance,
|
||||
)
|
||||
} else {
|
||||
vote_instruction::create_account(
|
||||
&config.signers[0].pubkey(),
|
||||
&vote_account_pubkey,
|
||||
&vote_init,
|
||||
required_balance,
|
||||
)
|
||||
};
|
||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
||||
|
||||
let message = Message::new(&ixs);
|
||||
let (message, _) = resolve_spend_tx_and_check_account_balance(
|
||||
rpc_client,
|
||||
false,
|
||||
amount,
|
||||
&fee_calculator,
|
||||
&config.signers[0].pubkey(),
|
||||
build_message,
|
||||
)?;
|
||||
let mut tx = Transaction::new_unsigned(message);
|
||||
tx.try_sign(&config.signers, recent_blockhash)?;
|
||||
check_account_for_fee(
|
||||
rpc_client,
|
||||
&config.signers[0].pubkey(),
|
||||
&fee_calculator,
|
||||
&tx.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction_with_spinner(&tx);
|
||||
log_instruction_custom_error::<SystemError>(result, &config)
|
||||
}
|
||||
|
Reference in New Issue
Block a user