use bitcoin::Address;
use reqwest::{Client, Response};
use url::Url;
use crate::builder::MempoolClientBuilder;
use crate::error::Error;
use crate::response::{
AddressStats, BlockInfo, DifficultyAdjustment, FeeRecommendations, HashrateStats,
MempoolBlockFees, MempoolStats, Prices,
};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum HashratePeriod {
#[default]
ThreeDays,
OneMonth,
ThreeMonths,
SixMonths,
OneYear,
TwoYears,
ThreeYears,
AllTime,
}
impl HashratePeriod {
fn as_str(&self) -> &str {
match self {
Self::ThreeDays => "3d",
Self::OneMonth => "1m",
Self::ThreeMonths => "3m",
Self::SixMonths => "6m",
Self::OneYear => "1y",
Self::TwoYears => "2y",
Self::ThreeYears => "3y",
Self::AllTime => "all_time",
}
}
}
#[derive(Debug, Clone)]
pub struct MempoolClient {
url: Url,
client: Client,
}
impl MempoolClient {
#[inline]
pub fn new(url: Url) -> Self {
Self::builder(url).build().expect("Failed to build client")
}
#[inline]
pub fn builder(url: Url) -> MempoolClientBuilder {
MempoolClientBuilder::new(url)
}
#[inline]
pub fn from_client(url: Url, client: Client) -> Self {
Self { client, url }
}
pub async fn get_difficulty_adjustment(&self) -> Result<DifficultyAdjustment, Error> {
let url: Url = self.url.join("/api/v1/difficulty-adjustment")?;
let response: Response = self.client.get(url).send().await?;
Ok(response.json().await?)
}
pub async fn get_prices(&self) -> Result<Prices, Error> {
let url: Url = self.url.join("/api/v1/prices")?;
let response: Response = self.client.get(url).send().await?;
Ok(response.json().await?)
}
pub async fn get_address(&self, address: &Address) -> Result<AddressStats, Error> {
let url: Url = self
.url
.join("/api/address/")?
.join(address.to_string().as_str())?;
let response: Response = self.client.get(url).send().await?;
Ok(response.json().await?)
}
pub async fn get_block_tip_height(&self) -> Result<u32, Error> {
let url: Url = self.url.join("/api/blocks/tip/height")?;
let response: Response = self.client.get(url).send().await?;
Ok(response.json().await?)
}
pub async fn get_blocks(&self, start_height: Option<u32>) -> Result<Vec<BlockInfo>, Error> {
let mut url: Url = self.url.join("/api/blocks")?;
if let Some(start_height) = start_height {
url = url.join(start_height.to_string().as_str())?;
}
let response: Response = self.client.get(url).send().await?;
Ok(response.json().await?)
}
pub async fn get_hashrate(&self, period: HashratePeriod) -> Result<HashrateStats, Error> {
let url: Url = self
.url
.join("/api/v1/mining/hashrate/")?
.join(period.as_str())?;
let response: Response = self.client.get(url).send().await?;
Ok(response.json().await?)
}
pub async fn get_recommended_fees(&self) -> Result<FeeRecommendations, Error> {
let url: Url = self.url.join("/api/v1/fees/recommended")?;
let response: Response = self.client.get(url).send().await?;
Ok(response.json().await?)
}
pub async fn get_mempool(&self) -> Result<MempoolStats, Error> {
let url: Url = self.url.join("/api/mempool")?;
let response: Response = self.client.get(url).send().await?;
Ok(response.json().await?)
}
pub async fn get_mempool_blocks_fees(&self) -> Result<Vec<MempoolBlockFees>, Error> {
let url: Url = self.url.join("/api/v1/fees/mempool-blocks")?;
let response: Response = self.client.get(url).send().await?;
Ok(response.json().await?)
}
}