zcash-sync/src/prices.rs

53 lines
2.0 KiB
Rust
Raw Normal View History

2021-08-09 07:13:10 -07:00
use chrono::NaiveDateTime;
use std::collections::HashMap;
2021-08-13 02:25:41 -07:00
use crate::TICKER;
2021-08-09 07:13:10 -07:00
const DAY_SEC: i64 = 24*3600;
pub async fn retrieve_historical_prices(timestamps: &[i64], currency: &str) -> anyhow::Result<Vec<(i64, f64)>> {
if timestamps.is_empty() { return Ok(Vec::new()); }
let mut timestamps_map: HashMap<i64, Option<f64>> = HashMap::new();
for ts in timestamps {
timestamps_map.insert(*ts, None);
}
let client = reqwest::Client::new();
let start = timestamps.first().unwrap();
let end = timestamps.last().unwrap() + DAY_SEC;
2021-08-13 02:25:41 -07:00
let url = format!("https://api.coingecko.com/api/v3/coins/{}/market_chart/range", TICKER);
2021-08-09 07:13:10 -07:00
let params = [("from", start.to_string()), ("to", end.to_string()), ("vs_currency", currency.to_string())];
let req = client.get(url).query(&params);
let res = req.send().await?;
let r: serde_json::Value = res.json().await?;
let prices = r["prices"].as_array().unwrap();
for p in prices.iter() {
let p = p.as_array().unwrap();
let ts = p[0].as_i64().unwrap() / 1000;
let px = p[1].as_f64().unwrap();
// rounded to daily
let date = NaiveDateTime::from_timestamp(ts, 0).date().and_hms(0, 0, 0);
let ts = date.timestamp();
if let Some(None) = timestamps_map.get(&ts) {
timestamps_map.insert(ts, Some(px));
}
}
let prices: Vec<_> = timestamps_map.iter().map(|(k, v)| {
(*k, v.expect(&format!("missing price for ts {}", *k)))
}).collect();
Ok(prices)
}
#[cfg(test)]
mod tests {
use crate::DbAdapter;
use crate::db::DEFAULT_DB_PATH;
use crate::prices::retrieve_historical_prices;
#[tokio::test]
async fn test() {
let currency = "EUR";
let mut db = DbAdapter::new(DEFAULT_DB_PATH).unwrap();
let ts = db.get_missing_prices_timestamp("USD").unwrap();
let prices = retrieve_historical_prices(&ts, currency).await.unwrap();
db.store_historical_prices(prices, currency).unwrap();
}
}