gate_swap_rest.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. use std::collections::BTreeMap;
  2. use reqwest::header::HeaderMap;
  3. use ring::{digest};
  4. use hex;
  5. use hmac::{Hmac, Mac, NewMac};
  6. use reqwest::Client;
  7. use rust_decimal::Decimal;
  8. use rust_decimal::prelude::FromPrimitive;
  9. use serde_json::Value;
  10. use sha2::Sha512;
  11. use tracing::{error, info};
  12. use crate::http_tool::RestTool;
  13. use crate::response_base::ResponseData;
  14. #[derive(Clone)]
  15. pub struct GateSwapRest {
  16. label: String,
  17. base_url: String,
  18. client: reqwest::Client,
  19. /*******参数*/
  20. //登录所需参数
  21. login_param: BTreeMap<String, String>,
  22. delays: Vec<i64>,
  23. max_delay: i64,
  24. avg_delay: Decimal,
  25. }
  26. impl GateSwapRest {
  27. /*******************************************************************************************************/
  28. /*****************************************获取一个对象****************************************************/
  29. /*******************************************************************************************************/
  30. pub fn new(is_colo: bool, login_param: BTreeMap<String, String>) -> GateSwapRest
  31. {
  32. return GateSwapRest::new_label("default-GateSwapRest".to_string(), is_colo, login_param);
  33. }
  34. pub fn new_label(label: String, is_colo: bool, login_param: BTreeMap<String, String>) -> GateSwapRest
  35. {
  36. let base_url = if is_colo {
  37. let url = "https://apiv4-private.gateapi.io".to_string();
  38. info!("开启高速通道:{:?}",url);
  39. url
  40. } else {
  41. let url = "https://api.gateio.ws".to_string();
  42. info!("走普通通道:{}",url);
  43. url
  44. };
  45. if is_colo {} else {}
  46. /*****返回结构体*******/
  47. GateSwapRest {
  48. label,
  49. base_url: base_url.to_string(),
  50. client: Client::new(),
  51. login_param,
  52. delays: vec![],
  53. max_delay: 0,
  54. avg_delay: Decimal::ZERO,
  55. }
  56. }
  57. /*******************************************************************************************************/
  58. /*****************************************rest请求函数********************************************************/
  59. /*******************************************************************************************************/
  60. //获取服务器当前时间
  61. pub async fn get_server_time(&mut self) -> ResponseData {
  62. let params = serde_json::json!({
  63. });
  64. let data = self.request("GET".to_string(),
  65. "/api/v4".to_string(),
  66. format!("/spot/time"),
  67. true,
  68. params.to_string(),
  69. ).await;
  70. data
  71. }
  72. //查询个人交易费率
  73. pub async fn wallet_fee(&mut self) -> ResponseData {
  74. let params = serde_json::json!({
  75. });
  76. let data = self.request("GET".to_string(),
  77. "/api/v4".to_string(),
  78. format!("/wallet/fee"),
  79. true,
  80. params.to_string(),
  81. ).await;
  82. data
  83. }
  84. //查询合约账户
  85. pub async fn get_account(&mut self, settle: String) -> ResponseData {
  86. let params = serde_json::json!({
  87. });
  88. let data = self.request("GET".to_string(),
  89. "/api/v4".to_string(),
  90. format!("/futures/{}/accounts", settle),
  91. true,
  92. params.to_string(),
  93. ).await;
  94. data
  95. }
  96. //用户仓位列表
  97. pub async fn get_user_position(&mut self, settle: String) -> ResponseData {
  98. let params = serde_json::json!({
  99. });
  100. let data = self.request("GET".to_string(),
  101. "/api/v4".to_string(),
  102. format!("/futures/{}/positions", settle),
  103. true,
  104. params.to_string(),
  105. ).await;
  106. data
  107. }
  108. //双仓模式下的持仓信息
  109. pub async fn get_position(&mut self, settle: String, contract: String) -> ResponseData {
  110. let params = serde_json::json!({
  111. });
  112. let data = self.request("GET".to_string(),
  113. "/api/v4".to_string(),
  114. format!("/futures/{}/dual_comp/positions/{}", settle, contract),
  115. true,
  116. params.to_string(),
  117. ).await;
  118. data
  119. }
  120. //获取所有合约交易行情统计
  121. pub async fn get_ticker(&mut self, settle: String) -> ResponseData {
  122. let params = serde_json::json!({
  123. });
  124. let data = self.request("GET".to_string(),
  125. "/api/v4".to_string(),
  126. format!("/futures/{}/tickers", settle),
  127. true,
  128. params.to_string(),
  129. ).await;
  130. data
  131. }
  132. //查询所有的合约信息
  133. pub async fn get_market_details(&mut self, settle: String) -> ResponseData {
  134. let params = serde_json::json!({
  135. });
  136. let data = self.request("GET".to_string(),
  137. "/api/v4".to_string(),
  138. format!("/futures/{}/contracts", settle),
  139. true,
  140. params.to_string(),
  141. ).await;
  142. data
  143. }
  144. //查询单个订单详情
  145. pub async fn get_order_details(&mut self, settle: String, order_id: String) -> ResponseData {
  146. let params = serde_json::json!({
  147. });
  148. let data = self.request("GET".to_string(),
  149. "/api/v4".to_string(),
  150. format!("/futures/{}/orders/{}", settle, order_id),
  151. true,
  152. params.to_string(),
  153. ).await;
  154. data
  155. }
  156. //查询合约订单列表
  157. pub async fn get_orders(&mut self, settle: String, status: String) -> ResponseData {
  158. let params = serde_json::json!({
  159. "status":status
  160. });
  161. let data = self.request("GET".to_string(),
  162. "/api/v4".to_string(),
  163. format!("/futures/{}/orders", settle),
  164. true,
  165. params.to_string(),
  166. ).await;
  167. data
  168. }
  169. //下单:side-下单方向,pos_side-持仓方向
  170. pub async fn order(&mut self,
  171. settle: String,
  172. pos_side: String,
  173. side: String,
  174. contract: String,
  175. size: i64,
  176. price: String,
  177. text: String,
  178. ) -> ResponseData
  179. {
  180. if side != "buy" && side != "sell" {
  181. ResponseData::error(self.label.clone(), format!("未知下单方向!{}", side));
  182. }
  183. if pos_side != "long" && pos_side != "short" {
  184. ResponseData::error(self.label.clone(), format!("未知持仓方向!{}", side));
  185. }
  186. let mut param = serde_json::json!({
  187. "contract":contract, //合约标识
  188. "size":size,
  189. "price":price,
  190. "text":text,
  191. });
  192. if price == "0" {
  193. param.as_object_mut().unwrap().insert("tif".to_string(), serde_json::json!("ioc"));
  194. }
  195. if size == 0 { //数量为0则平仓
  196. param.as_object_mut().unwrap().insert("close".to_string(), serde_json::json!(true));
  197. }
  198. match format!("{}_{}", pos_side, side).as_str() {
  199. "long_buy" => {//开多
  200. param.as_object_mut().unwrap().insert("reduce_only".to_string(), serde_json::json!(false));
  201. }
  202. "long_sell" => {//平多
  203. param.as_object_mut().unwrap().insert("reduce_only".to_string(), serde_json::json!(true));
  204. }
  205. "short_buy" => {//平空
  206. param.as_object_mut().unwrap().insert("reduce_only".to_string(), serde_json::json!(true));
  207. }
  208. "short_sell" => {//开空
  209. param.as_object_mut().unwrap().insert("reduce_only".to_string(), serde_json::json!(false));
  210. }
  211. _ => {} // 处理未知请求类型
  212. };
  213. // trace!("----param{}", param.to_string());
  214. let data = self.swap_order(settle, param).await;
  215. data
  216. }
  217. //合约交易下单
  218. pub async fn swap_order(&mut self, settle: String, params: serde_json::Value) -> ResponseData {
  219. let data = self.request("POST".to_string(),
  220. "/api/v4".to_string(),
  221. format!("/futures/{}/orders", settle),
  222. true,
  223. params.to_string(),
  224. ).await;
  225. data
  226. }
  227. // 提交一个自动订单
  228. pub async fn place_price_order(&mut self, settle: String, params: Value) -> ResponseData {
  229. self.request("POST".to_string(),
  230. "/api/v4".to_string(),
  231. format!("/futures/{}/price_orders", settle),
  232. true,
  233. params.to_string()).await
  234. }
  235. // 撤销自动订单
  236. pub async fn cancel_price_order(&mut self, settle: String, order_id: String) -> ResponseData {
  237. self.request("DELETE".to_string(),
  238. "/api/v4".to_string(),
  239. format!("/futures/{}/price_orders/{}", settle, order_id),
  240. true,
  241. "{}".to_string(),
  242. ).await
  243. }
  244. //设置持仓模式
  245. pub async fn setting_dual_mode(&mut self, settle: String, dual_mode: bool) -> ResponseData {
  246. let params = serde_json::json!({
  247. "dual_mode":dual_mode,
  248. });
  249. let data = self.request("POST".to_string(),
  250. "/api/v4".to_string(),
  251. format!("/futures/{}/dual_mode", settle),
  252. true,
  253. params.to_string(),
  254. ).await;
  255. data
  256. }
  257. //更新双仓模式下的杠杆
  258. pub async fn setting_dual_leverage(&mut self, settle: String, symbol: String, leverage: String) -> ResponseData {
  259. let params = serde_json::json!({
  260. "leverage":leverage,
  261. });
  262. let data = self.request("POST".to_string(),
  263. "/api/v4".to_string(),
  264. format!("/futures/{}/dual_comp/positions/{}/leverage", settle, symbol),
  265. true,
  266. params.to_string(),
  267. ).await;
  268. data
  269. }
  270. //交易账户互转
  271. pub async fn wallet_transfers(&mut self, currency: String, from: String, to: String, amount: String, settle: String) -> ResponseData {
  272. let params = serde_json::json!({
  273. "currency":currency,
  274. "from":from,
  275. "to":to,
  276. "amount":amount,
  277. "settle":settle,
  278. });
  279. let data = self.request("POST".to_string(),
  280. "/api/v4".to_string(),
  281. format!("/wallet/transfers"),
  282. true,
  283. params.to_string(),
  284. ).await;
  285. data
  286. }
  287. //撤销单个订单
  288. pub async fn cancel_order(&mut self, settle: String, order_id: String) -> ResponseData {
  289. let params = serde_json::json!({
  290. });
  291. let data = self.request("DELETE".to_string(),
  292. "/api/v4".to_string(),
  293. format!("/futures/{}/orders/{}", settle, order_id),
  294. true,
  295. params.to_string(),
  296. ).await;
  297. data
  298. }
  299. //撤销所有挂单
  300. pub async fn cancel_order_all(&mut self) -> ResponseData {
  301. let params = serde_json::json!({
  302. });
  303. let data = self.request("POST".to_string(),
  304. "/api/v5".to_string(),
  305. format!("/sprd/mass-cancel"),
  306. true,
  307. params.to_string(),
  308. ).await;
  309. data
  310. }
  311. //弃用
  312. pub async fn swap_bazaar_order(&mut self, text: String, origin_side: String, settle: String, contract: String, size: i64) -> ResponseData {
  313. let mut reduce_only = false;
  314. let mut param = serde_json::json!({
  315. "text":text,
  316. "contract":contract,
  317. "price":"0",
  318. "size":size,
  319. });
  320. let req = match origin_side.as_str() {
  321. "kd" => {
  322. reduce_only = false;
  323. true
  324. }
  325. "pd" => {
  326. reduce_only = true;
  327. true
  328. }
  329. "kk" => {
  330. reduce_only = false;
  331. true
  332. }
  333. "pk" => {
  334. reduce_only = true;
  335. true
  336. }
  337. _ => { false } // 处理未知请求类型
  338. };
  339. if req {
  340. param.as_object_mut().unwrap().insert("reduce_only".to_string(), serde_json::json!(reduce_only));
  341. }
  342. let data = self.swap_order(settle, param).await;
  343. data
  344. }
  345. //批量取消状态为 open 的订单
  346. pub async fn cancel_orders(&mut self, settle: String, contract: String) -> ResponseData {
  347. let params = serde_json::json!({
  348. "contract":contract
  349. });
  350. let data = self.request("DELETE".to_string(),
  351. "/api/v4".to_string(),
  352. format!("/futures/{}/orders", settle),
  353. true,
  354. params.to_string(),
  355. ).await;
  356. data
  357. }
  358. //查询个人成交记录
  359. pub async fn my_trades(&mut self, settle: String, contract: String, limit: i64) -> ResponseData {
  360. let mut params = serde_json::json!({
  361. "contract":contract,
  362. "limit":1000
  363. });
  364. if limit > 0 {
  365. params["limit"] = serde_json::json!(limit);
  366. }
  367. let data = self.request("GET".to_string(),
  368. "/api/v4".to_string(),
  369. format!("/futures/{}/my_trades", settle),
  370. true,
  371. params.to_string(),
  372. ).await;
  373. data
  374. }
  375. //查询合约账户变更历史
  376. pub async fn account_book(&mut self, settle: String) -> ResponseData {
  377. let params = serde_json::json!({
  378. "limit":200
  379. });
  380. let data = self.request("GET".to_string(),
  381. "/api/v4".to_string(),
  382. format!("/futures/{}/account_book", settle),
  383. true,
  384. params.to_string(),
  385. ).await;
  386. data
  387. }
  388. /*******************************************************************************************************/
  389. /*****************************************工具函数********************************************************/
  390. /*******************************************************************************************************/
  391. pub fn get_delays(&self) -> Vec<i64> {
  392. self.delays.clone()
  393. }
  394. pub fn get_avg_delay(&self) -> Decimal {
  395. self.avg_delay.clone()
  396. }
  397. pub fn get_max_delay(&self) -> i64 {
  398. self.max_delay.clone()
  399. }
  400. fn get_delay_info(&mut self) {
  401. let last_100 = if self.delays.len() > 100 {
  402. self.delays[self.delays.len() - 100..].to_vec()
  403. } else {
  404. self.delays.clone()
  405. };
  406. let max_value = last_100.iter().max().unwrap();
  407. if max_value.clone().to_owned() > self.max_delay {
  408. self.max_delay = max_value.clone().to_owned();
  409. }
  410. let sum: i64 = last_100.iter().sum();
  411. let sum_v = Decimal::from_i64(sum).unwrap();
  412. let len_v = Decimal::from_u64(last_100.len() as u64).unwrap();
  413. self.avg_delay = (sum_v / len_v).round_dp(1);
  414. self.delays = last_100.clone().into_iter().collect();
  415. }
  416. //调用请求
  417. async fn request(&mut self,
  418. requesst_type: String,
  419. prefix_url: String,
  420. request_url: String,
  421. is_login: bool,
  422. params: String) -> ResponseData
  423. {
  424. // trace!("login_param:{:?}", self.login_param);
  425. //解析账号信息
  426. let mut access_key = "".to_string();
  427. let mut secret_key = "".to_string();
  428. if self.login_param.contains_key("access_key") {
  429. access_key = self.login_param.get("access_key").unwrap().to_string();
  430. }
  431. if self.login_param.contains_key("secret_key") {
  432. secret_key = self.login_param.get("secret_key").unwrap().to_string();
  433. }
  434. let mut is_login_param = true;
  435. if access_key == "" || secret_key == "" {
  436. is_login_param = false
  437. }
  438. //请求头配置-如果需要登录则存在额外配置
  439. let mut body = "".to_string();
  440. let timestamp = chrono::Utc::now().timestamp().to_string();
  441. let mut headers = HeaderMap::new();
  442. if requesst_type == "GET" {
  443. headers.insert("Content-type", "application/x-www-form-urlencoded".parse().unwrap());
  444. headers.insert("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ".parse().unwrap());
  445. } else {
  446. headers.insert("Accept", "application/json".parse().unwrap());
  447. headers.insert("Content-Type", "application/json".parse().unwrap());
  448. }
  449. if requesst_type == "POST" {
  450. body = params.clone();
  451. }
  452. //是否需要登录-- 组装sing
  453. if is_login {
  454. if !is_login_param {
  455. let e = ResponseData::error(self.label.clone(), "登录参数错误!".to_string());
  456. return e;
  457. } else {//需要登录-且登录参数齐全
  458. //组装sing
  459. let sing = Self::sign(secret_key.clone(),
  460. requesst_type.clone(),
  461. prefix_url.clone(),
  462. request_url.clone(),
  463. params.clone(),
  464. body.clone(),
  465. timestamp.clone(),
  466. );
  467. // trace!("sing:{}", sing);
  468. //组装header
  469. headers.extend(Self::headers(access_key, timestamp, sing));
  470. }
  471. }
  472. // trace!("headers:{:?}", headers);
  473. let base_url = format!("{}{}", prefix_url.clone(), request_url.clone());
  474. let start_time = chrono::Utc::now().timestamp_millis();
  475. let response = self.http_tool(
  476. base_url.clone(),
  477. requesst_type.to_string(),
  478. params.clone(),
  479. headers,
  480. ).await;
  481. let time_array = chrono::Utc::now().timestamp_millis() - start_time;
  482. self.delays.push(time_array);
  483. self.get_delay_info();
  484. response
  485. }
  486. pub fn headers(access_key: String, timestamp: String, sign: String) -> HeaderMap {
  487. let mut headers = HeaderMap::new();
  488. headers.insert("KEY", access_key.clone().parse().unwrap());
  489. headers.insert("Timestamp", timestamp.clone().parse().unwrap());
  490. headers.insert("SIGN", sign.clone().parse().unwrap());
  491. headers
  492. }
  493. pub fn sign(secret_key: String,
  494. requesst_type: String, prefix_url: String, request_url: String,
  495. params: String, body_data: String, timestamp: String) -> String
  496. {
  497. let url = format!("{}{}", prefix_url, request_url);
  498. let params_str = RestTool::parse_params_to_str(params);
  499. let body = Some(body_data);
  500. let hashed_payload = if let Some(body) = body {
  501. let mut m = digest::Context::new(&digest::SHA512);
  502. m.update(body.as_bytes());
  503. hex::encode(m.finish().as_ref())
  504. } else {
  505. String::new()
  506. };
  507. // trace!("hashed_payload:{}", hashed_payload);
  508. let message = format!("{}\n{}\n{}\n{}\n{}",
  509. requesst_type,
  510. url,
  511. params_str,
  512. hashed_payload,
  513. timestamp);
  514. // trace!("**********", );
  515. // trace!("组装数据:{}", message);
  516. // trace!("**********", );
  517. let mut mac = Hmac::<Sha512>::new_varkey(secret_key.as_bytes()).expect("Failed to create HMAC");
  518. mac.update(message.as_bytes());
  519. let result = mac.finalize().into_bytes();
  520. let sign = hex::encode(result);
  521. sign
  522. }
  523. async fn http_tool(&mut self, request_path: String, request_type: String, params: String, headers: HeaderMap) -> ResponseData {
  524. /****请求接口与 地址*/
  525. let url = format!("{}{}", self.base_url.to_string(), request_path);
  526. let request_type = request_type.clone().to_uppercase();
  527. let addrs_url = format!("{}?{}", url.clone(), RestTool::parse_params_to_str(params.clone()));
  528. let request_builder = match request_type.as_str() {
  529. "GET" => self.client.get(addrs_url.clone()).headers(headers),
  530. "POST" => self.client.post(addrs_url.clone()).body(params.clone()).headers(headers),
  531. "DELETE" => self.client.delete(addrs_url.clone()).headers(headers),
  532. // "PUT" => self.client.put(url.clone()).json(&params),
  533. _ => {
  534. panic!("{}", format!("错误的请求类型:{}", request_type.clone()))
  535. }
  536. };
  537. // 读取响应的内容
  538. let response = request_builder.send().await.unwrap();
  539. let is_success = response.status().is_success(); // 先检查状态码
  540. let text = response.text().await.unwrap();
  541. return if is_success {
  542. self.on_success_data(&text)
  543. } else {
  544. self.on_error_data(&text, &addrs_url, &params)
  545. }
  546. }
  547. pub fn on_success_data(&mut self, text: &String) -> ResponseData {
  548. let data = serde_json::from_str(text.as_str()).unwrap();
  549. ResponseData::new(self.label.clone(), 200, "success".to_string(), data)
  550. }
  551. pub fn on_error_data(&mut self, text: &String, base_url: &String, params: &String) -> ResponseData {
  552. let json_value = serde_json::from_str::<Value>(&text);
  553. match json_value {
  554. Ok(data) => {
  555. let message;
  556. if !data["message"].is_null() {
  557. message = format!("{}:{}", data["label"].as_str().unwrap(), data["message"].as_str().unwrap());
  558. } else {
  559. message = data["label"].to_string();
  560. }
  561. let mut error = ResponseData::error(self.label.clone(), message);
  562. error.message = format!("请求地址:{}, 请求参数:{}, 报错内容:{}。", base_url, params, error.message);
  563. error
  564. }
  565. Err(e) => {
  566. error!("解析错误:{:?}", e);
  567. let error = ResponseData::error("".to_string(),
  568. format!("json 解析失败:{},相关参数:{}", e, text));
  569. error
  570. }
  571. }
  572. }
  573. }