Răsfoiți Sursa

优化代码

875428575@qq.com 2 ani în urmă
părinte
comite
f692d1fc69

+ 6 - 6
exchanges/src/binance_usdt_swap_rest.rs

@@ -4,6 +4,7 @@ use ring::hmac;
 use hex;
 use crate::http_tool::RestTool;
 use crate::response_base::ResponseData;
+
 #[derive(Clone)]
 pub struct BinanceUsdtSwapRest {
     /*******参数*/
@@ -18,13 +19,12 @@ impl BinanceUsdtSwapRest {
     /*******************************************************************************************************/
     pub fn new(is_colo: bool, login_param: BTreeMap<String, String>) -> BinanceUsdtSwapRest
     {
-        let mut base_url = "".to_string();
-        if is_colo {
+        let  base_url = if is_colo {
             println!("不支持colo高速线路");
-            base_url = "https://fapi.binance.com".to_string()
+            "https://fapi.binance.com".to_string()
         } else {
-            base_url = "https://fapi.binance.com".to_string()
-        }
+            "https://fapi.binance.com".to_string()
+        };
 
         /*****返回结构体*******/
         BinanceUsdtSwapRest {
@@ -77,7 +77,7 @@ impl BinanceUsdtSwapRest {
     }
 
     //生成sign,重新组装param
-    fn get_sign(&self,  params_str: String) -> String {
+    fn get_sign(&self, params_str: String) -> String {
         let mut params: serde_json::Value = serde_json::from_str(params_str.clone().as_str()).unwrap();
         if let Some(map) = params.as_object_mut() {
             map.insert("timestamp".to_owned(), chrono::Utc::now().timestamp_millis().to_string().parse().unwrap());

+ 4 - 6
exchanges/src/binance_usdt_swap_ws.rs

@@ -13,7 +13,6 @@ use url::Url;
 
 #[derive(Clone)]
 pub struct BinanceUsdtSwapWs {
-    /*******参数*/
     //连接地址
     request_url: String,
     //ip
@@ -75,7 +74,7 @@ impl BinanceUsdtSwapWs {
             b_name = format!("{}@{}", b_name, "kline_1s");
             params.push(b_name);
         }
-        self.run(b_array, params);
+        self.run(params);
     }
 
     //自定义-不需要认证
@@ -94,7 +93,7 @@ impl BinanceUsdtSwapWs {
                 params.push(format!("{}@depth20@100ms", b_name));
             }
         }
-        self.run(b_array, params);
+        self.run(params);
     }
 
     /*******************************************************************************************************/
@@ -104,7 +103,7 @@ impl BinanceUsdtSwapWs {
     /*******************************************************************************************************/
     /*****************************************socket基本*****************************************************/
     /*******************************************************************************************************/
-    fn run(&self, b_array: Vec<&str>, params: Vec<String>)
+    fn run(&self, params: Vec<String>)
     {
         //订阅信息组装
         let subscription = json!({
@@ -145,7 +144,7 @@ impl BinanceUsdtSwapWs {
                     }
                 };
             } else {
-                let no_proxy_ws = match connect(request_url.clone()) {
+                match connect(request_url.clone()) {
                     Ok(ws) => {
                         self.subscription(ws.0, &subscription);
                     }
@@ -159,7 +158,6 @@ impl BinanceUsdtSwapWs {
             }
             println!("退出来咯")
         }
-
     }
 
     //代理

+ 9 - 12
exchanges/src/gate_swap_rest.rs

@@ -1,5 +1,4 @@
 use std::collections::BTreeMap;
-use std::fmt::format;
 use reqwest::header::HeaderMap;
 use ring::{digest};
 use hex;
@@ -8,7 +7,6 @@ use reqwest::Client;
 use crate::http_tool::RestTool;
 use crate::response_base::ResponseData;
 use sha2::Sha512;
-use crate::OrderType;
 
 #[derive(Clone)]
 pub struct GateSwapRest {
@@ -227,7 +225,7 @@ impl GateSwapRest {
     //交易账户互转
     pub async fn wallet_transfers(&self, currency: String, from: String, to: String, amount: String, settle: String) -> ResponseData {
         let params = serde_json::json!({
-                "currency":settle,
+                "currency":currency,
                 "from":from,
                 "to":to,
                 "amount":amount,
@@ -335,7 +333,6 @@ impl GateSwapRest {
 
         //请求头配置-如果需要登陆则存在额外配置
         let mut body = "".to_string();
-        let mut sing = "".to_string();
         let timestamp = chrono::Utc::now().timestamp().to_string();
 
         let mut headers = HeaderMap::new();
@@ -358,13 +355,13 @@ impl GateSwapRest {
                 return e;
             } else {//需要登陆-且登陆参数齐全
                 //组装sing
-                sing = Self::sign(secret_key.clone(),
-                                  requesst_type.clone(),
-                                  prefix_url.clone(),
-                                  request_url.clone(),
-                                  params.clone(),
-                                  body.clone(),
-                                  timestamp.clone(),
+                let sing = Self::sign(secret_key.clone(),
+                                      requesst_type.clone(),
+                                      prefix_url.clone(),
+                                      request_url.clone(),
+                                      params.clone(),
+                                      body.clone(),
+                                      timestamp.clone(),
                 );
                 // println!("sing:{}", sing);
                 //组装header
@@ -430,7 +427,7 @@ impl GateSwapRest {
         let url = format!("{}{}", self.base_url.to_string(), request_path);
         let request_type = request_type.clone().to_uppercase();
         let addrs_url = format!("{}?{}", url.clone(), RestTool::parse_params_to_str(params.clone()));
-        let params_json: serde_json::Value = serde_json::from_str(&params).unwrap();
+        // let params_json: serde_json::Value = serde_json::from_str(&params).unwrap();
         // println!("url:{}",url);
         // println!("addrs_url:{}",url);
         // println!("params_json:{}",params_json);

+ 3 - 2
exchanges/src/kucoin_swap_rest.rs

@@ -5,6 +5,7 @@ use reqwest::{Client};
 use sha2::Sha256;
 use crate::http_tool::RestTool;
 use crate::response_base::ResponseData;
+
 #[derive(Clone, Debug)]
 pub struct KucoinSwapRest {
     base_url: String,
@@ -227,7 +228,7 @@ impl KucoinSwapRest {
 
     //获取合约令牌-公共
     pub async fn get_public_token(&self) -> ResponseData {
-        let mut params = serde_json::json!({});
+        let params = serde_json::json!({});
         let data = self.request("POST".to_string(),
                                 "/api/v1".to_string(),
                                 "/bullet-public".to_string(),
@@ -238,7 +239,7 @@ impl KucoinSwapRest {
     }
     //获取合约令牌-私有
     pub async fn get_private_token(&self) -> ResponseData {
-        let mut params = serde_json::json!({});
+        let  params = serde_json::json!({});
         let data = self.request("POST".to_string(),
                                 "/api/v1".to_string(),
                                 "/bullet-private".to_string(),

+ 88 - 55
exchanges/src/kuconin_swap_ws.rs

@@ -1,16 +1,10 @@
 use std::collections::{BTreeMap, HashSet};
-use std::error::Error;
-use std::future::Future;
 use std::io;
 use std::io::{Write};
 use std::net::{IpAddr, Ipv4Addr, SocketAddr};
 use std::sync::{mpsc};
-use std::thread::sleep;
-use hmac::{NewMac};
-use serde_json::{json, Value};
-use serde_json::map::Values;
-use tokio::runtime::Runtime;
-use crate::{proxy, WsType};
+use serde_json::{json};
+use crate::{proxy};
 use tungstenite::client::{AutoStream, connect_with_proxy, ProxyAutoStream};
 use tungstenite::{connect, Message, WebSocket};
 use tungstenite::protocol::WebSocketConfig;
@@ -19,9 +13,14 @@ use crate::kucoin_swap_rest::KucoinSwapRest;
 use crate::proxy::ParsingDetail;
 use crate::response_base::ResponseData;
 
+pub enum KuconinWsType {
+    Public,
+    Private,
+}
+
 #[derive(Debug)]
 #[derive(Clone)]
-pub struct WsParam {
+pub struct KuconinWsParam {
     pub token: String,
     pub ws_url: String,
     pub ws_ping_interval: i64,
@@ -29,7 +28,7 @@ pub struct WsParam {
 }
 
 #[derive(Clone)]                        //订阅枚举
-pub enum SubscribeType {
+pub enum KuconinSubscribeType {
     PuContractMarketLevel2Depth50,
     PuContractMarketExecution,
 
@@ -41,12 +40,18 @@ pub enum SubscribeType {
 
 #[derive(Clone)]
 pub struct KuconinSwapWs {
-    request_url: String,                    //实际ws 链接地址
-    proxy: ParsingDetail,                   //代理信息
-    login_param: BTreeMap<String, String>,  //登陆数据
-    ws_param: WsParam,                      //kuconis特殊参数
-    symbol_s: Vec<String>,                  //订阅币对
-    subscribe_types: Vec<SubscribeType>,    //订阅信息
+    request_url: String,
+    //实际ws 链接地址
+    proxy: ParsingDetail,
+    //代理信息
+    login_param: BTreeMap<String, String>,
+    //登陆数据
+    ws_param: KuconinWsParam,
+    //kuconis特殊参数
+    symbol_s: Vec<String>,
+    //订阅币对
+    subscribe_types: Vec<KuconinSubscribeType>,
+    //订阅信息
     sender: mpsc::Sender<ResponseData>,     //数据通道
 }
 
@@ -56,7 +61,7 @@ impl KuconinSwapWs {
     /*******************************************************************************************************/
     pub async fn new(is_colo: bool,
                      login_param: BTreeMap<String, String>,
-                     ws_type: WsType,
+                     ws_type: KuconinWsType,
                      sender: mpsc::Sender<ResponseData>,
     ) -> KuconinSwapWs
     {
@@ -68,7 +73,7 @@ impl KuconinSwapWs {
         let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
 
         /*******公共频道-私有频道数据组装*/
-        let mut ws_param = WsParam {
+        let mut ws_param = KuconinWsParam {
             token: "".to_string(),
             ws_url: "".to_string(),
             ws_ping_interval: 0,
@@ -99,21 +104,20 @@ impl KuconinSwapWs {
     /*****************************************订阅函数********************************************************/
     /*******************************************************************************************************/
     //手动添加订阅信息
-    pub fn set_subscribe(&mut self, subscribe_types: Vec<SubscribeType>) {
+    pub fn set_subscribe(&mut self, subscribe_types: Vec<KuconinSubscribeType>) {
         self.subscribe_types.extend(subscribe_types);
     }
     //根据当前类型获取对应的频道 地址 与 token
-    async fn get_rul_token(ws_type: WsType, login_param: BTreeMap<String, String>) -> Result<WsParam, reqwest::Error> {
+    async fn get_rul_token(ws_type: KuconinWsType, login_param: BTreeMap<String, String>) -> Result<KuconinWsParam, reqwest::Error> {
         let kucoin_exc = KucoinSwapRest::new(false, login_param.clone());
-        let mut res_data = ResponseData::error("等待数据~~~".to_string());
-        match ws_type {
-            WsType::Public => {
-                res_data = kucoin_exc.get_public_token().await;
+        let res_data = match ws_type {
+            KuconinWsType::Public => {
+                kucoin_exc.get_public_token().await
             }
-            WsType::Private => {
-                res_data = kucoin_exc.get_private_token().await;
+            KuconinWsType::Private => {
+                kucoin_exc.get_private_token().await
             }
-        }
+        };
 
         if res_data.code == "200" {
             let mut ws_url = "".to_string();
@@ -134,15 +138,15 @@ impl KuconinSwapWs {
             if let Some(endpoint) = parsed_json["instanceServers"][0]["endpoint"].as_str() {
                 ws_url = format!("{}", endpoint);
             }
-            if let Some(pingInterval) = parsed_json["instanceServers"][0]["pingInterval"].as_i64() {
-                ws_ping_interval = pingInterval;
+            if let Some(ping_interval) = parsed_json["instanceServers"][0]["pingInterval"].as_i64() {
+                ws_ping_interval = ping_interval;
             }
-            if let Some(pingTimeout) = parsed_json["instanceServers"][0]["pingTimeout"].as_i64() {
-                ws_ping_timeout = pingTimeout;
+            if let Some(ping_timeout) = parsed_json["instanceServers"][0]["pingTimeout"].as_i64() {
+                ws_ping_timeout = ping_timeout;
             }
 
 
-            Ok(WsParam { ws_url, token: ws_token, ws_ping_interval, ws_ping_timeout })
+            Ok(KuconinWsParam { ws_url, token: ws_token, ws_ping_interval, ws_ping_timeout })
         } else {
             panic!("公共/私有-频道获取失败:{:?}", res_data)
         }
@@ -159,24 +163,24 @@ impl KuconinSwapWs {
     /*****************************************工具函数********************************************************/
     /*******************************************************************************************************/
     //订阅枚举解析
-    pub fn enum_to_string(symbol: String, subscribe_type: SubscribeType) -> String {
+    pub fn enum_to_string(symbol: String, subscribe_type: KuconinSubscribeType) -> String {
         match subscribe_type {
-            SubscribeType::PuContractMarketLevel2Depth50 => {
+            KuconinSubscribeType::PuContractMarketLevel2Depth50 => {
                 format!("/contractMarket/level2Depth50:{}", symbol)
             }
-            SubscribeType::PuContractMarketExecution => {
+            KuconinSubscribeType::PuContractMarketExecution => {
                 format!("/contractMarket/execution:{}", symbol)
             }
-            SubscribeType::PrContractAccountWallet => {
+            KuconinSubscribeType::PrContractAccountWallet => {
                 format!("/contractAccount/wallet")
             }
-            SubscribeType::PrContractPosition => {
+            KuconinSubscribeType::PrContractPosition => {
                 format!("/contract/position:{}", symbol)
             }
-            SubscribeType::PrContractMarketTradeOrdersSys => {
+            KuconinSubscribeType::PrContractMarketTradeOrdersSys => {
                 format!("/contractMarket/tradeOrders")
             }
-            SubscribeType::PrContractMarketTradeOrders => {
+            KuconinSubscribeType::PrContractMarketTradeOrders => {
                 format!("/contractMarket/tradeOrders:{}", symbol)
             }
         }
@@ -226,8 +230,8 @@ impl KuconinSwapWs {
                     accept_unmasked_frames: false,
                 });
                 let max_redirects = 5;
-                match connect_with_proxy(request_url.clone(),
-                                         proxy_address, websocket_config, max_redirects) {
+                let _ = match connect_with_proxy(request_url.clone(),
+                                                 proxy_address, websocket_config, max_redirects) {
                     Ok(ws) => {
                         self.proxy_subscription(ws.0, subscription.clone());
                     }
@@ -236,7 +240,7 @@ impl KuconinSwapWs {
                     }
                 };
             } else {
-                let no_proxy_ws = match connect(request_url.clone()) {
+                let _ = match connect(request_url.clone()) {
                     Ok(ws) => {
                         self.subscription(ws.0, subscription.clone());
                     }
@@ -275,7 +279,7 @@ impl KuconinSwapWs {
                         }
                     } else {
                         //心跳-一定时间间隔发送心跳
-                        let mut get_time = chrono::Utc::now().timestamp_millis();
+                        let  get_time = chrono::Utc::now().timestamp_millis();
                         // println!("--心跳-{}-{}-{}-{}-{}", get_time, ping_interval
                         //          , (get_time - ping_interval), self.ws_param.ws_ping_interval, (get_time - ping_interval) >= self.ws_param.ws_ping_interval);
                         if (get_time - ping_interval) >= self.ws_param.ws_ping_interval {
@@ -322,30 +326,60 @@ impl KuconinSwapWs {
     fn subscription(&self, mut web_socket: WebSocket<AutoStream>,
                     subscription: Vec<String>)
     {
+        /*****消息溜***/
+        let mut stdout = io::stdout();
+        let mut ping_interval = chrono::Utc::now().timestamp_millis();
+        let mut ping_timeout = chrono::Utc::now().timestamp_millis();
         loop {
             let msg = web_socket.read_message();
             match msg {
                 Ok(Message::Text(text)) => {
+                    // writeln!(stdout, "Text-响应--{:?}", text.clone()).unwrap();
                     let res_data = Self::ok_text(text);
-                    self.sender.send(res_data).unwrap();
-                    // writeln!(stdout, "Pong-响应--{:?}", res_data).unwrap();
-                    // let parse_fn_clone = Arc::clone(parse_fn); // Clone the Arc for each iteration
-                    // tokio::spawn(async move {
-                    //     let parse_fn_lock = parse_fn_clone.lock().await;
-                    //     parse_fn_lock(res_data).await;
-                    // });
+
+                    if res_data.code == "-200" {//表示链接成功
+                        for sub in &subscription {
+                            println!("--订阅-成功-内容:{:?}", sub);
+                            web_socket.write_message(Message::Text(sub.parse().unwrap()))
+                                .unwrap();
+                        }
+                    } else {
+                        //心跳-一定时间间隔发送心跳
+                        let  get_time = chrono::Utc::now().timestamp_millis();
+                        // println!("--心跳-{}-{}-{}-{}-{}", get_time, ping_interval
+                        //          , (get_time - ping_interval), self.ws_param.ws_ping_interval, (get_time - ping_interval) >= self.ws_param.ws_ping_interval);
+                        if (get_time - ping_interval) >= self.ws_param.ws_ping_interval {
+                            web_socket.write_message(Message::Ping(Vec::from("ping")))
+                                .unwrap();
+                            println!("--发送心跳-ping");
+                            ping_interval = get_time;
+                            ping_timeout = get_time;
+                        } else if (get_time - ping_timeout) > (self.ws_param.ws_ping_timeout + self.ws_param.ws_ping_interval) {
+                            //心跳超时-发送心跳之后 一定时间没有响应
+                            println!("--心跳相应超时-重连");
+                            break;
+                        }
+
+                        self.sender.send(res_data).unwrap();
+                    }
                 }
                 Ok(Message::Ping(s)) => {
-                    println!("Ping-响应--{:?}", String::from_utf8(s));
+                    writeln!(stdout, "Ping-响应--{:?}", String::from_utf8(s.clone())).unwrap();
+                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+                    writeln!(stdout, "回应-pong---{:?}", String::from_utf8(s.clone())).unwrap();
                 }
                 Ok(Message::Pong(s)) => {
-                    println!("Pong-响应--{:?}", String::from_utf8(s));
+                    // println!("Pong-响应--{:?}", String::from_utf8(s));
+                    writeln!(stdout, "Pong-响应--{:?}", String::from_utf8(s.clone())).unwrap();
+                    ping_timeout = chrono::Utc::now().timestamp_millis();
                 }
                 Ok(Message::Close(_)) => {
-                    println!("socket 关闭: ");
+                    // println!("socket 关闭: ");
+                    writeln!(stdout, "Close-响应").unwrap();
                 }
                 Err(error) => {
-                    println!("Error receiving message: {}", error);
+                    // println!("Error receiving message: {}", error);
+                    writeln!(stdout, "Err-响应{}", error).unwrap();
                     break;
                 }
                 _ => {}
@@ -370,7 +404,6 @@ impl KuconinSwapWs {
             }
         } else if json_value.get("topic").is_some() {
             let topic = json_value["topic"].to_string();
-            let parts: Vec<&str> = topic.split(':').collect();
             res_data.channel = topic.to_string();
             res_data.data = json_value["data"].to_string();
         } else {

+ 1 - 12
exchanges/src/lib.rs

@@ -12,17 +12,6 @@ pub mod gate_swap_rest;
 pub mod socket_tool;
 pub mod kucoin_swap_rest;
 pub mod kuconin_swap_ws;
+pub mod okx_swap_ws;
 
 
-pub enum WsType {
-    Public,
-    Private,
-}
-
-pub enum OrderType {
-    LongBuy,
-    LongSell,
-    ShortSell,
-    ShortBuy,
-}
-

+ 357 - 0
exchanges/src/okx_swap_ws.rs

@@ -0,0 +1,357 @@
+use std::collections::{BTreeMap};
+use std::{io, thread};
+use std::io::{Write};
+use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+use std::sync::{mpsc};
+use std::time::Duration;
+use chrono::Utc;
+use serde_json::{json, Value};
+use ring::hmac;
+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;
+
+pub enum OkxWsType {
+    //订阅频道类型
+    Public,
+    Private,
+    Business,
+}
+
+
+#[derive(Clone)]                        //订阅枚举
+pub enum OkxSubscribeType {
+    BuIndexCandle30m,
+    //
+    PuIndexTickers,
+    //
+    PrAccount(String),
+}
+
+#[derive(Clone)]
+pub struct OkxSwapWs {
+    request_url: String,
+    //实际ws 链接地址
+    proxy: ParsingDetail,
+    //账号信息
+    login_param: BTreeMap<String, String>,
+    //kuconis特殊参数
+    symbol_s: Vec<String>,
+    //订阅币对
+    subscribe_types: Vec<OkxSubscribeType>,
+    //订阅信息
+    sender: mpsc::Sender<ResponseData>,     //数据通道
+}
+
+impl OkxSwapWs {
+    /*******************************************************************************************************/
+    /*****************************************获取一个对象****************************************************/
+    /*******************************************************************************************************/
+    pub async fn new(is_colo: bool,
+                     login_param: BTreeMap<String, String>,
+                     ws_type: OkxWsType,
+                     sender: mpsc::Sender<ResponseData>,
+    ) -> OkxSwapWs
+    {
+        if is_colo {
+            println!("不支持高速通道")
+        }
+
+        /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
+        let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
+
+        /*******公共频道-私有频道数据组装*/
+        let  request_url = match ws_type {
+            OkxWsType::Public => {
+                "wss://ws.okx.com:8443/ws/v5/public".to_string()
+            }
+            OkxWsType::Private => {
+                "wss://ws.okx.com:8443/ws/v5/private".to_string()
+            }
+            OkxWsType::Business => {
+                "wss://ws.okx.com:8443/ws/v5/business".to_string()
+            }
+        };
+
+        /*****返回结构体*******/
+        OkxSwapWs {
+            request_url,
+            proxy: parsing_detail,
+            login_param,
+            symbol_s: vec![],
+            subscribe_types: vec![],
+            sender,
+        }
+    }
+
+    /*******************************************************************************************************/
+    /*****************************************订阅函数********************************************************/
+    /*******************************************************************************************************/
+    //手动添加订阅信息
+    pub fn set_subscribe(&mut self, subscribe_types: Vec<OkxSubscribeType>) {
+        self.subscribe_types.extend(subscribe_types);
+    }
+    //自定义
+    pub fn custom_subscribe(&mut self, 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("_", "-");
+        }
+        self.symbol_s = symbol_s;
+        self.run();
+    }
+
+    /*******************************************************************************************************/
+    /*****************************************工具函数********************************************************/
+    /*******************************************************************************************************/
+    //订阅枚举解析
+    pub fn enum_to_string(symbol: String, subscribe_type: OkxSubscribeType) -> Value {
+        match subscribe_type {
+            OkxSubscribeType::BuIndexCandle30m => {
+                json!({
+                    "channel":"index-candle30m",
+                    "instId":symbol
+                })
+            }
+            OkxSubscribeType::PuIndexTickers => {
+                json!({
+                    "channel":"index-tickers",
+                    "instId":symbol
+                })
+            }
+            OkxSubscribeType::PrAccount(ccy) => {
+                json!({
+                    "channel":"account",
+                    "ccy":ccy
+                })
+            }
+        }
+    }
+    //组装订阅数据
+    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
+        });
+
+        println!("订阅信息:{}", str.to_string());
+
+        str.to_string()
+    }
+
+    //组装登陆数据
+    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 == "passphrase" {
+                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, "/users/self/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  }]
+                        });
+
+            println!("---login_json:{0}", login_json.to_string());
+            println!("--登陆:{:?}", login_json);
+            login_json_str = login_json.to_string();
+        }
+        login_json_str
+    }
+    /*******************************************************************************************************/
+    /*****************************************socket基本*****************************************************/
+    /*******************************************************************************************************/
+    fn run(&mut self)
+    {
+        //订阅信息组装
+        let subscription = self.get_subscription();
+        loop {
+            println!("要连接咯~~!!{}", 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) => {
+                        self.proxy_subscription(ws.0, subscription.clone());
+                    }
+                    Err(err) => {
+                        println!("Can't connect(无法连接): {}", err);
+                    }
+                };
+            } else {
+                match connect(request_url.clone()) {
+                    Ok(ws) => {
+                        self.subscription(ws.0, subscription.clone());
+                    }
+                    Err(err) => {
+                        // 连接失败时执行的操作
+                        println!("Can't connect(无法连接): {}", err);
+                        // 返回一个默认的 WebSocket 对象或其他适当的值
+                        // 或者根据需要触发 panic 或返回错误信息
+                    }
+                };
+            }
+            println!("退出来咯")
+        }
+    }
+
+    //代理
+    fn proxy_subscription(&self, mut web_socket: WebSocket<ProxyAutoStream>, subscription: String)
+    {
+        /*****登陆***/
+        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));
+        }
+        /*****订阅***/
+        web_socket.write_message(Message::Text(subscription))
+            .unwrap();
+        /*****消息溜***/
+        let mut stdout = io::stdout();
+        loop {
+            let msg = web_socket.read_message();
+            match msg {
+                Ok(Message::Text(text)) => {
+                    let res_data = Self::ok_text(text);
+                    if res_data.code == "-200" {
+                        writeln!(stdout, "订阅成功:{:?}", res_data.data).unwrap();
+                    } else {
+                        self.sender.send(res_data).unwrap();
+                    }
+                }
+                Ok(Message::Ping(s)) => {
+                    writeln!(stdout, "Ping-响应--{:?}", String::from_utf8(s.clone())).unwrap();
+                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+                    writeln!(stdout, "回应-pong---{:?}", String::from_utf8(s.clone())).unwrap();
+                }
+                Ok(Message::Pong(s)) => {
+                    // println!("Pong-响应--{:?}", String::from_utf8(s));
+                    writeln!(stdout, "Pong-响应--{:?}", String::from_utf8(s.clone())).unwrap();
+                }
+                Ok(Message::Close(_)) => {
+                    // println!("socket 关闭: ");
+                    writeln!(stdout, "Close-响应").unwrap();
+                }
+                Err(error) => {
+                    // println!("Error receiving message: {}", error);
+                    writeln!(stdout, "Err-响应{}", error).unwrap();
+                    break;
+                }
+                _ => {}
+            }
+        }
+        web_socket.close(None).unwrap();
+    }
+
+    //非代理
+    fn subscription(&self, mut web_socket: WebSocket<AutoStream>,
+                    subscription: String)
+    {
+        /*****订阅***/
+        web_socket.write_message(Message::Text(subscription))
+            .unwrap();
+        /*****消息溜***/
+        let mut stdout = io::stdout();
+        loop {
+            let msg = web_socket.read_message();
+            match msg {
+                Ok(Message::Text(text)) => {
+                    let res_data = Self::ok_text(text);
+                    if res_data.code == "-200" {
+                        writeln!(stdout, "订阅成功:{:?}", res_data.data).unwrap();
+                    } else {
+                        self.sender.send(res_data).unwrap();
+                    }
+                }
+                Ok(Message::Ping(s)) => {
+                    println!("Ping-响应--{:?}", String::from_utf8(s));
+                }
+                Ok(Message::Pong(s)) => {
+                    println!("Pong-响应--{:?}", String::from_utf8(s));
+                }
+                Ok(Message::Close(_)) => {
+                    println!("socket 关闭: ");
+                }
+                Err(error) => {
+                    println!("Error receiving message: {}", error);
+                    break;
+                }
+                _ => {}
+            }
+        }
+        web_socket.close(None).unwrap();
+    }
+
+    //数据解析
+    pub fn ok_text(text: String) -> ResponseData
+    {
+        let mut res_data = ResponseData::new("200".to_string(), "success".to_string(), "".to_string());
+        let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
+        if json_value.get("event").is_some() {//订阅返回
+            if json_value["event"].as_str() == Option::from("error") {
+                res_data.code = json_value["code"].to_string();
+                res_data.message = format!("错误:{}", json_value["msg"].to_string());
+            } else if json_value["event"].as_str() == Option::from("subscribe") {
+                res_data.code = "-200".to_string();
+                res_data.data = text;
+            } else {
+                res_data.data = text
+            }
+        } else {
+            res_data.data = text
+        }
+        res_data
+    }
+}

+ 0 - 189
exchanges/src/socket_tool.rs

@@ -1,189 +0,0 @@
-// use std::io;
-// use std::io::{Write};
-// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-// use crate::proxy;
-// use tungstenite::client::{AutoStream, connect_with_proxy, ProxyAutoStream};
-// use tungstenite::{Message, WebSocket};
-// use tungstenite::protocol::WebSocketConfig;
-// use url::Url;
-// use crate::proxy::ParsingDetail;
-// use crate::socket_tool::WsType::{WsNone, WsP};
-//
-//
-// pub enum WsType {
-//     WsP(WebSocket<ProxyAutoStream>),
-//     Ws(WebSocket<AutoStream>),
-//     WsNone(String),
-// }
-//
-//
-// #[derive(Debug)]
-// pub struct WsProxy {
-//     socket: Option<WebSocket<ProxyAutoStream>>,
-//     proxy: ParsingDetail,
-// }
-//
-// impl WsProxy {
-//     pub fn new(proxy: ParsingDetail) -> WsProxy {
-//         WsProxy { socket: None, proxy }
-//     }
-//     pub fn connect(&mut self, base_url: String) {
-//         loop {
-//             println!("--开始链接:");
-//             let request_url = Url::parse(base_url.as_str()).unwrap();
-//
-//             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;
-//             let ws = match connect_with_proxy(request_url.clone(), proxy_address, websocket_config, max_redirects) {
-//                 Ok((socket, res)) => {
-//                     socket
-//                 }
-//                 Err(err) => {
-//                     println!("连接代理失败:{:?},重连启动", err);
-//                     continue;
-//                 }
-//             };
-//             self.socket = Option::from(ws);
-//         }
-//     }
-//     pub fn subscription(ws_proxy: &WsProxy) {
-//         loop {}
-//     }
-// }
-//
-// #[derive(Debug)]
-// pub struct WsNoProxy {}
-//
-// impl WsNoProxy {
-//     pub fn new() -> WsNoProxy {
-//         WsNoProxy {}
-//     }
-//     pub fn connect(&mut self, base_url: String, proxy_ip: String, proxy_port: u16) -> Result<bool, bool> {
-//         Ok(true)
-//     }
-// }
-//
-// pub struct WsTool {
-//     base_url: String,
-//     ws_type: WsType,
-//     proxy: ParsingDetail,
-// }
-//
-// impl WsTool {
-//     pub fn new(base_url: String) -> WsTool {
-//         /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
-//         let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
-//         if parsing_detail.ip_address.len() > 0 && parsing_detail.port.len() > 0 {
-//             WsTool { base_url, ws_type: WsP(""), proxy: parsing_detail }
-//         } else {
-//             WsTool { base_url, ws_type: WsType::Ws(WebSocket::<AutoStream>::new()), proxy: parsing_detail }
-//         }
-//     }
-//     pub fn connect(&mut self) {
-//         let mut res = false;
-//         match &self.ws_type {
-//             WsType::WsP(ws_p) => {
-//                 self.proxy_connect();
-//             }
-//             WsType::Ws(ws_p) => {
-//                 self.proxy_connect();
-//             }
-//             WsNone(ws_none) => {}
-//         }
-//     }
-//     pub fn read(&mut self) {
-//         let mut res = false;
-//         match &self.ws_type {
-//             WsType::WsP(ws_p) => {
-//                 println!("????????");
-//                 loop {
-//                     println!("1231321");
-//                 }
-//             }
-//             WsType::Ws(ws_p) => {}
-//             WsNone(ws_none) => {}
-//         }
-//     }
-//
-//
-//     /**读取*/
-//     // pub fn proxy_read(mut ws_p: &WebSocket<ProxyAutoStream>) {
-//     //     /*****消息溜***/
-//     //     let mut stdout = io::stdout();
-//     //     let mut stderr = io::stderr();
-//     //     /******订阅信息********/
-//     //     loop {
-//     //         let msg =ws_p.read_message();
-//     //         match msg {
-//     //             Ok(Message::Text(text)) => {
-//     //                 writeln!(stdout, "Text-响应--{:?}", text.clone()).unwrap();
-//     //             }
-//     //             Ok(Message::Ping(s)) => {
-//     //                 writeln!(stdout, "Ping-响应--{:?}", String::from_utf8(s.clone())).unwrap();
-//     //                 let _ = ws_p.write_message(Message::Pong(Vec::from("pong")));
-//     //                 writeln!(stdout, "回应-pong---{:?}", String::from_utf8(s.clone())).unwrap();
-//     //             }
-//     //             Ok(Message::Pong(s)) => {
-//     //                 // println!("Pong-响应--{:?}", String::from_utf8(s));
-//     //                 writeln!(stdout, "Pong-响应--{:?}", String::from_utf8(s.clone())).unwrap();
-//     //             }
-//     //             Ok(Message::Close(_)) => {
-//     //                 // println!("socket 关闭: ");
-//     //                 writeln!(stdout, "Close-响应").unwrap();
-//     //             }
-//     //             Err(error) => {
-//     //                 // println!("Error receiving message: {}", error);
-//     //                 writeln!(stdout, "Err-响应{}", error).unwrap();
-//     //                 break;
-//     //             }
-//     //             _ => {}
-//     //         }
-//     //     }
-//     //     ws_p.close(None).unwrap();
-//     // }
-//
-//     /**链接*/
-//     //代理
-//     pub fn proxy_connect(&mut self) {
-//         println!("--开始链接:");
-//         let request_url = Url::parse(self.base_url.as_str()).unwrap();
-//
-//         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;
-//         let ws = match connect_with_proxy(request_url.clone(), proxy_address, websocket_config, max_redirects) {
-//             Ok((socket, res)) => {
-//                 socket
-//             }
-//             Err(err) => {
-//                 println!("连接代理失败:{:?},重连启动", err);
-//                 return;
-//             }
-//         };
-//         self.ws_type = WsP(ws);
-//     }
-//     //非代理
-// }

+ 297 - 20
exchanges/tests/test.rs

@@ -1,23 +1,300 @@
-use std::collections::BTreeMap;
+use std::{fs, io, thread};
 use exchanges::gate_swap_rest::GateSwapRest;
+use std::collections::BTreeMap;
+use std::io::{BufRead, BufReader, Read, Write};
+use std::net::{TcpListener, TcpStream};
+use std::sync::{Arc, mpsc};
+use std::time::Duration;
+use serde_json::json;
+use exchanges::binance_usdt_swap_rest::BinanceUsdtSwapRest;
+use exchanges::kucoin_swap_rest::KucoinSwapRest;
+use exchanges::kuconin_swap_ws::{KuconinSubscribeType, KuconinSwapWs, KuconinWsType};
+use exchanges::{proxy, socket_tool};
+use exchanges::binance_usdt_swap_ws::BinanceUsdtSwapWs;
+use exchanges::okx_swap_ws::{OkxSubscribeType, OkxSwapWs, OkxWsType};
+use exchanges::response_base::ResponseData;
+use crate::proxy::ParsingDetail;
+
 
 #[tokio::test]
- async fn test_import() {
-   //  //gate-rest -账户信息
-   //  let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
-   //  btree_map.insert("access_key".to_string(), "".to_string());
-   //  btree_map.insert("secret_key".to_string(), "".to_string());
-   //
-   //  let gate_exc = GateSwapRest::new(false, true, btree_map);
-   //  // let res_data = gate_exc.get_account("usdt".to_string()).await;
-   //  // println!("gate-rest -账户信息{:?}", res_data);
-   //  // let res_data = gate_exc.get_position("usdt".to_string(), "BTC_USDT".to_string()).await;
-   //  // println!("gate-rest -持仓信息{:?}", res_data);
-   //  // let res_data = gate_exc.get_ticker("usdt".to_string()).await;
-   //  // println!("gate-rest -ticker{:?}", res_data);
-   // // let res_data = gate_exc.get_market_details("usdt".to_string()).await;
-   // // println!("gate-rest -market_details{:?}", res_data);
-   //  let res_data = gate_exc.get_server_time().await;
-   //  println!("gate-rest -market_details{:?}", res_data);
-
-}
+async fn test_import() {
+    /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
+    if proxy::ParsingDetail::http_enable_proxy() {
+        println!("检测有代理配置,配置走代理")
+    }
+
+    //获取代理
+    // demo_get_http_proxy();
+
+    //币安---深度socket-公共频道订阅
+    // demo_pub_ws_ba();
+    // 币安-rest-获取账户信息
+    // demo_rest_ba().await;
+
+    //gate-rest -账户信息
+    // demo_rest_gate().await;
+
+
+    //kucoin_rest -账户信息
+    // demo_rest_kucoin().await;
+
+
+    //Kuconin-ws--公共频道
+    // demo_ws_kucoin_pu().await;
+    //Kuconin-ws--私有频道
+    // demo_ws_kucoin_pr().await;
+
+    //okx - Business 频道
+    // demo_ws_okx_bu().await;
+    //okx - public 频道
+    // demo_ws_okx_pu().await;
+}
+
+async fn demo_ws_okx_pu() {
+    let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
+    let (tx, rx) = mpsc::channel();
+    let mut ku_ws = OkxSwapWs::new(false, btree_map, OkxWsType::Public, tx).await;
+    ku_ws.set_subscribe(vec![OkxSubscribeType::PuIndexTickers]);
+    thread::spawn(move || {
+        ku_ws.custom_subscribe(vec!["BTC-USD".to_string()]);
+    });
+    let mut stdout = std::io::stdout();
+    loop {
+        if let Ok(received) = rx.try_recv() {
+            writeln!(stdout, "age: {:?}", received).unwrap();
+        }
+    }
+}
+
+async fn demo_ws_okx_bu() {
+    let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
+    let (tx, rx) = mpsc::channel();
+    let mut ku_ws = OkxSwapWs::new(false, btree_map, OkxWsType::Business, tx).await;
+    ku_ws.set_subscribe(vec![OkxSubscribeType::BuIndexCandle30m]);
+    thread::spawn(move || {
+        ku_ws.custom_subscribe(vec!["BTC-USD".to_string()]);
+    });
+    let mut stdout = std::io::stdout();
+    loop {
+        if let Ok(received) = rx.try_recv() {
+            writeln!(stdout, "age: {:?}", received).unwrap();
+        }
+    }
+}
+
+async fn demo_ws_kucoin_pr() {
+    let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
+    btree_map.insert("access_key".to_string(), "6393f3565f0d4500011f846b".to_string());
+    btree_map.insert("secret_key".to_string(), "9c0df8b7-daaa-493e-a53a-82703067f7dd".to_string());
+    btree_map.insert("pass_key".to_string(), "b87d055f".to_string());
+    println!("----------------------btree_map{:?}", btree_map.clone());
+    let (tx, rx) = mpsc::channel();
+    let mut ku_ws = KuconinSwapWs::new(false, btree_map.clone(),
+                                       KuconinWsType::Private, tx).await;
+    ku_ws.set_subscribe(vec![KuconinSubscribeType::PrContractMarketTradeOrdersSys]);
+    thread::spawn(move || {
+        ku_ws.custom_subscribe(vec!["ACHUSDTM".to_string(), "ROSEUSDTM".to_string()]);
+    });
+    let mut stdout = std::io::stdout();
+    loop {
+        if let Ok(received) = rx.try_recv() {
+            writeln!(stdout, "age: {:?}", received).unwrap();
+        }
+    }
+}
+
+async fn demo_ws_kucoin_pu() {
+    let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
+    let (tx, rx) = mpsc::channel();
+    let mut ku_ws = KuconinSwapWs::new(false, btree_map, KuconinWsType::Public, tx).await;
+    ku_ws.set_subscribe(vec![KuconinSubscribeType::PuContractMarketLevel2Depth50]);
+    thread::spawn(move || {
+        ku_ws.custom_subscribe(vec!["ACHUSDTM".to_string(), "ROSEUSDTM".to_string()]);
+    });
+    let mut stdout = std::io::stdout();
+    loop {
+        if let Ok(received) = rx.try_recv() {
+            writeln!(stdout, "age: {:?}", received).unwrap();
+        }
+    }
+}
+
+async fn demo_rest_kucoin() {
+    let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
+    btree_map.insert("access_key".to_string(), "6393f3565f0d4500011f846b".to_string());
+    btree_map.insert("secret_key".to_string(), "9c0df8b7-daaa-493e-a53a-82703067f7dd".to_string());
+    btree_map.insert("pass_key".to_string(), "b87d055f".to_string());
+    // btree_map.insert("access_key".to_string(), "5c2db93503aa674c74a31734".to_string());
+    // btree_map.insert("secret_key".to_string(), "f03a5284-5c39-4aaa-9b20-dea10bdcf8e3".to_string());
+    // btree_map.insert("pass_key".to_string(), "b87d055f".to_string());
+
+    let kucoin_exc = KucoinSwapRest::new(false, btree_map);
+    let res_data = kucoin_exc.get_server_time().await;
+    println!("kucoin_exc-rest - get_server_time- {:?}", res_data);
+    // let res_data = kucoin_exc.get_account("USDT".to_string()).await;
+    // println!("kucoin_exc-rest - get_account- {:?}", res_data);
+    // let res_data = kucoin_exc.get_position("XBTUSDM".to_string()).await;
+    // println!("kucoin_exc-rest - get_position- {:?}", res_data);
+    // let res_data = kucoin_exc.get_market_details().await;
+    // println!("kucoin_exc-rest - get_market_details- {:?}", res_data);
+    // let res_data = kucoin_exc.get_ticker("ROSEUSDTM".to_string()).await;
+    // println!("kucoin_exc-rest - get_ticker- {:?}", res_data);
+    // let res_data = kucoin_exc.get_orders("active".to_string(), "ROSEUSDTM".to_string()).await;
+    // println!("kucoin_exc-rest - get_orders- {:?}", res_data);
+    // let res_data = kucoin_exc.get_positions("USDT".to_string()).await;
+    // println!("kucoin_exc-rest - get_positions- {:?}", res_data);
+    // let res_data = kucoin_exc.get_orders_details("111".to_string(), "".to_string()).await;
+    // println!("kucoin_exc-rest - get_orders_details- {:?}", res_data);
+    // let res_data = kucoin_exc.swap_bazaar_order(
+    //     "cs_202309111808".to_string(),
+    //     "ROSEUSDTM".to_string(),
+    //     "pd".to_string(),
+    //     1,
+    //     "10".to_string(),
+    //     "0.03856".to_string(),
+    //     "limit".to_string(),
+    // ).await;
+    // println!("kucoin_exc-rest - swap_bazaar_order- {:?}
+    // let res_data = kucoin_exc.cancel_order("12312".to_string(), "".to_string()).await;
+    // println!("kucoin_exc-rest - cancel_order- {:?}", res_data);
+
+    // let res_data = kucoin_exc.get_public_token().await;
+    // println!("kucoin_exc-rest - get_public_token- {:?}", res_data);
+}
+
+async fn demo_rest_gate() {
+    let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
+    btree_map.insert("access_key".to_string(), "4181c882718a95e72122ac1d52c88533".to_string());
+    btree_map.insert("secret_key".to_string(), "de82d1507b843ff08d81a0e9b878b721359f274937216b307834b570b676fa3c".to_string());
+    // btree_map.insert("access_key".to_string(), "dbefbc809e3e83c283a984c3a1459732ea7db1360ca80c5c2c8867408d28cc83".to_string());
+    // btree_map.insert("secret_key".to_string(), "2b5eb11e18796d12d88f13dc27dbbd02c2cc51ff7059765ed9821957d82bb4d9".to_string());
+
+    let gate_exc = GateSwapRest::new(false, btree_map);
+    let res_data = gate_exc.get_account("usdt".to_string()).await;
+    println!("gate-rest -账户信息{:?}", res_data);
+    // let res_data = gate_exc.get_position("usdt".to_string(), "CYBER_USDT".to_string()).await;
+    // println!("gate-rest -持仓信息{:?}", res_data);
+    // let res_data = gate_exc.get_ticker("usdt".to_string()).await;
+    // println!("gate-rest -ticker{:?}", res_data);
+    // let res_data = gate_exc.get_server_time().await;
+    // println!("gate-rest -get_server_time{:?}", res_data);
+    // let res_data = gate_exc.get_user_position("usdt".to_string()).await;
+    // println!("gate-rest -get_server_time{:?}", res_data);
+    // let res_data = gate_exc.get_order_details("usdt".to_string(), "11335522".to_string()).await;
+    // println!("gate-rest -get_order_details{:?}", res_data);
+    // let res_data = gate_exc.get_orders("usdt".to_string(), "open".to_string()).await;
+    // println!("gate-rest -get_orders{:?}", res_data);
+    // let params = serde_json::json!({
+    //         "contract":"CYBER_USDT",
+    //         "size":-1,
+    //         "price":"0",
+    //         "tif":"ioc",
+    //      });
+    // let res_data = gate_exc.take_order("usdt".to_string(), params).await;
+    // println!("gate-rest -get_orders{:?}", res_data);
+    // let res_data = gate_exc.setting_dual_mode("usdt".to_string(), true).await;
+    // println!("gate-rest -setting_dual_mode{:?}", res_data);
+    // let res_data = gate_exc.setting_dual_leverage("usdt".to_string(),
+    //                                               "CYBER_USDT".to_string(),
+    //                                               "20".to_string(),
+    // ).await;
+    // println!("gate-rest -setting_dual_mode{:?}", res_data);
+    // let res_data = gate_exc.wallet_transfers("usdt".to_string(),
+    //                                               "CYBER_USDT".to_string(),
+    //                                               "20".to_string(),
+    // ).await;
+    // println!("gate-rest -setting_dual_mode{:?}", res_data);
+    // let res_data = gate_exc.cancel_order("usdt".to_string(),
+    //                                      "12345".to_string(),
+    // ).await;
+    // println!("gate-rest -setting_dual_mode{:?}", res_data);
+    // let res_data = gate_exc.cancel_orders("usdt".to_string(),
+    //                                      "CYBER_USDT".to_string(),
+    // ).await;
+    // println!("gate-rest -cancel_orders{:?}", res_data);
+    // let res_data = gate_exc.order(
+    //     "usdt".to_string(),
+    //     "long".to_string(),
+    //     "buy".to_string(),
+    //     "ROSE_USDT".to_string(),
+    //     1,
+    //     "0.03888".to_string(),
+    //     "t-my-custom-id-001".to_string(),
+    // ).await;
+    // println!("gate-rest -order{:?}", res_data);
+}
+
+async fn demo_rest_ba() {
+    let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
+    btree_map.insert("access_key".to_string(), "Z2KWEFuiTR26d0OrRh0UVnALiKwftEGKdaz6AHU7xAqZqkKwhb8OPWlG5uAGqGBI".to_string());
+    btree_map.insert("secret_key".to_string(), "w3HvCw17OHEDjpMwlfywtl3tLAfSOql81nXgLk4HTA2yQ4Qph0ilPkKiLgOOY7tQ".to_string());
+    // btree_map.insert("access_key".to_string(), "dbefbc809e3e83c283a984c3a1459732ea7db1360ca80c5c2c8867408d28cc83".to_string());
+    // btree_map.insert("secret_key".to_string(), "2b5eb11e18796d12d88f13dc27dbbd02c2cc51ff7059765ed9821957d82bb4d9".to_string());
+
+    let ba_exc = BinanceUsdtSwapRest::new(false, btree_map);
+    let res_data = ba_exc.get_account().await;
+    println!("币安-rest-获取账户信息{:?}", res_data);
+}
+
+fn demo_pub_ws_ba() {
+    let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
+    btree_map.insert("lable".parse().unwrap(), "binance".parse().unwrap());//交易行名称
+    let (tx, rx) = mpsc::channel();
+    thread::spawn(move || {
+        let ba_exc = BinanceUsdtSwapWs::new(false, btree_map, tx);
+        ba_exc.custom_subscribe(vec![&"BTCUSDT", "ROSEUSDT"], 1, 0);
+    });
+
+    let mut stdout = std::io::stdout();
+    loop {
+        if let Ok(received) = rx.try_recv() {
+            writeln!(stdout, "age: {:?}", received).unwrap();
+        }
+    }
+}
+
+fn demo_get_http_proxy() {
+    //代理地址
+    let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
+    println!("----代理信息:{:?}", parsing_detail);
+}
+
+
+/*********************web服务*/
+fn demo_http() {
+    let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
+    for stream in listener.incoming() {
+        let stream = stream.unwrap();
+
+        handle_connection(stream);
+    }
+}
+
+
+fn handle_connection(mut stream: TcpStream) {
+    let buf_reader = BufReader::new(&mut stream);
+    let http_request: Vec<_> = buf_reader
+        .lines()
+        .map(|result| result.unwrap())
+        .take_while(|line| !line.is_empty())
+        .collect();
+    println!("Request: {:#?}", http_request);
+    println!("Request2: {:#?}", http_request[0]);
+    println!("Request3: {:#?}", http_request[1]);
+
+    let (status_line, filename) = if http_request[0] == "GET / HTTP/1.1" {
+        ("HTTP/1.1 200 OK", "hello.html")
+    } else {
+        ("HTTP/1.1 404 NOT FOUND", "404.html")
+    };
+
+    let status_line = "HTTP/1.1 200 OK";
+    let contents = fs::read_to_string("src/404.html").unwrap();
+    let length = contents.len();
+
+    let response =
+        format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
+    // let response = "HTTP/1.1 200 OK\r\n\r\nccccc";
+
+    stream.write_all(response.as_bytes()).unwrap();
+}