1#![allow(dead_code)]
10
11use crate::common::{Address, Hash};
12use crate::{CustomNetwork, Network};
13use alloy::network::Ethereum;
14use alloy::providers::fillers::{
15 BlobGasFiller, ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller,
16 SimpleNonceManager,
17};
18use alloy::providers::{Identity, ProviderBuilder, RootProvider};
19use alloy::transports::http::reqwest;
20use std::env;
21
22const MAINNET_ID: u8 = 1;
23const ALPHANET_ID: u8 = 2;
24
25pub const RPC_URL: &str = "RPC_URL";
27const RPC_URL_BUILD_TIME_VAL: Option<&str> = option_env!("RPC_URL");
28pub const PAYMENT_TOKEN_ADDRESS: &str = "PAYMENT_TOKEN_ADDRESS";
29const PAYMENT_TOKEN_ADDRESS_BUILD_TIME_VAL: Option<&str> = option_env!("PAYMENT_TOKEN_ADDRESS");
30pub const DATA_PAYMENTS_ADDRESS: &str = "DATA_PAYMENTS_ADDRESS";
31const DATA_PAYMENTS_ADDRESS_BUILD_TIME_VAL: Option<&str> = option_env!("DATA_PAYMENTS_ADDRESS");
32pub const MERKLE_PAYMENTS_ADDRESS: &str = "MERKLE_PAYMENTS_ADDRESS";
33const MERKLE_PAYMENTS_ADDRESS_BUILD_TIME_VAL: Option<&str> = option_env!("MERKLE_PAYMENTS_ADDRESS");
34
35#[derive(thiserror::Error, Debug)]
36pub enum Error {
37 #[error("Failed to get EVM network: {0}")]
38 FailedToGetEvmNetwork(String),
39}
40
41pub fn dummy_address() -> Address {
43 use rand::Rng;
44 Address::new(rand::rngs::OsRng.r#gen())
45}
46
47pub fn dummy_hash() -> Hash {
49 use rand::Rng;
50 Hash::new(rand::rngs::OsRng.r#gen())
51}
52
53use std::sync::OnceLock;
54
55static EVM_NETWORK: OnceLock<Network> = OnceLock::new();
56
57pub fn get_evm_network(local: bool, network_id: Option<u8>) -> Result<Network, Error> {
70 if let Some(network) = EVM_NETWORK.get() {
71 return Ok(network.clone());
72 }
73
74 let res = match get_evm_network_from_env() {
75 Ok(evm_network) => Ok(evm_network),
76 Err(_) if local => Ok(local_evm_network_hardcoded()),
77 Err(_) => {
78 if let Some(id) = network_id {
79 match id {
80 MAINNET_ID => {
81 info!("Using Arbitrum One based on network ID {}", id);
82 Ok(Network::ArbitrumOne)
83 }
84 ALPHANET_ID => {
85 info!("Using Arbitrum Sepolia Test based on network ID {}", id);
86 Ok(Network::ArbitrumSepoliaTest)
87 }
88 _ => {
89 error!(
90 "Network ID {} requires EVM network configuration via environment variables",
91 id
92 );
93 Err(Error::FailedToGetEvmNetwork(format!(
94 "Network ID {id} requires EVM network to be configured via environment variables"
95 )))
96 }
97 }
98 } else {
99 error!("Failed to obtain the desired EVM network via any means");
100 Err(Error::FailedToGetEvmNetwork(
101 "Failed to obtain the desired EVM network via any means".to_string(),
102 ))
103 }
104 }
105 };
106
107 if let Ok(network) = res.as_ref() {
108 let _ = EVM_NETWORK.set(network.clone());
109 }
110
111 res
112}
113
114fn get_evm_network_from_env() -> Result<Network, Error> {
118 let evm_vars = [
119 env::var(RPC_URL)
120 .ok()
121 .or_else(|| RPC_URL_BUILD_TIME_VAL.map(|s| s.to_string())),
122 env::var(PAYMENT_TOKEN_ADDRESS)
123 .ok()
124 .or_else(|| PAYMENT_TOKEN_ADDRESS_BUILD_TIME_VAL.map(|s| s.to_string())),
125 env::var(DATA_PAYMENTS_ADDRESS)
126 .ok()
127 .or_else(|| DATA_PAYMENTS_ADDRESS_BUILD_TIME_VAL.map(|s| s.to_string())),
128 ]
129 .into_iter()
130 .map(|var| {
131 var.ok_or(Error::FailedToGetEvmNetwork(format!(
132 "missing env var, make sure to set all of: {RPC_URL}, {PAYMENT_TOKEN_ADDRESS}, {DATA_PAYMENTS_ADDRESS}"
133 )))
134 })
135 .collect::<Result<Vec<String>, Error>>();
136
137 let use_local_evm = std::env::var("EVM_NETWORK")
138 .map(|v| v == "local")
139 .unwrap_or(false);
140 if use_local_evm {
141 info!("Using local EVM network as EVM_NETWORK is set to 'local'");
142 }
143
144 let use_arbitrum_one = std::env::var("EVM_NETWORK")
145 .map(|v| v == "arbitrum-one")
146 .unwrap_or(false);
147
148 let use_arbitrum_sepolia_test = std::env::var("EVM_NETWORK")
149 .map(|v| v == "arbitrum-sepolia-test")
150 .unwrap_or(false);
151
152 if use_arbitrum_one {
153 info!("Using Arbitrum One EVM network as EVM_NETWORK is set to 'arbitrum-one'");
154 Ok(Network::ArbitrumOne)
155 } else if use_arbitrum_sepolia_test {
156 info!(
157 "Using Arbitrum Sepolia Test EVM network as EVM_NETWORK is set to 'arbitrum-sepolia-test'"
158 );
159 Ok(Network::ArbitrumSepoliaTest)
160 } else if let Ok(evm_vars) = evm_vars {
161 info!("Using custom EVM network from environment variables");
162 let merkle_addr = env::var(MERKLE_PAYMENTS_ADDRESS)
163 .ok()
164 .or_else(|| MERKLE_PAYMENTS_ADDRESS_BUILD_TIME_VAL.map(|s| s.to_string()));
165
166 let network = CustomNetwork::new(
167 &evm_vars[0],
168 &evm_vars[1],
169 &evm_vars[2],
170 merkle_addr.as_deref(),
171 );
172 Ok(Network::Custom(network))
173 } else if use_local_evm {
174 Ok(local_evm_network_hardcoded())
175 } else {
176 error!("Failed to obtain the desired EVM network through environment variables");
177 Err(Error::FailedToGetEvmNetwork(
178 "Failed to obtain the desired EVM network through environment variables".to_string(),
179 ))
180 }
181}
182
183fn local_evm_network_hardcoded() -> Network {
185 let network = CustomNetwork::new(
188 "http://localhost:61611",
189 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
190 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
191 Some("0x663F3ad617193148711d28f5334eE4Ed07016602"),
192 );
193 Network::Custom(network)
194}
195
196#[allow(clippy::type_complexity)]
197pub fn http_provider(
198 rpc_url: reqwest::Url,
199) -> FillProvider<
200 JoinFill<
201 JoinFill<
202 Identity,
203 JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>,
204 >,
205 NonceFiller<SimpleNonceManager>,
206 >,
207 RootProvider,
208 Ethereum,
209> {
210 ProviderBuilder::new()
211 .with_simple_nonce_management()
212 .connect_http(rpc_url)
213}