CLI: Support querying FeeCalculator for a specific blockhash (bp #15555) (#15577)

* cli-output: Minor refactor of CliFees

(cherry picked from commit ebd56f7ff4)

* CLI: Support querying fees by blockhash

(cherry picked from commit 21e08b5b2c)

Co-authored-by: Trent Nelson <trent@solana.com>
This commit is contained in:
mergify[bot]
2021-02-27 20:59:54 +00:00
committed by GitHub
parent 82ba19488e
commit 5d341d9bf4
3 changed files with 119 additions and 23 deletions

View File

@ -1406,17 +1406,17 @@ impl fmt::Display for CliSupply {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct CliFees { pub struct CliFeesInner {
pub slot: Slot, pub slot: Slot,
pub blockhash: String, pub blockhash: String,
pub lamports_per_signature: u64, pub lamports_per_signature: u64,
pub last_valid_slot: Slot, pub last_valid_slot: Option<Slot>,
} }
impl QuietDisplay for CliFees {} impl QuietDisplay for CliFeesInner {}
impl VerboseDisplay for CliFees {} impl VerboseDisplay for CliFeesInner {}
impl fmt::Display for CliFees { impl fmt::Display for CliFeesInner {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln_name_value(f, "Blockhash:", &self.blockhash)?; writeln_name_value(f, "Blockhash:", &self.blockhash)?;
writeln_name_value( writeln_name_value(
@ -1424,8 +1424,51 @@ impl fmt::Display for CliFees {
"Lamports per signature:", "Lamports per signature:",
&self.lamports_per_signature.to_string(), &self.lamports_per_signature.to_string(),
)?; )?;
writeln_name_value(f, "Last valid slot:", &self.last_valid_slot.to_string())?; let last_valid_slot = self
Ok(()) .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<CliFeesInner>,
}
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<Slot>,
) -> Self {
Self {
inner: Some(CliFeesInner {
slot,
blockhash: blockhash.to_string(),
lamports_per_signature,
last_valid_slot,
}),
}
}
pub fn none() -> Self {
Self { inner: None }
} }
} }

View File

@ -90,7 +90,9 @@ pub enum CliCommand {
}, },
Feature(FeatureCliCommand), Feature(FeatureCliCommand),
Inflation(InflationCliCommand), Inflation(InflationCliCommand),
Fees, Fees {
blockhash: Option<Hash>,
},
FirstAvailableBlock, FirstAvailableBlock,
GetBlock { GetBlock {
slot: Option<Slot>, slot: Option<Slot>,
@ -593,10 +595,13 @@ pub fn parse_command(
("feature", Some(matches)) => { ("feature", Some(matches)) => {
parse_feature_subcommand(matches, default_signer, wallet_manager) parse_feature_subcommand(matches, default_signer, wallet_manager)
} }
("fees", Some(_matches)) => Ok(CliCommandInfo { ("fees", Some(matches)) => {
command: CliCommand::Fees, let blockhash = value_of::<Hash>(matches, "blockhash");
Ok(CliCommandInfo {
command: CliCommand::Fees { blockhash },
signers: vec![], signers: vec![],
}), })
}
("first-available-block", Some(_matches)) => Ok(CliCommandInfo { ("first-available-block", Some(_matches)) => Ok(CliCommandInfo {
command: CliCommand::FirstAvailableBlock, command: CliCommand::FirstAvailableBlock,
signers: vec![], signers: vec![],
@ -1263,7 +1268,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
seed, seed,
program_id, program_id,
} => process_create_address_with_seed(config, from_pubkey.as_ref(), &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) => { CliCommand::Feature(feature_subcommand) => {
process_feature_subcommand(&rpc_client, config, feature_subcommand) process_feature_subcommand(&rpc_client, config, feature_subcommand)
} }

View File

@ -134,7 +134,17 @@ impl ClusterQuerySubCommands for App<'_, '_> {
SubCommand::with_name("cluster-version") SubCommand::with_name("cluster-version")
.about("Get the version of the cluster entrypoint"), .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(
SubCommand::with_name("first-available-block") 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 { 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 result = rpc_client.get_recent_blockhash_with_commitment(config.commitment)?;
let (recent_blockhash, fee_calculator, last_valid_slot) = result.value; let (recent_blockhash, fee_calculator, last_valid_slot) = result.value;
let fees = CliFees { CliFees::some(
slot: result.context.slot, result.context.slot,
blockhash: recent_blockhash.to_string(), recent_blockhash,
lamports_per_signature: fee_calculator.lamports_per_signature, fee_calculator.lamports_per_signature,
last_valid_slot, Some(last_valid_slot),
)
}; };
Ok(config.output_format.formatted_string(&fees)) Ok(config.output_format.formatted_string(&fees))
} }
@ -1905,7 +1936,24 @@ mod tests {
assert_eq!( assert_eq!(
parse_command(&test_fees, &default_signer, &mut None).unwrap(), parse_command(&test_fees, &default_signer, &mut None).unwrap(),
CliCommandInfo { 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![], signers: vec![],
} }
); );