|
|
@@ -1,7 +1,7 @@
|
|
|
use std::collections::BTreeMap;
|
|
|
use std::io::{Error, ErrorKind};
|
|
|
use std::str::FromStr;
|
|
|
-use std::sync::mpsc::Sender;
|
|
|
+use tokio::sync::mpsc::Sender;
|
|
|
use async_trait::async_trait;
|
|
|
use rust_decimal::Decimal;
|
|
|
use rust_decimal::prelude::ToPrimitive;
|
|
|
@@ -83,28 +83,32 @@ impl Platform for KucoinSwap {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- async fn get_position(&self, _mode: PositionModeEnum) -> Result<Position, Error> {
|
|
|
- let symbol_array: Vec<&str> = self.symbol.split("_").collect();
|
|
|
+ async fn get_position(&self) -> Result<Position, Error> {
|
|
|
let symbol_format = format!("{}M", utils::format_symbol(self.symbol.clone(), ""));
|
|
|
- let res_data = self.request.get_positions(symbol_array[1].to_string()).await;
|
|
|
+ let res_data = self.request.get_position(symbol_format).await;
|
|
|
if res_data.code == "200" {
|
|
|
let res_data_str = &res_data.data;
|
|
|
- let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
|
|
|
+ let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
|
|
|
+ println!("get_position {}", res_data_json);
|
|
|
let default_info = json!({"high_24h": "0","low_24h": "0","lowest_ask": "0","highest_bid": "0","last": "0","volume_24h": "0"});
|
|
|
- let position_info = res_data_json.iter().find(|item| item["symbol"].as_str().unwrap() == format!("{}M", symbol_format)).unwrap_or(&default_info);
|
|
|
+ let position_info = res_data_json;
|
|
|
let position_mode = match position_info["mode"].as_str().unwrap_or("") {
|
|
|
"dual_long" => PositionModeEnum::Long,
|
|
|
"dual_short" => PositionModeEnum::Both,
|
|
|
_ => PositionModeEnum::Long,
|
|
|
};
|
|
|
+ let symbol = position_info["symbol"].as_str().unwrap_or("");
|
|
|
+ let currency = position_info["settleCurrency"].as_str().unwrap_or("");
|
|
|
+ let coin = symbol.strip_suffix(currency).unwrap();
|
|
|
let result = Position {
|
|
|
- margin_level: position_info["size"].as_str().unwrap_or("1").parse().unwrap_or(dec!(1)),
|
|
|
+ symbol: format!("{}_{}", coin, currency),
|
|
|
+ margin_level: position_info["realLeverage"].as_str().unwrap_or("1").parse().unwrap_or(dec!(1)),
|
|
|
amount: position_info["size"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
frozen_amount: dec!(0),
|
|
|
price: position_info["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
profit: position_info["unrealised_pnl"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
position_mode,
|
|
|
- margin: position_info["margin"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
+ margin: position_info["posMargin"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
};
|
|
|
Ok(result)
|
|
|
} else {
|
|
|
@@ -112,6 +116,10 @@ impl Platform for KucoinSwap {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ async fn get_positions(&self) -> Result<Vec<Position>, Error> {
|
|
|
+ todo!()
|
|
|
+ }
|
|
|
+
|
|
|
async fn get_ticker(&self) -> Result<Ticker, Error> {
|
|
|
let symbol_format = format!("{}M", utils::format_symbol(self.symbol.clone(), ""));
|
|
|
let res_data = self.request.get_ticker(symbol_format).await;
|
|
|
@@ -122,11 +130,11 @@ impl Platform for KucoinSwap {
|
|
|
let time = (Decimal::from_str(&*ticker_info["ts"].to_string()).unwrap() / dec!(1000000)).floor().to_i64().unwrap();
|
|
|
let result = Ticker {
|
|
|
time,
|
|
|
- high: ticker_info["bestAskPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
- low: ticker_info["bestBidPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
- sell: ticker_info["bestAskPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
- buy: ticker_info["bestBidPrice"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
- last: ticker_info["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
+ high: ticker_info["bestAskPrice"].to_string().parse().unwrap_or(dec!(0)),
|
|
|
+ low: ticker_info["bestBidPrice"].to_string().parse().unwrap_or(dec!(0)),
|
|
|
+ sell: ticker_info["bestAskPrice"].to_string().parse().unwrap_or(dec!(0)),
|
|
|
+ buy: ticker_info["bestBidPrice"].to_string().parse().unwrap_or(dec!(0)),
|
|
|
+ last: ticker_info["price"].to_string().parse().unwrap_or(dec!(0)),
|
|
|
volume: ticker_info["size"].to_string().parse().unwrap_or(dec!(0)),
|
|
|
};
|
|
|
Ok(result)
|
|
|
@@ -143,21 +151,20 @@ impl Platform for KucoinSwap {
|
|
|
let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
|
|
|
let default_info = json!({});
|
|
|
let market_info = res_data_json.iter().find(|item| item["symbol"].as_str().unwrap() == symbol_format).unwrap_or(&default_info);
|
|
|
- let tick_size = market_info["order_price_round"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
|
|
|
- let amount_size = market_info["quanto_multiplier"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0));
|
|
|
+ println!("{}", market_info);
|
|
|
|
|
|
let result = Market {
|
|
|
symbol: self.symbol.clone(),
|
|
|
base_asset: market_info["baseCurrency"].as_str().unwrap_or("").to_string(),
|
|
|
quote_asset: market_info["quoteCurrency"].as_str().unwrap_or("").to_string(),
|
|
|
- tick_size,
|
|
|
- amount_size,
|
|
|
+ tick_size: market_info["tickSize"].to_string().parse().unwrap_or(dec!(0)),
|
|
|
+ amount_size: dec!(0),
|
|
|
price_precision: dec!(0),
|
|
|
amount_precision: dec!(0),
|
|
|
- min_qty: market_info["order_size_min"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
- max_qty: market_info["order_size_max"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
+ min_qty: market_info["lotSize"].to_string().parse().unwrap_or(dec!(0)),
|
|
|
+ max_qty: market_info["maxOrderQty"].to_string().parse().unwrap_or(dec!(0)),
|
|
|
min_notional: Default::default(),
|
|
|
- max_notional: Default::default(),
|
|
|
+ max_notional: market_info["maxPrice"].to_string().parse().unwrap_or(dec!(0)),
|
|
|
ct_val: Default::default(),
|
|
|
};
|
|
|
Ok(result)
|
|
|
@@ -166,8 +173,17 @@ impl Platform for KucoinSwap {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- async fn get_order_detail(&self, _order_id: &str, _is_custom_id: bool) -> Result<Order, Error> {
|
|
|
- todo!()
|
|
|
+ async fn get_order_detail(&self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
|
|
|
+ let res_data = self.request.get_orders_details(order_id.to_string(), custom_id.to_string()).await;
|
|
|
+ if res_data.code == "200" {
|
|
|
+ let res_data_str = &res_data.data;
|
|
|
+ let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
|
|
|
+ println!("{}", res_data_json);
|
|
|
+ let result = parse_order_item(&res_data_json);
|
|
|
+ Ok(result)
|
|
|
+ } else {
|
|
|
+ Err(Error::new(ErrorKind::Other, res_data.message))
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
async fn get_orders_list(&self, status: &str) -> Result<Vec<Order>, Error> {
|
|
|
@@ -176,7 +192,7 @@ impl Platform for KucoinSwap {
|
|
|
if res_data.code == "200" {
|
|
|
let res_data_str = &res_data.data;
|
|
|
let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
|
|
|
- let order_info: Vec<_> = res_data_json.iter().filter(|item| item["contract"].as_str().unwrap_or("") == self.symbol.clone()).collect();
|
|
|
+ let order_info: Vec<&serde_json::Value> = res_data_json.iter().filter(|item| item["contract"].as_str().unwrap_or("") == self.symbol.clone()).collect();
|
|
|
let result = order_info.iter().map(|item| parse_order_item(item)).collect();
|
|
|
Ok(result)
|
|
|
} else {
|
|
|
@@ -196,9 +212,33 @@ impl Platform for KucoinSwap {
|
|
|
todo!()
|
|
|
}
|
|
|
|
|
|
- async fn take_order(&self, custom_id: &str, origin_side: &str, _price: Decimal, amount: Decimal) -> Result<Order, Error> {
|
|
|
- let symbol_format = utils::format_symbol(self.symbol.clone(), "_");
|
|
|
- let res_data = self.request.swap_bazaar_order(custom_id.to_string(), symbol_format, origin_side.to_string(), amount.to_u64().unwrap(), "10".to_string(), "".to_string(), "".to_string()).await;
|
|
|
+ async fn take_order(&self, custom_id: &str, origin_side: &str, price: Decimal, amount: Decimal) -> Result<Order, Error> {
|
|
|
+ let symbol_format = format!("{}M", utils::format_symbol(self.symbol.clone(), ""));
|
|
|
+ let mut params = json!({
|
|
|
+ "clientOid": custom_id,
|
|
|
+ "symbol": symbol_format,
|
|
|
+ "leverage": "10",
|
|
|
+ "price": price.to_string(),
|
|
|
+ });
|
|
|
+ let size = amount;
|
|
|
+ params["size"] = json!(size);
|
|
|
+ match origin_side {
|
|
|
+ "kd" => {
|
|
|
+ params["side"] = json!("buy");
|
|
|
+ }
|
|
|
+ "pd" => {
|
|
|
+ params["side"] = json!("sell");
|
|
|
+ }
|
|
|
+ "kk" => {
|
|
|
+ params["side"] = json!("sell");
|
|
|
+ }
|
|
|
+ "pk" => {
|
|
|
+ params["side"] = json!("buy");
|
|
|
+ }
|
|
|
+ _ => { println!("下单参数错误"); }
|
|
|
+ };
|
|
|
+
|
|
|
+ let res_data = self.request.swap_order(Default::default()).await;
|
|
|
if res_data.code == "200" {
|
|
|
let res_data_str = &res_data.data;
|
|
|
let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
|
|
|
@@ -209,9 +249,8 @@ impl Platform for KucoinSwap {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- async fn cancel_order(&self, order_id: &str, _is_custom_id: bool) -> Result<Order, Error> {
|
|
|
- let symbol_array: Vec<&str> = self.symbol.split("_").collect();
|
|
|
- let res_data = self.request.cancel_order(symbol_array[1].to_string().to_lowercase(), order_id.to_string()).await;
|
|
|
+ async fn cancel_order(&self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
|
|
|
+ let res_data = self.request.cancel_order(order_id.to_string(), custom_id.to_string()).await;
|
|
|
if res_data.code == "200" {
|
|
|
let res_data_str = &res_data.data;
|
|
|
let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
|
|
|
@@ -233,14 +272,17 @@ impl Platform for KucoinSwap {
|
|
|
}
|
|
|
|
|
|
fn parse_order_item(order: &serde_json::Value) -> Order {
|
|
|
+ let deal_amount = order["dealSize"].to_string().parse().unwrap_or(dec!(0));
|
|
|
+ let deal_price = order["dealValue"].to_string().parse().unwrap_or(dec!(0));
|
|
|
+ let avg_price = deal_price / deal_amount;
|
|
|
Order {
|
|
|
- id: order["id"].to_string(),
|
|
|
- custom_id: order["text"].to_string(),
|
|
|
+ id: order["id"].as_str().unwrap_or("").parse().unwrap(),
|
|
|
+ custom_id: order["clientOid"].as_str().unwrap_or("").parse().unwrap(),
|
|
|
price: order["price"].as_str().unwrap_or("0").parse().unwrap_or(dec!(0)),
|
|
|
amount: order["size"].to_string().parse().unwrap_or(dec!(0)),
|
|
|
- deal_amount: Default::default(),
|
|
|
- avg_price: Default::default(),
|
|
|
- status: "".to_string(),
|
|
|
- order_type: "".to_string(),
|
|
|
+ deal_amount,
|
|
|
+ avg_price,
|
|
|
+ status: order["status"].as_str().unwrap_or("").parse().unwrap(),
|
|
|
+ order_type: order["type"].as_str().unwrap_or("").parse().unwrap(),
|
|
|
}
|
|
|
}
|