diff --git a/.gitignore b/.gitignore index 471056b..5879244 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ src/main.rs Cargo.lock +.env diff --git a/Cargo.toml b/Cargo.toml index aa53436..0572fdc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +dotenv = "0.15.0" api = "0.2.0" error-chain = "0.12.4" reqwest = { version = "0.12.7", features = ["blocking", "json"] } diff --git a/examples/candle.rs b/examples/candle.rs deleted file mode 100644 index 47674cc..0000000 --- a/examples/candle.rs +++ /dev/null @@ -1,23 +0,0 @@ -use datamaxi::{api::Datamaxi, candle::*}; - -fn main() { - let api_key: &str = "API_KEY"; - let candle: Candle = Datamaxi::new(api_key.to_string()); - - match candle.exchanges("futures") { - Ok(answer) => println!("{:?}", answer), - Err(e) => println!("Error: {}", e), - } - match candle.symbols("binance", "futures") { - Ok(answer) => println!("{:?}", answer), - Err(e) => println!("Error: {}", e), - } - match candle.intervals("binance", "futures") { - Ok(answer) => println!("{:?}", answer), - Err(e) => println!("Error: {}", e), - } - match candle.get("ETH-USDT", "binance", "spot", "1d") { - Ok(answer) => println!("{:?}", answer), - Err(e) => println!("Error: {}", e), - } -} diff --git a/examples/cex-candle.rs b/examples/cex-candle.rs new file mode 100644 index 0000000..8f51ec8 --- /dev/null +++ b/examples/cex-candle.rs @@ -0,0 +1,43 @@ +use datamaxi::cex; +use datamaxi::api::Datamaxi; +use std::env; + +fn main() { + dotenv::dotenv().ok(); + let api_key = env::var("API_KEY").expect("API_KEY not found"); + let candle: cex::Candle = Datamaxi::new(api_key); + + // CEX Candle Exchanges + match candle.exchanges("futures") { + Ok(answer) => println!("{:?}", answer), + Err(e) => println!("Error: {}", e), + } + + // CEX Candle Symbols + let symbols_options = cex::SymbolsOptionalParams::new(); + let symbols_response = candle.symbols("binance", symbols_options); + match symbols_response { + Ok(answer) => match serde_json::to_string(&answer) { + Ok(json) => println!("{}", json), + Err(e) => println!("Error: {}", e), + }, + Err(e) => println!("Error: {}", e), + } + + // CEX Candle Intervals + match candle.intervals("binance", "futures") { + Ok(answer) => println!("{:?}", answer), + Err(e) => println!("Error: {}", e), + } + + // CEX Candle Data + let candle_options = cex::CandleOptionalParams::new(); + let candle_response = candle.get("binance", "ETH-USDT", candle_options); + match candle_response { + Ok(answer) => match serde_json::to_string(&answer) { + Ok(json) => println!("{}", json), + Err(e) => println!("Error: {}", e), + }, + Err(e) => println!("Error: {}", e), + } +} diff --git a/examples/dex-candle.rs b/examples/dex-candle.rs new file mode 100644 index 0000000..ecd5bc6 --- /dev/null +++ b/examples/dex-candle.rs @@ -0,0 +1,54 @@ +use datamaxi::dex; +use datamaxi::api::Datamaxi; +use std::env; + +fn main() { + dotenv::dotenv().ok(); + let api_key = env::var("API_KEY").expect("API_KEY not found"); + let candle: dex::Candle = Datamaxi::new(api_key); + + // DEX Candle Intervals + match candle.intervals() { + Ok(answer) => println!("{:?}", answer), + Err(e) => println!("Error: {}", e), + } + + // DEX Candle Exchanges + match candle.exchanges() { + Ok(answer) => println!("{:?}", answer), + Err(e) => println!("Error: {}", e), + } + + // DEX Candle Chains + match candle.chains() { + Ok(answer) => println!("{:?}", answer), + Err(e) => println!("Error: {}", e), + } + + // DEX Candle Pools + let pools_options = dex::PoolsOptionalParams::new(); + let pools_response = candle.pools(pools_options); + match pools_response { + Ok(answer) => match serde_json::to_string(&answer) { + Ok(json) => println!("{}", json), + Err(e) => println!("Error: {}", e), + }, + Err(e) => println!("Error: {}", e), + } + + // DEX Candle Data + let params = dex::CandleOptionalParams::new(); + let candle_response = candle.get( + "bsc_mainnet", + "pancakeswap", + "0xb24cd29e32FaCDDf9e73831d5cD1FFcd1e535423", + params, + ); + match candle_response { + Ok(answer) => match serde_json::to_string(&answer) { + Ok(json) => println!("{}", json), + Err(e) => println!("Error: {}", e), + }, + Err(e) => println!("Error: {}", e), + } +} diff --git a/examples/dex-trade.rs b/examples/dex-trade.rs new file mode 100644 index 0000000..37186a1 --- /dev/null +++ b/examples/dex-trade.rs @@ -0,0 +1,48 @@ +use datamaxi::dex; +use datamaxi::api::Datamaxi; +use std::env; + +fn main() { + dotenv::dotenv().ok(); + let api_key = env::var("API_KEY").expect("API_KEY not found"); + let trade: dex::Trade = Datamaxi::new(api_key); + + // DEX Trade Exchanges + match trade.exchanges() { + Ok(answer) => println!("{:?}", answer), + Err(e) => println!("Error: {}", e), + } + + // DEX Trade Chains + match trade.chains() { + Ok(answer) => println!("{:?}", answer), + Err(e) => println!("Error: {}", e), + } + + // DEX Trade Pools + let pools_options = dex::PoolsOptionalParams::new(); + let pools_response = trade.pools(pools_options); + match pools_response { + Ok(answer) => match serde_json::to_string(&answer) { + Ok(json) => println!("{}", json), + Err(e) => println!("Error: {}", e), + }, + Err(e) => println!("Error: {}", e), + } + + // DEX Trade Data + let trade_options = dex::TradeOptionalParams::new(); + let trade_response = trade.get( + "bsc_mainnet", + "pancakeswap", + "0xb24cd29e32FaCDDf9e73831d5cD1FFcd1e535423", + trade_options + ); + match trade_response { + Ok(answer) => match serde_json::to_string(&answer) { + Ok(json) => println!("{}", json), + Err(e) => println!("Error: {}", e), + }, + Err(e) => println!("Error: {}", e), + } +} diff --git a/src/api.rs b/src/api.rs index cf01e62..f778cfd 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,118 +1,217 @@ -use crate::candle::Candle; use crate::client::Client; -use crate::forex::Forex; -use crate::fundingrate::FundingRate; -use crate::google::GoogleTrend; -use crate::naver::NaverTrend; +use crate::cex; +use crate::dex; pub enum API { - CandleApi(CandleApi), - FundingRateApi(FundingRateApi), - ForexApi(ForexApi), - NaverTrendApi(NaverTrendApi), - GoogleTrendApi(GoogleTrendApi), + Cex(CexCandleRoute), + Dex(DexRoute), } -pub enum CandleApi { +pub enum CexCandleRoute { + Data, Exchanges, Symbols, Intervals, - CandleDetails, } -pub enum FundingRateApi { - Exchanges, - Symbols, - HistoricalFundingRate, - LatestFundingRate, -} +pub enum DexRoute { + // Candle + CandleData, + CandleChains, + CandleExchanges, + CandlePools, + CandleIntervals, -pub enum ForexApi { - Symbols, - Forex, + // Trade + TradeData, + TradeChains, + TradeExchanges, + TradePools, + TradeIntervals, } -pub enum NaverTrendApi { - Symbols, - Trend, +pub enum DexTradeRoute { + Data, + Chains, + Exchanges, + Pools, } -pub enum GoogleTrendApi { - Keywords, - Trend, +pub trait ApiPath { + fn path(&self) -> &'static str; } -impl From for String { - fn from(item: API) -> Self { - String::from(match item { - API::CandleApi(route) => match route { - CandleApi::CandleDetails => "/candle", - CandleApi::Exchanges => "/candle/exchanges", - CandleApi::Symbols => "/candle/symbols", - CandleApi::Intervals => "/candle/intervals", - }, - API::FundingRateApi(route) => match route { - FundingRateApi::Exchanges => "/funding-rate/exchanges", - FundingRateApi::Symbols => "/funding-rate/symbols", - FundingRateApi::HistoricalFundingRate => "/funding-rate", - FundingRateApi::LatestFundingRate => "/funding-rate/latest", - }, - API::ForexApi(route) => match route { - ForexApi::Symbols => "/forex/symbols", - ForexApi::Forex => "/forex", - }, - API::NaverTrendApi(route) => match route { - NaverTrendApi::Symbols => "/naver/symbols", - NaverTrendApi::Trend => "/naver/trend", - }, - API::GoogleTrendApi(route) => match route { - GoogleTrendApi::Keywords => "/google/keywords", - GoogleTrendApi::Trend => "/google/trend", - }, - }) +impl ApiPath for API { + fn path(&self) -> &'static str { + match self { + API::Cex(route) => route.path(), + API::Dex(route) => route.path(), + } } } -pub trait Datamaxi { - fn new(api_key: String) -> Self; +impl ApiPath for CexCandleRoute { + fn path(&self) -> &'static str { + match self { + CexCandleRoute::Data => "/cex/candle", + CexCandleRoute::Exchanges => "/cex/candle/exchanges", + CexCandleRoute::Symbols => "/cex/candle/symbols", + CexCandleRoute::Intervals => "/cex/candle/intervals", + } + } } -impl Datamaxi for Candle { - fn new(api_key: String) -> Candle { - Candle { - client: Client::new(api_key), +impl ApiPath for DexRoute { + fn path(&self) -> &'static str { + match self { + // candle + DexRoute::CandleData => "/dex/candle", + DexRoute::CandleChains => "/dex/candle/chains", + DexRoute::CandleExchanges => "/dex/candle/exchanges", + DexRoute::CandlePools => "/dex/candle/pools", + DexRoute::CandleIntervals => "/dex/candle/intervals", + + // trade + DexRoute::TradeData => "/dex/trade", + DexRoute::TradeChains => "/dex/trade/chains", + DexRoute::TradeExchanges => "/dex/trade/exchanges", + DexRoute::TradePools => "/dex/trade/pools", + DexRoute::TradeIntervals => "/dex/trade/intervals", } } } -impl Datamaxi for FundingRate { - fn new(api_key: String) -> FundingRate { - FundingRate { - client: Client::new(api_key), - } + +// pub enum API { +// CexCandleApi(CexCandleApi), +// // FundingRateApi(FundingRateApi), +// // ForexApi(ForexApi), +// // NaverTrendApi(NaverTrendApi), +// // GoogleTrendApi(GoogleTrendApi), +// } + +// pub enum CexCandleApi { +// // Exchanges, +// Symbols, +// // Intervals, +// // CandleDetails, +// } + +// pub enum FundingRateApi { +// Exchanges, +// Symbols, +// HistoricalFundingRate, +// LatestFundingRate, +// } + +// pub enum ForexApi { +// Symbols, +// Forex, +// } + +// pub enum NaverTrendApi { +// Symbols, +// Trend, +// } + +// pub enum GoogleTrendApi { +// Keywords,+ +// Trend, +// } + +impl From for String { + fn from(api: API) -> Self { + String::from(api.path()) } } -impl Datamaxi for Forex { - fn new(api_key: String) -> Forex { - Forex { +// impl From for String { +// fn from(item: API) -> Self { +// String::from(match item { +// API::CexCandleApi(route) => match route { +// // CexApi::CandleDetails => "/cex/candle", +// // CexApi::Exchanges => "/cex/candle/exchanges", +// CexCandleApi::Symbols => "/cex/candle/symbols", +// // CexApi::Intervals => "/cex/candle/intervals", +// }, +// // API::FundingRateApi(route) => match route { +// // FundingRateApi::Exchanges => "/funding-rate/exchanges", +// // FundingRateApi::Symbols => "/funding-rate/symbols", +// // FundingRateApi::HistoricalFundingRate => "/funding-rate", +// // FundingRateApi::LatestFundingRate => "/funding-rate/latest", +// // }, +// // API::ForexApi(route) => match route { +// // ForexApi::Symbols => "/forex/symbols", +// // ForexApi::Forex => "/forex", +// // }, +// // API::NaverTrendApi(route) => match route { +// // NaverTrendApi::Symbols => "/naver/symbols", +// // NaverTrendApi::Trend => "/naver/trend", +// // }, +// // API::GoogleTrendApi(route) => match route { +// // GoogleTrendApi::Keywords => "/google/keywords", +// // GoogleTrendApi::Trend => "/google/trend", +// // }, +// }) +// } +// } + +pub trait Datamaxi { + fn new(api_key: String) -> Self; +} + +impl Datamaxi for cex::Candle { + fn new(api_key: String) -> cex::Candle { + cex::Candle { client: Client::new(api_key), } } } -impl Datamaxi for NaverTrend { - fn new(api_key: String) -> NaverTrend { - NaverTrend { +impl Datamaxi for dex::Candle { + fn new(api_key: String) -> dex::Candle { + dex::Candle { client: Client::new(api_key), } } } -impl Datamaxi for GoogleTrend { - fn new(api_key: String) -> GoogleTrend { - GoogleTrend { +impl Datamaxi for dex::Trade { + fn new(api_key: String) -> dex::Trade { + dex::Trade { client: Client::new(api_key), } } } + +// impl Datamaxi for FundingRate { +// fn new(api_key: String) -> FundingRate { +// FundingRate { +// client: Client::new(api_key), +// } +// } +// } + +// impl Datamaxi for Forex { +// fn new(api_key: String) -> Forex { +// Forex { +// client: Client::new(api_key), +// } +// } +// } + +// impl Datamaxi for NaverTrend { +// fn new(api_key: String) -> NaverTrend { +// NaverTrend { +// client: Client::new(api_key), +// } +// } +// } + +// impl Datamaxi for GoogleTrend { +// fn new(api_key: String) -> GoogleTrend { +// GoogleTrend { +// client: Client::new(api_key), +// } +// } +// } diff --git a/src/candle.rs b/src/candle.rs deleted file mode 100644 index 35c44f5..0000000 --- a/src/candle.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::api::CandleApi; -use crate::api::API; -use crate::client::Client; -use crate::error::Result; -use crate::models::CandleResponse; -use crate::utils::build_request; -use std::collections::BTreeMap; - -#[derive(Clone)] -pub struct Candle { - pub client: Client, -} - -impl Candle { - pub fn exchanges(&self, market: M) -> Result> - where - M: Into, - { - let mut parameters: BTreeMap = BTreeMap::new(); - parameters.insert("market".into(), market.into()); - let request = build_request(parameters); - let symbols: Vec = self - .client - .get(API::CandleApi(CandleApi::Exchanges), Some(request))?; - - Ok(symbols) - } - - pub fn symbols(&self, exchange: E, market: M) -> Result> - where - E: Into, - M: Into, - { - let mut parameters: BTreeMap = BTreeMap::new(); - parameters.insert("exchange".into(), exchange.into()); - parameters.insert("market".into(), market.into()); - let request = build_request(parameters); - let symbols: Vec = self - .client - .get(API::CandleApi(CandleApi::Symbols), Some(request))?; - - Ok(symbols) - } - - pub fn intervals(&self, exchange: E, market: M) -> Result> - where - E: Into, - M: Into, - { - let mut parameters: BTreeMap = BTreeMap::new(); - parameters.insert("exchange".into(), exchange.into()); - parameters.insert("market".into(), market.into()); - let request = build_request(parameters); - let symbols: Vec = self - .client - .get(API::CandleApi(CandleApi::Intervals), Some(request))?; - - Ok(symbols) - } - pub fn get( - &self, - symbol: S, - exchange: E, - market: M, - interval: I, - ) -> Result - where - S: Into, - E: Into, - M: Into, - I: Into, - { - let mut parameters: BTreeMap = BTreeMap::new(); - parameters.insert("symbol".into(), symbol.into()); - parameters.insert("exchange".into(), exchange.into()); - parameters.insert("market".into(), market.into()); - parameters.insert("interval".into(), interval.into()); - let request = build_request(parameters); - let candle: CandleResponse = self - .client - .get(API::CandleApi(CandleApi::CandleDetails), Some(request))?; - - Ok(candle) - } -} diff --git a/src/cex.rs b/src/cex.rs new file mode 100644 index 0000000..9855522 --- /dev/null +++ b/src/cex.rs @@ -0,0 +1,137 @@ +use std::collections::HashMap; +use serde::Serialize; +use serde::Deserialize; +use crate::api::API; +use crate::api::CexCandleRoute; +use crate::client::Client; +use crate::error::Result; +use crate::utils::build_request; +use crate::models::CandleResponse; + +#[derive(Serialize, Deserialize, Debug)] +pub struct SymbolResponse { + pub e: String, // exchange + pub m: String, // market + pub b: String, // base + pub q: String, // quote + pub s: String, // symbol + pub id: Option, // unique id +} + +pub struct CandleOptionalParams { + interval: Option, + market: Option, +} + +impl CandleOptionalParams { + pub fn new() -> Self { + CandleOptionalParams { + interval: None, + market: None, + } + } + + pub fn interval(mut self, interval: &str) -> Self { + self.interval = Some(interval.into()); + self + } + + pub fn market(mut self, market: &str) -> Self { + self.market = Some(market.into()); + self + } +} + +pub struct SymbolsOptionalParams { + market: Option, +} + +impl SymbolsOptionalParams { + pub fn new() -> Self { + SymbolsOptionalParams { + market: None, + } + } + + pub fn market(mut self, market: &str) -> Self { + self.market = Some(market.into()); + self + } +} + +#[derive(Clone)] +pub struct Candle { + pub client: Client, +} + +impl Candle { + pub fn get( + &self, + exchange: E, + symbol: S, + params: CandleOptionalParams, + ) -> Result + where + E: Into, + S: Into, + { + let mut parameters = HashMap::from([ + ("exchange".to_string(), exchange.into()), + ("symbol".to_string(), symbol.into()), + ]); + + if let Some(market) = params.market { + parameters.insert("market".to_string(), market); + } + + if let Some(interval) = params.interval { + parameters.insert("interval".to_string(), interval); + } + + let request = build_request(parameters); + self.client.get(API::Cex(CexCandleRoute::Data), Some(request)) + } + + pub fn exchanges(&self, market: M) -> Result> + where + M: Into, + { + let request = build_request( + HashMap::from([ + ("market".to_string(), market.into()), + ]) + ); + self.client.get(API::Cex(CexCandleRoute::Exchanges), Some(request)) + } + + pub fn symbols(&self, exchange: E, params: SymbolsOptionalParams) -> Result> + where + E: Into, + { + let mut parameters = HashMap::from([ + ("exchange".to_string(), exchange.into()), + ]); + + if let Some(market) = params.market { + parameters.insert("market".to_string(), market); + } + + let request = build_request(parameters); + self.client.get(API::Cex(CexCandleRoute::Symbols), Some(request)) + } + + pub fn intervals(&self, exchange: E, market: M) -> Result> + where + E: Into, + M: Into, + { + let request = build_request( + HashMap::from([ + ("exchange".to_string(), exchange.into()), + ("market".to_string(), market.into()), + ]) + ); + + self.client.get(API::Cex(CexCandleRoute::Intervals), Some(request)) + } +} diff --git a/src/dex.rs b/src/dex.rs new file mode 100644 index 0000000..8bf4b62 --- /dev/null +++ b/src/dex.rs @@ -0,0 +1,274 @@ +use std::collections::HashMap; +use serde::Serialize; +use serde::Deserialize; +use crate::api::API; +use crate::api::DexRoute; +use crate::client::Client; +use crate::error::Result; +use crate::utils::build_request; +use crate::models::CandleResponse; +use crate::models::TradeResponse; + +#[derive(Serialize, Deserialize, Debug)] +pub struct PoolsResponse { + pub c: String, // chain + pub e: String, // exchange + pub b: String, // base symbol + pub q: String, // quote symbol + pub ba: String, // base token address + pub qa: String, // quote token address + pub pa: String, // pool address + pub id: Option, // unique id +} + +pub struct CandleOptionalParams { + interval: Option, + page: Option, + limit: Option, + from: Option, + to: Option, + sort: Option, +} + +impl CandleOptionalParams { + pub fn new() -> Self { + CandleOptionalParams { + interval: None, + page: 1.into(), + limit: 1000.into(), + from: None, + to: None, + sort: Some("desc".into()), + } + } + + pub fn interval(mut self, interval: &str) -> Self { + self.interval = Some(interval.into()); + self + } + + pub fn page(mut self, page: i32) -> Self { + self.page = Some(page); + self + } + + pub fn limit(mut self, limit: i32) -> Self { + self.limit = Some(limit); + self + } + + pub fn from(mut self, from: &str) -> Self { + self.from = Some(from.into()); + self + } + + pub fn to(mut self, to: &str) -> Self { + self.to = Some(to.into()); + self + } + + pub fn sort(mut self, sort: &str) -> Self { + self.sort = Some(sort.into()); + self + } +} + +pub struct TradeOptionalParams { + page: Option, + limit: Option, + from: Option, + to: Option, + sort: Option, +} + +impl TradeOptionalParams { + pub fn new() -> Self { + TradeOptionalParams { + page: 1.into(), + limit: 1000.into(), + from: None, + to: None, + sort: Some("desc".into()), + } + } + + pub fn page(mut self, page: i32) -> Self { + self.page = Some(page); + self + } + + pub fn limit(mut self, limit: i32) -> Self { + self.limit = Some(limit); + self + } + + pub fn from(mut self, from: &str) -> Self { + self.from = Some(from.into()); + self + } + + pub fn to(mut self, to: &str) -> Self { + self.to = Some(to.into()); + self + } + + pub fn sort(mut self, sort: &str) -> Self { + self.sort = Some(sort.into()); + self + } +} + +pub struct PoolsOptionalParams { + chain: Option, + exchange: Option, +} + +impl PoolsOptionalParams { + pub fn new() -> Self { + PoolsOptionalParams { + chain: None, + exchange: None, + } + } + + pub fn chain(mut self, chain: &str) -> Self { + self.chain = Some(chain.into()); + self + } + + pub fn exchange(mut self, exchange: &str) -> Self { + self.exchange = Some(exchange.into()); + self + } +} + +#[derive(Clone)] +pub struct Candle { + pub client: Client, +} + +impl Candle { + pub fn get( + &self, + chain: C, + exchange: E, + pool: P, + params: CandleOptionalParams, + ) -> Result + where + C: Into, + E: Into, + P: Into, + { + let mut parameters = HashMap::from([ + ("chain".to_string(), chain.into()), + ("exchange".to_string(), exchange.into()), + ("pool".to_string(), pool.into()), + ]); + + if let Some(interval) = params.interval { + parameters.insert("interval".to_string(), interval); + } + + let request = build_request(parameters); + self.client.get(API::Dex(DexRoute::CandleData), Some(request)) + } + + pub fn pools(&self, options: PoolsOptionalParams) -> Result> + { + let mut parameters = HashMap::new(); + + // optional parameters + parameters.extend( + [ + options.exchange.map(|exchange| ("exchange".to_string(), exchange.to_string())), + options.chain.map(|chain| ("chain".to_string(), chain.to_string())), + ] + .into_iter() + .flatten(), + ); + + let request = build_request(parameters); + self.client.get(API::Dex(DexRoute::CandlePools), Some(request)) + } + + pub fn chains(&self) -> Result> + { + self.client.get(API::Dex(DexRoute::CandleChains), None) + } + + pub fn exchanges(&self) -> Result> + { + self.client.get(API::Dex(DexRoute::CandleExchanges), None) + } + + pub fn intervals(&self) -> Result> + { + self.client.get(API::Dex(DexRoute::CandleIntervals), None) + } +} + +#[derive(Clone)] +pub struct Trade { + pub client: Client, +} + +impl Trade { + pub fn get( + &self, + chain: C, + exchange: E, + pool: P, + params: TradeOptionalParams, + ) -> Result + where + C: Into, + E: Into, + P: Into, + { + // required parameters + let mut parameters = HashMap::new(); + parameters.insert("chain".to_string(), chain.into()); + parameters.insert("exchange".to_string(), exchange.into()); + parameters.insert("pool".to_string(), pool.into()); + + // optional parameters + parameters.extend( + [ + params.page.map(|page| ("page".to_string(), page.to_string())), + params.limit.map(|limit| ("limit".to_string(), limit.to_string())), + params.from.map(|from| ("from".to_string(), from.to_string())), + params.to.map(|to| ("to".to_string(), to.to_string())), + params.sort.map(|sort| ("sort".to_string(), sort.to_string())), + ] + .into_iter() + .flatten(), + ); + + let request = build_request(parameters); + self.client.get(API::Dex(DexRoute::TradeData), Some(request)) + } + + pub fn pools(&self, params: PoolsOptionalParams) -> Result> + { + let mut parameters = HashMap::new(); + if let Some(chain) = params.chain { + parameters.insert("chain".to_string(), chain); + } + if let Some(exchange) = params.exchange { + parameters.insert("exchange".to_string(), exchange); + } + let request = build_request(parameters); + self.client.get(API::Dex(DexRoute::TradePools), Some(request)) + } + + pub fn chains(&self) -> Result> + { + self.client.get(API::Dex(DexRoute::TradeChains), None) + } + + pub fn exchanges(&self) -> Result> + { + self.client.get(API::Dex(DexRoute::TradeExchanges), None) + } +} diff --git a/src/forex.rs b/src/forex.rs index 5c91740..6329f5f 100644 --- a/src/forex.rs +++ b/src/forex.rs @@ -1,23 +1,23 @@ -use crate::api::ForexApi; -use crate::api::API; -use crate::client::Client; -use crate::error::Result; -use crate::models::ForexDetail; +// use crate::api::ForexApi; +// use crate::api::API; +// use crate::client::Client; +// use crate::error::Result; +// use crate::models::ForexDetail; -pub struct Forex { - pub client: Client, -} +// pub struct Forex { +// pub client: Client, +// } -impl Forex { - pub fn symbols(&self) -> Result> { - let symbols: Vec = self.client.get(API::ForexApi(ForexApi::Symbols), None)?; +// impl Forex { +// pub fn symbols(&self) -> Result> { +// let symbols: Vec = self.client.get(API::ForexApi(ForexApi::Symbols), None)?; - Ok(symbols) - } +// Ok(symbols) +// } - pub fn get(&self) -> Result> { - let forex_data: Vec = self.client.get(API::ForexApi(ForexApi::Forex), None)?; +// pub fn get(&self) -> Result> { +// let forex_data: Vec = self.client.get(API::ForexApi(ForexApi::Forex), None)?; - Ok(forex_data) - } -} +// Ok(forex_data) +// } +// } diff --git a/src/fundingrate.rs b/src/fundingrate.rs index 368e8c9..578a93f 100644 --- a/src/fundingrate.rs +++ b/src/fundingrate.rs @@ -1,75 +1,75 @@ -use crate::api::FundingRateApi; -use crate::api::API; -use crate::client::Client; -use crate::error::Result; -use crate::models::HistoricalFundingRateResponse; -use crate::models::LatestFundingRateDetail; -use crate::utils::build_request; -use std::collections::BTreeMap; +// use crate::api::FundingRateApi; +// use crate::api::API; +// use crate::client::Client; +// use crate::error::Result; +// use crate::models::HistoricalFundingRateResponse; +// use crate::models::LatestFundingRateDetail; +// use crate::utils::build_request; +// use std::collections::BTreeMap; -#[derive(Clone)] -pub struct FundingRate { - pub client: Client, -} +// #[derive(Clone)] +// pub struct FundingRate { +// pub client: Client, +// } -impl FundingRate { - pub fn exchanges(&self, market: M) -> Result> - where - M: Into, - { - let mut parameters: BTreeMap = BTreeMap::new(); - parameters.insert("market".into(), market.into()); - let request = build_request(parameters); - let symbols: Vec = self.client.get( - API::FundingRateApi(FundingRateApi::Exchanges), - Some(request), - )?; +// impl FundingRate { +// pub fn exchanges(&self, market: M) -> Result> +// where +// M: Into, +// { +// let mut parameters: BTreeMap = BTreeMap::new(); +// parameters.insert("market".into(), market.into()); +// let request = build_request(parameters); +// let symbols: Vec = self.client.get( +// API::FundingRateApi(FundingRateApi::Exchanges), +// Some(request), +// )?; - Ok(symbols) - } +// Ok(symbols) +// } - pub fn symbols(&self, exchange: E, market: M) -> Result> - where - E: Into, - M: Into, - { - let mut parameters: BTreeMap = BTreeMap::new(); - parameters.insert("exchange".into(), exchange.into()); - parameters.insert("market".into(), market.into()); - let request = build_request(parameters); - let symbols: Vec = self - .client - .get(API::FundingRateApi(FundingRateApi::Symbols), Some(request))?; +// pub fn symbols(&self, exchange: E, market: M) -> Result> +// where +// E: Into, +// M: Into, +// { +// let mut parameters: BTreeMap = BTreeMap::new(); +// parameters.insert("exchange".into(), exchange.into()); +// parameters.insert("market".into(), market.into()); +// let request = build_request(parameters); +// let symbols: Vec = self +// .client +// .get(API::FundingRateApi(FundingRateApi::Symbols), Some(request))?; - Ok(symbols) - } +// Ok(symbols) +// } - pub fn get_latest(&self) -> Result> { - let hisitorical_funding_rate: Vec = self - .client - .get(API::FundingRateApi(FundingRateApi::LatestFundingRate), None)?; +// pub fn get_latest(&self) -> Result> { +// let hisitorical_funding_rate: Vec = self +// .client +// .get(API::FundingRateApi(FundingRateApi::LatestFundingRate), None)?; - Ok(hisitorical_funding_rate) - } +// Ok(hisitorical_funding_rate) +// } - pub fn get_historical( - &self, - symbol: S, - exchange: E, - ) -> Result - where - S: Into, - E: Into, - { - let mut parameters: BTreeMap = BTreeMap::new(); - parameters.insert("symbol".into(), symbol.into()); - parameters.insert("exchange".into(), exchange.into()); - let request = build_request(parameters); - let hisitorical_funding_rate: HistoricalFundingRateResponse = self.client.get( - API::FundingRateApi(FundingRateApi::HistoricalFundingRate), - Some(request), - )?; +// pub fn get_historical( +// &self, +// symbol: S, +// exchange: E, +// ) -> Result +// where +// S: Into, +// E: Into, +// { +// let mut parameters: BTreeMap = BTreeMap::new(); +// parameters.insert("symbol".into(), symbol.into()); +// parameters.insert("exchange".into(), exchange.into()); +// let request = build_request(parameters); +// let hisitorical_funding_rate: HistoricalFundingRateResponse = self.client.get( +// API::FundingRateApi(FundingRateApi::HistoricalFundingRate), +// Some(request), +// )?; - Ok(hisitorical_funding_rate) - } -} +// Ok(hisitorical_funding_rate) +// } +// } diff --git a/src/google.rs b/src/google.rs index 096a854..b103c69 100644 --- a/src/google.rs +++ b/src/google.rs @@ -1,34 +1,34 @@ -use crate::api::GoogleTrendApi; -use crate::api::API; -use crate::client::Client; -use crate::error::Result; -use crate::utils::build_request; -use std::collections::BTreeMap; +// use crate::api::GoogleTrendApi; +// use crate::api::API; +// use crate::client::Client; +// use crate::error::Result; +// use crate::utils::build_request; +// use std::collections::BTreeMap; -pub struct GoogleTrend { - pub client: Client, -} +// pub struct GoogleTrend { +// pub client: Client, +// } -impl GoogleTrend { - pub fn keywords(&self) -> Result> { - let keywords: Vec = self - .client - .get(API::GoogleTrendApi(GoogleTrendApi::Keywords), None)?; +// impl GoogleTrend { +// pub fn keywords(&self) -> Result> { +// let keywords: Vec = self +// .client +// .get(API::GoogleTrendApi(GoogleTrendApi::Keywords), None)?; - Ok(keywords) - } +// Ok(keywords) +// } - pub fn get(&self, keyword: K) -> Result>> - where - K: Into, - { - let mut parameters: BTreeMap = BTreeMap::new(); - parameters.insert("keyword".into(), keyword.into()); - let request = build_request(parameters); - let forex_data: Vec> = self - .client - .get(API::GoogleTrendApi(GoogleTrendApi::Trend), Some(request))?; +// pub fn get(&self, keyword: K) -> Result>> +// where +// K: Into, +// { +// let mut parameters: BTreeMap = BTreeMap::new(); +// parameters.insert("keyword".into(), keyword.into()); +// let request = build_request(parameters); +// let forex_data: Vec> = self +// .client +// .get(API::GoogleTrendApi(GoogleTrendApi::Trend), Some(request))?; - Ok(forex_data) - } -} +// Ok(forex_data) +// } +// } diff --git a/src/lib.rs b/src/lib.rs index b9650e8..622e944 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,8 @@ pub mod client; pub mod api; -pub mod candle; +pub mod cex; +pub mod dex; pub mod error; pub mod forex; pub mod fundingrate; diff --git a/src/models.rs b/src/models.rs index ec8163b..42b20b2 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,10 +1,17 @@ +use serde::Serialize; use serde::Deserialize; -#[derive(Deserialize, Debug)] -pub struct Symbols(pub Vec); -pub struct Intervals(pub Vec); +#[derive(Serialize, Deserialize, Debug)] +pub struct CandleDetail { + pub d: String, // timestamp + pub o: String, // open + pub h: String, // high + pub l: String, // low + pub c: String, // close + pub v: String, // quote volume +} -#[derive(Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug)] pub struct CandleResponse { pub data: Vec, pub page: i32, @@ -14,19 +21,24 @@ pub struct CandleResponse { pub sort: String, } -#[derive(Deserialize, Debug)] -pub struct CandleDetail { - pub d: String, - pub o: String, - pub h: String, - pub l: String, - pub c: String, - pub v: String, +#[derive(Serialize, Deserialize, Debug)] +pub struct TradeDetail { + pub d: String, // timestamp + pub b: i64, // block number + pub pool: String, // pool + pub s: String, // symbol + pub tx: String, // transaction hash + pub m: String, // maker + pub t: String, // type + pub bq: String, // base quantity in base unit + pub qq: String, // quote quantity in base unit + pub p: String, // price in quote unit } -#[derive(Deserialize, Debug)] -pub struct HistoricalFundingRateResponse { - pub data: Vec, + +#[derive(Serialize, Deserialize, Debug)] +pub struct TradeResponse { + pub data: Vec, pub page: i32, pub limit: i32, pub from: String, @@ -34,26 +46,69 @@ pub struct HistoricalFundingRateResponse { pub sort: String, } -#[derive(Deserialize, Debug)] -pub struct HistoricalFundingRateDetail { - pub d: String, - pub f: String, - pub m: String, -} +// #[derive(Deserialize, Debug)] +// pub struct Intervals(pub Vec); -#[derive(Deserialize, Debug)] -pub struct LatestFundingRateDetail { - pub e: String, - pub d: i64, - pub s: String, - pub b: String, - pub q: String, - pub r: f64, -} +// #[derive(Deserialize, Debug)] +// pub struct CexCandleSymbolResponse { +// pub e: String, // exchange +// pub b: String, // base +// pub q: String, // quote +// pub s: String, // symbol +// pub m: String, // market +// pub id: Option, // unique id +// } -#[derive(Deserialize, Debug)] -pub struct ForexDetail { - pub s: String, - pub d: i64, - pub r: f64, -} +// #[derive(Deserialize, Debug)] +// pub struct CandleResponse { +// pub data: Vec, +// pub page: i32, +// pub limit: i32, +// pub from: String, +// pub to: String, +// pub sort: String, +// } + +// #[derive(Deserialize, Debug)] +// pub struct CandleDetail { +// pub d: String, // timestamp +// pub o: String, // open +// pub h: String, // high +// pub l: String, // low +// pub c: String, // close +// pub v: String, // quote volume +// } + +// #[derive(Deserialize, Debug)] +// pub struct HistoricalFundingRateResponse { +// pub data: Vec, +// pub page: i32, +// pub limit: i32, +// pub from: String, +// pub to: String, +// pub sort: String, +// } + +// #[derive(Deserialize, Debug)] +// pub struct HistoricalFundingRateDetail { +// pub d: String, +// pub f: String, +// pub m: String, +// } + +// #[derive(Deserialize, Debug)] +// pub struct LatestFundingRateDetail { +// pub e: String, +// pub d: i64, +// pub s: String, +// pub b: String, +// pub q: String, +// pub r: f64, +// } + +// #[derive(Deserialize, Debug)] +// pub struct ForexDetail { +// pub s: String, +// pub d: i64, +// pub r: f64, +// } diff --git a/src/naver.rs b/src/naver.rs index f65334d..bc7312e 100644 --- a/src/naver.rs +++ b/src/naver.rs @@ -1,34 +1,34 @@ -use crate::api::NaverTrendApi; -use crate::api::API; -use crate::client::Client; -use crate::error::Result; -use crate::utils::build_request; -use std::collections::BTreeMap; +// use crate::api::NaverTrendApi; +// use crate::api::API; +// use crate::client::Client; +// use crate::error::Result; +// use crate::utils::build_request; +// use std::collections::BTreeMap; -pub struct NaverTrend { - pub client: Client, -} +// pub struct NaverTrend { +// pub client: Client, +// } -impl NaverTrend { - pub fn symbols(&self) -> Result> { - let symbols: Vec = self - .client - .get(API::NaverTrendApi(NaverTrendApi::Symbols), None)?; +// impl NaverTrend { +// pub fn symbols(&self) -> Result> { +// let symbols: Vec = self +// .client +// .get(API::NaverTrendApi(NaverTrendApi::Symbols), None)?; - Ok(symbols) - } +// Ok(symbols) +// } - pub fn get(&self, symbol: S) -> Result>> - where - S: Into, - { - let mut parameters: BTreeMap = BTreeMap::new(); - parameters.insert("symbol".into(), symbol.into()); - let request = build_request(parameters); - let forex_data: Vec> = self - .client - .get(API::NaverTrendApi(NaverTrendApi::Trend), Some(request))?; +// pub fn get(&self, symbol: S) -> Result>> +// where +// S: Into, +// { +// let mut parameters: BTreeMap = BTreeMap::new(); +// parameters.insert("symbol".into(), symbol.into()); +// let request = build_request(parameters); +// let forex_data: Vec> = self +// .client +// .get(API::NaverTrendApi(NaverTrendApi::Trend), Some(request))?; - Ok(forex_data) - } -} +// Ok(forex_data) +// } +// } diff --git a/src/utils.rs b/src/utils.rs index 58a94a7..8b0cb5c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,11 +1,9 @@ -use std::collections::BTreeMap; +use std::collections::HashMap; -pub fn build_request(parameters: BTreeMap) -> String { - let mut request = String::new(); - for (key, value) in parameters { - let param = format!("{}={}&", key, value); - request.push_str(param.as_ref()); - } - request.pop(); - request +pub fn build_request(parameters: HashMap) -> String { + parameters + .iter() + .map(|(key, value)| format!("{}={}", key, value)) + .collect::>() + .join("&") }