automerge
This commit is contained in:
@@ -361,6 +361,12 @@ pub enum CliCommand {
|
||||
use_lamports_unit: bool,
|
||||
commitment_config: CommitmentConfig,
|
||||
},
|
||||
WithdrawFromVoteAccount {
|
||||
vote_account_pubkey: Pubkey,
|
||||
destination_account_pubkey: Pubkey,
|
||||
withdraw_authority: SignerIndex,
|
||||
lamports: u64,
|
||||
},
|
||||
VoteAuthorize {
|
||||
vote_account_pubkey: Pubkey,
|
||||
new_authorized_pubkey: Pubkey,
|
||||
@@ -692,6 +698,9 @@ pub fn parse_command(
|
||||
VoteAuthorize::Withdrawer,
|
||||
),
|
||||
("vote-account", Some(matches)) => parse_vote_get_account_command(matches),
|
||||
("withdraw-from-vote-account", Some(matches)) => {
|
||||
parse_withdraw_from_vote_account(matches, default_signer_path, wallet_manager)
|
||||
}
|
||||
// Wallet Commands
|
||||
("address", Some(matches)) => Ok(CliCommandInfo {
|
||||
command: CliCommand::Address,
|
||||
@@ -1917,6 +1926,19 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
||||
*use_lamports_unit,
|
||||
*commitment_config,
|
||||
),
|
||||
CliCommand::WithdrawFromVoteAccount {
|
||||
vote_account_pubkey,
|
||||
withdraw_authority,
|
||||
lamports,
|
||||
destination_account_pubkey,
|
||||
} => process_withdraw_from_vote_account(
|
||||
&rpc_client,
|
||||
config,
|
||||
vote_account_pubkey,
|
||||
*withdraw_authority,
|
||||
*lamports,
|
||||
destination_account_pubkey,
|
||||
),
|
||||
CliCommand::VoteAuthorize {
|
||||
vote_account_pubkey,
|
||||
new_authorized_pubkey,
|
||||
@@ -2281,7 +2303,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.validator(is_valid_signer)
|
||||
.help("From (base) key, defaults to client keypair."),
|
||||
.help("From (base) key, [default: cli config keypair]"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
|
@@ -199,7 +199,7 @@ impl NonceSubCommands for App<'_, '_> {
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("withdraw-from-nonce-account")
|
||||
.about("Withdraw lamports from the nonce account")
|
||||
.about("Withdraw SOL from the nonce account")
|
||||
.arg(
|
||||
Arg::with_name("nonce_account_keypair")
|
||||
.index(1)
|
||||
@@ -207,7 +207,7 @@ impl NonceSubCommands for App<'_, '_> {
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_keypair_or_ask_keyword)
|
||||
.help("Nonce account from to withdraw from"),
|
||||
.help("Nonce account to withdraw from"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("destination_account_pubkey")
|
||||
@@ -216,7 +216,7 @@ impl NonceSubCommands for App<'_, '_> {
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("The account to which the lamports should be transferred"),
|
||||
.help("The account to which the SOL should be transferred"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("amount")
|
||||
@@ -869,31 +869,6 @@ mod tests {
|
||||
}
|
||||
);
|
||||
|
||||
let test_withdraw_from_nonce_account = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
"withdraw-from-nonce-account",
|
||||
&keypair_file,
|
||||
&nonce_account_string,
|
||||
"42",
|
||||
]);
|
||||
assert_eq!(
|
||||
parse_command(
|
||||
&test_withdraw_from_nonce_account,
|
||||
&default_keypair_file,
|
||||
None
|
||||
)
|
||||
.unwrap(),
|
||||
CliCommandInfo {
|
||||
command: CliCommand::WithdrawFromNonceAccount {
|
||||
nonce_account: read_keypair_file(&keypair_file).unwrap().pubkey(),
|
||||
nonce_authority: 0,
|
||||
destination_account_pubkey: nonce_account_pubkey,
|
||||
lamports: 42000000000
|
||||
},
|
||||
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()],
|
||||
}
|
||||
);
|
||||
|
||||
// Test WithdrawFromNonceAccount Subcommand with authority
|
||||
let test_withdraw_from_nonce_account = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
|
@@ -34,13 +34,13 @@ use std::{ops::Deref, sync::Arc};
|
||||
pub const STAKE_AUTHORITY_ARG: ArgConstant<'static> = ArgConstant {
|
||||
name: "stake_authority",
|
||||
long: "stake-authority",
|
||||
help: "Public key of authorized staker (defaults to cli config pubkey)",
|
||||
help: "Authorized staker [default: cli config keypair]",
|
||||
};
|
||||
|
||||
pub const WITHDRAW_AUTHORITY_ARG: ArgConstant<'static> = ArgConstant {
|
||||
name: "withdraw_authority",
|
||||
long: "withdraw-authority",
|
||||
help: "Public key of authorized withdrawer (defaults to cli config pubkey)",
|
||||
help: "Authorized withdrawer [default: cli config keypair]",
|
||||
};
|
||||
|
||||
fn stake_authority_arg<'a, 'b>() -> Arg<'a, 'b> {
|
||||
@@ -279,7 +279,7 @@ impl StakeSubCommands for App<'_, '_> {
|
||||
.takes_value(true)
|
||||
.validator(is_amount)
|
||||
.required(true)
|
||||
.help("The amount to move into the new stake account, in unit SOL")
|
||||
.help("The amount to move into the new stake account, in SOL")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("seed")
|
||||
@@ -296,7 +296,7 @@ impl StakeSubCommands for App<'_, '_> {
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("withdraw-stake")
|
||||
.about("Withdraw the unstaked lamports from the stake account")
|
||||
.about("Withdraw the unstaked SOL from the stake account")
|
||||
.arg(
|
||||
Arg::with_name("stake_account_pubkey")
|
||||
.index(1)
|
||||
@@ -313,7 +313,7 @@ impl StakeSubCommands for App<'_, '_> {
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("The account to which the lamports should be transferred")
|
||||
.help("The account to which the SOL should be transferred")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("amount")
|
||||
@@ -374,7 +374,7 @@ impl StakeSubCommands for App<'_, '_> {
|
||||
.takes_value(true)
|
||||
.value_name("KEYPAIR or PUBKEY or REMOTE WALLET PATH")
|
||||
.validator(is_valid_signer)
|
||||
.help("Public key of signing custodian (defaults to cli config pubkey)")
|
||||
.help("Public key of signing custodian [default: cli config pubkey]")
|
||||
)
|
||||
.offline_args()
|
||||
.arg(nonce_arg())
|
||||
|
168
cli/src/vote.rs
168
cli/src/vote.rs
@@ -1,7 +1,7 @@
|
||||
use crate::cli::{
|
||||
build_balance_message, check_account_for_fee, check_unique_pubkeys, generate_unique_signers,
|
||||
log_instruction_custom_error, CliCommand, CliCommandInfo, CliConfig, CliError, CliSignerInfo,
|
||||
ProcessResult,
|
||||
ProcessResult, SignerIndex,
|
||||
};
|
||||
use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand};
|
||||
use solana_clap_utils::{input_parsers::*, input_validators::*};
|
||||
@@ -16,7 +16,7 @@ use solana_sdk::{
|
||||
transaction::Transaction,
|
||||
};
|
||||
use solana_vote_program::{
|
||||
vote_instruction::{self, VoteError},
|
||||
vote_instruction::{self, withdraw, VoteError},
|
||||
vote_state::{VoteAuthorize, VoteInit, VoteState},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
@@ -62,7 +62,7 @@ impl VoteSubCommands for App<'_, '_> {
|
||||
.value_name("PUBKEY")
|
||||
.takes_value(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Public key of the authorized voter (defaults to vote account)"),
|
||||
.help("Public key of the authorized voter [default: vote account]"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("authorized_withdrawer")
|
||||
@@ -70,7 +70,7 @@ impl VoteSubCommands for App<'_, '_> {
|
||||
.value_name("PUBKEY")
|
||||
.takes_value(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Public key of the authorized withdrawer (defaults to cli config pubkey)"),
|
||||
.help("Public key of the authorized withdrawer [default: cli config pubkey]"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("seed")
|
||||
@@ -183,6 +183,45 @@ impl VoteSubCommands for App<'_, '_> {
|
||||
.help("Display balance in lamports instead of SOL"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("withdraw-from-vote-account")
|
||||
.about("Withdraw lamports from a vote account into a specified account")
|
||||
.arg(
|
||||
Arg::with_name("vote_account_pubkey")
|
||||
.index(1)
|
||||
.value_name("VOTE ACCOUNT PUBKEY")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("Vote account from which to withdraw"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("destination_account_pubkey")
|
||||
.index(2)
|
||||
.value_name("DESTINATION ACCOUNT")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_pubkey_or_keypair)
|
||||
.help("The account to which the SOL should be transferred"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("amount")
|
||||
.index(3)
|
||||
.value_name("AMOUNT")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.validator(is_amount)
|
||||
.help("The amount to withdraw, in SOL"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("authorized_withdrawer")
|
||||
.long("authorized-withdrawer")
|
||||
.value_name("KEYPAIR or PUBKEY or REMOTE WALLET PATH")
|
||||
.takes_value(true)
|
||||
.validator(is_valid_signer)
|
||||
.help("Authorized withdrawer [default: cli config keypair]"),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,6 +330,36 @@ pub fn parse_vote_get_account_command(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_withdraw_from_vote_account(
|
||||
matches: &ArgMatches<'_>,
|
||||
default_signer_path: &str,
|
||||
wallet_manager: Option<&Arc<RemoteWalletManager>>,
|
||||
) -> Result<CliCommandInfo, CliError> {
|
||||
let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap();
|
||||
let destination_account_pubkey = pubkey_of(matches, "destination_account_pubkey").unwrap();
|
||||
let lamports = lamports_of_sol(matches, "amount").unwrap();
|
||||
let (withdraw_authority, withdraw_authority_pubkey) =
|
||||
signer_of(matches, "authorized_withdrawer", wallet_manager)?;
|
||||
|
||||
let payer_provided = None;
|
||||
let signer_info = generate_unique_signers(
|
||||
vec![payer_provided, withdraw_authority],
|
||||
matches,
|
||||
default_signer_path,
|
||||
wallet_manager,
|
||||
)?;
|
||||
|
||||
Ok(CliCommandInfo {
|
||||
command: CliCommand::WithdrawFromVoteAccount {
|
||||
vote_account_pubkey,
|
||||
destination_account_pubkey,
|
||||
withdraw_authority: signer_info.index_of(withdraw_authority_pubkey).unwrap(),
|
||||
lamports,
|
||||
},
|
||||
signers: signer_info.signers,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn process_create_vote_account(
|
||||
rpc_client: &RpcClient,
|
||||
config: &CliConfig,
|
||||
@@ -517,6 +586,37 @@ pub fn process_show_vote_account(
|
||||
Ok("".to_string())
|
||||
}
|
||||
|
||||
pub fn process_withdraw_from_vote_account(
|
||||
rpc_client: &RpcClient,
|
||||
config: &CliConfig,
|
||||
vote_account_pubkey: &Pubkey,
|
||||
withdraw_authority: SignerIndex,
|
||||
lamports: u64,
|
||||
destination_account_pubkey: &Pubkey,
|
||||
) -> ProcessResult {
|
||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
||||
let withdraw_authority = config.signers[withdraw_authority];
|
||||
|
||||
let ix = withdraw(
|
||||
vote_account_pubkey,
|
||||
&withdraw_authority.pubkey(),
|
||||
lamports,
|
||||
destination_account_pubkey,
|
||||
);
|
||||
|
||||
let message = Message::new_with_payer(&[ix], Some(&config.signers[0].pubkey()));
|
||||
let mut transaction = Transaction::new_unsigned(message);
|
||||
transaction.try_sign(&config.signers, recent_blockhash)?;
|
||||
check_account_for_fee(
|
||||
rpc_client,
|
||||
&config.signers[0].pubkey(),
|
||||
&fee_calculator,
|
||||
&transaction.message,
|
||||
)?;
|
||||
let result = rpc_client.send_and_confirm_transaction(&mut transaction, &config.signers);
|
||||
log_instruction_custom_error::<VoteError>(result)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -699,5 +799,65 @@ mod tests {
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
// Test WithdrawFromVoteAccount subcommand
|
||||
let test_withdraw_from_vote_account = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
"withdraw-from-vote-account",
|
||||
&keypair_file,
|
||||
&pubkey_string,
|
||||
"42",
|
||||
]);
|
||||
assert_eq!(
|
||||
parse_command(
|
||||
&test_withdraw_from_vote_account,
|
||||
&default_keypair_file,
|
||||
None
|
||||
)
|
||||
.unwrap(),
|
||||
CliCommandInfo {
|
||||
command: CliCommand::WithdrawFromVoteAccount {
|
||||
vote_account_pubkey: read_keypair_file(&keypair_file).unwrap().pubkey(),
|
||||
destination_account_pubkey: pubkey,
|
||||
withdraw_authority: 0,
|
||||
lamports: 42_000_000_000
|
||||
},
|
||||
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()],
|
||||
}
|
||||
);
|
||||
|
||||
// Test WithdrawFromVoteAccount subcommand with authority
|
||||
let withdraw_authority = Keypair::new();
|
||||
let (withdraw_authority_file, mut tmp_file) = make_tmp_file();
|
||||
write_keypair(&withdraw_authority, tmp_file.as_file_mut()).unwrap();
|
||||
let test_withdraw_from_vote_account = test_commands.clone().get_matches_from(vec![
|
||||
"test",
|
||||
"withdraw-from-vote-account",
|
||||
&keypair_file,
|
||||
&pubkey_string,
|
||||
"42",
|
||||
"--authorized-withdrawer",
|
||||
&withdraw_authority_file,
|
||||
]);
|
||||
assert_eq!(
|
||||
parse_command(
|
||||
&test_withdraw_from_vote_account,
|
||||
&default_keypair_file,
|
||||
None
|
||||
)
|
||||
.unwrap(),
|
||||
CliCommandInfo {
|
||||
command: CliCommand::WithdrawFromVoteAccount {
|
||||
vote_account_pubkey: read_keypair_file(&keypair_file).unwrap().pubkey(),
|
||||
destination_account_pubkey: pubkey,
|
||||
withdraw_authority: 1,
|
||||
lamports: 42_000_000_000
|
||||
},
|
||||
signers: vec![
|
||||
read_keypair_file(&default_keypair_file).unwrap().into(),
|
||||
read_keypair_file(&withdraw_authority_file).unwrap().into()
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user