chore: ๐ง Switched to config based setup vs enviornment variables
c04cc33b
2 file(s) ยท +48 โ38
| 1 | 1 | [package] |
|
| 2 | - | name = "wallet-fetch" |
|
| 2 | + | name = "walletfetch" |
|
| 3 | 3 | version = "0.0.1" |
|
| 4 | 4 | edition = "2024" |
|
| 5 | 5 | ||
| 10 | 10 | serde_json = "1.0" |
|
| 11 | 11 | tokio = { version = "1.0", features = ["full"]} |
|
| 12 | 12 | futures = "0.3" |
|
| 13 | + | toml = "0.8" |
|
| 14 | + | dirs = "5.0" |
|
| 2 | 2 | use reqwest::Client; |
|
| 3 | 3 | use std::collections::HashMap; |
|
| 4 | 4 | use std::error::Error; |
|
| 5 | - | use std::env; |
|
| 6 | 5 | use serde::{Deserialize,Serialize}; |
|
| 7 | 6 | use futures::future::join_all; |
|
| 8 | 7 | use tokio::task::JoinHandle; |
|
| 8 | + | use toml; |
|
| 9 | + | use dirs; |
|
| 9 | 10 | ||
| 10 | 11 | #[derive(Serialize)] |
|
| 11 | 12 | struct JsonRpcRequest { |
|
| 23 | 24 | } |
|
| 24 | 25 | ||
| 25 | 26 | ||
| 26 | - | // #[derive(Deserialize)] |
|
| 27 | - | // struct Config { |
|
| 28 | - | // address: Option<String>, |
|
| 29 | - | // networks: Option<HashMap<String, NetworkConfig>>, |
|
| 30 | - | // } |
|
| 27 | + | #[derive(Deserialize)] |
|
| 28 | + | struct Config { |
|
| 29 | + | address: Option<String>, |
|
| 30 | + | networks: Option<HashMap<String, NetworkConfig>>, |
|
| 31 | + | } |
|
| 31 | 32 | ||
| 32 | - | // #[derive(Deserialize)] |
|
| 33 | - | // struct NetworkConfig { |
|
| 34 | - | // name: String, |
|
| 35 | - | // rpc_url: String, |
|
| 36 | - | // } |
|
| 33 | + | #[derive(Deserialize)] |
|
| 34 | + | struct NetworkConfig { |
|
| 35 | + | name: String, |
|
| 36 | + | rpc_url: String, |
|
| 37 | + | } |
|
| 37 | 38 | ||
| 38 | 39 | struct Network { |
|
| 39 | 40 | chain_id: u64, |
|
| 41 | 42 | rpc_url: String, |
|
| 42 | 43 | } |
|
| 43 | 44 | ||
| 44 | - | fn collect_rpc_urls() -> HashMap<u64, Network> { |
|
| 45 | - | let mut networks = HashMap::new(); |
|
| 45 | + | fn read_config() -> Result<Config, Box<dyn Error>> { |
|
| 46 | + | let home_dir = dirs::home_dir().ok_or("Could not find home directory")?; |
|
| 46 | 47 | ||
| 47 | - | for (key, value) in env::vars() { |
|
| 48 | - | if key.starts_with("RPC_URL_"){ |
|
| 49 | - | if let Some(chain_id_str) = key.strip_prefix("RPC_URL_"){ |
|
| 50 | - | if let Ok(chain_id) = chain_id_str.parse::<u64>(){ |
|
| 51 | - | let name = match chain_id { |
|
| 52 | - | 1 => "Ethereum Mainnet", |
|
| 53 | - | 8453 => "Base", |
|
| 54 | - | _ => "Uknown Network" |
|
| 55 | - | }; |
|
| 48 | + | let config_path = home_dir.join(".config").join("walletfetch").join("config.toml"); |
|
| 56 | 49 | ||
| 57 | - | networks.insert(chain_id, Network{ |
|
| 58 | - | chain_id: chain_id, |
|
| 59 | - | name: name.to_string(), |
|
| 60 | - | rpc_url: value, |
|
| 61 | - | }); |
|
| 62 | - | }; |
|
| 50 | + | if !config_path.exists(){ |
|
| 51 | + | return Err(format!("Config file not found at {}", config_path.display()).into()); |
|
| 52 | + | } |
|
| 53 | + | ||
| 54 | + | let config_content = std::fs::read_to_string(config_path)?; |
|
| 55 | + | let config: Config = toml::from_str(&config_content)?; |
|
| 56 | + | ||
| 57 | + | Ok(config) |
|
| 58 | + | } |
|
| 59 | + | ||
| 60 | + | fn collect_rpc_urls(config: &Config) -> HashMap<u64, Network> { |
|
| 61 | + | let mut networks = HashMap::new(); |
|
| 62 | + | ||
| 63 | + | if let Some(network_configs) = &config.networks { |
|
| 64 | + | for (chain_id_str, network_config) in network_configs { |
|
| 65 | + | if let Ok(chain_id) = chain_id_str.parse::<u64>(){ |
|
| 66 | + | networks.insert(chain_id, Network{ |
|
| 67 | + | chain_id, |
|
| 68 | + | name: network_config.name.clone(), |
|
| 69 | + | rpc_url: network_config.rpc_url.clone(), |
|
| 70 | + | }); |
|
| 63 | 71 | } |
|
| 64 | 72 | } |
|
| 65 | 73 | } |
|
| 156 | 164 | ) |
|
| 157 | 165 | .get_matches(); |
|
| 158 | 166 | ||
| 167 | + | let config = read_config()?; |
|
| 168 | + | ||
| 159 | 169 | let address = match matches.get_one::<String>("address"){ |
|
| 160 | 170 | Some(addr) if !addr.is_empty() => addr.to_string(), |
|
| 161 | - | _ => { |
|
| 162 | - | match env::var("WALLET_FETCH_ADDRESS") { |
|
| 163 | - | Ok(addr) if !addr.is_empty() => addr, |
|
| 164 | - | _ => { |
|
| 165 | - | eprintln!("Error: No Ethereum address provided. Either pass it as an argument or set the WALLET_FETCH_ADDRESS environment variable"); |
|
| 166 | - | return Err("No Ethereum address provided".into()); |
|
| 167 | - | } |
|
| 171 | + | _ => match &config.address { |
|
| 172 | + | Some(addr) if !addr.is_empty() => addr.clone(), |
|
| 173 | + | _ => { |
|
| 174 | + | eprintln!("Error: No address provided. Either passs it as an argument or set it in the config file"); |
|
| 175 | + | return Err("No address provided".into()); |
|
| 168 | 176 | } |
|
| 169 | - | } |
|
| 177 | + | }, |
|
| 170 | 178 | }; |
|
| 171 | 179 | ||
| 172 | - | let networks = collect_rpc_urls(); |
|
| 180 | + | let networks = collect_rpc_urls(&config); |
|
| 173 | 181 | ||
| 174 | 182 | if networks.is_empty(){ |
|
| 175 | 183 | eprintln!("RPC URLs are not defined"); |
|