diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 2d472744fe..7cd1ac024c 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -186,6 +186,9 @@ pub enum CliCommand { GetSlot { commitment_config: CommitmentConfig, }, + TotalSupply { + commitment_config: CommitmentConfig, + }, GetTransactionCount { commitment_config: CommitmentConfig, }, @@ -604,6 +607,7 @@ pub fn parse_command( signers: vec![], }), ("slot", Some(matches)) => parse_get_slot(matches), + ("total-supply", Some(matches)) => parse_total_supply(matches), ("transaction-count", Some(matches)) => parse_get_transaction_count(matches), ("leader-schedule", Some(_matches)) => Ok(CliCommandInfo { command: CliCommand::LeaderSchedule, @@ -1587,6 +1591,9 @@ pub fn process_command(config: &CliConfig) -> ProcessResult { CliCommand::GetSlot { commitment_config } => { process_get_slot(&rpc_client, *commitment_config) } + CliCommand::TotalSupply { commitment_config } => { + process_total_supply(&rpc_client, *commitment_config) + } CliCommand::GetTransactionCount { commitment_config } => { process_get_transaction_count(&rpc_client, *commitment_config) } diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs index 883e1c49b3..381e0ec839 100644 --- a/cli/src/cluster_query.rs +++ b/cli/src/cluster_query.rs @@ -23,6 +23,7 @@ use solana_sdk::{ epoch_schedule::Epoch, hash::Hash, message::Message, + native_token::lamports_to_sol, pubkey::Pubkey, signature::{Keypair, Signer}, system_instruction, @@ -118,6 +119,17 @@ impl ClusterQuerySubCommands for App<'_, '_> { ), ), ) + .subcommand( + SubCommand::with_name("total-supply").about("Get total number of SOL") + .arg( + Arg::with_name("confirmed") + .long("confirmed") + .takes_value(false) + .help( + "Return count at maximum-lockout commitment level", + ), + ), + ) .subcommand( SubCommand::with_name("transaction-count").about("Get current transaction count") .alias("get-transaction-count") @@ -323,6 +335,18 @@ pub fn parse_get_slot(matches: &ArgMatches<'_>) -> Result) -> Result { + let commitment_config = if matches.is_present("confirmed") { + CommitmentConfig::default() + } else { + CommitmentConfig::recent() + }; + Ok(CliCommandInfo { + command: CliCommand::TotalSupply { commitment_config }, + signers: vec![], + }) +} + pub fn parse_get_transaction_count(matches: &ArgMatches<'_>) -> Result { let commitment_config = if matches.is_present("confirmed") { CommitmentConfig::default() @@ -756,6 +780,14 @@ pub fn process_show_block_production( Ok("".to_string()) } +pub fn process_total_supply( + rpc_client: &RpcClient, + commitment_config: CommitmentConfig, +) -> ProcessResult { + let total_supply = rpc_client.total_supply_with_commitment(commitment_config.clone())?; + Ok(format!("{} SOL", lamports_to_sol(total_supply))) +} + pub fn process_get_transaction_count( rpc_client: &RpcClient, commitment_config: CommitmentConfig, @@ -1280,6 +1312,19 @@ mod tests { } ); + let test_total_supply = test_commands + .clone() + .get_matches_from(vec!["test", "total-supply"]); + assert_eq!( + parse_command(&test_total_supply, &default_keypair_file, None).unwrap(), + CliCommandInfo { + command: CliCommand::TotalSupply { + commitment_config: CommitmentConfig::recent(), + }, + signers: vec![], + } + ); + let test_transaction_count = test_commands .clone() .get_matches_from(vec!["test", "transaction-count"]); diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index a760e155bd..477cc0f4a9 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -164,6 +164,32 @@ impl RpcClient { }) } + pub fn total_supply(&self) -> io::Result { + self.total_supply_with_commitment(CommitmentConfig::default()) + } + + pub fn total_supply_with_commitment( + &self, + commitment_config: CommitmentConfig, + ) -> io::Result { + let response = self + .client + .send(&RpcRequest::GetTotalSupply, json!([commitment_config]), 0) + .map_err(|err| { + io::Error::new( + io::ErrorKind::Other, + format!("GetTotalSupply request failure: {:?}", err), + ) + })?; + + serde_json::from_value(response).map_err(|err| { + io::Error::new( + io::ErrorKind::Other, + format!("GetTotalSupply parse failure: {}", err), + ) + }) + } + pub fn get_vote_accounts(&self) -> io::Result { self.get_vote_accounts_with_commitment(CommitmentConfig::default()) } diff --git a/client/src/rpc_request.rs b/client/src/rpc_request.rs index d10ec03d83..cc0564170a 100644 --- a/client/src/rpc_request.rs +++ b/client/src/rpc_request.rs @@ -30,6 +30,7 @@ pub enum RpcRequest { GetStorageTurnRate, GetSlotsPerSegment, GetStoragePubkeysForSlot, + GetTotalSupply, GetTransactionCount, GetVersion, GetVoteAccounts, @@ -74,6 +75,7 @@ impl RpcRequest { RpcRequest::GetStorageTurnRate => "getStorageTurnRate", RpcRequest::GetSlotsPerSegment => "getSlotsPerSegment", RpcRequest::GetStoragePubkeysForSlot => "getStoragePubkeysForSlot", + RpcRequest::GetTotalSupply => "getTotalSupply", RpcRequest::GetTransactionCount => "getTransactionCount", RpcRequest::GetVersion => "getVersion", RpcRequest::GetVoteAccounts => "getVoteAccounts",