Skip to main content

ccxt_exchanges/bitget/rest/futures/
leverage.rs

1//! Leverage operations for Bitget futures/swap.
2
3use super::super::super::signed_request::HttpMethod;
4use super::super::super::{Bitget, symbol::BitgetSymbolConverter};
5use ccxt_core::{Error, ParseError, Result};
6
7impl Bitget {
8    /// Set leverage for a symbol.
9    ///
10    /// Uses Bitget POST `/api/v2/mix/account/set-leverage` endpoint.
11    pub async fn set_leverage_impl(
12        &self,
13        symbol: &str,
14        leverage: u32,
15        margin_mode: Option<&str>,
16    ) -> Result<()> {
17        let exchange_id = BitgetSymbolConverter::unified_to_exchange(symbol);
18        let product_type = BitgetSymbolConverter::product_type_from_symbol(symbol);
19        let margin_coin = Self::margin_coin_from_symbol(symbol);
20
21        let hold_side = if margin_mode == Some("isolated") {
22            // For isolated mode, set for both sides
23            "long"
24        } else {
25            // For cross mode, no holdSide needed
26            ""
27        };
28
29        let mut builder = self
30            .signed_request("/api/v2/mix/account/set-leverage")
31            .method(HttpMethod::Post)
32            .param("symbol", &exchange_id)
33            .param("productType", product_type)
34            .param("marginCoin", margin_coin)
35            .param("leverage", leverage.to_string());
36
37        if !hold_side.is_empty() {
38            builder = builder.param("holdSide", hold_side);
39        }
40
41        let _data = builder.execute().await?;
42
43        // If isolated mode, also set for short side
44        if margin_mode == Some("isolated") {
45            self.signed_request("/api/v2/mix/account/set-leverage")
46                .method(HttpMethod::Post)
47                .param("symbol", &exchange_id)
48                .param("productType", product_type)
49                .param("marginCoin", margin_coin)
50                .param("leverage", leverage.to_string())
51                .param("holdSide", "short")
52                .execute()
53                .await?;
54        }
55
56        Ok(())
57    }
58
59    /// Get current leverage for a symbol.
60    ///
61    /// Uses Bitget GET `/api/v2/mix/account/account` endpoint and extracts leverage.
62    pub async fn get_leverage_impl(&self, symbol: &str) -> Result<u32> {
63        let exchange_id = BitgetSymbolConverter::unified_to_exchange(symbol);
64        let product_type = BitgetSymbolConverter::product_type_from_symbol(symbol);
65        let margin_coin = Self::margin_coin_from_symbol(symbol);
66
67        let data = self
68            .signed_request("/api/v2/mix/account/account")
69            .param("symbol", &exchange_id)
70            .param("productType", product_type)
71            .param("marginCoin", margin_coin)
72            .execute()
73            .await?;
74
75        // Try to extract leverage from the account data
76        let lever_str = data["data"]["crossMarginLeverage"]
77            .as_str()
78            .or_else(|| data["data"]["fixedLongLeverage"].as_str())
79            .ok_or_else(|| Error::from(ParseError::missing_field("leverage")))?;
80
81        lever_str.parse::<f64>().map(|v| v as u32).map_err(|_| {
82            Error::from(ParseError::invalid_value(
83                "leverage",
84                format!("Cannot parse leverage: {}", lever_str),
85            ))
86        })
87    }
88}