chore: ๐Ÿ”ง Switched to config based setup vs enviornment variables c04cc33b
Steve Simkins ยท 2025-07-03 10:51 2 file(s) ยท +48 โˆ’38
Cargo.toml +3 โˆ’1
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"
src/main.rs +45 โˆ’37
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");