From 7a9be2dcd105a04f6e7c6d84196f651ca9384e0d Mon Sep 17 00:00:00 2001 From: Noah Gundotra Date: Wed, 20 Nov 2024 01:58:42 -0500 Subject: [PATCH] add subcommand to upload params --- src/main.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ src/solana_program.rs | 41 +++++++++++++++++++++++++++++++++++------ 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 320e7be..0a0e764 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ use signal_hook::{ }; use solana_cli_config::{Config, CONFIG_FILE}; use solana_client::rpc_client::RpcClient; +use solana_program::process_upload_program; use solana_sdk::{ bpf_loader_upgradeable::{self, UpgradeableLoaderState}, pubkey::Pubkey, @@ -177,6 +178,26 @@ async fn main() -> anyhow::Result<()> { .multiple(true) .last(true) .help("Arguments to pass to the underlying `cargo build-bpf` command"))) + .subcommand(SubCommand::with_name("write") + .about("Write parameters to the otter-verify PDA account associated with the given program ID") + .arg(Arg::with_name("program-id") + .long("program-id") + .required(true) + .takes_value(true) + .help("The address of the program to close the PDA")) + .arg(Arg::with_name("git-url") + .long("git-url") + .required(true) + .takes_value(true) + .help("The HTTPS url of the repository to verify")) + .arg(Arg::with_name("commit") + .long("commit") + .takes_value(true) + .help("The optional commit hash of the repository to verify")) + .arg(Arg::with_name("flags") + .multiple(true) + .last(true) + .help("Additional flags and values to pass"))) .subcommand(SubCommand::with_name("close") .about("Close the otter-verify PDA account associated with the given program ID") .arg(Arg::with_name("program-id") @@ -278,6 +299,28 @@ async fn main() -> anyhow::Result<()> { ) .await } + ("write", Some(sub_m)) => { + let program_id = sub_m.value_of("program-id").unwrap(); + let git_url = sub_m.value_of("git-url").unwrap(); + let commit = sub_m.value_of("commit").map(|s| s.to_string()); + // Check program id is valid + Pubkey::try_from(program_id).map_err(|_| anyhow!("Invalid program id"))?; + + let flags: Vec = sub_m + .values_of("flags") + .unwrap_or_default() + .map(|s| s.to_string()) + .collect(); + + process_upload_program( + Pubkey::try_from(program_id)?, + git_url.to_string(), + &commit, + flags, + ) + .await?; + Ok(()) + } ("close", Some(sub_m)) => { let program_id = sub_m.value_of("program-id").unwrap(); process_close(Pubkey::try_from(program_id)?).await diff --git a/src/solana_program.rs b/src/solana_program.rs index e1f0ae7..4c69f7c 100644 --- a/src/solana_program.rs +++ b/src/solana_program.rs @@ -8,8 +8,8 @@ use std::{ use borsh::{to_vec, BorshDeserialize, BorshSerialize}; use solana_sdk::{ - instruction::AccountMeta, message::Message, pubkey::Pubkey, signature::Keypair, signer::Signer, - system_program, transaction::Transaction, + commitment_config::CommitmentConfig, instruction::AccountMeta, message::Message, + pubkey::Pubkey, signature::Keypair, signer::Signer, system_program, transaction::Transaction, }; use crate::api::get_last_deployed_slot; @@ -64,7 +64,12 @@ fn get_user_config() -> anyhow::Result<(Keypair, RpcClient)> { let config_file = solana_cli_config::CONFIG_FILE .as_ref() .ok_or_else(|| anyhow!("Unable to get config file path"))?; - let cli_config: Config = Config::load(config_file)?; + + let cli_config: Config = Config::load(config_file) + .map_err(|err| anyhow!( + "Unable to load config file {}: {}\nTry running `solana config set -um` to init a config if you haven't already.", + config_file, err + ))?; let signer = solana_clap_utils::keypair::keypair_from_path( &Default::default(), @@ -119,15 +124,34 @@ fn process_otter_verify_ixs( tx.sign(&[&signer], connection.get_latest_blockhash()?); let tx_id = connection - .send_and_confirm_transaction_with_spinner(&tx) + .send_and_confirm_transaction_with_spinner_and_commitment( + &tx, + CommitmentConfig::confirmed(), + ) .map_err(|err| { println!("{:?}", err); anyhow!("Failed to send transaction to the network.") })?; - println!("Program uploaded successfully. Transaction ID: {}", tx_id); + println!( + "Program verification params uploaded successfully. Transaction ID: {}", + tx_id + ); Ok(()) } +pub async fn process_upload_program( + program_address: Pubkey, + git_url: String, + commit: &Option, + args: Vec, +) -> anyhow::Result<()> { + let user_config = get_user_config()?; + let connection = user_config.1; + let rpc_url = connection.url(); + + upload_program(git_url, commit, args, program_address, Some(rpc_url)).await +} + pub async fn upload_program( git_url: String, commit: &Option, @@ -136,7 +160,12 @@ pub async fn upload_program( connection_url: Option, ) -> anyhow::Result<()> { if prompt_user_input( - "Do you want to upload the program verification to the Solana Blockchain? (y/n) ", + &format!("Do you want to upload these parameters for program verification to the Solana Blockchain?\nProgram ID: {}\nGit URL: {}\nCommit Hash: {}\nArgs: {:?}\n(y/n) ", + program_address, + git_url, + commit.as_ref().unwrap_or(&"None".to_string()), + args, + ), ) { println!("Uploading the program verification params to the Solana blockchain...");