use serde::{Deserialize, Deserializer, Serialize};
use std::collections::HashMap;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum CmcError {
#[error("HTTP error: {0}")]
Http(#[from] reqwest_middleware::Error),
#[error("Request error: {0}")]
Request(#[from] reqwest::Error),
#[error("API error {code}: {message}")]
Api { code: i32, message: String },
}
fn deserialize_error_code<'de, D>(deserializer: D) -> Result<i32, D::Error>
where
D: Deserializer<'de>,
{
use serde::de;
#[derive(Deserialize)]
#[serde(untagged)]
enum StringOrInt {
String(String),
Int(i32),
}
match StringOrInt::deserialize(deserializer)? {
StringOrInt::String(s) => s.parse().map_err(de::Error::custom),
StringOrInt::Int(i) => Ok(i),
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Status {
pub timestamp: String,
#[serde(deserialize_with = "deserialize_error_code")]
pub error_code: i32,
#[serde(default)]
pub error_message: Option<String>,
pub elapsed: i32,
pub credit_count: i32,
#[serde(default)]
pub notice: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Platform {
pub id: i32,
pub name: String,
pub symbol: String,
pub slug: String,
pub token_address: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Quote {
pub price: Option<f64>,
pub volume_24h: Option<f64>,
pub volume_change_24h: Option<f64>,
pub percent_change_1h: Option<f64>,
pub percent_change_24h: Option<f64>,
pub percent_change_7d: Option<f64>,
pub market_cap: Option<f64>,
pub market_cap_dominance: Option<f64>,
pub fully_diluted_market_cap: Option<f64>,
pub last_updated: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Cryptocurrency {
pub id: i32,
pub name: String,
pub symbol: String,
pub slug: String,
pub num_market_pairs: Option<i32>,
pub date_added: Option<String>,
pub tags: Option<Vec<String>>,
pub max_supply: Option<f64>,
pub circulating_supply: Option<f64>,
pub total_supply: Option<f64>,
pub infinite_supply: Option<bool>,
pub platform: Option<Platform>,
pub cmc_rank: Option<i32>,
pub self_reported_circulating_supply: Option<f64>,
pub self_reported_market_cap: Option<f64>,
pub tvl_ratio: Option<f64>,
pub last_updated: String,
pub quote: HashMap<String, Quote>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListingsLatestResponse {
pub status: Status,
pub data: Vec<Cryptocurrency>,
}
#[derive(Debug, Clone, Default)]
pub struct GetListingsLatestRequest {
pub start: Option<i32>,
pub limit: Option<i32>,
pub price_min: Option<f64>,
pub price_max: Option<f64>,
pub market_cap_min: Option<f64>,
pub market_cap_max: Option<f64>,
pub volume_24h_min: Option<f64>,
pub volume_24h_max: Option<f64>,
pub circulating_supply_min: Option<f64>,
pub circulating_supply_max: Option<f64>,
pub percent_change_24h_min: Option<f64>,
pub percent_change_24h_max: Option<f64>,
pub convert: Option<String>,
pub convert_id: Option<String>,
pub sort: Option<String>,
pub sort_dir: Option<String>,
pub cryptocurrency_type: Option<String>,
pub tag: Option<String>,
pub aux: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GlobalQuote {
pub total_market_cap: f64,
pub total_volume_24h: f64,
pub total_volume_24h_reported: f64,
pub altcoin_volume_24h: f64,
pub altcoin_market_cap: f64,
pub defi_volume_24h: Option<f64>,
pub defi_market_cap: Option<f64>,
pub defi_24h_percentage_change: Option<f64>,
pub stablecoin_volume_24h: Option<f64>,
pub stablecoin_market_cap: Option<f64>,
pub stablecoin_24h_percentage_change: Option<f64>,
pub der_volume_24h: Option<f64>,
pub der_24h_percentage_change: Option<f64>,
pub last_updated: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GlobalMetricsQuotesLatestData {
pub active_cryptocurrencies: i32,
pub total_cryptocurrencies: i32,
pub active_market_pairs: i32,
pub active_exchanges: i32,
pub total_exchanges: i32,
pub eth_dominance: f64,
pub btc_dominance: f64,
pub eth_dominance_yesterday: Option<f64>,
pub btc_dominance_yesterday: Option<f64>,
pub defi_volume_24h_reported: Option<f64>,
pub stablecoin_volume_24h_reported: Option<f64>,
pub der_volume_24h_reported: Option<f64>,
pub quote: HashMap<String, GlobalQuote>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GlobalMetricsQuotesLatestResponse {
pub status: Status,
pub data: GlobalMetricsQuotesLatestData,
}
#[derive(Debug, Clone, Default)]
pub struct GetGlobalMetricsQuotesLatestRequest {
pub convert: Option<String>,
pub convert_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FearAndGreed {
pub value: f64,
pub value_classification: String,
#[serde(alias = "timestamp", alias = "update_time")]
pub update_time: String,
#[serde(default)]
pub time_until_update: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FearAndGreedResponse {
pub status: Status,
pub data: FearAndGreed,
}
#[derive(Debug, Clone, Default)]
pub struct GetFearAndGreedLatestRequest {}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlanInfo {
#[serde(default)]
pub credit_limit_daily: Option<i64>,
#[serde(default)]
pub credit_limit_daily_reset: Option<String>,
#[serde(default)]
pub credit_limit_monthly: Option<i64>,
#[serde(default)]
pub credit_limit_monthly_reset: Option<String>,
#[serde(default)]
pub credit_limit_monthly_reset_timestamp: Option<String>,
#[serde(default)]
pub rate_limit_minute: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UsageDetails {
#[serde(default)]
pub credits_used: Option<i64>,
#[serde(default)]
pub credits_left: Option<i64>,
#[serde(default)]
pub requests_made: Option<i32>,
#[serde(default)]
pub requests_left: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UsageInfo {
#[serde(default)]
pub current_minute: Option<UsageDetails>,
#[serde(default)]
pub current_day: Option<UsageDetails>,
#[serde(default)]
pub current_month: Option<UsageDetails>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KeyInfoData {
pub plan: PlanInfo,
pub usage: UsageInfo,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KeyInfoResponse {
pub status: Status,
pub data: KeyInfoData,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CryptocurrencyMapItem {
pub id: i32,
pub rank: Option<i32>,
pub name: String,
pub symbol: String,
pub slug: String,
pub is_active: i32,
#[serde(default)]
pub first_historical_data: Option<String>,
#[serde(default)]
pub last_historical_data: Option<String>,
#[serde(default)]
pub platform: Option<Platform>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CryptocurrencyMapResponse {
pub status: Status,
pub data: Vec<CryptocurrencyMapItem>,
}
#[derive(Debug, Clone, Default)]
pub struct GetCryptocurrencyMapRequest {
pub listing_status: Option<String>,
pub start: Option<i32>,
pub limit: Option<i32>,
pub sort: Option<String>,
pub symbol: Option<String>,
pub aux: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct CryptocurrencyUrls {
#[serde(default)]
pub website: Vec<String>,
#[serde(default)]
pub twitter: Vec<String>,
#[serde(default)]
pub message_board: Vec<String>,
#[serde(default)]
pub chat: Vec<String>,
#[serde(default)]
pub facebook: Vec<String>,
#[serde(default)]
pub explorer: Vec<String>,
#[serde(default)]
pub reddit: Vec<String>,
#[serde(default)]
pub technical_doc: Vec<String>,
#[serde(default)]
pub source_code: Vec<String>,
#[serde(default)]
pub announcement: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CryptocurrencyInfo {
pub id: i32,
pub name: String,
pub symbol: String,
pub slug: String,
#[serde(default)]
pub category: Option<String>,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub logo: Option<String>,
#[serde(default)]
pub subreddit: Option<String>,
#[serde(default)]
pub notice: Option<String>,
#[serde(default)]
pub tags: Option<Vec<String>>,
#[serde(default)]
pub platform: Option<Platform>,
#[serde(default)]
pub date_added: Option<String>,
#[serde(default)]
pub date_launched: Option<String>,
#[serde(default)]
pub urls: Option<CryptocurrencyUrls>,
#[serde(default)]
pub is_hidden: Option<i32>,
#[serde(default)]
pub infinite_supply: Option<bool>,
#[serde(default)]
pub self_reported_circulating_supply: Option<f64>,
#[serde(default)]
pub self_reported_market_cap: Option<f64>,
#[serde(default)]
pub self_reported_tags: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CryptocurrencyInfoResponse {
pub status: Status,
pub data: HashMap<String, CryptocurrencyInfo>,
}
#[derive(Debug, Clone, Default)]
pub struct GetCryptocurrencyInfoRequest {
pub id: Option<String>,
pub slug: Option<String>,
pub symbol: Option<String>,
pub address: Option<String>,
pub aux: Option<String>,
pub skip_invalid: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QuotesTag {
pub slug: String,
pub name: String,
pub category: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QuotesCryptocurrency {
pub id: i32,
pub name: String,
pub symbol: String,
pub slug: String,
pub num_market_pairs: Option<i32>,
pub date_added: Option<String>,
#[serde(default)]
pub tags: Option<Vec<QuotesTag>>,
pub max_supply: Option<f64>,
pub circulating_supply: Option<f64>,
pub total_supply: Option<f64>,
pub infinite_supply: Option<bool>,
pub platform: Option<Platform>,
pub cmc_rank: Option<i32>,
pub self_reported_circulating_supply: Option<f64>,
pub self_reported_market_cap: Option<f64>,
pub tvl_ratio: Option<f64>,
pub last_updated: String,
pub quote: HashMap<String, Quote>,
#[serde(default)]
pub is_active: Option<i32>,
#[serde(default)]
pub is_fiat: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QuotesLatestResponse {
pub status: Status,
pub data: HashMap<String, Vec<QuotesCryptocurrency>>,
}
#[derive(Debug, Clone, Default)]
pub struct GetQuotesLatestRequest {
pub id: Option<String>,
pub slug: Option<String>,
pub symbol: Option<String>,
pub convert: Option<String>,
pub convert_id: Option<String>,
pub aux: Option<String>,
pub skip_invalid: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FiatMapItem {
pub id: i32,
pub name: String,
pub sign: String,
pub symbol: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FiatMapResponse {
pub status: Status,
pub data: Vec<FiatMapItem>,
}
#[derive(Debug, Clone, Default)]
pub struct GetFiatMapRequest {
pub start: Option<i32>,
pub limit: Option<i32>,
pub sort: Option<String>,
pub include_metals: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConversionQuote {
pub price: f64,
pub last_updated: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PriceConversionData {
pub id: i32,
pub symbol: String,
pub name: String,
pub amount: f64,
pub last_updated: String,
pub quote: HashMap<String, ConversionQuote>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PriceConversionResponse {
pub status: Status,
pub data: PriceConversionData,
}
#[derive(Debug, Clone, Default)]
pub struct PriceConversionRequest {
pub amount: f64,
pub id: Option<i32>,
pub symbol: Option<String>,
pub convert: Option<String>,
pub convert_id: Option<String>,
pub time: Option<String>,
}