use crate::cli::common::write_json_output;
use clap::{Args, Subcommand};
use polymarket_hft::client::coinmarketcap::{
Client, GetCryptocurrencyInfoRequest, GetCryptocurrencyMapRequest,
GetFearAndGreedLatestRequest, GetFiatMapRequest, GetGlobalMetricsQuotesLatestRequest,
GetListingsLatestRequest, GetQuotesLatestRequest, PriceConversionRequest,
};
#[allow(clippy::enum_variant_names)] #[derive(Subcommand)]
pub enum CmcCommands {
GetListings {
#[command(flatten)]
params: GetListingsArgs,
},
GetGlobalMetrics {
#[arg(short, long)]
convert: Option<String>,
},
GetFearAndGreed,
GetKeyInfo,
GetMap {
#[command(flatten)]
params: GetMapArgs,
},
GetInfo {
#[command(flatten)]
params: GetInfoArgs,
},
GetQuotes {
#[command(flatten)]
params: GetQuotesArgs,
},
GetFiatMap {
#[command(flatten)]
params: GetFiatMapArgs,
},
PriceConvert {
#[command(flatten)]
params: PriceConvertArgs,
},
}
#[derive(Args, Debug, Clone)]
pub struct GetListingsArgs {
#[arg(short, long, default_value_t = 10)]
pub limit: i32,
#[arg(long)]
pub start: Option<i32>,
#[arg(long)]
pub price_min: Option<f64>,
#[arg(long)]
pub price_max: Option<f64>,
#[arg(long)]
pub market_cap_min: Option<f64>,
#[arg(long)]
pub market_cap_max: Option<f64>,
#[arg(short, long)]
pub convert: Option<String>,
#[arg(long)]
pub sort: Option<String>,
#[arg(long)]
pub sort_dir: Option<String>,
#[arg(long)]
pub cryptocurrency_type: Option<String>,
#[arg(long)]
pub tag: Option<String>,
}
#[derive(Args, Debug, Clone)]
pub struct GetMapArgs {
#[arg(short, long, default_value_t = 100)]
pub limit: i32,
#[arg(long)]
pub start: Option<i32>,
#[arg(long)]
pub listing_status: Option<String>,
#[arg(short, long)]
pub symbol: Option<String>,
#[arg(long)]
pub sort: Option<String>,
}
#[derive(Args, Debug, Clone)]
pub struct GetInfoArgs {
#[arg(long)]
pub id: Option<String>,
#[arg(long)]
pub slug: Option<String>,
#[arg(short, long)]
pub symbol: Option<String>,
#[arg(long)]
pub skip_invalid: bool,
}
#[derive(Args, Debug, Clone)]
pub struct GetQuotesArgs {
#[arg(long)]
pub id: Option<String>,
#[arg(long)]
pub slug: Option<String>,
#[arg(short, long)]
pub symbol: Option<String>,
#[arg(short, long)]
pub convert: Option<String>,
#[arg(long)]
pub skip_invalid: bool,
}
#[derive(Args, Debug, Clone)]
pub struct GetFiatMapArgs {
#[arg(short, long, default_value_t = 100)]
pub limit: i32,
#[arg(long)]
pub start: Option<i32>,
#[arg(long)]
pub sort: Option<String>,
#[arg(long)]
pub include_metals: bool,
}
#[derive(Args, Debug, Clone)]
pub struct PriceConvertArgs {
#[arg(short, long)]
pub amount: f64,
#[arg(long)]
pub id: Option<i32>,
#[arg(short, long)]
pub symbol: Option<String>,
#[arg(short, long, default_value = "USD")]
pub convert: String,
}
fn get_api_key() -> anyhow::Result<String> {
std::env::var("CMC_API_KEY").map_err(|_| {
anyhow::anyhow!(
"CMC_API_KEY environment variable not set.\n\
Get a free API key at: https://coinmarketcap.com/api/"
)
})
}
pub async fn handle(command: &CmcCommands) -> anyhow::Result<()> {
let api_key = get_api_key()?;
let client = Client::new(api_key);
match command {
CmcCommands::GetListings { params } => {
let request = GetListingsLatestRequest {
start: params.start,
limit: Some(params.limit),
price_min: params.price_min,
price_max: params.price_max,
market_cap_min: params.market_cap_min,
market_cap_max: params.market_cap_max,
convert: params.convert.clone(),
sort: params.sort.clone(),
sort_dir: params.sort_dir.clone(),
cryptocurrency_type: params.cryptocurrency_type.clone(),
tag: params.tag.clone(),
..Default::default()
};
let response = client.get_listings_latest(request).await?;
write_json_output(&response)?;
}
CmcCommands::GetGlobalMetrics { convert } => {
let request = GetGlobalMetricsQuotesLatestRequest {
convert: convert.clone(),
..Default::default()
};
let response = client.get_global_metrics_quotes_latest(request).await?;
write_json_output(&response)?;
}
CmcCommands::GetFearAndGreed => {
let response = client
.get_fear_and_greed_latest(GetFearAndGreedLatestRequest::default())
.await?;
write_json_output(&response)?;
}
CmcCommands::GetKeyInfo => {
let response = client.get_key_info().await?;
write_json_output(&response)?;
}
CmcCommands::GetMap { params } => {
let request = GetCryptocurrencyMapRequest {
start: params.start,
limit: Some(params.limit),
listing_status: params.listing_status.clone(),
symbol: params.symbol.clone(),
sort: params.sort.clone(),
..Default::default()
};
let response = client.get_cryptocurrency_map(request).await?;
write_json_output(&response)?;
}
CmcCommands::GetInfo { params } => {
let request = GetCryptocurrencyInfoRequest {
id: params.id.clone(),
slug: params.slug.clone(),
symbol: params.symbol.clone(),
skip_invalid: if params.skip_invalid {
Some(true)
} else {
None
},
..Default::default()
};
let response = client.get_cryptocurrency_info(request).await?;
write_json_output(&response)?;
}
CmcCommands::GetQuotes { params } => {
let request = GetQuotesLatestRequest {
id: params.id.clone(),
slug: params.slug.clone(),
symbol: params.symbol.clone(),
convert: params.convert.clone(),
skip_invalid: if params.skip_invalid {
Some(true)
} else {
None
},
..Default::default()
};
let response = client.get_quotes_latest(request).await?;
write_json_output(&response)?;
}
CmcCommands::GetFiatMap { params } => {
let request = GetFiatMapRequest {
start: params.start,
limit: Some(params.limit),
sort: params.sort.clone(),
include_metals: if params.include_metals {
Some(true)
} else {
None
},
};
let response = client.get_fiat_map(request).await?;
write_json_output(&response)?;
}
CmcCommands::PriceConvert { params } => {
let request = PriceConversionRequest {
amount: params.amount,
id: params.id,
symbol: params.symbol.clone(),
convert: Some(params.convert.clone()),
..Default::default()
};
let response = client.get_price_conversion(request).await?;
write_json_output(&response)?;
}
}
Ok(())
}