use chrono::serde as chrono_serde;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
use crate::common::*;
use crate::v2::rest::api_impl::*;
#[derive(Serialize, Debug)]
pub struct GetDeposits {
pub currency: String,
#[serde(
rename = "from",
skip_serializing_if = "Option::is_none",
with = "chrono_serde::ts_seconds_option"
)]
pub from_timestamp: Option<DateTime>,
#[serde(
rename = "to",
skip_serializing_if = "Option::is_none",
with = "chrono_serde::ts_seconds_option"
)]
pub to_timestamp: Option<DateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<DepositState>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pagination: Option<bool>,
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub page_params: Option<PageParams>,
#[serde(skip_serializing_if = "Option::is_none")]
pub offset: Option<u64>,
}
impl_api!(GetDeposits => Vec<RespDepositRecord> : auth GET, "/api/v2/deposits");
#[derive(Serialize, Debug)]
pub struct GetDepositDetail {
pub txid: String,
}
impl_api!(GetDepositDetail => RespDepositRecord : auth GET, "/api/v2/deposit");
#[derive(Serialize, Debug)]
pub struct GetDepositAddresses {
pub currency: String,
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub pagination: Option<bool>,
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub page_params: Option<PageParams>,
#[serde(skip_serializing_if = "Option::is_none")]
pub offset: Option<u64>,
}
impl_api!(GetDepositAddresses => Vec<DepositAddress> : auth GET, "/api/v2/deposit_addresses");
#[derive(Serialize, Eq, PartialEq, Debug)]
pub struct CreateDepositAddress {
pub currency: String,
}
impl_api!(CreateDepositAddress => Vec<DepositAddress> : auth POST, "/api/v2/deposit_addresses");
#[derive(Deserialize, Default, Eq, PartialEq, Debug)]
#[serde(default)]
pub struct RespDepositRecord {
pub uuid: String,
pub currency: String,
pub currency_version: String,
pub amount: Decimal,
pub fee: Decimal,
pub txid: String,
#[serde(with = "chrono_serde::ts_seconds_option")]
pub created_at: Option<DateTime>,
pub confirmations: u64,
#[serde(with = "chrono_serde::ts_seconds_option")]
pub updated_at: Option<DateTime>,
pub state: DepositState,
}
#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum DepositState {
Submitting,
Cancelled,
Submitted,
Suspended,
Rejected,
Accepted,
Checking,
Refunded,
Suspect,
RefundCanceled,
Unknown,
}
impl DepositState {
pub fn is_unknown(&self) -> bool {
self == &Self::Unknown
}
}
impl Default for DepositState {
fn default() -> Self {
Self::Unknown
}
}
#[derive(Deserialize, Eq, PartialEq, Default, Debug)]
#[serde(default)]
pub struct DepositAddress {
pub sn: String,
pub composite_currency: String,
pub version: Option<String>,
pub currency: String,
pub address: String,
pub label: Option<String>,
#[serde(rename = "type")]
pub wallet_type: String,
#[serde(with = "chrono_serde::ts_seconds_option")]
pub created_at: Option<DateTime>,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::util::test_util::*;
use chrono::{TimeZone, Utc};
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("private");
path_builder.push("deposit");
path_builder.push(cassette);
create_test_recording_client(VcrMode::Replay, path_builder.as_path().to_str().unwrap())
.await
}
#[async_std::test]
async fn get_deposits() {
let params = GetDeposits {
currency: "twd".to_string(),
from_timestamp: None,
to_timestamp: None,
state: None,
pagination: None,
page_params: None,
offset: None,
};
let resp = create_client("get_deposits.yaml")
.await
.send(params.to_request(&TEST_CREDENTIALS))
.await
.expect("Error while sending request");
let result = GetDeposits::read_response(resp.into()).await;
let history: Vec<RespDepositRecord> = result.expect("failed to parse result");
assert_eq!(history.len(), 27);
}
#[async_std::test]
async fn get_deposit_detail() {
let params = GetDepositDetail {
txid: "20201222-2-30388-1024064000298304-1893115".into(),
};
let resp = create_client("get_deposit_detail.yaml")
.await
.send(params.to_request(&TEST_CREDENTIALS))
.await
.expect("Error while sending request");
let result = GetDepositDetail::read_response(resp.into()).await;
let detail: RespDepositRecord = result.expect("failed to parse result");
assert_eq!(
detail,
RespDepositRecord {
uuid: "(test erased uuid)".into(),
currency: "twd".into(),
currency_version: "twd".into(),
amount: dec!(50000.0),
fee: dec!(0),
txid: "(test erased txid)".into(),
created_at: Some(Utc.timestamp(1608626791, 0)),
confirmations: 0,
updated_at: Some(Utc.timestamp(1608626791, 0)),
state: DepositState::Accepted,
}
);
}
#[async_std::test]
async fn get_deposit_addresses() {
let params = GetDepositAddresses {
currency: "btc".into(),
pagination: None,
page_params: None,
offset: None,
};
let resp = create_client("get_deposit_addresses.yaml")
.await
.send(params.to_request(&TEST_CREDENTIALS))
.await
.expect("Error while sending request");
let result = GetDepositAddresses::read_response(resp.into()).await;
let addr_list: Vec<DepositAddress> = result.expect("failed to parse result");
assert_eq!(
addr_list,
vec![DepositAddress {
sn: "(test erased sn)".into(),
composite_currency: "btc".into(),
version: None,
currency: "btc".into(),
address: "(test erased address)".into(),
label: None,
wallet_type: "exchange".into(),
created_at: Some(Utc.timestamp(1599742451, 0)),
}]
);
}
#[async_std::test]
async fn create_deposit_addresses() {
let params = CreateDepositAddress {
currency: "btc".into(),
};
let resp = create_client("create_deposit_addresses.yaml")
.await
.send(params.to_request(&TEST_CREDENTIALS))
.await
.expect("Error while sending request");
let result = CreateDepositAddress::read_response(resp.into()).await;
let addr_list: Vec<DepositAddress> = result.expect("failed to parse result");
assert_eq!(
addr_list,
vec![DepositAddress {
sn: "(test erased sn)".into(),
composite_currency: "btc".into(),
version: None,
currency: "btc".into(),
address: "(test erased address)".into(),
label: None,
wallet_type: "exchange".into(),
created_at: Some(Utc.timestamp(1599742451, 0)),
}]
);
}
}