use anyhow::Result;
use clap::{Parser, Subcommand, ValueEnum};
use crate::client::{build_client, get_json};
use crate::config::canonical_base_url;
use crate::output::print_json;
#[derive(Debug, Parser)]
pub struct SymbolsCmd {
#[command(subcommand)]
sub: SymbolsSub,
}
#[derive(Debug, Subcommand)]
enum SymbolsSub {
List {
#[arg(long)]
asset: Option<AssetClass>,
#[arg(long, short)]
q: Option<String>,
},
}
#[derive(Debug, Clone, Copy, ValueEnum)]
enum AssetClass {
Crypto,
Fx,
}
impl SymbolsCmd {
pub async fn run(self, api_url: &str, pretty: bool) -> Result<()> {
let base = canonical_base_url(api_url);
match self.sub {
SymbolsSub::List { asset, q } => run_list(&base, asset, q.as_deref(), pretty).await,
}
}
}
async fn run_list(
base: &str,
asset: Option<AssetClass>,
q: Option<&str>,
pretty: bool,
) -> Result<()> {
let (client, token) = build_client()?;
let mut params: Vec<(&str, String)> = Vec::new();
if let Some(a) = asset {
let s = match a {
AssetClass::Crypto => "crypto",
AssetClass::Fx => "fx",
};
params.push(("asset", s.to_string()));
}
if let Some(q) = q {
params.push(("q", q.to_string()));
}
let url = format!("{base}/v1/symbols");
let rb = client.get(&url).bearer_auth(&token).query(¶ms);
let json = get_json(rb).await?;
print_json(&json, pretty)
}
#[cfg(test)]
mod tests {
use super::*;
use clap::Parser;
#[test]
fn parse_symbols_list_no_filter() {
let cmd = SymbolsCmd::try_parse_from(["symbols", "list"]).unwrap();
assert!(matches!(
cmd.sub,
SymbolsSub::List {
asset: None,
q: None
}
));
}
#[test]
fn parse_symbols_list_crypto() {
let cmd = SymbolsCmd::try_parse_from(["symbols", "list", "--asset", "crypto"]).unwrap();
assert!(matches!(
cmd.sub,
SymbolsSub::List {
asset: Some(AssetClass::Crypto),
..
}
));
}
#[test]
fn parse_symbols_list_fx_with_query() {
let cmd =
SymbolsCmd::try_parse_from(["symbols", "list", "--asset", "fx", "--q", "EUR"]).unwrap();
assert!(matches!(
cmd.sub,
SymbolsSub::List {
asset: Some(AssetClass::Fx),
q: Some(_),
}
));
}
}