use serde::{Deserialize, Serialize};
use serde_json::value::to_raw_value;
use std::fmt;
use crate::{client::Client, command::CallableCommand, Blockhash};
use super::request::request;
type BlockHeight = u64;
pub enum TargetBlockArgument {
Hash(Blockhash),
Height(BlockHeight),
}
#[derive(Serialize, Deserialize, Debug)]
pub enum StatsArgumentChoices {
AvgFee,
AvgTxSize,
Blockhash,
FeeRatePercentiles,
Height,
Ins,
MaxFee,
MaxFeeRate,
MaxTxSize,
MedianFee,
MedianTime,
MedianTxSize,
MinFee,
MinFeeRate,
MinTxSize,
Outs,
Subsidy,
SwTotalSize,
SwTotalWeight,
SwTxs,
Time,
TotalOut,
TotalSize,
TotalWeight,
TotalFee,
Txs,
UtxoIncrease,
UtxoSizeInc,
}
impl fmt::Display for StatsArgumentChoices {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
StatsArgumentChoices::AvgFee => write!(f, "avgfee"),
StatsArgumentChoices::AvgTxSize => write!(f, "avgtxsize"),
StatsArgumentChoices::Blockhash => write!(f, "blockhash"),
StatsArgumentChoices::FeeRatePercentiles => write!(f, "feerate_percentiles"),
StatsArgumentChoices::Height => write!(f, "height"),
StatsArgumentChoices::Ins => write!(f, "ins"),
StatsArgumentChoices::MaxFee => write!(f, "maxfee"),
StatsArgumentChoices::MaxFeeRate => write!(f, "maxfeerate"),
StatsArgumentChoices::MaxTxSize => write!(f, "maxtxsize"),
StatsArgumentChoices::MedianFee => write!(f, "medianfee"),
StatsArgumentChoices::MedianTime => write!(f, "mediantime"),
StatsArgumentChoices::MedianTxSize => write!(f, "mediantxsize"),
StatsArgumentChoices::MinFee => write!(f, "minfee"),
StatsArgumentChoices::MinFeeRate => write!(f, "minfeerate"),
StatsArgumentChoices::MinTxSize => write!(f, "mintxsize"),
StatsArgumentChoices::Outs => write!(f, "outs"),
StatsArgumentChoices::Subsidy => write!(f, "subsidy"),
StatsArgumentChoices::SwTotalSize => write!(f, "swtotal_size"),
StatsArgumentChoices::SwTotalWeight => write!(f, "swtotal_weight"),
StatsArgumentChoices::SwTxs => write!(f, "swtxs"),
StatsArgumentChoices::Time => write!(f, "time"),
StatsArgumentChoices::TotalOut => write!(f, "total_out"),
StatsArgumentChoices::TotalSize => write!(f, "total_size"),
StatsArgumentChoices::TotalWeight => write!(f, "total_weight"),
StatsArgumentChoices::TotalFee => write!(f, "totalfee"),
StatsArgumentChoices::Txs => write!(f, "txs"),
StatsArgumentChoices::UtxoIncrease => write!(f, "utxo_increase"),
StatsArgumentChoices::UtxoSizeInc => write!(f, "utxo_size_inc"),
}
}
}
pub struct GetBlockStatsCommand {
target_block: TargetBlockArgument,
stats: Vec<StatsArgumentChoices>,
}
impl GetBlockStatsCommand {
pub fn new(target_block: TargetBlockArgument) -> Self {
GetBlockStatsCommand {
target_block,
stats: vec![],
}
}
pub fn add_selective_stats(
&mut self,
stats_argument_choices: Vec<StatsArgumentChoices>,
) -> &Self {
self.stats = stats_argument_choices;
self
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GetBlockStatsCommandWithSelectiveStatsResponse {
pub avgfee: Option<u64>, pub avgfeerate: Option<u64>, pub avgtxsize: Option<u64>, pub blockhash: Option<String>, pub feerate_percentiles: Option<[u64; 5]>, pub height: Option<u64>, pub ins: Option<u64>, pub maxfee: Option<u64>, pub maxfeerate: Option<u64>, pub maxtxsize: Option<u64>, pub medianfee: Option<u64>, pub mediantime: Option<u64>, pub mediantxsize: Option<u64>, pub minfee: Option<u64>, pub minfeerate: Option<u64>, pub mintxsize: Option<u64>, pub outs: Option<u64>, pub subsidy: Option<u64>, pub swtotal_size: Option<u64>, pub swtotal_weight: Option<u64>, pub swtxs: Option<u64>, pub time: Option<u64>, pub total_out: Option<u64>, pub total_size: Option<u64>, pub total_weight: Option<u64>, pub totalfee: Option<u64>, pub txs: Option<u64>, pub utxo_increase: Option<u64>, pub utxo_size_inc: Option<u64>, }
#[derive(Serialize, Deserialize, Debug)]
pub struct GetBlockStatsCommandWithAllStatsResponse {
pub avgfee: u64, pub avgfeerate: u64, pub avgtxsize: u64, pub blockhash: String, pub feerate_percentiles: [u64; 5], pub height: u64, pub ins: u64, pub maxfee: u64, pub maxfeerate: u64, pub maxtxsize: u64, pub medianfee: u64, pub mediantime: u64, pub mediantxsize: u64, pub minfee: u64, pub minfeerate: u64, pub mintxsize: u64, pub outs: u64, pub subsidy: u64, pub swtotal_size: u64, pub swtotal_weight: u64, pub swtxs: u64, pub time: u64, pub total_out: u64, pub total_size: u64, pub total_weight: u64, pub totalfee: u64, pub txs: u64, pub utxo_increase: i64, pub utxo_size_inc: i64, }
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
#[serde(untagged)]
pub enum GetBlockStatsCommandResponse {
SelectiveStats(GetBlockStatsCommandWithSelectiveStatsResponse),
AllStats(GetBlockStatsCommandWithAllStatsResponse),
}
impl CallableCommand for GetBlockStatsCommand {
type Response = GetBlockStatsCommandResponse;
fn call(&self, client: &Client) -> Result<Self::Response, jsonrpc::Error> {
let target_block = &self.target_block;
let hash_or_height_arg_raw_value = match target_block {
TargetBlockArgument::Hash(hash) => to_raw_value(&hash).unwrap(),
TargetBlockArgument::Height(height) => to_raw_value(&height).unwrap(),
};
let stats_arg: Vec<String> = self.stats.iter().map(|stat| stat.to_string()).collect();
let stats_arg_raw_value = to_raw_value(&stats_arg).unwrap();
let command = "getblockstats";
let params = vec![hash_or_height_arg_raw_value, stats_arg_raw_value];
let r = request(client, command, params);
let response: GetBlockStatsCommandResponse = if stats_arg.is_empty() {
GetBlockStatsCommandResponse::AllStats(r.result()?)
} else {
GetBlockStatsCommandResponse::SelectiveStats(r.result()?)
};
Ok(response)
}
}