solana_exec/utilities/
create_tx_from_swap_configs.rs

1use crate::constants::{JITO_DONT_FRONT_ACCOUNT, JITO_TIP_ACCOUNTS};
2use crate::types::compute_budget_instruction_idl::ComputeBudgetInstructionIdl;
3use crate::types::swap_config::SwapConfig;
4use crate::utilities::make_swap_instructions::make_swap_instructions;
5use solana_central::CentralContext;
6use solana_central::constants::SOLANA_PROGRAMS;
7use solana_compute_budget_interface::ComputeBudgetInstruction;
8use solana_sdk::instruction::{AccountMeta, Instruction};
9use solana_sdk::signature::{Keypair, Signer};
10use solana_sdk::transaction::Transaction;
11use solana_system_interface::instruction::transfer;
12use std::sync::Arc;
13
14/// Assemble a Solana transaction from an ordered vector of swap configs. Builds a complete transaction including:
15/// - Token account management (opening/closing accounts as needed)
16/// - Jito don't front account included for sandwich protection
17/// - Compute budget instructions (reasonable priority fee if Jito not used)
18/// - All swap instructions
19/// - Jito tip instruction (if `use_jito` is true and tip is nonzero)
20///
21/// If `use_jito` is true, priority fees are omitted as Jito bundles don't use them.
22pub fn create_tx_from_swap_configs(
23  swap_configs: &Vec<SwapConfig>,
24  central_context: &Arc<CentralContext>,
25  use_jito: bool,
26  jito_tip_lp: u64,
27  wallet_keypair: &Keypair,
28) -> Transaction {
29  let wallet_pubkey = wallet_keypair.pubkey();
30  let mut compute_unit_budget = 0;
31  let swap_instructions =
32    make_swap_instructions(swap_configs, central_context, &mut compute_unit_budget);
33  let mut ixs: Vec<Instruction> = Vec::new();
34  /*
35  We should always be using the don't front account to avoid being frontrun in a
36  separate bundle. A good place in Jito's demo to include that is in the compute budget limit
37  instruction, so we are doing that here.
38  https://explorer.jito.wtf/bundle/0748de4fd7a60c419da9fb09781157ab08e7b0adfbd664193c91f51e49af5491
39  */
40  ixs.push(Instruction::new_with_borsh(
41    SOLANA_PROGRAMS.compute_budget_program,
42    &ComputeBudgetInstructionIdl::new(compute_unit_budget),
43    vec![AccountMeta::new_readonly(JITO_DONT_FRONT_ACCOUNT, false)],
44  ));
45  // Add a reasonable priority fee if there is no jito tip and push regular limit otherwise
46  // println!("Compute budget being used: {}", compute_unit_budget);
47  if !use_jito {
48    ixs.push(ComputeBudgetInstruction::set_compute_unit_price(400000));
49  }
50  ixs.extend(swap_instructions);
51  if use_jito && jito_tip_lp > 0 {
52    ixs.push(transfer(&wallet_pubkey, &JITO_TIP_ACCOUNTS[0], jito_tip_lp));
53  }
54  let blockhash = central_context.latest_blockhash.read().unwrap().clone();
55  let message = solana_sdk::message::Message::new(&ixs, Some(&wallet_pubkey));
56  Transaction::new(&[&wallet_keypair], message, blockhash)
57}