|
|
@@ -1,23 +1,19 @@
|
|
|
-use std::collections::{BTreeMap, HashMap};
|
|
|
+use std::collections::{BTreeMap};
|
|
|
use std::{env, io, thread};
|
|
|
-use std::io::{Stdout, Write};
|
|
|
+use std::io::{Write};
|
|
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
|
|
use std::str::FromStr;
|
|
|
use std::time::Duration;
|
|
|
use chrono::Utc;
|
|
|
use reqwest;
|
|
|
-use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
|
|
|
+use reqwest::header::{HeaderMap, HeaderValue};
|
|
|
use hex;
|
|
|
-use reqwest::Response;
|
|
|
use ring::hmac;
|
|
|
-use serde_json::{json, Value};
|
|
|
-use serde_json::map::Values;
|
|
|
-use tungstenite::client::{AutoStream, connect_with_proxy, ProxyAutoStream};
|
|
|
-use tungstenite::{connect, Message, WebSocket};
|
|
|
+use serde_json::{json};
|
|
|
+use tungstenite::client::{connect_with_proxy};
|
|
|
+use tungstenite::{connect, Message};
|
|
|
use tungstenite::protocol::WebSocketConfig;
|
|
|
use url::Url;
|
|
|
-use tungstenite::stream::Stream;
|
|
|
-// use std::io::{self, Write,io};
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
@@ -204,28 +200,7 @@ impl OkxExc {
|
|
|
btree_map,
|
|
|
).await;
|
|
|
|
|
|
- match result {
|
|
|
- Ok(req_data) => {
|
|
|
- if req_data.code != "0" {
|
|
|
- req_data
|
|
|
- } else {
|
|
|
- let body: String = req_data.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
|
|
|
- }
|
|
|
- }
|
|
|
+ self.req_data_analysis(result)
|
|
|
}
|
|
|
|
|
|
//撤单接口
|
|
|
@@ -239,28 +214,7 @@ impl OkxExc {
|
|
|
btree_map,
|
|
|
).await;
|
|
|
|
|
|
- match result {
|
|
|
- Ok(req_data) => {
|
|
|
- if req_data.code != "0" {
|
|
|
- req_data
|
|
|
- } else {
|
|
|
- let body: String = req_data.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
|
|
|
- }
|
|
|
- }
|
|
|
+ self.req_data_analysis(result)
|
|
|
}
|
|
|
|
|
|
//下单接口
|
|
|
@@ -278,28 +232,7 @@ impl OkxExc {
|
|
|
btree_map,
|
|
|
).await;
|
|
|
|
|
|
- match result {
|
|
|
- Ok(req_data) => {
|
|
|
- if req_data.code != "0" {
|
|
|
- req_data
|
|
|
- } else {
|
|
|
- let body: String = req_data.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
|
|
|
- }
|
|
|
- }
|
|
|
+ self.req_data_analysis(result)
|
|
|
}
|
|
|
|
|
|
//账户信息
|
|
|
@@ -311,31 +244,8 @@ impl OkxExc {
|
|
|
"/api/v5/account/balance".to_string(),
|
|
|
btree_map,
|
|
|
).await;
|
|
|
- match result {
|
|
|
- Ok(req_data) => {
|
|
|
- if req_data.code != "0" {
|
|
|
- req_data
|
|
|
- } else {
|
|
|
- let body: String = req_data.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();
|
|
|
|
|
|
- // println!("--解析成功----code:{}",code);
|
|
|
- // println!("--解析成功----data:{}",data);
|
|
|
- // println!("--解析成功----msg:{}",msg);
|
|
|
- let success = ReqData::new(code.parse().unwrap(),
|
|
|
- msg.parse().unwrap(),
|
|
|
- data.parse().unwrap());
|
|
|
- success
|
|
|
- }
|
|
|
- }
|
|
|
- Err(err) => {
|
|
|
- let error = ReqData::error(format!("json 解析失败:{}", err));
|
|
|
- error
|
|
|
- }
|
|
|
- }
|
|
|
+ self.req_data_analysis(result)
|
|
|
}
|
|
|
|
|
|
//带认证-get
|
|
|
@@ -353,16 +263,16 @@ impl OkxExc {
|
|
|
|
|
|
/*签名生成*/
|
|
|
let timestamp = get_timestamp();
|
|
|
- let mut params_str = parse_params_to_str(params);
|
|
|
+ let params_str = parse_params_to_str(params);
|
|
|
let get_url_params = format!("{}?{}", request_path, params_str); //接口与参数组装
|
|
|
|
|
|
// 时间戳 + 请求类型+ 请求参数字符串
|
|
|
let message = format!("{}GET{}", timestamp, get_url_params);
|
|
|
println!("---message:{:?}", message);
|
|
|
- let mut sign = self.okx_sign(secret_key, message);
|
|
|
+ let sign = self.okx_sign(secret_key, message);
|
|
|
|
|
|
//添加请求头
|
|
|
- let mut headers = self.okx_create_header(&access_key, &passphrase, &sign, ×tamp);
|
|
|
+ let headers = self.okx_create_header(&access_key, &passphrase, &sign, ×tamp);
|
|
|
|
|
|
let client = reqwest::Client::new();
|
|
|
let req = client.get(base_url + &get_url_params)
|
|
|
@@ -413,10 +323,10 @@ impl OkxExc {
|
|
|
// 时间戳 + 请求类型+ 请求参数字符串
|
|
|
let message = format!("{}POST{}{}", timestamp, request_path, ¶ms_str);
|
|
|
println!("---message:{:?}", message);
|
|
|
- let mut sign = self.okx_sign(secret_key, message);
|
|
|
+ let sign = self.okx_sign(secret_key, message);
|
|
|
|
|
|
//添加请求头
|
|
|
- let mut headers = self.okx_create_header(&access_key, &passphrase, &sign, ×tamp);
|
|
|
+ let headers = self.okx_create_header(&access_key, &passphrase, &sign, ×tamp);
|
|
|
|
|
|
let client = reqwest::Client::new();
|
|
|
let url = format!("{}{}", base_url, request_path);
|
|
|
@@ -443,7 +353,6 @@ impl OkxExc {
|
|
|
Ok((req_data))
|
|
|
}
|
|
|
|
|
|
-
|
|
|
//okx 签名生成
|
|
|
fn okx_sign(&self, secret_key: String, message: String) -> String {
|
|
|
// 做签名
|
|
|
@@ -452,6 +361,7 @@ impl OkxExc {
|
|
|
base64::encode(result)
|
|
|
}
|
|
|
|
|
|
+ //生成hdear
|
|
|
fn okx_create_header(&self, api_key: &str, passphrase: &str, sign: &str, timestamp: &str) -> HeaderMap {
|
|
|
// 处理请求头 headers
|
|
|
|
|
|
@@ -482,6 +392,35 @@ impl OkxExc {
|
|
|
// );
|
|
|
header_map
|
|
|
}
|
|
|
+
|
|
|
+ //req_data 解析
|
|
|
+ fn req_data_analysis(&self, result: Result<ReqData, reqwest::Error>) -> ReqData {
|
|
|
+ match result {
|
|
|
+ Ok(req_data) => {
|
|
|
+ if req_data.code != "0" {
|
|
|
+ req_data
|
|
|
+ } else {
|
|
|
+ let body: String = req_data.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();
|
|
|
+
|
|
|
+ // println!("--解析成功----code:{}",code);
|
|
|
+ // println!("--解析成功----data:{}",data);
|
|
|
+ // println!("--解析成功----msg:{}",msg);
|
|
|
+ let success = ReqData::new(code.parse().unwrap(),
|
|
|
+ msg.parse().unwrap(),
|
|
|
+ data.parse().unwrap());
|
|
|
+ success
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Err(err) => {
|
|
|
+ let error = ReqData::error(format!("json 解析失败:{}", err));
|
|
|
+ error
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
//代理
|
|
|
@@ -541,8 +480,8 @@ impl ReqData {
|
|
|
}
|
|
|
|
|
|
|
|
|
-type HookFn = fn(String);
|
|
|
-
|
|
|
+pub type ParseFn = fn(String);
|
|
|
+pub type HookFn = fn(String, ParseFn);
|
|
|
|
|
|
pub struct SocketTool {
|
|
|
//连接地址
|
|
|
@@ -557,8 +496,6 @@ pub struct SocketTool {
|
|
|
login_param: BTreeMap<String, String>,
|
|
|
//订阅参数
|
|
|
subscription: serde_json::Value,
|
|
|
- //回调
|
|
|
- hook_fn: HookFn,
|
|
|
}
|
|
|
|
|
|
impl SocketTool {
|
|
|
@@ -566,7 +503,6 @@ impl SocketTool {
|
|
|
is_login: bool,
|
|
|
login_param: BTreeMap<String, String>,
|
|
|
subscription: serde_json::Value,
|
|
|
- hookfn: HookFn,
|
|
|
) -> SocketTool {
|
|
|
let mut ip_v = "";
|
|
|
let mut port_v = 8080;
|
|
|
@@ -600,10 +536,9 @@ impl SocketTool {
|
|
|
is_login: is_login,
|
|
|
login_param: login_param,
|
|
|
subscription: subscription,
|
|
|
- hook_fn: hookfn,
|
|
|
}
|
|
|
}
|
|
|
- pub fn run(&self) {
|
|
|
+ pub(crate) fn run(&self, exc_name: String, parse_fn: ParseFn) {
|
|
|
/*****消息溜***/
|
|
|
let mut stdout = io::stdout();
|
|
|
let mut stderr = io::stderr();
|
|
|
@@ -634,7 +569,6 @@ impl SocketTool {
|
|
|
/******登陆认证********/
|
|
|
if self.is_login {
|
|
|
println!("----需要登陆");
|
|
|
- let lable = self.login_param.get("lable");
|
|
|
|
|
|
let login_json_str = self.log_in_to_str();
|
|
|
println!("---组装 登陆信息:{0}", login_json_str);
|
|
|
@@ -653,7 +587,6 @@ impl SocketTool {
|
|
|
.unwrap();
|
|
|
|
|
|
/******数据读取********/
|
|
|
- let mut z_time = Utc::now().timestamp() ;
|
|
|
loop {
|
|
|
if !socket.can_read() {
|
|
|
continue;
|
|
|
@@ -664,7 +597,11 @@ impl SocketTool {
|
|
|
match msg {
|
|
|
Ok(Message::Text(text)) => {
|
|
|
writeln!(stdout, "{:?}", text).unwrap();
|
|
|
- (self.hook_fn)("mamamimya".to_string());
|
|
|
+ if exc_name == "binance" {
|
|
|
+ SocketTool::hook_fn_binance(text, parse_fn)
|
|
|
+ } else if exc_name == "okx" {
|
|
|
+ SocketTool::hook_fn_okx(text, parse_fn)
|
|
|
+ }
|
|
|
}
|
|
|
Ok(Message::Ping(_)) | Ok(Message::Pong(_)) | Ok(Message::Close(_)) => {
|
|
|
socket.write_message(Message::text("pong"));
|
|
|
@@ -690,7 +627,6 @@ impl SocketTool {
|
|
|
/******登陆认证********/
|
|
|
if self.is_login {
|
|
|
println!("----需要登陆");
|
|
|
- let lable = self.login_param.get("lable");
|
|
|
|
|
|
let login_json_str = self.log_in_to_str();
|
|
|
println!("---组装 登陆信息:{0}", login_json_str);
|
|
|
@@ -719,7 +655,12 @@ impl SocketTool {
|
|
|
match msg {
|
|
|
Ok(Message::Text(text)) => {
|
|
|
writeln!(stdout, "{:?}", text).unwrap();
|
|
|
- (self.hook_fn)("mamamimya".to_string());
|
|
|
+ println!("??????????---{0}--",exc_name);
|
|
|
+ if exc_name == "binance" {
|
|
|
+ SocketTool::hook_fn_binance(text, parse_fn)
|
|
|
+ } else if exc_name == "okx" {
|
|
|
+ SocketTool::hook_fn_okx(text, parse_fn)
|
|
|
+ }
|
|
|
}
|
|
|
Ok(Message::Ping(_)) | Ok(Message::Pong(_)) | Ok(Message::Close(_)) => {
|
|
|
socket.write_message(Message::Pong(vec![]))
|
|
|
@@ -789,6 +730,57 @@ impl SocketTool {
|
|
|
|
|
|
login_json_str
|
|
|
}
|
|
|
+
|
|
|
+ //币安--深度信息
|
|
|
+ pub fn binance_run_kline(b_array: Vec<&str>, channel: String, time_str: String, parse_fn: ParseFn) {
|
|
|
+ let str = format!("{}_{}", channel, time_str);
|
|
|
+ SocketTool::binance_run(b_array, str, parse_fn);
|
|
|
+ }
|
|
|
+ //币安--深度信息
|
|
|
+ pub fn binance_run_depth(b_array: Vec<&str>, channel: String, time_str: String, parse_fn: ParseFn) {
|
|
|
+ let str = format!("{}@{}", channel, time_str);
|
|
|
+ SocketTool::binance_run(b_array, str, parse_fn);
|
|
|
+ }
|
|
|
+ //币安--订阅
|
|
|
+ pub fn binance_run(b_array: Vec<&str>, subscription_name: String, parse_fn: ParseFn) {
|
|
|
+ let mut params = vec![];
|
|
|
+
|
|
|
+ for item in &b_array {
|
|
|
+ let mut b_name = item.to_lowercase();
|
|
|
+ b_name = format!("{}@{}", b_name, subscription_name);
|
|
|
+ println!("-订阅频道--{0}", b_name);
|
|
|
+ params.push(b_name);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 币安----socket
|
|
|
+ let subscription = json!({
|
|
|
+ "method": "SUBSCRIBE",
|
|
|
+ "params":params,
|
|
|
+ // [
|
|
|
+ // "btcusdt@depth@100ms",//深度信息
|
|
|
+ // "btcusdt@kline_1s"//k线信息
|
|
|
+ // ],
|
|
|
+ "id": 1
|
|
|
+ });
|
|
|
+ let mut btree_map: BTreeMap<String, String> = BTreeMap::new();
|
|
|
+ btree_map.insert("lable".parse().unwrap(), "binance".parse().unwrap());//产品Id
|
|
|
+ let biance_socke = SocketTool::new("wss://stream.binance.com:443/ws",
|
|
|
+ false,
|
|
|
+ btree_map,
|
|
|
+ subscription,
|
|
|
+ );
|
|
|
+ biance_socke.run("binance".to_string(), parse_fn);
|
|
|
+ }
|
|
|
+ fn hook_fn_binance(message: String, parse_fn: ParseFn) {
|
|
|
+ println!("币安--回调函数:响应: {}", message);
|
|
|
+ parse_fn(message);
|
|
|
+ }
|
|
|
+ fn hook_fn_okx(message: String, parse_fn: ParseFn) {
|
|
|
+ println!("OKX--回调函数:响应: {}", message);
|
|
|
+ parse_fn(message);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|