tycho_simulation/evm/engine_db/
utils.rs

1use std::{env, sync::Arc};
2
3use alloy::providers::ProviderBuilder;
4use dotenv::dotenv;
5use tokio::runtime::Runtime;
6use tycho_common::simulation::errors::SimulationError;
7
8use crate::evm::engine_db::simulation_db::EVMProvider;
9
10pub fn get_runtime() -> Result<Option<Arc<Runtime>>, SimulationError> {
11    if tokio::runtime::Handle::try_current().is_ok() {
12        Err(SimulationError::FatalError(
13            "A Tokio runtime is already running in this context".to_string(),
14        ))?;
15    }
16
17    Runtime::new()
18        .map(|runtime| Some(Arc::new(runtime)))
19        .map_err(|err| {
20            SimulationError::FatalError(format!("Failed to create Tokio runtime: {err}"))
21        })
22}
23
24pub fn get_client(rpc_url: Option<String>) -> Result<Arc<EVMProvider>, SimulationError> {
25    let runtime = get_runtime()?.ok_or(SimulationError::FatalError(
26        "A Tokio runtime is required to create the EVM client".to_string(),
27    ))?;
28
29    let url = match rpc_url {
30        Some(r) => r,
31        None => match env::var("RPC_URL") {
32            Ok(v) => v,
33            Err(_) => {
34                dotenv().map_err(|e| {
35                    SimulationError::FatalError(format!("Failed to load .env file: {e}"))
36                })?;
37                env::var("RPC_URL").map_err(|_| {
38                    SimulationError::InvalidInput(
39                        "RPC_URL environment variable is required when no RPC URL is provided"
40                            .to_string(),
41                        None,
42                    )
43                })?
44            }
45        },
46    };
47
48    let connect_future = async {
49        ProviderBuilder::new()
50            .connect(&url)
51            .await
52            .map_err(|err| {
53                SimulationError::RecoverableError(format!(
54                    "Failed to connect to RPC `{url}`: {err}"
55                ))
56            })
57    };
58
59    let client = runtime.block_on(connect_future)?;
60
61    Ok(Arc::new(client))
62}