Explorar o código

修改gate取消所有订单

gepangpang %!s(int64=2) %!d(string=hai) anos
pai
achega
51380c93ec

+ 1 - 1
exchanges/src/bitget_spot_rest.rs

@@ -503,7 +503,7 @@ impl BitgetSpotRest {
         data
     }
     //批量撤销计划委托
-    pub async fn cancel_plan_orders(&mut self, symbol_list: Vec<String>) -> ResponseData {
+    pub async fn cancel_plan_orders(&mut self, symbol_list: String) -> ResponseData {
         let params = serde_json::json!({
             "symbolList":symbol_list
          });

+ 26 - 26
standard/src/bitget_spot.rs

@@ -8,7 +8,7 @@ use rust_decimal::prelude::ToPrimitive;
 use rust_decimal_macros::dec;
 use serde_json::json;
 use tracing::error;
-use exchanges::kucoin_swap_rest::KucoinSwapRest;
+use exchanges::bitget_spot_rest::BitgetSpotRest;
 use global::trace_stack::TraceStack;
 use crate::exchange::ExchangeEnum;
 use crate::{Account, bitget_spot_handle, Market, Order, OrderCommand, Platform, Position, Ticker, utils};
@@ -20,7 +20,7 @@ pub struct BitgetSpot {
     symbol: String,
     is_colo: bool,
     params: BTreeMap<String, String>,
-    request: KucoinSwapRest,
+    request: BitgetSpotRest,
     market: Market,
     order_sender: Sender<Order>,
     error_sender: Sender<Error>,
@@ -29,18 +29,18 @@ pub struct BitgetSpot {
 impl BitgetSpot {
     pub async fn new(symbol: String, is_colo: bool, params: BTreeMap<String, String>, order_sender: Sender<Order>, error_sender: Sender<Error>) -> BitgetSpot {
         let market = Market::new();
-        let mut kucoin_swap = BitgetSpot {
-            exchange: ExchangeEnum::KucoinSwap,
+        let bitget_spot = BitgetSpot {
+            exchange: ExchangeEnum::BitgetSpot,
             symbol: symbol.to_uppercase(),
             is_colo,
             params: params.clone(),
-            request: KucoinSwapRest::new(is_colo, params.clone()),
+            request: BitgetSpotRest::new(is_colo, params.clone()),
             market,
             order_sender,
             error_sender,
         };
-        kucoin_swap.market = BitgetSpot::get_market(&mut kucoin_swap).await.unwrap_or(kucoin_swap.market);
-        return kucoin_swap;
+        // bitget_spot.market = BitgetSpot::get_market(&mut bitget_spot).await.unwrap_or(bitget_spot.market);
+        return bitget_spot;
     }
 }
 
@@ -65,20 +65,20 @@ impl Platform for BitgetSpot {
     fn get_request_max_delay(&self) -> i64 { self.request.get_max_delay() }
 
     async fn get_server_time(&mut self) -> Result<String, Error> {
-        let res_data = self.request.get_server_time().await;
-        if res_data.code == "200" {
-            let res_data_str = &res_data.data;
-            let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
-            let result = res_data_json["serverTime"].as_str().unwrap().to_string();
-            Ok(result)
-        } else {
-            Err(Error::new(ErrorKind::Other, res_data.to_string()))
-        }
+        todo!()
+        // let res_data = self.request.get().await;
+        // if res_data.code == "200" {
+        //     let res_data_str = &res_data.data;
+        //     let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
+        //     let result = res_data_json["serverTime"].as_str().unwrap().to_string();
+        //     Ok(result)
+        // } else {
+        //     Err(Error::new(ErrorKind::Other, res_data.to_string()))
+        // }
     }
 
     async fn get_account(&mut self) -> Result<Account, Error> {
-        let symbol_array: Vec<&str> = self.symbol.split("_").collect();
-        let res_data = self.request.get_account(symbol_array[1].to_string().to_uppercase()).await;
+        let res_data = self.request.get_account_assets().await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
@@ -108,7 +108,7 @@ impl Platform for BitgetSpot {
 
     async fn get_ticker(&mut self) -> Result<Ticker, Error> {
         let symbol_format = utils::format_symbol(self.symbol.clone(), "");
-        let res_data = self.request.get_ticker(symbol_format).await;
+        let res_data = self.request.get_tickers(symbol_format).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
@@ -134,7 +134,7 @@ impl Platform for BitgetSpot {
 
     async fn get_market(&mut self) -> Result<Market, Error> {
         let symbol_format = utils::format_symbol(self.symbol.clone(), "");
-        let res_data = self.request.get_market_details().await;
+        let res_data = self.request.get_market_fills("".to_string(), "".to_string()).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
@@ -181,7 +181,7 @@ impl Platform for BitgetSpot {
     async fn get_order_detail(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
         let amount_size = self.market.amount_size;
         let id = if order_id.eq("") { custom_id.to_string() } else { order_id.to_string() };
-        let res_data = self.request.get_orders(id, "".to_string()).await;
+        let res_data = self.request.get_order(id, "".to_string()).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
@@ -196,7 +196,7 @@ impl Platform for BitgetSpot {
     async fn get_orders_list(&mut self, status: &str) -> Result<Vec<Order>, Error> {
         let symbol_format = utils::format_symbol(self.symbol.clone(), "");
         let amount_size = self.market.amount_size;
-        let res_data = self.request.get_orders(status.to_string(), symbol_format.to_string()).await;
+        let res_data = self.request.get_unfilled_orders(status.to_string(), symbol_format.to_string(), "".to_string(), "".to_string(), "".to_string(), "".to_string()).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
@@ -237,7 +237,7 @@ impl Platform for BitgetSpot {
             }
             _ => { error!("下单参数错误"); }
         };
-        let res_data = self.request.swap_order(params).await;
+        let res_data = self.request.spot_order(params).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
@@ -287,7 +287,7 @@ impl Platform for BitgetSpot {
             }
             _ => { error!("下单参数错误"); }
         };
-        let res_data = self.request.swap_order(params).await;
+        let res_data = self.request.spot_order(params).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
@@ -311,7 +311,7 @@ impl Platform for BitgetSpot {
     async fn cancel_order(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
         // let symbol_format = utils::format_symbol(self.symbol.clone(), "");
         // let id = if order_id.eq("") { custom_id.to_string() } else { order_id.to_string() };
-        let res_data = self.request.cancel_order(order_id.to_string(), custom_id.to_string()).await;
+        let res_data = self.request.cancel_plan_order(order_id.to_string(), custom_id.to_string()).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
@@ -334,7 +334,7 @@ impl Platform for BitgetSpot {
 
     async fn cancel_orders(&mut self) -> Result<Vec<Order>, Error> {
         let symbol_format = utils::format_symbol(self.symbol.clone(), "");
-        let res_data = self.request.cancel_orders(symbol_format.clone()).await;
+        let res_data = self.request.cancel_plan_orders(symbol_format.clone()).await;
         if res_data.code == "200" {
             let res_data_str = &res_data.data;
             let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();

+ 2 - 2
standard/src/gate_swap.rs

@@ -439,7 +439,7 @@ impl Platform for GateSwap {
         }
     }
 
-    async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> { todo!() }
+    async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> { Err(Error::new(ErrorKind::NotFound, "gate:该交易所方法未实现".to_string())) }
 
     // 设置持仓模式
     async fn set_dual_mode(&mut self, coin: &str, is_dual_mode: bool) -> Result<String, Error> {
@@ -466,7 +466,7 @@ impl Platform for GateSwap {
         }
     }
 
-    async fn set_auto_deposit_status(&mut self, _status: bool) -> Result<String, Error> { todo!() }
+    async fn set_auto_deposit_status(&mut self, _status: bool) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "gate:该交易所方法未实现".to_string())) }
 
     // 交易账户互转
     async fn wallet_transfers(&mut self, coin: &str, from: &str, to: &str, amount: Decimal) -> Result<String, Error> {

+ 0 - 1
standard/src/okx_handle.rs

@@ -121,7 +121,6 @@ pub fn handle_position(res_data: ResponseData, amount_size: Decimal) -> Vec<Posi
     let res_data_str = res_data.data;
     let res_data_json: serde_json::Value = serde_json::from_str(&res_data_str).unwrap();
     let position_data = res_data_json[0]["posData"].clone();
-    trace!(?position_data);
     let result = format_position_item(position_data, amount_size);
     return vec![result];
 }

+ 178 - 16
standard/src/okx_swap.rs

@@ -1,11 +1,14 @@
-use std::collections::{BTreeMap};
+use std::collections::{BTreeMap, HashMap};
 use std::io::{Error, ErrorKind};
 use std::str::FromStr;
 use tokio::sync::mpsc::Sender;
 use async_trait::async_trait;
+use futures::stream::FuturesUnordered;
+use futures::TryStreamExt;
 use rust_decimal::Decimal;
 use rust_decimal::prelude::FromPrimitive;
 use rust_decimal_macros::dec;
+use serde_json::json;
 use tracing::error;
 use exchanges::okx_swap_rest::OkxSwapRest;
 use global::trace_stack::TraceStack;
@@ -28,7 +31,7 @@ pub struct OkxSwap {
 impl OkxSwap {
     pub async fn new(symbol: String, is_colo: bool, params: BTreeMap<String, String>, order_sender: Sender<Order>, error_sender: Sender<Error>) -> OkxSwap {
         let market = Market::new();
-        let mut kucoin_swap = OkxSwap {
+        let mut okx_swap = OkxSwap {
             exchange: ExchangeEnum::OkxSwap,
             symbol: symbol.to_uppercase(),
             is_colo,
@@ -38,8 +41,8 @@ impl OkxSwap {
             order_sender,
             error_sender,
         };
-        kucoin_swap.market = OkxSwap::get_market(&mut kucoin_swap).await.unwrap_or(kucoin_swap.market);
-        return kucoin_swap;
+        okx_swap.market = OkxSwap::get_market(&mut okx_swap).await.unwrap_or(okx_swap.market);
+        return okx_swap;
     }
 }
 
@@ -317,9 +320,45 @@ impl Platform for OkxSwap {
         }
     }
 
-    async fn take_order(&mut self, _custom_id: &str, _origin_side: &str, _price: Decimal, _amount: Decimal) -> Result<Order, Error> { todo!() }
+    async fn take_order(&mut self, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
+        let symbol_format = utils::format_symbol(self.symbol.clone(), "-");
+        let amount_size = self.market.amount_size;
+        let mut params = json!({
+            "tdMode": "cross",
+            "clOrdId": custom_id.to_string(),
+            "instId": symbol_format,
+            "px": price.to_string(),
+            "ordType": "limit",
+        });
+        let size = (amount / amount_size).floor();
+        params["sz"] = json!(size);
+        match origin_side {
+            "kd" => {
+                params["side"] = json!("buy");
+            }
+            "pd" => {
+                params["side"] = json!("sell");
+            }
+            "kk" => {
+                params["side"] = json!("sell");
+            }
+            "pk" => {
+                params["side"] = json!("buy");
+            }
+            _ => { error!("下单参数错误"); }
+        };
+        let res_data = self.request.swap_order(params).await;
+        if res_data.code == "200" {
+            let res_data_str = &res_data.data;
+            let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
+            let result = okx_handle::format_order_item(res_data_json, amount_size);
+            Ok(result)
+        } else {
+            Err(Error::new(ErrorKind::Other, res_data.to_string()))
+        }
+    }
 
-    async fn take_order_symbol(&mut self, _symbol: String, _custom_id: &str, _origin_side: &str, _price: Decimal, _amount: Decimal) -> Result<Order, Error> { todo!() }
+    async fn take_order_symbol(&mut self, _symbol: String, _custom_id: &str, _origin_side: &str, _price: Decimal, _amount: Decimal) -> Result<Order, Error> { Err(Error::new(ErrorKind::NotFound, "okx:该交易所方法未实现".to_string())) }
 
     async fn cancel_order(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
         let symbol_format = utils::format_symbol(self.symbol.clone(), "-");
@@ -343,7 +382,7 @@ impl Platform for OkxSwap {
                 avg_price: dec!(0),
                 status: "REMOVE".to_string(),
                 order_type: "".to_string(),
-                trace_stack: TraceStack::default().on_special("360 kucoin_swap".to_string()),
+                trace_stack: TraceStack::default().on_special("346 okx_swap".to_string()),
             };
             Ok(result)
         } else {
@@ -352,20 +391,143 @@ impl Platform for OkxSwap {
     }
 
     async fn cancel_orders(&mut self) -> Result<Vec<Order>, Error> {
-        todo!()
+        Err(Error::new(ErrorKind::NotFound, "okx:该交易所方法未实现".to_string()))
     }
 
-    async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> { todo!() }
-
-    async fn set_dual_mode(&mut self, _coin: &str, _is_dual_mode: bool) -> Result<String, Error> { todo!() }
+    async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> {
+        Err(Error::new(ErrorKind::NotFound, "okx:该交易所方法未实现".to_string()))
+    }
 
-    async fn set_dual_leverage(&mut self, _leverage: &str) -> Result<String, Error> {
-        todo!()
+    async fn set_dual_mode(&mut self, _coin: &str, _is_dual_mode: bool) -> Result<String, Error> {
+        let res_data = self.request.set_position_mode().await;
+        if res_data.code == "200" {
+            let res_data_str = &res_data.data;
+            let result = res_data_str.clone();
+            Ok(result)
+        } else {
+            Err(Error::new(ErrorKind::Other, res_data.to_string()))
+        }
     }
 
-    async fn set_auto_deposit_status(&mut self, _status: bool) -> Result<String, Error> { todo!() }
+    async fn set_dual_leverage(&mut self, leverage: &str) -> Result<String, Error> {
+        let symbol_format = utils::format_symbol(self.symbol.clone(), "-");
+        let res_data = self.request.set_leverage(symbol_format, leverage.to_string()).await;
+        if res_data.code == "200" {
+            let res_data_str = &res_data.data;
+            let result = res_data_str.clone();
+            Ok(result)
+        } else {
+            Err(Error::new(ErrorKind::Other, res_data.to_string()))
+        }
+    }
 
-    async fn wallet_transfers(&mut self, _coin: &str, _from: &str, _to: &str, _amount: Decimal) -> Result<String, Error> { todo!() }
+    async fn set_auto_deposit_status(&mut self, _status: bool) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "okx:该交易所方法未实现".to_string())) }
+
+    async fn wallet_transfers(&mut self, _coin: &str, _from: &str, _to: &str, _amount: Decimal) -> Result<String, Error> { Err(Error::new(ErrorKind::NotFound, "okx:该交易所方法未实现".to_string())) }
+
+    async fn command_order(&mut self, order_command: OrderCommand, trace_stack: TraceStack) {
+        let mut handles = vec![];
+        // 撤销订单
+        let cancel = order_command.cancel;
+        for item in cancel.keys() {
+            let mut self_clone = self.clone();
+            let cancel_clone = cancel.clone();
+            let item_clone = item.clone();
+            let order_id = cancel_clone[&item_clone].get(1).unwrap_or(&"".to_string()).clone();
+            let custom_id = cancel_clone[&item_clone].get(0).unwrap_or(&"".to_string()).clone();
+            let result_sd = self.order_sender.clone();
+            let err_sd = self.error_sender.clone();
+            let handle = tokio::spawn(async move {
+                if order_id != "" {
+                    let result = self_clone.cancel_order(&order_id, &custom_id).await;
+                    match result {
+                        Ok(_) => {
+                            // result_sd.send(result).await.unwrap();
+                        }
+                        Err(error) => {
+                            // 取消失败去查订单。
+                            let query_rst = self_clone.get_order_detail(&order_id, &custom_id).await;
+                            match query_rst {
+                                Ok(order) => {
+                                    result_sd.send(order).await.unwrap();
+                                }
+                                Err(query_err) => {
+                                    error!(?query_err);
+                                    error!("撤单失败,而且查单也失败了,okx_swap,oid={}, cid={}。", order_id.clone(), custom_id.clone());
+                                }
+                            }
+                            err_sd.send(error).await.unwrap();
+                        }
+                    }
+                }
+            });
+            handles.push(handle)
+        }
+        // 下单指令
+        let mut limits = HashMap::new();
+        limits.extend(order_command.limits_open);
+        limits.extend(order_command.limits_close);
+        for item in limits.keys() {
+            let mut self_clone = self.clone();
+            let limits_clone = limits.clone();
+            let item_clone = item.clone();
+            let result_sd = self.order_sender.clone();
+            let err_sd = self.error_sender.clone();
+            let mut ts = trace_stack.clone();
+
+            let handle = tokio::spawn(async move {
+                let value = limits_clone[&item_clone].clone();
+                let amount = Decimal::from_str(value.get(0).unwrap_or(&"0".to_string())).unwrap();
+                let side = value.get(1).unwrap();
+                let price = Decimal::from_str(value.get(2).unwrap_or(&"0".to_string())).unwrap();
+                let cid = value.get(3).unwrap();
+
+                //  order_name: [数量,方向,价格,c_id]
+                let result = self_clone.take_order(cid, side, price, amount).await;
+                match result {
+                    Ok(mut result) => {
+                        ts.on_after_send();
+                        result.trace_stack = ts.clone();
+
+                        result_sd.send(result).await.unwrap();
+                    }
+                    Err(error) => {
+                        let mut err_order = Order::new();
+                        err_order.custom_id = cid.clone();
+                        err_order.status = "REMOVE".to_string();
+
+                        result_sd.send(err_order).await.unwrap();
+                        err_sd.send(error).await.unwrap();
+                    }
+                }
+            });
+            handles.push(handle)
+        }
+        // 检查订单指令
+        let check = order_command.check;
+        for item in check.keys() {
+            let mut self_clone = self.clone();
+            let check_clone = check.clone();
+            let item_clone = item.clone();
+            let order_id = check_clone[&item_clone].get(1).unwrap_or(&"".to_string()).clone();
+            let custom_id = check_clone[&item_clone].get(0).unwrap_or(&"".to_string()).clone();
+            let result_sd = self.order_sender.clone();
+            let err_sd = self.error_sender.clone();
+            let handle = tokio::spawn(async move {
+                let result = self_clone.get_order_detail(&order_id, &custom_id).await;
+                match result {
+                    Ok(result) => {
+                        result_sd.send(result).await.unwrap();
+                    }
+                    Err(error) => {
+                        err_sd.send(error).await.unwrap();
+                    }
+                }
+            });
+            handles.push(handle)
+        }
 
-    async fn command_order(&mut self, _order_command: OrderCommand, _trace_stack: TraceStack) { todo!() }
+        let futures = FuturesUnordered::from_iter(handles);
+        let _: Result<Vec<_>, _> = futures.try_collect().await;
+    }
 }

+ 117 - 0
standard/tests/bitget_spot_test.rs

@@ -0,0 +1,117 @@
+use tracing::{instrument, trace};
+use standard::exchange::ExchangeEnum;
+use standard::Platform;
+use crate::exchange_test::test_new_exchange;
+
+mod exchange_test;
+
+const SYMBOL: &str = "ETH_USDT";
+
+// 测试获取Exchange实体
+#[tokio::test]
+async fn test_get_self_exchange() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSpot, SYMBOL).await;
+    let bitget_get_self_exchange = bitget_swap_exchange.get_self_exchange();
+    trace!(?bitget_get_self_exchange);
+}
+
+// 测试获取交易对信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_self_symbol() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSpot, SYMBOL).await;
+    let bitget_get_self_symbol = bitget_swap_exchange.get_self_symbol();
+    trace!(?bitget_get_self_symbol);
+}
+
+// 测试获取是否使用高速通道
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_self_is_colo() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSpot, SYMBOL).await;
+    let bitget_get_self_is_colo = bitget_swap_exchange.get_self_is_colo();
+    trace!(?bitget_get_self_is_colo);
+}
+
+// 测试获取登录params信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_self_params() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSpot, SYMBOL).await;
+    let bitget_get_self_params = bitget_swap_exchange.get_self_params();
+    trace!("bitget_get_self_params={:?}",bitget_get_self_params);
+}
+
+// 测试获取Market信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_self_market() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSpot, SYMBOL).await;
+    let bitget_get_self_market = bitget_swap_exchange.get_self_market();
+    trace!(?bitget_get_self_market);
+}
+
+// 测试获取请求时间信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_request_delays() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSpot, SYMBOL).await;
+    let bitget_get_request_delays = bitget_swap_exchange.get_request_delays();
+    trace!(?bitget_get_request_delays);
+}
+
+// 测试获取请求平均时间信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_request_avg_delay() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSpot, SYMBOL).await;
+    let bitget_get_request_avg_delay = bitget_swap_exchange.get_request_avg_delay();
+    trace!(?bitget_get_request_avg_delay);
+}
+
+// 测试获取最大请求时间信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_request_max_delay() {
+    global::log_utils::init_log_with_trace();
+
+    let bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSpot, SYMBOL).await;
+    let bitget_get_request_max_delay = bitget_swap_exchange.get_request_max_delay();
+    trace!(?bitget_get_request_max_delay);
+}
+
+// 测试获取服务器时间
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_server_time() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSpot, SYMBOL).await;
+    let bitget_get_server_time = bitget_swap_exchange.get_server_time().await;
+    trace!(?bitget_get_server_time);
+}
+
+// 测试获取账号信息
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_account() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bitget_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::BitgetSpot, SYMBOL).await;
+    let bitget_get_account = bitget_swap_exchange.get_account().await;
+    trace!(?bitget_get_account);
+}

+ 9 - 3
standard/tests/exchange_test.rs

@@ -76,9 +76,15 @@ pub async fn test_new_exchange(exchange: ExchangeEnum, symbol: &str) -> Box<dyn
             params.insert("pass_key".to_string(), pass_key);
             Exchange::new(exchange, symbol.to_string(), false, params, order_sender, error_sender).await
         }
-        _ => {
-            error!("该交易所不支持!test_new_exchange:{:?}",exchange);
-            panic!("该交易所不支持!test_new_exchange:{:?}", exchange)
+        ExchangeEnum::BitgetSpot => {
+            let mut params: BTreeMap<String, String> = BTreeMap::new();
+            let access_key = env::var("bitget_access_key").unwrap_or("".to_string());
+            let secret_key = env::var("bitget_secret_key").unwrap_or("".to_string());
+            let pass_key = env::var("bitget_passphrase").unwrap_or("".to_string());
+            params.insert("access_key".to_string(), access_key);
+            params.insert("secret_key".to_string(), secret_key);
+            params.insert("pass_key".to_string(), pass_key);
+            Exchange::new(exchange, symbol.to_string(), false, params, order_sender, error_sender).await
         }
     }
 }

+ 24 - 1
standard/tests/okx_swap_test.rs

@@ -4,6 +4,7 @@ use standard::Platform;
 use crate::exchange_test::test_new_exchange;
 
 mod exchange_test;
+
 const SYMBOL: &str = "ETH_USDT";
 
 // 测试获取Exchange实体
@@ -166,7 +167,29 @@ async fn test_get_order_detail() {
 async fn test_get_orders_list() {
     global::log_utils::init_log_with_trace();
 
-    let mut okx_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::KucoinSwap, SYMBOL).await;
+    let mut okx_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::OkxSwap, SYMBOL).await;
     let okx_get_orders_list = okx_swap_exchange.get_orders_list("active").await;
     trace!(?okx_get_orders_list);
+}
+
+// 测试设置持仓模式
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_set_dual_mode() {
+    global::log_utils::init_log_with_trace();
+
+    let mut okx_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::OkxSwap, SYMBOL).await;
+    let okx_set_dual_mode = okx_swap_exchange.set_dual_mode("usdt", true).await;
+    trace!(?okx_set_dual_mode);
+}
+
+// 测试设置杠杆
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_set_dual_leverage() {
+    global::log_utils::init_log_with_trace();
+
+    let mut okx_swap_exchange: Box<dyn Platform> = test_new_exchange(ExchangeEnum::OkxSwap, SYMBOL).await;
+    let okx_set_dual_leverage = okx_swap_exchange.set_dual_leverage("10").await;
+    trace!(?okx_set_dual_leverage);
 }