Browse Source

bitget 交易交易所 完成,待调整

875428575@qq.com 2 years ago
parent
commit
b03ef2f2b8

+ 745 - 0
exchanges/src/bitget_spot_rest.rs

@@ -0,0 +1,745 @@
+use std::collections::BTreeMap;
+use reqwest::header::HeaderMap;
+use reqwest::{Client};
+use rust_decimal::Decimal;
+use rust_decimal::prelude::FromPrimitive;
+use rust_decimal_macros::dec;
+use tracing::{info, trace};
+use crate::http_tool::RestTool;
+use crate::response_base::ResponseData;
+use ring::hmac;
+use serde_json::Value;
+
+#[derive(Clone, Debug)]
+pub struct BitgetSwapRest {
+    pub label: String,
+    base_url: String,
+    client: reqwest::Client,
+    /*******参数*/
+    //是否需要登陆
+    //登陆所需参数
+    login_param: BTreeMap<String, String>,
+    delays: Vec<i64>,
+    max_delay: i64,
+    avg_delay: Decimal,
+
+}
+
+impl BitgetSwapRest {
+    /*******************************************************************************************************/
+    /*****************************************获取一个对象****************************************************/
+    /*******************************************************************************************************/
+
+    pub fn new(is_colo: bool, login_param: BTreeMap<String, String>) -> BitgetSwapRest
+    {
+        return BitgetSwapRest::new_lable("default-BitgetSwapRest".to_string(), is_colo, login_param);
+    }
+    pub fn new_lable(label: String, is_colo: bool, login_param: BTreeMap<String, String>) -> BitgetSwapRest {
+        let base_url = if is_colo {
+            "https://api.bitget.com".to_string()
+        } else {
+            "https://api.bitget.com".to_string()
+        };
+
+        if is_colo {
+            info!("开启高速(未配置,走普通:{})通道",base_url);
+        } else {
+            info!("走普通通道:{}",base_url);
+        }
+        /*****返回结构体*******/
+        BitgetSwapRest {
+            label,
+            base_url,
+            client: Client::new(),
+            login_param,
+            delays: vec![],
+            max_delay: 0,
+            avg_delay: dec!(0.0),
+        }
+    }
+
+    /*******************************************************************************************************/
+    /*****************************************rest请求函数********************************************************/
+    /*******************************************************************************************************/
+    //账户信息
+    pub async fn get_account_info(&mut self) -> ResponseData {
+        let params = serde_json::json!({
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/account/info".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取账户币种资产
+    pub async fn get_account_assets(&mut self) -> ResponseData {
+        let params = serde_json::json!({
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/account/assets".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取币种信息
+    pub async fn get_coins(&mut self, coin: String) -> ResponseData {
+        let params = serde_json::json!({
+            "coin":coin
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/public/coins".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取交易对信息
+    pub async fn get_symbols(&mut self, symbol: String) -> ResponseData {
+        let params = serde_json::json!({
+            "symbol":symbol
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/public/symbols".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取现货VIP费率
+    pub async fn get_vip_fee_rate(&mut self) -> ResponseData {
+        let params = serde_json::json!({
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/market/vip-fee-rate".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取行情信息
+    pub async fn get_tickers(&mut self, symbol: String) -> ResponseData {
+        let params = serde_json::json!({
+            "symbol":symbol
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/market/tickers".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取合并交易深度
+    pub async fn get_merge_depth(&mut self, symbol: String) -> ResponseData {
+        let params = serde_json::json!({
+            "symbol":symbol
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/market/merge-depth".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取K线数据
+    //参数:granularity: K线的时间颗粒度
+    //                   分钟:1min,5min,15min,30min
+    //                   小时:1h,4h,6h,12h
+    //                   天:1day,3day
+    //                   周:1week
+    //                   月:1M
+    //                   零时区小时线:6Hutc,12Hutc
+    //                   零时区日线:1Dutc ,3Dutc
+    //                   零时区周线:1Wutc
+    //                   零时区月线:1Mutc
+    //                   1m、3m、5m可以查一个月 ;15m可以查52天; 30m查62天; 1H可以查83天; 2H可以查120天; 4H可以查240天; 6H可以查360天
+    //start_time :K线数据的时间起始点,即获取该时间戳以后的K线数据 Unix毫秒时间戳,例如1690196141868
+    //end_time :K线数据的时间终止点,即获取该时间戳以前的K线数据 Unix毫秒时间戳,例如1690196141868
+    //limit :查询条数  默认100,最大1000
+    pub async fn get_candles(&mut self, symbol: String, granularity: String, start_time: String, end_time: String, limit: String) -> ResponseData {
+        let params = serde_json::json!({
+            "symbol":symbol,
+            "granularity":granularity,
+            "startTime":start_time,
+            "endTime":end_time,
+            "limit":limit,
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/market/candles".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取历史K线数据
+    pub async fn get_history_candles(&mut self, symbol: String, granularity: String, end_time: String, limit: String) -> ResponseData {
+        let params = serde_json::json!({
+            "symbol":symbol,
+            "granularity":granularity,
+            "endTime":end_time,
+            "limit":limit,
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/market/history-candles".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取最近成交数据
+    pub async fn get_market_fills(&mut self, symbol: String, limit: String) -> ResponseData {
+        let params = serde_json::json!({
+            "symbol":symbol,
+            "limit":limit,
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/market/fills".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取历史成交数据
+    pub async fn get_market_fills_history(&mut self, symbol: String, start_time: String, end_time: String, limit: String) -> ResponseData {
+        let params = serde_json::json!({
+            "symbol":symbol,
+            "startTime":start_time,
+            "endTime":end_time,
+            "limit":limit,
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/market/fills-history".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //下单
+    pub async fn spot_order(&mut self, params: serde_json::Value) -> ResponseData {
+        let data = self.request("POST".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/place-order".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //批量下单
+    pub async fn spot_orders(&mut self, params: serde_json::Value) -> ResponseData {
+        let data = self.request("POST".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/batch-orders".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //撤单
+    pub async fn spot_cancel_order(&mut self, symbol: String, order_id: String, client_oid: String) -> ResponseData {
+        let mut params = serde_json::json!({
+            "symbol":symbol,
+         });
+        if order_id.len() > 0 {
+            params.as_object_mut().unwrap().insert("orderId".parse().unwrap(), serde_json::Value::from(order_id));
+        }
+        if client_oid.len() > 0 {
+            params.as_object_mut().unwrap().insert("clientOid".parse().unwrap(), serde_json::Value::from(client_oid));
+        }
+        let data = self.request("POST".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/cancel-order".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //批量撤单
+    pub async fn spot_cancel_orders(&mut self, symbol: String, order_list: Vec<Value>) -> ResponseData {
+        let params = serde_json::json!({
+            "symbol":symbol,
+            "orderList":order_list,
+         });
+        let data = self.request("POST".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/batch-cancel-order".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //按币对撤单
+    pub async fn spot_cancel_symbol_orders(&mut self, symbol: String) -> ResponseData {
+        let params = serde_json::json!({
+            "symbol":symbol,
+         });
+        let data = self.request("POST".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/cancel-symbol-order".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取订单详情
+    pub async fn get_order(&mut self, order_id: String, client_oid: String) -> ResponseData {
+        let params = serde_json::json!({
+            "orderId":order_id,
+            "clientOid":client_oid,
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/orderInfo".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取当前委托列表
+    pub async fn get_unfilled_orders(&mut self,
+                                     symbol: String,
+                                     start_time: String,
+                                     end_time: String,
+                                     id_less_than: String,
+                                     limit: String,
+                                     order_id: String,
+    ) -> ResponseData {
+        let mut params = serde_json::json!({
+            "symbol":symbol,
+         });
+        if start_time.len() > 0 {
+            params.as_object_mut().unwrap().insert("startTime".parse().unwrap(), serde_json::Value::from(start_time));
+        }
+        if end_time.len() > 0 {
+            params.as_object_mut().unwrap().insert("endTime".parse().unwrap(), serde_json::Value::from(end_time));
+        }
+        if id_less_than.len() > 0 {
+            params.as_object_mut().unwrap().insert("idLessThan".parse().unwrap(), serde_json::Value::from(id_less_than));
+        }
+        if limit.len() > 0 {
+            params.as_object_mut().unwrap().insert("limit".parse().unwrap(), serde_json::Value::from(limit));
+        }
+        if order_id.len() > 0 {
+            params.as_object_mut().unwrap().insert("orderId".parse().unwrap(), serde_json::Value::from(order_id));
+        }
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/unfilled-orders".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取历史委托列表
+    pub async fn get_history_orders(&mut self,
+                                    symbol: String,
+                                    start_time: String,
+                                    end_time: String,
+                                    id_less_than: String,
+                                    limit: String,
+                                    order_id: String,
+    ) -> ResponseData {
+        let mut params = serde_json::json!({
+            "symbol":symbol,
+         });
+        if start_time.len() > 0 {
+            params.as_object_mut().unwrap().insert("startTime".parse().unwrap(), serde_json::Value::from(start_time));
+        }
+        if end_time.len() > 0 {
+            params.as_object_mut().unwrap().insert("endTime".parse().unwrap(), serde_json::Value::from(end_time));
+        }
+        if id_less_than.len() > 0 {
+            params.as_object_mut().unwrap().insert("idLessThan".parse().unwrap(), serde_json::Value::from(id_less_than));
+        }
+        if limit.len() > 0 {
+            params.as_object_mut().unwrap().insert("limit".parse().unwrap(), serde_json::Value::from(limit));
+        }
+        if order_id.len() > 0 {
+            params.as_object_mut().unwrap().insert("orderId".parse().unwrap(), serde_json::Value::from(order_id));
+        }
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/history-orders".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+
+    //获取成交明细
+    pub async fn get_fills(&mut self,
+                           symbol: String,
+                           order_id: String,
+                           start_time: String,
+                           end_time: String,
+                           limit: String,
+                           id_less_than: String,
+    ) -> ResponseData {
+        let mut params = serde_json::json!({
+            "symbol":symbol,
+         });
+        if order_id.len() > 0 {
+            params.as_object_mut().unwrap().insert("orderId".parse().unwrap(), serde_json::Value::from(order_id));
+        }
+        if start_time.len() > 0 {
+            params.as_object_mut().unwrap().insert("startTime".parse().unwrap(), serde_json::Value::from(start_time));
+        }
+        if end_time.len() > 0 {
+            params.as_object_mut().unwrap().insert("endTime".parse().unwrap(), serde_json::Value::from(end_time));
+        }
+        if limit.len() > 0 {
+            params.as_object_mut().unwrap().insert("limit".parse().unwrap(), serde_json::Value::from(limit));
+        }
+        if id_less_than.len() > 0 {
+            params.as_object_mut().unwrap().insert("idLessThan".parse().unwrap(), serde_json::Value::from(id_less_than));
+        }
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/fills".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+
+    //下单计划委托
+    pub async fn spot_place_plan_order(&mut self, params: serde_json::Value) -> ResponseData {
+        let data = self.request("POST".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/place-plan-order".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+
+    //修改计划委托
+    pub async fn update_place_plan_order(&mut self, params: serde_json::Value) -> ResponseData {
+        let data = self.request("POST".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/modify-plan-order".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+
+    //撤销计划委托
+    pub async fn cancel_plan_order(&mut self, order_id: String, client_oid: String) -> ResponseData {
+        let mut params = serde_json::json!({
+         });
+        if order_id.len() > 0 {
+            params.as_object_mut().unwrap().insert("orderId".parse().unwrap(), serde_json::Value::from(order_id));
+        }
+        if client_oid.len() > 0 {
+            params.as_object_mut().unwrap().insert("clientOid".parse().unwrap(), serde_json::Value::from(client_oid));
+        }
+        let data = self.request("POST".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/cancel-plan-order".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取当前计划委托
+    pub async fn get_current_plan_order(&mut self,
+                                        symbol: String,
+                                        limit: String,
+                                        id_less_than: String,
+                                        start_time: String,
+                                        end_time: String) -> ResponseData {
+        let mut params = serde_json::json!({
+            "symbol":symbol,
+            "limit":limit,
+         });
+        if id_less_than.len() > 0 {
+            params.as_object_mut().unwrap().insert("idLessThan".parse().unwrap(), serde_json::Value::from(id_less_than));
+        }
+        if start_time.len() > 0 {
+            params.as_object_mut().unwrap().insert("startTime".parse().unwrap(), serde_json::Value::from(start_time));
+        }
+        if end_time.len() > 0 {
+            params.as_object_mut().unwrap().insert("endTime".parse().unwrap(), serde_json::Value::from(end_time));
+        }
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/current-plan-order".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //获取历史计划委托
+    pub async fn get_history_plan_order(&mut self,
+                                        symbol: String,
+                                        start_time: String,
+                                        end_time: String,
+                                        limit: String,
+    ) -> ResponseData {
+        let mut params = serde_json::json!({
+            "symbol":symbol,
+            "startTime":start_time,
+            "endTime":end_time,
+            "limit":limit,
+         });
+        let data = self.request("GET".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/history-plan-order".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    //批量撤销计划委托
+    pub async fn cancel_plan_orders(&mut self, symbol_list: Vec<String>) -> ResponseData {
+        let mut params = serde_json::json!({
+            "symbolList":symbol_list
+         });
+        let data = self.request("POST".to_string(),
+                                "/api/v2".to_string(),
+                                "/spot/trade/batch-cancel-plan-order".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
+    /*******************************************************************************************************/
+    /*****************************************工具函数********************************************************/
+    /*******************************************************************************************************/
+    pub fn get_delays(&self) -> Vec<i64> {
+        self.delays.clone()
+    }
+    pub fn get_avg_delay(&self) -> Decimal {
+        self.avg_delay.clone()
+    }
+    pub fn get_max_delay(&self) -> i64 {
+        self.max_delay.clone()
+    }
+    fn get_delay_info(&mut self) {
+        let last_100 = if self.delays.len() > 100 {
+            self.delays[self.delays.len() - 100..].to_vec()
+        } else {
+            self.delays.clone()
+        };
+
+        let max_value = last_100.iter().max().unwrap();
+        if max_value.clone().to_owned() > self.max_delay {
+            self.max_delay = max_value.clone().to_owned();
+        }
+
+        let sum: i64 = last_100.iter().sum();
+        let sum_v = Decimal::from_i64(sum).unwrap();
+        let len_v = Decimal::from_u64(last_100.len() as u64).unwrap();
+        self.avg_delay = (sum_v / len_v).round_dp(1);
+        self.delays = last_100.clone().into_iter().collect();
+    }
+    //调用请求
+    pub async fn request(&mut self,
+                         method: String,
+                         prefix_url: String,
+                         request_url: String,
+                         is_login: bool,
+                         params: String) -> ResponseData
+    {
+        trace!("login_param:{:?}", self.login_param);
+        //解析账号信息
+        let mut access_key = "".to_string();
+        let mut secret_key = "".to_string();
+        let mut passphrase = "".to_string();
+        if self.login_param.contains_key("access_key") {
+            access_key = self.login_param.get("access_key").unwrap().to_string();
+        }
+        if self.login_param.contains_key("secret_key") {
+            secret_key = self.login_param.get("secret_key").unwrap().to_string();
+        }
+        if self.login_param.contains_key("pass_key") {
+            passphrase = self.login_param.get("pass_key").unwrap().to_string();
+        }
+        let mut is_login_param = true;
+        if access_key == "" || secret_key == "" || passphrase == "" {
+            is_login_param = false
+        }
+
+
+        //请求头配置-如果需要登陆则存在额外配置
+        let mut body = "".to_string();
+        let timestamp = Self::get_timestamp();
+        let mut headers = HeaderMap::new();
+        headers.insert("Content-Type", "application/json".parse().unwrap());
+        headers.insert("locale", "en-US".parse().unwrap());
+        if method == "POST" {
+            body = params.clone();
+        }
+
+
+        //是否需要登陆-- 组装sing
+        if is_login {
+            if !is_login_param {
+                let e = ResponseData::error(self.label.clone(), "登陆参数错误!".to_string());
+                return e;
+            } else {
+                //需要登陆-且登陆参数齐全
+                trace!("param:{}", params);
+                trace!("body:{}", body);
+                //组装sing
+                let sing = Self::sign(secret_key.clone(),
+                                      method.clone(),
+                                      prefix_url.clone(),
+                                      request_url.clone(),
+                                      params.clone(),
+                                      body.clone(),
+                                      timestamp.clone(),
+                );
+                //组装header
+                headers.extend(Self::headers(sing, timestamp, passphrase, access_key));
+            }
+        }
+
+
+        // trace!("headers:{:?}", headers);
+        let base_url = format!("{}{}", prefix_url.clone(), request_url.clone());
+        let start_time = chrono::Utc::now().timestamp_millis();
+        let get_response = self.http_toll(
+            format!("{}{}", prefix_url.clone(), request_url.clone()),
+            method.to_string(),
+            params.clone(),
+            headers,
+        ).await;
+        let time_array = chrono::Utc::now().timestamp_millis() - start_time;
+        self.delays.push(time_array);
+        self.get_delay_info();
+        let res_data = Self::res_data_analysis(get_response, base_url, params);
+        res_data
+    }
+
+    pub fn headers(sign: String, timestamp: String, passphrase: String, access_key: String) -> HeaderMap {
+        let mut headers = HeaderMap::new();
+        headers.insert("ACCESS-KEY", access_key.parse().unwrap());
+        headers.insert("ACCESS-SIGN", sign.parse().unwrap());
+        headers.insert("ACCESS-TIMESTAMP", timestamp.parse().unwrap());
+        headers.insert("ACCESS-PASSPHRASE", passphrase.parse().unwrap());
+        headers
+    }
+    pub fn sign(secret_key: String,
+                method: String, prefix_url: String, request_url: String,
+                params: String, body: String, timestamp: String) -> String
+    {
+        /*签名生成*/
+        let url_param_str = RestTool::parse_params_to_str(params);
+        let base_url = if method == "GET" && url_param_str.len() > 0 {
+            format!("{}{}?{}", prefix_url, request_url, url_param_str)
+        } else {
+            format!("{}{}", prefix_url, request_url)
+        };
+
+        // 时间戳 + 请求类型+ 请求参数字符串
+        let message = format!("{}{}{}{}", timestamp, method, base_url, body);
+        trace!("message:{}",message);
+
+        // 做签名
+        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);
+        sign
+    }
+
+    async fn http_toll(&mut self, request_path: String, request_type: String, params: String, headers: HeaderMap) -> Result<ResponseData, reqwest::Error> {
+        let res_data: ResponseData;
+        /****请求接口与 地址*/
+        let url = format!("{}{}", self.base_url.to_string(), request_path);
+        let request_type = request_type.clone().to_uppercase();
+        let addrs_url: String = if RestTool::parse_params_to_str(params.clone()) == "" {
+            url.clone()
+        } else {
+            format!("{}?{}", url.clone(), RestTool::parse_params_to_str(params.clone()))
+        };
+        trace!("url:{}", url);
+        trace!("addrs_url:{}", addrs_url);
+        let params_json: serde_json::Value = serde_json::from_str(&params).unwrap();
+        trace!("params_json:{}",params_json);
+        trace!("headers:{:?}",headers);
+
+
+        let req = match request_type.as_str() {
+            "GET" => self.client.get(addrs_url.clone()).headers(headers),
+            "POST" => self.client.post(url.clone()).body(params).headers(headers),
+            "DELETE" => self.client.delete(addrs_url.clone()).headers(headers),
+            // "PUT" => self.client.put(url.clone()).json(&params),
+            _ => return Ok(ResponseData::error(self.label.clone(), format!("错误的请求类型:{}", request_type.clone()))), // 处理未知请求类型
+        };
+
+        let response = req.send().await?;
+        if response.status().is_success() {
+            // 读取响应的内容
+            let body = response.text().await?;
+            // trace!("ok-----{}", body);
+            res_data = ResponseData::new(self.label.clone(), "200".to_string(), "success".to_string(), body);
+        } else {
+            let body = response.text().await?;
+            // trace!("error-----{}", body);
+            res_data = ResponseData::error(self.label.clone(), body.to_string())
+        }
+
+        Ok(res_data)
+    }
+
+
+    //res_data 解析
+    pub fn res_data_analysis(result: Result<ResponseData, reqwest::Error>, base_url: String, params: String) -> ResponseData {
+        trace!("原始数据:{:?}",result);
+        match result {
+            Ok(res_data) => {
+                if res_data.code != "200" {
+                    trace!("不等于200");
+                    let message: String = res_data.message;
+                    let json_value: serde_json::Value = serde_json::from_str(&message).unwrap();
+                    let code = json_value["code"].as_str().unwrap();
+                    let msg = json_value["msg"].as_str().unwrap();
+                    let error = ResponseData::new("".to_string(),
+                                                  format!("{}", code),
+                                                  format!("{}", msg),
+                                                  format!("请求地址:{},请求参数:{}", base_url, params));
+                    error
+                } else {
+                    trace!("等于200");
+                    let body: String = res_data.data;
+                    let json_value: serde_json::Value = serde_json::from_str(&body).unwrap();
+
+                    let code = json_value["code"].as_str().unwrap();
+                    if code == "00000" {
+                        let data = serde_json::to_string(&json_value["data"]).unwrap();
+                        let success = ResponseData::new("".to_string(), "200".to_string(), "success".to_string(), data.parse().unwrap());
+                        success
+                    } else {
+                        let msg = json_value["msg"].as_str().unwrap();
+                        // trace!("发生错误:??{:?}",data_json.to_string());
+                        let error = ResponseData::new("".to_string(),
+                                                      format!("{}", code),
+                                                      format!("{}", msg),
+                                                      format!("请求地址:{},请求参数:{}", base_url, params));
+                        error
+                    }
+                }
+            }
+            Err(err) => {
+                let error = ResponseData::error("".to_string(), format!("json 解析失败:{}", err));
+                error
+            }
+        }
+    }
+    fn get_timestamp() -> String {
+        chrono::Utc::now().timestamp_millis().to_string()
+    }
+}

+ 1 - 0
exchanges/src/lib.rs

@@ -16,4 +16,5 @@ pub mod okx_swap_rest;
 pub mod binance_swap_rest;
 mod utils;
 pub mod bitget_spot_ws;
+pub mod bitget_spot_rest;
 

+ 285 - 21
exchanges/tests/bitget_spot_test.rs

@@ -6,6 +6,7 @@ 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_rest::BitgetSwapRest;
 use exchanges::bitget_spot_ws::{BitgetSubscribeType, BitgetSwapWs, BitgetWsType};
 use exchanges::kucoin_swap_rest::KucoinSwapRest;
 use exchanges::kucoin_swap_ws::{KucoinSubscribeType, KucoinSwapWs, KucoinWsType};
@@ -74,45 +75,308 @@ async fn ws_custom_subscribe_pr() {
 }
 
 
-//rest-撤销全部订单
+//rest-获取账户信息
 #[tokio::test]
-async fn rest_get_server_time_test() {
+async fn rest_get_account_info_test() {
     global::log_utils::init_log_with_trace();
 
     let mut rest = get_rest();
-    let rep_data = rest.cancel_orders("BLZUSDTM".to_string()).await;
+    let rep_data = rest.get_account_info().await;
     trace!(?rep_data)
 }
 
+//rest-获取账户币种资产
+#[tokio::test]
+async fn rest_get_account_assets_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.get_account_assets().await;
+    trace!(?rep_data)
+}
+
+//rest-获取币种信息
+#[tokio::test]
+async fn rest_get_coins_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.get_coins("USDT".to_string()).await;
+    trace!(?rep_data)
+}
+
+//rest-获取交易对信息
+#[tokio::test]
+async fn rest_get_symbols_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.get_symbols("BTCUSDT".to_string()).await;
+    trace!(?rep_data)
+}
+
+//rest-获取现货VIP费率
+#[tokio::test]
+async fn rest_get_vip_fee_rate_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.get_vip_fee_rate().await;
+    trace!(?rep_data)
+}
+
+//rest-获取行情信息
+#[tokio::test]
+async fn rest_get_tickers_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.get_tickers("BTCUSDT".to_string()).await;
+    trace!(?rep_data)
+}
+
+//rest-获取合并交易深度
+#[tokio::test]
+async fn rest_get_merge_depth_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.get_merge_depth("BTCUSDT".to_string()).await;
+    trace!(?rep_data)
+}
+
+//rest-获取K线数据
+#[tokio::test]
+async fn rest_get_candles_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.get_candles("BTCUSDT".to_string(), "1min".to_string(), "1697701550192".to_string(), "1697701556192".to_string(), "100".to_string()).await;
+    trace!(?rep_data)
+}
+
+//rest-获取历史K线数据
+#[tokio::test]
+async fn rest_get_history_candles_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.get_history_candles("BTCUSDT".to_string(), "1min".to_string(), "1697701556192".to_string(), "100".to_string()).await;
+    trace!(?rep_data)
+}
+
+//rest-获取最近成交数据
+#[tokio::test]
+async fn rest_get_market_fills_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.get_market_fills("BTCUSDT".to_string(), "100".to_string()).await;
+    trace!(?rep_data)
+}
 
-//rest-杠杆测试
+//rest-获取历史成交数据
 #[tokio::test]
-async fn rest_leverage_test() {
+async fn rest_get_fills_history_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_data = rest.get_market_fills_history("BTCUSDT".to_string(), "1697701550192".to_string(), "1697701556192".to_string(), "100".to_string()).await;
+    trace!(?rep_data)
+}
 
-    //设置杠杆
-    let rep_data2 = rest.set_leverage("BLZUSDTM".to_string(), 1).await;
-    trace!("设置杠杆{:?}",rep_data2);
+//rest-下单
+#[tokio::test]
+async fn rest_spot_order_test() {
+    global::log_utils::init_log_with_trace();
 
-    // //查询杠杆
-    // let rep_data3 = rest.get_leverage("BLZUSDTM".to_string()).await;
-    // trace!("查询杠杆{:?}",rep_data3);
+    //市价单
+    let mut rest = get_rest();
+    let params = serde_json::json!({
+            // "symbol":"CELRUSDT",
+            // "side":"sell",
+            // "orderType":"market",
+            // "force":"fok",
+            // "size":"887",
+            // "clientOid":"7d8zd4d_3",
+         });
+
+    //限价单
+    let params = serde_json::json!({
+            // "symbol":"CELRUSDT",
+            // "side":"buy",
+            // "orderType":"limit",
+            // "force":"gtc",
+            // "price":"0.01001",
+            // "size":"10",
+            // "clientOid":"7d8zd4d_z1",
+         });
+
+    let rep_data = rest.spot_order(params).await;
+    trace!(?rep_data)
 }
 
-//rest-设置自动开启补仓
+
+//rest-撤单
 #[tokio::test]
-async fn rest_auto_deposit_test() {
+async fn rest_spot_cancel_order_test() {
     global::log_utils::init_log_with_trace();
+    let mut rest = get_rest();
+    let rep_data = rest.spot_cancel_order("CELRUSDT".to_string(), "".to_string(), "1".to_string()).await;
+    trace!(?rep_data)
+}
 
-    //设置是否自动补仓
+//rest-批量撤单
+#[tokio::test]
+async fn rest_spot_cancel_orders_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);
+    let v = serde_json::json!({
+            "orderId":"1073370944162058240",
+            "clientOid":"1073370944162058240"
+        });
+    let rep_data = rest.spot_cancel_orders("CELRUSDT".to_string(), vec![v]).await;
+    trace!(?rep_data)
+}
+
+//rest-按币对撤单
+#[tokio::test]
+async fn rest_spot_cancel_symbol_orders_test() {
+    global::log_utils::init_log_with_trace();
+    let mut rest = get_rest();
+    let rep_data = rest.spot_cancel_symbol_orders("CELRUSDT".to_string()).await;
+    trace!(?rep_data)
+}
+
+//rest-获取订单详情
+#[tokio::test]
+async fn rest_get_order_test() {
+    global::log_utils::init_log_with_trace();
+    let mut rest = get_rest();
+    let rep_data = rest.get_order("".to_string(), "1".to_string()).await;
+    trace!(?rep_data)
+}
+
+//rest-获取当前委托列表
+#[tokio::test]
+async fn rest_get_unfilled_orders_test() {
+    global::log_utils::init_log_with_trace();
+    let mut rest = get_rest();
+    let rep_data = rest.get_unfilled_orders("CELRUSDT".to_string(),
+                                            "".to_string(),
+                                            "".to_string(),
+                                            "".to_string(),
+                                            "".to_string(),
+                                            "".to_string(),
+    ).await;
+    trace!(?rep_data)
+}
+
+//rest-获取历史委托列表
+#[tokio::test]
+async fn rest_get_history_orders_test() {
+    global::log_utils::init_log_with_trace();
+    let mut rest = get_rest();
+    let rep_data = rest.get_history_orders("CELRUSDT".to_string(),
+                                           "".to_string(),
+                                           "".to_string(),
+                                           "".to_string(),
+                                           "".to_string(),
+                                           "".to_string(),
+    ).await;
+    trace!(?rep_data)
+}
+
+//rest-获取成交明细
+#[tokio::test]
+async fn rest_get_fills_test() {
+    global::log_utils::init_log_with_trace();
+    let mut rest = get_rest();
+    let rep_data = rest.get_fills("CELRUSDT".to_string(),
+                                  "1".to_string(),
+                                  "".to_string(),
+                                  "".to_string(),
+                                  "".to_string(),
+                                  "".to_string(),
+    ).await;
+    trace!(?rep_data)
+}
+
+//rest-获取成交明细
+#[tokio::test]
+async fn rest_spot_place_plan_order_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    //限价-委托单
+    let params = serde_json::json!({
+         });
+
+    let rep_data = rest.spot_place_plan_order(params).await;
+    trace!(?rep_data)
+}
+
+//rest-修改计划委托
+#[tokio::test]
+async fn rest_update_place_plan_order_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    //限价-委托单
+    let params = serde_json::json!({
+         });
+
+    let rep_data = rest.update_place_plan_order(params).await;
+    trace!(?rep_data)
+}
+
+//rest-撤销计划委托
+#[tokio::test]
+async fn rest_cancel_plan_order_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.cancel_plan_order("32131".to_string(), "3211".to_string()).await;
+    trace!(?rep_data)
+}
+
+//rest-获取当前计划委托
+#[tokio::test]
+async fn rest_get_current_plan_order_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.get_current_plan_order("CELRUSDT".to_string(),
+                                               "1".to_string(),
+                                               "".to_string(),
+                                               "".to_string(),
+                                               "".to_string(),
+    ).await;
+    trace!(?rep_data)
+}
+
+//rest-获取历史计划委托
+#[tokio::test]
+async fn rest_get_history_plan_order_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.get_history_plan_order("CELRUSDT".to_string(),
+                                               "1697701550192".to_string(),
+                                               "1697701580192".to_string(),
+                                               "100".to_string(),
+    ).await;
+    trace!(?rep_data)
+}
+
+//rest-批量撤销计划委托
+#[tokio::test]
+async fn rest_cancel_plan_orders_test() {
+    global::log_utils::init_log_with_trace();
+
+    let mut rest = get_rest();
+    let rep_data = rest.cancel_plan_orders(vec!["CELRUSDT".to_string()]).await;
+    trace!(?rep_data)
 }
 
 
@@ -122,7 +386,7 @@ async fn get_ws(btree_map: BTreeMap<String, String>, type_v: BitgetWsType, tx: S
     ku_ws
 }
 
-fn get_rest() -> KucoinSwapRest {
+fn get_rest() -> BitgetSwapRest {
     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());
@@ -130,6 +394,6 @@ fn get_rest() -> KucoinSwapRest {
     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);
+    let mut ku_exc = BitgetSwapRest::new(false, btree_map);
     ku_exc
 }

+ 14 - 0
exchanges/tests/kucoin_swap_test.rs

@@ -105,6 +105,20 @@ async fn rest_leverage_test() {
     // 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: KucoinWsType, tx: Sender<ResponseData>) -> KucoinSwapWs {
     let mut ku_ws = KucoinSwapWs::new(false, btree_map.clone(),

+ 4 - 1
exchanges/tests/okx_swap_test.rs

@@ -76,7 +76,8 @@ async fn ws_custom_subscribe_pr() {
     ws.set_subscribe(vec![
         OkxSubscribeType::PrBalanceAndPosition,
         OkxSubscribeType::PrAccount("USDT".to_string()),
-        OkxSubscribeType::PrOrders,
+        // OkxSubscribeType::PrOrders,
+        OkxSubscribeType::PrPositions,
     ]);
 
     let t1 = tokio::spawn(async move {
@@ -93,6 +94,8 @@ async fn ws_custom_subscribe_pr() {
     try_join!(t1,t2).unwrap();
 }
 
+
+
 //rest-订单查询
 #[tokio::test]
 async fn rest_get_order_test() {