diff --git a/core/lib/zksync_core/src/dev_api_conversion_rate/mod.rs b/core/lib/zksync_core/src/dev_api_conversion_rate/mod.rs new file mode 100644 index 000000000000..e095c97fe62c --- /dev/null +++ b/core/lib/zksync_core/src/dev_api_conversion_rate/mod.rs @@ -0,0 +1,35 @@ +use axum::{extract, extract::Json, routing::get, Router}; +use tokio::sync::watch; +use zksync_config::configs::native_token_fetcher::NativeTokenFetcherConfig; + +pub(crate) async fn run_server( + mut stop_receiver: watch::Receiver, + server_configs: &NativeTokenFetcherConfig, +) -> anyhow::Result<()> { + let app = Router::new().route("/conversion_rate/:token_address", get(get_conversion_rate)); + + let bind_address = if server_configs.host.starts_with("http://") { + &server_configs.host[7..] // If it starts with "http://", strip the prefix + } else { + &server_configs.host // Otherwise, return the original string + }; + + axum::Server::bind(&bind_address.parse().expect("Unable to parse socket address")) + .serve(app.into_make_service()) + .with_graceful_shutdown(async move { + if stop_receiver.changed().await.is_err() { + tracing::warn!("Stop signal sender for conversion rate API server was dropped without sending a signal"); + } + tracing::info!("Stop signal received, conversion rate server is shutting down"); + }) + .await + .expect("Conversion rate server failed"); + tracing::info!("Conversion rate server shut down"); + Ok(()) +} + +// basic handler that responds with a static string +async fn get_conversion_rate(extract::Path(_token_address): extract::Path) -> Json { + tracing::info!("Received request for conversion rate"); + Json(42) +} diff --git a/core/lib/zksync_core/src/lib.rs b/core/lib/zksync_core/src/lib.rs index 130d36956473..2f68d633cf5c 100644 --- a/core/lib/zksync_core/src/lib.rs +++ b/core/lib/zksync_core/src/lib.rs @@ -79,6 +79,7 @@ pub mod basic_witness_input_producer; pub mod block_reverter; pub mod consensus; pub mod consistency_checker; +pub mod dev_api_conversion_rate; pub mod eth_sender; pub mod eth_watch; mod fee_model; @@ -233,6 +234,8 @@ pub enum Component { ProofDataHandler, /// Native Token fetcher NativeTokenFetcher, + /// Conversion rate API, for local development. + DevConversionRateApi, } #[derive(Debug)] @@ -268,6 +271,7 @@ impl FromStr for Components { "eth_tx_manager" => Ok(Components(vec![Component::EthTxManager])), "proof_data_handler" => Ok(Components(vec![Component::ProofDataHandler])), "native_token_fetcher" => Ok(Components(vec![Component::NativeTokenFetcher])), + "dev_conversion_rate_api" => Ok(Components(vec![Component::DevConversionRateApi])), other => Err(format!("{} is not a valid component name", other)), } } @@ -323,7 +327,24 @@ pub async fn initialize_components( circuit_breaker_checker.check().await.unwrap_or_else(|err| { panic!("Circuit breaker triggered: {}", err); }); + + let mut task_futures: Vec>> = Vec::new(); let (stop_sender, stop_receiver) = watch::channel(false); + + // spawn the conversion rate API if it is enabled + if components.contains(&Component::DevConversionRateApi) { + let native_token_fetcher_config = configs + .native_token_fetcher_config + .clone() + .context("native_token_fetcher_config")?; + + let stop_receiver = stop_receiver.clone(); + let conversion_rate_task = tokio::spawn(async move { + dev_api_conversion_rate::run_server(stop_receiver, &native_token_fetcher_config).await + }); + task_futures.push(conversion_rate_task); + }; + let (cb_sender, cb_receiver) = oneshot::channel(); let native_token_fetcher = if components.contains(&Component::NativeTokenFetcher) { @@ -366,10 +387,10 @@ pub async fn initialize_components( res }); - let mut task_futures: Vec>> = vec![ + task_futures.extend(vec![ prometheus_task, tokio::spawn(circuit_breaker_checker.run(cb_sender, stop_receiver.clone())), - ]; + ]); if components.contains(&Component::WsApi) || components.contains(&Component::HttpApi) diff --git a/erc20_example.py b/erc20_example.py deleted file mode 100644 index 70828545b1f9..000000000000 --- a/erc20_example.py +++ /dev/null @@ -1,8 +0,0 @@ -from flask import Flask -from random import randint - -app = Flask(__name__) - -@app.route("/conversion_rate/") -def conversion_rate(token_address): - return str(randint(1, 100))