From dd78184f8f8e17f5b0eb17cde57ebf6e33048ece Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Sun, 10 May 2020 12:05:14 -0600 Subject: [PATCH] Cli: Add solana supply command; hide total-supply (#9956) * Add cli supply command; hide total-supply * Use print-accounts arg instead of verbose --- cli/src/cli.rs | 9 +++++++ cli/src/cli_output.rs | 49 ++++++++++++++++++++++++++++++++++++++- cli/src/cluster_query.rs | 37 ++++++++++++++++++++++++++++- client/src/rpc_client.rs | 13 +++++++++++ client/src/rpc_request.rs | 2 ++ 5 files changed, 108 insertions(+), 2 deletions(-) diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 9789fc102..43287992b 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -201,6 +201,10 @@ pub enum CliCommand { GetSlot { commitment_config: CommitmentConfig, }, + Supply { + commitment_config: CommitmentConfig, + print_accounts: bool, + }, TotalSupply { commitment_config: CommitmentConfig, }, @@ -612,6 +616,7 @@ pub fn parse_command( }), ("epoch", Some(matches)) => parse_get_epoch(matches), ("slot", Some(matches)) => parse_get_slot(matches), + ("supply", Some(matches)) => parse_supply(matches), ("total-supply", Some(matches)) => parse_total_supply(matches), ("transaction-count", Some(matches)) => parse_get_transaction_count(matches), ("leader-schedule", Some(_matches)) => Ok(CliCommandInfo { @@ -1696,6 +1701,10 @@ pub fn process_command(config: &CliConfig) -> ProcessResult { CliCommand::GetSlot { commitment_config } => { process_get_slot(&rpc_client, *commitment_config) } + CliCommand::Supply { + commitment_config, + print_accounts, + } => process_supply(&rpc_client, config, *commitment_config, *print_accounts), CliCommand::TotalSupply { commitment_config } => { process_total_supply(&rpc_client, *commitment_config) } diff --git a/cli/src/cli_output.rs b/cli/src/cli_output.rs index 3ab15507d..06f3d8418 100644 --- a/cli/src/cli_output.rs +++ b/cli/src/cli_output.rs @@ -4,9 +4,10 @@ use console::{style, Emoji}; use inflector::cases::titlecase::to_title_case; use serde::Serialize; use serde_json::{Map, Value}; -use solana_client::rpc_response::{RpcEpochInfo, RpcKeyedAccount, RpcVoteAccountInfo}; +use solana_client::rpc_response::{RpcEpochInfo, RpcKeyedAccount, RpcSupply, RpcVoteAccountInfo}; use solana_sdk::{ clock::{self, Epoch, Slot, UnixTimestamp}, + native_token::lamports_to_sol, stake_history::StakeHistoryEntry, }; use solana_stake_program::stake_state::{Authorized, Lockup}; @@ -907,3 +908,49 @@ impl fmt::Display for CliSignature { Ok(()) } } + +#[derive(Serialize, Deserialize)] +pub struct CliSupply { + pub total: u64, + pub circulating: u64, + pub non_circulating: u64, + pub non_circulating_accounts: Vec, + #[serde(skip_serializing)] + pub print_accounts: bool, +} + +impl From for CliSupply { + fn from(rpc_supply: RpcSupply) -> Self { + Self { + total: rpc_supply.total, + circulating: rpc_supply.circulating, + non_circulating: rpc_supply.non_circulating, + non_circulating_accounts: rpc_supply.non_circulating_accounts, + print_accounts: false, + } + } +} + +impl fmt::Display for CliSupply { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + writeln_name_value(f, "Total:", &format!("{} SOL", lamports_to_sol(self.total)))?; + writeln_name_value( + f, + "Circulating:", + &format!("{} SOL", lamports_to_sol(self.circulating)), + )?; + writeln_name_value( + f, + "Non-Circulating:", + &format!("{} SOL", lamports_to_sol(self.non_circulating)), + )?; + if self.print_accounts { + writeln!(f)?; + writeln_name_value(f, "Non-Circulating Accounts:", " ")?; + for account in &self.non_circulating_accounts { + writeln!(f, " {}", account)?; + } + } + Ok(()) + } +} diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs index 4eae49ccf..aeeff8142 100644 --- a/cli/src/cluster_query.rs +++ b/cli/src/cluster_query.rs @@ -3,7 +3,7 @@ use crate::{ cli_output::*, display::println_name_value, }; -use clap::{value_t, value_t_or_exit, App, Arg, ArgMatches, SubCommand}; +use clap::{value_t, value_t_or_exit, App, AppSettings, Arg, ArgMatches, SubCommand}; use console::{style, Emoji}; use indicatif::{ProgressBar, ProgressStyle}; use solana_clap_utils::{ @@ -119,8 +119,19 @@ impl ClusterQuerySubCommands for App<'_, '_> { SubCommand::with_name("epoch").about("Get current epoch") .arg(commitment_arg()), ) + .subcommand( + SubCommand::with_name("supply").about("Get information about the cluster supply of SOL") + .arg( + Arg::with_name("print_accounts") + .long("print-accounts") + .takes_value(false) + .help("Print list of non-circualting account addresses") + ) + .arg(commitment_arg()), + ) .subcommand( SubCommand::with_name("total-supply").about("Get total number of SOL") + .setting(AppSettings::Hidden) .arg(commitment_arg()), ) .subcommand( @@ -341,6 +352,18 @@ pub fn parse_get_epoch(matches: &ArgMatches<'_>) -> Result) -> Result { + let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap(); + let print_accounts = matches.is_present("print_accounts"); + Ok(CliCommandInfo { + command: CliCommand::Supply { + commitment_config, + print_accounts, + }, + signers: vec![], + }) +} + pub fn parse_total_supply(matches: &ArgMatches<'_>) -> Result { let commitment_config = commitment_of(matches, COMMITMENT_ARG.long).unwrap(); Ok(CliCommandInfo { @@ -792,6 +815,18 @@ pub fn process_show_block_production( Ok(config.output_format.formatted_string(&block_production)) } +pub fn process_supply( + rpc_client: &RpcClient, + config: &CliConfig, + commitment_config: CommitmentConfig, + print_accounts: bool, +) -> ProcessResult { + let supply_response = rpc_client.supply_with_commitment(commitment_config.clone())?; + let mut supply: CliSupply = supply_response.value.into(); + supply.print_accounts = print_accounts; + Ok(config.output_format.formatted_string(&supply)) +} + pub fn process_total_supply( rpc_client: &RpcClient, commitment_config: CommitmentConfig, diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index 539cfde54..38cf64773 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -179,6 +179,19 @@ impl RpcClient { self.send(RpcRequest::GetSlot, json!([commitment_config]), 0) } + pub fn supply_with_commitment( + &self, + commitment_config: CommitmentConfig, + ) -> RpcResult { + let response = self + .client + .send(&RpcRequest::GetSupply, json!([commitment_config]), 0) + .map_err(|err| err.into_with_command("GetSupply"))?; + + serde_json::from_value::>(response) + .map_err(|err| ClientError::new_with_command(err.into(), "GetSupply")) + } + pub fn total_supply(&self) -> ClientResult { self.total_supply_with_commitment(CommitmentConfig::default()) } diff --git a/client/src/rpc_request.rs b/client/src/rpc_request.rs index fd02283fb..7ce48e95a 100644 --- a/client/src/rpc_request.rs +++ b/client/src/rpc_request.rs @@ -31,6 +31,7 @@ pub enum RpcRequest { GetStorageTurnRate, GetSlotsPerSegment, GetStoragePubkeysForSlot, + GetSupply, GetTotalSupply, GetTransactionCount, GetVersion, @@ -73,6 +74,7 @@ impl fmt::Display for RpcRequest { RpcRequest::GetStorageTurnRate => "getStorageTurnRate", RpcRequest::GetSlotsPerSegment => "getSlotsPerSegment", RpcRequest::GetStoragePubkeysForSlot => "getStoragePubkeysForSlot", + RpcRequest::GetSupply => "getSupply", RpcRequest::GetTotalSupply => "getTotalSupply", RpcRequest::GetTransactionCount => "getTransactionCount", RpcRequest::GetVersion => "getVersion",