|
|
@@ -22,33 +22,6 @@ pub async fn binan_k(symbol: &str, interval: &str, limit: &i32) -> String {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-fn okx_create_header(api_key: &str, passphrase: &str, sign: &str, timestamp: &str) -> HeaderMap {
|
|
|
- // 处理请求头 headers
|
|
|
-
|
|
|
- let mut header_map = HeaderMap::new();
|
|
|
-
|
|
|
- header_map.insert(
|
|
|
- "OK-ACCESS-KEY",
|
|
|
- HeaderValue::from_str(&api_key).unwrap(),
|
|
|
- );
|
|
|
- header_map.insert(
|
|
|
- "OK-ACCESS-SIGN",
|
|
|
- HeaderValue::from_str(&sign).unwrap());
|
|
|
- header_map.insert(
|
|
|
- "OK-ACCESS-TIMESTAMP",
|
|
|
- HeaderValue::from_str(×tamp).unwrap(),
|
|
|
- );
|
|
|
- header_map.insert(
|
|
|
- "OK-ACCESS-PASSPHRASE",
|
|
|
- HeaderValue::from_str(&passphrase).unwrap(),
|
|
|
- );
|
|
|
- header_map.insert(
|
|
|
- "CONTENT_TYPE",
|
|
|
- HeaderValue::from_static("application/json; charset=UTF-8"),
|
|
|
- );
|
|
|
- header_map
|
|
|
-}
|
|
|
-
|
|
|
|
|
|
/*普通 Get 请求*/
|
|
|
pub async fn get(url: String) -> Result<(String), reqwest::Error> {
|
|
|
@@ -108,6 +81,7 @@ pub fn is_proxy() -> bool {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
pub struct OkxExc {
|
|
|
base_url: String,
|
|
|
access_keu: String,
|
|
|
@@ -120,12 +94,121 @@ impl OkxExc {
|
|
|
OkxExc { base_url: "https://www.okx.com".to_string(), access_keu, secret_key, passphrase }
|
|
|
}
|
|
|
|
|
|
+ //获取订单信息
|
|
|
+ pub async fn okx_get_order(&self, inst_id: &str, ord_id: &str) -> ReqData {
|
|
|
+ let mut btree_map: BTreeMap<&str, &str> = BTreeMap::new();
|
|
|
+ btree_map.insert("instId", inst_id);//产品Id
|
|
|
+ btree_map.insert("ordId", ord_id);//顶顶那
|
|
|
+
|
|
|
+ let result = self.get_v(
|
|
|
+ "/api/v5/trade/order".to_string(),
|
|
|
+ btree_map,
|
|
|
+ ).await;
|
|
|
+
|
|
|
+ match result {
|
|
|
+ Ok(reqData) => {
|
|
|
+ if (reqData.code != "0") {
|
|
|
+ reqData
|
|
|
+ } else {
|
|
|
+ let body: String = reqData.data;
|
|
|
+ let json_value: serde_json::Value = serde_json::from_str(&body).unwrap();
|
|
|
+ let code = json_value["code"].to_string();
|
|
|
+ let data = json_value["data"].to_string();
|
|
|
+ let msg = json_value["msg"].to_string();
|
|
|
+
|
|
|
+ let success = ReqData::new(code.parse().unwrap(),
|
|
|
+ msg.parse().unwrap(),
|
|
|
+ data.parse().unwrap());
|
|
|
+ success
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Err(err) => {
|
|
|
+ let error = ReqData::error(format!("json 解析失败:{}", err));
|
|
|
+ error
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //撤单接口
|
|
|
+ pub async fn okx_revocation_order(&self, inst_id: &str, ord_id: &str) -> ReqData {
|
|
|
+ let mut btree_map: BTreeMap<&str, &str> = BTreeMap::new();
|
|
|
+ btree_map.insert("instId", inst_id);//产品Id
|
|
|
+ btree_map.insert("ordId", ord_id);//顶顶那
|
|
|
+
|
|
|
+ let result = self.post_v(
|
|
|
+ "/api/v5/trade/cancel-order".to_string(),
|
|
|
+ btree_map,
|
|
|
+ ).await;
|
|
|
+
|
|
|
+ match result {
|
|
|
+ Ok(reqData) => {
|
|
|
+ if (reqData.code != "0") {
|
|
|
+ reqData
|
|
|
+ } else {
|
|
|
+ let body: String = reqData.data;
|
|
|
+ let json_value: serde_json::Value = serde_json::from_str(&body).unwrap();
|
|
|
+ let code = json_value["code"].to_string();
|
|
|
+ let data = json_value["data"].to_string();
|
|
|
+ let msg = json_value["msg"].to_string();
|
|
|
+
|
|
|
+ let success = ReqData::new(code.parse().unwrap(),
|
|
|
+ msg.parse().unwrap(),
|
|
|
+ data.parse().unwrap());
|
|
|
+ success
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Err(err) => {
|
|
|
+ let error = ReqData::error(format!("json 解析失败:{}", err));
|
|
|
+ error
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //下单接口
|
|
|
+ pub async fn okx_order(&self, inst_id: &str, td_mode: &str, side: &str, ord_type: &str, px: &str, sz: &str) -> ReqData {
|
|
|
+ let mut btree_map: BTreeMap<&str, &str> = BTreeMap::new();
|
|
|
+ btree_map.insert("instId", inst_id);//产品Id
|
|
|
+ btree_map.insert("tdMode", td_mode);//交易模式
|
|
|
+ btree_map.insert("side", side);//订单方向
|
|
|
+ btree_map.insert("ordType", ord_type);//订单类
|
|
|
+ btree_map.insert("px", px);//委托价格
|
|
|
+ btree_map.insert("sz", sz);//委托数量
|
|
|
+
|
|
|
+ let result = self.post_v(
|
|
|
+ "/api/v5/trade/order".to_string(),
|
|
|
+ btree_map,
|
|
|
+ ).await;
|
|
|
+
|
|
|
+ match result {
|
|
|
+ Ok(reqData) => {
|
|
|
+ if (reqData.code != "0") {
|
|
|
+ reqData
|
|
|
+ } else {
|
|
|
+ let body: String = reqData.data;
|
|
|
+ let json_value: serde_json::Value = serde_json::from_str(&body).unwrap();
|
|
|
+ let code = json_value["code"].to_string();
|
|
|
+ let data = json_value["data"].to_string();
|
|
|
+ let msg = json_value["msg"].to_string();
|
|
|
+
|
|
|
+ let success = ReqData::new(code.parse().unwrap(),
|
|
|
+ msg.parse().unwrap(),
|
|
|
+ data.parse().unwrap());
|
|
|
+ success
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Err(err) => {
|
|
|
+ let error = ReqData::error(format!("json 解析失败:{}", err));
|
|
|
+ error
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
//账户信息
|
|
|
pub async fn okx_acc(&self, ccy: &str) -> ReqData {
|
|
|
let mut btree_map: BTreeMap<&str, &str> = BTreeMap::new();
|
|
|
- btree_map.insert("ccy", &ccy);
|
|
|
+ btree_map.insert("ccy", ccy);
|
|
|
|
|
|
- let result = self.getV(
|
|
|
+ let result = self.get_v(
|
|
|
"/api/v5/account/balance".to_string(),
|
|
|
btree_map,
|
|
|
).await;
|
|
|
@@ -157,8 +240,8 @@ impl OkxExc {
|
|
|
}
|
|
|
|
|
|
//带认证-get
|
|
|
- async fn getV(&self, request_path: String, params: BTreeMap<&str, &str>) -> Result<(ReqData), reqwest::Error> {
|
|
|
- let mut reqData: ReqData;
|
|
|
+ async fn get_v(&self, request_path: String, params: BTreeMap<&str, &str>) -> Result<(ReqData), reqwest::Error> {
|
|
|
+ let mut req_data: ReqData;
|
|
|
|
|
|
/*请求接口与 地址*/
|
|
|
let base_url = self.base_url.to_string();
|
|
|
@@ -180,7 +263,7 @@ impl OkxExc {
|
|
|
let mut sign = self.okx_sign(secret_key, message);
|
|
|
|
|
|
//添加请求头
|
|
|
- let mut headers = okx_create_header(&access_keu, &passphrase, &sign, ×tamp);
|
|
|
+ let mut headers = self.okx_create_header(&access_keu, &passphrase, &sign, ×tamp);
|
|
|
|
|
|
let client = reqwest::Client::new();
|
|
|
let req = client.get(base_url + &get_url_params)
|
|
|
@@ -191,18 +274,77 @@ impl OkxExc {
|
|
|
let response = req.send()
|
|
|
.await?;
|
|
|
// 检查响应是否成功
|
|
|
+ println!("---状态:{:?},{}", response.status(), response.status().is_success());
|
|
|
if response.status().is_success() {
|
|
|
// 读取响应的内容
|
|
|
let body = response.text().await?;
|
|
|
println!("okx_acc-Response body:\n{}", body);
|
|
|
- reqData = ReqData::new("0".to_string(), "success".to_string(), body);
|
|
|
+ req_data = ReqData::new("0".to_string(), "success".to_string(), body);
|
|
|
+ } else {
|
|
|
+ let body = response.text().await?;
|
|
|
+ println!("okx_acc-Request failed with status: {}", body);
|
|
|
+ req_data = ReqData::error(body.to_string())
|
|
|
+ }
|
|
|
+ Ok((req_data))
|
|
|
+ }
|
|
|
+
|
|
|
+ //带认证-post
|
|
|
+ async fn post_v(&self, request_path: String, params: BTreeMap<&str, &str>) -> Result<(ReqData), reqwest::Error> {
|
|
|
+ let mut req_data: ReqData;
|
|
|
+
|
|
|
+ /*请求接口与 地址*/
|
|
|
+ let base_url = self.base_url.to_string();
|
|
|
+
|
|
|
+ /*账号 密钥 密码*/
|
|
|
+ let access_keu = self.access_keu.to_string();
|
|
|
+ let secret_key = self.secret_key.to_string();
|
|
|
+ let passphrase = self.passphrase.to_string();
|
|
|
+
|
|
|
+
|
|
|
+ /*签名生成*/
|
|
|
+ let timestamp = get_timestamp();
|
|
|
+ let params_str = serde_json::to_string(¶ms).unwrap();
|
|
|
+
|
|
|
+ // let params_json = serde_json::to_value(params_str.clone()).unwrap();
|
|
|
+
|
|
|
+ println!("---params:{:?}", params);
|
|
|
+ println!("---params-json_str:{ }", params_str.clone());
|
|
|
+ // println!("---params-json:{:?}", params_json);
|
|
|
+
|
|
|
+ // 时间戳 + 请求类型+ 请求参数字符串
|
|
|
+ let message = format!("{}POST{}{}", timestamp, request_path, ¶ms_str);
|
|
|
+ println!("---message:{:?}", message);
|
|
|
+ let mut sign = self.okx_sign(secret_key, message);
|
|
|
+
|
|
|
+ //添加请求头
|
|
|
+ let mut headers = self.okx_create_header(&access_keu, &passphrase, &sign, ×tamp);
|
|
|
+
|
|
|
+ let client = reqwest::Client::new();
|
|
|
+ let url = format!("{}{}", base_url, request_path);
|
|
|
+ let req = client
|
|
|
+ .post(url)
|
|
|
+ .headers(headers)
|
|
|
+ .json(¶ms)
|
|
|
+ ;
|
|
|
+
|
|
|
+ let response = req.send()
|
|
|
+ .await?;
|
|
|
+ // 检查响应是否成功
|
|
|
+ println!("---状态:{:?},{}", response.status(), response.status().is_success());
|
|
|
+ if response.status().is_success() {
|
|
|
+ // 读取响应的内容
|
|
|
+ let body = response.text().await?;
|
|
|
+ println!("okx_order-Response body:\n{}", body);
|
|
|
+ req_data = ReqData::new("0".to_string(), "success".to_string(), body);
|
|
|
} else {
|
|
|
- println!("okx_acc-Request failed with status: {}", response.status());
|
|
|
- reqData = ReqData::error(response.status().to_string())
|
|
|
+ let body = response.text().await?;
|
|
|
+ println!("okx_order-Request failed with status: {}", body);
|
|
|
+ req_data = ReqData::error(body.to_string())
|
|
|
}
|
|
|
- Ok((reqData))
|
|
|
+ Ok((req_data))
|
|
|
}
|
|
|
|
|
|
+
|
|
|
//okx 签名生成
|
|
|
fn okx_sign(&self, secret_key: String, message: String) -> String {
|
|
|
// 做签名
|
|
|
@@ -210,6 +352,37 @@ impl OkxExc {
|
|
|
let result = ring::hmac::sign(&hmac_key, &message.as_bytes());
|
|
|
base64::encode(result)
|
|
|
}
|
|
|
+
|
|
|
+ fn okx_create_header(&self, api_key: &str, passphrase: &str, sign: &str, timestamp: &str) -> HeaderMap {
|
|
|
+ // 处理请求头 headers
|
|
|
+
|
|
|
+ let mut header_map = HeaderMap::new();
|
|
|
+
|
|
|
+ header_map.insert(
|
|
|
+ "OK-ACCESS-KEY",
|
|
|
+ HeaderValue::from_str(&api_key).unwrap(),
|
|
|
+ );
|
|
|
+ header_map.insert(
|
|
|
+ "OK-ACCESS-SIGN",
|
|
|
+ HeaderValue::from_str(&sign).unwrap());
|
|
|
+ header_map.insert(
|
|
|
+ "OK-ACCESS-TIMESTAMP",
|
|
|
+ HeaderValue::from_str(×tamp).unwrap(),
|
|
|
+ );
|
|
|
+ header_map.insert(
|
|
|
+ "OK-ACCESS-PASSPHRASE",
|
|
|
+ HeaderValue::from_str(&passphrase).unwrap(),
|
|
|
+ );
|
|
|
+ header_map.insert(
|
|
|
+ "CONTENT-TYPE",
|
|
|
+ HeaderValue::from_static("application/json; charset=UTF-8"),
|
|
|
+ );
|
|
|
+ // header_map.insert(
|
|
|
+ // reqwest::header::CONTENT_TYPE,
|
|
|
+ // HeaderValue::from_static("application/json; charset=UTF-8"),
|
|
|
+ // );
|
|
|
+ header_map
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -231,4 +404,3 @@ impl ReqData {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|