From b933cb0ec02683c30eb089f1d90479cd95f2ab75 Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Wed, 13 Mar 2024 14:34:07 +0200 Subject: [PATCH 01/13] :zap: Add compute unit budget --- cli/src/lib.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 4fdf34b0ad..b994bbb654 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -33,6 +33,7 @@ use solana_sdk::bpf_loader; use solana_sdk::bpf_loader_deprecated; use solana_sdk::bpf_loader_upgradeable::{self, UpgradeableLoaderState}; use solana_sdk::commitment_config::CommitmentConfig; +use solana_sdk::compute_budget::ComputeBudgetInstruction; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::Keypair; use solana_sdk::signature::Signer; @@ -2132,9 +2133,18 @@ fn idl_set_buffer( print_idl_instruction("SetBuffer", &ix, &idl_address)?; } else { // Build the transaction. + let mut instructions = vec![ix]; + let priority_fee = get_recommended_micro_lamport_fee(&client)?; + if priority_fee > 0 { + instructions.insert( + 0, + ComputeBudgetInstruction::set_compute_unit_price(priority_fee), + ); + } + let latest_hash = client.get_latest_blockhash()?; let tx = Transaction::new_signed_with_payer( - &[ix], + &instructions, Some(&keypair.pubkey()), &[&keypair], latest_hash, @@ -2345,10 +2355,18 @@ fn idl_write(cfg: &Config, program_id: &Pubkey, idl: &Idl, idl_address: Pubkey) accounts, data, }; + let mut instructions = vec![ix]; // Send transaction. + let priority_fee = get_recommended_micro_lamport_fee(&client)?; + if priority_fee > 0 { + instructions.insert( + 0, + ComputeBudgetInstruction::set_compute_unit_price(priority_fee), + ); + } let latest_hash = client.get_latest_blockhash()?; let tx = Transaction::new_signed_with_payer( - &[ix], + &instructions, Some(&keypair.pubkey()), &[&keypair], latest_hash, @@ -3685,6 +3703,13 @@ fn create_idl_account( }); } let latest_hash = client.get_latest_blockhash()?; + let priority_fee = get_recommended_micro_lamport_fee(&client)?; + if priority_fee > 0 { + instructions.insert( + 0, + ComputeBudgetInstruction::set_compute_unit_price(priority_fee), + ); + } let tx = Transaction::new_signed_with_payer( &instructions, Some(&keypair.pubkey()), @@ -3742,10 +3767,19 @@ fn create_idl_buffer( } }; + let mut instructions = vec![create_account_ix, create_buffer_ix]; + let priority_fee = get_recommended_micro_lamport_fee(&client)?; + if priority_fee > 0 { + instructions.insert( + 0, + ComputeBudgetInstruction::set_compute_unit_price(priority_fee), + ); + } + // Build the transaction. let latest_hash = client.get_latest_blockhash()?; let tx = Transaction::new_signed_with_payer( - &[create_account_ix, create_buffer_ix], + &instructions, Some(&keypair.pubkey()), &[&keypair, &buffer], latest_hash, @@ -4371,6 +4405,19 @@ fn get_node_version() -> Result { Version::parse(output).map_err(Into::into) } +fn get_recommended_micro_lamport_fee(client: &RpcClient) -> Result { + let fees = client.get_recent_prioritization_fees(&[])?; + println!("Recent fees: {:#?}", fees); + let fee = fees + .into_iter() + .fold(0, |acc, x| u64::max(acc, x.prioritization_fee)) + + 1; + + println!("Selected fee: {}", fee); + + Ok(fee) +} + fn get_node_dns_option() -> Result<&'static str> { let version = get_node_version()?; let req = VersionReq::parse(">=16.4.0").unwrap(); From 03388f7f2f6ed63257956585ec30b09f36cc4f0e Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Thu, 14 Mar 2024 20:40:04 +0200 Subject: [PATCH 02/13] :recycle: Modify fee and commitment --- cli/src/lib.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index b994bbb654..1224424096 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -2333,7 +2333,7 @@ fn idl_write(cfg: &Config, program_id: &Pubkey, idl: &Idl, idl_address: Pubkey) e.finish()? }; - const MAX_WRITE_SIZE: usize = 1000; + const MAX_WRITE_SIZE: usize = 500; let mut offset = 0; while offset < idl_data.len() { // Instruction data. @@ -4407,15 +4407,20 @@ fn get_node_version() -> Result { fn get_recommended_micro_lamport_fee(client: &RpcClient) -> Result { let fees = client.get_recent_prioritization_fees(&[])?; - println!("Recent fees: {:#?}", fees); let fee = fees .into_iter() .fold(0, |acc, x| u64::max(acc, x.prioritization_fee)) + 1; - println!("Selected fee: {}", fee); + // Min to 200 lamports per 200_000 CU (default 1 ix transaction) + // 200 * 1M / 200_000 = 1000 + const MIN_FEE: u64 = 1000; - Ok(fee) + let priority_fee = u64::max(fee, MIN_FEE); + + println!("Selected fee: {}", priority_fee); + + Ok(priority_fee) } fn get_node_dns_option() -> Result<&'static str> { @@ -4444,7 +4449,7 @@ fn strip_workspace_prefix(absolute_path: String) -> String { /// Create a new [`RpcClient`] with `confirmed` commitment level instead of the default(finalized). fn create_client(url: U) -> RpcClient { - RpcClient::new_with_commitment(url, CommitmentConfig::confirmed()) + RpcClient::new_with_commitment(url, CommitmentConfig::finalized()) } #[cfg(test)] From a1b2974f9f96a9a6fe7066376fa9c9f1eebfdd33 Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Thu, 14 Mar 2024 23:28:07 +0200 Subject: [PATCH 03/13] :construction: WIP fix error --- cli/src/lib.rs | 67 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 1224424096..c5e2930fc6 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -2333,9 +2333,12 @@ fn idl_write(cfg: &Config, program_id: &Pubkey, idl: &Idl, idl_address: Pubkey) e.finish()? }; - const MAX_WRITE_SIZE: usize = 500; + println!("Idl data length: {:?} bytes", idl_data.len()); + + const MAX_WRITE_SIZE: usize = 600; let mut offset = 0; while offset < idl_data.len() { + println!("Step {offset} "); // Instruction data. let data = { let start = offset; @@ -2364,14 +2367,27 @@ fn idl_write(cfg: &Config, program_id: &Pubkey, idl: &Idl, idl_address: Pubkey) ComputeBudgetInstruction::set_compute_unit_price(priority_fee), ); } - let latest_hash = client.get_latest_blockhash()?; - let tx = Transaction::new_signed_with_payer( - &instructions, - Some(&keypair.pubkey()), - &[&keypair], - latest_hash, - ); - client.send_and_confirm_transaction_with_spinner(&tx)?; + for retry_transactions in 0..20 { + let latest_hash = client.get_latest_blockhash()?; + let tx = Transaction::new_signed_with_payer( + &instructions, + Some(&keypair.pubkey()), + &[&keypair], + latest_hash, + ); + + client.simulate_transaction(transaction) + match client.send_and_confirm_transaction_with_spinner(&tx) { + Ok(_) => break, + Err(e) => { + if retry_transactions == 19 { + return Err(anyhow!("Error: {e}. Failed to send transaction.")); + } + println!("Error: {e}. Retrying transaction."); + } + } + } + offset += MAX_WRITE_SIZE; } Ok(()) @@ -3776,17 +3792,24 @@ fn create_idl_buffer( ); } - // Build the transaction. - let latest_hash = client.get_latest_blockhash()?; - let tx = Transaction::new_signed_with_payer( - &instructions, - Some(&keypair.pubkey()), - &[&keypair, &buffer], - latest_hash, - ); - - // Send the transaction. - client.send_and_confirm_transaction_with_spinner(&tx)?; + for retries in 0..5 { + let latest_hash = client.get_latest_blockhash()?; + let tx = Transaction::new_signed_with_payer( + &instructions, + Some(&keypair.pubkey()), + &[&keypair, &buffer], + latest_hash, + ); + match client.send_and_confirm_transaction_with_spinner(&tx) { + Ok(_) => break, + Err(err) => { + if retries == 4 { + return Err(anyhow!("Error creating buffer account: {}", err)); + } + println!("Error creating buffer account: {}. Retrying...", err); + } + } + } Ok(buffer.pubkey()) } @@ -4414,7 +4437,7 @@ fn get_recommended_micro_lamport_fee(client: &RpcClient) -> Result { // Min to 200 lamports per 200_000 CU (default 1 ix transaction) // 200 * 1M / 200_000 = 1000 - const MIN_FEE: u64 = 1000; + const MIN_FEE: u64 = 1000 * 15; let priority_fee = u64::max(fee, MIN_FEE); @@ -4449,7 +4472,7 @@ fn strip_workspace_prefix(absolute_path: String) -> String { /// Create a new [`RpcClient`] with `confirmed` commitment level instead of the default(finalized). fn create_client(url: U) -> RpcClient { - RpcClient::new_with_commitment(url, CommitmentConfig::finalized()) + RpcClient::new_with_commitment(url, CommitmentConfig::confirmed()) } #[cfg(test)] From f662131019122ad1af9b6c7737536d2cabaf457c Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Thu, 14 Mar 2024 23:55:55 +0200 Subject: [PATCH 04/13] :pencil2: Fix typo --- cli/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index c5e2930fc6..a464ace22a 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -2376,7 +2376,14 @@ fn idl_write(cfg: &Config, program_id: &Pubkey, idl: &Idl, idl_address: Pubkey) latest_hash, ); - client.simulate_transaction(transaction) + let res = client.simulate_transaction(&tx); + + if let Ok(sim_res) = res { + println!("Result ok, {:?} ", sim_res); + } else { + println!("Result error, {:?} ", res); + } + match client.send_and_confirm_transaction_with_spinner(&tx) { Ok(_) => break, Err(e) => { From 0dd2b4adce6f02f215f99d06e995cdadc41980b4 Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Fri, 15 Mar 2024 15:59:13 +0200 Subject: [PATCH 05/13] :lipstick: Prettify the commands --- cli/src/lib.rs | 162 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 120 insertions(+), 42 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index a464ace22a..41e878f9e3 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -361,6 +361,8 @@ pub enum IdlCommand { program_id: Pubkey, #[clap(short, long)] filepath: String, + #[clap(short, long)] + priority_fee: Option, }, Close { program_id: Pubkey, @@ -368,6 +370,8 @@ pub enum IdlCommand { /// Useful for multisig execution when the local wallet keypair is not available. #[clap(long)] print_only: bool, + #[clap(short, long)] + priority_fee: Option, }, /// Writes an IDL into a buffer account. This can be used with SetBuffer /// to perform an upgrade. @@ -375,6 +379,8 @@ pub enum IdlCommand { program_id: Pubkey, #[clap(short, long)] filepath: String, + #[clap(short, long)] + priority_fee: Option, }, /// Sets a new IDL buffer for the program. SetBuffer { @@ -386,6 +392,8 @@ pub enum IdlCommand { /// Useful for multisig execution when the local wallet keypair is not available. #[clap(long)] print_only: bool, + #[clap(short, long)] + priority_fee: Option, }, /// Upgrades the IDL to the new file. An alias for first writing and then /// then setting the idl buffer account. @@ -393,6 +401,8 @@ pub enum IdlCommand { program_id: Pubkey, #[clap(short, long)] filepath: String, + #[clap(short, long)] + priority_fee: Option, }, /// Sets a new authority on the IDL account. SetAuthority { @@ -409,6 +419,8 @@ pub enum IdlCommand { /// Useful for multisig execution when the local wallet keypair is not available. #[clap(long)] print_only: bool, + #[clap(short, long)] + priority_fee: Option, }, /// Command to remove the ability to modify the IDL account. This should /// likely be used in conjection with eliminating an "upgrade authority" on @@ -416,6 +428,8 @@ pub enum IdlCommand { EraseAuthority { #[clap(short, long)] program_id: Pubkey, + #[clap(short, long)] + priority_fee: Option, }, /// Outputs the authority for the IDL account. Authority { @@ -1964,31 +1978,47 @@ fn idl(cfg_override: &ConfigOverride, subcmd: IdlCommand) -> Result<()> { IdlCommand::Init { program_id, filepath, - } => idl_init(cfg_override, program_id, filepath), + priority_fee, + } => idl_init(cfg_override, program_id, filepath, priority_fee), IdlCommand::Close { program_id, print_only, - } => idl_close(cfg_override, program_id, print_only), + priority_fee, + } => idl_close(cfg_override, program_id, print_only, priority_fee), IdlCommand::WriteBuffer { program_id, filepath, - } => idl_write_buffer(cfg_override, program_id, filepath).map(|_| ()), + priority_fee, + } => idl_write_buffer(cfg_override, program_id, filepath, priority_fee).map(|_| ()), IdlCommand::SetBuffer { program_id, buffer, print_only, - } => idl_set_buffer(cfg_override, program_id, buffer, print_only), + priority_fee, + } => idl_set_buffer(cfg_override, program_id, buffer, print_only, priority_fee), IdlCommand::Upgrade { program_id, filepath, - } => idl_upgrade(cfg_override, program_id, filepath), + priority_fee, + } => idl_upgrade(cfg_override, program_id, filepath, priority_fee), IdlCommand::SetAuthority { program_id, address, new_authority, print_only, - } => idl_set_authority(cfg_override, program_id, address, new_authority, print_only), - IdlCommand::EraseAuthority { program_id } => idl_erase_authority(cfg_override, program_id), + priority_fee, + } => idl_set_authority( + cfg_override, + program_id, + address, + new_authority, + print_only, + priority_fee, + ), + IdlCommand::EraseAuthority { + program_id, + priority_fee, + } => idl_erase_authority(cfg_override, program_id, priority_fee), IdlCommand::Authority { program_id } => idl_authority(cfg_override, program_id), IdlCommand::Parse { file, @@ -2048,24 +2078,34 @@ fn get_idl_account(client: &RpcClient, idl_address: &Pubkey) -> Result Result<()> { +fn idl_init( + cfg_override: &ConfigOverride, + program_id: Pubkey, + idl_filepath: String, + priority_fee: Option, +) -> Result<()> { with_workspace(cfg_override, |cfg| { let keypair = cfg.provider.wallet.to_string(); let bytes = fs::read(idl_filepath)?; let idl: Idl = serde_json::from_reader(&*bytes)?; - let idl_address = create_idl_account(cfg, &keypair, &program_id, &idl)?; + let idl_address = create_idl_account(cfg, &keypair, &program_id, &idl, priority_fee)?; println!("Idl account created: {idl_address:?}"); Ok(()) }) } -fn idl_close(cfg_override: &ConfigOverride, program_id: Pubkey, print_only: bool) -> Result<()> { +fn idl_close( + cfg_override: &ConfigOverride, + program_id: Pubkey, + print_only: bool, + priority_fee: Option, +) -> Result<()> { with_workspace(cfg_override, |cfg| { let idl_address = IdlAccount::address(&program_id); - idl_close_account(cfg, &program_id, idl_address, print_only)?; + idl_close_account(cfg, &program_id, idl_address, print_only, priority_fee)?; if !print_only { println!("Idl account closed: {idl_address:?}"); @@ -2079,6 +2119,7 @@ fn idl_write_buffer( cfg_override: &ConfigOverride, program_id: Pubkey, idl_filepath: String, + priority_fee: Option, ) -> Result { with_workspace(cfg_override, |cfg| { let keypair = cfg.provider.wallet.to_string(); @@ -2086,8 +2127,8 @@ fn idl_write_buffer( let bytes = fs::read(idl_filepath)?; let idl: Idl = serde_json::from_reader(&*bytes)?; - let idl_buffer = create_idl_buffer(cfg, &keypair, &program_id, &idl)?; - idl_write(cfg, &program_id, &idl, idl_buffer)?; + let idl_buffer = create_idl_buffer(cfg, &keypair, &program_id, &idl, priority_fee)?; + idl_write(cfg, &program_id, &idl, idl_buffer, priority_fee)?; println!("Idl buffer created: {idl_buffer:?}"); @@ -2100,6 +2141,7 @@ fn idl_set_buffer( program_id: Pubkey, buffer: Pubkey, print_only: bool, + priority_fee: Option, ) -> Result<()> { with_workspace(cfg_override, |cfg| { let keypair = solana_sdk::signature::read_keypair_file(&cfg.provider.wallet.to_string()) @@ -2134,8 +2176,8 @@ fn idl_set_buffer( } else { // Build the transaction. let mut instructions = vec![ix]; - let priority_fee = get_recommended_micro_lamport_fee(&client)?; - if priority_fee > 0 { + if let Some(priority_fee) = priority_fee { + let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; instructions.insert( 0, ComputeBudgetInstruction::set_compute_unit_price(priority_fee), @@ -2162,9 +2204,10 @@ fn idl_upgrade( cfg_override: &ConfigOverride, program_id: Pubkey, idl_filepath: String, + priority_fee: Option, ) -> Result<()> { - let buffer = idl_write_buffer(cfg_override, program_id, idl_filepath)?; - idl_set_buffer(cfg_override, program_id, buffer, false) + let buffer = idl_write_buffer(cfg_override, program_id, idl_filepath, priority_fee)?; + idl_set_buffer(cfg_override, program_id, buffer, false, priority_fee) } fn idl_authority(cfg_override: &ConfigOverride, program_id: Pubkey) -> Result<()> { @@ -2194,6 +2237,7 @@ fn idl_set_authority( address: Option, new_authority: Pubkey, print_only: bool, + priority_fee: Option, ) -> Result<()> { with_workspace(cfg_override, |cfg| { // Misc. @@ -2232,10 +2276,19 @@ fn idl_set_authority( if print_only { print_idl_instruction("SetAuthority", &ix, &idl_address)?; } else { + let mut instructions = vec![ix]; + if let Some(priority_fee) = priority_fee { + let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; + instructions.insert( + 0, + ComputeBudgetInstruction::set_compute_unit_price(priority_fee), + ); + } + // Send transaction. let latest_hash = client.get_latest_blockhash()?; let tx = Transaction::new_signed_with_payer( - &[ix], + &instructions, Some(&keypair.pubkey()), &[&keypair], latest_hash, @@ -2249,7 +2302,11 @@ fn idl_set_authority( }) } -fn idl_erase_authority(cfg_override: &ConfigOverride, program_id: Pubkey) -> Result<()> { +fn idl_erase_authority( + cfg_override: &ConfigOverride, + program_id: Pubkey, + priority_fee: Option, +) -> Result<()> { println!("Are you sure you want to erase the IDL authority: [y/n]"); let stdin = std::io::stdin(); @@ -2260,7 +2317,14 @@ fn idl_erase_authority(cfg_override: &ConfigOverride, program_id: Pubkey) -> Res return Ok(()); } - idl_set_authority(cfg_override, program_id, None, ERASED_AUTHORITY, false)?; + idl_set_authority( + cfg_override, + program_id, + None, + ERASED_AUTHORITY, + false, + priority_fee, + )?; Ok(()) } @@ -2270,6 +2334,7 @@ fn idl_close_account( program_id: &Pubkey, idl_address: Pubkey, print_only: bool, + priority_fee: Option, ) -> Result<()> { let keypair = solana_sdk::signature::read_keypair_file(&cfg.provider.wallet.to_string()) .map_err(|_| anyhow!("Unable to read keypair file"))?; @@ -2297,10 +2362,19 @@ fn idl_close_account( if print_only { print_idl_instruction("Close", &ix, &idl_address)?; } else { + let mut instructions = vec![ix]; + if let Some(priority_fee) = priority_fee { + let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; + instructions.insert( + 0, + ComputeBudgetInstruction::set_compute_unit_price(priority_fee), + ); + } + // Send transaction. let latest_hash = client.get_latest_blockhash()?; let tx = Transaction::new_signed_with_payer( - &[ix], + &instructions, Some(&keypair.pubkey()), &[&keypair], latest_hash, @@ -2314,7 +2388,13 @@ fn idl_close_account( // Write the idl to the account buffer, chopping up the IDL into pieces // and sending multiple transactions in the event the IDL doesn't fit into // a single transaction. -fn idl_write(cfg: &Config, program_id: &Pubkey, idl: &Idl, idl_address: Pubkey) -> Result<()> { +fn idl_write( + cfg: &Config, + program_id: &Pubkey, + idl: &Idl, + idl_address: Pubkey, + priority_fee: Option, +) -> Result<()> { // Remove the metadata before deploy. let mut idl = idl.clone(); idl.metadata = None; @@ -2360,8 +2440,8 @@ fn idl_write(cfg: &Config, program_id: &Pubkey, idl: &Idl, idl_address: Pubkey) }; let mut instructions = vec![ix]; // Send transaction. - let priority_fee = get_recommended_micro_lamport_fee(&client)?; - if priority_fee > 0 { + if let Some(priority_fee) = priority_fee { + let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; instructions.insert( 0, ComputeBudgetInstruction::set_compute_unit_price(priority_fee), @@ -2376,14 +2456,6 @@ fn idl_write(cfg: &Config, program_id: &Pubkey, idl: &Idl, idl_address: Pubkey) latest_hash, ); - let res = client.simulate_transaction(&tx); - - if let Ok(sim_res) = res { - println!("Result ok, {:?} ", sim_res); - } else { - println!("Result error, {:?} ", res); - } - match client.send_and_confirm_transaction_with_spinner(&tx) { Ok(_) => break, Err(e) => { @@ -3671,6 +3743,7 @@ fn create_idl_account( keypair_path: &str, program_id: &Pubkey, idl: &Idl, + priority_fee: Option, ) -> Result { // Misc. let idl_address = IdlAccount::address(program_id); @@ -3726,13 +3799,14 @@ fn create_idl_account( }); } let latest_hash = client.get_latest_blockhash()?; - let priority_fee = get_recommended_micro_lamport_fee(&client)?; - if priority_fee > 0 { + if let Some(priority_fee) = priority_fee { + let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; instructions.insert( 0, ComputeBudgetInstruction::set_compute_unit_price(priority_fee), ); } + let tx = Transaction::new_signed_with_payer( &instructions, Some(&keypair.pubkey()), @@ -3743,7 +3817,13 @@ fn create_idl_account( } // Write directly to the IDL account buffer. - idl_write(cfg, program_id, idl, IdlAccount::address(program_id))?; + idl_write( + cfg, + program_id, + idl, + IdlAccount::address(program_id), + priority_fee, + )?; Ok(idl_address) } @@ -3753,6 +3833,7 @@ fn create_idl_buffer( keypair_path: &str, program_id: &Pubkey, idl: &Idl, + priority_fee: Option, ) -> Result { let keypair = solana_sdk::signature::read_keypair_file(keypair_path) .map_err(|_| anyhow!("Unable to read keypair file"))?; @@ -3791,8 +3872,8 @@ fn create_idl_buffer( }; let mut instructions = vec![create_account_ix, create_buffer_ix]; - let priority_fee = get_recommended_micro_lamport_fee(&client)?; - if priority_fee > 0 { + if let Some(priority_fee) = priority_fee { + let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; instructions.insert( 0, ComputeBudgetInstruction::set_compute_unit_price(priority_fee), @@ -4435,7 +4516,7 @@ fn get_node_version() -> Result { Version::parse(output).map_err(Into::into) } -fn get_recommended_micro_lamport_fee(client: &RpcClient) -> Result { +fn get_recommended_micro_lamport_fee(client: &RpcClient, priority_fee: u64) -> Result { let fees = client.get_recent_prioritization_fees(&[])?; let fee = fees .into_iter() @@ -4444,11 +4525,8 @@ fn get_recommended_micro_lamport_fee(client: &RpcClient) -> Result { // Min to 200 lamports per 200_000 CU (default 1 ix transaction) // 200 * 1M / 200_000 = 1000 - const MIN_FEE: u64 = 1000 * 15; - - let priority_fee = u64::max(fee, MIN_FEE); - println!("Selected fee: {}", priority_fee); + let priority_fee = u64::max(priority_fee, fee); Ok(priority_fee) } From 604eeb727724a01daea418913f5f184ec74f79ae Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Fri, 15 Mar 2024 16:27:42 +0200 Subject: [PATCH 06/13] :wastebasket: Clean up --- cli/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 41e878f9e3..d7e8cb8166 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -4523,9 +4523,6 @@ fn get_recommended_micro_lamport_fee(client: &RpcClient, priority_fee: u64) -> R .fold(0, |acc, x| u64::max(acc, x.prioritization_fee)) + 1; - // Min to 200 lamports per 200_000 CU (default 1 ix transaction) - // 200 * 1M / 200_000 = 1000 - let priority_fee = u64::max(priority_fee, fee); Ok(priority_fee) From 22625f2af9197c8e883cdf38a3688126743eb25b Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Sat, 16 Mar 2024 20:06:46 +0200 Subject: [PATCH 07/13] :recycle: Address comments --- cli/src/lib.rs | 57 ++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index d7e8cb8166..d0d8d4cc37 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -361,7 +361,7 @@ pub enum IdlCommand { program_id: Pubkey, #[clap(short, long)] filepath: String, - #[clap(short, long)] + #[clap(long)] priority_fee: Option, }, Close { @@ -370,7 +370,7 @@ pub enum IdlCommand { /// Useful for multisig execution when the local wallet keypair is not available. #[clap(long)] print_only: bool, - #[clap(short, long)] + #[clap(long)] priority_fee: Option, }, /// Writes an IDL into a buffer account. This can be used with SetBuffer @@ -379,7 +379,7 @@ pub enum IdlCommand { program_id: Pubkey, #[clap(short, long)] filepath: String, - #[clap(short, long)] + #[clap(long)] priority_fee: Option, }, /// Sets a new IDL buffer for the program. @@ -392,7 +392,7 @@ pub enum IdlCommand { /// Useful for multisig execution when the local wallet keypair is not available. #[clap(long)] print_only: bool, - #[clap(short, long)] + #[clap(long)] priority_fee: Option, }, /// Upgrades the IDL to the new file. An alias for first writing and then @@ -401,7 +401,7 @@ pub enum IdlCommand { program_id: Pubkey, #[clap(short, long)] filepath: String, - #[clap(short, long)] + #[clap(long)] priority_fee: Option, }, /// Sets a new authority on the IDL account. @@ -419,7 +419,7 @@ pub enum IdlCommand { /// Useful for multisig execution when the local wallet keypair is not available. #[clap(long)] print_only: bool, - #[clap(short, long)] + #[clap(long)] priority_fee: Option, }, /// Command to remove the ability to modify the IDL account. This should @@ -428,7 +428,7 @@ pub enum IdlCommand { EraseAuthority { #[clap(short, long)] program_id: Pubkey, - #[clap(short, long)] + #[clap(long)] priority_fee: Option, }, /// Outputs the authority for the IDL account. @@ -2278,11 +2278,7 @@ fn idl_set_authority( } else { let mut instructions = vec![ix]; if let Some(priority_fee) = priority_fee { - let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; - instructions.insert( - 0, - ComputeBudgetInstruction::set_compute_unit_price(priority_fee), - ); + prepend_set_compute_unit_ix(&mut instructions, &client, priority_fee)?; } // Send transaction. @@ -2364,11 +2360,7 @@ fn idl_close_account( } else { let mut instructions = vec![ix]; if let Some(priority_fee) = priority_fee { - let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; - instructions.insert( - 0, - ComputeBudgetInstruction::set_compute_unit_price(priority_fee), - ); + prepend_set_compute_unit_ix(&mut instructions, &client, priority_fee)?; } // Send transaction. @@ -2441,11 +2433,7 @@ fn idl_write( let mut instructions = vec![ix]; // Send transaction. if let Some(priority_fee) = priority_fee { - let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; - instructions.insert( - 0, - ComputeBudgetInstruction::set_compute_unit_price(priority_fee), - ); + prepend_set_compute_unit_ix(&mut instructions, &client, priority_fee)?; } for retry_transactions in 0..20 { let latest_hash = client.get_latest_blockhash()?; @@ -3800,11 +3788,7 @@ fn create_idl_account( } let latest_hash = client.get_latest_blockhash()?; if let Some(priority_fee) = priority_fee { - let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; - instructions.insert( - 0, - ComputeBudgetInstruction::set_compute_unit_price(priority_fee), - ); + prepend_set_compute_unit_ix(&mut instructions, &client, priority_fee)?; } let tx = Transaction::new_signed_with_payer( @@ -3873,11 +3857,7 @@ fn create_idl_buffer( let mut instructions = vec![create_account_ix, create_buffer_ix]; if let Some(priority_fee) = priority_fee { - let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; - instructions.insert( - 0, - ComputeBudgetInstruction::set_compute_unit_price(priority_fee), - ); + prepend_set_compute_unit_ix(&mut instructions, &client, priority_fee)?; } for retries in 0..5 { @@ -4528,6 +4508,19 @@ fn get_recommended_micro_lamport_fee(client: &RpcClient, priority_fee: u64) -> R Ok(priority_fee) } +fn prepend_set_compute_unit_ix( + instructions: &mut Vec, + client: &RpcClient, + priority_fee: u64, +) -> Result<()> { + let priority_fee = get_recommended_micro_lamport_fee(client, priority_fee)?; + instructions.insert( + 0, + ComputeBudgetInstruction::set_compute_unit_price(priority_fee), + ); + Ok(()) +} + fn get_node_dns_option() -> Result<&'static str> { let version = get_node_version()?; let req = VersionReq::parse(">=16.4.0").unwrap(); From 4f80da109d13283efd41d710a1ff175ea57d2376 Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Sun, 17 Mar 2024 14:06:29 +0200 Subject: [PATCH 08/13] :recycle: Get median fee, address comments --- cli/src/lib.rs | 114 ++++++++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 53 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index d0d8d4cc37..1489dae40f 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -2175,25 +2175,28 @@ fn idl_set_buffer( print_idl_instruction("SetBuffer", &ix, &idl_address)?; } else { // Build the transaction. - let mut instructions = vec![ix]; - if let Some(priority_fee) = priority_fee { - let priority_fee = get_recommended_micro_lamport_fee(&client, priority_fee)?; - instructions.insert( - 0, - ComputeBudgetInstruction::set_compute_unit_price(priority_fee), - ); - } - - let latest_hash = client.get_latest_blockhash()?; - let tx = Transaction::new_signed_with_payer( - &instructions, - Some(&keypair.pubkey()), - &[&keypair], - latest_hash, - ); + let instructions = prepend_compute_unit_ix(vec![ix], &client, priority_fee)?; // Send the transaction. - client.send_and_confirm_transaction_with_spinner(&tx)?; + for retry_transactions in 0..20 { + let latest_hash = client.get_latest_blockhash()?; + let tx = Transaction::new_signed_with_payer( + &instructions, + Some(&keypair.pubkey()), + &[&keypair], + latest_hash, + ); + + match client.send_and_confirm_transaction_with_spinner(&tx) { + Ok(_) => break, + Err(e) => { + if retry_transactions == 19 { + return Err(anyhow!("Error: {e}. Failed to send transaction.")); + } + println!("Error: {e}. Retrying transaction."); + } + } + } } Ok(()) @@ -2276,10 +2279,7 @@ fn idl_set_authority( if print_only { print_idl_instruction("SetAuthority", &ix, &idl_address)?; } else { - let mut instructions = vec![ix]; - if let Some(priority_fee) = priority_fee { - prepend_set_compute_unit_ix(&mut instructions, &client, priority_fee)?; - } + let instructions = prepend_compute_unit_ix(vec![ix], &client, priority_fee)?; // Send transaction. let latest_hash = client.get_latest_blockhash()?; @@ -2358,10 +2358,7 @@ fn idl_close_account( if print_only { print_idl_instruction("Close", &ix, &idl_address)?; } else { - let mut instructions = vec![ix]; - if let Some(priority_fee) = priority_fee { - prepend_set_compute_unit_ix(&mut instructions, &client, priority_fee)?; - } + let instructions = prepend_compute_unit_ix(vec![ix], &client, priority_fee)?; // Send transaction. let latest_hash = client.get_latest_blockhash()?; @@ -2430,11 +2427,9 @@ fn idl_write( accounts, data, }; - let mut instructions = vec![ix]; // Send transaction. - if let Some(priority_fee) = priority_fee { - prepend_set_compute_unit_ix(&mut instructions, &client, priority_fee)?; - } + let instructions = prepend_compute_unit_ix(vec![ix], &client, priority_fee)?; + for retry_transactions in 0..20 { let latest_hash = client.get_latest_blockhash()?; let tx = Transaction::new_signed_with_payer( @@ -3787,9 +3782,7 @@ fn create_idl_account( }); } let latest_hash = client.get_latest_blockhash()?; - if let Some(priority_fee) = priority_fee { - prepend_set_compute_unit_ix(&mut instructions, &client, priority_fee)?; - } + instructions = prepend_compute_unit_ix(instructions, &client, priority_fee)?; let tx = Transaction::new_signed_with_payer( &instructions, @@ -3855,10 +3848,11 @@ fn create_idl_buffer( } }; - let mut instructions = vec![create_account_ix, create_buffer_ix]; - if let Some(priority_fee) = priority_fee { - prepend_set_compute_unit_ix(&mut instructions, &client, priority_fee)?; - } + let instructions = prepend_compute_unit_ix( + vec![create_account_ix, create_buffer_ix], + &client, + priority_fee, + )?; for retries in 0..5 { let latest_hash = client.get_latest_blockhash()?; @@ -4496,29 +4490,43 @@ fn get_node_version() -> Result { Version::parse(output).map_err(Into::into) } -fn get_recommended_micro_lamport_fee(client: &RpcClient, priority_fee: u64) -> Result { - let fees = client.get_recent_prioritization_fees(&[])?; - let fee = fees - .into_iter() - .fold(0, |acc, x| u64::max(acc, x.prioritization_fee)) - + 1; +fn get_recommended_micro_lamport_fee(client: &RpcClient, priority_fee: Option) -> Result { + let mut fees = client.get_recent_prioritization_fees(&[])?; - let priority_fee = u64::max(priority_fee, fee); + // Get the median fee from the most recent recent 150 slots' prioritization fee + fees.sort_unstable_by_key(|fee| fee.prioritization_fee); + let median_index = fees.len() / 2; - Ok(priority_fee) + let median_priority_fee = if fees.len() % 2 == 0 { + (fees[median_index - 1].prioritization_fee + fees[median_index].prioritization_fee) / 2 + } else { + fees[median_index].prioritization_fee + }; + + if let Some(priority_fee) = priority_fee { + Ok(priority_fee) + } else { + Ok(median_priority_fee) + } } -fn prepend_set_compute_unit_ix( - instructions: &mut Vec, +fn prepend_compute_unit_ix( + instructions: Vec, client: &RpcClient, - priority_fee: u64, -) -> Result<()> { + priority_fee: Option, +) -> Result> { let priority_fee = get_recommended_micro_lamport_fee(client, priority_fee)?; - instructions.insert( - 0, - ComputeBudgetInstruction::set_compute_unit_price(priority_fee), - ); - Ok(()) + + if priority_fee > 0 { + let mut instructions_appended = instructions.clone(); + instructions_appended.insert( + 0, + ComputeBudgetInstruction::set_compute_unit_price(priority_fee), + ); + Ok(instructions) + } else { + Ok(instructions) + } } fn get_node_dns_option() -> Result<&'static str> { From 28a6a2c4fad5370b72567198bf12069a0c83f7c6 Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Sun, 17 Mar 2024 14:06:29 +0200 Subject: [PATCH 09/13] :recycle: Get median fee, address comments --- cli/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 1489dae40f..23b4ce3f39 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -4523,7 +4523,7 @@ fn prepend_compute_unit_ix( 0, ComputeBudgetInstruction::set_compute_unit_price(priority_fee), ); - Ok(instructions) + Ok(instructions_appended) } else { Ok(instructions) } From 609bc5fe748788929e9e0ddcd6b76e2772efc105 Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Mon, 18 Mar 2024 13:39:12 +0200 Subject: [PATCH 10/13] :memo: Final changes --- cli/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 23b4ce3f39..9294182a42 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -4491,6 +4491,10 @@ fn get_node_version() -> Result { } fn get_recommended_micro_lamport_fee(client: &RpcClient, priority_fee: Option) -> Result { + if let Some(priority_fee) = priority_fee { + return Ok(priority_fee); + } + let mut fees = client.get_recent_prioritization_fees(&[])?; // Get the median fee from the most recent recent 150 slots' prioritization fee @@ -4503,11 +4507,7 @@ fn get_recommended_micro_lamport_fee(client: &RpcClient, priority_fee: Option Date: Thu, 21 Mar 2024 17:43:16 +0200 Subject: [PATCH 11/13] :recycle: Change buffer size --- cli/src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 9294182a42..3147412f5c 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -2187,6 +2187,9 @@ fn idl_set_buffer( latest_hash, ); + let tx_hash = client.simulate_transaction(&tx)?.value; + println!("tx_hash, {:?} ", tx_hash); + match client.send_and_confirm_transaction_with_spinner(&tx) { Ok(_) => break, Err(e) => { @@ -2404,7 +2407,7 @@ fn idl_write( println!("Idl data length: {:?} bytes", idl_data.len()); - const MAX_WRITE_SIZE: usize = 600; + const MAX_WRITE_SIZE: usize = 800; let mut offset = 0; while offset < idl_data.len() { println!("Step {offset} "); @@ -2439,6 +2442,9 @@ fn idl_write( latest_hash, ); + let tx_hash = client.simulate_transaction(&tx)?.value; + println!("tx_hash, {:?} ", tx_hash); + match client.send_and_confirm_transaction_with_spinner(&tx) { Ok(_) => break, Err(e) => { From 5b7e46ed3ba7d2f0a1561e27f57c1217aaa8f5c4 Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Mon, 13 May 2024 17:51:11 +0300 Subject: [PATCH 12/13] :recycle: Don't overspam the idl write --- cli/src/lib.rs | 48 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 3147412f5c..423415dd28 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -2177,9 +2177,12 @@ fn idl_set_buffer( // Build the transaction. let instructions = prepend_compute_unit_ix(vec![ix], &client, priority_fee)?; + let mut latest_hash = client.get_latest_blockhash()?; // Send the transaction. for retry_transactions in 0..20 { - let latest_hash = client.get_latest_blockhash()?; + if !client.is_blockhash_valid(&latest_hash, client.commitment())? { + latest_hash = client.get_latest_blockhash()?; + } let tx = Transaction::new_signed_with_payer( &instructions, Some(&keypair.pubkey()), @@ -2433,8 +2436,11 @@ fn idl_write( // Send transaction. let instructions = prepend_compute_unit_ix(vec![ix], &client, priority_fee)?; + let mut latest_hash = client.get_latest_blockhash()?; for retry_transactions in 0..20 { - let latest_hash = client.get_latest_blockhash()?; + if !client.is_blockhash_valid(&latest_hash, client.commitment())? { + latest_hash = client.get_latest_blockhash()?; + } let tx = Transaction::new_signed_with_payer( &instructions, Some(&keypair.pubkey()), @@ -3787,16 +3793,27 @@ fn create_idl_account( data, }); } - let latest_hash = client.get_latest_blockhash()?; instructions = prepend_compute_unit_ix(instructions, &client, priority_fee)?; - let tx = Transaction::new_signed_with_payer( - &instructions, - Some(&keypair.pubkey()), - &[&keypair], - latest_hash, - ); - client.send_and_confirm_transaction_with_spinner(&tx)?; + println!("Initializing IDL account"); + let latest_hash = client.get_latest_blockhash()?; + for retries in 0..10 { + let tx = Transaction::new_signed_with_payer( + &instructions, + Some(&keypair.pubkey()), + &[&keypair], + latest_hash, + ); + match client.send_and_confirm_transaction_with_spinner(&tx) { + Ok(_) => break, + Err(err) => { + if retries == 9 { + return Err(anyhow!("Error initializing IDL account: {}", err)); + } + println!("Error initializing IDL account: {}. Retrying...", err); + } + } + } } // Write directly to the IDL account buffer. @@ -3824,6 +3841,7 @@ fn create_idl_buffer( let client = create_client(url); let buffer = Keypair::new(); + println!("Buffer address, {:?} ", buffer.pubkey()); // Creates the new buffer account with the system program. let create_account_ix = { @@ -3860,8 +3878,12 @@ fn create_idl_buffer( priority_fee, )?; - for retries in 0..5 { - let latest_hash = client.get_latest_blockhash()?; + println!("Creating IDL buffer"); + let mut latest_hash = client.get_latest_blockhash()?; + for retries in 0..10 { + if !client.is_blockhash_valid(&latest_hash, client.commitment())? { + latest_hash = client.get_latest_blockhash()?; + } let tx = Transaction::new_signed_with_payer( &instructions, Some(&keypair.pubkey()), @@ -3871,7 +3893,7 @@ fn create_idl_buffer( match client.send_and_confirm_transaction_with_spinner(&tx) { Ok(_) => break, Err(err) => { - if retries == 4 { + if retries == 9 { return Err(anyhow!("Error creating buffer account: {}", err)); } println!("Error creating buffer account: {}. Retrying...", err); From f9d8192c167bcfcebc177fa9b605780928899ef6 Mon Sep 17 00:00:00 2001 From: Andrei Hrs Date: Mon, 13 May 2024 18:03:12 +0300 Subject: [PATCH 13/13] :bug: Fix idl write overwrites from retries --- cli/src/lib.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 423415dd28..2881de07f4 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -2179,7 +2179,7 @@ fn idl_set_buffer( let mut latest_hash = client.get_latest_blockhash()?; // Send the transaction. - for retry_transactions in 0..20 { + for retries in 0..20 { if !client.is_blockhash_valid(&latest_hash, client.commitment())? { latest_hash = client.get_latest_blockhash()?; } @@ -2196,7 +2196,7 @@ fn idl_set_buffer( match client.send_and_confirm_transaction_with_spinner(&tx) { Ok(_) => break, Err(e) => { - if retry_transactions == 19 { + if retries == 19 { return Err(anyhow!("Error: {e}. Failed to send transaction.")); } println!("Error: {e}. Retrying transaction."); @@ -2437,7 +2437,7 @@ fn idl_write( let instructions = prepend_compute_unit_ix(vec![ix], &client, priority_fee)?; let mut latest_hash = client.get_latest_blockhash()?; - for retry_transactions in 0..20 { + for retries in 0..20 { if !client.is_blockhash_valid(&latest_hash, client.commitment())? { latest_hash = client.get_latest_blockhash()?; } @@ -2454,7 +2454,7 @@ fn idl_write( match client.send_and_confirm_transaction_with_spinner(&tx) { Ok(_) => break, Err(e) => { - if retry_transactions == 19 { + if retries == 19 { return Err(anyhow!("Error: {e}. Failed to send transaction.")); } println!("Error: {e}. Retrying transaction."); @@ -3795,22 +3795,26 @@ fn create_idl_account( } instructions = prepend_compute_unit_ix(instructions, &client, priority_fee)?; - println!("Initializing IDL account"); - let latest_hash = client.get_latest_blockhash()?; - for retries in 0..10 { + let mut latest_hash = client.get_latest_blockhash()?; + for retries in 0..20 { + if !client.is_blockhash_valid(&latest_hash, client.commitment())? { + latest_hash = client.get_latest_blockhash()?; + } + let tx = Transaction::new_signed_with_payer( &instructions, Some(&keypair.pubkey()), &[&keypair], latest_hash, ); + match client.send_and_confirm_transaction_with_spinner(&tx) { Ok(_) => break, Err(err) => { - if retries == 9 { - return Err(anyhow!("Error initializing IDL account: {}", err)); + if retries == 19 { + return Err(anyhow!("Error creating IDL account: {}", err)); } - println!("Error initializing IDL account: {}. Retrying...", err); + println!("Error creating IDL account: {}. Retrying...", err); } } } @@ -3878,9 +3882,8 @@ fn create_idl_buffer( priority_fee, )?; - println!("Creating IDL buffer"); let mut latest_hash = client.get_latest_blockhash()?; - for retries in 0..10 { + for retries in 0..20 { if !client.is_blockhash_valid(&latest_hash, client.commitment())? { latest_hash = client.get_latest_blockhash()?; } @@ -3893,7 +3896,7 @@ fn create_idl_buffer( match client.send_and_confirm_transaction_with_spinner(&tx) { Ok(_) => break, Err(err) => { - if retries == 9 { + if retries == 19 { return Err(anyhow!("Error creating buffer account: {}", err)); } println!("Error creating buffer account: {}. Retrying...", err); @@ -4537,7 +4540,8 @@ fn get_recommended_micro_lamport_fee(client: &RpcClient, priority_fee: Option, client: &RpcClient,