| @@ -16,7 +16,7 @@ use solana_drone::drone::request_airdrop_transaction; | ||||
| use solana_drone::drone_mock::request_airdrop_transaction; | ||||
| use solana_sdk::{ | ||||
|     account_utils::State, | ||||
|     bpf_loader, | ||||
|     bpf_loader, clock, | ||||
|     fee_calculator::FeeCalculator, | ||||
|     hash::Hash, | ||||
|     instruction::InstructionError, | ||||
| @@ -97,6 +97,7 @@ pub enum WalletCommand { | ||||
|     ShowStorageAccount(Pubkey), | ||||
|     Deploy(String), | ||||
|     GetSlot, | ||||
|     GetEpochInfo, | ||||
|     GetTransactionCount, | ||||
|     GetVersion, | ||||
|     Pay { | ||||
| @@ -343,6 +344,7 @@ pub fn parse_command( | ||||
|                 .to_string(), | ||||
|         )), | ||||
|         ("get-slot", Some(_matches)) => Ok(WalletCommand::GetSlot), | ||||
|         ("get-epoch-info", Some(_matches)) => Ok(WalletCommand::GetEpochInfo), | ||||
|         ("get-transaction-count", Some(_matches)) => Ok(WalletCommand::GetTransactionCount), | ||||
|         ("pay", Some(pay_matches)) => { | ||||
|             let lamports = parse_amount_lamports( | ||||
| @@ -1089,6 +1091,35 @@ fn process_get_slot(rpc_client: &RpcClient) -> ProcessResult { | ||||
|     Ok(slot.to_string()) | ||||
| } | ||||
|  | ||||
| fn process_get_epoch_info(rpc_client: &RpcClient) -> ProcessResult { | ||||
|     let epoch_info = rpc_client.get_epoch_info()?; | ||||
|     println!(); | ||||
|     println_name_value("Current epoch:", &epoch_info.epoch.to_string()); | ||||
|     println_name_value("Current slot:", &epoch_info.absolute_slot.to_string()); | ||||
|     println_name_value( | ||||
|         "Total slots in current epoch:", | ||||
|         &epoch_info.slots_in_epoch.to_string(), | ||||
|     ); | ||||
|     let remaining_slots_in_epoch = epoch_info.slots_in_epoch - epoch_info.slot_index; | ||||
|     println_name_value( | ||||
|         "Remaining slots in current epoch:", | ||||
|         &remaining_slots_in_epoch.to_string(), | ||||
|     ); | ||||
|  | ||||
|     let remaining_time_in_epoch = Duration::from_secs( | ||||
|         remaining_slots_in_epoch * clock::DEFAULT_TICKS_PER_SLOT / clock::DEFAULT_TICKS_PER_SECOND, | ||||
|     ); | ||||
|     println_name_value( | ||||
|         "Time remaining in current epoch:", | ||||
|         &format!( | ||||
|             "{} minutes, {} seconds", | ||||
|             remaining_time_in_epoch.as_secs() / 60, | ||||
|             remaining_time_in_epoch.as_secs() % 60 | ||||
|         ), | ||||
|     ); | ||||
|     Ok("".to_string()) | ||||
| } | ||||
|  | ||||
| fn process_get_transaction_count(rpc_client: &RpcClient) -> ProcessResult { | ||||
|     let transaction_count = rpc_client.get_transaction_count()?; | ||||
|     Ok(transaction_count.to_string()) | ||||
| @@ -1471,6 +1502,7 @@ pub fn process_command(config: &WalletConfig) -> ProcessResult { | ||||
|         } | ||||
|  | ||||
|         WalletCommand::GetSlot => process_get_slot(&rpc_client), | ||||
|         WalletCommand::GetEpochInfo => process_get_epoch_info(&rpc_client), | ||||
|         WalletCommand::GetTransactionCount => process_get_transaction_count(&rpc_client), | ||||
|  | ||||
|         // If client has positive balance, pay lamports to another address | ||||
| @@ -2168,6 +2200,10 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' | ||||
|             SubCommand::with_name("get-slot") | ||||
|                 .about("Get current slot"), | ||||
|         ) | ||||
|         .subcommand( | ||||
|             SubCommand::with_name("get-epoch-info") | ||||
|                 .about("Get information about the current epoch"), | ||||
|         ) | ||||
|         .subcommand( | ||||
|             SubCommand::with_name("get-transaction-count") | ||||
|                 .about("Get current transaction count"), | ||||
|   | ||||
| @@ -1,3 +1,6 @@ | ||||
| #[macro_use] | ||||
| extern crate serde_derive; | ||||
|  | ||||
| pub mod client_error; | ||||
| mod generic_rpc_client_request; | ||||
| pub mod mock_rpc_client_request; | ||||
|   | ||||
| @@ -2,23 +2,26 @@ use crate::client_error::ClientError; | ||||
| use crate::generic_rpc_client_request::GenericRpcClientRequest; | ||||
| use crate::mock_rpc_client_request::MockRpcClientRequest; | ||||
| use crate::rpc_client_request::RpcClientRequest; | ||||
| use crate::rpc_request::RpcRequest; | ||||
| use crate::rpc_request::{RpcEpochInfo, RpcRequest}; | ||||
| use bincode::serialize; | ||||
| use log::*; | ||||
| use serde_json::{json, Value}; | ||||
| use solana_sdk::account::Account; | ||||
| use solana_sdk::clock::{DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT}; | ||||
| use solana_sdk::fee_calculator::FeeCalculator; | ||||
| use solana_sdk::hash::Hash; | ||||
| use solana_sdk::inflation::Inflation; | ||||
| use solana_sdk::pubkey::Pubkey; | ||||
| use solana_sdk::signature::{KeypairUtil, Signature}; | ||||
| use solana_sdk::transaction::{self, Transaction, TransactionError}; | ||||
| use std::error; | ||||
| use std::io; | ||||
| use std::net::SocketAddr; | ||||
| use std::thread::sleep; | ||||
| use std::time::{Duration, Instant}; | ||||
| use solana_sdk::{ | ||||
|     account::Account, | ||||
|     clock::{Slot, DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT}, | ||||
|     fee_calculator::FeeCalculator, | ||||
|     hash::Hash, | ||||
|     inflation::Inflation, | ||||
|     pubkey::Pubkey, | ||||
|     signature::{KeypairUtil, Signature}, | ||||
|     transaction::{self, Transaction, TransactionError}, | ||||
| }; | ||||
| use std::{ | ||||
|     error, io, | ||||
|     net::SocketAddr, | ||||
|     thread::sleep, | ||||
|     time::{Duration, Instant}, | ||||
| }; | ||||
|  | ||||
| pub struct RpcClient { | ||||
|     client: Box<dyn GenericRpcClientRequest + Send + Sync>, | ||||
| @@ -76,7 +79,7 @@ impl RpcClient { | ||||
|         Ok(result) | ||||
|     } | ||||
|  | ||||
|     pub fn get_slot(&self) -> io::Result<u64> { | ||||
|     pub fn get_slot(&self) -> io::Result<Slot> { | ||||
|         let response = self | ||||
|             .client | ||||
|             .send(&RpcRequest::GetSlot, None, 0) | ||||
| @@ -95,6 +98,25 @@ impl RpcClient { | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub fn get_epoch_info(&self) -> io::Result<RpcEpochInfo> { | ||||
|         let response = self | ||||
|             .client | ||||
|             .send(&RpcRequest::GetEpochInfo, None, 0) | ||||
|             .map_err(|err| { | ||||
|                 io::Error::new( | ||||
|                     io::ErrorKind::Other, | ||||
|                     format!("GetEpochInfo request failure: {:?}", err), | ||||
|                 ) | ||||
|             })?; | ||||
|  | ||||
|         serde_json::from_value(response).map_err(|err| { | ||||
|             io::Error::new( | ||||
|                 io::ErrorKind::Other, | ||||
|                 format!("GetEpochInfo parse failure: {}", err), | ||||
|             ) | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub fn get_inflation(&self) -> io::Result<Inflation> { | ||||
|         let response = self | ||||
|             .client | ||||
|   | ||||
| @@ -1,6 +1,22 @@ | ||||
| use serde_json::{json, Value}; | ||||
| use std::{error, fmt}; | ||||
|  | ||||
| #[derive(Serialize, Deserialize, Clone, Debug)] | ||||
| #[serde(rename_all = "camelCase")] | ||||
| pub struct RpcEpochInfo { | ||||
|     /// The current epoch | ||||
|     pub epoch: u64, | ||||
|  | ||||
|     /// The current slot, relative to the start of the current epoch | ||||
|     pub slot_index: u64, | ||||
|  | ||||
|     /// The number of slots in this epoch | ||||
|     pub slots_in_epoch: u64, | ||||
|  | ||||
|     /// The absolute current slot | ||||
|     pub absolute_slot: u64, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum RpcRequest { | ||||
|     ConfirmTransaction, | ||||
| @@ -9,6 +25,7 @@ pub enum RpcRequest { | ||||
|     GetAccountInfo, | ||||
|     GetBalance, | ||||
|     GetClusterNodes, | ||||
|     GetEpochInfo, | ||||
|     GetGenesisBlockhash, | ||||
|     GetInflation, | ||||
|     GetNumBlocksSinceSignatureConfirmation, | ||||
| @@ -41,6 +58,7 @@ impl RpcRequest { | ||||
|             RpcRequest::GetAccountInfo => "getAccountInfo", | ||||
|             RpcRequest::GetBalance => "getBalance", | ||||
|             RpcRequest::GetClusterNodes => "getClusterNodes", | ||||
|             RpcRequest::GetEpochInfo => "getEpochInfo", | ||||
|             RpcRequest::GetGenesisBlockhash => "getGenesisBlockhash", | ||||
|             RpcRequest::GetInflation => "getInflation", | ||||
|             RpcRequest::GetNumBlocksSinceSignatureConfirmation => { | ||||
| @@ -114,6 +132,10 @@ mod tests { | ||||
|         let request = test_request.build_request_json(1, Some(addr)); | ||||
|         assert_eq!(request["method"], "getBalance"); | ||||
|  | ||||
|         let test_request = RpcRequest::GetEpochInfo; | ||||
|         let request = test_request.build_request_json(1, None); | ||||
|         assert_eq!(request["method"], "getEpochInfo"); | ||||
|  | ||||
|         let test_request = RpcRequest::GetInflation; | ||||
|         let request = test_request.build_request_json(1, None); | ||||
|         assert_eq!(request["method"], "getInflation"); | ||||
|   | ||||
| @@ -10,6 +10,7 @@ use crate::version::VERSION; | ||||
| use bincode::{deserialize, serialize}; | ||||
| use jsonrpc_core::{Error, Metadata, Result}; | ||||
| use jsonrpc_derive::rpc; | ||||
| use solana_client::rpc_request::RpcEpochInfo; | ||||
| use solana_drone::drone::request_airdrop_transaction; | ||||
| use solana_runtime::bank::Bank; | ||||
| use solana_sdk::account::Account; | ||||
| @@ -271,22 +272,6 @@ pub struct RpcVoteAccountInfo { | ||||
|     pub last_vote: u64, | ||||
| } | ||||
|  | ||||
| #[derive(Serialize, Deserialize, Clone, Debug)] | ||||
| #[serde(rename_all = "camelCase")] | ||||
| pub struct RpcEpochInfo { | ||||
|     /// The current epoch | ||||
|     pub epoch: u64, | ||||
|  | ||||
|     /// The current slot, relative to the start of the current epoch | ||||
|     pub slot_index: u64, | ||||
|  | ||||
|     /// The number of slots in this epoch | ||||
|     pub slots_in_epoch: u64, | ||||
|  | ||||
|     /// The absolute current slot | ||||
|     pub absolute_slot: u64, | ||||
| } | ||||
|  | ||||
| #[derive(Serialize, Deserialize, Clone, Debug)] | ||||
| #[serde(rename_all = "kebab-case")] | ||||
| pub struct RpcVersionInfo { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user