use crate::core::types::Symbol;
#[derive(Debug, Clone)]
pub struct TiingoUrls {
pub rest_base: &'static str,
pub _ws_iex: &'static str,
pub _ws_forex: &'static str,
pub _ws_crypto: &'static str,
}
impl TiingoUrls {
pub const MAINNET: Self = Self {
rest_base: "https://api.tiingo.com",
_ws_iex: "wss://api.tiingo.com/iex",
_ws_forex: "wss://api.tiingo.com/fx",
_ws_crypto: "wss://api.tiingo.com/crypto",
};
pub fn rest_url(&self) -> &str {
self.rest_base
}
pub fn _ws_iex_url(&self) -> &str {
self._ws_iex
}
pub fn _ws_forex_url(&self) -> &str {
self._ws_forex
}
pub fn _ws_crypto_url(&self) -> &str {
self._ws_crypto
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[allow(dead_code)]
pub enum TiingoEndpoint {
DailyMeta, DailyPrices,
IexMeta, IexPrices,
CryptoMeta, CryptoTop, CryptoPrices,
ForexTop, ForexPrices,
FundamentalsDefinitions, FundamentalsDaily, FundamentalsStatements,
News, }
impl TiingoEndpoint {
pub fn path(&self) -> &'static str {
match self {
Self::DailyMeta => "/tiingo/daily/{ticker}",
Self::DailyPrices => "/tiingo/daily/{ticker}/prices",
Self::IexMeta => "/iex/{ticker}",
Self::IexPrices => "/iex/{ticker}/prices",
Self::CryptoMeta => "/tiingo/crypto",
Self::CryptoTop => "/tiingo/crypto/top",
Self::CryptoPrices => "/tiingo/crypto/prices",
Self::ForexTop => "/tiingo/fx/{ticker}/top",
Self::ForexPrices => "/tiingo/fx/{ticker}/prices",
Self::FundamentalsDefinitions => "/tiingo/fundamentals/definitions",
Self::FundamentalsDaily => "/tiingo/fundamentals/{ticker}/daily",
Self::FundamentalsStatements => "/tiingo/fundamentals/{ticker}/statements",
Self::News => "/tiingo/news",
}
}
pub fn _requires_auth(&self) -> bool {
true
}
pub fn _method(&self) -> &'static str {
"GET" }
pub fn build_url(&self, base_url: &str, ticker: Option<&str>) -> String {
let path = self.path();
let url = format!("{}{}", base_url, path);
if let Some(ticker) = ticker {
url.replace("{ticker}", ticker)
} else {
url
}
}
}
pub fn format_crypto_symbol(symbol: &Symbol) -> String {
format!("{}{}", symbol.base, symbol.quote).to_lowercase()
}
pub fn format_forex_symbol(symbol: &Symbol) -> String {
format!("{}{}", symbol.base, symbol.quote).to_lowercase()
}
pub fn map_interval(interval: &str) -> &'static str {
match interval {
"1m" => "1min",
"5m" => "5min",
"15m" => "15min",
"30m" => "30min",
"1h" => "1hour",
"4h" => "4hour",
"1d" => "1day",
"1w" => "weekly",
"1M" => "monthly",
_ => "1day",
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_format_crypto_symbol() {
let btc = Symbol::new("BTC", "USD");
assert_eq!(format_crypto_symbol(&btc), "btcusd");
let eth = Symbol::new("eth", "usdt");
assert_eq!(format_crypto_symbol(ð), "ethusdt");
}
#[test]
fn test_format_forex_symbol() {
let eur = Symbol::new("EUR", "USD");
assert_eq!(format_forex_symbol(&eur), "eurusd");
}
#[test]
fn test_map_interval() {
assert_eq!(map_interval("1m"), "1min");
assert_eq!(map_interval("5m"), "5min");
assert_eq!(map_interval("1h"), "1hour");
assert_eq!(map_interval("1d"), "1day");
assert_eq!(map_interval("1w"), "weekly");
}
#[test]
fn test_endpoint_build_url() {
let endpoint = TiingoEndpoint::DailyPrices;
let url = endpoint.build_url("https://api.tiingo.com", Some("AAPL"));
assert_eq!(url, "https://api.tiingo.com/tiingo/daily/AAPL/prices");
}
}