use crate::client::Client;
use crate::error::Result;
use crate::models::wallet::{
AccountSnapshot, AccountSnapshotType, AccountStatus, ApiKeyPermissions, ApiTradingStatus,
AssetDetail, CoinInfo, DepositAddress, DepositRecord, FundingAsset, SystemStatus, TradeFee,
TransferHistory, TransferResponse, UniversalTransferType, WalletBalance, WithdrawRecord,
WithdrawResponse,
};
const SAPI_V1_SYSTEM_STATUS: &str = "/sapi/v1/system/status";
const SAPI_V1_CAPITAL_CONFIG_GETALL: &str = "/sapi/v1/capital/config/getall";
const SAPI_V1_ACCOUNT_SNAPSHOT: &str = "/sapi/v1/accountSnapshot";
const SAPI_V1_CAPITAL_DEPOSIT_HISREC: &str = "/sapi/v1/capital/deposit/hisrec";
const SAPI_V1_CAPITAL_DEPOSIT_ADDRESS: &str = "/sapi/v1/capital/deposit/address";
const SAPI_V1_CAPITAL_WITHDRAW_APPLY: &str = "/sapi/v1/capital/withdraw/apply";
const SAPI_V1_CAPITAL_WITHDRAW_HISTORY: &str = "/sapi/v1/capital/withdraw/history";
const SAPI_V1_ASSET_ASSET_DETAIL: &str = "/sapi/v1/asset/assetDetail";
const SAPI_V1_ASSET_TRADE_FEE: &str = "/sapi/v1/asset/tradeFee";
const SAPI_V1_ASSET_TRANSFER: &str = "/sapi/v1/asset/transfer";
const SAPI_V1_ASSET_GET_FUNDING_ASSET: &str = "/sapi/v1/asset/get-funding-asset";
const SAPI_V1_ASSET_WALLET_BALANCE: &str = "/sapi/v1/asset/wallet/balance";
const SAPI_V1_ACCOUNT_STATUS: &str = "/sapi/v1/account/status";
const SAPI_V1_ACCOUNT_API_TRADING_STATUS: &str = "/sapi/v1/account/apiTradingStatus";
const SAPI_V1_ACCOUNT_API_RESTRICTIONS: &str = "/sapi/v1/account/apiRestrictions";
#[derive(Clone)]
pub struct Wallet {
pub(crate) client: Client,
}
impl Wallet {
pub(crate) fn new(client: Client) -> Self {
Self { client }
}
pub async fn system_status(&self) -> Result<SystemStatus> {
self.client.get(SAPI_V1_SYSTEM_STATUS, None).await
}
pub async fn all_coins(&self) -> Result<Vec<CoinInfo>> {
self.client
.get_signed(SAPI_V1_CAPITAL_CONFIG_GETALL, &[])
.await
}
pub async fn account_snapshot(
&self,
snapshot_type: AccountSnapshotType,
start_time: Option<u64>,
end_time: Option<u64>,
limit: Option<u32>,
) -> Result<AccountSnapshot> {
let type_str = match snapshot_type {
AccountSnapshotType::Spot => "SPOT",
AccountSnapshotType::Margin => "MARGIN",
AccountSnapshotType::Futures => "FUTURES",
};
let mut params: Vec<(&str, String)> = vec![("type", type_str.to_string())];
if let Some(st) = start_time {
params.push(("startTime", st.to_string()));
}
if let Some(et) = end_time {
params.push(("endTime", et.to_string()));
}
if let Some(l) = limit {
params.push(("limit", l.to_string()));
}
let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
self.client
.get_signed(SAPI_V1_ACCOUNT_SNAPSHOT, ¶ms_ref)
.await
}
pub async fn deposit_address(
&self,
coin: &str,
network: Option<&str>,
) -> Result<DepositAddress> {
let mut params: Vec<(&str, String)> = vec![("coin", coin.to_string())];
if let Some(n) = network {
params.push(("network", n.to_string()));
}
let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
self.client
.get_signed(SAPI_V1_CAPITAL_DEPOSIT_ADDRESS, ¶ms_ref)
.await
}
pub async fn deposit_history(
&self,
coin: Option<&str>,
status: Option<u32>,
start_time: Option<u64>,
end_time: Option<u64>,
offset: Option<u32>,
limit: Option<u32>,
) -> Result<Vec<DepositRecord>> {
let mut params: Vec<(&str, String)> = vec![];
if let Some(c) = coin {
params.push(("coin", c.to_string()));
}
if let Some(s) = status {
params.push(("status", s.to_string()));
}
if let Some(st) = start_time {
params.push(("startTime", st.to_string()));
}
if let Some(et) = end_time {
params.push(("endTime", et.to_string()));
}
if let Some(o) = offset {
params.push(("offset", o.to_string()));
}
if let Some(l) = limit {
params.push(("limit", l.to_string()));
}
let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
self.client
.get_signed(SAPI_V1_CAPITAL_DEPOSIT_HISREC, ¶ms_ref)
.await
}
pub async fn withdraw(
&self,
coin: &str,
address: &str,
amount: &str,
network: Option<&str>,
address_tag: Option<&str>,
withdraw_order_id: Option<&str>,
) -> Result<WithdrawResponse> {
let mut params: Vec<(&str, String)> = vec![
("coin", coin.to_string()),
("address", address.to_string()),
("amount", amount.to_string()),
];
if let Some(n) = network {
params.push(("network", n.to_string()));
}
if let Some(tag) = address_tag {
params.push(("addressTag", tag.to_string()));
}
if let Some(id) = withdraw_order_id {
params.push(("withdrawOrderId", id.to_string()));
}
let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
self.client
.post_signed(SAPI_V1_CAPITAL_WITHDRAW_APPLY, ¶ms_ref)
.await
}
#[allow(clippy::too_many_arguments)]
pub async fn withdraw_history(
&self,
coin: Option<&str>,
withdraw_order_id: Option<&str>,
status: Option<u32>,
start_time: Option<u64>,
end_time: Option<u64>,
offset: Option<u32>,
limit: Option<u32>,
) -> Result<Vec<WithdrawRecord>> {
let mut params: Vec<(&str, String)> = vec![];
if let Some(c) = coin {
params.push(("coin", c.to_string()));
}
if let Some(id) = withdraw_order_id {
params.push(("withdrawOrderId", id.to_string()));
}
if let Some(s) = status {
params.push(("status", s.to_string()));
}
if let Some(st) = start_time {
params.push(("startTime", st.to_string()));
}
if let Some(et) = end_time {
params.push(("endTime", et.to_string()));
}
if let Some(o) = offset {
params.push(("offset", o.to_string()));
}
if let Some(l) = limit {
params.push(("limit", l.to_string()));
}
let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
self.client
.get_signed(SAPI_V1_CAPITAL_WITHDRAW_HISTORY, ¶ms_ref)
.await
}
pub async fn asset_detail(
&self,
asset: Option<&str>,
) -> Result<std::collections::HashMap<String, AssetDetail>> {
let mut params: Vec<(&str, String)> = vec![];
if let Some(a) = asset {
params.push(("asset", a.to_string()));
}
let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
self.client
.get_signed(SAPI_V1_ASSET_ASSET_DETAIL, ¶ms_ref)
.await
}
pub async fn trade_fee(&self, symbol: Option<&str>) -> Result<Vec<TradeFee>> {
let mut params: Vec<(&str, String)> = vec![];
if let Some(s) = symbol {
params.push(("symbol", s.to_string()));
}
let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
self.client
.get_signed(SAPI_V1_ASSET_TRADE_FEE, ¶ms_ref)
.await
}
pub async fn universal_transfer(
&self,
transfer_type: UniversalTransferType,
asset: &str,
amount: &str,
from_symbol: Option<&str>,
to_symbol: Option<&str>,
) -> Result<TransferResponse> {
let type_str = transfer_type.as_str().to_string();
let mut params: Vec<(&str, String)> = vec![
("type", type_str),
("asset", asset.to_string()),
("amount", amount.to_string()),
];
if let Some(from) = from_symbol {
params.push(("fromSymbol", from.to_string()));
}
if let Some(to) = to_symbol {
params.push(("toSymbol", to.to_string()));
}
let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
self.client
.post_signed(SAPI_V1_ASSET_TRANSFER, ¶ms_ref)
.await
}
pub async fn transfer_history(
&self,
transfer_type: UniversalTransferType,
start_time: Option<u64>,
end_time: Option<u64>,
current: Option<u32>,
size: Option<u32>,
) -> Result<TransferHistory> {
let type_str = transfer_type.as_str().to_string();
let mut params: Vec<(&str, String)> = vec![("type", type_str)];
if let Some(st) = start_time {
params.push(("startTime", st.to_string()));
}
if let Some(et) = end_time {
params.push(("endTime", et.to_string()));
}
if let Some(c) = current {
params.push(("current", c.to_string()));
}
if let Some(s) = size {
params.push(("size", s.to_string()));
}
let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
self.client
.get_signed(SAPI_V1_ASSET_TRANSFER, ¶ms_ref)
.await
}
pub async fn funding_wallet(
&self,
asset: Option<&str>,
need_btc_valuation: Option<bool>,
) -> Result<Vec<FundingAsset>> {
let mut params: Vec<(&str, String)> = vec![];
if let Some(a) = asset {
params.push(("asset", a.to_string()));
}
if let Some(btc) = need_btc_valuation {
params.push(("needBtcValuation", btc.to_string()));
}
let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
self.client
.post_signed(SAPI_V1_ASSET_GET_FUNDING_ASSET, ¶ms_ref)
.await
}
pub async fn wallet_balance(&self) -> Result<Vec<WalletBalance>> {
self.client
.get_signed(SAPI_V1_ASSET_WALLET_BALANCE, &[])
.await
}
pub async fn account_status(&self) -> Result<AccountStatus> {
self.client.get_signed(SAPI_V1_ACCOUNT_STATUS, &[]).await
}
pub async fn api_trading_status(&self) -> Result<ApiTradingStatus> {
self.client
.get_signed(SAPI_V1_ACCOUNT_API_TRADING_STATUS, &[])
.await
}
pub async fn api_key_permissions(&self) -> Result<ApiKeyPermissions> {
self.client
.get_signed(SAPI_V1_ACCOUNT_API_RESTRICTIONS, &[])
.await
}
}