rust client: fix TransactionBuilder append to correctly handle CU (#960)

This commit is contained in:
Serge Farny 2024-05-15 11:44:02 +02:00 committed by GitHub
parent 2d9f248063
commit fdb3e987f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 29 additions and 6 deletions

View File

@ -285,6 +285,7 @@ impl<'a> SettleBatchProcessor<'a> {
payer: fee_payer.pubkey(), payer: fee_payer.pubkey(),
signers: vec![fee_payer], signers: vec![fee_payer],
config: client.config().transaction_builder_config.clone(), config: client.config().transaction_builder_config.clone(),
additional_cus: vec![],
} }
.transaction_with_blockhash(self.blockhash) .transaction_with_blockhash(self.blockhash)
} }

View File

@ -395,6 +395,7 @@ impl MangoClient {
payer: payer.pubkey(), payer: payer.pubkey(),
signers: vec![owner, payer], signers: vec![owner, payer],
config: client.config.transaction_builder_config.clone(), config: client.config.transaction_builder_config.clone(),
additional_cus: vec![],
} }
.send_and_confirm(&client) .send_and_confirm(&client)
.await?; .await?;
@ -2395,6 +2396,7 @@ impl MangoClient {
payer: fee_payer.pubkey(), payer: fee_payer.pubkey(),
signers: vec![fee_payer], signers: vec![fee_payer],
config: self.client.config.transaction_builder_config.clone(), config: self.client.config.transaction_builder_config.clone(),
additional_cus: vec![],
}) })
} }
@ -2409,6 +2411,7 @@ impl MangoClient {
payer: fee_payer.pubkey(), payer: fee_payer.pubkey(),
signers: vec![fee_payer], signers: vec![fee_payer],
config: self.client.config.transaction_builder_config.clone(), config: self.client.config.transaction_builder_config.clone(),
additional_cus: vec![],
} }
.simulate(&self.client) .simulate(&self.client)
.await .await
@ -2518,6 +2521,7 @@ pub struct TransactionBuilder {
pub signers: Vec<Arc<Keypair>>, pub signers: Vec<Arc<Keypair>>,
pub payer: Pubkey, pub payer: Pubkey,
pub config: TransactionBuilderConfig, pub config: TransactionBuilderConfig,
pub additional_cus: Vec<u32>,
} }
pub type SimulateTransactionResponse = pub type SimulateTransactionResponse =
@ -2558,10 +2562,15 @@ impl TransactionBuilder {
let cu_per_ix = self.config.compute_budget_per_instruction.unwrap_or(0); let cu_per_ix = self.config.compute_budget_per_instruction.unwrap_or(0);
if !has_compute_unit_limit && cu_per_ix > 0 { if !has_compute_unit_limit && cu_per_ix > 0 {
let ix_count: u32 = (ixs.len() - cu_instructions).try_into().unwrap(); let ix_count: u32 = (ixs.len() - cu_instructions - self.additional_cus.len())
.try_into()
.unwrap();
let additional_cu_sum: u32 = self.additional_cus.iter().sum();
ixs.insert( ixs.insert(
0, 0,
ComputeBudgetInstruction::set_compute_unit_limit(cu_per_ix * ix_count), ComputeBudgetInstruction::set_compute_unit_limit(
cu_per_ix * ix_count + additional_cu_sum,
),
); );
} }
@ -2649,8 +2658,10 @@ impl TransactionBuilder {
} }
pub fn append(&mut self, prepared_instructions: PreparedInstructions) { pub fn append(&mut self, prepared_instructions: PreparedInstructions) {
self.instructions // Do NOT use to instruction s it would add a CU limit
.extend(prepared_instructions.to_instructions()); // That CU limit would overwrite the one computed by the transaction builder
self.instructions.extend(prepared_instructions.instructions);
self.additional_cus.push(prepared_instructions.cu);
} }
} }

View File

@ -204,6 +204,7 @@ impl<'a> JupiterV6<'a> {
.send() .send()
.await .await
.context("quote request to jupiter")?; .context("quote request to jupiter")?;
let quote: QuoteResponse = let quote: QuoteResponse =
util::http_error_handling(response).await.with_context(|| { util::http_error_handling(response).await.with_context(|| {
format!("error requesting jupiter route between {input_mint} and {output_mint}") format!("error requesting jupiter route between {input_mint} and {output_mint}")
@ -392,6 +393,7 @@ impl<'a> JupiterV6<'a> {
.config() .config()
.transaction_builder_config .transaction_builder_config
.clone(), .clone(),
additional_cus: vec![],
}) })
} }

View File

@ -321,6 +321,7 @@ impl<'a> Sanctum<'a> {
.config() .config()
.transaction_builder_config .transaction_builder_config
.clone(), .clone(),
additional_cus: vec![],
}) })
} }

View File

@ -3,6 +3,7 @@ use solana_sdk::instruction::Instruction;
use anchor_lang::prelude::{AccountMeta, Pubkey}; use anchor_lang::prelude::{AccountMeta, Pubkey};
use anyhow::Context; use anyhow::Context;
use tracing::warn;
/// Some Result<> types don't convert to anyhow::Result nicely. Force them through stringification. /// Some Result<> types don't convert to anyhow::Result nicely. Force them through stringification.
pub trait AnyhowWrap { pub trait AnyhowWrap {
@ -80,8 +81,15 @@ pub async fn http_error_handling<T: serde::de::DeserializeOwned>(
if !status.is_success() { if !status.is_success() {
anyhow::bail!("http request failed, status: {status}, body: {response_text}"); anyhow::bail!("http request failed, status: {status}, body: {response_text}");
} }
serde_json::from_str::<T>(&response_text) let object = serde_json::from_str::<T>(&response_text);
.with_context(|| format!("response has unexpected format, body: {response_text}"))
match object {
Ok(o) => Ok(o),
Err(e) => {
warn!("{}", e);
anyhow::bail!("response has unexpected format, body: {response_text}")
}
}
} }
pub fn to_readonly_account_meta(pubkey: Pubkey) -> AccountMeta { pub fn to_readonly_account_meta(pubkey: Pubkey) -> AccountMeta {