Skip to main content

bybit_api/api/
asset.rs

1//! Asset API endpoints.
2
3use crate::client::BybitClient;
4use crate::error::Result;
5use crate::models::asset::*;
6use tracing::info;
7use uuid::Uuid;
8
9impl BybitClient {
10    /// Get coin info.
11    ///
12    /// # Arguments
13    /// * `coin` - Optional coin filter
14    pub async fn get_coin_info(&self, coin: Option<&str>) -> Result<CoinInfoResponse> {
15        let mut params = vec![];
16
17        if let Some(c) = coin {
18            params.push(("coin", c));
19        }
20
21        self.get("/v5/asset/coin/query-info", &params).await
22    }
23
24    /// Internal transfer between accounts.
25    ///
26    /// # Arguments
27    /// * `coin` - Coin to transfer
28    /// * `amount` - Amount to transfer
29    /// * `from_account` - Source account type
30    /// * `to_account` - Destination account type
31    pub async fn internal_transfer(
32        &self,
33        coin: &str,
34        amount: &str,
35        from_account: &str,
36        to_account: &str,
37    ) -> Result<TransferResponse> {
38        let params = InternalTransferParams {
39            transfer_id: Uuid::new_v4().to_string(),
40            coin: coin.to_string(),
41            amount: amount.to_string(),
42            from_account_type: from_account.to_string(),
43            to_account_type: to_account.to_string(),
44        };
45
46        // Validate parameters
47        params.validate()?;
48
49        info!(
50            coin = %coin,
51            amount = %amount,
52            from = %from_account,
53            to = %to_account,
54            "Internal transfer"
55        );
56
57        self.post("/v5/asset/transfer/inter-transfer", &params)
58            .await
59    }
60
61    /// Get internal transfer list.
62    ///
63    /// # Arguments
64    /// * `coin` - Optional coin filter
65    /// * `limit` - Optional limit (default 20)
66    pub async fn get_internal_transfer_list(
67        &self,
68        coin: Option<&str>,
69        limit: Option<u32>,
70    ) -> Result<TransferList> {
71        let limit_str = limit.unwrap_or(20).to_string();
72        let mut params = vec![("limit", limit_str.as_str())];
73
74        if let Some(c) = coin {
75            params.push(("coin", c));
76        }
77
78        self.get("/v5/asset/transfer/query-inter-transfer-list", &params)
79            .await
80    }
81
82    /// Get deposit address.
83    ///
84    /// # Arguments
85    /// * `coin` - Coin name
86    /// * `chain_type` - Optional chain type
87    pub async fn get_deposit_address(
88        &self,
89        coin: &str,
90        chain_type: Option<&str>,
91    ) -> Result<DepositAddressResponse> {
92        let mut params = vec![("coin", coin)];
93
94        if let Some(ct) = chain_type {
95            params.push(("chainType", ct));
96        }
97
98        self.get("/v5/asset/deposit/query-address", &params).await
99    }
100
101    /// Get deposit records.
102    ///
103    /// # Arguments
104    /// * `coin` - Optional coin filter
105    /// * `limit` - Optional limit (default 50)
106    pub async fn get_deposit_records(
107        &self,
108        coin: Option<&str>,
109        limit: Option<u32>,
110    ) -> Result<DepositRecords> {
111        let limit_str = limit.unwrap_or(50).to_string();
112        let mut params = vec![("limit", limit_str.as_str())];
113
114        if let Some(c) = coin {
115            params.push(("coin", c));
116        }
117
118        self.get("/v5/asset/deposit/query-record", &params).await
119    }
120
121    /// Withdraw funds (REQUIRES STRICT VALIDATION).
122    ///
123    /// # Arguments
124    /// * `params` - Withdraw parameters
125    ///
126    /// # Safety
127    /// This function validates all parameters before sending to prevent fund loss.
128    pub async fn withdraw(&self, params: WithdrawParams) -> Result<WithdrawResponse> {
129        // CRITICAL: Validate all parameters (fund safety)
130        params.validate()?;
131
132        info!(
133            coin = %params.coin,
134            chain = %params.chain,
135            address = %params.address,
136            amount = %params.amount,
137            "Initiating withdrawal"
138        );
139
140        self.post("/v5/asset/withdraw/create", &params).await
141    }
142
143    /// Cancel a pending withdrawal.
144    ///
145    /// # Arguments
146    /// * `withdraw_id` - Withdraw ID to cancel
147    pub async fn cancel_withdraw(&self, withdraw_id: &str) -> Result<serde_json::Value> {
148        let params = CancelWithdrawParams {
149            id: withdraw_id.to_string(),
150        };
151
152        info!(withdraw_id = %withdraw_id, "Cancelling withdrawal");
153
154        self.post("/v5/asset/withdraw/cancel", &params).await
155    }
156
157    /// Get withdraw records.
158    ///
159    /// # Arguments
160    /// * `coin` - Optional coin filter
161    /// * `limit` - Optional limit (default 50)
162    pub async fn get_withdraw_records(
163        &self,
164        coin: Option<&str>,
165        limit: Option<u32>,
166    ) -> Result<WithdrawRecords> {
167        let limit_str = limit.unwrap_or(50).to_string();
168        let mut params = vec![("limit", limit_str.as_str())];
169
170        if let Some(c) = coin {
171            params.push(("coin", c));
172        }
173
174        self.get("/v5/asset/withdraw/query-record", &params).await
175    }
176
177    /// Get withdrawable amount.
178    ///
179    /// # Arguments
180    /// * `coin` - Coin name
181    pub async fn get_withdrawable_amount(&self, coin: &str) -> Result<WithdrawableAmount> {
182        let params = vec![("coin", coin)];
183
184        self.get("/v5/asset/withdraw/withdrawable-amount", &params)
185            .await
186    }
187}