Skip to content

Commit a7ae1c3

Browse files
authored
Merge pull request #79 from ChiefWoods/feat/tuktuk-crank-turner
Add default config file, optional arguments for tuktuk-crank-turner
2 parents 6202c89 + 611d9d0 commit a7ae1c3

File tree

5 files changed

+116
-5
lines changed

5 files changed

+116
-5
lines changed

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tuktuk-crank-turner/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ lru = "0.13.0"
4242
lazy_static = "1.5.0"
4343
warp = "0.3.3"
4444
rand = "0.9"
45+
shellexpand = "3.1.1"
4546

4647
[features]
4748
default=[]

tuktuk-crank-turner/src/main.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub mod cache;
3232
mod metrics;
3333
pub mod profitability;
3434
pub mod settings;
35+
pub mod setup;
3536
mod sync;
3637
pub mod task_completion_processor;
3738
pub mod task_context;
@@ -46,8 +47,34 @@ pub struct Cli {
4647
/// Optional configuration file to use. If present the toml file at the
4748
/// given path will be loaded. Environment variables can override the
4849
/// settings in the given file.
49-
#[clap(short = 'c')]
50+
#[clap(
51+
short = 'c',
52+
long,
53+
default_value = "~/.config/helium/cli/tuktuk-crank-turner/config.toml"
54+
)]
5055
pub config: Option<path::PathBuf>,
56+
57+
/// RPC endpoint URL
58+
#[clap(short = 'u', long)]
59+
pub rpc_url: Option<String>,
60+
61+
/// Path to Solana keypair file
62+
#[clap(short = 'k', long)]
63+
pub key_path: Option<String>,
64+
65+
/// Minimum crank fee in lamports
66+
#[clap(short = 'm', long)]
67+
pub min_crank_fee: Option<u64>,
68+
}
69+
70+
impl Cli {
71+
fn get_expanded_config_path(&self) -> Option<path::PathBuf> {
72+
self.config.as_ref().map(|p| {
73+
shellexpand::full(&p.to_string_lossy())
74+
.map(|expanded| path::PathBuf::from(expanded.as_ref()))
75+
.unwrap_or_else(|_| p.clone())
76+
})
77+
}
5178
}
5279

5380
async fn metrics_handler() -> Result<impl Reply, Rejection> {
@@ -89,7 +116,19 @@ const PACKED_TX_CHANNEL_CAPACITY: usize = 32;
89116
impl Cli {
90117
pub async fn run(&self) -> Result<()> {
91118
register_custom_metrics();
92-
let settings = Settings::new(self.config.as_ref())?;
119+
let mut settings = Settings::new(self.get_expanded_config_path().as_ref())?;
120+
121+
// Apply CLI overrides
122+
if let Some(rpc_url) = &self.rpc_url {
123+
settings.rpc_url = rpc_url.clone();
124+
}
125+
if let Some(key_path) = &self.key_path {
126+
settings.key_path = key_path.clone();
127+
}
128+
if let Some(min_crank_fee) = self.min_crank_fee {
129+
settings.min_crank_fee = min_crank_fee;
130+
}
131+
93132
tracing_subscriber::registry()
94133
.with(tracing_subscriber::EnvFilter::new(&settings.log))
95134
.with(tracing_subscriber::fmt::layer().with_span_events(FmtSpan::CLOSE))
@@ -295,6 +334,9 @@ impl Cli {
295334

296335
#[tokio::main]
297336
async fn main() -> anyhow::Result<()> {
337+
// Create default config if it doesn't exist
338+
setup::create_config_if_missing()?;
339+
298340
let cli = Cli::parse();
299341
cli.run().await
300342
}

tuktuk-crank-turner/src/settings.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl Settings {
6565
/// Load Settings from a given path. Settings are loaded from a given
6666
/// optional path and can be overriden with environment variables.
6767
///
68-
/// Environemnt overrides have the same name as the entries in the settings
68+
/// Environment overrides have the same name as the entries in the settings
6969
/// file in uppercase and prefixed with "QN_". For example
7070
/// "QN_LOG" will override the log setting. A double underscore distinguishes
7171
/// subsections in the settings file
@@ -79,9 +79,16 @@ impl Settings {
7979
}
8080
// Add in settings from the environment (with a prefix of APP)
8181
// Eg.. `TUKTUK_DEBUG=1 ./target/app` would set the `debug` key
82-
builder
82+
let mut settings: Settings = builder
8383
.add_source(Environment::with_prefix("TUKTUK").separator("__"))
8484
.build()
85-
.and_then(|config| config.try_deserialize())
85+
.and_then(|config| config.try_deserialize())?;
86+
87+
// Expand environment variables in key_path (supports both $HOME and ~)
88+
settings.key_path = shellexpand::full(&settings.key_path)
89+
.map_err(|e| config::ConfigError::Message(format!("Failed to expand key_path: {}", e)))?
90+
.into_owned();
91+
92+
Ok(settings)
8693
}
8794
}

tuktuk-crank-turner/src/setup.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use anyhow::Result;
2+
use std::fs;
3+
use std::path::PathBuf;
4+
5+
const DEFAULT_CONFIG: &str = r#"# RPC endpoint URL
6+
rpc_url = "https://api.mainnet-beta.solana.com"
7+
8+
# Path to your Solana keypair file
9+
key_path = "~/.config/solana/id.json"
10+
11+
# Minimum crank fee in lamports
12+
min_crank_fee = 10000
13+
"#;
14+
15+
pub fn get_default_config_path() -> Option<PathBuf> {
16+
let home_dir = std::env::var("HOME")
17+
.or_else(|_| std::env::var("USERPROFILE"))
18+
.ok()?;
19+
20+
Some(
21+
PathBuf::from(home_dir)
22+
.join(".config")
23+
.join("helium")
24+
.join("cli")
25+
.join("tuktuk-crank-turner")
26+
.join("config.toml"),
27+
)
28+
}
29+
30+
fn write_default_config(config_path: &PathBuf) -> Result<()> {
31+
if let Some(parent) = config_path.parent() {
32+
fs::create_dir_all(parent)?;
33+
}
34+
35+
fs::write(config_path, DEFAULT_CONFIG)?;
36+
37+
Ok(())
38+
}
39+
40+
pub fn create_config_if_missing() -> Result<()> {
41+
let Some(config_path) = get_default_config_path() else {
42+
eprintln!("Warning: Could not determine home directory. Skipping config creation.");
43+
return Ok(());
44+
};
45+
46+
if !config_path.exists() {
47+
write_default_config(&config_path)?;
48+
}
49+
50+
Ok(())
51+
}

0 commit comments

Comments
 (0)