From 31b5e2855ba39069b964a9808f8fb562739f4b05 Mon Sep 17 00:00:00 2001 From: ysq Date: Mon, 8 Sep 2025 10:58:43 +0800 Subject: [PATCH] perf: optimize constants and memory allocation for trading instruction performance --- src/common/bonding_curve.rs | 14 ++- src/constants/accounts.rs | 37 ++++++ src/constants/mod.rs | 23 +--- src/instruction/bonk.rs | 28 ++--- src/instruction/pumpfun.rs | 147 +++++++++++------------- src/instruction/pumpswap.rs | 36 +++--- src/instruction/raydium_amm_v4.rs | 8 +- src/instruction/raydium_cpmm.rs | 16 +-- src/instruction/utils/bonk.rs | 36 +++--- src/instruction/utils/pumpfun.rs | 107 ++++++++++------- src/instruction/utils/pumpswap.rs | 93 ++++++++------- src/instruction/utils/raydium_amm_v4.rs | 10 +- src/instruction/utils/raydium_cpmm.rs | 20 ++-- 13 files changed, 314 insertions(+), 261 deletions(-) create mode 100644 src/constants/accounts.rs diff --git a/src/common/bonding_curve.rs b/src/common/bonding_curve.rs index b3a7b01..657cb86 100755 --- a/src/common/bonding_curve.rs +++ b/src/common/bonding_curve.rs @@ -65,9 +65,14 @@ impl BondingCurveAccount { dev_sol_amount: u64, creator: Pubkey, ) -> Self { + let account = if mint != &Pubkey::default() { + get_bonding_curve_pda(mint).unwrap() + } else { + Pubkey::default() + }; Self { discriminator: 0, - account: get_bonding_curve_pda(mint).unwrap(), + account: account, virtual_token_reserves: INITIAL_VIRTUAL_TOKEN_RESERVES - dev_token_amount, virtual_sol_reserves: INITIAL_VIRTUAL_SOL_RESERVES + dev_sol_amount, real_token_reserves: INITIAL_REAL_TOKEN_RESERVES - dev_token_amount, @@ -79,9 +84,14 @@ impl BondingCurveAccount { } pub fn from_trade(event: &PumpFunTradeEvent) -> Self { + let account = if event.bonding_curve != Pubkey::default() { + event.bonding_curve + } else { + get_bonding_curve_pda(&event.mint).unwrap() + }; Self { discriminator: 0, - account: get_bonding_curve_pda(&event.mint).unwrap(), + account: account, virtual_token_reserves: event.virtual_token_reserves, virtual_sol_reserves: event.virtual_sol_reserves, real_token_reserves: event.real_token_reserves, diff --git a/src/constants/accounts.rs b/src/constants/accounts.rs new file mode 100644 index 0000000..26752b6 --- /dev/null +++ b/src/constants/accounts.rs @@ -0,0 +1,37 @@ +use solana_sdk::{pubkey, pubkey::Pubkey}; + +pub const SYSTEM_PROGRAM: Pubkey = solana_sdk::system_program::ID; +pub const SYSTEM_PROGRAM_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: SYSTEM_PROGRAM, + is_signer: false, + is_writable: false, + }; + +pub const TOKEN_PROGRAM: Pubkey = spl_token::ID; +pub const TOKEN_PROGRAM_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: TOKEN_PROGRAM, + is_signer: false, + is_writable: false, + }; + +pub const TOKEN_PROGRAM_2022: Pubkey = spl_token_2022::ID; +pub const TOKEN_PROGRAM_2022_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: TOKEN_PROGRAM_2022, + is_signer: false, + is_writable: false, + }; + +pub const WSOL_TOKEN_ACCOUNT: Pubkey = pubkey!("So11111111111111111111111111111111111111112"); +pub const WSOL_TOKEN_ACCOUNT_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: WSOL_TOKEN_ACCOUNT, + is_signer: false, + is_writable: false, + }; + +pub const RENT: Pubkey = solana_sdk::sysvar::rent::id(); +pub const RENT_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { pubkey: RENT, is_signer: false, is_writable: false }; diff --git a/src/constants/mod.rs b/src/constants/mod.rs index 20f5c5f..2249453 100755 --- a/src/constants/mod.rs +++ b/src/constants/mod.rs @@ -1,26 +1,7 @@ -use solana_sdk::{pubkey, pubkey::Pubkey}; - +pub mod accounts; pub mod decimals; pub mod swqos; pub mod trade; pub mod trade_platform; -pub const SYSTEM_PROGRAM: Pubkey = solana_sdk::system_program::ID; -pub const SYSTEM_PROGRAM_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(SYSTEM_PROGRAM, false) - }); - -pub const TOKEN_PROGRAM: Pubkey = spl_token::ID; -pub const TOKEN_PROGRAM_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(TOKEN_PROGRAM, false) - }); - -pub const TOKEN_PROGRAM_2022: Pubkey = spl_token_2022::ID; - -pub const WSOL_TOKEN_ACCOUNT: Pubkey = pubkey!("So11111111111111111111111111111111111111112"); -pub const WSOL_TOKEN_ACCOUNT_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(WSOL_TOKEN_ACCOUNT, false) - }); +pub use accounts::*; diff --git a/src/instruction/bonk.rs b/src/instruction/bonk.rs index 22facf2..ab9fac7 100755 --- a/src/instruction/bonk.rs +++ b/src/instruction/bonk.rs @@ -109,8 +109,8 @@ impl InstructionBuilder for BonkInstructionBuilder { // Create buy instruction let accounts = vec![ solana_sdk::instruction::AccountMeta::new(params.payer.pubkey(), true), // Payer (signer) - accounts::AUTHORITY_META.clone(), // Authority (readonly) - accounts::GLOBAL_CONFIG_META.clone(), // Global Config (readonly) + accounts::AUTHORITY_META, // Authority (readonly) + accounts::GLOBAL_CONFIG_META, // Global Config (readonly) solana_sdk::instruction::AccountMeta::new_readonly( protocol_params.platform_config, false, @@ -121,15 +121,15 @@ impl InstructionBuilder for BonkInstructionBuilder { solana_sdk::instruction::AccountMeta::new(base_vault_account, false), // Base Vault solana_sdk::instruction::AccountMeta::new(quote_vault_account, false), // Quote Vault solana_sdk::instruction::AccountMeta::new_readonly(params.mint, false), // Base Token Mint (readonly) - crate::constants::WSOL_TOKEN_ACCOUNT_META.clone(), // Quote Token Mint (readonly) + crate::constants::WSOL_TOKEN_ACCOUNT_META, // Quote Token Mint (readonly) solana_sdk::instruction::AccountMeta::new_readonly( protocol_params.mint_token_program, false, ), // Base Token Program (readonly) - crate::constants::TOKEN_PROGRAM_META.clone(), // Quote Token Program (readonly) - accounts::EVENT_AUTHORITY_META.clone(), // Event Authority (readonly) - accounts::BONK_META.clone(), // Program (readonly) - crate::constants::SYSTEM_PROGRAM_META.clone(), // System Program (readonly) + crate::constants::TOKEN_PROGRAM_META, // Quote Token Program (readonly) + accounts::EVENT_AUTHORITY_META, // Event Authority (readonly) + accounts::BONK_META, // Program (readonly) + crate::constants::SYSTEM_PROGRAM_META, // System Program (readonly) solana_sdk::instruction::AccountMeta::new( protocol_params.platform_associated_account, false, @@ -243,8 +243,8 @@ impl InstructionBuilder for BonkInstructionBuilder { // Create sell instruction let accounts = vec![ solana_sdk::instruction::AccountMeta::new(params.payer.pubkey(), true), // Payer (signer) - accounts::AUTHORITY_META.clone(), // Authority (readonly) - accounts::GLOBAL_CONFIG_META.clone(), // Global Config (readonly) + accounts::AUTHORITY_META, // Authority (readonly) + accounts::GLOBAL_CONFIG_META, // Global Config (readonly) solana_sdk::instruction::AccountMeta::new_readonly( protocol_params.platform_config, false, @@ -255,15 +255,15 @@ impl InstructionBuilder for BonkInstructionBuilder { solana_sdk::instruction::AccountMeta::new(base_vault_account, false), // Base Vault solana_sdk::instruction::AccountMeta::new(quote_vault_account, false), // Quote Vault solana_sdk::instruction::AccountMeta::new_readonly(params.mint, false), // Base Token Mint (readonly) - crate::constants::WSOL_TOKEN_ACCOUNT_META.clone(), // Quote Token Mint (readonly) + crate::constants::WSOL_TOKEN_ACCOUNT_META, // Quote Token Mint (readonly) solana_sdk::instruction::AccountMeta::new_readonly( protocol_params.mint_token_program, false, ), // Base Token Program (readonly) - crate::constants::TOKEN_PROGRAM_META.clone(), // Quote Token Program (readonly) - accounts::EVENT_AUTHORITY_META.clone(), // Event Authority (readonly) - accounts::BONK_META.clone(), // Program (readonly) - crate::constants::SYSTEM_PROGRAM_META.clone(), // System Program (readonly) + crate::constants::TOKEN_PROGRAM_META, // Quote Token Program (readonly) + accounts::EVENT_AUTHORITY_META, // Event Authority (readonly) + accounts::BONK_META, // Program (readonly) + crate::constants::SYSTEM_PROGRAM_META, // System Program (readonly) solana_sdk::instruction::AccountMeta::new( protocol_params.platform_associated_account, false, diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index 459f56f..2e71c55 100755 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -7,7 +7,7 @@ use spl_token::instruction::close_account; use crate::{ instruction::utils::pumpfun::{ - accounts, get_bonding_curve_pda, get_creator_vault_pda, get_user_volume_accumulator_pda, + accounts, get_bonding_curve_pda, get_creator, get_user_volume_accumulator_pda, global_constants::{self}, }, utils::calc::{ @@ -16,7 +16,7 @@ use crate::{ }, }; -use solana_sdk::{instruction::AccountMeta, pubkey::Pubkey}; +use solana_sdk::instruction::AccountMeta; use crate::{ constants::trade::trade::DEFAULT_SLIPPAGE, @@ -50,21 +50,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { params.slippage_basis_points.unwrap_or(DEFAULT_SLIPPAGE), ); let creator_vault_pda = protocol_params.creator_vault; - - // Optimize creator lookup - avoid PDA calculation if not default - let creator = if creator_vault_pda == Pubkey::default() { - Pubkey::default() - } else { - // Fast check against cached default creator vault - static DEFAULT_CREATOR_VAULT: std::sync::LazyLock> = - std::sync::LazyLock::new(|| get_creator_vault_pda(&Pubkey::default())); - - if Some(creator_vault_pda) == *DEFAULT_CREATOR_VAULT { - Pubkey::default() - } else { - creator_vault_pda - } - }; + let creator = get_creator(&creator_vault_pda); let buy_token_amount = get_buy_token_amount_from_sol_amount( bonding_curve.virtual_token_reserves as u128, @@ -85,42 +71,44 @@ impl InstructionBuilder for PumpFunInstructionBuilder { )); // Create buy instruction data - let mut buy_data = Vec::with_capacity(8 + 8 + 8); - buy_data.extend_from_slice(&[102, 6, 61, 18, 1, 218, 235, 234]); // discriminator - buy_data.extend_from_slice(&buy_token_amount.to_le_bytes()); - buy_data.extend_from_slice(&max_sol_cost.to_le_bytes()); + let mut buy_data = [0u8; 24]; + buy_data[..8].copy_from_slice(&[102, 6, 61, 18, 1, 218, 235, 234]); + buy_data[8..16].copy_from_slice(&buy_token_amount.to_le_bytes()); + buy_data[16..24].copy_from_slice(&max_sol_cost.to_le_bytes()); + + let accounts: [AccountMeta; 16] = [ + global_constants::GLOBAL_ACCOUNT_META, + global_constants::FEE_RECIPIENT_META, + AccountMeta::new_readonly(params.mint, false), + AccountMeta::new(bonding_curve.account, false), + AccountMeta::new( + get_associated_token_address(&bonding_curve.account, ¶ms.mint), + false, + ), + AccountMeta::new( + get_associated_token_address(¶ms.payer.pubkey(), ¶ms.mint), + false, + ), + AccountMeta::new(params.payer.pubkey(), true), + crate::constants::SYSTEM_PROGRAM_META, + crate::constants::TOKEN_PROGRAM_META, + AccountMeta::new(creator_vault_pda, false), + accounts::EVENT_AUTHORITY_META, + accounts::PUMPFUN_META, + accounts::GLOBAL_VOLUME_ACCUMULATOR_META, + AccountMeta::new( + get_user_volume_accumulator_pda(¶ms.payer.pubkey()).unwrap(), + false, + ), + accounts::FEE_CONFIG_META, + accounts::FEE_PROGRAM_META, + ]; // Create buy instruction instructions.push(Instruction::new_with_bytes( accounts::PUMPFUN, &buy_data, - vec![ - global_constants::GLOBAL_ACCOUNT_META.clone(), - global_constants::FEE_RECIPIENT_META.clone(), - AccountMeta::new_readonly(params.mint, false), - AccountMeta::new(bonding_curve.account, false), - AccountMeta::new( - get_associated_token_address(&bonding_curve.account, ¶ms.mint), - false, - ), - AccountMeta::new( - get_associated_token_address(¶ms.payer.pubkey(), ¶ms.mint), - false, - ), - AccountMeta::new(params.payer.pubkey(), true), - crate::constants::SYSTEM_PROGRAM_META.clone(), - crate::constants::TOKEN_PROGRAM_META.clone(), - AccountMeta::new(creator_vault_pda, false), - accounts::EVENT_AUTHORITY_META.clone(), - accounts::PUMPFUN_META.clone(), - accounts::GLOBAL_VOLUME_ACCUMULATOR_META.clone(), - AccountMeta::new( - get_user_volume_accumulator_pda(¶ms.payer.pubkey()).unwrap(), - false, - ), - accounts::FEE_CONFIG_META.clone(), - accounts::FEE_PROGRAM_META.clone(), - ], + accounts.to_vec(), )); Ok(instructions) @@ -144,15 +132,9 @@ impl InstructionBuilder for PumpFunInstructionBuilder { } else { return Err(anyhow!("Amount token is required")); }; - let creator_vault_pda = protocol_params.creator_vault; let ata = get_associated_token_address(¶ms.payer.pubkey(), ¶ms.mint); - - let mut creator = Pubkey::default(); - if let Some(default_creator_ata) = get_creator_vault_pda(&creator) { - if default_creator_ata != creator_vault_pda { - creator = creator_vault_pda; - } - } + let creator_vault_pda = protocol_params.creator_vault; + let creator = get_creator(&creator_vault_pda); let sol_amount = get_sell_sol_amount_from_token_amount( bonding_curve.virtual_token_reserves as u128, @@ -166,37 +148,36 @@ impl InstructionBuilder for PumpFunInstructionBuilder { ); // Create sell instruction data - let mut sell_data = Vec::with_capacity(8 + 8 + 8); - sell_data.extend_from_slice(&[51, 230, 133, 164, 1, 127, 131, 173]); // discriminator - sell_data.extend_from_slice(&token_amount.to_le_bytes()); - sell_data.extend_from_slice(&min_sol_output.to_le_bytes()); + let mut sell_data = [0u8; 24]; + sell_data[..8].copy_from_slice(&[51, 230, 133, 164, 1, 127, 131, 173]); + sell_data[8..16].copy_from_slice(&token_amount.to_le_bytes()); + sell_data[16..24].copy_from_slice(&min_sol_output.to_le_bytes()); let bonding_curve = get_bonding_curve_pda(¶ms.mint).unwrap(); + let accounts: [AccountMeta; 14] = [ + global_constants::GLOBAL_ACCOUNT_META, + global_constants::FEE_RECIPIENT_META, + AccountMeta::new_readonly(params.mint, false), + AccountMeta::new(bonding_curve, false), + AccountMeta::new(get_associated_token_address(&bonding_curve, ¶ms.mint), false), + AccountMeta::new( + get_associated_token_address(¶ms.payer.pubkey(), ¶ms.mint), + false, + ), + AccountMeta::new(params.payer.pubkey(), true), + crate::constants::SYSTEM_PROGRAM_META, + AccountMeta::new(creator_vault_pda, false), + crate::constants::TOKEN_PROGRAM_META, + accounts::EVENT_AUTHORITY_META, + accounts::PUMPFUN_META, + accounts::FEE_CONFIG_META, + accounts::FEE_PROGRAM_META, + ]; + // Create sell instruction - let mut instructions = vec![Instruction::new_with_bytes( - accounts::PUMPFUN, - &sell_data, - vec![ - global_constants::GLOBAL_ACCOUNT_META.clone(), - global_constants::FEE_RECIPIENT_META.clone(), - AccountMeta::new_readonly(params.mint, false), - AccountMeta::new(bonding_curve, false), - AccountMeta::new(get_associated_token_address(&bonding_curve, ¶ms.mint), false), - AccountMeta::new( - get_associated_token_address(¶ms.payer.pubkey(), ¶ms.mint), - false, - ), - AccountMeta::new(params.payer.pubkey(), true), - crate::constants::SYSTEM_PROGRAM_META.clone(), - AccountMeta::new(creator_vault_pda, false), - crate::constants::TOKEN_PROGRAM_META.clone(), - accounts::EVENT_AUTHORITY_META.clone(), - accounts::PUMPFUN_META.clone(), - accounts::FEE_CONFIG_META.clone(), - accounts::FEE_PROGRAM_META.clone(), - ], - )]; + let mut instructions = + vec![Instruction::new_with_bytes(accounts::PUMPFUN, &sell_data, accounts.to_vec())]; // If selling all tokens, close the account if protocol_params.close_token_account_when_sell.unwrap_or(false) { diff --git a/src/instruction/pumpswap.rs b/src/instruction/pumpswap.rs index fee930d..69b3c7f 100755 --- a/src/instruction/pumpswap.rs +++ b/src/instruction/pumpswap.rs @@ -175,21 +175,21 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { let mut accounts = vec![ solana_sdk::instruction::AccountMeta::new_readonly(pool, false), // pool_id (readonly) solana_sdk::instruction::AccountMeta::new(params.payer.pubkey(), true), // user (signer) - accounts::GLOBAL_ACCOUNT_META.clone(), // global (readonly) + accounts::GLOBAL_ACCOUNT_META, // global (readonly) solana_sdk::instruction::AccountMeta::new_readonly(base_mint, false), // base_mint (readonly) solana_sdk::instruction::AccountMeta::new_readonly(quote_mint, false), // quote_mint (readonly) solana_sdk::instruction::AccountMeta::new(user_base_token_account, false), // user_base_token_account solana_sdk::instruction::AccountMeta::new(user_quote_token_account, false), // user_quote_token_account solana_sdk::instruction::AccountMeta::new(pool_base_token_account, false), // pool_base_token_account solana_sdk::instruction::AccountMeta::new(pool_quote_token_account, false), // pool_quote_token_account - accounts::FEE_RECIPIENT_META.clone(), // fee_recipient (readonly) + accounts::FEE_RECIPIENT_META, // fee_recipient (readonly) solana_sdk::instruction::AccountMeta::new(fee_recipient_ata, false), // fee_recipient_ata solana_sdk::instruction::AccountMeta::new_readonly(base_token_program, false), // TOKEN_PROGRAM_ID (readonly) solana_sdk::instruction::AccountMeta::new_readonly(quote_token_program, false), // TOKEN_PROGRAM_ID (readonly, duplicated as in JS) - crate::constants::SYSTEM_PROGRAM_META.clone(), // System Program (readonly) - accounts::ASSOCIATED_TOKEN_PROGRAM_META.clone(), // ASSOCIATED_TOKEN_PROGRAM_ID (readonly) - accounts::EVENT_AUTHORITY_META.clone(), // event_authority (readonly) - accounts::AMM_PROGRAM_META.clone(), // PUMP_AMM_PROGRAM_ID (readonly) + crate::constants::SYSTEM_PROGRAM_META, // System Program (readonly) + accounts::ASSOCIATED_TOKEN_PROGRAM_META, // ASSOCIATED_TOKEN_PROGRAM_ID (readonly) + accounts::EVENT_AUTHORITY_META, // event_authority (readonly) + accounts::AMM_PROGRAM_META, // PUMP_AMM_PROGRAM_ID (readonly) solana_sdk::instruction::AccountMeta::new(params_coin_creator_vault_ata, false), // coin_creator_vault_ata solana_sdk::instruction::AccountMeta::new_readonly( params_coin_creator_vault_authority, @@ -197,14 +197,14 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { ), // coin_creator_vault_authority (readonly) ]; if quote_mint_is_wsol { - accounts.push(accounts::GLOBAL_VOLUME_ACCUMULATOR_META.clone()); + accounts.push(accounts::GLOBAL_VOLUME_ACCUMULATOR_META); accounts.push(solana_sdk::instruction::AccountMeta::new( get_user_volume_accumulator_pda(¶ms.payer.pubkey()).unwrap(), false, )); } - accounts.push(accounts::FEE_CONFIG_META.clone()); - accounts.push(accounts::FEE_PROGRAM_META.clone()); + accounts.push(accounts::FEE_CONFIG_META); + accounts.push(accounts::FEE_PROGRAM_META); // Create instruction data let mut data = vec![]; @@ -366,21 +366,21 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { let mut accounts = vec![ solana_sdk::instruction::AccountMeta::new_readonly(pool, false), // pool_id (readonly) solana_sdk::instruction::AccountMeta::new(params.payer.pubkey(), true), // user (signer) - accounts::GLOBAL_ACCOUNT_META.clone(), // global (readonly) + accounts::GLOBAL_ACCOUNT_META, // global (readonly) solana_sdk::instruction::AccountMeta::new_readonly(base_mint, false), // mint (readonly) solana_sdk::instruction::AccountMeta::new_readonly(quote_mint, false), // WSOL_TOKEN_ACCOUNT (readonly) solana_sdk::instruction::AccountMeta::new(user_base_token_account, false), // user_base_token_account solana_sdk::instruction::AccountMeta::new(user_quote_token_account, false), // user_quote_token_account solana_sdk::instruction::AccountMeta::new(pool_base_token_account, false), // pool_base_token_account solana_sdk::instruction::AccountMeta::new(pool_quote_token_account, false), // pool_quote_token_account - accounts::FEE_RECIPIENT_META.clone(), // fee_recipient (readonly) + accounts::FEE_RECIPIENT_META, // fee_recipient (readonly) solana_sdk::instruction::AccountMeta::new(fee_recipient_ata, false), // fee_recipient_ata solana_sdk::instruction::AccountMeta::new_readonly(base_token_program, false), // TOKEN_PROGRAM_ID (readonly) solana_sdk::instruction::AccountMeta::new_readonly(quote_token_program, false), // TOKEN_PROGRAM_ID (readonly, duplicated as in JS) - crate::constants::SYSTEM_PROGRAM_META.clone(), // System Program (readonly) - accounts::ASSOCIATED_TOKEN_PROGRAM_META.clone(), // ASSOCIATED_TOKEN_PROGRAM_ID (readonly) - accounts::EVENT_AUTHORITY_META.clone(), // event_authority (readonly) - accounts::AMM_PROGRAM_META.clone(), // PUMP_AMM_PROGRAM_ID (readonly) + crate::constants::SYSTEM_PROGRAM_META, // System Program (readonly) + accounts::ASSOCIATED_TOKEN_PROGRAM_META, // ASSOCIATED_TOKEN_PROGRAM_ID (readonly) + accounts::EVENT_AUTHORITY_META, // event_authority (readonly) + accounts::AMM_PROGRAM_META, // PUMP_AMM_PROGRAM_ID (readonly) solana_sdk::instruction::AccountMeta::new(params_coin_creator_vault_ata, false), // coin_creator_vault_ata solana_sdk::instruction::AccountMeta::new_readonly( params_coin_creator_vault_authority, @@ -388,15 +388,15 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { ), // coin_creator_vault_authority (readonly) ]; if !quote_mint_is_wsol { - accounts.push(accounts::GLOBAL_VOLUME_ACCUMULATOR_META.clone()); + accounts.push(accounts::GLOBAL_VOLUME_ACCUMULATOR_META); accounts.push(solana_sdk::instruction::AccountMeta::new( get_user_volume_accumulator_pda(¶ms.payer.pubkey()).unwrap(), false, )); } - accounts.push(accounts::FEE_CONFIG_META.clone()); - accounts.push(accounts::FEE_PROGRAM_META.clone()); + accounts.push(accounts::FEE_CONFIG_META); + accounts.push(accounts::FEE_PROGRAM_META); // Create instruction data let mut data = vec![]; diff --git a/src/instruction/raydium_amm_v4.rs b/src/instruction/raydium_amm_v4.rs index e4e98a2..93414df 100755 --- a/src/instruction/raydium_amm_v4.rs +++ b/src/instruction/raydium_amm_v4.rs @@ -93,9 +93,9 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { // Create buy instruction let accounts = vec![ - crate::constants::TOKEN_PROGRAM_META.clone(), // Token Program (readonly) + crate::constants::TOKEN_PROGRAM_META, // Token Program (readonly) solana_sdk::instruction::AccountMeta::new(protocol_params.amm, false), // Amm - accounts::AUTHORITY_META.clone(), // Authority (readonly) + accounts::AUTHORITY_META, // Authority (readonly) solana_sdk::instruction::AccountMeta::new(protocol_params.amm, false), // Amm Open Orders solana_sdk::instruction::AccountMeta::new(protocol_params.token_coin, false), // Pool Coin Token Account solana_sdk::instruction::AccountMeta::new(protocol_params.token_pc, false), // Pool Pc Token Account @@ -187,9 +187,9 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { // Create buy instruction let accounts = vec![ - crate::constants::TOKEN_PROGRAM_META.clone(), // Token Program (readonly) + crate::constants::TOKEN_PROGRAM_META, // Token Program (readonly) solana_sdk::instruction::AccountMeta::new(protocol_params.amm, false), // Amm - accounts::AUTHORITY_META.clone(), // Authority (readonly) + accounts::AUTHORITY_META, // Authority (readonly) solana_sdk::instruction::AccountMeta::new(protocol_params.amm, false), // Amm Open Orders solana_sdk::instruction::AccountMeta::new(protocol_params.token_coin, false), // Pool Coin Token Account solana_sdk::instruction::AccountMeta::new(protocol_params.token_pc, false), // Pool Pc Token Account diff --git a/src/instruction/raydium_cpmm.rs b/src/instruction/raydium_cpmm.rs index 20a2f99..37ae419 100755 --- a/src/instruction/raydium_cpmm.rs +++ b/src/instruction/raydium_cpmm.rs @@ -112,16 +112,16 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { // Create buy instruction let accounts = vec![ solana_sdk::instruction::AccountMeta::new(params.payer.pubkey(), true), // Payer (signer) - accounts::AUTHORITY_META.clone(), // Authority (readonly) - accounts::AMM_CONFIG_META.clone(), // Amm Config (readonly) + accounts::AUTHORITY_META, // Authority (readonly) + accounts::AMM_CONFIG_META, // Amm Config (readonly) solana_sdk::instruction::AccountMeta::new(pool_state, false), // Pool State solana_sdk::instruction::AccountMeta::new(wsol_token_account, false), // Input Token Account solana_sdk::instruction::AccountMeta::new(mint_token_account, false), // Output Token Account solana_sdk::instruction::AccountMeta::new(wsol_vault_account, false), // Input Vault Account solana_sdk::instruction::AccountMeta::new(mint_vault_account, false), // Output Vault Account - crate::constants::TOKEN_PROGRAM_META.clone(), // Input Token Program (readonly) + crate::constants::TOKEN_PROGRAM_META, // Input Token Program (readonly) solana_sdk::instruction::AccountMeta::new_readonly(mint_token_program, false), // Output Token Program (readonly) - crate::constants::WSOL_TOKEN_ACCOUNT_META.clone(), // Input token mint (readonly) + crate::constants::WSOL_TOKEN_ACCOUNT_META, // Input token mint (readonly) solana_sdk::instruction::AccountMeta::new_readonly(params.mint, false), // Output token mint (readonly) solana_sdk::instruction::AccountMeta::new(observation_state_account, false), // Observation State Account ]; @@ -218,17 +218,17 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { // Create sell instruction let accounts = vec![ solana_sdk::instruction::AccountMeta::new(params.payer.pubkey(), true), // Payer (signer) - accounts::AUTHORITY_META.clone(), // Authority (readonly) - accounts::AMM_CONFIG_META.clone(), // Amm Config (readonly) + accounts::AUTHORITY_META, // Authority (readonly) + accounts::AMM_CONFIG_META, // Amm Config (readonly) solana_sdk::instruction::AccountMeta::new(pool_state, false), // Pool State solana_sdk::instruction::AccountMeta::new(mint_token_account, false), // Input Token Account solana_sdk::instruction::AccountMeta::new(wsol_token_account, false), // Output Token Account solana_sdk::instruction::AccountMeta::new(mint_vault_account, false), // Input Vault Account solana_sdk::instruction::AccountMeta::new(wsol_vault_account, false), // Output Vault Account solana_sdk::instruction::AccountMeta::new_readonly(mint_token_program, false), // Input Token Program (readonly) - crate::constants::TOKEN_PROGRAM_META.clone(), // Output Token Program (readonly) + crate::constants::TOKEN_PROGRAM_META, // Output Token Program (readonly) solana_sdk::instruction::AccountMeta::new_readonly(params.mint, false), // Input token mint (readonly) - crate::constants::WSOL_TOKEN_ACCOUNT_META.clone(), // Output token mint (readonly) + crate::constants::WSOL_TOKEN_ACCOUNT_META, // Output token mint (readonly) solana_sdk::instruction::AccountMeta::new(observation_state_account, false), // Observation State Account ]; // Create instruction data diff --git a/src/instruction/utils/bonk.rs b/src/instruction/utils/bonk.rs index 4a10137..cfedd15 100644 --- a/src/instruction/utils/bonk.rs +++ b/src/instruction/utils/bonk.rs @@ -25,22 +25,26 @@ pub mod accounts { pub const SHARE_FEE_RATE: u128 = 0; // 0% // META - pub const AUTHORITY_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(AUTHORITY, false) - }); - pub const GLOBAL_CONFIG_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(GLOBAL_CONFIG, false) - }); - pub const EVENT_AUTHORITY_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(EVENT_AUTHORITY, false) - }); - pub const BONK_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(BONK, false) - }); + pub const AUTHORITY_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: AUTHORITY, + is_signer: false, + is_writable: false, + }; + pub const GLOBAL_CONFIG_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: GLOBAL_CONFIG, + is_signer: false, + is_writable: false, + }; + pub const EVENT_AUTHORITY_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: EVENT_AUTHORITY, + is_signer: false, + is_writable: false, + }; + pub const BONK_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { pubkey: BONK, is_signer: false, is_writable: false }; } pub const BUY_EXECT_IN_DISCRIMINATOR: [u8; 8] = [250, 234, 13, 123, 213, 156, 19, 236]; diff --git a/src/instruction/utils/pumpfun.rs b/src/instruction/utils/pumpfun.rs index 29ae3b2..3498581 100644 --- a/src/instruction/utils/pumpfun.rs +++ b/src/instruction/utils/pumpfun.rs @@ -51,7 +51,7 @@ pub mod global_constants { pub const POOL_MIGRATION_FEE: u64 = 15_000_001; - pub const CREATOR_FEE: u64 = 5; + pub const CREATOR_FEE: u64 = 30; pub const SCALE: u64 = 1_000_000; // 10^6 for token decimals @@ -61,19 +61,21 @@ pub mod global_constants { /// Public key for the fee recipient pub const FEE_RECIPIENT: Pubkey = pubkey!("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"); - /// Static AccountMeta for fee recipient (initialized once) - pub static FEE_RECIPIENT_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new(FEE_RECIPIENT, false) - }); + pub const FEE_RECIPIENT_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: FEE_RECIPIENT, + is_signer: false, + is_writable: true, + }; /// Public key for the global PDA pub const GLOBAL_ACCOUNT: Pubkey = pubkey!("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"); - /// Static AccountMeta for global account (initialized once) - pub static GLOBAL_ACCOUNT_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(GLOBAL_ACCOUNT, false) - }); + pub const GLOBAL_ACCOUNT_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: GLOBAL_ACCOUNT, + is_signer: false, + is_writable: false, + }; /// Public key for the authority pub const AUTHORITY: Pubkey = pubkey!("FFWtrEQ4B4PKQoVuHYzZq8FabGkVatYzDpEVHsK5rrhF"); @@ -95,10 +97,6 @@ pub mod global_constants { pub mod accounts { use solana_sdk::{pubkey, pubkey::Pubkey}; - use crate::instruction::utils::pumpfun::{ - get_fee_config_pda, get_global_volume_accumulator_pda, - }; - /// Public key for the Pump.fun program pub const PUMPFUN: Pubkey = pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"); @@ -112,43 +110,50 @@ pub mod accounts { pub const ASSOCIATED_TOKEN_PROGRAM: Pubkey = pubkey!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"); - /// Rent Sysvar ID - pub const RENT: Pubkey = pubkey!("SysvarRent111111111111111111111111111111111"); - pub const AMM_PROGRAM: Pubkey = pubkey!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); pub const FEE_PROGRAM: Pubkey = pubkey!("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"); + pub const GLOBAL_VOLUME_ACCUMULATOR: Pubkey = + pubkey!("Hq2wp8uJ9jCPsYgNHex8RtqdvMPfVGoYwjvF1ATiwn2Y"); // get_global_volume_accumulator_pda().unwrap(); + + pub const FEE_CONFIG: Pubkey = pubkey!("8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt"); // get_fee_config_pda().unwrap(); + // META + pub const PUMPFUN_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: PUMPFUN, + is_signer: false, + is_writable: false, + }; - pub const PUMPFUN_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(PUMPFUN, false) - }); + pub const EVENT_AUTHORITY_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: EVENT_AUTHORITY, + is_signer: false, + is_writable: false, + }; - pub const EVENT_AUTHORITY_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(EVENT_AUTHORITY, false) - }); + pub const FEE_PROGRAM_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: FEE_PROGRAM, + is_signer: false, + is_writable: false, + }; - pub const FEE_PROGRAM_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(FEE_PROGRAM, false) - }); + pub const GLOBAL_VOLUME_ACCUMULATOR_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: GLOBAL_VOLUME_ACCUMULATOR, + is_signer: false, + is_writable: true, + }; - pub const GLOBAL_VOLUME_ACCUMULATOR_META: once_cell::sync::Lazy< - solana_sdk::instruction::AccountMeta, - > = once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new( - get_global_volume_accumulator_pda().unwrap(), - false, - ) - }); - - pub const FEE_CONFIG_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(get_fee_config_pda().unwrap(), false) - }); + pub const FEE_CONFIG_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: FEE_CONFIG, + is_signer: false, + is_writable: false, + }; } pub struct Symbol; @@ -185,6 +190,22 @@ pub fn get_bonding_curve_pda(mint: &Pubkey) -> Option { pda.map(|pubkey| pubkey.0) } +#[inline] +pub fn get_creator(creator_vault_pda: &Pubkey) -> Pubkey { + if creator_vault_pda.eq(&Pubkey::default()) { + Pubkey::default() + } else { + // Fast check against cached default creator vault + static DEFAULT_CREATOR_VAULT: std::sync::LazyLock> = + std::sync::LazyLock::new(|| get_creator_vault_pda(&Pubkey::default())); + if creator_vault_pda.eq(&DEFAULT_CREATOR_VAULT.unwrap()) { + Pubkey::default() + } else { + *creator_vault_pda + } + } +} + #[inline] pub fn get_creator_vault_pda(creator: &Pubkey) -> Option { let seeds: &[&[u8]; 2] = &[seeds::CREATOR_VAULT_SEED, creator.as_ref()]; diff --git a/src/instruction/utils/pumpswap.rs b/src/instruction/utils/pumpswap.rs index eaa381a..df2cd41 100644 --- a/src/instruction/utils/pumpswap.rs +++ b/src/instruction/utils/pumpswap.rs @@ -51,9 +51,6 @@ pub mod accounts { pub const PROTOCOL_FEE_RECIPIENT: Pubkey = pubkey!("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"); - /// Rent Sysvar ID - pub const RENT: Pubkey = pubkey!("SysvarRent111111111111111111111111111111111"); - pub const AMM_PROGRAM: Pubkey = pubkey!("pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"); pub const LP_FEE_BASIS_POINTS: u64 = 20; @@ -62,52 +59,68 @@ pub mod accounts { pub const FEE_PROGRAM: Pubkey = pubkey!("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"); + pub const GLOBAL_VOLUME_ACCUMULATOR: Pubkey = + pubkey!("C2aFPdENg4A2HQsmrd5rTw5TaYBX5Ku887cWjbFKtZpw"); // get_global_volume_accumulator_pda().unwrap(); + + pub const FEE_CONFIG: Pubkey = pubkey!("5PHirr8joyTMp9JMm6nW7hNDVyEYdkzDqazxPD7RaTjx"); // get_fee_config_pda().unwrap(); + // META - pub const GLOBAL_ACCOUNT_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(GLOBAL_ACCOUNT, false) - }); + pub const GLOBAL_ACCOUNT_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: GLOBAL_ACCOUNT, + is_signer: false, + is_writable: false, + }; - pub const FEE_RECIPIENT_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(FEE_RECIPIENT, false) - }); + pub const FEE_RECIPIENT_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: FEE_RECIPIENT, + is_signer: false, + is_writable: false, + }; - pub const ASSOCIATED_TOKEN_PROGRAM_META: once_cell::sync::Lazy< - solana_sdk::instruction::AccountMeta, - > = once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(ASSOCIATED_TOKEN_PROGRAM, false) - }); + pub const ASSOCIATED_TOKEN_PROGRAM_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: ASSOCIATED_TOKEN_PROGRAM, + is_signer: false, + is_writable: false, + }; - pub const EVENT_AUTHORITY_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(EVENT_AUTHORITY, false) - }); + pub const EVENT_AUTHORITY_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: EVENT_AUTHORITY, + is_signer: false, + is_writable: false, + }; - pub const AMM_PROGRAM_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(AMM_PROGRAM, false) - }); + pub const AMM_PROGRAM_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: AMM_PROGRAM, + is_signer: false, + is_writable: false, + }; - pub const GLOBAL_VOLUME_ACCUMULATOR_META: once_cell::sync::Lazy< - solana_sdk::instruction::AccountMeta, - > = once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new( - get_global_volume_accumulator_pda().unwrap(), - false, - ) - }); + pub const GLOBAL_VOLUME_ACCUMULATOR_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: GLOBAL_VOLUME_ACCUMULATOR, + is_signer: false, + is_writable: true, + }; - pub const FEE_CONFIG_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(get_fee_config_pda().unwrap(), false) - }); + pub const FEE_CONFIG_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: FEE_CONFIG, + is_signer: false, + is_writable: false, + }; - pub const FEE_PROGRAM_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(FEE_PROGRAM, false) - }); + pub const FEE_PROGRAM_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: FEE_PROGRAM, + is_signer: false, + is_writable: false, + }; } pub const BUY_DISCRIMINATOR: [u8; 8] = [102, 6, 61, 18, 1, 218, 235, 234]; diff --git a/src/instruction/utils/raydium_amm_v4.rs b/src/instruction/utils/raydium_amm_v4.rs index 05fc0e2..f871f9e 100644 --- a/src/instruction/utils/raydium_amm_v4.rs +++ b/src/instruction/utils/raydium_amm_v4.rs @@ -24,10 +24,12 @@ pub mod accounts { // META - pub const AUTHORITY_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(AUTHORITY, false) - }); + pub const AUTHORITY_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: AUTHORITY, + is_signer: false, + is_writable: false, + }; } pub const SWAP_BASE_IN_DISCRIMINATOR: &[u8] = &[9]; diff --git a/src/instruction/utils/raydium_cpmm.rs b/src/instruction/utils/raydium_cpmm.rs index 40df0da..1c8316e 100644 --- a/src/instruction/utils/raydium_cpmm.rs +++ b/src/instruction/utils/raydium_cpmm.rs @@ -24,15 +24,19 @@ pub mod accounts { pub const PROTOCOL_FEE_RATE: u64 = 120000; pub const FUND_FEE_RATE: u64 = 40000; // META - pub const AUTHORITY_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(AUTHORITY, false) - }); + pub const AUTHORITY_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: AUTHORITY, + is_signer: false, + is_writable: false, + }; - pub const AMM_CONFIG_META: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - solana_sdk::instruction::AccountMeta::new_readonly(AMM_CONFIG, false) - }); + pub const AMM_CONFIG_META: solana_sdk::instruction::AccountMeta = + solana_sdk::instruction::AccountMeta { + pubkey: AMM_CONFIG, + is_signer: false, + is_writable: false, + }; } pub const SWAP_BASE_IN_DISCRIMINATOR: &[u8] = &[143, 190, 90, 218, 196, 30, 51, 222];