use query_params::QueryParams;
use serde::{Deserialize, Serialize};
use serde_with::chrono::NaiveDateTime;
use serde_with::DefaultOnNull;
use serde_with::TimestampMilliSeconds;
use typed_builder::TypedBuilder;
pub mod private;
pub mod public;
pub mod stream;
use serde_with::{serde_as, DisplayFromStr};
#[derive(derive_more::Display, Debug, Clone)]
#[display(fmt = "{_0}_{_1}")]
pub struct Pair(pub Asset, pub Asset);
impl std::str::FromStr for Pair {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let sep = s
.char_indices()
.find(|(_, c)| *c == '_')
.map(|(idx, _)| idx)
.ok_or(anyhow::anyhow!("failed to parse pair"))?;
let x = s[0..sep].parse()?;
let y = s[sep + 1..].parse()?;
Ok(Self(x, y))
}
}
#[derive(strum::EnumString, strum::Display, Debug, Clone)]
#[strum(serialize_all = "snake_case")]
pub enum Asset {
XRP,
JPY,
BTC,
LTC,
ETH,
MONA,
BCC,
XLM,
QTUM,
BAT,
OMG,
XYM,
LINK,
MKR,
BOBA,
ENJ,
MATIC,
DOT,
DOGE,
ASTR,
ADA,
AVAX,
AXS,
FLR,
SAND,
GALA,
APE,
CHZ,
OAS,
}
#[cfg(test)]
pub use Asset::*;
#[derive(strum::EnumString, strum::Display, Debug, Clone)]
#[strum(serialize_all = "snake_case")]
pub enum SortOrder {
Desc,
Asc,
}
#[derive(strum::EnumString, strum::Display, Debug, Clone)]
#[strum(serialize_all = "snake_case")]
pub enum Side {
Buy,
Sell,
}
#[derive(strum::EnumString, strum::Display, Debug, Clone)]
#[strum(serialize_all = "snake_case")]
pub enum OrderType {
Limit,
Market,
Stop,
StopLimit,
}
#[derive(strum::EnumString, Debug, Clone)]
#[strum(serialize_all = "snake_case")]
pub enum MakerTaker {
Maker,
Taker,
}
#[derive(strum::EnumString, Debug, Clone)]
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
pub enum OrderStatus {
Inactive,
Unfilled,
ParitallyFilled,
FullyFilled,
CanceledUnfilled,
CanceledPartiallyFilled,
}
#[derive(Deserialize, Debug)]
struct Response {
success: u16,
data: serde_json::Value,
}
impl Response {
fn result(self) -> anyhow::Result<serde_json::Value> {
if self.success == 1 {
Ok(self.data)
} else {
let e: ResponseError = serde_json::from_value(self.data)?;
Err(ApiError { code: e.code }.into())
}
}
}
#[derive(thiserror::Error, Debug)]
#[error("bitbank API error (code={code})")]
struct ApiError {
code: u16,
}
#[derive(Deserialize, Debug)]
struct ResponseError {
code: u16,
}