pub mod order; pub mod table_mgmt; use hmac_sha256::HMAC; use crate::RunningMode::*; use crate::{API_KEY, API_KEY_TESTNET, RUNNING_MODE, SECRET_KEY, SECRET_KEY_TESTNET, FUTURES_URL, FUTURES_URL_TEST}; use crate::strategy_team::{AllData, TimeData}; use crate::database_control::*; use rust_decimal::Decimal; use sqlx::FromRow; use hex::ToHex; use crate::future::table_mgmt::select_listuped_positions; #[derive(Debug, PartialEq, Clone, sqlx::Type)] pub enum Position { Long, Short } #[derive(Debug, PartialEq, Clone, sqlx::Type)] pub enum Status { #[sqlx(rename = "listup")] Listup, #[sqlx(rename = "filled")] Filled, #[sqlx(rename = "partially_filled")] PartiallyFilled } impl std::fmt::Display for Position { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{:?}", self) } } pub struct EntryCoinInfo { pub symbol: String, pub close_time: i64, pub registered_server_epoch: i64, } impl EntryCoinInfo { fn new() -> EntryCoinInfo { let a = EntryCoinInfo { symbol: String::new(), close_time: 0, registered_server_epoch: 0 }; a } } #[derive(Debug, Clone)] pub enum ContractType { Perpetual, // this is the target CurrentMonth, NextMonth, CurrentQuarter, NextQuarter, PerpetualDelivering, } #[derive(Debug, Clone)] pub enum ContractStatus { PendingTrading, // this is the target Trading, PreDelivering, Delivering, Delivered, PreSettle, Settling, Close, } #[derive(Debug, FromRow, Clone)] pub struct FuturesExchangeInfo { pub stepsize: Decimal, pub ticksize: Decimal, pub contract_type: ContractType, pub contract_status: ContractStatus, pub base_asset_precision: u32, pub quote_precision: u32, pub notional: Decimal } impl FuturesExchangeInfo { fn new() -> FuturesExchangeInfo { let a = FuturesExchangeInfo { stepsize: Decimal::new(0, 8), ticksize: Decimal::new(0, 8), contract_type: ContractType::Perpetual, contract_status: ContractStatus::Trading, base_asset_precision: 0, quote_precision: 0, notional: Decimal::new(0, 8), }; a } } #[derive(Clone, Debug)] pub struct FuturesTradeFee { user_level: Option, taker_fee_percent: Decimal, maker_fee_percent: Decimal, } impl FuturesTradeFee { pub fn new() -> FuturesTradeFee { let a = FuturesTradeFee { user_level: None, taker_fee_percent: Decimal::new(0, 8), maker_fee_percent: Decimal::new(0, 8), }; a } } #[derive(Debug, FromRow, Clone)] pub struct PositionCoinList { pub id: u64, pub order_type: String, pub status: String, pub symbol: String, pub order_id: u64, pub position: String, pub registered_server_epoch: i64, pub transact_time: i64, pub close_time: i64, pub used_usdt: Decimal, pub expected_get_usdt: f64, pub expected_usdt_profit: f64, pub entry_price: Decimal, pub current_price: Decimal, pub base_qty_ordered: Decimal, pub base_qty_fee_adjusted: Decimal, pub pure_profit_percent: f64, pub minimum_profit_percent: f64, pub maximum_profit_percent: f64, } impl PositionCoinList { fn new() -> PositionCoinList { let a = PositionCoinList{ id: 0, order_type: String::new(), status: String::new(), symbol: String::new(), order_id: 0, position: String::new(), registered_server_epoch: 0, transact_time: 0, close_time: 0, used_usdt: Decimal::new(0, 8), expected_get_usdt: 0.0, expected_usdt_profit: 0.0, entry_price: Decimal::new(0, 8), current_price: Decimal::new(0, 8), base_qty_ordered: Decimal::new(0, 8), base_qty_fee_adjusted: Decimal::new(0, 8), pure_profit_percent: 0.0, minimum_profit_percent: 0.0, maximum_profit_percent: 0.0, }; a } } async fn hmac_signature(query: &mut String) { // fetch time information from [time] table let table_name = String::from("time"); let columns = String::from("*"); let condition = None; let mut time_info = TimeData { server_epoch: 0, local_epoch: 0, epoch_difference: 0, server_ymdhs: String::new(), local_ymdhs: String::new(), last_server_epoch: 0, last_server_ymdhs: String::new(), }; let select_result = select_record(&table_name, &columns, &condition, &time_info) .await .unwrap(); let difference_epoch = select_result.first().unwrap().epoch_difference; let server_epoch = select_result.first().unwrap().server_epoch; // build query message // local 시간이 server 시간보다 너무 앞서거나 뒤쳐지면 USER_DATA를 요청할 수 없으므로 local과 server 의 시간 차이만큼을 local에서 빼어 보정한 뒤 // 이를 timestamp로 사용한다. let mut timestamp; if difference_epoch >= 0 { timestamp = (server_epoch as u128 + difference_epoch as u128).to_string(); } else if difference_epoch < 0 { timestamp = (server_epoch as u128 + (difference_epoch * -1) as u128).to_string(); } else { timestamp = server_epoch.to_string(); } let recv_window_size = "30000".to_string(); // default: 5,000ms, Max: 60,000ms let mut query_build = String::from("×tamp="); query_build.push_str(×tamp); query_build.push_str("&recvWindow="); query_build.push_str(&recv_window_size); let mut secret_key = String::new(); unsafe { if RUNNING_MODE == TEST { secret_key.push_str(SECRET_KEY_TESTNET); } else { secret_key.push_str(SECRET_KEY); } } query.push_str(&query_build); let signature = HMAC::mac(&query.as_bytes(), secret_key.as_bytes()); query.push_str("&signature="); query.push_str(signature.encode_hex::().as_str()); }