#![warn(missing_docs)]
#![warn(unused_extern_crates)]
#![warn(unused_qualifications)]
mod client;
pub mod params;
pub mod response;
pub use crate::client::{CoinGeckoClient, COINGECKO_API_DEMO_URL};
#[cfg(test)]
mod tests {
use chrono::{self, Datelike};
use crate::{
params::{MarketsOrder, OhlcDays, PriceChangePercentage, TickersOrder},
CoinGeckoClient,
};
use chrono::NaiveDate;
macro_rules! aw {
($e:expr) => {
tokio_test::block_on($e)
};
}
#[test]
#[doc(hidden)]
fn ping() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let res = aw!(client.ping());
assert!(res.is_ok(), "ping should resolve");
assert_eq!(res.unwrap().gecko_says, "(V3) To the Moon!");
}
#[test]
fn price() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let res_1 = aw!(client.price(&["bitcoin"], &["usd"], true, true, true, true));
assert!(res_1.is_ok(), "price should resolve");
let price_1 = &res_1.unwrap()["bitcoin"];
assert!(price_1.usd.is_some(), "usd price should be defined");
assert!(
price_1.usd_market_cap.is_some(),
"usd price should be defined"
);
assert!(
price_1.usd24_h_vol.is_some(),
"usd 24h vol should be defined"
);
assert!(
price_1.usd24_h_change.is_some(),
"usd 24h change should be defined"
);
assert!(
price_1.last_updated_at.is_some(),
"usd last update should be defined"
);
let res_2 = aw!(client.price(&["ethereum"], &["eur"], true, true, true, true));
assert!(res_2.is_ok(), "price should resolve");
let price_2 = &res_2.unwrap()["ethereum"];
assert!(price_2.eur.is_some(), "eur price should be defined");
assert!(
price_2.eur_market_cap.is_some(),
"eur price should be defined"
);
assert!(
price_2.eur24_h_vol.is_some(),
"eur 24h vol should be defined"
);
assert!(
price_2.eur24_h_change.is_some(),
"eur 24h change should be defined"
);
assert!(
price_2.last_updated_at.is_some(),
"eur last update should be defined"
);
}
#[test]
fn token_price() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let uniswap_contract = "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984";
let res = aw!(client.token_price(
"ethereum",
&[uniswap_contract],
&["usd"],
true,
true,
true,
true
));
assert!(res.is_ok(), "token price should resolve");
let token_price = &res.unwrap()[&uniswap_contract.to_string()];
assert!(token_price.usd.is_some(), "usd price should be defined");
assert!(
token_price.usd_market_cap.is_some(),
"usd price should be defined"
);
assert!(
token_price.usd24_h_vol.is_some(),
"usd 24h vol should be defined"
);
assert!(
token_price.usd24_h_change.is_some(),
"usd 24h change should be defined"
);
assert!(
token_price.last_updated_at.is_some(),
"usd last update should be defined"
);
}
#[test]
fn supported_vs_currencies() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let res = aw!(client.supported_vs_currencies());
assert!(res.is_ok(), "supported_vs_currencies should resolve");
assert!(
!res.unwrap().is_empty(),
"should return at least one currency"
);
}
#[test]
fn coins_list() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let res = aw!(client.coins_list(true));
assert!(res.is_ok(), "list should resolve");
assert!(!res.unwrap().is_empty(), "should return at least one coin");
}
#[test]
fn coins_markets() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let res = aw!(client.coins_markets(
"usd",
&["bitcoin"],
None,
MarketsOrder::GeckoDesc,
1,
0,
true,
&[
PriceChangePercentage::OneHour,
PriceChangePercentage::TwentyFourHours,
PriceChangePercentage::SevenDays,
PriceChangePercentage::FourteenDays,
PriceChangePercentage::ThirtyDays,
PriceChangePercentage::OneYear
],
));
assert!(res.is_ok(), "markets should resolve");
let res2 = aw!(client.coins_markets(
"usd",
&[] as &[&str],
None,
MarketsOrder::MarketCapDesc,
250,
30,
false,
&[],
));
assert!(
res2.is_ok(),
"markets should resolve for pages near the end"
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn coin() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let res1 = client
.coin("01coin", false, false, false, false, false, false)
.await;
assert!(&res1.is_ok(), "coin should resolve");
assert_eq!(res1.unwrap().id, "01coin", "coin 01coin should resolve");
}
#[test]
fn coin_tickers() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let res1 = aw!(client.coin_tickers::<&str>(
"bitcoin",
None,
true,
1,
TickersOrder::VolumeDesc,
true
));
assert!(res1.is_ok(), "tickers without filter should resolve");
let res2 = aw!(client.coin_tickers(
"bitcoin",
#[allow(clippy::useless_vec)]
Some(&vec![String::from("binance")]), true,
1,
TickersOrder::VolumeDesc,
true
));
assert!(res2.is_ok(), "tickers without page should resolve");
let res3 = aw!(client.coin_tickers(
"bitcoin",
Some(&["binance"]),
true,
1,
TickersOrder::VolumeDesc,
true
));
assert!(res3.is_ok(), "tickers should resolve");
}
#[test]
fn coin_history() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let current_date = chrono::Utc::now();
let res = aw!(client.coin_history(
"bitcoin",
NaiveDate::from_ymd_opt(current_date.year(), 12, 30).unwrap(),
true
));
assert!(res.is_ok(), "history should resolve");
}
#[test]
fn coin_market_chart() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let res = aw!(client.coin_market_chart("bitcoin", "usd", 1, true));
assert!(res.is_ok(), "market chart should resolve");
}
#[test]
fn coin_market_chart_range() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let current_date = chrono::Utc::now();
let from = NaiveDate::from_ymd_opt(
current_date.year(),
current_date.month() - 1,
current_date.day(),
)
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap();
let to = NaiveDate::from_ymd_opt(
current_date.year(),
current_date.month(),
current_date.day(),
)
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap();
let res = aw!(client.coin_market_chart_range("bitcoin", "usd", from, to));
assert!(res.is_ok(), "market chart range should resolve");
}
#[test]
fn coin_ohlc() {
let client: CoinGeckoClient = CoinGeckoClient::default();
let res = aw!(client.coin_ohlc("bitcoin", "usd", OhlcDays::OneDay));
assert!(res.is_ok(), "ohlc should resolve");
}
}