Skip to content

Commit ef33a2f

Browse files
committed
feat: Add early validation for configuration and keypair in main function
1 parent 3f6506a commit ef33a2f

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

src/main.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ mod test;
3838

3939
use crate::solana_program::{
4040
compose_transaction, find_build_params_pda, get_all_pdas_available, get_program_pda,
41-
process_close, resolve_rpc_url, upload_program_verification_data, InputParams,
42-
OtterBuildParams, OtterVerifyInstructions,
41+
process_close, resolve_rpc_url, upload_program_verification_data, validate_config_and_keypair,
42+
InputParams, OtterBuildParams, OtterVerifyInstructions,
4343
};
4444

4545
const MAINNET_GENESIS_HASH: &str = "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d";
@@ -352,9 +352,21 @@ async fn main() -> anyhow::Result<()> {
352352
)
353353
.get_matches();
354354

355+
// Validate configuration early if custom config is provided
356+
let config_path = matches.value_of("config").map(|s| s.to_string());
357+
if config_path.is_some() {
358+
// Check if verify-from-repo subcommand has a keypair parameter
359+
let keypair_path = if let ("verify-from-repo", Some(sub_m)) = matches.subcommand() {
360+
sub_m.value_of("keypair").map(|s| s.to_string())
361+
} else {
362+
None
363+
};
364+
validate_config_and_keypair(config_path.as_deref(), keypair_path.as_deref())?;
365+
}
366+
355367
let connection = resolve_rpc_url(
356368
matches.value_of("url").map(|s| s.to_string()),
357-
matches.value_of("config").map(|s| s.to_string()),
369+
config_path.clone(),
358370
)?;
359371
let res = match matches.subcommand() {
360372
("build", Some(sub_m)) => {
@@ -385,7 +397,7 @@ async fn main() -> anyhow::Result<()> {
385397
executable_path.to_string(),
386398
image.to_string(),
387399
matches.value_of("url").map(|s| s.to_string()),
388-
matches.value_of("config").map(|s| s.to_string()),
400+
config_path.clone(),
389401
Pubkey::try_from(program_id)?,
390402
current_dir,
391403
&mut temp_dir,
@@ -458,7 +470,7 @@ async fn main() -> anyhow::Result<()> {
458470
&mut container_id,
459471
&mut temp_dir,
460472
&check_signal,
461-
matches.value_of("config").map(|s| s.to_string()),
473+
config_path.clone(),
462474
)
463475
.await
464476
}
@@ -473,7 +485,7 @@ async fn main() -> anyhow::Result<()> {
473485
Pubkey::try_from(program_id)?,
474486
&connection,
475487
compute_unit_price,
476-
matches.value_of("config").map(|s| s.to_string()),
488+
config_path.clone(),
477489
)
478490
.await
479491
}
@@ -510,7 +522,7 @@ async fn main() -> anyhow::Result<()> {
510522

511523
let connection = resolve_rpc_url(
512524
matches.value_of("url").map(|s| s.to_string()),
513-
matches.value_of("config").map(|s| s.to_string()),
525+
config_path.clone(),
514526
)?;
515527
println!("Using connection url: {}", connection.url());
516528

@@ -542,7 +554,7 @@ async fn main() -> anyhow::Result<()> {
542554
Pubkey::try_from(program_id)?,
543555
signer,
544556
&connection,
545-
matches.value_of("config").map(|s| s.to_string()),
557+
config_path.clone(),
546558
)
547559
.await
548560
}

src/solana_program.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,13 @@ fn get_keypair_from_path(path: &str) -> anyhow::Result<Keypair> {
100100

101101
fn get_user_config_with_path(config_path: Option<String>) -> anyhow::Result<(Keypair, RpcClient)> {
102102
let cli_config: Config = match config_path {
103-
Some(config_file) => Config::load(&config_file).map_err(|err| anyhow!("Failed to load Solana CLI configuration file '{}'.\nError: {}", config_file, err))?,
103+
Some(config_file) => Config::load(&config_file).map_err(|err| {
104+
anyhow!(
105+
"Failed to load Solana CLI configuration file '{}'.\nError: {}",
106+
config_file,
107+
err
108+
)
109+
})?,
104110
None => {
105111
let config_file = solana_cli_config::CONFIG_FILE
106112
.as_ref()
@@ -115,6 +121,35 @@ fn get_user_config_with_path(config_path: Option<String>) -> anyhow::Result<(Key
115121
Ok((signer, rpc_client))
116122
}
117123

124+
/// Validates configuration and keypair early to avoid late failures
125+
pub fn validate_config_and_keypair(
126+
config_path: Option<&str>,
127+
path_to_keypair: Option<&str>,
128+
) -> anyhow::Result<()> {
129+
// Validate the config file if provided
130+
if let Some(config_file) = config_path {
131+
let cli_config = Config::load(config_file).map_err(|err| {
132+
anyhow!(
133+
"Failed to load Solana CLI configuration file '{}'.\nError: {}",
134+
config_file,
135+
err
136+
)
137+
})?;
138+
139+
// If no explicit keypair path provided, validate the one from config
140+
if path_to_keypair.is_none() {
141+
let _ = get_keypair_from_path(&cli_config.keypair_path)?;
142+
}
143+
}
144+
145+
// Validate the explicit keypair path if provided
146+
if let Some(keypair_path) = path_to_keypair {
147+
let _ = get_keypair_from_path(keypair_path)?;
148+
}
149+
150+
Ok(())
151+
}
152+
118153
pub fn compose_transaction(
119154
params: &InputParams,
120155
signer_pubkey: Pubkey,

0 commit comments

Comments
 (0)