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:
Tyera Eulberg
2020-05-14 12:24:14 -06:00
committed by GitHub
parent 4e4a21f9b7
commit ed53a70b5c
21 changed files with 929 additions and 443 deletions

View File

@@ -1,6 +1,7 @@
use crate::{
cli::{check_account_for_fee, CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult},
cli::{CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult},
cli_output::{CliValidatorInfo, CliValidatorInfoVec},
spend_utils::{resolve_spend_tx_and_check_account_balance, SpendAmount},
};
use bincode::deserialize;
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
@@ -310,8 +311,10 @@ pub fn process_set_validator_info(
.poll_get_balance_with_commitment(&info_pubkey, CommitmentConfig::default())
.unwrap_or(0);
let keys = vec![(id(), false), (config.signers[0].pubkey(), true)];
let (message, signers): (Message, Vec<&dyn Signer>) = if balance == 0 {
let lamports =
rpc_client.get_minimum_balance_for_rent_exemption(ValidatorInfo::max_space() as usize)?;
let signers = if balance == 0 {
if info_pubkey != info_keypair.pubkey() {
println!(
"Account {:?} does not exist. Generating new keypair...",
@@ -319,54 +322,59 @@ pub fn process_set_validator_info(
);
info_pubkey = info_keypair.pubkey();
}
println!(
"Publishing info for Validator {:?}",
config.signers[0].pubkey()
);
let lamports = rpc_client
.get_minimum_balance_for_rent_exemption(ValidatorInfo::max_space() as usize)?;
let mut instructions = config_instruction::create_account::<ValidatorInfo>(
&config.signers[0].pubkey(),
&info_keypair.pubkey(),
lamports,
keys.clone(),
);
instructions.extend_from_slice(&[config_instruction::store(
&info_keypair.pubkey(),
true,
keys,
&validator_info,
)]);
let signers = vec![config.signers[0], &info_keypair];
let message = Message::new(&instructions);
(message, signers)
vec![config.signers[0], &info_keypair]
} else {
println!(
"Updating Validator {:?} info at: {:?}",
config.signers[0].pubkey(),
info_pubkey
);
let instructions = vec![config_instruction::store(
&info_pubkey,
false,
keys,
&validator_info,
)];
let message = Message::new_with_payer(&instructions, Some(&config.signers[0].pubkey()));
let signers = vec![config.signers[0]];
(message, signers)
vec![config.signers[0]]
};
let build_message = |lamports| {
let keys = vec![(id(), false), (config.signers[0].pubkey(), true)];
if balance == 0 {
println!(
"Publishing info for Validator {:?}",
config.signers[0].pubkey()
);
let mut instructions = config_instruction::create_account::<ValidatorInfo>(
&config.signers[0].pubkey(),
&info_pubkey,
lamports,
keys.clone(),
);
instructions.extend_from_slice(&[config_instruction::store(
&info_pubkey,
true,
keys,
&validator_info,
)]);
Message::new(&instructions)
} else {
println!(
"Updating Validator {:?} info at: {:?}",
config.signers[0].pubkey(),
info_pubkey
);
let instructions = vec![config_instruction::store(
&info_pubkey,
false,
keys,
&validator_info,
)];
Message::new_with_payer(&instructions, Some(&config.signers[0].pubkey()))
}
};
// Submit transaction
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let (message, _) = resolve_spend_tx_and_check_account_balance(
rpc_client,
false,
SpendAmount::Some(lamports),
&fee_calculator,
&config.signers[0].pubkey(),
build_message,
)?;
let mut tx = Transaction::new_unsigned(message);
tx.try_sign(&signers, recent_blockhash)?;
check_account_for_fee(
rpc_client,
&config.signers[0].pubkey(),
&fee_calculator,
&tx.message,
)?;
let signature_str = rpc_client.send_and_confirm_transaction_with_spinner(&tx)?;
println!("Success! Validator info published at: {:?}", info_pubkey);