pub use self::backend::CoinDesk;
pub use self::utils::{Group, AssetLookupPriority, Param, call_api_endpoint};
pub use self::schemas::{CCMinResponse, CCMinWrapper, CCRateLimit, CCMaxCalls, CCCallsMade};
pub use self::schemas::min_api::{BalanceDistribution, SupplyBand};
pub use self::schemas::{CoinDeskResponse, CCError, CCErrorOtherInfo};
pub use self::schemas::data_api::indices_and_reference_rates::{IndicesMarket, IndicesOHLCV};
pub use self::schemas::data_api::spot::{SpotMarket, SpotInstrumentStatus, SpotOHLCV, SpotInstrumentMetdata, SpotMarkets, SpotMarketsInstruments};
pub use self::schemas::data_api::futures::{FuturesMarket, FuturesOHLCV, FuturesInstrumentMetadata, FuturesMarkets};
pub use self::schemas::data_api::options::{OptionsMarket, OptionsOHLCV, OptionsInstrumentMetadata, OptionsMarkets};
pub use self::schemas::data_api::derivatives_indices::{DerIndicesMarket, DerIndicesOHLCV, DerIndicesMarkets};
pub use self::schemas::data_api::on_chain_dex::{OCDEXMarket, OCDEXOHLCV, OCDEXMarkets};
pub use self::schemas::data_api::on_chain_core::{OCCoreETHBlock, OCCoreAssetByChain, OCCoreAssetByAddress, OCCoreSupply};
pub use self::schemas::data_api::asset::{AssetMetadata, AssetEvent, AssetCodeRepoMetrics, AssetDiscord, AssetReddit, AssetTelegram, AssetTwitter};
pub use self::schemas::data_api::news::{NewsStatus, NewsLang, NewsSourceID, NewsLatestArticle, NewsSourceType, NewsSource, NewsCategory};
pub use self::schemas::data_api::overview::OverviewMktCapOHLCV;
pub mod error;
pub mod schemas;
pub mod utils;
pub mod backend;
use std::fmt::Display;
use serde::{Serialize, Deserialize};
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
pub enum Unit {
#[default]
Day,
Hour,
Minute,
NA,
}
impl Display for Unit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Day | Unit::NA => write!(f, "/days"),
Self::Hour => write!(f, "/hours"),
Self::Minute => write!(f, "/minutes"),
}
}
}
pub trait APIEndpointTrait {
fn default_groups(&self) -> Option<Vec<Group>>;
fn default_params(&self) -> Option<Vec<Param<'_>>>;
fn url(&self, unit: &Unit) -> String;
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum APIEndpoint {
#[deprecated(since="1.0.6", note="Deprecated by CoinDesk")]
BalanceDistribution,
IndicesOHLCV,
SpotOHLCV,
SpotInstrumentMetadata,
SpotMarketsV2,
SpotMarketsInstruments,
FuturesOHLCV,
FuturesInstrumentMetadata,
FuturesMarketsV2,
OptionsOHLCV,
OptionsInstrumentMetadata,
OptionsMarketsV2,
DerIndicesOHLCV,
DerIndicesMarketsV2,
OCDEXOHLCV,
OCDEXMarketsV2,
OCCoreETHBlocks,
OCCoreAssetsByChain,
OCCoreAssetByAddress,
OCCoreSupply,
AssetMetadataV2,
AssetEvents,
AssetCodeRepo,
AssetDiscord,
AssetReddit,
AssetTelegram,
AssetTwitter,
NewsLatestArticles,
NewsSources,
NewsCategories,
OverviewMktCapOHLCV,
}
impl APIEndpoint {
fn resolve_url(&self) -> String {
match self {
Self::BalanceDistribution => String::from("https://min-api.cryptocompare.com/data/blockchain/balancedistribution/histo/day"),
Self::IndicesOHLCV => String::from("https://data-api.coindesk.com/index/cc/v1/historical"),
Self::SpotOHLCV => String::from("https://data-api.coindesk.com/spot/v1/historical"),
Self::SpotInstrumentMetadata => String::from("https://data-api.coindesk.com/spot/v1/latest/instrument/metadata"),
Self::SpotMarketsV2 => String::from("https://data-api.coindesk.com/spot/v2/markets"),
Self::SpotMarketsInstruments => String::from("https://data-api.coindesk.com/spot/v1/markets/instruments"),
Self::FuturesOHLCV => String::from("https://data-api.coindesk.com/futures/v1/historical"),
Self::FuturesInstrumentMetadata => String::from("https://data-api.coindesk.com/futures/v1/latest/instrument/metadata"),
Self::FuturesMarketsV2 => String::from("https://data-api.coindesk.com/futures/v2/markets"),
Self::OptionsOHLCV => String::from("https://data-api.coindesk.com/options/v1/historical"),
Self::OptionsInstrumentMetadata => String::from("https://data-api.coindesk.com/options/v1/latest/instrument/metadata"),
Self::OptionsMarketsV2 => String::from("https://data-api.coindesk.com/options/v2/markets"),
Self::DerIndicesOHLCV => String::from("https://data-api.coindesk.com/index/v1/historical"),
Self::DerIndicesMarketsV2 => String::from("https://data-api.coindesk.com/index/v2/markets"),
Self::OCDEXOHLCV => String::from("https://data-api.coindesk.com/onchain/v1/amm/historical/swap"),
Self::OCDEXMarketsV2 => String::from("https://data-api.coindesk.com/onchain/v2/amm/markets"),
Self::OCCoreETHBlocks => String::from("https://data-api.coindesk.com/onchain/v1/block/2"),
Self::OCCoreAssetsByChain => String::from("https://data-api.coindesk.com/onchain/v3/summary/by/chain"),
Self::OCCoreAssetByAddress => String::from("https://data-api.coindesk.com/onchain/v2/data/by/address"),
Self::OCCoreSupply => String::from("https://data-api.coindesk.com/onchain/v2/historical/supply/days"),
Self::AssetMetadataV2 => String::from("https://data-api.coindesk.com/asset/v2/metadata"),
Self::AssetEvents => String::from("https://data-api.coindesk.com/asset/v1/events"),
Self::AssetCodeRepo => String::from("https://data-api.coindesk.com/asset/v1/historical/code-repository/days"),
Self::AssetDiscord => String::from("https://data-api.coindesk.com/asset/v1/historical/discord/days"),
Self::AssetReddit => String::from("https://data-api.coindesk.com/asset/v1/historical/reddit/days"),
Self::AssetTelegram => String::from("https://data-api.coindesk.com/asset/v1/historical/telegram/days"),
Self::AssetTwitter => String::from("https://data-api.coindesk.com/asset/v1/historical/twitter/days"),
Self::NewsLatestArticles => String::from("https://data-api.coindesk.com/news/v1/article/list"),
Self::NewsSources => String::from("https://data-api.coindesk.com/news/v1/source/list"),
Self::NewsCategories => String::from("https://data-api.coindesk.com/news/v1/category/list"),
Self::OverviewMktCapOHLCV => String::from("https://data-api.coindesk.com/overview/v1/historical/marketcap/all/assets/days"),
}
}
fn add_unit_to_url(&self, url: &mut String, unit: &Unit) -> () {
match self {
Self::IndicesOHLCV | Self::SpotOHLCV | Self::FuturesOHLCV |
Self::OptionsOHLCV | Self::DerIndicesOHLCV | Self::OCDEXOHLCV => {
url.push_str(&unit.to_string());
},
_ => (),
}
}
}
impl APIEndpointTrait for APIEndpoint {
fn default_groups(&self) -> Option<Vec<Group>> {
match self {
Self::FuturesOHLCV => Some(vec![ Group::Id, Group::Mapping, Group::OHLC, Group::Trade, Group::Volume, Group::MappingAdvanced, Group::OHLCTrade]),
Self::FuturesInstrumentMetadata => Some(vec![Group::Status, Group::General]),
Self::OptionsOHLCV => Some(vec![Group::Id, Group::Mapping, Group::OHLC, Group::Trade, Group::Volume, Group::MappingAdvanced, Group::OHLCTrade]),
Self::OptionsInstrumentMetadata => Some(vec![Group::Status, Group::General]),
Self::DerIndicesOHLCV => Some(vec![Group::Id, Group::OHLC, Group::OHLCMessage, Group::Message, Group::MappingAdvanced]),
Self::OCDEXOHLCV => Some(vec![Group::Id, Group::Mapping, Group::MappingAdvanced, Group::OHLC, Group::OHLCSwap, Group::Swap, Group::Volume]),
Self::OCCoreETHBlocks => Some(vec![Group::Id, Group::Metadata, Group::Transactions, Group::OrphanTraces, Group::Uncles, Group::Withdrawals]),
Self::OCCoreAssetByAddress => Some(vec![
Group::Id, Group::Basic, Group::SupportedPlatforms, Group::SecurityMetrics, Group::Supply, Group::SupplyAddresses,
Group::AssetTypeSpecificMetrics, Group::ResourceLinks, Group::Classification, Group::Price, Group::MktCap, Group::Volume,
Group::Change, Group::ToplistRank, Group::Description, Group::DescriptionSummary, Group::Contact, Group::SEO,
]),
Self::AssetMetadataV2 => Some(vec![Group::Id, Group::Basic, Group::Supply, Group::SupplyAddresses, Group::Classification]),
Self::AssetCodeRepo => Some(vec![Group::Id, Group::General, Group::Activity, Group::Source]),
Self::AssetDiscord => Some(vec![Group::Id, Group::General, Group::Activity, Group::Source]),
Self::AssetReddit => Some(vec![Group::Id, Group::General, Group::Activity, Group::Source]),
Self::AssetTelegram => Some(vec![Group::Id, Group::General, Group::Source]),
Self::AssetTwitter => Some(vec![Group::Id, Group::General, Group::Activity, Group::Source]),
Self::OverviewMktCapOHLCV => Some(vec![Group::Id, Group::OHLC, Group::Volume]),
_ => None,
}
}
fn default_params(&self) -> Option<Vec<Param<'_>>> {
match self {
Self::FuturesInstrumentMetadata => Some(vec![Param::ApplyMapping { v: true, }]),
Self::OptionsInstrumentMetadata => Some(vec![Param::ApplyMapping { v: true, }]),
Self::OCCoreAssetsByChain => Some(vec![Param::AssetLookupPriority { v: AssetLookupPriority::Symbol, }]),
Self::OCCoreAssetByAddress => Some(vec![Param::AssetLookupPriority { v: AssetLookupPriority::Symbol, }]),
Self::AssetMetadataV2 => Some(vec![Param::AssetLookupPriority { v: AssetLookupPriority::Symbol, }, Param::QuoteAsset { v: "USD", }]),
_ => None,
}
}
fn url(&self, unit: &Unit) -> String {
let mut url: String = self.resolve_url();
self.add_unit_to_url(&mut url, unit);
url
}
}
#[cfg(test)]
mod tests {
#[test]
fn unit_test_add_unit_to_url() -> () {
use crate::{Unit, APIEndpointTrait, APIEndpoint};
let unit: Unit = Unit::Hour;
let api_endpoint: APIEndpoint = APIEndpoint::IndicesOHLCV;
assert_eq!(api_endpoint.url(&unit), String::from("https://data-api.coindesk.com/index/cc/v1/historical/hours"));
}
#[test]
fn unit_test_custom_api_endpoint() -> () {
use crate::{Unit, APIEndpointTrait, call_api_endpoint};
enum CustomEndpoint { CustomSpotOHLCV, }
impl APIEndpointTrait for CustomEndpoint {
fn default_groups(&self) -> Option<Vec<crate::Group>> { None }
fn default_params(&self) -> Option<Vec<crate::Param<'_>>> { None }
fn url(&self, unit: &crate::Unit) -> String {
format!("https://data-api.coindesk.com/spot/v1/historical{}", unit.to_string())
}
}
assert_eq!(String::from("https://data-api.coindesk.com/spot/v1/historical/days"), CustomEndpoint::CustomSpotOHLCV.url(&Unit::Day))
}
}