#![allow(clippy::result_large_err)]
mod error;
mod http;
mod pagination;
mod params;
mod resources;
use std::sync::Arc;
use std::time::Duration;
pub use error::{ApiError, Error};
pub use http::Quota;
pub use pagination::{AutoPager, Page, PageLinks, PageMeta};
pub use params::{Params, QueryValue};
pub use resources::{
Alarms, Calculators, Coins, Conversion, Editorial, Exchanges, GlobalMarket, Indicators,
Liquidations, Markets, Meta, NewAlarm, NewWebhook, Prices, Sentiment, Wallets, Webhooks,
};
use http::HttpClient;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
const DEFAULT_BASE_URL: &str = "https://bitculator.com";
#[derive(Clone)]
pub struct Client {
http: Arc<HttpClient>,
}
impl Client {
pub fn new(api_key: impl Into<String>) -> Self {
Self::builder(api_key).build()
}
pub fn builder(api_key: impl Into<String>) -> ClientBuilder {
ClientBuilder::new(api_key.into())
}
pub fn quota(&self) -> Option<Quota> {
self.http.quota()
}
pub fn coins(&self) -> Coins {
Coins::new(self.http.clone())
}
pub fn prices(&self) -> Prices {
Prices::new(self.http.clone())
}
pub fn markets(&self) -> Markets {
Markets::new(self.http.clone())
}
pub fn exchanges(&self) -> Exchanges {
Exchanges::new(self.http.clone())
}
pub fn wallets(&self) -> Wallets {
Wallets::new(self.http.clone())
}
pub fn global_market(&self) -> GlobalMarket {
GlobalMarket::new(self.http.clone())
}
pub fn sentiment(&self) -> Sentiment {
Sentiment::new(self.http.clone())
}
pub fn indicators(&self) -> Indicators {
Indicators::new(self.http.clone())
}
pub fn liquidations(&self) -> Liquidations {
Liquidations::new(self.http.clone())
}
pub fn conversion(&self) -> Conversion {
Conversion::new(self.http.clone())
}
pub fn calculators(&self) -> Calculators {
Calculators::new(self.http.clone())
}
pub fn editorial(&self) -> Editorial {
Editorial::new(self.http.clone())
}
pub fn alarms(&self) -> Alarms {
Alarms::new(self.http.clone())
}
pub fn webhooks(&self) -> Webhooks {
Webhooks::new(self.http.clone())
}
pub fn meta(&self) -> Meta {
Meta::new(self.http.clone())
}
}
pub struct ClientBuilder {
api_key: String,
base_url: String,
timeout: Duration,
max_retries: u32,
user_agent: String,
}
impl ClientBuilder {
fn new(api_key: String) -> Self {
ClientBuilder {
api_key,
base_url: DEFAULT_BASE_URL.to_string(),
timeout: Duration::from_secs(30),
max_retries: 2,
user_agent: format!("bitculator-rust/{VERSION}"),
}
}
pub fn base_url(mut self, url: impl Into<String>) -> Self {
self.base_url = url.into().trim_end_matches('/').to_string();
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
pub fn max_retries(mut self, retries: u32) -> Self {
self.max_retries = retries;
self
}
pub fn user_agent(mut self, ua: impl Into<String>) -> Self {
self.user_agent = ua.into();
self
}
pub fn build(self) -> Client {
if self.api_key.is_empty() {
panic!("bitculator: a Data API key is required");
}
let client = reqwest::blocking::Client::builder()
.timeout(self.timeout)
.build()
.expect("failed to build reqwest client");
Client {
http: Arc::new(HttpClient::new(
self.api_key,
self.base_url,
self.user_agent,
self.max_retries,
client,
)),
}
}
}