From 544e65318d8b106c21d880286d8b7d2ffa4523d0 Mon Sep 17 00:00:00 2001 From: ysq Date: Sun, 7 Sep 2025 21:36:57 +0800 Subject: [PATCH] refactor: optimize AccountMeta creation with lazy static constants - Consolidate protocol constants to unified module - Pre-build AccountMeta objects using once_cell::Lazy - Reduce instruction building overhead across all DEX protocols - Improve code maintainability and performance --- examples/pumpswap_trading/src/main.rs | 8 +- examples/raydium_amm_v4_trading/src/main.rs | 2 +- examples/raydium_cpmm_trading/src/main.rs | 3 +- src/constants/mod.rs | 22 ++++++ src/instruction/bonk.rs | 54 ++++++------- src/instruction/pumpfun.rs | 43 ++++++----- src/instruction/pumpswap.rs | 84 +++++++++------------ src/instruction/raydium_amm_v4.rs | 41 +++++----- src/instruction/raydium_cpmm.rs | 47 ++++++------ src/instruction/utils/bonk.rs | 26 +++++-- src/instruction/utils/pumpfun.rs | 51 +++++++++++-- src/instruction/utils/pumpswap.rs | 68 ++++++++++++++--- src/instruction/utils/raydium_amm_v4.rs | 9 ++- src/instruction/utils/raydium_cpmm.rs | 13 +++- src/trading/common/utils.rs | 21 ++++-- src/trading/core/params.rs | 14 ++-- src/utils/price/bonk.rs | 2 +- 17 files changed, 323 insertions(+), 185 deletions(-) diff --git a/examples/pumpswap_trading/src/main.rs b/examples/pumpswap_trading/src/main.rs index 2602fc5..2bf5aaa 100644 --- a/examples/pumpswap_trading/src/main.rs +++ b/examples/pumpswap_trading/src/main.rs @@ -86,7 +86,7 @@ fn create_event_callback() -> impl Fn(Box) { |event: Box| { match_event!(event, { PumpSwapBuyEvent => |e: PumpSwapBuyEvent| { - if e.base_mint == accounts::WSOL_TOKEN_ACCOUNT || e.quote_mint == accounts::WSOL_TOKEN_ACCOUNT { + if e.base_mint == sol_trade_sdk::constants::WSOL_TOKEN_ACCOUNT || e.quote_mint == sol_trade_sdk::constants::WSOL_TOKEN_ACCOUNT { // Test code, only test one transaction if !ALREADY_EXECUTED.swap(true, Ordering::SeqCst) { let event_clone = e.clone(); @@ -100,7 +100,7 @@ fn create_event_callback() -> impl Fn(Box) { } }, PumpSwapSellEvent => |e: PumpSwapSellEvent| { - if e.base_mint == accounts::WSOL_TOKEN_ACCOUNT || e.quote_mint == accounts::WSOL_TOKEN_ACCOUNT { + if e.base_mint == sol_trade_sdk::constants::WSOL_TOKEN_ACCOUNT || e.quote_mint == sol_trade_sdk::constants::WSOL_TOKEN_ACCOUNT { // Test code, only test one transaction if !ALREADY_EXECUTED.swap(true, Ordering::SeqCst) { let event_clone = e.clone(); @@ -147,7 +147,7 @@ async fn create_solana_trade_client() -> AnyResult { async fn pumpswap_trade_with_grpc_buy_event(trade_info: PumpSwapBuyEvent) -> AnyResult<()> { let params = PumpSwapParams::from_buy_trade(&trade_info); - let mint = if trade_info.base_mint == accounts::WSOL_TOKEN_ACCOUNT { + let mint = if trade_info.base_mint == sol_trade_sdk::constants::WSOL_TOKEN_ACCOUNT { trade_info.quote_mint } else { trade_info.base_mint @@ -158,7 +158,7 @@ async fn pumpswap_trade_with_grpc_buy_event(trade_info: PumpSwapBuyEvent) -> Any async fn pumpswap_trade_with_grpc_sell_event(trade_info: PumpSwapSellEvent) -> AnyResult<()> { let params = PumpSwapParams::from_sell_trade(&trade_info); - let mint = if trade_info.base_mint == accounts::WSOL_TOKEN_ACCOUNT { + let mint = if trade_info.base_mint == sol_trade_sdk::constants::WSOL_TOKEN_ACCOUNT { trade_info.quote_mint } else { trade_info.base_mint diff --git a/examples/raydium_amm_v4_trading/src/main.rs b/examples/raydium_amm_v4_trading/src/main.rs index 687e97b..69bf04a 100644 --- a/examples/raydium_amm_v4_trading/src/main.rs +++ b/examples/raydium_amm_v4_trading/src/main.rs @@ -134,7 +134,7 @@ async fn raydium_amm_v4_copy_trade_with_grpc(trade_info: RaydiumAmmV4SwapEvent) let amm_info = fetch_amm_info(&client.rpc, trade_info.amm).await?; let (coin_reserve, pc_reserve) = get_multi_token_balances(&client.rpc, &amm_info.token_coin, &amm_info.token_pc).await?; - let mint_pubkey = if amm_info.pc_mint == accounts::WSOL_TOKEN_ACCOUNT { + let mint_pubkey = if amm_info.pc_mint == sol_trade_sdk::constants::WSOL_TOKEN_ACCOUNT { amm_info.coin_mint } else { amm_info.pc_mint diff --git a/examples/raydium_cpmm_trading/src/main.rs b/examples/raydium_cpmm_trading/src/main.rs index e81f10b..9bd7440 100644 --- a/examples/raydium_cpmm_trading/src/main.rs +++ b/examples/raydium_cpmm_trading/src/main.rs @@ -138,7 +138,8 @@ async fn raydium_cpmm_copy_trade_with_grpc(trade_info: RaydiumCpmmSwapEvent) -> println!("Testing Raydium_cpmm trading..."); let client = create_solana_trade_client().await?; - let mint_pubkey = if trade_info.input_token_mint == accounts::WSOL_TOKEN_ACCOUNT { + let mint_pubkey = if trade_info.input_token_mint == sol_trade_sdk::constants::WSOL_TOKEN_ACCOUNT + { trade_info.output_token_mint } else { trade_info.input_token_mint diff --git a/src/constants/mod.rs b/src/constants/mod.rs index 37a7081..20f5c5f 100755 --- a/src/constants/mod.rs +++ b/src/constants/mod.rs @@ -1,4 +1,26 @@ +use solana_sdk::{pubkey, pubkey::Pubkey}; + 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) + }); diff --git a/src/instruction/bonk.rs b/src/instruction/bonk.rs index 9345f9f..22facf2 100755 --- a/src/instruction/bonk.rs +++ b/src/instruction/bonk.rs @@ -37,7 +37,7 @@ impl InstructionBuilder for BonkInstructionBuilder { .downcast_ref::() .ok_or_else(|| anyhow!("Invalid protocol params for Bonk"))?; - let pool_state = get_pool_pda(¶ms.mint, &accounts::WSOL_TOKEN_ACCOUNT).unwrap(); + let pool_state = get_pool_pda(¶ms.mint, &crate::constants::WSOL_TOKEN_ACCOUNT).unwrap(); // Create user token accounts let user_base_token_account = spl_associated_token_account::get_associated_token_address( @@ -46,13 +46,13 @@ impl InstructionBuilder for BonkInstructionBuilder { ); let user_quote_token_account = spl_associated_token_account::get_associated_token_address( ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, + &crate::constants::WSOL_TOKEN_ACCOUNT, ); // Get pool token accounts let base_vault_account = get_vault_pda(&pool_state, ¶ms.mint).unwrap(); let quote_vault_account = - get_vault_pda(&pool_state, &accounts::WSOL_TOKEN_ACCOUNT).unwrap(); + get_vault_pda(&pool_state, &crate::constants::WSOL_TOKEN_ACCOUNT).unwrap(); let virtual_base = protocol_params.virtual_base; let virtual_quote = protocol_params.virtual_quote; @@ -79,8 +79,8 @@ impl InstructionBuilder for BonkInstructionBuilder { create_associated_token_account_idempotent( ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, - &accounts::TOKEN_PROGRAM, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, ), ); instructions.push( @@ -91,7 +91,7 @@ impl InstructionBuilder for BonkInstructionBuilder { // Sync wSOL balance instructions.push( spl_token::instruction::sync_native( - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, &user_quote_token_account, ) .unwrap(), @@ -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) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::AUTHORITY, false), // Authority (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::GLOBAL_CONFIG, false), // Global Config (readonly) + accounts::AUTHORITY_META.clone(), // Authority (readonly) + accounts::GLOBAL_CONFIG_META.clone(), // 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) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::WSOL_TOKEN_ACCOUNT, false), // Quote Token Mint (readonly) + crate::constants::WSOL_TOKEN_ACCOUNT_META.clone(), // Quote Token Mint (readonly) solana_sdk::instruction::AccountMeta::new_readonly( protocol_params.mint_token_program, false, ), // Base Token Program (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::TOKEN_PROGRAM, false), // Quote Token Program (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::EVENT_AUTHORITY, false), // Event Authority (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::BONK, false), // Program (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::SYSTEM_PROGRAM, false), // System 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) solana_sdk::instruction::AccountMeta::new( protocol_params.platform_associated_account, false, @@ -152,7 +152,7 @@ impl InstructionBuilder for BonkInstructionBuilder { // Close wSOL ATA account, reclaim rent instructions.push( spl_token::instruction::close_account( - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, &user_quote_token_account, ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), @@ -191,7 +191,7 @@ impl InstructionBuilder for BonkInstructionBuilder { return Err(anyhow!("Amount cannot be zero")); } - let pool_state = get_pool_pda(¶ms.mint, &accounts::WSOL_TOKEN_ACCOUNT).unwrap(); + let pool_state = get_pool_pda(¶ms.mint, &crate::constants::WSOL_TOKEN_ACCOUNT).unwrap(); let virtual_base = protocol_params.virtual_base; let virtual_quote = protocol_params.virtual_quote; @@ -217,13 +217,13 @@ impl InstructionBuilder for BonkInstructionBuilder { ); let user_quote_token_account = spl_associated_token_account::get_associated_token_address( ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, + &crate::constants::WSOL_TOKEN_ACCOUNT, ); // Get pool token accounts let base_vault_account = get_vault_pda(&pool_state, ¶ms.mint).unwrap(); let quote_vault_account = - get_vault_pda(&pool_state, &accounts::WSOL_TOKEN_ACCOUNT).unwrap(); + get_vault_pda(&pool_state, &crate::constants::WSOL_TOKEN_ACCOUNT).unwrap(); let share_fee_rate: u64 = 0; @@ -235,16 +235,16 @@ impl InstructionBuilder for BonkInstructionBuilder { create_associated_token_account_idempotent( ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, - &accounts::TOKEN_PROGRAM, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, ), ); // Create sell instruction let accounts = vec![ solana_sdk::instruction::AccountMeta::new(params.payer.pubkey(), true), // Payer (signer) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::AUTHORITY, false), // Authority (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::GLOBAL_CONFIG, false), // Global Config (readonly) + accounts::AUTHORITY_META.clone(), // Authority (readonly) + accounts::GLOBAL_CONFIG_META.clone(), // 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) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::WSOL_TOKEN_ACCOUNT, false), // Quote Token Mint (readonly) + crate::constants::WSOL_TOKEN_ACCOUNT_META.clone(), // Quote Token Mint (readonly) solana_sdk::instruction::AccountMeta::new_readonly( protocol_params.mint_token_program, false, ), // Base Token Program (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::TOKEN_PROGRAM, false), // Quote Token Program (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::EVENT_AUTHORITY, false), // Event Authority (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::BONK, false), // Program (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::SYSTEM_PROGRAM, false), // System 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) solana_sdk::instruction::AccountMeta::new( protocol_params.platform_associated_account, false, @@ -286,7 +286,7 @@ impl InstructionBuilder for BonkInstructionBuilder { if protocol_params.auto_handle_wsol { instructions.push( close_account( - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, &user_quote_token_account, ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index 8f1d59c..459f56f 100755 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -7,9 +7,8 @@ use spl_token::instruction::close_account; use crate::{ instruction::utils::pumpfun::{ - accounts, get_bonding_curve_pda, get_creator_vault_pda, get_fee_config_pda, - get_global_volume_accumulator_pda, get_user_volume_accumulator_pda, - global_constants::{self, FEE_RECIPIENT}, + accounts, get_bonding_curve_pda, get_creator_vault_pda, get_user_volume_accumulator_pda, + global_constants::{self}, }, utils::calc::{ common::{calculate_with_slippage_buy, calculate_with_slippage_sell}, @@ -82,7 +81,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), ¶ms.mint, - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, )); // Create buy instruction data @@ -96,8 +95,8 @@ impl InstructionBuilder for PumpFunInstructionBuilder { accounts::PUMPFUN, &buy_data, vec![ - AccountMeta::new_readonly(global_constants::GLOBAL_ACCOUNT, false), - AccountMeta::new(FEE_RECIPIENT, false), + 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( @@ -109,18 +108,18 @@ impl InstructionBuilder for PumpFunInstructionBuilder { false, ), AccountMeta::new(params.payer.pubkey(), true), - AccountMeta::new_readonly(accounts::SYSTEM_PROGRAM, false), - AccountMeta::new_readonly(accounts::TOKEN_PROGRAM, false), + crate::constants::SYSTEM_PROGRAM_META.clone(), + crate::constants::TOKEN_PROGRAM_META.clone(), AccountMeta::new(creator_vault_pda, false), - AccountMeta::new_readonly(accounts::EVENT_AUTHORITY, false), - AccountMeta::new_readonly(accounts::PUMPFUN, false), - AccountMeta::new(get_global_volume_accumulator_pda().unwrap(), 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, ), - AccountMeta::new_readonly(get_fee_config_pda().unwrap(), false), - AccountMeta::new_readonly(accounts::FEE_PROGRAM, false), + accounts::FEE_CONFIG_META.clone(), + accounts::FEE_PROGRAM_META.clone(), ], )); @@ -179,8 +178,8 @@ impl InstructionBuilder for PumpFunInstructionBuilder { accounts::PUMPFUN, &sell_data, vec![ - AccountMeta::new_readonly(global_constants::GLOBAL_ACCOUNT, false), - AccountMeta::new(FEE_RECIPIENT, false), + 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), @@ -189,20 +188,20 @@ impl InstructionBuilder for PumpFunInstructionBuilder { false, ), AccountMeta::new(params.payer.pubkey(), true), - AccountMeta::new_readonly(accounts::SYSTEM_PROGRAM, false), + crate::constants::SYSTEM_PROGRAM_META.clone(), AccountMeta::new(creator_vault_pda, false), - AccountMeta::new_readonly(accounts::TOKEN_PROGRAM, false), - AccountMeta::new_readonly(accounts::EVENT_AUTHORITY, false), - AccountMeta::new_readonly(accounts::PUMPFUN, false), - AccountMeta::new_readonly(get_fee_config_pda().unwrap(), false), - AccountMeta::new_readonly(accounts::FEE_PROGRAM, 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(), ], )]; // If selling all tokens, close the account if protocol_params.close_token_account_when_sell.unwrap_or(false) { instructions.push(close_account( - &spl_token::ID, + &crate::constants::TOKEN_PROGRAM, &ata, ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), diff --git a/src/instruction/pumpswap.rs b/src/instruction/pumpswap.rs index 3431cad..fee930d 100755 --- a/src/instruction/pumpswap.rs +++ b/src/instruction/pumpswap.rs @@ -7,9 +7,8 @@ use spl_token::instruction::close_account; use crate::{ constants::trade::trade::DEFAULT_SLIPPAGE, instruction::utils::pumpswap::{ - accounts, coin_creator_vault_ata, fee_recipient_ata, get_fee_config_pda, - get_global_volume_accumulator_pda, get_user_volume_accumulator_pda, BUY_DISCRIMINATOR, - SELL_DISCRIMINATOR, + accounts, coin_creator_vault_ata, fee_recipient_ata, get_user_volume_accumulator_pda, + BUY_DISCRIMINATOR, SELL_DISCRIMINATOR, }, trading::core::{ params::{BuyParams, PumpSwapParams, SellParams}, @@ -47,13 +46,15 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { let base_token_program = protocol_params.base_token_program; let quote_token_program = protocol_params.quote_token_program; - if base_mint != accounts::WSOL_TOKEN_ACCOUNT && quote_mint != accounts::WSOL_TOKEN_ACCOUNT { + if base_mint != crate::constants::WSOL_TOKEN_ACCOUNT + && quote_mint != crate::constants::WSOL_TOKEN_ACCOUNT + { return Err(anyhow!("Invalid base mint and quote mint")); } if params.rpc.is_none() { return Err(anyhow!("RPC is not set")); } - let quote_mint_is_wsol = quote_mint == accounts::WSOL_TOKEN_ACCOUNT; + let quote_mint_is_wsol = quote_mint == crate::constants::WSOL_TOKEN_ACCOUNT; let mut token_amount = 0; let mut sol_amount = 0; @@ -129,8 +130,8 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { create_associated_token_account_idempotent( ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, - &accounts::TOKEN_PROGRAM, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, ), ); instructions.push( @@ -149,7 +150,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { // Sync wSOL balance instructions.push( spl_token::instruction::sync_native( - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, if quote_mint_is_wsol { &user_quote_token_account } else { @@ -174,24 +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) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::GLOBAL_ACCOUNT, false), // global (readonly) + accounts::GLOBAL_ACCOUNT_META.clone(), // 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 - solana_sdk::instruction::AccountMeta::new_readonly(accounts::FEE_RECIPIENT, false), // fee_recipient (readonly) + accounts::FEE_RECIPIENT_META.clone(), // 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) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::SYSTEM_PROGRAM, false), // System Program (readonly) - solana_sdk::instruction::AccountMeta::new_readonly( - accounts::ASSOCIATED_TOKEN_PROGRAM, - false, - ), // ASSOCIATED_TOKEN_PROGRAM_ID (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::EVENT_AUTHORITY, false), // event_authority (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::AMM_PROGRAM, false), // PUMP_AMM_PROGRAM_ID (readonly) + 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) 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, @@ -199,19 +197,14 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { ), // coin_creator_vault_authority (readonly) ]; if quote_mint_is_wsol { - accounts.push(solana_sdk::instruction::AccountMeta::new( - get_global_volume_accumulator_pda().unwrap(), - false, - )); + accounts.push(accounts::GLOBAL_VOLUME_ACCUMULATOR_META.clone()); accounts.push(solana_sdk::instruction::AccountMeta::new( get_user_volume_accumulator_pda(¶ms.payer.pubkey()).unwrap(), false, )); } - accounts - .push(solana_sdk::instruction::AccountMeta::new(get_fee_config_pda().unwrap(), false)); - accounts - .push(solana_sdk::instruction::AccountMeta::new_readonly(accounts::FEE_PROGRAM, false)); + accounts.push(accounts::FEE_CONFIG_META.clone()); + accounts.push(accounts::FEE_PROGRAM_META.clone()); // Create instruction data let mut data = vec![]; @@ -234,7 +227,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { // Close wSOL ATA account, reclaim rent instructions.push( spl_token::instruction::close_account( - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, if quote_mint_is_wsol { &user_quote_token_account } else { @@ -270,7 +263,9 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { let base_token_program = protocol_params.base_token_program; let quote_token_program = protocol_params.quote_token_program; - if base_mint != accounts::WSOL_TOKEN_ACCOUNT && quote_mint != accounts::WSOL_TOKEN_ACCOUNT { + if base_mint != crate::constants::WSOL_TOKEN_ACCOUNT + && quote_mint != crate::constants::WSOL_TOKEN_ACCOUNT + { return Err(anyhow!("Invalid base mint and quote mint")); } if params.rpc.is_none() { @@ -280,7 +275,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { return Err(anyhow!("Token amount is not set")); } - let quote_mint_is_wsol = quote_mint == accounts::WSOL_TOKEN_ACCOUNT; + let quote_mint_is_wsol = quote_mint == crate::constants::WSOL_TOKEN_ACCOUNT; let mut token_amount = 0; let mut sol_amount = 0; @@ -354,8 +349,8 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { create_associated_token_account_idempotent( ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, - &accounts::TOKEN_PROGRAM, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, ), ); @@ -371,24 +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) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::GLOBAL_ACCOUNT, false), // global (readonly) + accounts::GLOBAL_ACCOUNT_META.clone(), // 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 - solana_sdk::instruction::AccountMeta::new_readonly(accounts::FEE_RECIPIENT, false), // fee_recipient (readonly) + accounts::FEE_RECIPIENT_META.clone(), // 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) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::SYSTEM_PROGRAM, false), // System Program (readonly) - solana_sdk::instruction::AccountMeta::new_readonly( - accounts::ASSOCIATED_TOKEN_PROGRAM, - false, - ), // ASSOCIATED_TOKEN_PROGRAM_ID (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::EVENT_AUTHORITY, false), // event_authority (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::AMM_PROGRAM, false), // PUMP_AMM_PROGRAM_ID (readonly) + 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) 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, @@ -396,20 +388,15 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { ), // coin_creator_vault_authority (readonly) ]; if !quote_mint_is_wsol { - accounts.push(solana_sdk::instruction::AccountMeta::new( - get_global_volume_accumulator_pda().unwrap(), - false, - )); + accounts.push(accounts::GLOBAL_VOLUME_ACCUMULATOR_META.clone()); accounts.push(solana_sdk::instruction::AccountMeta::new( get_user_volume_accumulator_pda(¶ms.payer.pubkey()).unwrap(), false, )); } - accounts - .push(solana_sdk::instruction::AccountMeta::new(get_fee_config_pda().unwrap(), false)); - accounts - .push(solana_sdk::instruction::AccountMeta::new_readonly(accounts::FEE_PROGRAM, false)); + accounts.push(accounts::FEE_CONFIG_META.clone()); + accounts.push(accounts::FEE_PROGRAM_META.clone()); // Create instruction data let mut data = vec![]; @@ -432,7 +419,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { if auto_handle_wsol { instructions.push( close_account( - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, if quote_mint_is_wsol { &user_quote_token_account } else { @@ -448,4 +435,3 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { Ok(instructions) } } - diff --git a/src/instruction/raydium_amm_v4.rs b/src/instruction/raydium_amm_v4.rs index 3c000eb..e4e98a2 100755 --- a/src/instruction/raydium_amm_v4.rs +++ b/src/instruction/raydium_amm_v4.rs @@ -31,10 +31,10 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { let wsol_token_account = spl_associated_token_account::get_associated_token_address( ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, + &crate::constants::WSOL_TOKEN_ACCOUNT, ); - let is_base_in = protocol_params.coin_mint == accounts::WSOL_TOKEN_ACCOUNT; + let is_base_in = protocol_params.coin_mint == crate::constants::WSOL_TOKEN_ACCOUNT; let amount_in: u64 = params.sol_amount; let swap_result = compute_swap_amount( @@ -55,8 +55,8 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { create_associated_token_account_idempotent( ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, - &accounts::TOKEN_PROGRAM, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, ), ); instructions.push( @@ -66,8 +66,11 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { // Sync wSOL balance instructions.push( - spl_token::instruction::sync_native(&accounts::TOKEN_PROGRAM, &wsol_token_account) - .unwrap(), + spl_token::instruction::sync_native( + &crate::constants::TOKEN_PROGRAM, + &wsol_token_account, + ) + .unwrap(), ); } @@ -75,12 +78,12 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), ¶ms.mint, - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, )); let user_source_token_account = spl_associated_token_account::get_associated_token_address( ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, + &crate::constants::WSOL_TOKEN_ACCOUNT, ); let user_destination_token_account = spl_associated_token_account::get_associated_token_address( @@ -90,9 +93,9 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { // Create buy instruction let accounts = vec![ - solana_sdk::instruction::AccountMeta::new_readonly(accounts::TOKEN_PROGRAM, false), // Token Program (readonly) + crate::constants::TOKEN_PROGRAM_META.clone(), // Token Program (readonly) solana_sdk::instruction::AccountMeta::new(protocol_params.amm, false), // Amm - solana_sdk::instruction::AccountMeta::new_readonly(accounts::AUTHORITY, false), // Authority (readonly) + accounts::AUTHORITY_META.clone(), // 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 @@ -120,7 +123,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { // Close wSOL ATA account, reclaim rent instructions.push( spl_token::instruction::close_account( - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, &wsol_token_account, ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), @@ -146,10 +149,10 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { let wsol_token_account = spl_associated_token_account::get_associated_token_address( ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, + &crate::constants::WSOL_TOKEN_ACCOUNT, ); - let is_base_in = protocol_params.pc_mint == accounts::WSOL_TOKEN_ACCOUNT; + let is_base_in = protocol_params.pc_mint == crate::constants::WSOL_TOKEN_ACCOUNT; let swap_result = compute_swap_amount( protocol_params.coin_reserve, protocol_params.pc_reserve, @@ -167,8 +170,8 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { create_associated_token_account_idempotent( ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, - &accounts::TOKEN_PROGRAM, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, ), ); @@ -179,14 +182,14 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { let user_destination_token_account = spl_associated_token_account::get_associated_token_address( ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, + &crate::constants::WSOL_TOKEN_ACCOUNT, ); // Create buy instruction let accounts = vec![ - solana_sdk::instruction::AccountMeta::new_readonly(accounts::TOKEN_PROGRAM, false), // Token Program (readonly) + crate::constants::TOKEN_PROGRAM_META.clone(), // Token Program (readonly) solana_sdk::instruction::AccountMeta::new(protocol_params.amm, false), // Amm - solana_sdk::instruction::AccountMeta::new_readonly(accounts::AUTHORITY, false), // Authority (readonly) + accounts::AUTHORITY_META.clone(), // 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 @@ -213,7 +216,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { if protocol_params.auto_handle_wsol { instructions.push( close_account( - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, &wsol_token_account, ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), diff --git a/src/instruction/raydium_cpmm.rs b/src/instruction/raydium_cpmm.rs index b07361b..20a2f99 100755 --- a/src/instruction/raydium_cpmm.rs +++ b/src/instruction/raydium_cpmm.rs @@ -39,7 +39,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { ) .unwrap(); - let is_base_in = protocol_params.base_mint == accounts::WSOL_TOKEN_ACCOUNT; + let is_base_in = protocol_params.base_mint == crate::constants::WSOL_TOKEN_ACCOUNT; let mint_token_program = if is_base_in { protocol_params.quote_token_program } else { @@ -48,7 +48,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { let wsol_token_account = spl_associated_token_account::get_associated_token_address( ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, + &crate::constants::WSOL_TOKEN_ACCOUNT, ); let mint_token_account = spl_associated_token_account::get_associated_token_address_with_program_id( @@ -58,7 +58,8 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { ); // Get pool token accounts - let wsol_vault_account = get_vault_pda(&pool_state, &accounts::WSOL_TOKEN_ACCOUNT).unwrap(); + let wsol_vault_account = + get_vault_pda(&pool_state, &crate::constants::WSOL_TOKEN_ACCOUNT).unwrap(); let mint_vault_account = get_vault_pda(&pool_state, ¶ms.mint).unwrap(); let observation_state_account = get_observation_state_pda(&pool_state).unwrap(); @@ -82,8 +83,8 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { create_associated_token_account_idempotent( ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, - &accounts::TOKEN_PROGRAM, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, ), ); instructions.push( @@ -93,8 +94,11 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { // Sync wSOL balance instructions.push( - spl_token::instruction::sync_native(&accounts::TOKEN_PROGRAM, &wsol_token_account) - .unwrap(), + spl_token::instruction::sync_native( + &crate::constants::TOKEN_PROGRAM, + &wsol_token_account, + ) + .unwrap(), ); } @@ -108,16 +112,16 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { // Create buy instruction let accounts = vec![ solana_sdk::instruction::AccountMeta::new(params.payer.pubkey(), true), // Payer (signer) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::AUTHORITY, false), // Authority (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::AMM_CONFIG, false), // Amm Config (readonly) + accounts::AUTHORITY_META.clone(), // Authority (readonly) + accounts::AMM_CONFIG_META.clone(), // 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 - solana_sdk::instruction::AccountMeta::new_readonly(accounts::TOKEN_PROGRAM, false), // Input Token Program (readonly) + crate::constants::TOKEN_PROGRAM_META.clone(), // Input Token Program (readonly) solana_sdk::instruction::AccountMeta::new_readonly(mint_token_program, false), // Output Token Program (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::WSOL_TOKEN_ACCOUNT, false), // Input token mint (readonly) + crate::constants::WSOL_TOKEN_ACCOUNT_META.clone(), // 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 ]; @@ -133,7 +137,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { // Close wSOL ATA account, reclaim rent instructions.push( spl_token::instruction::close_account( - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, &wsol_token_account, ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), @@ -182,7 +186,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { let wsol_token_account = spl_associated_token_account::get_associated_token_address( ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, + &crate::constants::WSOL_TOKEN_ACCOUNT, ); let mint_token_account = spl_associated_token_account::get_associated_token_address_with_program_id( @@ -192,7 +196,8 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { ); // Get pool token accounts - let wsol_vault_account = get_vault_pda(&pool_state, &accounts::WSOL_TOKEN_ACCOUNT).unwrap(); + let wsol_vault_account = + get_vault_pda(&pool_state, &crate::constants::WSOL_TOKEN_ACCOUNT).unwrap(); let mint_vault_account = get_vault_pda(&pool_state, ¶ms.mint).unwrap(); let observation_state_account = get_observation_state_pda(&pool_state).unwrap(); @@ -205,25 +210,25 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { create_associated_token_account_idempotent( ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), - &accounts::WSOL_TOKEN_ACCOUNT, - &spl_token::ID, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, ), ); // Create sell instruction let accounts = vec![ solana_sdk::instruction::AccountMeta::new(params.payer.pubkey(), true), // Payer (signer) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::AUTHORITY, false), // Authority (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::AMM_CONFIG, false), // Amm Config (readonly) + accounts::AUTHORITY_META.clone(), // Authority (readonly) + accounts::AMM_CONFIG_META.clone(), // 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) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::TOKEN_PROGRAM, false), // Output Token Program (readonly) + crate::constants::TOKEN_PROGRAM_META.clone(), // Output Token Program (readonly) solana_sdk::instruction::AccountMeta::new_readonly(params.mint, false), // Input token mint (readonly) - solana_sdk::instruction::AccountMeta::new_readonly(accounts::WSOL_TOKEN_ACCOUNT, false), // Output token mint (readonly) + crate::constants::WSOL_TOKEN_ACCOUNT_META.clone(), // Output token mint (readonly) solana_sdk::instruction::AccountMeta::new(observation_state_account, false), // Observation State Account ]; // Create instruction data @@ -237,7 +242,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { if protocol_params.auto_handle_wsol { instructions.push( close_account( - &accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, &wsol_token_account, ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), diff --git a/src/instruction/utils/bonk.rs b/src/instruction/utils/bonk.rs index a29bc6d..4a10137 100644 --- a/src/instruction/utils/bonk.rs +++ b/src/instruction/utils/bonk.rs @@ -17,15 +17,30 @@ pub mod accounts { pub const AUTHORITY: Pubkey = pubkey!("WLHv2UAZm6z4KyaaELi5pjdbJh6RESMva1Rnn8pJVVh"); pub const GLOBAL_CONFIG: Pubkey = pubkey!("6s1xP3hpbAfFoNtUNF8mfHsjr2Bd97JxFJRWLbL6aHuX"); - pub const TOKEN_PROGRAM: Pubkey = spl_token::ID; pub const EVENT_AUTHORITY: Pubkey = pubkey!("2DPAtwB8L12vrMRExbLuyGnC7n2J5LNoZQSejeQGpwkr"); - pub const WSOL_TOKEN_ACCOUNT: Pubkey = pubkey!("So11111111111111111111111111111111111111112"); pub const BONK: Pubkey = pubkey!("LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj"); - pub const SYSTEM_PROGRAM: Pubkey = solana_sdk::system_program::ID; pub const PLATFORM_FEE_RATE: u128 = 100; // 1% pub const PROTOCOL_FEE_RATE: u128 = 25; // 0.25% 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 BUY_EXECT_IN_DISCRIMINATOR: [u8; 8] = [250, 234, 13, 123, 213, 156, 19, 236]; @@ -142,14 +157,15 @@ pub fn get_vault_pda(pool_state: &Pubkey, mint: &Pubkey) -> Option { } pub fn get_platform_associated_account(platform_config: &Pubkey) -> Option { - let seeds: &[&[u8]; 2] = &[platform_config.as_ref(), accounts::WSOL_TOKEN_ACCOUNT.as_ref()]; + let seeds: &[&[u8]; 2] = + &[platform_config.as_ref(), crate::constants::WSOL_TOKEN_ACCOUNT.as_ref()]; let program_id: &Pubkey = &accounts::BONK; let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); pda.map(|pubkey| pubkey.0) } pub fn get_creator_associated_account(creator: &Pubkey) -> Option { - let seeds: &[&[u8]; 2] = &[creator.as_ref(), accounts::WSOL_TOKEN_ACCOUNT.as_ref()]; + let seeds: &[&[u8]; 2] = &[creator.as_ref(), crate::constants::WSOL_TOKEN_ACCOUNT.as_ref()]; let program_id: &Pubkey = &accounts::BONK; let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); pda.map(|pubkey| pubkey.0) diff --git a/src/instruction/utils/pumpfun.rs b/src/instruction/utils/pumpfun.rs index d32b938..29f9e14 100644 --- a/src/instruction/utils/pumpfun.rs +++ b/src/instruction/utils/pumpfun.rs @@ -61,9 +61,19 @@ 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) + }); /// 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) + }); /// Public key for the authority pub const AUTHORITY: Pubkey = pubkey!("FFWtrEQ4B4PKQoVuHYzZq8FabGkVatYzDpEVHsK5rrhF"); @@ -85,6 +95,10 @@ 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"); @@ -94,12 +108,6 @@ pub mod accounts { /// Authority for program events pub const EVENT_AUTHORITY: Pubkey = pubkey!("Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"); - /// System Program ID - pub const SYSTEM_PROGRAM: Pubkey = pubkey!("11111111111111111111111111111111"); - - /// Token Program ID - pub const TOKEN_PROGRAM: Pubkey = spl_token::ID; - /// Associated Token Program ID pub const ASSOCIATED_TOKEN_PROGRAM: Pubkey = pubkey!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"); @@ -110,6 +118,37 @@ pub mod accounts { pub const AMM_PROGRAM: Pubkey = pubkey!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); pub const FEE_PROGRAM: Pubkey = pubkey!("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"); + + // META + + 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: once_cell::sync::Lazy = + once_cell::sync::Lazy::new(|| { + solana_sdk::instruction::AccountMeta::new_readonly(EVENT_AUTHORITY, 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: once_cell::sync::Lazy< + solana_sdk::instruction::AccountMeta, + > = once_cell::sync::Lazy::new(|| { + solana_sdk::instruction::AccountMeta::new_readonly( + 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 struct Symbol; diff --git a/src/instruction/utils/pumpswap.rs b/src/instruction/utils/pumpswap.rs index 5a59380..c2a4ecc 100644 --- a/src/instruction/utils/pumpswap.rs +++ b/src/instruction/utils/pumpswap.rs @@ -1,4 +1,7 @@ -use crate::{common::SolanaRpcClient, constants}; +use crate::{ + common::SolanaRpcClient, + constants::{self, TOKEN_PROGRAM}, +}; use anyhow::anyhow; use solana_account_decoder::UiAccountEncoding; use solana_sdk::pubkey::Pubkey; @@ -27,6 +30,10 @@ pub mod seeds { pub mod accounts { use solana_sdk::{pubkey, pubkey::Pubkey}; + use crate::instruction::utils::pumpswap::{ + get_fee_config_pda, get_global_volume_accumulator_pda, + }; + /// Public key for the fee recipient pub const FEE_RECIPIENT: Pubkey = pubkey!("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"); @@ -36,14 +43,6 @@ pub mod accounts { /// Authority for program events pub const EVENT_AUTHORITY: Pubkey = pubkey!("GS4CU59F31iL7aR2Q8zVS8DRrcRnXX1yjQ66TqNVQnaR"); - pub const WSOL_TOKEN_ACCOUNT: Pubkey = pubkey!("So11111111111111111111111111111111111111112"); - - /// System Program ID - pub const SYSTEM_PROGRAM: Pubkey = pubkey!("11111111111111111111111111111111"); - - /// Token Program ID - pub const TOKEN_PROGRAM: Pubkey = spl_token::ID; - /// Associated Token Program ID pub const ASSOCIATED_TOKEN_PROGRAM: Pubkey = pubkey!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"); @@ -62,6 +61,53 @@ pub mod accounts { pub const COIN_CREATOR_FEE_BASIS_POINTS: u64 = 5; pub const FEE_PROGRAM: Pubkey = pubkey!("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"); + + // 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 FEE_RECIPIENT_META: once_cell::sync::Lazy = + once_cell::sync::Lazy::new(|| { + solana_sdk::instruction::AccountMeta::new_readonly(FEE_RECIPIENT, 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 EVENT_AUTHORITY_META: once_cell::sync::Lazy = + once_cell::sync::Lazy::new(|| { + solana_sdk::instruction::AccountMeta::new_readonly(EVENT_AUTHORITY, 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 GLOBAL_VOLUME_ACCUMULATOR_META: once_cell::sync::Lazy< + solana_sdk::instruction::AccountMeta, + > = once_cell::sync::Lazy::new(|| { + solana_sdk::instruction::AccountMeta::new_readonly( + 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_PROGRAM_META: once_cell::sync::Lazy = + once_cell::sync::Lazy::new(|| { + solana_sdk::instruction::AccountMeta::new_readonly(FEE_PROGRAM, false) + }); } pub const BUY_DISCRIMINATOR: [u8; 8] = [102, 6, 61, 18, 1, 218, 235, 234]; @@ -87,7 +133,7 @@ pub(crate) fn coin_creator_vault_ata(coin_creator: Pubkey, quote_mint: Pubkey) - spl_associated_token_account::get_associated_token_address_with_program_id( &creator_vault_authority, "e_mint, - &accounts::TOKEN_PROGRAM, + &TOKEN_PROGRAM, ); associated_token_creator_vault_authority } @@ -97,7 +143,7 @@ pub(crate) fn fee_recipient_ata(fee_recipient: Pubkey, quote_mint: Pubkey) -> Pu spl_associated_token_account::get_associated_token_address_with_program_id( &fee_recipient, "e_mint, - &accounts::TOKEN_PROGRAM, + &TOKEN_PROGRAM, ); associated_token_fee_recipient } diff --git a/src/instruction/utils/raydium_amm_v4.rs b/src/instruction/utils/raydium_amm_v4.rs index a7c99f2..05fc0e2 100644 --- a/src/instruction/utils/raydium_amm_v4.rs +++ b/src/instruction/utils/raydium_amm_v4.rs @@ -15,14 +15,19 @@ pub mod seeds { pub mod accounts { use solana_sdk::{pubkey, pubkey::Pubkey}; pub const AUTHORITY: Pubkey = pubkey!("5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1"); - pub const TOKEN_PROGRAM: Pubkey = spl_token::ID; - pub const WSOL_TOKEN_ACCOUNT: Pubkey = pubkey!("So11111111111111111111111111111111111111112"); pub const RAYDIUM_AMM_V4: Pubkey = pubkey!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); pub const TRADE_FEE_NUMERATOR: u64 = 25; pub const TRADE_FEE_DENOMINATOR: u64 = 10000; pub const SWAP_FEE_NUMERATOR: u64 = 25; pub const SWAP_FEE_DENOMINATOR: u64 = 10000; + + // META + + pub const AUTHORITY_META: once_cell::sync::Lazy = + once_cell::sync::Lazy::new(|| { + solana_sdk::instruction::AccountMeta::new_readonly(AUTHORITY, 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 d8e5805..40df0da 100644 --- a/src/instruction/utils/raydium_cpmm.rs +++ b/src/instruction/utils/raydium_cpmm.rs @@ -17,15 +17,22 @@ pub mod accounts { use solana_sdk::{pubkey, pubkey::Pubkey}; pub const AUTHORITY: Pubkey = pubkey!("GpMZbSM2GgvTKHJirzeGfMFoaZ8UR2X7F4v8vHTvxFbL"); pub const AMM_CONFIG: Pubkey = pubkey!("D4FPEruKEHrG5TenZ2mpDGEfu1iUvTiqBxvpU8HLBvC2"); - pub const TOKEN_PROGRAM: Pubkey = spl_token::ID; - pub const WSOL_TOKEN_ACCOUNT: Pubkey = pubkey!("So11111111111111111111111111111111111111112"); pub const RAYDIUM_CPMM: Pubkey = pubkey!("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"); - pub const FEE_RATE_DENOMINATOR_VALUE: u128 = 1_000_000; pub const TRADE_FEE_RATE: u64 = 2500; pub const CREATOR_FEE_RATE: u64 = 0; 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 AMM_CONFIG_META: once_cell::sync::Lazy = + once_cell::sync::Lazy::new(|| { + solana_sdk::instruction::AccountMeta::new_readonly(AMM_CONFIG, false) + }); } pub const SWAP_BASE_IN_DISCRIMINATOR: &[u8] = &[143, 190, 90, 218, 196, 30, 51, 222]; diff --git a/src/trading/common/utils.rs b/src/trading/common/utils.rs index ba9b4cf..b884a35 100644 --- a/src/trading/common/utils.rs +++ b/src/trading/common/utils.rs @@ -18,10 +18,14 @@ pub async fn get_multi_token_balances( let token0_balance = rpc.get_token_account_balance(&token0_vault).await?; let token1_balance = rpc.get_token_account_balance(&token1_vault).await?; // Parse balance string to u64 - let token0_amount = - token0_balance.amount.parse::().map_err(|e| anyhow!("Failed to parse token0 balance: {}", e))?; - let token1_amount = - token1_balance.amount.parse::().map_err(|e| anyhow!("Failed to parse token1 balance: {}", e))?; + let token0_amount = token0_balance + .amount + .parse::() + .map_err(|e| anyhow!("Failed to parse token0 balance: {}", e))?; + let token1_amount = token1_balance + .amount + .parse::() + .map_err(|e| anyhow!("Failed to parse token1 balance: {}", e))?; Ok((token0_amount, token1_amount)) } @@ -107,8 +111,13 @@ pub async fn close_token_account( } // Build close account instruction - let close_account_ix = - close_account(&spl_token::ID, &ata, &payer.pubkey(), &payer.pubkey(), &[&payer.pubkey()])?; + let close_account_ix = close_account( + &crate::constants::TOKEN_PROGRAM, + &ata, + &payer.pubkey(), + &payer.pubkey(), + &[&payer.pubkey()], + )?; // Build transaction let recent_blockhash = rpc.get_latest_blockhash().await?; diff --git a/src/trading/core/params.rs b/src/trading/core/params.rs index 500cbfb..138a2ea 100755 --- a/src/trading/core/params.rs +++ b/src/trading/core/params.rs @@ -189,13 +189,13 @@ impl PumpSwapParams { spl_associated_token_account::get_associated_token_address_with_program_id( &pool_address, &pool_data.base_mint, - &crate::instruction::utils::pumpswap::accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, ); let quote_token_program_ata = spl_associated_token_account::get_associated_token_address_with_program_id( &pool_address, &pool_data.quote_mint, - &crate::instruction::utils::pumpswap::accounts::TOKEN_PROGRAM, + &crate::constants::TOKEN_PROGRAM, ); Ok(Self { @@ -207,14 +207,14 @@ impl PumpSwapParams { coin_creator_vault_ata: coin_creator_vault_ata, coin_creator_vault_authority: coin_creator_vault_authority, base_token_program: if pool_data.pool_base_token_account == base_token_program_ata { - crate::instruction::utils::pumpswap::accounts::TOKEN_PROGRAM + crate::constants::TOKEN_PROGRAM } else { - spl_token_2022::ID + crate::constants::TOKEN_PROGRAM_2022 }, quote_token_program: if pool_data.pool_quote_token_account == quote_token_program_ata { - crate::instruction::utils::pumpswap::accounts::TOKEN_PROGRAM + crate::constants::TOKEN_PROGRAM } else { - spl_token_2022::ID + crate::constants::TOKEN_PROGRAM_2022 }, auto_handle_wsol: true, }) @@ -337,7 +337,7 @@ impl BonkParams { ) -> Result { let pool_address = crate::instruction::utils::bonk::get_pool_pda( mint, - &crate::instruction::utils::bonk::accounts::WSOL_TOKEN_ACCOUNT, + &crate::constants::WSOL_TOKEN_ACCOUNT, ) .unwrap(); let pool_data = diff --git a/src/utils/price/bonk.rs b/src/utils/price/bonk.rs index 2ce79ba..57aa91f 100644 --- a/src/utils/price/bonk.rs +++ b/src/utils/price/bonk.rs @@ -2,7 +2,7 @@ use solana_streamer_sdk::streaming::event_parser::protocols::bonk::types::PoolSt use crate::{ constants::decimals::{DEFAULT_TOKEN_DECIMALS, SOL_DECIMALS}, - instruction::utils::bonk::accounts::WSOL_TOKEN_ACCOUNT, + constants::WSOL_TOKEN_ACCOUNT, }; /// Calculate the token price in WSOL based on pool state