From 5d341d9bf41fec7cab03f681bda98fd05691cc22 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 27 Feb 2021 20:59:54 +0000 Subject: [PATCH] CLI: Support querying FeeCalculator for a specific blockhash (bp #15555) (#15577) * cli-output: Minor refactor of CliFees (cherry picked from commit ebd56f7ff421fb771a22ca8a45a1882860b5d21f) * CLI: Support querying fees by blockhash (cherry picked from commit 21e08b5b2ce4cb680b335d263f4b8bbc65af63df) Co-authored-by: Trent Nelson --- cli-output/src/cli_output.rs | 57 ++++++++++++++++++++++++++---- cli/src/cli.rs | 17 +++++---- cli/src/cluster_query.rs | 68 ++++++++++++++++++++++++++++++------ 3 files changed, 119 insertions(+), 23 deletions(-) diff --git a/cli-output/src/cli_output.rs b/cli-output/src/cli_output.rs index 6698ab00d4..9b1d343e33 100644 --- a/cli-output/src/cli_output.rs +++ b/cli-output/src/cli_output.rs @@ -1406,17 +1406,17 @@ impl fmt::Display for CliSupply { #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct CliFees { +pub struct CliFeesInner { pub slot: Slot, pub blockhash: String, pub lamports_per_signature: u64, - pub last_valid_slot: Slot, + pub last_valid_slot: Option, } -impl QuietDisplay for CliFees {} -impl VerboseDisplay for CliFees {} +impl QuietDisplay for CliFeesInner {} +impl VerboseDisplay for CliFeesInner {} -impl fmt::Display for CliFees { +impl fmt::Display for CliFeesInner { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { writeln_name_value(f, "Blockhash:", &self.blockhash)?; writeln_name_value( @@ -1424,8 +1424,51 @@ impl fmt::Display for CliFees { "Lamports per signature:", &self.lamports_per_signature.to_string(), )?; - writeln_name_value(f, "Last valid slot:", &self.last_valid_slot.to_string())?; - Ok(()) + let last_valid_slot = self + .last_valid_slot + .map(|s| s.to_string()) + .unwrap_or_default(); + writeln_name_value(f, "Last valid slot:", &last_valid_slot) + } +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CliFees { + #[serde(flatten, skip_serializing_if = "Option::is_none")] + pub inner: Option, +} + +impl QuietDisplay for CliFees {} +impl VerboseDisplay for CliFees {} + +impl fmt::Display for CliFees { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.inner.as_ref() { + Some(inner) => write!(f, "{}", inner), + None => write!(f, "Fees unavailable"), + } + } +} + +impl CliFees { + pub fn some( + slot: Slot, + blockhash: Hash, + lamports_per_signature: u64, + last_valid_slot: Option, + ) -> Self { + Self { + inner: Some(CliFeesInner { + slot, + blockhash: blockhash.to_string(), + lamports_per_signature, + last_valid_slot, + }), + } + } + pub fn none() -> Self { + Self { inner: None } } } diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 869fc77162..8a4ee194d7 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -90,7 +90,9 @@ pub enum CliCommand { }, Feature(FeatureCliCommand), Inflation(InflationCliCommand), - Fees, + Fees { + blockhash: Option, + }, FirstAvailableBlock, GetBlock { slot: Option, @@ -593,10 +595,13 @@ pub fn parse_command( ("feature", Some(matches)) => { parse_feature_subcommand(matches, default_signer, wallet_manager) } - ("fees", Some(_matches)) => Ok(CliCommandInfo { - command: CliCommand::Fees, - signers: vec![], - }), + ("fees", Some(matches)) => { + let blockhash = value_of::(matches, "blockhash"); + Ok(CliCommandInfo { + command: CliCommand::Fees { blockhash }, + signers: vec![], + }) + } ("first-available-block", Some(_matches)) => Ok(CliCommandInfo { command: CliCommand::FirstAvailableBlock, signers: vec![], @@ -1263,7 +1268,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult { seed, program_id, } => process_create_address_with_seed(config, from_pubkey.as_ref(), &seed, &program_id), - CliCommand::Fees => process_fees(&rpc_client, config), + CliCommand::Fees { ref blockhash } => process_fees(&rpc_client, config, blockhash.as_ref()), CliCommand::Feature(feature_subcommand) => { process_feature_subcommand(&rpc_client, config, feature_subcommand) } diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs index 2816bec35f..d8fc2ddbe0 100644 --- a/cli/src/cluster_query.rs +++ b/cli/src/cluster_query.rs @@ -134,7 +134,17 @@ impl ClusterQuerySubCommands for App<'_, '_> { SubCommand::with_name("cluster-version") .about("Get the version of the cluster entrypoint"), ) - .subcommand(SubCommand::with_name("fees").about("Display current cluster fees"), + .subcommand( + SubCommand::with_name("fees") + .about("Display current cluster fees") + .arg( + Arg::with_name("blockhash") + .long("blockhash") + .takes_value(true) + .value_name("BLOCKHASH") + .validator(is_hash) + .help("Query fees for BLOCKHASH instead of the the most recent blockhash") + ), ) .subcommand( SubCommand::with_name("first-available-block") @@ -820,14 +830,35 @@ pub fn process_cluster_version(rpc_client: &RpcClient, config: &CliConfig) -> Pr } } -pub fn process_fees(rpc_client: &RpcClient, config: &CliConfig) -> ProcessResult { - let result = rpc_client.get_recent_blockhash_with_commitment(config.commitment)?; - let (recent_blockhash, fee_calculator, last_valid_slot) = result.value; - let fees = CliFees { - slot: result.context.slot, - blockhash: recent_blockhash.to_string(), - lamports_per_signature: fee_calculator.lamports_per_signature, - last_valid_slot, +pub fn process_fees( + rpc_client: &RpcClient, + config: &CliConfig, + blockhash: Option<&Hash>, +) -> ProcessResult { + let fees = if let Some(recent_blockhash) = blockhash { + let result = rpc_client.get_fee_calculator_for_blockhash_with_commitment( + recent_blockhash, + config.commitment, + )?; + if let Some(fee_calculator) = result.value { + CliFees::some( + result.context.slot, + *recent_blockhash, + fee_calculator.lamports_per_signature, + None, + ) + } else { + CliFees::none() + } + } else { + let result = rpc_client.get_recent_blockhash_with_commitment(config.commitment)?; + let (recent_blockhash, fee_calculator, last_valid_slot) = result.value; + CliFees::some( + result.context.slot, + recent_blockhash, + fee_calculator.lamports_per_signature, + Some(last_valid_slot), + ) }; Ok(config.output_format.formatted_string(&fees)) } @@ -1905,7 +1936,24 @@ mod tests { assert_eq!( parse_command(&test_fees, &default_signer, &mut None).unwrap(), CliCommandInfo { - command: CliCommand::Fees, + command: CliCommand::Fees { blockhash: None }, + signers: vec![], + } + ); + + let blockhash = Hash::new_unique(); + let test_fees = test_commands.clone().get_matches_from(vec![ + "test", + "fees", + "--blockhash", + &blockhash.to_string(), + ]); + assert_eq!( + parse_command(&test_fees, &default_signer, &mut None).unwrap(), + CliCommandInfo { + command: CliCommand::Fees { + blockhash: Some(blockhash) + }, signers: vec![], } );