From 21d6714c258ec41942dc392c9b35411408b499a2 Mon Sep 17 00:00:00 2001 From: ysq Date: Sun, 7 Sep 2025 19:00:08 +0800 Subject: [PATCH] refactor: reorganize code structure and optimize modular design - Remove src/common/address_lookup.rs and tip_cache.rs to simplify common modules - Move protocol-specific utility functions from trading/ to instruction/utils/ - Refactor utility functions for PumpFun, PumpSwap, Raydium AMM V4, and Raydium CPMM - Consolidate constant definitions by inlining seeds and accounts modules into respective utility files - Update all import paths to ensure code consistency - Optimize trading parameter construction and executor logic - Improve address lookup cache and nonce management mechanisms --- examples/pumpswap_trading/src/main.rs | 2 +- examples/raydium_amm_v4_trading/src/main.rs | 6 +- examples/raydium_cpmm_trading/src/main.rs | 2 +- src/common/bonding_curve.rs | 21 +- src/common/global.rs | 10 +- src/constants/bonk.rs | 37 --- src/constants/mod.rs | 17 +- src/constants/pumpfun.rs | 121 -------- src/constants/pumpswap.rs | 74 ----- src/constants/raydium_cpmm.rs | 37 --- src/constants/trade.rs | 2 +- src/constants/trade_platform.rs | 8 + src/instruction/bonk.rs | 8 +- src/instruction/mod.rs | 3 +- src/instruction/pumpfun.rs | 43 ++- src/instruction/pumpswap.rs | 20 +- src/instruction/raydium_amm_v4.rs | 6 +- src/instruction/raydium_cpmm.rs | 16 +- .../common.rs => instruction/utils/bonk.rs} | 99 +++---- src/instruction/utils/mod.rs | 5 + src/instruction/utils/pumpfun.rs | 259 ++++++++++++++++++ .../utils/pumpswap.rs} | 90 ++++-- .../utils}/raydium_amm_v4.rs | 25 +- .../utils/raydium_cpmm.rs} | 89 +++--- src/trading/bonk/mod.rs | 1 - src/trading/core/params.rs | 87 +++--- src/trading/mod.rs | 5 - src/trading/pumpfun/common.rs | 169 ------------ src/trading/pumpfun/mod.rs | 1 - src/trading/pumpswap/mod.rs | 1 - src/trading/raydium_amm_v4/common.rs | 14 - src/trading/raydium_amm_v4/mod.rs | 1 - src/trading/raydium_cpmm/mod.rs | 1 - src/utils/calc/bonk.rs | 2 +- src/utils/calc/pumpfun.rs | 2 +- src/utils/calc/pumpswap.rs | 2 +- src/utils/calc/raydium_amm_v4.rs | 2 +- src/utils/calc/raydium_cpmm.rs | 5 +- src/utils/mod.rs | 25 +- src/utils/price/bonk.rs | 6 +- src/utils/price/pumpfun.rs | 2 +- 41 files changed, 571 insertions(+), 755 deletions(-) delete mode 100755 src/constants/bonk.rs delete mode 100755 src/constants/pumpfun.rs delete mode 100755 src/constants/pumpswap.rs delete mode 100755 src/constants/raydium_cpmm.rs create mode 100644 src/constants/trade_platform.rs rename src/{trading/bonk/common.rs => instruction/utils/bonk.rs} (67%) mode change 100755 => 100644 create mode 100644 src/instruction/utils/mod.rs create mode 100644 src/instruction/utils/pumpfun.rs rename src/{trading/pumpswap/common.rs => instruction/utils/pumpswap.rs} (66%) mode change 100755 => 100644 rename src/{constants => instruction/utils}/raydium_amm_v4.rs (64%) mode change 100755 => 100644 rename src/{trading/raydium_cpmm/common.rs => instruction/utils/raydium_cpmm.rs} (56%) mode change 100755 => 100644 delete mode 100755 src/trading/bonk/mod.rs delete mode 100755 src/trading/pumpfun/common.rs delete mode 100755 src/trading/pumpfun/mod.rs delete mode 100755 src/trading/pumpswap/mod.rs delete mode 100755 src/trading/raydium_amm_v4/common.rs delete mode 100755 src/trading/raydium_amm_v4/mod.rs delete mode 100755 src/trading/raydium_cpmm/mod.rs diff --git a/examples/pumpswap_trading/src/main.rs b/examples/pumpswap_trading/src/main.rs index 77938a4..2602fc5 100644 --- a/examples/pumpswap_trading/src/main.rs +++ b/examples/pumpswap_trading/src/main.rs @@ -21,7 +21,7 @@ use sol_trade_sdk::{ SolanaTrade, }; use sol_trade_sdk::{ - constants::pumpswap::accounts, + instruction::utils::pumpswap::accounts, solana_streamer_sdk::streaming::event_parser::{ common::filter::EventTypeFilter, protocols::pumpswap::PumpSwapBuyEvent, }, diff --git a/examples/raydium_amm_v4_trading/src/main.rs b/examples/raydium_amm_v4_trading/src/main.rs index 0bd1c54..687e97b 100644 --- a/examples/raydium_amm_v4_trading/src/main.rs +++ b/examples/raydium_amm_v4_trading/src/main.rs @@ -3,7 +3,7 @@ use std::sync::{ Arc, }; -use sol_trade_sdk::{constants::raydium_amm_v4::accounts, solana_streamer_sdk::{match_event, streaming::event_parser::protocols::raydium_amm_v4::RaydiumAmmV4SwapEvent}, trading::common::get_multi_token_balances}; +use sol_trade_sdk::{instruction::utils::raydium_amm_v4::{accounts, fetch_amm_info}, solana_streamer_sdk::{match_event, streaming::event_parser::protocols::raydium_amm_v4::RaydiumAmmV4SwapEvent}, trading::common::get_multi_token_balances}; use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::filter::EventTypeFilter; use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::common::EventType; use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::protocols::raydium_amm_v4::parser::RAYDIUM_AMM_V4_PROGRAM_ID; @@ -131,9 +131,7 @@ async fn raydium_amm_v4_copy_trade_with_grpc(trade_info: RaydiumAmmV4SwapEvent) let slippage_basis_points = Some(100); let recent_blockhash = client.rpc.get_latest_blockhash().await?; - let amm_info = - sol_trade_sdk::trading::raydium_amm_v4::common::fetch_amm_info(&client.rpc, trade_info.amm) - .await?; + 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 { diff --git a/examples/raydium_cpmm_trading/src/main.rs b/examples/raydium_cpmm_trading/src/main.rs index a7d4738..e81f10b 100644 --- a/examples/raydium_cpmm_trading/src/main.rs +++ b/examples/raydium_cpmm_trading/src/main.rs @@ -17,7 +17,7 @@ use sol_trade_sdk::{ SolanaTrade, }; use sol_trade_sdk::{ - constants::raydium_cpmm::accounts, + instruction::utils::raydium_cpmm::accounts, solana_streamer_sdk::streaming::event_parser::protocols::raydium_cpmm::parser::RAYDIUM_CPMM_PROGRAM_ID, }; use sol_trade_sdk::{ diff --git a/src/common/bonding_curve.rs b/src/common/bonding_curve.rs index dbba619..b3a7b01 100755 --- a/src/common/bonding_curve.rs +++ b/src/common/bonding_curve.rs @@ -25,10 +25,14 @@ //! - `get_final_market_cap_sol`: Calculates the final market cap in SOL after all tokens are sold //! - `get_buy_out_price`: Calculates the price to buy out all remaining tokens -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use solana_sdk::pubkey::Pubkey; -use crate::{constants::pumpfun::global_constants::{INITIAL_REAL_TOKEN_RESERVES, INITIAL_VIRTUAL_SOL_RESERVES, INITIAL_VIRTUAL_TOKEN_RESERVES, TOKEN_TOTAL_SUPPLY}, trading::pumpfun::common::{get_bonding_curve_pda, get_creator_vault_pda}}; +use crate::instruction::utils::pumpfun::global_constants::{ + INITIAL_REAL_TOKEN_RESERVES, INITIAL_VIRTUAL_SOL_RESERVES, INITIAL_VIRTUAL_TOKEN_RESERVES, + TOKEN_TOTAL_SUPPLY, +}; +use crate::instruction::utils::pumpfun::{get_bonding_curve_pda, get_creator_vault_pda}; use crate::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; /// Represents the global configuration account for token pricing and fees @@ -55,7 +59,12 @@ pub struct BondingCurveAccount { } impl BondingCurveAccount { - pub fn from_dev_trade(mint: &Pubkey, dev_token_amount: u64, dev_sol_amount: u64, creator: Pubkey) -> Self { + pub fn from_dev_trade( + mint: &Pubkey, + dev_token_amount: u64, + dev_sol_amount: u64, + creator: Pubkey, + ) -> Self { Self { discriminator: 0, account: get_bonding_curve_pda(mint).unwrap(), @@ -118,11 +127,7 @@ impl BondingCurveAccount { // Convert back to u64 and return the minimum of calculated tokens and real reserves let s_u64 = s as u64; - Ok(if s_u64 < self.real_token_reserves { - s_u64 - } else { - self.real_token_reserves - }) + Ok(if s_u64 < self.real_token_reserves { s_u64 } else { self.real_token_reserves }) } /// Calculates the amount of SOL received for selling tokens diff --git a/src/common/global.rs b/src/common/global.rs index 3a5c414..ea37fb9 100755 --- a/src/common/global.rs +++ b/src/common/global.rs @@ -23,10 +23,16 @@ //! - `creator_fee`: Fee for creators //! - `fee_recipients`: Array of fee recipient accounts +use serde::{Deserialize, Serialize}; use solana_sdk::pubkey::Pubkey; -use serde::{Serialize, Deserialize}; -use crate::constants::pumpfun::global_constants::*; +use crate::instruction::utils::pumpfun::global_constants::{ + AUTHORITY, CREATOR_FEE, ENABLE_MIGRATE, FEE_BASIS_POINTS, FEE_RECIPIENT, GLOBAL_ACCOUNT, + INITIAL_REAL_TOKEN_RESERVES, INITIAL_VIRTUAL_SOL_RESERVES, INITIAL_VIRTUAL_TOKEN_RESERVES, + POOL_MIGRATION_FEE, PUMPFUN_AMM_FEE_1, PUMPFUN_AMM_FEE_2, PUMPFUN_AMM_FEE_3, PUMPFUN_AMM_FEE_4, + PUMPFUN_AMM_FEE_5, PUMPFUN_AMM_FEE_6, PUMPFUN_AMM_FEE_7, TOKEN_TOTAL_SUPPLY, + WITHDRAW_AUTHORITY, +}; /// Represents the global configuration account for token pricing and fees #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/src/constants/bonk.rs b/src/constants/bonk.rs deleted file mode 100755 index 87470c0..0000000 --- a/src/constants/bonk.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! Constants used by the crate. -//! -//! This module contains various constants used throughout the crate, including: -//! -//! - Seeds for deriving Program Derived Addresses (PDAs) -//! - Program account addresses and public keys -//! -//! The constants are organized into submodules for better organization: -//! -//! - `seeds`: Contains seed values used for PDA derivation -//! - `accounts`: Contains important program account addresses - -/// Constants used as seeds for deriving PDAs (Program Derived Addresses) -pub mod seeds { - pub const POOL_SEED: &[u8] = b"pool"; - pub const POOL_VAULT_SEED: &[u8] = b"pool_vault"; -} - -/// Constants related to program accounts and authorities -pub mod accounts { - use solana_sdk::{pubkey, pubkey::Pubkey}; - - 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% -} - -pub const BUY_EXECT_IN_DISCRIMINATOR: [u8; 8] = [250, 234, 13, 123, 213, 156, 19, 236]; -pub const SELL_EXECT_IN_DISCRIMINATOR: [u8; 8] = [149, 39, 222, 155, 211, 124, 152, 26]; diff --git a/src/constants/mod.rs b/src/constants/mod.rs index 472b7bb..37a7081 100755 --- a/src/constants/mod.rs +++ b/src/constants/mod.rs @@ -1,17 +1,4 @@ -pub mod bonk; -pub mod pumpfun; -pub mod pumpswap; +pub mod decimals; pub mod swqos; pub mod trade; -pub mod raydium_cpmm; -pub mod raydium_amm_v4; -pub mod decimals; - -pub mod trade_platform { - pub const PUMPFUN: &'static str = "pumpfun"; - pub const PUMPFUN_SWAP: &'static str = "pumpswap"; - pub const BONK: &'static str = "bonk"; - pub const RAYDIUM_CPMM: &'static str = "raydium_cpmm"; - pub const RAYDIUM_CLMM: &'static str = "raydium_clmm"; - pub const RAYDIUM_AMM_V4: &'static str = "raydium_amm_v4"; -} +pub mod trade_platform; diff --git a/src/constants/pumpfun.rs b/src/constants/pumpfun.rs deleted file mode 100755 index 057ae9c..0000000 --- a/src/constants/pumpfun.rs +++ /dev/null @@ -1,121 +0,0 @@ -//! Constants used by the crate. -//! -//! This module contains various constants used throughout the crate, including: -//! -//! - Seeds for deriving Program Derived Addresses (PDAs) -//! - Program account addresses and public keys -//! -//! The constants are organized into submodules for better organization: -//! -//! - `seeds`: Contains seed values used for PDA derivation -//! - `accounts`: Contains important program account addresses - -/// Constants used as seeds for deriving PDAs (Program Derived Addresses) -pub mod seeds { - /// Seed for the global state PDA - pub const GLOBAL_SEED: &[u8] = b"global"; - - /// Seed for the mint authority PDA - pub const MINT_AUTHORITY_SEED: &[u8] = b"mint-authority"; - - /// Seed for bonding curve PDAs - pub const BONDING_CURVE_SEED: &[u8] = b"bonding-curve"; - - /// Seed for creator vault PDAs - pub const CREATOR_VAULT_SEED: &[u8] = b"creator-vault"; - - /// Seed for metadata PDAs - pub const METADATA_SEED: &[u8] = b"metadata"; - - /// Seed for user volume accumulator PDAs - pub const USER_VOLUME_ACCUMULATOR_SEED: &[u8] = b"user_volume_accumulator"; - - /// Seed for global volume accumulator PDAs - pub const GLOBAL_VOLUME_ACCUMULATOR_SEED: &[u8] = b"global_volume_accumulator"; - - pub const FEE_CONFIG_SEED: &[u8] = b"fee_config"; -} - -pub mod global_constants { - use solana_sdk::{pubkey, pubkey::Pubkey}; - - pub const INITIAL_VIRTUAL_TOKEN_RESERVES: u64 = 1_073_000_000_000_000; - - pub const INITIAL_VIRTUAL_SOL_RESERVES: u64 = 30_000_000_000; - - pub const INITIAL_REAL_TOKEN_RESERVES: u64 = 793_100_000_000_000; - - pub const TOKEN_TOTAL_SUPPLY: u64 = 1_000_000_000_000_000; - - pub const FEE_BASIS_POINTS: u64 = 95; - - pub const ENABLE_MIGRATE: bool = false; - - pub const POOL_MIGRATION_FEE: u64 = 15_000_001; - - pub const CREATOR_FEE: u64 = 5; - - pub const SCALE: u64 = 1_000_000; // 10^6 for token decimals - - pub const LAMPORTS_PER_SOL: u64 = 1_000_000_000; // 10^9 for solana lamports - - pub const COMPLETION_LAMPORTS: u64 = 85 * LAMPORTS_PER_SOL; // ~ 85 SOL - - /// Public key for the fee recipient - pub const FEE_RECIPIENT: Pubkey = pubkey!("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"); - - /// Public key for the global PDA - pub const GLOBAL_ACCOUNT: Pubkey = pubkey!("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"); - - /// Public key for the authority - pub const AUTHORITY: Pubkey = pubkey!("FFWtrEQ4B4PKQoVuHYzZq8FabGkVatYzDpEVHsK5rrhF"); - - /// Public key for the withdraw authority - pub const WITHDRAW_AUTHORITY: Pubkey = pubkey!("39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg"); - - pub const PUMPFUN_AMM_FEE_1: Pubkey = pubkey!("7VtfL8fvgNfhz17qKRMjzQEXgbdpnHHHQRh54R9jP2RJ"); // Pump.fun AMM: Protocol Fee 1 - pub const PUMPFUN_AMM_FEE_2: Pubkey = pubkey!("7hTckgnGnLQR6sdH7YkqFTAA7VwTfYFaZ6EhEsU3saCX"); // Pump.fun AMM: Protocol Fee 2 - pub const PUMPFUN_AMM_FEE_3: Pubkey = pubkey!("9rPYyANsfQZw3DnDmKE3YCQF5E8oD89UXoHn9JFEhJUz"); // Pump.fun AMM: Protocol Fee 3 - pub const PUMPFUN_AMM_FEE_4: Pubkey = pubkey!("AVmoTthdrX6tKt4nDjco2D775W2YK3sDhxPcMmzUAmTY"); // Pump.fun AMM: Protocol Fee 4 - pub const PUMPFUN_AMM_FEE_5: Pubkey = pubkey!("CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM"); // Pump.fun AMM: Protocol Fee 5 - pub const PUMPFUN_AMM_FEE_6: Pubkey = pubkey!("FWsW1xNtWscwNmKv6wVsU1iTzRN6wmmk3MjxRP5tT7hz"); // Pump.fun AMM: Protocol Fee 6 - pub const PUMPFUN_AMM_FEE_7: Pubkey = pubkey!("G5UZAVbAf46s7cKWoyKu8kYTip9DGTpbLZ2qa9Aq69dP"); - // Pump.fun AMM: Protocol Fee 7 -} - -/// Constants related to program accounts and authorities -pub mod accounts { - use solana_sdk::{pubkey, pubkey::Pubkey}; - - /// Public key for the Pump.fun program - pub const PUMPFUN: Pubkey = pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"); - - /// Public key for the MPL Token Metadata program - pub const MPL_TOKEN_METADATA: Pubkey = pubkey!("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); - - /// 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"); - - /// Rent Sysvar ID - pub const RENT: Pubkey = pubkey!("SysvarRent111111111111111111111111111111111"); - - pub const AMM_PROGRAM: Pubkey = pubkey!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); - - pub const FEE_PROGRAM: Pubkey = pubkey!("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"); -} - -pub struct Symbol; - -impl Symbol { - pub const SOLANA: &'static str = "solana"; -} diff --git a/src/constants/pumpswap.rs b/src/constants/pumpswap.rs deleted file mode 100755 index 6c4c385..0000000 --- a/src/constants/pumpswap.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! Constants used by the crate. -//! -//! This module contains various constants used throughout the crate, including: -//! -//! - Seeds for deriving Program Derived Addresses (PDAs) -//! - Program account addresses and public keys -//! -//! The constants are organized into submodules for better organization: -//! -//! - `seeds`: Contains seed values used for PDA derivation -//! - `accounts`: Contains important program account addresses - -/// Constants used as seeds for deriving PDAs (Program Derived Addresses) -pub mod seeds { - /// Seed for the global state PDA - pub const GLOBAL_SEED: &[u8] = b"global"; - - /// Seed for the mint authority PDA - pub const MINT_AUTHORITY_SEED: &[u8] = b"mint-authority"; - - /// Seed for bonding curve PDAs - pub const BONDING_CURVE_SEED: &[u8] = b"bonding-curve"; - - /// Seed for metadata PDAs - pub const METADATA_SEED: &[u8] = b"metadata"; - - pub const USER_VOLUME_ACCUMULATOR_SEED: &[u8] = b"user_volume_accumulator"; - pub const GLOBAL_VOLUME_ACCUMULATOR_SEED: &[u8] = b"global_volume_accumulator"; - pub const FEE_CONFIG_SEED: &[u8] = b"fee_config"; -} - -/// Constants related to program accounts and authorities -pub mod accounts { - use solana_sdk::{pubkey, pubkey::Pubkey}; - - /// Public key for the fee recipient - pub const FEE_RECIPIENT: Pubkey = pubkey!("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"); - - /// Public key for the global PDA - pub const GLOBAL_ACCOUNT: Pubkey = pubkey!("ADyA8hdefvWN2dbGGWFotbzWxrAvLW83WG6QCVXvJKqw"); - - /// 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"); - - // PumpSwap 协议费用接收者 - 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; - pub const PROTOCOL_FEE_BASIS_POINTS: u64 = 5; - pub const COIN_CREATOR_FEE_BASIS_POINTS: u64 = 5; - - pub const FEE_PROGRAM: Pubkey = pubkey!("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"); -} - -pub const BUY_DISCRIMINATOR: [u8; 8] = [102, 6, 61, 18, 1, 218, 235, 234]; -pub const SELL_DISCRIMINATOR: [u8; 8] = [51, 230, 133, 164, 1, 127, 131, 173]; diff --git a/src/constants/raydium_cpmm.rs b/src/constants/raydium_cpmm.rs deleted file mode 100755 index c66c959..0000000 --- a/src/constants/raydium_cpmm.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! Constants used by the crate. -//! -//! This module contains various constants used throughout the crate, including: -//! -//! - Seeds for deriving Program Derived Addresses (PDAs) -//! - Program account addresses and public keys -//! -//! The constants are organized into submodules for better organization: -//! -//! - `seeds`: Contains seed values used for PDA derivation -//! - `accounts`: Contains important program account addresses - -/// Constants used as seeds for deriving PDAs (Program Derived Addresses) -pub mod seeds { - pub const POOL_SEED: &[u8] = b"pool"; - pub const POOL_VAULT_SEED: &[u8] = b"pool_vault"; - pub const OBSERVATION_STATE_SEED: &[u8] = b"observation"; -} - -/// Constants related to program accounts and authorities -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; -} - -pub const SWAP_BASE_IN_DISCRIMINATOR: &[u8] = &[143, 190, 90, 218, 196, 30, 51, 222]; -pub const SWAP_BASE_OUT_DISCRIMINATOR: &[u8] = &[55, 217, 98, 86, 163, 74, 180, 173]; diff --git a/src/constants/trade.rs b/src/constants/trade.rs index 043ba09..4a96442 100644 --- a/src/constants/trade.rs +++ b/src/constants/trade.rs @@ -6,4 +6,4 @@ pub mod trade { pub const DEFAULT_SELL_TIP_FEE: f64 = 0.0001; pub const DEFAULT_RPC_UNIT_LIMIT: u32 = 78000; pub const DEFAULT_RPC_UNIT_PRICE: u64 = 500000; -} +} \ No newline at end of file diff --git a/src/constants/trade_platform.rs b/src/constants/trade_platform.rs new file mode 100644 index 0000000..642aeae --- /dev/null +++ b/src/constants/trade_platform.rs @@ -0,0 +1,8 @@ +pub mod trade_platform { + pub const PUMPFUN: &'static str = "pumpfun"; + pub const PUMPFUN_SWAP: &'static str = "pumpswap"; + pub const BONK: &'static str = "bonk"; + pub const RAYDIUM_CPMM: &'static str = "raydium_cpmm"; + pub const RAYDIUM_CLMM: &'static str = "raydium_clmm"; + pub const RAYDIUM_AMM_V4: &'static str = "raydium_amm_v4"; +} diff --git a/src/instruction/bonk.rs b/src/instruction/bonk.rs index aeaaa85..39d3efc 100755 --- a/src/instruction/bonk.rs +++ b/src/instruction/bonk.rs @@ -5,12 +5,12 @@ use spl_associated_token_account::instruction::create_associated_token_account_i use spl_token::instruction::close_account; use crate::{ - constants::{ - bonk::{accounts, BUY_EXECT_IN_DISCRIMINATOR, SELL_EXECT_IN_DISCRIMINATOR}, - trade::trade::DEFAULT_SLIPPAGE, + constants::trade::trade::DEFAULT_SLIPPAGE, + instruction::utils::bonk::{ + accounts, get_pool_pda, get_vault_pda, BUY_EXECT_IN_DISCRIMINATOR, + SELL_EXECT_IN_DISCRIMINATOR, }, trading::{ - bonk::common::{get_pool_pda, get_vault_pda}, common::utils::get_token_balance, core::{ params::{BonkParams, BuyParams, SellParams}, diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index 81bdcc0..3f94772 100755 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -2,4 +2,5 @@ pub mod pumpfun; pub mod pumpswap; pub mod bonk; pub mod raydium_cpmm; -pub mod raydium_amm_v4; \ No newline at end of file +pub mod raydium_amm_v4; +pub mod utils; \ No newline at end of file diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index 0f6b23d..1893749 100755 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -6,9 +6,10 @@ use spl_associated_token_account::{ use spl_token::instruction::close_account; use crate::{ - constants, - trading::pumpfun::common::{ - get_bonding_curve_pda, get_fee_config_pda, get_global_volume_accumulator_pda, get_user_volume_accumulator_pda + 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}, }, utils::calc::{ common::{calculate_with_slippage_buy, calculate_with_slippage_sell}, @@ -19,13 +20,11 @@ use crate::{ use solana_sdk::{instruction::AccountMeta, pubkey::Pubkey, signature::Keypair, signer::Signer}; use crate::{ - constants::pumpfun::global_constants::FEE_RECIPIENT, constants::trade::trade::DEFAULT_SLIPPAGE, trading::core::{ params::{BuyParams, PumpFunParams, SellParams}, traits::InstructionBuilder, }, - trading::pumpfun::common::get_creator_vault_pda, }; /// Instruction builder for PumpFun protocol @@ -58,9 +57,9 @@ impl InstructionBuilder for PumpFunInstructionBuilder { Pubkey::default() } else { // Fast check against cached default creator vault - static DEFAULT_CREATOR_VAULT: std::sync::LazyLock> = + 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 { @@ -83,7 +82,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), ¶ms.mint, - &constants::pumpfun::accounts::TOKEN_PROGRAM, + &accounts::TOKEN_PROGRAM, )); // Create buy instruction @@ -200,25 +199,25 @@ pub fn buy( args: Buy, ) -> Instruction { Instruction::new_with_bytes( - constants::pumpfun::accounts::PUMPFUN, + accounts::PUMPFUN, &args.data(), vec![ - AccountMeta::new_readonly(constants::pumpfun::global_constants::GLOBAL_ACCOUNT, false), + AccountMeta::new_readonly(global_constants::GLOBAL_ACCOUNT, false), AccountMeta::new(*fee_recipient, false), AccountMeta::new_readonly(*mint, false), AccountMeta::new(*bonding_curve_pda, false), AccountMeta::new(get_associated_token_address(bonding_curve_pda, mint), false), AccountMeta::new(get_associated_token_address(&payer.pubkey(), mint), false), AccountMeta::new(payer.pubkey(), true), - AccountMeta::new_readonly(constants::pumpfun::accounts::SYSTEM_PROGRAM, false), - AccountMeta::new_readonly(constants::pumpfun::accounts::TOKEN_PROGRAM, false), + AccountMeta::new_readonly(accounts::SYSTEM_PROGRAM, false), + AccountMeta::new_readonly(accounts::TOKEN_PROGRAM, false), AccountMeta::new(*creator_vault_pda, false), - AccountMeta::new_readonly(constants::pumpfun::accounts::EVENT_AUTHORITY, false), - AccountMeta::new_readonly(constants::pumpfun::accounts::PUMPFUN, false), + AccountMeta::new_readonly(accounts::EVENT_AUTHORITY, false), + AccountMeta::new_readonly(accounts::PUMPFUN, false), AccountMeta::new(get_global_volume_accumulator_pda().unwrap(), false), AccountMeta::new(get_user_volume_accumulator_pda(&payer.pubkey()).unwrap(), false), AccountMeta::new_readonly(get_fee_config_pda().unwrap(), false), - AccountMeta::new_readonly(constants::pumpfun::accounts::FEE_PROGRAM, false), + AccountMeta::new_readonly(accounts::FEE_PROGRAM, false), ], ) } @@ -232,23 +231,23 @@ pub fn sell( ) -> Instruction { let bonding_curve: Pubkey = get_bonding_curve_pda(mint).unwrap(); Instruction::new_with_bytes( - constants::pumpfun::accounts::PUMPFUN, + accounts::PUMPFUN, &args.data(), vec![ - AccountMeta::new_readonly(constants::pumpfun::global_constants::GLOBAL_ACCOUNT, false), + AccountMeta::new_readonly(global_constants::GLOBAL_ACCOUNT, false), AccountMeta::new(*fee_recipient, false), AccountMeta::new_readonly(*mint, false), AccountMeta::new(bonding_curve, false), AccountMeta::new(get_associated_token_address(&bonding_curve, mint), false), AccountMeta::new(get_associated_token_address(&payer.pubkey(), mint), false), AccountMeta::new(payer.pubkey(), true), - AccountMeta::new_readonly(constants::pumpfun::accounts::SYSTEM_PROGRAM, false), + AccountMeta::new_readonly(accounts::SYSTEM_PROGRAM, false), AccountMeta::new(*creator_vault_pda, false), - AccountMeta::new_readonly(constants::pumpfun::accounts::TOKEN_PROGRAM, false), - AccountMeta::new_readonly(constants::pumpfun::accounts::EVENT_AUTHORITY, false), - AccountMeta::new_readonly(constants::pumpfun::accounts::PUMPFUN, 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(constants::pumpfun::accounts::FEE_PROGRAM, false), + AccountMeta::new_readonly(accounts::FEE_PROGRAM, false), ], ) } diff --git a/src/instruction/pumpswap.rs b/src/instruction/pumpswap.rs index ebac507..13136ff 100755 --- a/src/instruction/pumpswap.rs +++ b/src/instruction/pumpswap.rs @@ -5,19 +5,15 @@ use spl_associated_token_account::instruction::create_associated_token_account_i use spl_token::instruction::close_account; use crate::{ - constants::{ - pumpswap::{accounts, BUY_DISCRIMINATOR, SELL_DISCRIMINATOR}, - trade::trade::DEFAULT_SLIPPAGE, + 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, }, - trading::{ - core::{ - params::{BuyParams, PumpSwapParams, SellParams}, - traits::InstructionBuilder, - }, - pumpswap::common::{ - coin_creator_vault_ata, coin_creator_vault_authority, fee_recipient_ata, - get_fee_config_pda, get_global_volume_accumulator_pda, get_user_volume_accumulator_pda, - }, + trading::core::{ + params::{BuyParams, PumpSwapParams, SellParams}, + traits::InstructionBuilder, }, utils::calc::pumpswap::{buy_quote_input_internal, sell_base_input_internal}, }; diff --git a/src/instruction/raydium_amm_v4.rs b/src/instruction/raydium_amm_v4.rs index 4256f9c..265c59b 100755 --- a/src/instruction/raydium_amm_v4.rs +++ b/src/instruction/raydium_amm_v4.rs @@ -5,10 +5,8 @@ use spl_associated_token_account::instruction::create_associated_token_account_i use spl_token::instruction::close_account; use crate::{ - constants::{ - raydium_amm_v4::{accounts, SWAP_BASE_IN_DISCRIMINATOR}, - trade::trade::DEFAULT_SLIPPAGE, - }, + constants::trade::trade::DEFAULT_SLIPPAGE, + instruction::utils::raydium_amm_v4::{accounts, SWAP_BASE_IN_DISCRIMINATOR}, trading::core::{ params::{BuyParams, RaydiumAmmV4Params, SellParams}, traits::InstructionBuilder, diff --git a/src/instruction/raydium_cpmm.rs b/src/instruction/raydium_cpmm.rs index 7c211e9..39b1fce 100755 --- a/src/instruction/raydium_cpmm.rs +++ b/src/instruction/raydium_cpmm.rs @@ -5,16 +5,14 @@ use spl_associated_token_account::instruction::create_associated_token_account_i use spl_token::instruction::close_account; use crate::{ - constants::{ - raydium_cpmm::{accounts, SWAP_BASE_IN_DISCRIMINATOR}, - trade::trade::DEFAULT_SLIPPAGE, + constants::trade::trade::DEFAULT_SLIPPAGE, + instruction::utils::raydium_cpmm::{ + accounts, get_observation_state_pda, get_pool_pda, get_vault_pda, + SWAP_BASE_IN_DISCRIMINATOR, }, - trading::{ - core::{ - params::{BuyParams, RaydiumCpmmParams, SellParams}, - traits::InstructionBuilder, - }, - raydium_cpmm::common::{get_observation_state_pda, get_pool_pda, get_vault_pda}, + trading::core::{ + params::{BuyParams, RaydiumCpmmParams, SellParams}, + traits::InstructionBuilder, }, utils::calc::raydium_cpmm::compute_swap_amount, }; diff --git a/src/trading/bonk/common.rs b/src/instruction/utils/bonk.rs old mode 100755 new mode 100644 similarity index 67% rename from src/trading/bonk/common.rs rename to src/instruction/utils/bonk.rs index afe9b41..a29bc6d --- a/src/trading/bonk/common.rs +++ b/src/instruction/utils/bonk.rs @@ -1,13 +1,36 @@ -use crate::{ - common::SolanaRpcClient, - constants::{self, bonk::accounts}, -}; +use crate::common::SolanaRpcClient; use anyhow::anyhow; use solana_sdk::pubkey::Pubkey; use solana_streamer_sdk::streaming::event_parser::protocols::bonk::{ pool_state_decode, types::PoolState, }; +/// Constants used as seeds for deriving PDAs (Program Derived Addresses) +pub mod seeds { + pub const POOL_SEED: &[u8] = b"pool"; + pub const POOL_VAULT_SEED: &[u8] = b"pool_vault"; +} + +/// Constants related to program accounts and authorities +pub mod accounts { + use solana_sdk::{pubkey, pubkey::Pubkey}; + + 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% +} + +pub const BUY_EXECT_IN_DISCRIMINATOR: [u8; 8] = [250, 234, 13, 123, 213, 156, 19, 236]; +pub const SELL_EXECT_IN_DISCRIMINATOR: [u8; 8] = [149, 39, 222, 155, 211, 124, 152, 26]; + pub async fn fetch_pool_state( rpc: &SolanaRpcClient, pool_address: &Pubkey, @@ -105,85 +128,29 @@ pub fn get_amount_out( } pub fn get_pool_pda(base_mint: &Pubkey, quote_mint: &Pubkey) -> Option { - let seeds: &[&[u8]; 3] = - &[constants::bonk::seeds::POOL_SEED, base_mint.as_ref(), quote_mint.as_ref()]; - let program_id: &Pubkey = &constants::bonk::accounts::BONK; + let seeds: &[&[u8]; 3] = &[seeds::POOL_SEED, base_mint.as_ref(), quote_mint.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_vault_pda(pool_state: &Pubkey, mint: &Pubkey) -> Option { - let seeds: &[&[u8]; 3] = - &[constants::bonk::seeds::POOL_VAULT_SEED, pool_state.as_ref(), mint.as_ref()]; - let program_id: &Pubkey = &constants::bonk::accounts::BONK; + let seeds: &[&[u8]; 3] = &[seeds::POOL_VAULT_SEED, pool_state.as_ref(), mint.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_platform_associated_account(platform_config: &Pubkey) -> Option { let seeds: &[&[u8]; 2] = &[platform_config.as_ref(), accounts::WSOL_TOKEN_ACCOUNT.as_ref()]; - let program_id: &Pubkey = &constants::bonk::accounts::BONK; + 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 program_id: &Pubkey = &constants::bonk::accounts::BONK; + let program_id: &Pubkey = &accounts::BONK; let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); pda.map(|pubkey| pubkey.0) } - -#[cfg(test)] -mod tests { - use crate::constants::bonk::accounts::{PLATFORM_FEE_RATE, PROTOCOL_FEE_RATE, SHARE_FEE_RATE}; - - use super::*; - - #[test] - fn test_amount_in_out_consistency() { - // 测试参数 - let protocol_fee_rate = PROTOCOL_FEE_RATE; - let platform_fee_rate = PLATFORM_FEE_RATE; - let share_fee_rate = SHARE_FEE_RATE; - let virtual_base = 1073025605596382; - let virtual_quote = 30000852951; - let real_base = 0; - let real_quote = 0; - let slippage_basis_points = 0; - - let original_amount_in = 2000000000; - - let geet_amount_out_result = get_amount_out( - original_amount_in, - protocol_fee_rate, - platform_fee_rate, - share_fee_rate, - virtual_base, - virtual_quote, - real_base, - real_quote, - slippage_basis_points, - ); - - let amount_out = 25959582643397; - let get_amount_in_result = get_amount_in( - amount_out, - protocol_fee_rate, - platform_fee_rate, - share_fee_rate, - virtual_base, - virtual_quote, - real_base, - real_quote, - slippage_basis_points, - ); - - println!("Original amount_in: {}", original_amount_in); - println!("Amount_out: {}", geet_amount_out_result); - println!("Calculated amount_in: {}", get_amount_in_result); - - assert!(geet_amount_out_result == 66275810509273); - assert!(get_amount_in_result == 753217040); - } -} diff --git a/src/instruction/utils/mod.rs b/src/instruction/utils/mod.rs new file mode 100644 index 0000000..cf75b01 --- /dev/null +++ b/src/instruction/utils/mod.rs @@ -0,0 +1,5 @@ +pub mod bonk; +pub mod pumpfun; +pub mod pumpswap; +pub mod raydium_amm_v4; +pub mod raydium_cpmm; diff --git a/src/instruction/utils/pumpfun.rs b/src/instruction/utils/pumpfun.rs new file mode 100644 index 0000000..d32b938 --- /dev/null +++ b/src/instruction/utils/pumpfun.rs @@ -0,0 +1,259 @@ +use crate::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; +use crate::{ + common::{bonding_curve::BondingCurveAccount, global::GlobalAccount, SolanaRpcClient}, + constants::{self, trade::trade::DEFAULT_SLIPPAGE}, +}; +use anyhow::anyhow; +use solana_sdk::pubkey::Pubkey; +use std::{collections::HashMap, sync::Arc}; +use tokio::sync::RwLock; + +/// Constants used as seeds for deriving PDAs (Program Derived Addresses) +pub mod seeds { + /// Seed for the global state PDA + pub const GLOBAL_SEED: &[u8] = b"global"; + + /// Seed for the mint authority PDA + pub const MINT_AUTHORITY_SEED: &[u8] = b"mint-authority"; + + /// Seed for bonding curve PDAs + pub const BONDING_CURVE_SEED: &[u8] = b"bonding-curve"; + + /// Seed for creator vault PDAs + pub const CREATOR_VAULT_SEED: &[u8] = b"creator-vault"; + + /// Seed for metadata PDAs + pub const METADATA_SEED: &[u8] = b"metadata"; + + /// Seed for user volume accumulator PDAs + pub const USER_VOLUME_ACCUMULATOR_SEED: &[u8] = b"user_volume_accumulator"; + + /// Seed for global volume accumulator PDAs + pub const GLOBAL_VOLUME_ACCUMULATOR_SEED: &[u8] = b"global_volume_accumulator"; + + pub const FEE_CONFIG_SEED: &[u8] = b"fee_config"; +} + +pub mod global_constants { + use solana_sdk::{pubkey, pubkey::Pubkey}; + + pub const INITIAL_VIRTUAL_TOKEN_RESERVES: u64 = 1_073_000_000_000_000; + + pub const INITIAL_VIRTUAL_SOL_RESERVES: u64 = 30_000_000_000; + + pub const INITIAL_REAL_TOKEN_RESERVES: u64 = 793_100_000_000_000; + + pub const TOKEN_TOTAL_SUPPLY: u64 = 1_000_000_000_000_000; + + pub const FEE_BASIS_POINTS: u64 = 95; + + pub const ENABLE_MIGRATE: bool = false; + + pub const POOL_MIGRATION_FEE: u64 = 15_000_001; + + pub const CREATOR_FEE: u64 = 5; + + pub const SCALE: u64 = 1_000_000; // 10^6 for token decimals + + pub const LAMPORTS_PER_SOL: u64 = 1_000_000_000; // 10^9 for solana lamports + + pub const COMPLETION_LAMPORTS: u64 = 85 * LAMPORTS_PER_SOL; // ~ 85 SOL + + /// Public key for the fee recipient + pub const FEE_RECIPIENT: Pubkey = pubkey!("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"); + + /// Public key for the global PDA + pub const GLOBAL_ACCOUNT: Pubkey = pubkey!("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf"); + + /// Public key for the authority + pub const AUTHORITY: Pubkey = pubkey!("FFWtrEQ4B4PKQoVuHYzZq8FabGkVatYzDpEVHsK5rrhF"); + + /// Public key for the withdraw authority + pub const WITHDRAW_AUTHORITY: Pubkey = pubkey!("39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg"); + + pub const PUMPFUN_AMM_FEE_1: Pubkey = pubkey!("7VtfL8fvgNfhz17qKRMjzQEXgbdpnHHHQRh54R9jP2RJ"); // Pump.fun AMM: Protocol Fee 1 + pub const PUMPFUN_AMM_FEE_2: Pubkey = pubkey!("7hTckgnGnLQR6sdH7YkqFTAA7VwTfYFaZ6EhEsU3saCX"); // Pump.fun AMM: Protocol Fee 2 + pub const PUMPFUN_AMM_FEE_3: Pubkey = pubkey!("9rPYyANsfQZw3DnDmKE3YCQF5E8oD89UXoHn9JFEhJUz"); // Pump.fun AMM: Protocol Fee 3 + pub const PUMPFUN_AMM_FEE_4: Pubkey = pubkey!("AVmoTthdrX6tKt4nDjco2D775W2YK3sDhxPcMmzUAmTY"); // Pump.fun AMM: Protocol Fee 4 + pub const PUMPFUN_AMM_FEE_5: Pubkey = pubkey!("CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM"); // Pump.fun AMM: Protocol Fee 5 + pub const PUMPFUN_AMM_FEE_6: Pubkey = pubkey!("FWsW1xNtWscwNmKv6wVsU1iTzRN6wmmk3MjxRP5tT7hz"); // Pump.fun AMM: Protocol Fee 6 + pub const PUMPFUN_AMM_FEE_7: Pubkey = pubkey!("G5UZAVbAf46s7cKWoyKu8kYTip9DGTpbLZ2qa9Aq69dP"); + // Pump.fun AMM: Protocol Fee 7 +} + +/// Constants related to program accounts and authorities +pub mod accounts { + use solana_sdk::{pubkey, pubkey::Pubkey}; + + /// Public key for the Pump.fun program + pub const PUMPFUN: Pubkey = pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"); + + /// Public key for the MPL Token Metadata program + pub const MPL_TOKEN_METADATA: Pubkey = pubkey!("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); + + /// 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"); + + /// Rent Sysvar ID + pub const RENT: Pubkey = pubkey!("SysvarRent111111111111111111111111111111111"); + + pub const AMM_PROGRAM: Pubkey = pubkey!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); + + pub const FEE_PROGRAM: Pubkey = pubkey!("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"); +} + +pub struct Symbol; + +impl Symbol { + pub const SOLANA: &'static str = "solana"; +} + +lazy_static::lazy_static! { + static ref ACCOUNT_CACHE: RwLock>> = RwLock::new(HashMap::new()); +} + +#[inline] +pub fn get_global_pda() -> Pubkey { + static GLOBAL_PDA: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { + Pubkey::find_program_address(&[seeds::GLOBAL_SEED], &accounts::PUMPFUN).0 + }); + *GLOBAL_PDA +} + +#[inline] +pub fn get_mint_authority_pda() -> Pubkey { + static MINT_AUTHORITY_PDA: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { + Pubkey::find_program_address(&[seeds::MINT_AUTHORITY_SEED], &accounts::PUMPFUN).0 + }); + *MINT_AUTHORITY_PDA +} + +#[inline] +pub fn get_bonding_curve_pda(mint: &Pubkey) -> Option { + let seeds: &[&[u8]; 2] = &[seeds::BONDING_CURVE_SEED, mint.as_ref()]; + let program_id: &Pubkey = &accounts::PUMPFUN; + let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); + pda.map(|pubkey| pubkey.0) +} + +#[inline] +pub fn get_creator_vault_pda(creator: &Pubkey) -> Option { + let seeds: &[&[u8]; 2] = &[seeds::CREATOR_VAULT_SEED, creator.as_ref()]; + let program_id: &Pubkey = &accounts::PUMPFUN; + let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); + pda.map(|pubkey| pubkey.0) +} + +#[inline] +pub fn get_user_volume_accumulator_pda(user: &Pubkey) -> Option { + let seeds: &[&[u8]; 2] = &[seeds::USER_VOLUME_ACCUMULATOR_SEED, user.as_ref()]; + let program_id: &Pubkey = &accounts::PUMPFUN; + let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); + pda.map(|pubkey| pubkey.0) +} + +#[inline] +pub fn get_global_volume_accumulator_pda() -> Option { + let seeds: &[&[u8]; 1] = &[seeds::GLOBAL_VOLUME_ACCUMULATOR_SEED]; + let program_id: &Pubkey = &accounts::PUMPFUN; + let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); + pda.map(|pubkey| pubkey.0) +} + +#[inline] +pub fn get_fee_config_pda() -> Option { + let seeds: &[&[u8]; 2] = &[seeds::FEE_CONFIG_SEED, accounts::PUMPFUN.as_ref()]; + let program_id: &Pubkey = &accounts::FEE_PROGRAM; + let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); + pda.map(|pubkey| pubkey.0) +} + +#[inline] +pub fn get_metadata_pda(mint: &Pubkey) -> Pubkey { + Pubkey::find_program_address( + &[seeds::METADATA_SEED, accounts::MPL_TOKEN_METADATA.as_ref(), mint.as_ref()], + &accounts::MPL_TOKEN_METADATA, + ) + .0 +} + +#[inline] +pub async fn get_global_account(/*rpc: &SolanaRpcClient*/ +) -> Result, anyhow::Error> { + let global_account = GlobalAccount::new(); + let global_account = Arc::new(global_account); + Ok(global_account) +} + +#[inline] +pub async fn get_initial_buy_price( + global_account: &Arc, + amount_sol: u64, +) -> Result { + let buy_amount = global_account.get_initial_buy_price(amount_sol); + Ok(buy_amount) +} + +#[inline] +pub async fn fetch_bonding_curve_account( + rpc: &SolanaRpcClient, + mint: &Pubkey, +) -> Result<(Arc, Pubkey), anyhow::Error>{ + let bonding_curve_pda: Pubkey = + get_bonding_curve_pda(mint).ok_or(anyhow!("Bonding curve not found"))?; + + let account = rpc.get_account(&bonding_curve_pda).await?; + if account.data.is_empty() { + return Err(anyhow!("Bonding curve not found")); + } + + let bonding_curve = solana_sdk::borsh1::try_from_slice_unchecked::(&account.data[8..]) + .map_err(|e| anyhow::anyhow!("Failed to deserialize bonding curve account: {}", e))?; + + Ok((Arc::new(bonding_curve), bonding_curve_pda)) +} + +#[inline] +pub async fn init_bonding_curve_account( + mint: &Pubkey, + dev_buy_token: u64, + dev_sol_cost: u64, + creator: Pubkey, +) -> Result, anyhow::Error> { + let bonding_curve = + BondingCurveAccount::from_dev_trade(mint, dev_buy_token, dev_sol_cost, creator); + let bonding_curve = Arc::new(bonding_curve); + Ok(bonding_curve) +} + +#[inline] +pub fn get_buy_amount_with_slippage(amount_sol: u64, slippage_basis_points: Option) -> u64 { + let slippage = slippage_basis_points.unwrap_or(DEFAULT_SLIPPAGE); + amount_sol + (amount_sol * slippage / 10000) +} + +#[inline] +pub fn get_buy_price(amount: u64, trade_info: &PumpFunTradeEvent) -> u64 { + if amount == 0 { + return 0; + } + + let n: u128 = + (trade_info.virtual_sol_reserves as u128) * (trade_info.virtual_token_reserves as u128); + let i: u128 = (trade_info.virtual_sol_reserves as u128) + (amount as u128); + let r: u128 = n / i + 1; + let s: u128 = (trade_info.virtual_token_reserves as u128) - r; + let s_u64 = s as u64; + + s_u64.min(trade_info.real_token_reserves) +} diff --git a/src/trading/pumpswap/common.rs b/src/instruction/utils/pumpswap.rs old mode 100755 new mode 100644 similarity index 66% rename from src/trading/pumpswap/common.rs rename to src/instruction/utils/pumpswap.rs index d53bbad..5a59380 --- a/src/trading/pumpswap/common.rs +++ b/src/instruction/utils/pumpswap.rs @@ -1,10 +1,72 @@ -use crate::constants::pumpswap::accounts; use crate::{common::SolanaRpcClient, constants}; use anyhow::anyhow; use solana_account_decoder::UiAccountEncoding; use solana_sdk::pubkey::Pubkey; use solana_streamer_sdk::streaming::event_parser::protocols::pumpswap::types::{pool_decode, Pool}; +/// Constants used as seeds for deriving PDAs (Program Derived Addresses) +pub mod seeds { + /// Seed for the global state PDA + pub const GLOBAL_SEED: &[u8] = b"global"; + + /// Seed for the mint authority PDA + pub const MINT_AUTHORITY_SEED: &[u8] = b"mint-authority"; + + /// Seed for bonding curve PDAs + pub const BONDING_CURVE_SEED: &[u8] = b"bonding-curve"; + + /// Seed for metadata PDAs + pub const METADATA_SEED: &[u8] = b"metadata"; + + pub const USER_VOLUME_ACCUMULATOR_SEED: &[u8] = b"user_volume_accumulator"; + pub const GLOBAL_VOLUME_ACCUMULATOR_SEED: &[u8] = b"global_volume_accumulator"; + pub const FEE_CONFIG_SEED: &[u8] = b"fee_config"; +} + +/// Constants related to program accounts and authorities +pub mod accounts { + use solana_sdk::{pubkey, pubkey::Pubkey}; + + /// Public key for the fee recipient + pub const FEE_RECIPIENT: Pubkey = pubkey!("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"); + + /// Public key for the global PDA + pub const GLOBAL_ACCOUNT: Pubkey = pubkey!("ADyA8hdefvWN2dbGGWFotbzWxrAvLW83WG6QCVXvJKqw"); + + /// 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"); + + // PumpSwap 协议费用接收者 + 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; + pub const PROTOCOL_FEE_BASIS_POINTS: u64 = 5; + pub const COIN_CREATOR_FEE_BASIS_POINTS: u64 = 5; + + pub const FEE_PROGRAM: Pubkey = pubkey!("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"); +} + +pub const BUY_DISCRIMINATOR: [u8; 8] = [102, 6, 61, 18, 1, 218, 235, 234]; +pub const SELL_DISCRIMINATOR: [u8; 8] = [51, 230, 133, 164, 1, 127, 131, 173]; + // Find a pool for a specific mint pub async fn find_pool(rpc: &SolanaRpcClient, mint: &Pubkey) -> Result { let (pool_address, _) = find_by_mint(rpc, mint).await?; @@ -14,7 +76,7 @@ pub async fn find_pool(rpc: &SolanaRpcClient, mint: &Pubkey) -> Result Pubkey { let (pump_pool_authority, _) = Pubkey::find_program_address( &[b"creator_vault", &coin_creator.to_bytes()], - &crate::constants::pumpswap::accounts::AMM_PROGRAM, + &accounts::AMM_PROGRAM, ); pump_pool_authority } @@ -25,7 +87,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, - &crate::constants::pumpswap::accounts::TOKEN_PROGRAM, + &accounts::TOKEN_PROGRAM, ); associated_token_creator_vault_authority } @@ -35,22 +97,21 @@ 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, - &crate::constants::pumpswap::accounts::TOKEN_PROGRAM, + &accounts::TOKEN_PROGRAM, ); associated_token_fee_recipient } pub fn get_user_volume_accumulator_pda(user: &Pubkey) -> Option { - let seeds: &[&[u8]; 2] = - &[&crate::constants::pumpswap::seeds::USER_VOLUME_ACCUMULATOR_SEED, user.as_ref()]; - let program_id: &Pubkey = &&crate::constants::pumpswap::accounts::AMM_PROGRAM; + let seeds: &[&[u8]; 2] = &[&seeds::USER_VOLUME_ACCUMULATOR_SEED, user.as_ref()]; + let program_id: &Pubkey = &&accounts::AMM_PROGRAM; let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); pda.map(|pubkey| pubkey.0) } pub fn get_global_volume_accumulator_pda() -> Option { - let seeds: &[&[u8]; 1] = &[&crate::constants::pumpswap::seeds::GLOBAL_VOLUME_ACCUMULATOR_SEED]; - let program_id: &Pubkey = &&crate::constants::pumpswap::accounts::AMM_PROGRAM; + let seeds: &[&[u8]; 1] = &[&seeds::GLOBAL_VOLUME_ACCUMULATOR_SEED]; + let program_id: &Pubkey = &&accounts::AMM_PROGRAM; let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); pda.map(|pubkey| pubkey.0) } @@ -89,7 +150,7 @@ pub async fn find_by_base_mint( with_context: None, sort_results: None, }; - let program_id = crate::constants::pumpswap::accounts::AMM_PROGRAM; + let program_id = accounts::AMM_PROGRAM; let accounts = rpc.get_program_accounts_with_config(&program_id, config).await?; if accounts.is_empty() { return Err(anyhow!("No pool found for mint {}", base_mint)); @@ -125,7 +186,7 @@ pub async fn find_by_quote_mint( with_context: None, sort_results: None, }; - let program_id = crate::constants::pumpswap::accounts::AMM_PROGRAM; + let program_id = accounts::AMM_PROGRAM; let accounts = rpc.get_program_accounts_with_config(&program_id, config).await?; if accounts.is_empty() { return Err(anyhow!("No pool found for mint {}", quote_mint)); @@ -167,11 +228,8 @@ pub async fn get_token_balances( #[inline] pub fn get_fee_config_pda() -> Option { - let seeds: &[&[u8]; 2] = &[ - constants::pumpswap::seeds::FEE_CONFIG_SEED, - constants::pumpswap::accounts::AMM_PROGRAM.as_ref(), - ]; - let program_id: &Pubkey = &constants::pumpswap::accounts::FEE_PROGRAM; + let seeds: &[&[u8]; 2] = &[seeds::FEE_CONFIG_SEED, accounts::AMM_PROGRAM.as_ref()]; + let program_id: &Pubkey = &accounts::FEE_PROGRAM; let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); pda.map(|pubkey| pubkey.0) } diff --git a/src/constants/raydium_amm_v4.rs b/src/instruction/utils/raydium_amm_v4.rs old mode 100755 new mode 100644 similarity index 64% rename from src/constants/raydium_amm_v4.rs rename to src/instruction/utils/raydium_amm_v4.rs index 6c44296..a7c99f2 --- a/src/constants/raydium_amm_v4.rs +++ b/src/instruction/utils/raydium_amm_v4.rs @@ -1,14 +1,10 @@ -//! Constants used by the crate. -//! -//! This module contains various constants used throughout the crate, including: -//! -//! - Seeds for deriving Program Derived Addresses (PDAs) -//! - Program account addresses and public keys -//! -//! The constants are organized into submodules for better organization: -//! -//! - `seeds`: Contains seed values used for PDA derivation -//! - `accounts`: Contains important program account addresses +use anyhow::anyhow; +use solana_sdk::pubkey::Pubkey; +use solana_streamer_sdk::streaming::event_parser::protocols::raydium_amm_v4::types::{ + amm_info_decode, AmmInfo, +}; + +use crate::common::SolanaRpcClient; /// Constants used as seeds for deriving PDAs (Program Derived Addresses) pub mod seeds { @@ -31,3 +27,10 @@ pub mod accounts { pub const SWAP_BASE_IN_DISCRIMINATOR: &[u8] = &[9]; pub const SWAP_BASE_OUT_DISCRIMINATOR: &[u8] = &[11]; + +pub async fn fetch_amm_info(rpc: &SolanaRpcClient, amm: Pubkey) -> Result { + let amm_info = rpc.get_account_data(&amm).await?; + let amm_info = + amm_info_decode(&amm_info).ok_or_else(|| anyhow!("Failed to decode amm info"))?; + Ok(amm_info) +} diff --git a/src/trading/raydium_cpmm/common.rs b/src/instruction/utils/raydium_cpmm.rs old mode 100755 new mode 100644 similarity index 56% rename from src/trading/raydium_cpmm/common.rs rename to src/instruction/utils/raydium_cpmm.rs index f35eff3..d8e5805 --- a/src/trading/raydium_cpmm/common.rs +++ b/src/instruction/utils/raydium_cpmm.rs @@ -1,16 +1,36 @@ -use crate::{ - common::SolanaRpcClient, - constants::{ - self, - raydium_cpmm::accounts::{self}, - }, -}; +use crate::common::SolanaRpcClient; use anyhow::anyhow; use solana_sdk::pubkey::Pubkey; use solana_streamer_sdk::streaming::event_parser::protocols::raydium_cpmm::types::{ pool_state_decode, PoolState, }; +/// Constants used as seeds for deriving PDAs (Program Derived Addresses) +pub mod seeds { + pub const POOL_SEED: &[u8] = b"pool"; + pub const POOL_VAULT_SEED: &[u8] = b"pool_vault"; + pub const OBSERVATION_STATE_SEED: &[u8] = b"observation"; +} + +/// Constants related to program accounts and authorities +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; +} + +pub const SWAP_BASE_IN_DISCRIMINATOR: &[u8] = &[143, 190, 90, 218, 196, 30, 51, 222]; +pub const SWAP_BASE_OUT_DISCRIMINATOR: &[u8] = &[55, 217, 98, 86, 163, 74, 180, 173]; + pub async fn fetch_pool_state( rpc: &SolanaRpcClient, pool_address: &Pubkey, @@ -25,29 +45,23 @@ pub async fn fetch_pool_state( } pub fn get_pool_pda(amm_config: &Pubkey, mint1: &Pubkey, mint2: &Pubkey) -> Option { - let seeds: &[&[u8]; 4] = &[ - constants::raydium_cpmm::seeds::POOL_SEED, - amm_config.as_ref(), - mint1.as_ref(), - mint2.as_ref(), - ]; - let program_id: &Pubkey = &constants::raydium_cpmm::accounts::RAYDIUM_CPMM; + let seeds: &[&[u8]; 4] = + &[seeds::POOL_SEED, amm_config.as_ref(), mint1.as_ref(), mint2.as_ref()]; + let program_id: &Pubkey = &accounts::RAYDIUM_CPMM; let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); pda.map(|pubkey| pubkey.0) } pub fn get_vault_pda(pool_state: &Pubkey, mint: &Pubkey) -> Option { - let seeds: &[&[u8]; 3] = - &[constants::raydium_cpmm::seeds::POOL_VAULT_SEED, pool_state.as_ref(), mint.as_ref()]; - let program_id: &Pubkey = &constants::raydium_cpmm::accounts::RAYDIUM_CPMM; + let seeds: &[&[u8]; 3] = &[seeds::POOL_VAULT_SEED, pool_state.as_ref(), mint.as_ref()]; + let program_id: &Pubkey = &accounts::RAYDIUM_CPMM; let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); pda.map(|pubkey| pubkey.0) } pub fn get_observation_state_pda(pool_state: &Pubkey) -> Option { - let seeds: &[&[u8]; 2] = - &[constants::raydium_cpmm::seeds::OBSERVATION_STATE_SEED, pool_state.as_ref()]; - let program_id: &Pubkey = &constants::raydium_cpmm::accounts::RAYDIUM_CPMM; + let seeds: &[&[u8]; 2] = &[seeds::OBSERVATION_STATE_SEED, pool_state.as_ref()]; + let program_id: &Pubkey = &accounts::RAYDIUM_CPMM; let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); pda.map(|pubkey| pubkey.0) } @@ -96,38 +110,3 @@ pub async fn calculate_price( let price = token1_adjusted / token0_adjusted; Ok(price) } - -#[cfg(test)] -mod tests { - use super::*; - use solana_sdk::pubkey; - - #[test] - fn test_get_pool_pda() { - // 测试get_pool_pda函数 - let amm_config = constants::raydium_cpmm::accounts::AMM_CONFIG; - let input_mint = pubkey!("So11111111111111111111111111111111111111112"); // WSOL - let output_mint = pubkey!("BnwbwoqPm5ZNx7YTJ8g9jR2qCpYeHBC7xxpU8zEtbonk"); // USDC - let pool_state = pubkey!("E9rRRpcdsKAseeLFbwC1Ewxd3aYG27meqwTTrMfCTbSG"); - let result = get_pool_pda(&amm_config, &input_mint, &output_mint); - assert_eq!(result, Some(pool_state)); - } - - #[test] - fn test_get_vault_pda() { - // 测试get_vault_pda函数 - let pool_state = pubkey!("HBMkgQvt4NAFx6XzNav23bNcv6K3oiC5UfY3JsE22scY"); - let mint = pubkey!("DeESECsL3cLXno1LFquss98kNQSno1xpQC2ERCqSbonk"); // WSOL - let vault_pda = pubkey!("7rkgNG3A8z636DuzhchKeqAJTaH3H5ZFWmBQeStydovA"); - let result = get_vault_pda(&pool_state, &mint); - assert_eq!(result, Some(vault_pda)); - } - - #[test] - fn test_get_observation_state_pda() { - let pool_state = pubkey!("HBMkgQvt4NAFx6XzNav23bNcv6K3oiC5UfY3JsE22scY"); - let observation_state_pda = pubkey!("Gq8u9N18ASjq3AK2gCk6RtGSNyjXZf9EZDb6vTtB9JRs"); - let result = get_observation_state_pda(&pool_state); - assert_eq!(result, Some(observation_state_pda)); - } -} diff --git a/src/trading/bonk/mod.rs b/src/trading/bonk/mod.rs deleted file mode 100755 index 34994bf..0000000 --- a/src/trading/bonk/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod common; diff --git a/src/trading/core/params.rs b/src/trading/core/params.rs index 4e92142..500cbfb 100755 --- a/src/trading/core/params.rs +++ b/src/trading/core/params.rs @@ -10,20 +10,9 @@ use std::sync::Arc; use super::traits::ProtocolParams; use crate::common::bonding_curve::BondingCurveAccount; use crate::common::{PriorityFee, SolanaRpcClient}; -use crate::constants::bonk::accounts::{ - self, PLATFORM_FEE_RATE, PROTOCOL_FEE_RATE, SHARE_FEE_RATE, -}; use crate::solana_streamer_sdk::streaming::event_parser::common::EventType; use crate::solana_streamer_sdk::streaming::event_parser::protocols::bonk::BonkTradeEvent; -use crate::trading::bonk::common::{ - get_amount_in, get_amount_in_net, get_amount_out, get_creator_associated_account, - get_platform_associated_account, -}; use crate::trading::common::get_multi_token_balances; -use crate::trading::pumpswap::common::{ - coin_creator_vault_ata, coin_creator_vault_authority, get_token_balances, -}; -use crate::trading::raydium_cpmm::common::get_pool_token_balances; /// Buy parameters #[derive(Clone)] pub struct BuyParams { @@ -185,24 +174,28 @@ impl PumpSwapParams { rpc: &SolanaRpcClient, pool_address: &Pubkey, ) -> Result { - let pool_data = crate::trading::pumpswap::common::fetch_pool(rpc, pool_address).await?; + let pool_data = crate::instruction::utils::pumpswap::fetch_pool(rpc, pool_address).await?; let (pool_base_token_reserves, pool_quote_token_reserves) = - get_token_balances(&pool_data, rpc).await?; + crate::instruction::utils::pumpswap::get_token_balances(&pool_data, rpc).await?; let creator = pool_data.creator; - let coin_creator_vault_ata = coin_creator_vault_ata(creator, pool_data.quote_mint); - let coin_creator_vault_authority = coin_creator_vault_authority(creator); + let coin_creator_vault_ata = crate::instruction::utils::pumpswap::coin_creator_vault_ata( + creator, + pool_data.quote_mint, + ); + let coin_creator_vault_authority = + crate::instruction::utils::pumpswap::coin_creator_vault_authority(creator); let base_token_program_ata = spl_associated_token_account::get_associated_token_address_with_program_id( &pool_address, &pool_data.base_mint, - &accounts::TOKEN_PROGRAM, + &crate::instruction::utils::pumpswap::accounts::TOKEN_PROGRAM, ); let quote_token_program_ata = spl_associated_token_account::get_associated_token_address_with_program_id( &pool_address, &pool_data.quote_mint, - &accounts::TOKEN_PROGRAM, + &crate::instruction::utils::pumpswap::accounts::TOKEN_PROGRAM, ); Ok(Self { @@ -214,12 +207,12 @@ 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 { - accounts::TOKEN_PROGRAM + crate::instruction::utils::pumpswap::accounts::TOKEN_PROGRAM } else { spl_token_2022::ID }, quote_token_program: if pool_data.pool_quote_token_account == quote_token_program_ata { - accounts::TOKEN_PROGRAM + crate::instruction::utils::pumpswap::accounts::TOKEN_PROGRAM } else { spl_token_2022::ID }, @@ -291,11 +284,11 @@ impl BonkParams { let amount_in = if trade_info.metadata.event_type == EventType::BonkBuyExactIn { trade_info.amount_in } else { - get_amount_in( + crate::instruction::utils::bonk::get_amount_in( trade_info.amount_out, - PROTOCOL_FEE_RATE, - PLATFORM_FEE_RATE, - SHARE_FEE_RATE, + crate::instruction::utils::bonk::accounts::PROTOCOL_FEE_RATE, + crate::instruction::utils::bonk::accounts::PLATFORM_FEE_RATE, + crate::instruction::utils::bonk::accounts::SHARE_FEE_RATE, DEFAULT_VIRTUAL_BASE, DEFAULT_VIRTUAL_QUOTE, 0, @@ -303,15 +296,18 @@ impl BonkParams { 0, ) }; - let real_quote = - get_amount_in_net(amount_in, PROTOCOL_FEE_RATE, PLATFORM_FEE_RATE, SHARE_FEE_RATE) - as u128; + let real_quote = crate::instruction::utils::bonk::get_amount_in_net( + amount_in, + crate::instruction::utils::bonk::accounts::PROTOCOL_FEE_RATE, + crate::instruction::utils::bonk::accounts::PLATFORM_FEE_RATE, + crate::instruction::utils::bonk::accounts::SHARE_FEE_RATE, + ) as u128; let amount_out = if trade_info.metadata.event_type == EventType::BonkBuyExactIn { - get_amount_out( + crate::instruction::utils::bonk::get_amount_out( trade_info.amount_in, - PROTOCOL_FEE_RATE, - PLATFORM_FEE_RATE, - SHARE_FEE_RATE, + crate::instruction::utils::bonk::accounts::PROTOCOL_FEE_RATE, + crate::instruction::utils::bonk::accounts::PLATFORM_FEE_RATE, + crate::instruction::utils::bonk::accounts::SHARE_FEE_RATE, DEFAULT_VIRTUAL_BASE, DEFAULT_VIRTUAL_QUOTE, 0, @@ -339,14 +335,20 @@ impl BonkParams { rpc: &SolanaRpcClient, mint: &Pubkey, ) -> Result { - let pool_address = - crate::trading::bonk::common::get_pool_pda(mint, &accounts::WSOL_TOKEN_ACCOUNT) - .unwrap(); - let pool_data = crate::trading::bonk::common::fetch_pool_state(rpc, &pool_address).await?; + let pool_address = crate::instruction::utils::bonk::get_pool_pda( + mint, + &crate::instruction::utils::bonk::accounts::WSOL_TOKEN_ACCOUNT, + ) + .unwrap(); + let pool_data = + crate::instruction::utils::bonk::fetch_pool_state(rpc, &pool_address).await?; let token_account = rpc.get_account(&pool_data.base_mint).await?; let platform_associated_account = - get_platform_associated_account(&pool_data.platform_config); - let creator_associated_account = get_creator_associated_account(&pool_data.creator); + crate::instruction::utils::bonk::get_platform_associated_account( + &pool_data.platform_config, + ); + let creator_associated_account = + crate::instruction::utils::bonk::get_creator_associated_account(&pool_data.creator); let platform_associated_account = platform_associated_account.unwrap(); let creator_associated_account = creator_associated_account.unwrap(); Ok(Self { @@ -399,10 +401,15 @@ impl RaydiumCpmmParams { pool_address: &Pubkey, ) -> Result { let pool = - crate::trading::raydium_cpmm::common::fetch_pool_state(rpc, pool_address).await?; + crate::instruction::utils::raydium_cpmm::fetch_pool_state(rpc, pool_address).await?; let (token0_balance, token1_balance) = - get_pool_token_balances(rpc, pool_address, &pool.token0_mint, &pool.token1_mint) - .await?; + crate::instruction::utils::raydium_cpmm::get_pool_token_balances( + rpc, + pool_address, + &pool.token0_mint, + &pool.token1_mint, + ) + .await?; Ok(Self { base_mint: pool.token0_mint, quote_mint: pool.token1_mint, @@ -469,7 +476,7 @@ impl RaydiumAmmV4Params { rpc: &SolanaRpcClient, amm: Pubkey, ) -> Result { - let amm_info = crate::trading::raydium_amm_v4::common::fetch_amm_info(rpc, amm).await?; + let amm_info = crate::instruction::utils::raydium_amm_v4::fetch_amm_info(rpc, amm).await?; let (coin_reserve, pc_reserve) = get_multi_token_balances(rpc, &amm_info.token_coin, &amm_info.token_pc).await?; Ok(Self { diff --git a/src/trading/mod.rs b/src/trading/mod.rs index 1d879d8..c8d5d8d 100755 --- a/src/trading/mod.rs +++ b/src/trading/mod.rs @@ -1,12 +1,7 @@ -pub mod bonk; pub mod common; pub mod core; pub mod factory; pub mod middleware; -pub mod pumpfun; -pub mod pumpswap; -pub mod raydium_amm_v4; -pub mod raydium_cpmm; pub use core::params::{BuyParams, SellParams}; pub use core::traits::{InstructionBuilder, TradeExecutor}; diff --git a/src/trading/pumpfun/common.rs b/src/trading/pumpfun/common.rs deleted file mode 100755 index 19c723a..0000000 --- a/src/trading/pumpfun/common.rs +++ /dev/null @@ -1,169 +0,0 @@ -use crate::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; -use crate::{ - common::{ - bonding_curve::BondingCurveAccount, global::GlobalAccount, PriorityFee, SolanaRpcClient, - }, - constants::{self, trade::trade::DEFAULT_SLIPPAGE}, -}; -use anyhow::anyhow; -use solana_sdk::{ - compute_budget::ComputeBudgetInstruction, instruction::Instruction, pubkey::Pubkey, -}; -use std::{collections::HashMap, sync::Arc}; -use tokio::sync::RwLock; - -lazy_static::lazy_static! { - static ref ACCOUNT_CACHE: RwLock>> = RwLock::new(HashMap::new()); -} - -#[inline] -pub fn get_global_pda() -> Pubkey { - static GLOBAL_PDA: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { - Pubkey::find_program_address( - &[constants::pumpfun::seeds::GLOBAL_SEED], - &constants::pumpfun::accounts::PUMPFUN, - ) - .0 - }); - *GLOBAL_PDA -} - -#[inline] -pub fn get_mint_authority_pda() -> Pubkey { - static MINT_AUTHORITY_PDA: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { - Pubkey::find_program_address( - &[constants::pumpfun::seeds::MINT_AUTHORITY_SEED], - &constants::pumpfun::accounts::PUMPFUN, - ) - .0 - }); - *MINT_AUTHORITY_PDA -} - -#[inline] -pub fn get_bonding_curve_pda(mint: &Pubkey) -> Option { - let seeds: &[&[u8]; 2] = &[constants::pumpfun::seeds::BONDING_CURVE_SEED, mint.as_ref()]; - let program_id: &Pubkey = &constants::pumpfun::accounts::PUMPFUN; - let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); - pda.map(|pubkey| pubkey.0) -} - -#[inline] -pub fn get_creator_vault_pda(creator: &Pubkey) -> Option { - let seeds: &[&[u8]; 2] = &[constants::pumpfun::seeds::CREATOR_VAULT_SEED, creator.as_ref()]; - let program_id: &Pubkey = &constants::pumpfun::accounts::PUMPFUN; - let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); - pda.map(|pubkey| pubkey.0) -} - -#[inline] -pub fn get_user_volume_accumulator_pda(user: &Pubkey) -> Option { - let seeds: &[&[u8]; 2] = - &[constants::pumpfun::seeds::USER_VOLUME_ACCUMULATOR_SEED, user.as_ref()]; - let program_id: &Pubkey = &constants::pumpfun::accounts::PUMPFUN; - let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); - pda.map(|pubkey| pubkey.0) -} - -#[inline] -pub fn get_global_volume_accumulator_pda() -> Option { - let seeds: &[&[u8]; 1] = &[constants::pumpfun::seeds::GLOBAL_VOLUME_ACCUMULATOR_SEED]; - let program_id: &Pubkey = &constants::pumpfun::accounts::PUMPFUN; - let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); - pda.map(|pubkey| pubkey.0) -} - -#[inline] -pub fn get_fee_config_pda() -> Option { - let seeds: &[&[u8]; 2] = &[ - constants::pumpfun::seeds::FEE_CONFIG_SEED, - constants::pumpfun::accounts::PUMPFUN.as_ref(), - ]; - let program_id: &Pubkey = &constants::pumpfun::accounts::FEE_PROGRAM; - let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id); - pda.map(|pubkey| pubkey.0) -} - -#[inline] -pub fn get_metadata_pda(mint: &Pubkey) -> Pubkey { - Pubkey::find_program_address( - &[ - constants::pumpfun::seeds::METADATA_SEED, - constants::pumpfun::accounts::MPL_TOKEN_METADATA.as_ref(), - mint.as_ref(), - ], - &constants::pumpfun::accounts::MPL_TOKEN_METADATA, - ) - .0 -} - -#[inline] -pub async fn get_global_account(/*rpc: &SolanaRpcClient*/ -) -> Result, anyhow::Error> { - let global_account = GlobalAccount::new(); - let global_account = Arc::new(global_account); - Ok(global_account) -} - -#[inline] -pub async fn get_initial_buy_price( - global_account: &Arc, - amount_sol: u64, -) -> Result { - let buy_amount = global_account.get_initial_buy_price(amount_sol); - Ok(buy_amount) -} - -#[inline] -pub async fn fetch_bonding_curve_account( - rpc: &SolanaRpcClient, - mint: &Pubkey, -) -> Result<(Arc, Pubkey), anyhow::Error>{ - let bonding_curve_pda: Pubkey = - get_bonding_curve_pda(mint).ok_or(anyhow!("Bonding curve not found"))?; - - let account = rpc.get_account(&bonding_curve_pda).await?; - if account.data.is_empty() { - return Err(anyhow!("Bonding curve not found")); - } - - let bonding_curve = solana_sdk::borsh1::try_from_slice_unchecked::(&account.data[8..]) - .map_err(|e| anyhow::anyhow!("Failed to deserialize bonding curve account: {}", e))?; - - Ok((Arc::new(bonding_curve), bonding_curve_pda)) -} - -#[inline] -pub async fn init_bonding_curve_account( - mint: &Pubkey, - dev_buy_token: u64, - dev_sol_cost: u64, - creator: Pubkey, -) -> Result, anyhow::Error> { - let bonding_curve = - BondingCurveAccount::from_dev_trade(mint, dev_buy_token, dev_sol_cost, creator); - let bonding_curve = Arc::new(bonding_curve); - Ok(bonding_curve) -} - -#[inline] -pub fn get_buy_amount_with_slippage(amount_sol: u64, slippage_basis_points: Option) -> u64 { - let slippage = slippage_basis_points.unwrap_or(DEFAULT_SLIPPAGE); - amount_sol + (amount_sol * slippage / 10000) -} - -#[inline] -pub fn get_buy_price(amount: u64, trade_info: &PumpFunTradeEvent) -> u64 { - if amount == 0 { - return 0; - } - - let n: u128 = - (trade_info.virtual_sol_reserves as u128) * (trade_info.virtual_token_reserves as u128); - let i: u128 = (trade_info.virtual_sol_reserves as u128) + (amount as u128); - let r: u128 = n / i + 1; - let s: u128 = (trade_info.virtual_token_reserves as u128) - r; - let s_u64 = s as u64; - - s_u64.min(trade_info.real_token_reserves) -} diff --git a/src/trading/pumpfun/mod.rs b/src/trading/pumpfun/mod.rs deleted file mode 100755 index 34994bf..0000000 --- a/src/trading/pumpfun/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod common; diff --git a/src/trading/pumpswap/mod.rs b/src/trading/pumpswap/mod.rs deleted file mode 100755 index 34994bf..0000000 --- a/src/trading/pumpswap/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod common; diff --git a/src/trading/raydium_amm_v4/common.rs b/src/trading/raydium_amm_v4/common.rs deleted file mode 100755 index e0e849d..0000000 --- a/src/trading/raydium_amm_v4/common.rs +++ /dev/null @@ -1,14 +0,0 @@ -use anyhow::anyhow; -use solana_sdk::pubkey::Pubkey; -use solana_streamer_sdk::streaming::event_parser::protocols::raydium_amm_v4::types::{ - amm_info_decode, AmmInfo, -}; - -use crate::common::SolanaRpcClient; - -pub async fn fetch_amm_info(rpc: &SolanaRpcClient, amm: Pubkey) -> Result { - let amm_info = rpc.get_account_data(&amm).await?; - let amm_info = - amm_info_decode(&amm_info).ok_or_else(|| anyhow!("Failed to decode amm info"))?; - Ok(amm_info) -} diff --git a/src/trading/raydium_amm_v4/mod.rs b/src/trading/raydium_amm_v4/mod.rs deleted file mode 100755 index 34994bf..0000000 --- a/src/trading/raydium_amm_v4/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod common; diff --git a/src/trading/raydium_cpmm/mod.rs b/src/trading/raydium_cpmm/mod.rs deleted file mode 100755 index 34994bf..0000000 --- a/src/trading/raydium_cpmm/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod common; diff --git a/src/utils/calc/bonk.rs b/src/utils/calc/bonk.rs index 21a3d73..81ca51f 100644 --- a/src/utils/calc/bonk.rs +++ b/src/utils/calc/bonk.rs @@ -1,4 +1,4 @@ -use crate::constants::bonk::accounts; +use crate::instruction::utils::bonk::accounts; /// Calculates the amount of tokens to receive when buying with SOL /// diff --git a/src/utils/calc/pumpfun.rs b/src/utils/calc/pumpfun.rs index 275a14e..a15f94d 100644 --- a/src/utils/calc/pumpfun.rs +++ b/src/utils/calc/pumpfun.rs @@ -1,7 +1,7 @@ use solana_sdk::{native_token::sol_str_to_lamports, pubkey::Pubkey}; use crate::{ - constants::pumpfun::global_constants::{CREATOR_FEE, FEE_BASIS_POINTS}, + instruction::utils::pumpfun::global_constants::{CREATOR_FEE, FEE_BASIS_POINTS}, utils::calc::common::compute_fee, }; diff --git a/src/utils/calc/pumpswap.rs b/src/utils/calc/pumpswap.rs index 1364819..ed6dc99 100644 --- a/src/utils/calc/pumpswap.rs +++ b/src/utils/calc/pumpswap.rs @@ -1,7 +1,7 @@ use super::common::{ calculate_with_slippage_buy, calculate_with_slippage_sell, ceil_div, compute_fee, }; -use crate::constants::pumpswap::accounts::{ +use crate::instruction::utils::pumpswap::accounts::{ COIN_CREATOR_FEE_BASIS_POINTS, LP_FEE_BASIS_POINTS, PROTOCOL_FEE_BASIS_POINTS, }; use solana_sdk::pubkey::Pubkey; diff --git a/src/utils/calc/raydium_amm_v4.rs b/src/utils/calc/raydium_amm_v4.rs index 50c705f..59550b4 100644 --- a/src/utils/calc/raydium_amm_v4.rs +++ b/src/utils/calc/raydium_amm_v4.rs @@ -1,4 +1,4 @@ -use crate::constants::raydium_amm_v4::accounts::{ +use crate::instruction::utils::raydium_amm_v4::accounts::{ SWAP_FEE_DENOMINATOR, SWAP_FEE_NUMERATOR, TRADE_FEE_DENOMINATOR, TRADE_FEE_NUMERATOR, }; diff --git a/src/utils/calc/raydium_cpmm.rs b/src/utils/calc/raydium_cpmm.rs index 2b85c67..924a876 100644 --- a/src/utils/calc/raydium_cpmm.rs +++ b/src/utils/calc/raydium_cpmm.rs @@ -1,4 +1,4 @@ -use crate::constants::raydium_cpmm::accounts::{ +use crate::instruction::utils::raydium_cpmm::accounts::{ CREATOR_FEE_RATE, FEE_RATE_DENOMINATOR_VALUE, FUND_FEE_RATE, PROTOCOL_FEE_RATE, TRADE_FEE_RATE, }; @@ -176,7 +176,8 @@ pub fn compute_swap_amount( true, ); - let min_amount_out = ((swap_result.output_amount as f64) * (1.0 - (slippage_basis_points as f64) / 10000.0)) as u64; + let min_amount_out = ((swap_result.output_amount as f64) + * (1.0 - (slippage_basis_points as f64) / 10000.0)) as u64; let all_trade = swap_result.input_amount == amount_in; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 6f8c671..4387c27 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,5 +1,5 @@ -pub mod price; pub mod calc; +pub mod price; use crate::solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent; use crate::trading; @@ -62,7 +62,7 @@ impl SolanaTrade { #[inline] pub fn get_pumpfun_token_buy_price(&self, amount: u64, trade_info: &PumpFunTradeEvent) -> u64 { - trading::pumpfun::common::get_buy_price(amount, trade_info) + crate::instruction::utils::pumpfun::get_buy_price(amount, trade_info) } #[inline] @@ -71,7 +71,8 @@ impl SolanaTrade { mint: &Pubkey, ) -> Result { let (bonding_curve, _) = - trading::pumpfun::common::fetch_bonding_curve_account(&self.rpc, mint).await?; + crate::instruction::utils::pumpfun::fetch_bonding_curve_account(&self.rpc, mint) + .await?; let virtual_sol_reserves = bonding_curve.virtual_sol_reserves; let virtual_token_reserves = bonding_curve.virtual_token_reserves; @@ -85,7 +86,8 @@ impl SolanaTrade { mint: &Pubkey, ) -> Result { let (bonding_curve, _) = - trading::pumpfun::common::fetch_bonding_curve_account(&self.rpc, mint).await?; + crate::instruction::utils::pumpfun::fetch_bonding_curve_account(&self.rpc, mint) + .await?; let actual_sol_reserves = bonding_curve.real_sol_reserves; @@ -95,7 +97,8 @@ impl SolanaTrade { #[inline] pub async fn get_pumpfun_token_creator(&self, mint: &Pubkey) -> Result { let (bonding_curve, _) = - trading::pumpfun::common::fetch_bonding_curve_account(&self.rpc, mint).await?; + crate::instruction::utils::pumpfun::fetch_bonding_curve_account(&self.rpc, mint) + .await?; let creator = bonding_curve.creator; @@ -109,10 +112,10 @@ impl SolanaTrade { &self, pool_address: &Pubkey, ) -> Result { - let pool = trading::pumpswap::common::fetch_pool(&self.rpc, pool_address).await?; + let pool = crate::instruction::utils::pumpswap::fetch_pool(&self.rpc, pool_address).await?; let (base_amount, quote_amount) = - trading::pumpswap::common::get_token_balances(&pool, &self.rpc).await?; + crate::instruction::utils::pumpswap::get_token_balances(&pool, &self.rpc).await?; // Calculate price using constant product formula (x * y = k) // Price = quote_amount / base_amount @@ -130,10 +133,10 @@ impl SolanaTrade { &self, pool_address: &Pubkey, ) -> Result { - let pool = trading::pumpswap::common::fetch_pool(&self.rpc, pool_address).await?; + let pool = crate::instruction::utils::pumpswap::fetch_pool(&self.rpc, pool_address).await?; let (_, quote_amount) = - trading::pumpswap::common::get_token_balances(&pool, &self.rpc).await?; + crate::instruction::utils::pumpswap::get_token_balances(&pool, &self.rpc).await?; Ok(quote_amount) } @@ -143,10 +146,10 @@ impl SolanaTrade { &self, pool_address: &Pubkey, ) -> Result { - let pool = trading::pumpswap::common::fetch_pool(&self.rpc, pool_address).await?; + let pool = crate::instruction::utils::pumpswap::fetch_pool(&self.rpc, pool_address).await?; let (base_amount, _) = - trading::pumpswap::common::get_token_balances(&pool, &self.rpc).await?; + crate::instruction::utils::pumpswap::get_token_balances(&pool, &self.rpc).await?; Ok(base_amount) } diff --git a/src/utils/price/bonk.rs b/src/utils/price/bonk.rs index 103fdb7..2ce79ba 100644 --- a/src/utils/price/bonk.rs +++ b/src/utils/price/bonk.rs @@ -1,8 +1,8 @@ use solana_streamer_sdk::streaming::event_parser::protocols::bonk::types::PoolState; -use crate::constants::{ - bonk::accounts::WSOL_TOKEN_ACCOUNT, - decimals::{DEFAULT_TOKEN_DECIMALS, SOL_DECIMALS}, +use crate::{ + constants::decimals::{DEFAULT_TOKEN_DECIMALS, SOL_DECIMALS}, + instruction::utils::bonk::accounts::WSOL_TOKEN_ACCOUNT, }; /// Calculate the token price in WSOL based on pool state diff --git a/src/utils/price/pumpfun.rs b/src/utils/price/pumpfun.rs index 3f6a0e4..a5b321a 100644 --- a/src/utils/price/pumpfun.rs +++ b/src/utils/price/pumpfun.rs @@ -1,6 +1,6 @@ use solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::types::BondingCurve; -use crate::constants::pumpfun::global_constants::{LAMPORTS_PER_SOL, SCALE}; +use crate::instruction::utils::pumpfun::global_constants::{LAMPORTS_PER_SOL, SCALE}; /// Calculate the token price in SOL based on virtual reserves ///