use std::convert::From;
use chrono::{NaiveDateTime, Utc};
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
use crate::common::*;
use crate::v2::rest::api_impl::*;
#[derive(Serialize, Debug)]
pub struct GetVIPLevels {}
impl_api!(GetVIPLevels => Vec<RespVIPLevel> : GET, "/api/v2/vip_levels");
#[derive(Serialize, Debug)]
pub struct GetVIPByLevel {
#[serde(skip)]
pub level: u8,
}
impl_api!(GetVIPByLevel => RespVIPLevel : GET, dynamic params {
api_url!(dynamic "/api/v2/vip_levels/{}", params.level)
});
#[derive(Serialize, Debug)]
pub struct GetCurrencies {}
impl_api!(GetCurrencies => Vec<CurrencyInfo> : GET, "/api/v2/currencies");
#[derive(Serialize, Debug)]
pub struct GetTimestamp {}
impl_api!(GetTimestamp => RespTimestamp : GET, "/api/v2/timestamp");
#[derive(Serialize, Debug)]
pub struct GetWithdrawalConstraints {
#[serde(skip_serializing_if = "Option::is_none")]
pub currency: Option<String>,
}
impl_api!(GetWithdrawalConstraints => Vec<WithdrawalConstraints> : GET, "/api/v2/withdrawal/constraint");
#[derive(Deserialize, Eq, PartialEq, Default, Debug)]
#[serde(default)]
pub struct RespVIPLevel {
pub level: u8,
pub minimum_trading_volume: Decimal,
pub minimum_staking_volume: Decimal,
pub maker_fee: Decimal,
pub taker_fee: Decimal,
}
#[derive(Deserialize, Eq, PartialEq, Debug)]
pub struct RespTimestamp(pub i64);
impl From<RespTimestamp> for DateTime {
fn from(resp: RespTimestamp) -> Self {
DateTime::from_utc(NaiveDateTime::from_timestamp(resp.0, 0), Utc)
}
}
#[derive(Deserialize, Eq, PartialEq, Default, Debug)]
#[serde(default)]
pub struct CurrencyInfo {
pub id: String,
pub precision: u8,
pub sygna_supported: bool,
}
#[derive(Deserialize, Eq, PartialEq, Default, Debug)]
#[serde(default)]
pub struct WithdrawalConstraints {
pub currency: String,
pub fee: Decimal,
pub ratio: Decimal,
pub min_amount: Decimal,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::util::test_util::*;
use chrono::TimeZone;
use rust_decimal_macros::dec;
use surf::Client as HTTPClient;
use surf_vcr::VcrMode;
async fn create_client(cassette: &'static str) -> HTTPClient {
let mut path_builder = test_resource_path();
path_builder.push("rest");
path_builder.push("public");
path_builder.push("misc");
path_builder.push(cassette);
create_test_recording_client(VcrMode::Replay, path_builder.as_path().to_str().unwrap())
.await
}
#[async_std::test]
async fn get_vip_level_list() {
let params = GetVIPLevels {};
let resp = create_client("get_vip_level_list.yaml")
.await
.send(params.to_request())
.await
.expect("Error while sending request");
let result = GetVIPLevels::read_response(resp.into()).await;
let levels: Vec<RespVIPLevel> = result.expect("failed to parse result");
for lv in 0..10 {
assert_eq!(levels[lv].level, lv as u8);
}
assert_eq!(
levels[4],
RespVIPLevel {
level: 4,
minimum_trading_volume: dec!(150000000),
minimum_staking_volume: dec!(10000),
maker_fee: dec!(0),
taker_fee: dec!(0.0009),
}
)
}
#[async_std::test]
async fn get_vip_by_level() {
let params = GetVIPByLevel { level: 3 };
let resp = create_client("get_vip_by_level.yaml")
.await
.send(params.to_request())
.await
.expect("Error while sending request");
let result = GetVIPByLevel::read_response(resp.into()).await;
let level: RespVIPLevel = result.expect("failed to parse result");
assert_eq!(
level,
RespVIPLevel {
level: 3,
minimum_trading_volume: dec!(30000000),
minimum_staking_volume: dec!(10000),
maker_fee: dec!(0),
taker_fee: dec!(0.00105),
}
);
}
#[async_std::test]
async fn get_currencies() {
let params = GetCurrencies {};
let resp = create_client("get_currencies.yaml")
.await
.send(params.to_request())
.await
.expect("Error while sending request");
let result = GetCurrencies::read_response(resp.into()).await;
let currencies: Vec<CurrencyInfo> = result.expect("failed to parse result");
assert_eq!(
currencies[0],
CurrencyInfo {
id: "twd".into(),
precision: 0,
sygna_supported: false
}
);
}
#[async_std::test]
async fn get_timestamp() {
let params = GetTimestamp {};
let resp = create_client("get_timestamp.yaml")
.await
.send(params.to_request())
.await
.expect("Error while sending request");
let result = GetTimestamp::read_response(resp.into()).await;
let ts: RespTimestamp = result.expect("failed to parse result");
assert_eq!(ts.0, 1636258261);
assert_eq!(Into::<DateTime>::into(ts), Utc.timestamp(1636258261, 0))
}
#[async_std::test]
async fn get_withdrawal_constraints() {
let client = create_client("get_withdrawal_constraints.yaml").await;
let params_all = GetWithdrawalConstraints { currency: None };
let resp = client
.send(params_all.to_request())
.await
.expect("Error while sending request");
let result = GetWithdrawalConstraints::read_response(resp.into()).await;
let constrains_all: Vec<WithdrawalConstraints> = result.expect("failed to parse result");
assert_eq!(constrains_all.len(), 31);
let params_single = GetWithdrawalConstraints {
currency: Some("twd".into()),
};
let resp = client
.send(params_single.to_request())
.await
.expect("Error while sending request");
let result = GetWithdrawalConstraints::read_response(resp.into()).await;
let mut constrains_single: Vec<WithdrawalConstraints> =
result.expect("failed to parse result");
assert_eq!(constrains_single.len(), 1);
let constraint_item = constrains_single.pop().unwrap();
assert_eq!(
constraint_item,
WithdrawalConstraints {
currency: "twd".into(),
fee: dec!(0),
ratio: dec!(0),
min_amount: dec!(100)
}
)
}
}