use reqwest::header::HeaderMap;
use std::{collections::HashMap, fmt};
use crate::{
api::{private::PrivateMethod, public::PublicMethod, ApiKind},
KRAKEN_DOMAIN,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ApiBuilder {
pub(crate) kind: ApiKind,
pub(crate) domain: String,
pub(crate) version: String,
pub(crate) path: String,
pub(crate) method: String,
pub(crate) params: HashMap<String, String>,
pub(crate) headers: HeaderMap,
}
impl fmt::Display for ApiBuilder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.url())?;
if self.kind == ApiKind::Private && !self.params.is_empty() {
write!(f, "?{}", self.params())?;
}
Ok(())
}
}
impl ApiBuilder {
fn with_method(kind: ApiKind, method: impl fmt::Display) -> Self {
Self {
kind,
domain: KRAKEN_DOMAIN.into(),
version: "0".into(),
path: kind.to_string(),
method: method.to_string(),
params: HashMap::default(),
headers: HeaderMap::default(),
}
}
pub fn with(
mut self,
key: impl fmt::Display,
value: impl fmt::Display,
) -> Self {
self.params.insert(key.to_string(), value.to_string());
self
}
pub fn with_mut(
&mut self,
key: impl fmt::Display,
value: impl fmt::Display,
) -> &mut Self {
self.params.insert(key.to_string(), value.to_string());
self
}
pub(crate) fn public(method: PublicMethod) -> Self {
Self::with_method(ApiKind::Public, method)
}
pub(crate) fn private(method: PrivateMethod) -> Self {
Self::with_method(ApiKind::Private, method)
}
pub(crate) fn uri_path(&self) -> String {
format!("/{}/{}/{}", self.version, self.path, self.method)
}
pub(crate) fn url(&self) -> String {
let mut url = format!("{}{}", self.domain, self.uri_path());
if self.kind == ApiKind::Public && !self.params.is_empty() {
url.push_str(&format!("?{}", self.params()));
}
url
}
fn params(&self) -> String {
let mut params = String::new();
for (key, value) in &self.params {
params.push_str(&format!("{}={}&", key, value));
}
params.pop();
params
}
}