Skip to content

Commit

Permalink
feat(ticker): modifies dev ticker to proxy to coingecko
Browse files Browse the repository at this point in the history
  • Loading branch information
jurajpiar committed Sep 15, 2023
1 parent a3fdb5c commit e0c8c1b
Showing 1 changed file with 84 additions and 8 deletions.
92 changes: 84 additions & 8 deletions core/bin/zksync_api/src/bin/providers/dev_price_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
//! Implements coinmarketcap API for tokens deployed using `deploy-dev-erc20`
//! Prices are randomly distributed around base values estimated from real world prices.
use actix_web::{web, HttpRequest, HttpResponse, Result};
use actix_web::{web, HttpRequest, HttpResponse, Result, Scope};
use bigdecimal::BigDecimal;
use chrono::{SecondsFormat, Utc};
use jsonrpc_ws_server::ws::Handler;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use serde_json::json;
use serde_json::{json, Value};
use std::sync::{Arc, Mutex};
use std::time::Instant;
use std::{collections::HashMap, fs::read_to_string, path::Path};
use std::{convert::TryFrom, time::Duration};
use zksync_crypto::rand::{thread_rng, Rng};
Expand All @@ -18,6 +22,77 @@ struct CoinMarketCapTokenQuery {
symbol: String,
}

struct Cache<T> {
data: T,
last_fetched: Instant,
}

#[derive(Clone)]
struct ProxyState {
cache: Arc<Mutex<HashMap<String, Cache<Value>>>>,
}

async fn fetch_coins_list(data: web::Data<ProxyState>, path: web::Path<(bool,)>) -> HttpResponse {
let include_platform = path.0.clone();
let url = format!(
"https://api.coingecko.com/api/v3/coins/list?include_platform={}",
include_platform
);
proxy_request(&url, &data.cache).await
}

async fn fetch_market_chart(
data: web::Data<ProxyState>,
path: web::Path<(String,)>,
) -> HttpResponse {
let coin = path.0.clone();
let url = format!(
"https://api.coingecko.com/api/v3/coins/{}/market_chart",
coin
);
proxy_request(&url, &data.cache).await
}

async fn fetch_coin_market_cap(data: web::Data<ProxyState>) -> HttpResponse {
proxy_request(
"https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest",
&data.cache,
)
.await
}

async fn proxy_request(url: &str, cache: &Mutex<HashMap<String, Cache<Value>>>) -> HttpResponse {
let mut lock = cache.lock().unwrap();

// Check cache first
if let Some(cached) = lock.get(url) {
if cached.last_fetched.elapsed() < Duration::from_secs(5) {
// TODO: configure timeout (or use existing one)
return HttpResponse::Ok().json(&cached.data);
}
}

// Fetch data if not in cache or stale
let client = Client::new();
match client.get(url).send().await {
Ok(response) => match response.json::<Value>().await {
Ok(data) => {
// Cache the fetched data
lock.insert(
url.to_string(),
Cache {
data: data.clone(),
last_fetched: Instant::now(),
},
);
HttpResponse::Ok().json(data)
}
Err(_) => HttpResponse::InternalServerError().finish(),
},
Err(_) => HttpResponse::InternalServerError().finish(),
}
}

macro_rules! make_sloppy {
($f: ident) => {{
|query, data| async {
Expand Down Expand Up @@ -176,6 +251,9 @@ pub fn create_price_service(sloppy_mode: bool) -> actix_web::Scope {
.into_iter()
.chain(testnet_tokens.into_iter())
.collect();

// When sloppy mode is enabled, we are more tolerant of errors and we use
// a fake API that returns random prices. This is useful for testing.
if sloppy_mode {
web::scope("")
.app_data(web::Data::new(data))
Expand All @@ -192,19 +270,17 @@ pub fn create_price_service(sloppy_mode: bool) -> actix_web::Scope {
web::get().to(make_sloppy!(handle_coingecko_token_price_query)),
)
} else {
// TODO: allow non-sloppy mode for dev env (ei move the proxy to its own service)
web::scope("")
.app_data(web::Data::new(data))
.route(
"/cryptocurrency/quotes/latest",
web::get().to(handle_coinmarketcap_token_price_query),
)
.route(
"/api/v3/coins/list",
web::get().to(handle_coingecko_token_list),
web::get().to(fetch_coin_market_cap),
)
.route("/api/v3/coins/list", web::get().to(fetch_coins_list))
.route(
"/api/v3/coins/{coin_id}/market_chart",
web::get().to(handle_coingecko_token_price_query),
web::get().to(fetch_market_chart),
)
}
}

0 comments on commit e0c8c1b

Please sign in to comment.