浏览代码

bitget 的参考交易所

875428575@qq.com 2 年之前
父节点
当前提交
7b941048b4
共有 4 个文件被更改,包括 651 次插入0 次删除
  1. 507 0
      exchanges/src/bitget_spot_ws.rs
  2. 1 0
      exchanges/src/lib.rs
  3. 8 0
      exchanges/src/okx_swap_ws.rs
  4. 135 0
      exchanges/tests/bitget_spot_test.rs

+ 507 - 0
exchanges/src/bitget_spot_ws.rs

@@ -0,0 +1,507 @@
+use std::collections::{BTreeMap};
+use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+use std::sync::Arc;
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::thread;
+use std::time::Duration;
+use chrono::Utc;
+use tokio::sync::mpsc::Sender;
+use serde_json::{json, Value};
+use tracing::{error, info, trace};
+use crate::{proxy};
+use tungstenite::client::{AutoStream, connect_with_proxy, ProxyAutoStream};
+use tungstenite::{connect, Message, WebSocket};
+use tungstenite::protocol::WebSocketConfig;
+use url::Url;
+use crate::proxy::ParsingDetail;
+use crate::response_base::ResponseData;
+use crate::utils::get_time_microsecond;
+
+use ring::hmac;
+
+pub enum BitgetWsType {
+    //频道类型
+    Public,
+    Private,
+}
+
+
+#[derive(Clone)]                        //订阅枚举
+pub enum BitgetSubscribeType {
+    PuTicker,
+    PuCandle1m,
+    PuTrade,
+    PuBooks5,
+
+    PrAccount,
+    PrOrders,
+}
+
+#[derive(Clone)]
+pub struct BitgetSwapWs {
+    pub label: String,
+    request_url: String,
+    //实际ws 链接地址
+    proxy: ParsingDetail,
+    //账号信息
+    login_param: BTreeMap<String, String>,
+    //kuconis特殊参数
+    symbol_s: Vec<String>,
+    //订阅币对
+    subscribe_types: Vec<BitgetSubscribeType>,
+    //订阅信息
+    sender: Sender<ResponseData>,     //数据通道
+}
+
+impl BitgetSwapWs {
+    /*******************************************************************************************************/
+    /*****************************************获取一个对象****************************************************/
+    /*******************************************************************************************************/
+    pub fn new(is_colo: bool,
+               login_param: BTreeMap<String, String>,
+               ws_type: BitgetWsType,
+               sender: Sender<ResponseData>,
+    ) -> BitgetSwapWs
+    {
+        return BitgetSwapWs::new_label("default-BitgetSwapWs".to_string(), is_colo, login_param, ws_type, sender);
+    }
+    pub fn new_label(label: String, is_colo: bool,
+                     login_param: BTreeMap<String, String>,
+                     ws_type: BitgetWsType,
+                     sender: Sender<ResponseData>,
+    ) -> BitgetSwapWs
+    {
+        /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
+        let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
+
+
+        let request_url = match ws_type {
+            BitgetWsType::Public => {
+                format!("wss://ws.bitget.com/v2/ws/public")
+            }
+            BitgetWsType::Private => {
+                format!("	wss://ws.bitget.com/v2/ws/private")
+            }
+        };
+
+        if is_colo {
+            info!("开启高速(未配置,走普通:{})通道",request_url);
+        } else {
+            info!("走普通通道:{}",request_url);
+        }
+        /*****返回结构体*******/
+        BitgetSwapWs {
+            label,
+            request_url,
+            proxy: parsing_detail,
+            login_param,
+            symbol_s: vec![],
+            subscribe_types: vec![],
+            sender,
+        }
+    }
+
+    /*******************************************************************************************************/
+    /*****************************************订阅函数********************************************************/
+    /*******************************************************************************************************/
+    //手动添加订阅信息
+    pub fn set_subscribe(&mut self, subscribe_types: Vec<BitgetSubscribeType>) {
+        self.subscribe_types.extend(subscribe_types);
+    }
+    //自定义
+    pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
+    {
+        let mut symbol_s = b_array.clone();
+        for symbol in symbol_s.iter_mut() {
+            // 大写
+            *symbol = symbol.to_uppercase();
+            // 字符串替换
+            *symbol = symbol.replace("-", "");
+            *symbol = symbol.replace("_", "");
+        }
+        self.symbol_s = symbol_s;
+        self.run(bool_v1).await;
+    }
+
+    /*******************************************************************************************************/
+    /*****************************************工具函数********************************************************/
+    /*******************************************************************************************************/
+    //订阅枚举解析
+    pub fn enum_to_string(symbol: String, subscribe_type: BitgetSubscribeType) -> Value {
+        match subscribe_type {
+            BitgetSubscribeType::PuTicker => {
+                json!({
+                    "instType": "SPOT",
+                    "channel": "ticker",
+                    "instId": symbol,
+                })
+            }
+            BitgetSubscribeType::PuCandle1m => {
+                json!({
+                    "instType": "SPOT",
+                    "channel": "candle1m",
+                    "instId": symbol,
+                })
+            }
+            BitgetSubscribeType::PuTrade => {
+                json!({
+                    "instType": "SPOT",
+                    "channel": "trade",
+                    "instId": symbol,
+                })
+            }
+            BitgetSubscribeType::PuBooks5 => {
+                json!({
+                    "instType": "SPOT",
+                    "channel": "books5",
+                    "instId": symbol,
+                })
+            }
+            BitgetSubscribeType::PrAccount => {
+                json!({
+                    "instType": "SPOT",
+                    "channel": "account",
+                    "coin": "default"
+                })
+            }
+            BitgetSubscribeType::PrOrders => {
+                json!({
+                    "instType": "SPOT",
+                    "channel": "orders",
+                    "instId": symbol
+                })
+            }
+        }
+    }
+    //组装订阅数据
+    pub fn get_subscription(&self) -> String {
+        let mut args = vec![];
+        for symbol in &self.symbol_s {
+            for subscribe_type in &self.subscribe_types {
+                let ty_str = Self::enum_to_string(symbol.clone(), subscribe_type.clone());
+                args.push(ty_str);
+            }
+        }
+        let str = json!({
+            "op": "subscribe",
+            "args": args
+        });
+
+        trace!("订阅信息:{}", str.to_string());
+
+        str.to_string()
+    }
+
+    // fn sign(secret_key: String, channel: String, event: String, time: String) -> String {
+    //     let message = format!("channel={}&event={}&time={}", channel, event, time);
+    //     let mut mac = Hmac::<Sha512>::new_varkey(secret_key.as_bytes()).expect("Failed to create HMAC");
+    //     mac.update(message.as_bytes());
+    //     let result = mac.finalize().into_bytes();
+    //     let sign = hex::encode(result);
+    //     sign
+    // }
+
+    //组装登陆数据
+    fn log_in_to_str(&self) -> String {
+        let mut login_json_str = "".to_string();
+
+        let mut access_key: String = "".to_string();
+        let mut secret_key: String = "".to_string();
+        let mut passphrase: String = "".to_string();
+        for (key, value) in &self.login_param {
+            if key == "access_key" {
+                access_key = value.parse().unwrap();
+            } else if key == "secret_key" {
+                secret_key = value.parse().unwrap();
+            } else if key == "pass_key" {
+                passphrase = value.parse().unwrap();
+            }
+        }
+        if access_key.len() > 0 || secret_key.len() > 0 || passphrase.len() > 0 {
+            let timestamp = Utc::now().timestamp().to_string();
+            // 时间戳 + 请求类型+ 请求参数字符串
+            let message = format!("{}GET{}", timestamp, "/user/verify");
+            let hmac_key = ring::hmac::Key::new(hmac::HMAC_SHA256, secret_key.as_bytes());
+            let result = ring::hmac::sign(&hmac_key, &message.as_bytes());
+            let sign = base64::encode(result);
+
+            let login_json = json!({
+                              "op": "login",
+                              "args": [{
+                                "apiKey": access_key,
+                                "passphrase": passphrase,
+                                "timestamp": timestamp,
+                                "sign": sign
+                              }]
+                        });
+
+            trace!("---login_json:{0}", login_json.to_string());
+            trace!("--登陆:{}", login_json.to_string());
+            login_json_str = login_json.to_string();
+        }
+        login_json_str
+    }
+    /*******************************************************************************************************/
+    /*****************************************socket基本*****************************************************/
+    /*******************************************************************************************************/
+    async fn run(&mut self, bool_v1: Arc<AtomicBool>)
+    {
+        //订阅信息组装
+        let subscription = self.get_subscription();
+        loop {
+            tokio::time::sleep(Duration::from_millis(5000)).await;
+            trace!("要连接咯~~!!{}", self.request_url);
+
+            let request_url = Url::parse(self.request_url.as_str()).unwrap();
+            //1. 判断是否需要代理,根据代理地址是否存来选择
+            if self.proxy.ip_address.len() > 0 {
+                let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
+                let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
+                    ip_array[0].parse().unwrap(),
+                    ip_array[1].parse().unwrap(),
+                    ip_array[2].parse().unwrap(),
+                    ip_array[3].parse().unwrap())
+                ), self.proxy.port.parse().unwrap());
+                let websocket_config = Some(WebSocketConfig {
+                    max_send_queue: Some(16),
+                    max_message_size: Some(16 * 1024 * 1024),
+                    max_frame_size: Some(16 * 1024 * 1024),
+                    accept_unmasked_frames: false,
+                });
+                let max_redirects = 5;
+                match connect_with_proxy(request_url.clone(),
+                                         proxy_address, websocket_config, max_redirects) {
+                    Ok(ws) => {
+                        let bool_v1_clone = Arc::clone(&bool_v1);
+                        self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+                    }
+                    Err(err) => {
+                        error!("Can't connect(无法连接): {}", err);
+                    }
+                };
+            } else {
+                match connect(request_url.clone()) {
+                    Ok(ws) => {
+                        let bool_v1_clone = Arc::clone(&bool_v1);
+                        self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+                    }
+                    Err(err) => {
+                        // 连接失败时执行的操作
+                        error!("Can't connect(无法连接): {}", err);
+                        // 返回一个默认的 WebSocket 对象或其他适当的值
+                        // 或者根据需要触发 panic 或返回错误信息
+                    }
+                };
+            }
+            trace!("退出来咯");
+
+            let bool_v1_clone = Arc::clone(&bool_v1);
+            let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
+            if !bool_v1_v {
+                break;
+            }
+        }
+    }
+
+    //代理
+    async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>, subscription: String)
+    {
+        info!("走代理-链接成功!开始数据读取");
+        let label = self.label.clone();
+        /*****登陆***/
+        let login_str = self.log_in_to_str();
+        if login_str != "" {
+            let _ = web_socket.write_message(Message::Text(login_str));
+            thread::sleep(Duration::from_secs(3));
+        }
+        /*****消息溜***/
+        let mut ping_timeout = chrono::Utc::now().timestamp_millis();
+        loop {
+            tokio::time::sleep(Duration::from_millis(1)).await;
+            let msg = web_socket.read_message();
+            match msg {
+                Ok(Message::Text(text)) => {
+                    let get_time = chrono::Utc::now().timestamp_millis();
+                    if (get_time - ping_timeout) >= (1000 * 30) {
+                        trace!("30s 一次主动发送心跳包!");
+                        let _ = web_socket.write_message(Message::Ping(Vec::from("ping")));
+                        ping_timeout = get_time;
+                    }
+
+                    let mut res_data = Self::ok_text(label.to_string(), text);
+                    res_data.time = get_time_microsecond();
+                    if res_data.code == "-200" {
+                        trace!("订阅成功:{:?}", res_data.data);
+                    } else if res_data.code == "-201" {
+                        trace!("登陆:{:?}", res_data);
+                        /*****订阅***/
+                        if subscription.len() > 0 {
+                            // trace!("订阅信息:{}", subscription);
+                            web_socket.write_message(Message::Text(subscription.clone()))
+                                .unwrap();
+                        }
+                    } else {
+                        let sender = self.sender.clone();
+                        tokio::spawn(async move {
+                            sender.send(res_data).await.unwrap();
+                        });
+                        tokio::spawn(async move {});
+                    }
+                }
+                Ok(Message::Ping(s)) => {
+                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+                }
+                Ok(Message::Pong(s)) => {
+                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
+                    trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
+                }
+                Ok(Message::Close(_)) => {
+                    // trace!("socket 关闭: ");
+                    trace!( "Close-响应");
+                    break;
+                }
+                Err(error) => {
+                    // trace!("Error receiving message: {}", error);
+                    error!( "Err-响应{}", error);
+                    break;
+                }
+                _ => {}
+            }
+
+            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+            if !bool_v1_v {
+                break;
+            }
+        }
+        web_socket.close(None).unwrap();
+    }
+
+    //非代理
+    async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>,
+                          subscription: String)
+    {
+        info!("链接成功!开始数据读取");
+        let label = self.label.clone();
+        /*****订阅***/
+        if subscription.len() > 0 {
+            trace!("订阅信息:{}",subscription);
+            web_socket.write_message(Message::Text(subscription))
+                .unwrap();
+        }
+        /*****消息溜***/
+        let mut start_ping = chrono::Utc::now().timestamp_millis();
+        loop {
+            tokio::time::sleep(Duration::from_millis(1)).await;
+            let msg = web_socket.read_message();
+            match msg {
+                Ok(Message::Text(text)) => {
+                    // trace!("获取推送:{}",text.clone());
+                    let mut res_data = Self::ok_text(label.to_string(), text);
+                    res_data.time = get_time_microsecond();
+                    if res_data.code == "-200" {
+                        trace!("订阅成功:{:?}", res_data.data);
+                    } else {
+                        // self.sender.send(res_data).await.unwrap();
+                        let sender = self.sender.clone();
+                        tokio::spawn(async move {
+                            sender.send(res_data).await.unwrap();
+                        });
+                        tokio::spawn(async move {});
+
+                        //主动ping 服务器
+                        let new_time = chrono::Utc::now().timestamp_millis();
+                        // let tr = format!("判断-ping {}--{},{},{}",new_time,start_ping,(new_time - start_ping), (new_time - start_ping) > 10000);
+                        // trace!(tr);
+                        if (new_time - start_ping) > 10000 {
+                            let t = chrono::Utc::now().timestamp();
+                            let ping_str = serde_json::json!({
+                                "time" :t, "channel" : "futures.ping"
+                            });
+                            let _ = web_socket.write_message(Message::Ping(Vec::from(ping_str.to_string())));
+                            start_ping = new_time;
+                        }
+                    }
+                }
+                Ok(Message::Ping(s)) => {
+                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+                }
+                Ok(Message::Pong(s)) => {
+                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
+                    trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
+                }
+                Ok(Message::Close(_)) => {
+                    // trace!("socket 关闭: ");
+                    trace!( "Close-响应");
+                    break;
+                }
+                Err(error) => {
+                    // trace!("Error receiving message: {}", error);
+                    error!( "Err-响应{}", error);
+                    break;
+                }
+                _ => {}
+            }
+
+            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+            if !bool_v1_v {
+                break;
+            }
+        }
+        web_socket.close(None).unwrap();
+    }
+
+    //数据解析
+    pub fn ok_text(label: String, text: String) -> ResponseData
+    {
+        // trace!("原始数据:{}", text);
+        let mut res_data = ResponseData::new(label.to_string(), "200".to_string(), "success".to_string(), "".to_string());
+        let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
+
+        // {"event":"login","code":0}
+        if json_value.get("event").is_some() && json_value["event"].as_str() == Option::from("login") {
+            if json_value.get("code").is_some() && json_value["code"]  == 0 {
+                res_data.message = format!("登陆成功");
+            } else {
+                res_data.message = format!("登陆失败:({},{})", json_value.get("code").as_ref().unwrap(), json_value.get("msg").as_ref().unwrap());
+            }
+            res_data.channel = format!("login");
+            res_data.code = "-201".to_string();
+            res_data
+        } else if json_value.get("event").is_some() && json_value["event"].as_str() == Option::from("subscribe") {
+            // trace!("解析-订阅反馈:{}", text);
+            res_data.code = "-200".to_string();
+            res_data.data = text;
+            res_data.channel = format!("{}", json_value["arg"]["channel"].as_str().unwrap());
+            res_data
+        } else if json_value.get("action").is_some() {
+            // trace!("解析-推送数据:{}", text);
+            res_data.code = "200".to_string();
+            res_data.data = json_value["data"].to_string();
+            res_data.channel = format!("{}", json_value["arg"]["channel"].as_str().unwrap());
+            res_data
+        } else {
+            res_data
+        }
+
+        // if json_value.get("error").is_some() {
+        //     let message = json_value["error"]["message"].as_str().unwrap().to_string();
+        //     let mes = message.trim_end_matches('\n');
+        //
+        //     // let mes_json_value: serde_json::Value = serde_json::from_str(mes).unwrap();
+        //     // // trace!("错误信息:{}", mes_json_value.to_string());
+        //     res_data.code = json_value["error"]["code"].to_string();
+        //     res_data.message = mes.clone().to_string();
+        // } else if json_value["result"]["status"].as_str() == Option::from("success") {//订阅返回
+        //     res_data.code = "-200".to_string();
+        //     res_data.data = text;
+        // } else {
+        //     res_data.channel = format!("{}", json_value["channel"].as_str().unwrap());
+        //     res_data.code = "200".to_string();
+        //     res_data.data = json_value["result"].to_string();
+        // }
+    }
+}

+ 1 - 0
exchanges/src/lib.rs

@@ -15,4 +15,5 @@ pub mod binance_swap_ws;
 pub mod okx_swap_rest;
 pub mod binance_swap_rest;
 mod utils;
+pub mod bitget_spot_ws;
 

+ 8 - 0
exchanges/src/okx_swap_ws.rs

@@ -390,10 +390,18 @@ impl OkxSwapWs {
         web_socket.write_message(Message::Text(subscription))
             .unwrap();
         /*****消息溜***/
+        let mut  ping_timeout = chrono::Utc::now().timestamp_millis();
         loop {
             let msg = web_socket.read_message();
             match msg {
                 Ok(Message::Text(text)) => {
+                    let get_time = chrono::Utc::now().timestamp_millis();
+                    if (get_time - ping_timeout) >= (1000 * 30) {
+                        trace!("30s 一次主动发送心跳包!");
+                        let _ = web_socket.write_message(Message::Ping(Vec::from("ping")));
+                        ping_timeout = get_time;
+                    }
+
                     let mut res_data = Self::ok_text(lable.to_string(), text);
                     res_data.time = get_time_microsecond();
                     if res_data.code == "-201" {

+ 135 - 0
exchanges/tests/bitget_spot_test.rs

@@ -0,0 +1,135 @@
+use std::collections::BTreeMap;
+use std::sync::Arc;
+use std::sync::atomic::AtomicBool;
+use tokio::sync::mpsc::{channel, Sender};
+use tokio::try_join;
+use tracing::trace;
+use exchanges::binance_swap_rest::BinanceSwapRest;
+use exchanges::binance_swap_ws::{BinanceSubscribeType, BinanceSwapWs, BinanceWsType};
+use exchanges::bitget_spot_ws::{BitgetSubscribeType, BitgetSwapWs, BitgetWsType};
+use exchanges::kucoin_swap_rest::KucoinSwapRest;
+use exchanges::kucoin_swap_ws::{KucoinSubscribeType, KucoinSwapWs, KucoinWsType};
+use exchanges::proxy;
+use exchanges::response_base::ResponseData;
+
+const ACCESS_KEY: &str = "";
+const SECRET_KEY: &str = "";
+const PASS_KEY: &str = "";
+
+//ws-订阅公共频道信息
+#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
+async fn ws_custom_subscribe_pu() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bool_v1 = Arc::new(AtomicBool::new(true));
+    let btree_map: BTreeMap<String, String> = BTreeMap::new();
+    let (tx, mut rx) = channel(1024);
+    let mut ws = get_ws(btree_map, BitgetWsType::Public, tx).await;
+    ws.set_subscribe(vec![
+        BitgetSubscribeType::PuTicker,
+        BitgetSubscribeType::PuCandle1m,
+        BitgetSubscribeType::PuTrade,
+        BitgetSubscribeType::PuBooks5,
+    ]);
+    let t1 = tokio::spawn(async move {
+        ws.custom_subscribe(bool_v1, vec!["BTC_USDT".to_string()]).await;
+    });
+    let t2 = tokio::spawn(async move {
+        loop {
+            if let Ok(received) = rx.try_recv() {
+                trace!( "age: {:?}", received);
+            }
+        }
+    });
+    try_join!(t1,t2).unwrap();
+}
+
+//ws-订阅私有频道信息
+#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
+async fn ws_custom_subscribe_pr() {
+    global::log_utils::init_log_with_trace();
+
+    let mut bool_v1 = Arc::new(AtomicBool::new(true));
+    let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
+    btree_map.insert("access_key".to_string(), ACCESS_KEY.to_string());
+    btree_map.insert("secret_key".to_string(), SECRET_KEY.to_string());
+    btree_map.insert("pass_key".to_string(), PASS_KEY.to_string());
+    let (tx, mut rx) = channel(1024);
+    let mut ws = get_ws(btree_map, BitgetWsType::Private, tx).await;
+    ws.set_subscribe(vec![
+        BitgetSubscribeType::PrAccount,
+        BitgetSubscribeType::PrOrders,
+    ]);
+    let t1 = tokio::spawn(async move {
+        ws.custom_subscribe(bool_v1, vec!["BTC_USDT".to_string()]).await;
+    });
+    let t2 = tokio::spawn(async move {
+        loop {
+            if let Ok(received) = rx.try_recv() {
+                trace!( "age: {:?}", received);
+            }
+        }
+    });
+    try_join!(t1,t2).unwrap();
+}
+
+
+//rest-撤销全部订单
+#[tokio::test]
+async fn rest_get_server_time_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.cancel_orders("BLZUSDTM".to_string()).await;
+    trace!(?rep_data)
+}
+
+
+//rest-杠杆测试
+#[tokio::test]
+async fn rest_leverage_test() {
+    global::log_utils::init_log_with_trace();
+
+    // //查询杠杆
+    let mut rest = get_rest();
+    // let rep_data = rest.get_leverage("ADAUSDTM".to_string()).await;
+    // trace!("查询杠杆{:?}",rep_data);
+
+    //设置杠杆
+    let rep_data2 = rest.set_leverage("BLZUSDTM".to_string(), 1).await;
+    trace!("设置杠杆{:?}",rep_data2);
+
+    // //查询杠杆
+    // let rep_data3 = rest.get_leverage("BLZUSDTM".to_string()).await;
+    // trace!("查询杠杆{:?}",rep_data3);
+}
+
+//rest-设置自动开启补仓
+#[tokio::test]
+async fn rest_auto_deposit_test() {
+    global::log_utils::init_log_with_trace();
+
+    //设置是否自动补仓
+    let mut rest = get_rest();
+    let rep_data = rest.auto_deposit_status("BLZUSDTM".to_string(), false).await;
+    trace!("设置是否自动补仓{:?}",rep_data);
+}
+
+
+async fn get_ws(btree_map: BTreeMap<String, String>, type_v: BitgetWsType, tx: Sender<ResponseData>) -> BitgetSwapWs {
+    let mut ku_ws = BitgetSwapWs::new(false, btree_map.clone(),
+                                      type_v, tx);
+    ku_ws
+}
+
+fn get_rest() -> KucoinSwapRest {
+    let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
+    // btree_map.insert("access_key".to_string(), ACCESS_KEY.to_string());
+    // btree_map.insert("secret_key".to_string(), SECRET_KEY.to_string());
+    btree_map.insert("access_key".to_string(), ACCESS_KEY.to_string());
+    btree_map.insert("secret_key".to_string(), SECRET_KEY.to_string());
+    btree_map.insert("pass_key".to_string(), PASS_KEY.to_string());
+
+    let mut ku_exc = KucoinSwapRest::new(false, btree_map);
+    ku_exc
+}