Sfoglia il codice sorgente

coinex 新增rest接口 创建子账号一系列操作

hl 1 anno fa
parent
commit
c478e9e0a5
2 ha cambiato i file con 232 aggiunte e 43 eliminazioni
  1. 108 39
      exchanges/src/coinex_swap_rest.rs
  2. 124 4
      exchanges/tests/coinex_swap_test.rs

+ 108 - 39
exchanges/src/coinex_swap_rest.rs

@@ -54,13 +54,12 @@ impl CoinexSwapRest {
     /*******************************************************************************************************/
     //获取服务器当前时间
     pub async fn get_server_time(&mut self) -> ResponseData {
-
         let data = self.request("GET".to_string(),
                                 "/v2".to_string(),
                                 "/time".to_string(),
                                 false,
                                 None,
-                                None
+                                None,
         ).await;
         data
     }
@@ -71,7 +70,7 @@ impl CoinexSwapRest {
                                 "/account/trade-fee-rate".to_string(),
                                 true,
                                 None,
-                                None
+                                None,
         ).await;
         data
     }
@@ -82,7 +81,7 @@ impl CoinexSwapRest {
                                 "/assets/futures/balance".to_string(),
                                 true,
                                 None,
-                                None
+                                None,
         ).await;
         data
     }
@@ -94,7 +93,7 @@ impl CoinexSwapRest {
                                 "/assets/spot/balance".to_string(),
                                 true,
                                 None,
-                                None
+                                None,
         ).await;
         data
     }
@@ -110,7 +109,7 @@ impl CoinexSwapRest {
                                 "/futures/pending-position".to_string(),
                                 true,
                                 Some(params.to_string()),
-                                None
+                                None,
         ).await;
         data
     }
@@ -125,7 +124,7 @@ impl CoinexSwapRest {
                                 "/futures/pending-position".to_string(),
                                 true,
                                 Some(params.to_string()),
-                                None
+                                None,
         ).await;
         data
     }
@@ -140,7 +139,7 @@ impl CoinexSwapRest {
                                 "/futures/ticker".to_string(),
                                 false,
                                 Some(params.to_string()),
-                                None
+                                None,
         ).await;
         data
     }
@@ -154,7 +153,7 @@ impl CoinexSwapRest {
                                 "/futures/market".to_string(),
                                 false,
                                 Some(params.to_string()),
-                                None
+                                None,
         ).await;
         data
     }
@@ -169,7 +168,7 @@ impl CoinexSwapRest {
                                 "/futures/order-status".to_string(),
                                 true,
                                 Some(params.to_string()),
-                                None
+                                None,
         ).await;
         data
     }
@@ -185,7 +184,7 @@ impl CoinexSwapRest {
                                 "/futures/pending-order".to_string(),
                                 true,
                                 Some(params.to_string()),
-                                None
+                                None,
         ).await;
         data
     }
@@ -200,7 +199,7 @@ impl CoinexSwapRest {
                                 "/futures/pending-order".to_string(),
                                 true,
                                 Some(params.to_string()),
-                                None
+                                None,
         ).await;
         data
     }
@@ -215,7 +214,7 @@ impl CoinexSwapRest {
                                 "/futures/finished-order".to_string(),
                                 true,
                                 Some(params.to_string()),
-                                None
+                                None,
         ).await;
         data
     }
@@ -228,7 +227,7 @@ impl CoinexSwapRest {
                        side: String,
                        size: Decimal,
                        price: Decimal,
-                       client_id: String
+                       client_id: String,
     ) -> ResponseData
     {
         // 默认为限价单
@@ -245,7 +244,7 @@ impl CoinexSwapRest {
                 data = self.swap_order(market, side, type_y, size, price, client_id, false).await;
             }
             "long_sell" => {//平多
-                data = self.close_position(market, type_y,  price, client_id, false).await;
+                data = self.close_position(market, type_y, price, client_id, false).await;
             }
             "short_buy" => {//平空
                 data = self.close_position(market, type_y, price, client_id, false).await;
@@ -253,7 +252,8 @@ impl CoinexSwapRest {
             "short_sell" => {//开空
                 data = self.swap_order(market, side, type_y, size, price, client_id, false).await;
             }
-            _ => {// 处理未知请求类型
+            _ => {
+                // 处理未知请求类型
                 error!("下单失败,数量异常! size: {}", size);
                 data = ResponseData::error(self.label.clone(), format!("下单失败, 下单参数: <market: {:?}, pos_side: {:?}, side: {:?}, size: {}, price: {:?}, client_id: {:?}>", market, pos_side, side, size, price, client_id));
             }
@@ -262,7 +262,7 @@ impl CoinexSwapRest {
     }
 
     // 平仓下单
-    pub async fn close_position(&mut self, market: String, type_y : String,  price: Decimal, client_id: String, is_hide: bool) -> ResponseData {
+    pub async fn close_position(&mut self, market: String, type_y: String, price: Decimal, client_id: String, is_hide: bool) -> ResponseData {
         // 数量不传为全平
         let param = serde_json::json!({
             "market":market,
@@ -278,13 +278,13 @@ impl CoinexSwapRest {
                                 "/futures/close-position".to_string(),
                                 true,
                                 None,
-                                Some(param.to_string())
+                                Some(param.to_string()),
         ).await;
         data
     }
 
     //合约交易开仓下单
-    pub async fn swap_order(&mut self, market: String, side: String, type_y : String, amount: Decimal, price: Decimal, client_id: String, is_hide: bool) -> ResponseData {
+    pub async fn swap_order(&mut self, market: String, side: String, type_y: String, amount: Decimal, price: Decimal, client_id: String, is_hide: bool) -> ResponseData {
         let param = serde_json::json!({
             "market":market,
             "market_type": "FUTURES",
@@ -301,7 +301,7 @@ impl CoinexSwapRest {
                                 "/futures/order".to_string(),
                                 true,
                                 None,
-                                Some(param.to_string())
+                                Some(param.to_string()),
         ).await;
         data
     }
@@ -325,7 +325,7 @@ impl CoinexSwapRest {
                                 "/futures/adjust-position-leverage".to_string(),
                                 true,
                                 None,
-                                Some(params.to_string())
+                                Some(params.to_string()),
         ).await;
         data
     }
@@ -344,7 +344,7 @@ impl CoinexSwapRest {
                                     "/futures/cancel-order".to_string(),
                                     true,
                                     None,
-                                    Some(params.to_string())
+                                    Some(params.to_string()),
             ).await;
             data
         } else if client_id != "" {  // 如果客户端id不为空,则用客户端id取消订单
@@ -355,18 +355,19 @@ impl CoinexSwapRest {
             });
 
             let mut data = self.request("POST".to_string(),
-                                    "/v2".to_string(),
-                                    "/futures/cancel-order-by-client-id".to_string(),
-                                    true,
-                                    None,
-                                    Some(params.to_string())
+                                        "/v2".to_string(),
+                                        "/futures/cancel-order-by-client-id".to_string(),
+                                        true,
+                                        None,
+                                        Some(params.to_string()),
             ).await;
             // 非空的
             if data.code == 200 && !data.data.is_null() {
                 data.data = data.data.as_array().unwrap()[0]["data"].clone();
             }
             data
-        } else {  // 否则返回错误
+        } else {
+            // 否则返回错误
             error!("取消订单失败失败,id异常");
             ResponseData::error(self.label.clone(), format!("取消订单失败失败, orderId:{:?}, clientId: {:?} ", order_id, client_id))
         }
@@ -383,7 +384,7 @@ impl CoinexSwapRest {
                                 "/futures/cancel-all-order".to_string(),
                                 true,
                                 None,
-                                Some(params.to_string())
+                                Some(params.to_string()),
         ).await;
         data
     }
@@ -414,6 +415,74 @@ impl CoinexSwapRest {
     }
 
 
+    //查询子账号列表
+    pub async fn account_get(&mut self) -> ResponseData {
+        let mut params = serde_json::json!({
+            "is_frozen":false,
+            "page":1,
+            "limit":100,
+        });
+
+        let data = self.request("GET".to_string(),
+                                "/v2".to_string(),
+                                "/account/subs".to_string(),
+                                true,
+                                Some(params.to_string()), None).await;
+        data
+    }
+
+
+    //根据子账号,生成子账号 APIKEY
+    pub async fn account_subs_api(&mut self, params: Value) -> ResponseData {
+        let data = self.request("POST".to_string(),
+                                "/v2".to_string(),
+                                "/account/subs/api".to_string(),
+                                true,
+                                None,
+                                Some(params.to_string())).await;
+        data
+    }
+
+    //获取子账号 APIKEY 列表
+    pub async fn account_get_apikey(&mut self, params: Value) -> ResponseData {
+        let data = self.request("GET".to_string(),
+                                "/v2".to_string(),
+                                "/account/subs/api".to_string(),
+                                true,
+                                Some(params.to_string()), None).await;
+        data
+    }
+
+    //获取子账号 APIKEY 详情
+    pub async fn account_get_detail(&mut self, params: Value) -> ResponseData {
+        let data = self.request("GET".to_string(),
+                                "/v2".to_string(),
+                                "/account/subs/api-detail".to_string(),
+                                true,
+                                Some(params.to_string()), None).await;
+        data
+    }
+
+    //编辑子账号 APIKEY
+    pub async fn account_get_update(&mut self, params: Value) -> ResponseData {
+        let data = self.request("POST".to_string(),
+                                "/v2".to_string(),
+                                "/account/subs/edit-api".to_string(),
+                                true,
+                                None,  Some(params.to_string())).await;
+        data
+    }
+
+    //删除子账号 APIKEY
+    pub async fn account_del_apikey(&mut self, params: Value) -> ResponseData {
+        let data = self.request("POST".to_string(),
+                                "/v2".to_string(),
+                                "/account/subs/delete-api".to_string(),
+                                true,
+                                None,
+                                Some(params.to_string())).await;
+        data
+    }
     /*******************************************************************************************************/
     /*****************************************工具函数********************************************************/
     /*******************************************************************************************************/
@@ -505,7 +574,7 @@ impl CoinexSwapRest {
                     &url_and_query,
                     &body_s,
                     timestamp.clone(),
-                    &secret_key
+                    &secret_key,
                 );
                 // trace!("sing:{}", sing);
                 //组装header
@@ -532,7 +601,7 @@ impl CoinexSwapRest {
         path: &String,
         body: &String,
         timestamp: String,
-        secret_key: &String
+        secret_key: &String,
     ) -> Result<String, Box<dyn Error>> {
         let prepared_str = format!(
             "{}{}{}{}{}",
@@ -569,26 +638,26 @@ impl CoinexSwapRest {
                         let data_json_str: Result<Value, serde_json::Error> = serde_json::from_str(text.as_str());
                         match data_json_str {
                             Ok(data_json) => {
-                                return if is_success && data_json["code"].to_string() == "0"{
+                                return if is_success && data_json["code"].to_string() == "0" {
                                     self.on_success_data(data_json["data"].clone())
                                 } else {
                                     self.on_error_data(&text, &url, &body)
-                                }
-                            },
+                                };
+                            }
                             Err(e) => {
                                 error!("{} 请求完成,解析响应内容JSON失败 {} {}", url, text.as_str(), e);
                                 self.on_error_data(&e.to_string(), &url, &body)
                             }
                         }
-
-                    },
+                    }
                     Err(e) => {
                         error!("{} 请求完成,解析响应内容失败 {}", url, e);
                         self.on_error_data(&e.to_string(), &url, &body)
                     }
                 }
-            },
-            Err(e) => {// 异常情况
+            }
+            Err(e) => {
+                // 异常情况
                 error!("{} 请求失败,网络错误 {}", url, e);
                 self.on_error_data(&e.to_string(), &url, &body)
             }
@@ -619,7 +688,7 @@ impl CoinexSwapRest {
             }
             Err(e) => {
                 error!("解析错误:{:?}", e);
-                let error = ResponseData::error("".to_string(),format!("json 解析失败:{},相关参数:{}", e, text));
+                let error = ResponseData::error("".to_string(), format!("json 解析失败:{},相关参数:{}", e, text));
                 error
             }
         }

+ 124 - 4
exchanges/tests/coinex_swap_test.rs

@@ -1,4 +1,3 @@
-
 use std::collections::BTreeMap;
 use std::str::FromStr;
 use std::sync::Arc;
@@ -6,10 +5,11 @@ use std::sync::atomic::AtomicBool;
 use rust_decimal::Decimal;
 use serde_json::Value;
 use tokio::sync::Mutex;
-use tracing::{error, trace};
+use tracing::{error, info, trace};
 use exchanges::coinex_swap_rest::CoinexSwapRest;
 use exchanges::coinex_swap_ws::{CoinexSwapLogin, CoinexSwapSubscribeType, CoinexSwapWs};
 use exchanges::response_base::ResponseData;
+use global::log_utils::{init_log_with_info, init_log_with_trace};
 
 
 const ACCESS_KEY: &str = "";
@@ -195,7 +195,7 @@ async fn rest_cancel_order_test() {
     let mut ret = get_rest();
     let req_data = ret.cancel_order("DOGEUSDT".to_string(), "", "436265461").await;
 
-    println!("coinex--查询cancel_order--{} {:?}",req_data.data.is_null(), req_data);
+    println!("coinex--查询cancel_order--{} {:?}", req_data.data.is_null(), req_data);
 }
 
 #[tokio::test]
@@ -207,7 +207,7 @@ async fn rest_cancel_all_order_test() {
     if orders_res_data.code == 200 {
         let orders_res_data_json = orders_res_data.data.as_array().unwrap();
         for order in orders_res_data_json {
-            let cancel_res_data = ret.cancel_order_all( order["market"].as_str().unwrap().to_string()).await;
+            let cancel_res_data = ret.cancel_order_all(order["market"].as_str().unwrap().to_string()).await;
             if cancel_res_data.code == 200 {
                 result.push(order.clone())
             }
@@ -253,7 +253,127 @@ async fn rest_time() {
     println!("coinex--time--{:?}", result);
 }
 
+#[tokio::test]
+async fn rest_account_get_test() {
+    let mut ret = get_rest();
+    let res_data = ret.account_get().await;
+    let res_data_json: Value = res_data.data;
+    if res_data_json.is_array() {
+        let array = res_data_json.as_array().unwrap();
+        for z in array {
+            trace!("coinex--查看子账号列表--{:?}", z);
+        }
+    }
+}
+
+#[tokio::test]
+async fn rest_account_subs_api_test() {
+    let mut ret = get_rest();
+    let params = serde_json::json!({
+            "sub_user_name":"2024050",
+            "ip_whitelist":[],
+            "trade_enabled":false,
+            "remark":"",
+        });
+    let res_data = ret.account_subs_api(params).await;
+    // let res_data_json: Value = res_data.data;
+    // let result = res_data_json["timestamp"].to_string();
+    println!("coinex--获取子账号的apikey--{:?}", res_data);
+}
+
+// 将主账号下的  子账号 都创建apikey
+#[tokio::test]
+async fn rest_account_get_and_api_test() {
+    let mut ret = get_rest();
+    let res_data = ret.account_get().await;
+    let res_data_json: Value = res_data.data;
+    if res_data_json.is_array() {
+        let array = res_data_json.as_array().unwrap();
+        for z in array {
+            let sub_user_name = z["sub_user_name"].as_str().unwrap();
+            info!("coinex--查看子账号列表--{:?}", z);
+
+
+            // //每个账号创建apiKey
+            // let params2 = serde_json::json!({
+            //     "sub_user_name":sub_user_name,
+            //     "ip_whitelist":[],
+            //     "trade_enabled":false,
+            //     "remark":"",
+            // });
+            // let res_data2 = ret.account_subs_api(params2).await;
+            // // info!("coinex--创建成功响应--{:?}", res_data2);
+            // let res_data_json2: Value = res_data2.data;
+            // let api_id = res_data_json2["api_id"].as_i64().unwrap();
+            // let access_id = res_data_json2["access_id"].as_str().unwrap();
+            // let secret_key = res_data_json2["secret_key"].as_str().unwrap();
+            // info!("sub_user_name:{:?} \tapi_id:{:?} \t access_id:{:?}\t secret_key:{:?}",sub_user_name,api_id,access_id,secret_key);
+
+        }
+    }
+}
+
+// 获取子账号 APIKEY 列表
+#[tokio::test]
+async fn rest_account_get_apikey_test() {
+    let str = "api_id access_id secret_key";
+    let mut ret = get_rest();
+    let res_data = ret.account_get().await;
+    let res_data_json: Value = res_data.data;
+    if res_data_json.is_array() {
+        let array = res_data_json.as_array().unwrap();
+        for z in array {
+            let sub_user_name = z["sub_user_name"].as_str().unwrap();
+            info!("coinex--查看子账号列表--{:?}", sub_user_name);
+
+            //每个账号创建apiKey
+            let params = serde_json::json!({
+                "sub_user_name":sub_user_name,
+            });
+            let res_data2 = ret.account_get_apikey(params).await;
+            // trace!("coinex--获取子账号的apikey--{:?}", res_data2);
+            let res_data_json2: Value = res_data2.data;
+            if res_data_json2.is_array() {
+                let array2 = res_data_json2.as_array().unwrap();
+                for z2 in array2 {
+                    let api_id = z2["api_id"].as_i64().unwrap();
+                    let access_id = z2["access_id"].as_str().unwrap();
+                    info!("sub_user_name:{:?} \tapi_id:{:?} \t access_id:{:?}\t ",sub_user_name,api_id,access_id);
+
+                    //查询详情
+                    let params3 = serde_json::json!({
+                       "api_id":api_id
+                    });
+                    let res_data3 = ret.account_get_detail(params3).await;
+                    info!("coinex--详情--{:?}", res_data3.data);
+
+                    //编辑子账号 APIKEY
+                    // let params4 = serde_json::json!({
+                    //     "sub_user_name":sub_user_name,
+                    //     "api_id":api_id,
+                    //     "trade_enabled":true
+                    // });
+                    // let res_data4 = ret.account_get_update(params4).await;
+                    // info!("coinex--编辑结果--{:?}", res_data4.data);
+
+
+                    //删除
+                    // let params2 = serde_json::json!({
+                    //     "api_id":api_id
+                    // });
+                    // let res_data23 = ret.account_del_apikey(params2).await;
+                    // info!("coinex--删除结果--{:?}", res_data23);
+                }
+            }
+        }
+    }
+    // info!("sub_user_name:{:?} \tapi_id:{:?} \t access_id:{:?}\t ",sub_user_name,api_id,access_id)
+}
+
+
 fn get_rest() -> CoinexSwapRest {
+    // init_log_with_trace();
+    init_log_with_info();
     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());