Skip to main content

asterdex_sdk/futures/endpoints/
asset.rs

1// US-015: Asset and sub-account endpoints
2
3use crate::futures::models::account::{WalletTransferParams, WalletTransferResponse};
4use crate::rest::client::RestClient;
5use crate::rest::error::AsterDexError;
6use crate::rest::response::ApiResponse;
7
8impl RestClient {
9    /// Transfer assets between wallets.
10    ///
11    /// The `transfer_type` field identifies the wallet pair (e.g. spot→futures, futures→spot).
12    /// Consult the API docs for valid values.
13    ///
14    /// # Errors
15    /// - `ConfigError` — credentials not set
16    /// - `ApiError` — invalid asset, amount, or transfer type
17    /// - `RateLimited` — HTTP 429
18    /// - `IpBanned` — HTTP 418
19    pub async fn wallet_transfer(
20        &self,
21        params: WalletTransferParams,
22    ) -> Result<ApiResponse<WalletTransferResponse>, AsterDexError> {
23        let transfer_type_str = params.transfer_type.to_string();
24        self.signed_post(
25            "/fapi/v3/asset/wallet/transfer",
26            &[
27                ("asset", params.asset.as_str()),
28                ("amount", params.amount.as_str()),
29                ("type", &transfer_type_str),
30            ],
31        )
32        .await
33    }
34
35    /// Bind a sub-account to the current account.
36    ///
37    /// The response structure is not yet documented — returned as raw JSON until API docs
38    /// are clarified. Refactor to a typed struct in a follow-up story.
39    ///
40    /// # Errors
41    /// - `ConfigError` — credentials not set
42    /// - `ApiError` — invalid sub-account UID or binding already exists
43    /// - `RateLimited` — HTTP 429
44    /// - `IpBanned` — HTTP 418
45    pub async fn sub_account_bind(
46        &self,
47        sub_uid: &str,
48    ) -> Result<ApiResponse<serde_json::Value>, AsterDexError> {
49        self.signed_post("/fapi/v3/apiKeySubAccountBindings", &[("subUid", sub_uid)])
50            .await
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    // US-015: wallet_transfer without credentials returns ConfigError
59    #[tokio::test]
60    async fn wallet_transfer_without_credentials_returns_config_error() {
61        let server = mockito::Server::new_async().await;
62        // No mock needed — error is returned before any HTTP call
63        let client = RestClient::new_public(&server.url()).unwrap();
64        let params = WalletTransferParams {
65            asset: "USDT".to_string(),
66            amount: "100.0".to_string(),
67            transfer_type: 1,
68        };
69        let result = client.wallet_transfer(params).await;
70        assert!(
71            matches!(result, Err(AsterDexError::ConfigError { .. })),
72            "expected ConfigError, got: {:?}",
73            result
74        );
75        drop(server);
76    }
77}