Add show-stake-history command to cli (#6541)
This commit is contained in:
parent
3879109e4c
commit
71ff269780
|
@ -73,6 +73,9 @@ pub enum CliCommand {
|
||||||
DeactivateStake(Pubkey),
|
DeactivateStake(Pubkey),
|
||||||
DelegateStake(Pubkey, Pubkey, bool),
|
DelegateStake(Pubkey, Pubkey, bool),
|
||||||
RedeemVoteCredits(Pubkey, Pubkey),
|
RedeemVoteCredits(Pubkey, Pubkey),
|
||||||
|
ShowStakeHistory {
|
||||||
|
use_lamports_unit: bool,
|
||||||
|
},
|
||||||
ShowStakeAccount {
|
ShowStakeAccount {
|
||||||
pubkey: Pubkey,
|
pubkey: Pubkey,
|
||||||
use_lamports_unit: bool,
|
use_lamports_unit: bool,
|
||||||
|
@ -252,6 +255,7 @@ pub fn parse_command(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, Box<dyn
|
||||||
}
|
}
|
||||||
("redeem-vote-credits", Some(matches)) => parse_redeem_vote_credits(matches),
|
("redeem-vote-credits", Some(matches)) => parse_redeem_vote_credits(matches),
|
||||||
("show-stake-account", Some(matches)) => parse_show_stake_account(matches),
|
("show-stake-account", Some(matches)) => parse_show_stake_account(matches),
|
||||||
|
("show-stake-history", Some(matches)) => parse_show_stake_history(matches),
|
||||||
// Storage Commands
|
// Storage Commands
|
||||||
("create-archiver-storage-account", Some(matches)) => {
|
("create-archiver-storage-account", Some(matches)) => {
|
||||||
parse_storage_create_archiver_account(matches)
|
parse_storage_create_archiver_account(matches)
|
||||||
|
@ -486,7 +490,7 @@ fn process_airdrop(
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
println!(
|
println!(
|
||||||
"Requesting airdrop of {} from {}",
|
"Requesting airdrop of {} from {}",
|
||||||
build_balance_message(lamports, use_lamports_unit),
|
build_balance_message(lamports, use_lamports_unit, true),
|
||||||
drone_addr
|
drone_addr
|
||||||
);
|
);
|
||||||
let previous_balance = match rpc_client.retry_get_balance(&config.keypair.pubkey(), 5)? {
|
let previous_balance = match rpc_client.retry_get_balance(&config.keypair.pubkey(), 5)? {
|
||||||
|
@ -505,7 +509,11 @@ fn process_airdrop(
|
||||||
.retry_get_balance(&config.keypair.pubkey(), 5)?
|
.retry_get_balance(&config.keypair.pubkey(), 5)?
|
||||||
.unwrap_or(previous_balance);
|
.unwrap_or(previous_balance);
|
||||||
|
|
||||||
Ok(build_balance_message(current_balance, use_lamports_unit))
|
Ok(build_balance_message(
|
||||||
|
current_balance,
|
||||||
|
use_lamports_unit,
|
||||||
|
true,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_balance(
|
fn process_balance(
|
||||||
|
@ -517,7 +525,7 @@ fn process_balance(
|
||||||
let pubkey = pubkey.unwrap_or(config.keypair.pubkey());
|
let pubkey = pubkey.unwrap_or(config.keypair.pubkey());
|
||||||
let balance = rpc_client.retry_get_balance(&pubkey, 5)?;
|
let balance = rpc_client.retry_get_balance(&pubkey, 5)?;
|
||||||
match balance {
|
match balance {
|
||||||
Some(lamports) => Ok(build_balance_message(lamports, use_lamports_unit)),
|
Some(lamports) => Ok(build_balance_message(lamports, use_lamports_unit, true)),
|
||||||
None => Err(
|
None => Err(
|
||||||
CliError::RpcRequestError("Received result of an unexpected type".to_string()).into(),
|
CliError::RpcRequestError("Received result of an unexpected type".to_string()).into(),
|
||||||
),
|
),
|
||||||
|
@ -553,7 +561,7 @@ fn process_show_account(
|
||||||
println_name_value("Public Key:", &account_pubkey.to_string());
|
println_name_value("Public Key:", &account_pubkey.to_string());
|
||||||
println_name_value(
|
println_name_value(
|
||||||
"Balance:",
|
"Balance:",
|
||||||
&build_balance_message(account.lamports, use_lamports_unit),
|
&build_balance_message(account.lamports, use_lamports_unit, true),
|
||||||
);
|
);
|
||||||
println_name_value("Owner:", &account.owner.to_string());
|
println_name_value("Owner:", &account.owner.to_string());
|
||||||
println_name_value("Executable:", &account.executable.to_string());
|
println_name_value("Executable:", &account.executable.to_string());
|
||||||
|
@ -877,6 +885,9 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
|
||||||
&stake_account_pubkey,
|
&stake_account_pubkey,
|
||||||
*use_lamports_unit,
|
*use_lamports_unit,
|
||||||
),
|
),
|
||||||
|
CliCommand::ShowStakeHistory { use_lamports_unit } => {
|
||||||
|
process_show_stake_history(&rpc_client, config, *use_lamports_unit)
|
||||||
|
}
|
||||||
CliCommand::StakeAuthorize(
|
CliCommand::StakeAuthorize(
|
||||||
stake_account_pubkey,
|
stake_account_pubkey,
|
||||||
new_authorized_pubkey,
|
new_authorized_pubkey,
|
||||||
|
@ -1151,15 +1162,25 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn build_balance_message(lamports: u64, use_lamports_unit: bool) -> String {
|
pub(crate) fn build_balance_message(
|
||||||
|
lamports: u64,
|
||||||
|
use_lamports_unit: bool,
|
||||||
|
show_unit: bool,
|
||||||
|
) -> String {
|
||||||
if use_lamports_unit {
|
if use_lamports_unit {
|
||||||
let ess = if lamports == 1 { "" } else { "s" };
|
let ess = if lamports == 1 { "" } else { "s" };
|
||||||
format!("{:?} lamport{}", lamports, ess)
|
let unit = if show_unit {
|
||||||
|
format!(" lamport{}", ess)
|
||||||
|
} else {
|
||||||
|
"".to_string()
|
||||||
|
};
|
||||||
|
format!("{:?}{}", lamports, unit)
|
||||||
} else {
|
} else {
|
||||||
let sol = lamports_to_sol(lamports);
|
let sol = lamports_to_sol(lamports);
|
||||||
let sol_str = format!("{:.8}", sol);
|
let sol_str = format!("{:.8}", sol);
|
||||||
let pretty_sol = sol_str.trim_end_matches('0').trim_end_matches('.');
|
let pretty_sol = sol_str.trim_end_matches('0').trim_end_matches('.');
|
||||||
format!("{} SOL", pretty_sol)
|
let unit = if show_unit { " SOL" } else { "" };
|
||||||
|
format!("{}{}", pretty_sol, unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -320,14 +320,14 @@ pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool)
|
||||||
|
|
||||||
println_name_value(
|
println_name_value(
|
||||||
"Active Stake:",
|
"Active Stake:",
|
||||||
&build_balance_message(total_active_stake as u64, use_lamports_unit),
|
&build_balance_message(total_active_stake as u64, use_lamports_unit, true),
|
||||||
);
|
);
|
||||||
if total_deliquent_stake > 0. {
|
if total_deliquent_stake > 0. {
|
||||||
println_name_value(
|
println_name_value(
|
||||||
"Current Stake:",
|
"Current Stake:",
|
||||||
&format!(
|
&format!(
|
||||||
"{} ({:0.2}%)",
|
"{} ({:0.2}%)",
|
||||||
&build_balance_message(total_current_stake as u64, use_lamports_unit),
|
&build_balance_message(total_current_stake as u64, use_lamports_unit, true),
|
||||||
100. * total_current_stake / total_active_stake
|
100. * total_current_stake / total_active_stake
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -335,7 +335,7 @@ pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool)
|
||||||
"Delinquent Stake:",
|
"Delinquent Stake:",
|
||||||
&format!(
|
&format!(
|
||||||
"{} ({:0.2}%)",
|
"{} ({:0.2}%)",
|
||||||
&build_balance_message(total_deliquent_stake as u64, use_lamports_unit),
|
&build_balance_message(total_deliquent_stake as u64, use_lamports_unit, true),
|
||||||
100. * total_deliquent_stake / total_active_stake
|
100. * total_deliquent_stake / total_active_stake
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -385,7 +385,7 @@ pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool)
|
||||||
if vote_account.activated_stake > 0 {
|
if vote_account.activated_stake > 0 {
|
||||||
format!(
|
format!(
|
||||||
"{} ({:.2}%)",
|
"{} ({:.2}%)",
|
||||||
build_balance_message(vote_account.activated_stake, use_lamports_unit),
|
build_balance_message(vote_account.activated_stake, use_lamports_unit, true),
|
||||||
100. * vote_account.activated_stake as f64 / total_active_stake
|
100. * vote_account.activated_stake as f64 / total_active_stake
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,9 +8,14 @@ use crate::{
|
||||||
input_validators::*,
|
input_validators::*,
|
||||||
};
|
};
|
||||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||||
|
use console::style;
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account_utils::State, pubkey::Pubkey, signature::KeypairUtil, system_instruction::SystemError,
|
account_utils::State,
|
||||||
|
pubkey::Pubkey,
|
||||||
|
signature::KeypairUtil,
|
||||||
|
system_instruction::SystemError,
|
||||||
|
sysvar::stake_history::{self, StakeHistory},
|
||||||
transaction::Transaction,
|
transaction::Transaction,
|
||||||
};
|
};
|
||||||
use solana_stake_api::{
|
use solana_stake_api::{
|
||||||
|
@ -18,6 +23,7 @@ use solana_stake_api::{
|
||||||
stake_state::{Authorized, Lockup, StakeAuthorize, StakeState},
|
stake_state::{Authorized, Lockup, StakeAuthorize, StakeState},
|
||||||
};
|
};
|
||||||
use solana_vote_api::vote_state::VoteState;
|
use solana_vote_api::vote_state::VoteState;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
pub trait StakeSubCommands {
|
pub trait StakeSubCommands {
|
||||||
fn stake_subcommands(self) -> Self;
|
fn stake_subcommands(self) -> Self;
|
||||||
|
@ -249,6 +255,16 @@ impl StakeSubCommands for App<'_, '_> {
|
||||||
.help("Display balance in lamports instead of SOL")
|
.help("Display balance in lamports instead of SOL")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.subcommand(
|
||||||
|
SubCommand::with_name("show-stake-history")
|
||||||
|
.about("Show the stake history")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("lamports")
|
||||||
|
.long("lamports")
|
||||||
|
.takes_value(false)
|
||||||
|
.help("Display balance in lamports instead of SOL")
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,6 +360,14 @@ pub fn parse_show_stake_account(matches: &ArgMatches<'_>) -> Result<CliCommandIn
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_show_stake_history(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||||
|
let use_lamports_unit = matches.is_present("lamports");
|
||||||
|
Ok(CliCommandInfo {
|
||||||
|
command: CliCommand::ShowStakeHistory { use_lamports_unit },
|
||||||
|
require_keypair: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn process_create_stake_account(
|
pub fn process_create_stake_account(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
config: &CliConfig,
|
config: &CliConfig,
|
||||||
|
@ -527,12 +551,12 @@ pub fn process_show_stake_account(
|
||||||
Ok(StakeState::Stake(authorized, lockup, stake)) => {
|
Ok(StakeState::Stake(authorized, lockup, stake)) => {
|
||||||
println!(
|
println!(
|
||||||
"total stake: {}",
|
"total stake: {}",
|
||||||
build_balance_message(stake_account.lamports, use_lamports_unit)
|
build_balance_message(stake_account.lamports, use_lamports_unit, true)
|
||||||
);
|
);
|
||||||
println!("credits observed: {}", stake.credits_observed);
|
println!("credits observed: {}", stake.credits_observed);
|
||||||
println!(
|
println!(
|
||||||
"delegated stake: {}",
|
"delegated stake: {}",
|
||||||
build_balance_message(stake.stake, use_lamports_unit)
|
build_balance_message(stake.stake, use_lamports_unit, true)
|
||||||
);
|
);
|
||||||
if stake.voter_pubkey != Pubkey::default() {
|
if stake.voter_pubkey != Pubkey::default() {
|
||||||
println!("delegated voter pubkey: {}", stake.voter_pubkey);
|
println!("delegated voter pubkey: {}", stake.voter_pubkey);
|
||||||
|
@ -567,6 +591,37 @@ pub fn process_show_stake_account(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn process_show_stake_history(
|
||||||
|
rpc_client: &RpcClient,
|
||||||
|
_config: &CliConfig,
|
||||||
|
use_lamports_unit: bool,
|
||||||
|
) -> ProcessResult {
|
||||||
|
let stake_history_account = rpc_client.get_account(&stake_history::id())?;
|
||||||
|
let stake_history = StakeHistory::from_account(&stake_history_account).unwrap();
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
style(format!(
|
||||||
|
" {:<5} {:>15} {:>16} {:>18}",
|
||||||
|
"Epoch", "Effective Stake", "Activating Stake", "Deactivating Stake",
|
||||||
|
))
|
||||||
|
.bold()
|
||||||
|
);
|
||||||
|
|
||||||
|
for (epoch, entry) in stake_history.deref() {
|
||||||
|
println!(
|
||||||
|
" {:>5} {:>15} {:>16} {:>18} {}",
|
||||||
|
epoch,
|
||||||
|
build_balance_message(entry.effective, use_lamports_unit, false),
|
||||||
|
build_balance_message(entry.activating, use_lamports_unit, false),
|
||||||
|
build_balance_message(entry.deactivating, use_lamports_unit, false),
|
||||||
|
if use_lamports_unit { "lamports" } else { "SOL" }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok("".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn process_delegate_stake(
|
pub fn process_delegate_stake(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
config: &CliConfig,
|
config: &CliConfig,
|
||||||
|
|
|
@ -334,7 +334,7 @@ pub fn process_show_vote_account(
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"account balance: {}",
|
"account balance: {}",
|
||||||
build_balance_message(vote_account.lamports, use_lamports_unit)
|
build_balance_message(vote_account.lamports, use_lamports_unit, true)
|
||||||
);
|
);
|
||||||
println!("node id: {}", vote_state.node_pubkey);
|
println!("node id: {}", vote_state.node_pubkey);
|
||||||
println!("authorized voter: {}", vote_state.authorized_voter);
|
println!("authorized voter: {}", vote_state.authorized_voter);
|
||||||
|
|
Loading…
Reference in New Issue