use super::{
fetch,
models::ApiParams
};
use crate::utils::{data_from_json, data_to_json,string_to_f64, get_folder_path};
use serde::Deserialize;
use serde_json::from_str;
use std::error::Error;
#[derive(Deserialize, Debug)]
pub struct Filter {
#[serde(rename = "filterType")]
filter_type: String,
#[serde(rename = "minPrice", deserialize_with = "string_to_f64", default)]
min_price: f64,
#[serde(rename = "maxPrice", deserialize_with = "string_to_f64", default)]
max_price: f64,
#[serde(rename = "minQty", deserialize_with = "string_to_f64", default)]
min_qty: f64,
#[serde(rename = "maxQty", deserialize_with = "string_to_f64", default)]
max_qty: f64,
}
#[derive(Deserialize, Debug)]
pub enum TradingSymbolFilters {
#[serde(rename = "PRICE_FILTER")]
PriceFilter {
#[serde(rename = "minPrice", deserialize_with = "string_to_f64")]
min_price: f64,
#[serde(rename = "maxPrice", deserialize_with = "string_to_f64")]
max_price: f64,
},
#[serde(rename = "LOT_SIZE")]
LotSize {
#[serde(rename = "minQty", deserialize_with = "string_to_f64")]
min_qty: f64,
#[serde(rename = "maxQty", deserialize_with = "string_to_f64")]
max_qty: f64,
},
}
#[derive(Deserialize, Debug)]
pub struct TradingSymbol {
pub symbol: String,
pub status: String,
#[serde(rename = "baseAsset")]
pub base_asset: String,
#[serde(rename = "baseAssetPrecision")]
pub base_asset_precision: u64,
#[serde(rename = "quoteAsset")]
pub quote_asset: String,
#[serde(rename = "quotePrecision")]
pub quote_precision: u64,
#[serde(rename = "orderTypes")]
pub order_types: Vec<String>,
pub filters: Vec<Filter>,
}
impl TradingSymbol {
pub fn filters(&self) -> Vec<TradingSymbolFilters> {
self.filters
.iter()
.filter_map(|filter| match filter.filter_type.as_str() {
"PRICE_FILTER" => Some(TradingSymbolFilters::PriceFilter {
min_price: filter.min_price,
max_price: filter.max_price,
}),
"LOT_SIZE" => Some(TradingSymbolFilters::LotSize {
min_qty: filter.min_qty,
max_qty: filter.max_qty,
}),
_ => None, })
.collect()
}
}
#[derive(Deserialize, Debug)]
pub struct ExchangeInfo {
#[serde(rename = "serverTime")]
pub server_time: u64,
pub symbols: Vec<TradingSymbol>,
}
#[allow(dead_code)]
pub fn remote_to_file(api_params: ApiParams) -> Result<(), Box<dyn Error>> {
let response = fetch::data(api_params)?;
let exchange_info = response.text()?;
let folder_path= get_folder_path(api_params.base_url, "exchangeInfo");
data_to_json(folder_path.as_str(), "info", exchange_info.as_str(), )
}
#[allow(dead_code)]
pub fn info(source: &str, api_params: ApiParams) -> Result<ExchangeInfo, Box<dyn Error>> {
match source {
"api" => {
let response = fetch::data(api_params)?;
let exchange_info: ExchangeInfo = response.json()?;
Ok(exchange_info)
}
"file" => {
let folder_path= get_folder_path(api_params.base_url, "exchangeInfo");
let data = data_from_json(folder_path.as_str(), "info")?;
let exchange_info: ExchangeInfo = from_str(&data)?;
Ok(exchange_info)
}
_ => Err("Invalid source".into()),
}
}