2025-09-08 22:33:05 +08:00
|
|
|
use super::traits::ProtocolParams;
|
|
|
|
|
use crate::common::bonding_curve::BondingCurveAccount;
|
|
|
|
|
use crate::common::{PriorityFee, SolanaRpcClient};
|
|
|
|
|
use crate::solana_streamer_sdk::streaming::event_parser::common::EventType;
|
|
|
|
|
use crate::solana_streamer_sdk::streaming::event_parser::protocols::bonk::BonkTradeEvent;
|
2025-09-09 17:02:24 +08:00
|
|
|
use crate::swqos::SwqosClient;
|
2025-09-08 22:33:05 +08:00
|
|
|
use crate::trading::common::get_multi_token_balances;
|
2025-09-09 17:02:24 +08:00
|
|
|
use crate::trading::MiddlewareManager;
|
2025-06-17 23:32:20 +08:00
|
|
|
use solana_hash::Hash;
|
|
|
|
|
use solana_sdk::{pubkey::Pubkey, signature::Keypair};
|
2025-08-18 18:00:14 +08:00
|
|
|
use solana_streamer_sdk::streaming::event_parser::protocols::pumpfun::PumpFunTradeEvent;
|
|
|
|
|
use solana_streamer_sdk::streaming::event_parser::protocols::pumpswap::{
|
|
|
|
|
PumpSwapBuyEvent, PumpSwapSellEvent,
|
|
|
|
|
};
|
2025-08-19 18:07:21 +08:00
|
|
|
use solana_streamer_sdk::streaming::event_parser::protocols::raydium_amm_v4::types::AmmInfo;
|
2025-09-08 22:33:05 +08:00
|
|
|
use solana_streamer_sdk::streaming::event_parser::protocols::raydium_cpmm::RaydiumCpmmSwapEvent;
|
2025-06-17 23:32:20 +08:00
|
|
|
use std::sync::Arc;
|
2025-09-07 17:22:58 +08:00
|
|
|
/// Buy parameters
|
2025-06-17 23:32:20 +08:00
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct BuyParams {
|
|
|
|
|
pub rpc: Option<Arc<SolanaRpcClient>>,
|
|
|
|
|
pub payer: Arc<Keypair>,
|
|
|
|
|
pub mint: Pubkey,
|
2025-07-10 23:54:49 +08:00
|
|
|
pub sol_amount: u64,
|
2025-06-17 23:32:20 +08:00
|
|
|
pub slippage_basis_points: Option<u64>,
|
2025-09-09 17:02:24 +08:00
|
|
|
pub priority_fee: Arc<PriorityFee>,
|
2025-06-17 23:32:20 +08:00
|
|
|
pub lookup_table_key: Option<Pubkey>,
|
|
|
|
|
pub recent_blockhash: Hash,
|
|
|
|
|
pub data_size_limit: u32,
|
2025-08-21 21:32:53 +08:00
|
|
|
pub wait_transaction_confirmed: bool,
|
2025-06-17 23:32:20 +08:00
|
|
|
pub protocol_params: Box<dyn ProtocolParams>,
|
2025-09-09 17:02:24 +08:00
|
|
|
pub open_seed_optimize: bool,
|
|
|
|
|
pub swqos_clients: Vec<Arc<SwqosClient>>,
|
|
|
|
|
pub middleware_manager: Option<Arc<MiddlewareManager>>,
|
2025-06-17 23:32:20 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-07 17:22:58 +08:00
|
|
|
/// Sell parameters
|
2025-06-17 23:32:20 +08:00
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct SellParams {
|
|
|
|
|
pub rpc: Option<Arc<SolanaRpcClient>>,
|
|
|
|
|
pub payer: Arc<Keypair>,
|
|
|
|
|
pub mint: Pubkey,
|
2025-07-10 23:54:49 +08:00
|
|
|
pub token_amount: Option<u64>,
|
2025-06-17 23:32:20 +08:00
|
|
|
pub slippage_basis_points: Option<u64>,
|
2025-09-09 17:02:24 +08:00
|
|
|
pub priority_fee: Arc<PriorityFee>,
|
2025-06-17 23:32:20 +08:00
|
|
|
pub lookup_table_key: Option<Pubkey>,
|
|
|
|
|
pub recent_blockhash: Hash,
|
2025-08-21 21:32:53 +08:00
|
|
|
pub wait_transaction_confirmed: bool,
|
2025-09-07 17:22:58 +08:00
|
|
|
pub with_tip: bool,
|
2025-06-17 23:32:20 +08:00
|
|
|
pub protocol_params: Box<dyn ProtocolParams>,
|
2025-09-09 17:02:24 +08:00
|
|
|
pub open_seed_optimize: bool,
|
|
|
|
|
pub swqos_clients: Vec<Arc<SwqosClient>>,
|
|
|
|
|
pub middleware_manager: Option<Arc<MiddlewareManager>>,
|
2025-06-17 23:32:20 +08:00
|
|
|
}
|
|
|
|
|
|
2025-08-18 18:00:14 +08:00
|
|
|
/// PumpFun protocol specific parameters
|
|
|
|
|
/// Configuration parameters specific to PumpFun trading protocol
|
2025-06-17 23:32:20 +08:00
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct PumpFunParams {
|
2025-08-18 18:00:14 +08:00
|
|
|
pub bonding_curve: Arc<BondingCurveAccount>,
|
2025-09-08 17:12:29 +08:00
|
|
|
pub associated_bonding_curve: Pubkey,
|
2025-08-23 20:37:03 +08:00
|
|
|
pub creator_vault: Pubkey,
|
2025-08-18 18:00:14 +08:00
|
|
|
/// Whether to close token account when selling, only effective during sell operations
|
|
|
|
|
pub close_token_account_when_sell: Option<bool>,
|
2025-06-17 23:32:20 +08:00
|
|
|
}
|
|
|
|
|
|
2025-07-10 18:14:21 +08:00
|
|
|
impl PumpFunParams {
|
2025-08-23 20:37:03 +08:00
|
|
|
pub fn immediate_sell(creator_vault: Pubkey, close_token_account_when_sell: bool) -> Self {
|
2025-08-21 23:54:26 +08:00
|
|
|
Self {
|
2025-08-23 20:37:03 +08:00
|
|
|
bonding_curve: Arc::new(BondingCurveAccount { ..Default::default() }),
|
2025-09-08 17:12:29 +08:00
|
|
|
associated_bonding_curve: Pubkey::default(),
|
2025-08-23 20:37:03 +08:00
|
|
|
creator_vault: creator_vault,
|
2025-08-21 23:54:26 +08:00
|
|
|
close_token_account_when_sell: Some(close_token_account_when_sell),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-18 18:00:14 +08:00
|
|
|
pub fn from_dev_trade(
|
2025-08-23 20:37:03 +08:00
|
|
|
event: &PumpFunTradeEvent,
|
2025-08-18 18:00:14 +08:00
|
|
|
close_token_account_when_sell: Option<bool>,
|
|
|
|
|
) -> Self {
|
2025-08-23 20:37:03 +08:00
|
|
|
let bonding_curve = BondingCurveAccount::from_dev_trade(
|
|
|
|
|
&event.mint,
|
|
|
|
|
event.token_amount,
|
|
|
|
|
event.max_sol_cost,
|
|
|
|
|
event.creator,
|
|
|
|
|
);
|
2025-07-10 18:14:21 +08:00
|
|
|
Self {
|
2025-08-18 18:00:14 +08:00
|
|
|
bonding_curve: Arc::new(bonding_curve),
|
2025-09-08 17:12:29 +08:00
|
|
|
associated_bonding_curve: event.associated_bonding_curve,
|
2025-08-23 20:37:03 +08:00
|
|
|
creator_vault: event.creator_vault,
|
2025-08-18 18:00:14 +08:00
|
|
|
close_token_account_when_sell: close_token_account_when_sell,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn from_trade(
|
|
|
|
|
event: &PumpFunTradeEvent,
|
|
|
|
|
close_token_account_when_sell: Option<bool>,
|
|
|
|
|
) -> Self {
|
|
|
|
|
let bonding_curve = BondingCurveAccount::from_trade(event);
|
|
|
|
|
Self {
|
|
|
|
|
bonding_curve: Arc::new(bonding_curve),
|
2025-09-08 17:12:29 +08:00
|
|
|
associated_bonding_curve: event.associated_bonding_curve,
|
2025-08-23 20:37:03 +08:00
|
|
|
creator_vault: event.creator_vault,
|
2025-08-18 18:00:14 +08:00
|
|
|
close_token_account_when_sell: close_token_account_when_sell,
|
2025-07-10 18:14:21 +08:00
|
|
|
}
|
2025-06-17 23:32:20 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-10 18:14:21 +08:00
|
|
|
impl ProtocolParams for PumpFunParams {
|
2025-06-17 23:32:20 +08:00
|
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clone_box(&self) -> Box<dyn ProtocolParams> {
|
|
|
|
|
Box::new(self.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-02 23:51:04 +08:00
|
|
|
/// PumpSwap Protocol Specific Parameters
|
|
|
|
|
///
|
|
|
|
|
/// Parameters for configuring PumpSwap trading protocol, including liquidity pool information,
|
|
|
|
|
/// token configuration, and transaction amounts.
|
|
|
|
|
///
|
|
|
|
|
/// **Performance Note**: If these parameters are not provided, the system will attempt to
|
|
|
|
|
/// retrieve the relevant information from RPC, which will increase transaction time.
|
|
|
|
|
/// For optimal performance, it is recommended to provide all necessary parameters in advance.
|
2025-06-17 23:32:20 +08:00
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct PumpSwapParams {
|
2025-08-02 23:51:04 +08:00
|
|
|
/// Liquidity pool address
|
2025-08-18 18:00:14 +08:00
|
|
|
pub pool: Pubkey,
|
2025-08-02 23:51:04 +08:00
|
|
|
/// Base token mint address
|
|
|
|
|
/// The mint account address of the base token in the trading pair
|
2025-08-18 18:00:14 +08:00
|
|
|
pub base_mint: Pubkey,
|
2025-08-02 23:51:04 +08:00
|
|
|
/// Quote token mint address
|
|
|
|
|
/// The mint account address of the quote token in the trading pair, usually SOL or USDC
|
2025-08-18 18:00:14 +08:00
|
|
|
pub quote_mint: Pubkey,
|
2025-09-08 21:54:05 +08:00
|
|
|
/// Pool base token account
|
|
|
|
|
pub pool_base_token_account: Pubkey,
|
|
|
|
|
/// Pool quote token account
|
|
|
|
|
pub pool_quote_token_account: Pubkey,
|
2025-08-02 23:51:04 +08:00
|
|
|
/// Base token reserves in the pool
|
2025-08-18 18:00:14 +08:00
|
|
|
pub pool_base_token_reserves: u64,
|
2025-08-02 23:51:04 +08:00
|
|
|
/// Quote token reserves in the pool
|
2025-08-18 18:00:14 +08:00
|
|
|
pub pool_quote_token_reserves: u64,
|
2025-08-23 20:37:03 +08:00
|
|
|
/// Coin creator vault ATA
|
|
|
|
|
pub coin_creator_vault_ata: Pubkey,
|
|
|
|
|
/// Coin creator vault authority
|
|
|
|
|
pub coin_creator_vault_authority: Pubkey,
|
2025-08-25 00:21:15 +08:00
|
|
|
/// Token program ID
|
|
|
|
|
pub base_token_program: Pubkey,
|
|
|
|
|
/// Quote token program ID
|
|
|
|
|
pub quote_token_program: Pubkey,
|
2025-09-09 17:35:09 +08:00
|
|
|
pub create_wsol_ata: bool,
|
|
|
|
|
pub close_wsol_ata: bool,
|
2025-06-17 23:32:20 +08:00
|
|
|
}
|
|
|
|
|
|
2025-07-10 18:14:21 +08:00
|
|
|
impl PumpSwapParams {
|
2025-08-18 18:00:14 +08:00
|
|
|
pub fn from_buy_trade(event: &PumpSwapBuyEvent) -> Self {
|
2025-07-10 18:14:21 +08:00
|
|
|
Self {
|
2025-08-18 18:00:14 +08:00
|
|
|
pool: event.pool,
|
|
|
|
|
base_mint: event.base_mint,
|
|
|
|
|
quote_mint: event.quote_mint,
|
2025-09-08 21:54:05 +08:00
|
|
|
pool_base_token_account: event.pool_base_token_account,
|
|
|
|
|
pool_quote_token_account: event.pool_quote_token_account,
|
2025-08-18 18:00:14 +08:00
|
|
|
pool_base_token_reserves: event.pool_base_token_reserves,
|
|
|
|
|
pool_quote_token_reserves: event.pool_quote_token_reserves,
|
2025-08-23 20:37:03 +08:00
|
|
|
coin_creator_vault_ata: event.coin_creator_vault_ata,
|
|
|
|
|
coin_creator_vault_authority: event.coin_creator_vault_authority,
|
2025-08-25 00:21:15 +08:00
|
|
|
base_token_program: event.base_token_program,
|
|
|
|
|
quote_token_program: event.quote_token_program,
|
2025-09-09 17:35:09 +08:00
|
|
|
create_wsol_ata: true,
|
|
|
|
|
close_wsol_ata: true,
|
2025-07-10 18:14:21 +08:00
|
|
|
}
|
|
|
|
|
}
|
2025-08-18 18:00:14 +08:00
|
|
|
|
|
|
|
|
pub fn from_sell_trade(event: &PumpSwapSellEvent) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
pool: event.pool,
|
|
|
|
|
base_mint: event.base_mint,
|
|
|
|
|
quote_mint: event.quote_mint,
|
2025-09-08 21:54:05 +08:00
|
|
|
pool_base_token_account: event.pool_base_token_account,
|
|
|
|
|
pool_quote_token_account: event.pool_quote_token_account,
|
2025-08-18 18:00:14 +08:00
|
|
|
pool_base_token_reserves: event.pool_base_token_reserves,
|
|
|
|
|
pool_quote_token_reserves: event.pool_quote_token_reserves,
|
2025-08-23 20:37:03 +08:00
|
|
|
coin_creator_vault_ata: event.coin_creator_vault_ata,
|
|
|
|
|
coin_creator_vault_authority: event.coin_creator_vault_authority,
|
2025-08-25 00:21:15 +08:00
|
|
|
base_token_program: event.base_token_program,
|
|
|
|
|
quote_token_program: event.quote_token_program,
|
2025-09-09 17:35:09 +08:00
|
|
|
create_wsol_ata: true,
|
|
|
|
|
close_wsol_ata: true,
|
2025-08-18 18:00:14 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn from_pool_address_by_rpc(
|
|
|
|
|
rpc: &SolanaRpcClient,
|
|
|
|
|
pool_address: &Pubkey,
|
|
|
|
|
) -> Result<Self, anyhow::Error> {
|
2025-09-07 19:00:08 +08:00
|
|
|
let pool_data = crate::instruction::utils::pumpswap::fetch_pool(rpc, pool_address).await?;
|
2025-08-18 18:00:14 +08:00
|
|
|
let (pool_base_token_reserves, pool_quote_token_reserves) =
|
2025-09-07 19:00:08 +08:00
|
|
|
crate::instruction::utils::pumpswap::get_token_balances(&pool_data, rpc).await?;
|
2025-09-07 23:54:37 +08:00
|
|
|
let creator = pool_data.coin_creator;
|
2025-09-07 19:00:08 +08:00
|
|
|
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);
|
2025-08-25 00:21:15 +08:00
|
|
|
|
|
|
|
|
let base_token_program_ata =
|
|
|
|
|
spl_associated_token_account::get_associated_token_address_with_program_id(
|
|
|
|
|
&pool_address,
|
|
|
|
|
&pool_data.base_mint,
|
2025-09-07 21:36:57 +08:00
|
|
|
&crate::constants::TOKEN_PROGRAM,
|
2025-08-25 00:21:15 +08:00
|
|
|
);
|
|
|
|
|
let quote_token_program_ata =
|
|
|
|
|
spl_associated_token_account::get_associated_token_address_with_program_id(
|
|
|
|
|
&pool_address,
|
|
|
|
|
&pool_data.quote_mint,
|
2025-09-07 21:36:57 +08:00
|
|
|
&crate::constants::TOKEN_PROGRAM,
|
2025-08-25 00:21:15 +08:00
|
|
|
);
|
|
|
|
|
|
2025-08-18 18:00:14 +08:00
|
|
|
Ok(Self {
|
|
|
|
|
pool: pool_address.clone(),
|
|
|
|
|
base_mint: pool_data.base_mint,
|
|
|
|
|
quote_mint: pool_data.quote_mint,
|
2025-09-08 21:54:05 +08:00
|
|
|
pool_base_token_account: pool_data.pool_base_token_account,
|
|
|
|
|
pool_quote_token_account: pool_data.pool_quote_token_account,
|
2025-08-18 18:00:14 +08:00
|
|
|
pool_base_token_reserves: pool_base_token_reserves,
|
|
|
|
|
pool_quote_token_reserves: pool_quote_token_reserves,
|
2025-08-23 20:37:03 +08:00
|
|
|
coin_creator_vault_ata: coin_creator_vault_ata,
|
|
|
|
|
coin_creator_vault_authority: coin_creator_vault_authority,
|
2025-08-25 00:21:15 +08:00
|
|
|
base_token_program: if pool_data.pool_base_token_account == base_token_program_ata {
|
2025-09-07 21:36:57 +08:00
|
|
|
crate::constants::TOKEN_PROGRAM
|
2025-08-25 00:21:15 +08:00
|
|
|
} else {
|
2025-09-07 21:36:57 +08:00
|
|
|
crate::constants::TOKEN_PROGRAM_2022
|
2025-08-25 00:21:15 +08:00
|
|
|
},
|
|
|
|
|
quote_token_program: if pool_data.pool_quote_token_account == quote_token_program_ata {
|
2025-09-07 21:36:57 +08:00
|
|
|
crate::constants::TOKEN_PROGRAM
|
2025-08-25 00:21:15 +08:00
|
|
|
} else {
|
2025-09-07 21:36:57 +08:00
|
|
|
crate::constants::TOKEN_PROGRAM_2022
|
2025-08-25 00:21:15 +08:00
|
|
|
},
|
2025-09-09 17:35:09 +08:00
|
|
|
create_wsol_ata: true,
|
|
|
|
|
close_wsol_ata: true,
|
2025-08-18 18:00:14 +08:00
|
|
|
})
|
|
|
|
|
}
|
2025-07-10 18:14:21 +08:00
|
|
|
}
|
|
|
|
|
|
2025-06-17 23:32:20 +08:00
|
|
|
impl ProtocolParams for PumpSwapParams {
|
|
|
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clone_box(&self) -> Box<dyn ProtocolParams> {
|
|
|
|
|
Box::new(self.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-18 18:00:14 +08:00
|
|
|
/// Bonk protocol specific parameters
|
|
|
|
|
/// Configuration parameters specific to Bonk trading protocol
|
2025-08-21 23:54:26 +08:00
|
|
|
#[derive(Clone, Default)]
|
2025-07-10 00:23:29 +08:00
|
|
|
pub struct BonkParams {
|
2025-08-18 18:00:14 +08:00
|
|
|
pub virtual_base: u128,
|
|
|
|
|
pub virtual_quote: u128,
|
|
|
|
|
pub real_base: u128,
|
|
|
|
|
pub real_quote: u128,
|
2025-09-08 18:29:05 +08:00
|
|
|
pub pool_state: Pubkey,
|
|
|
|
|
pub base_vault: Pubkey,
|
|
|
|
|
pub quote_vault: Pubkey,
|
2025-08-18 18:00:14 +08:00
|
|
|
/// Token program ID
|
|
|
|
|
/// Specifies the program used by the token, usually spl_token::ID or spl_token_2022::ID
|
|
|
|
|
pub mint_token_program: Pubkey,
|
2025-08-30 23:51:20 +08:00
|
|
|
pub platform_config: Pubkey,
|
2025-08-22 21:49:14 +08:00
|
|
|
pub platform_associated_account: Pubkey,
|
|
|
|
|
pub creator_associated_account: Pubkey,
|
2025-09-09 17:35:09 +08:00
|
|
|
pub create_wsol_ata: bool,
|
|
|
|
|
pub close_wsol_ata: bool,
|
2025-07-09 22:29:29 +08:00
|
|
|
}
|
|
|
|
|
|
2025-07-10 18:14:21 +08:00
|
|
|
impl BonkParams {
|
2025-08-22 22:28:54 +08:00
|
|
|
pub fn immediate_sell(
|
|
|
|
|
mint_token_program: Pubkey,
|
2025-08-30 23:51:20 +08:00
|
|
|
platform_config: Pubkey,
|
2025-08-22 22:28:54 +08:00
|
|
|
platform_associated_account: Pubkey,
|
|
|
|
|
creator_associated_account: Pubkey,
|
|
|
|
|
) -> Self {
|
|
|
|
|
Self {
|
2025-09-09 17:35:09 +08:00
|
|
|
create_wsol_ata: true,
|
|
|
|
|
close_wsol_ata: true,
|
2025-08-22 22:28:54 +08:00
|
|
|
mint_token_program,
|
2025-08-30 23:51:20 +08:00
|
|
|
platform_config,
|
2025-08-22 22:28:54 +08:00
|
|
|
platform_associated_account,
|
|
|
|
|
creator_associated_account,
|
|
|
|
|
..Default::default()
|
|
|
|
|
}
|
2025-08-21 23:54:26 +08:00
|
|
|
}
|
2025-07-14 22:26:03 +08:00
|
|
|
pub fn from_trade(trade_info: BonkTradeEvent) -> Self {
|
|
|
|
|
Self {
|
2025-08-18 18:00:14 +08:00
|
|
|
virtual_base: trade_info.virtual_base as u128,
|
|
|
|
|
virtual_quote: trade_info.virtual_quote as u128,
|
|
|
|
|
real_base: trade_info.real_base_after as u128,
|
|
|
|
|
real_quote: trade_info.real_quote_after as u128,
|
2025-09-08 18:29:05 +08:00
|
|
|
pool_state: trade_info.pool_state,
|
|
|
|
|
base_vault: trade_info.base_vault,
|
|
|
|
|
quote_vault: trade_info.quote_vault,
|
2025-08-18 18:00:14 +08:00
|
|
|
mint_token_program: trade_info.base_token_program,
|
2025-08-30 23:51:20 +08:00
|
|
|
platform_config: trade_info.platform_config,
|
2025-08-22 21:49:14 +08:00
|
|
|
platform_associated_account: trade_info.platform_associated_account,
|
|
|
|
|
creator_associated_account: trade_info.creator_associated_account,
|
2025-09-09 17:35:09 +08:00
|
|
|
create_wsol_ata: true,
|
|
|
|
|
close_wsol_ata: true,
|
2025-07-14 22:26:03 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn from_dev_trade(trade_info: BonkTradeEvent) -> Self {
|
|
|
|
|
const DEFAULT_VIRTUAL_BASE: u128 = 1073025605596382;
|
|
|
|
|
const DEFAULT_VIRTUAL_QUOTE: u128 = 30000852951;
|
|
|
|
|
let amount_in = if trade_info.metadata.event_type == EventType::BonkBuyExactIn {
|
|
|
|
|
trade_info.amount_in
|
|
|
|
|
} else {
|
2025-09-07 19:00:08 +08:00
|
|
|
crate::instruction::utils::bonk::get_amount_in(
|
2025-07-14 22:26:03 +08:00
|
|
|
trade_info.amount_out,
|
2025-09-07 19:00:08 +08:00
|
|
|
crate::instruction::utils::bonk::accounts::PROTOCOL_FEE_RATE,
|
|
|
|
|
crate::instruction::utils::bonk::accounts::PLATFORM_FEE_RATE,
|
|
|
|
|
crate::instruction::utils::bonk::accounts::SHARE_FEE_RATE,
|
2025-07-14 22:26:03 +08:00
|
|
|
DEFAULT_VIRTUAL_BASE,
|
|
|
|
|
DEFAULT_VIRTUAL_QUOTE,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
};
|
2025-09-07 19:00:08 +08:00
|
|
|
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;
|
2025-07-14 22:26:03 +08:00
|
|
|
let amount_out = if trade_info.metadata.event_type == EventType::BonkBuyExactIn {
|
2025-09-07 19:00:08 +08:00
|
|
|
crate::instruction::utils::bonk::get_amount_out(
|
2025-07-14 22:26:03 +08:00
|
|
|
trade_info.amount_in,
|
2025-09-07 19:00:08 +08:00
|
|
|
crate::instruction::utils::bonk::accounts::PROTOCOL_FEE_RATE,
|
|
|
|
|
crate::instruction::utils::bonk::accounts::PLATFORM_FEE_RATE,
|
|
|
|
|
crate::instruction::utils::bonk::accounts::SHARE_FEE_RATE,
|
2025-07-14 22:26:03 +08:00
|
|
|
DEFAULT_VIRTUAL_BASE,
|
|
|
|
|
DEFAULT_VIRTUAL_QUOTE,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
) as u128
|
|
|
|
|
} else {
|
|
|
|
|
trade_info.amount_out as u128
|
|
|
|
|
};
|
|
|
|
|
let real_base = amount_out;
|
|
|
|
|
Self {
|
2025-08-18 18:00:14 +08:00
|
|
|
virtual_base: DEFAULT_VIRTUAL_BASE,
|
|
|
|
|
virtual_quote: DEFAULT_VIRTUAL_QUOTE,
|
|
|
|
|
real_base: real_base,
|
|
|
|
|
real_quote: real_quote,
|
2025-09-08 18:29:05 +08:00
|
|
|
pool_state: trade_info.pool_state,
|
|
|
|
|
base_vault: trade_info.base_vault,
|
|
|
|
|
quote_vault: trade_info.quote_vault,
|
2025-08-18 18:00:14 +08:00
|
|
|
mint_token_program: trade_info.base_token_program,
|
2025-08-30 23:51:20 +08:00
|
|
|
platform_config: trade_info.platform_config,
|
2025-08-22 21:49:14 +08:00
|
|
|
platform_associated_account: trade_info.platform_associated_account,
|
|
|
|
|
creator_associated_account: trade_info.creator_associated_account,
|
2025-09-09 17:35:09 +08:00
|
|
|
create_wsol_ata: true,
|
|
|
|
|
close_wsol_ata: true,
|
2025-07-14 22:26:03 +08:00
|
|
|
}
|
|
|
|
|
}
|
2025-08-18 18:00:14 +08:00
|
|
|
|
|
|
|
|
pub async fn from_mint_by_rpc(
|
|
|
|
|
rpc: &SolanaRpcClient,
|
|
|
|
|
mint: &Pubkey,
|
|
|
|
|
) -> Result<Self, anyhow::Error> {
|
2025-09-07 19:00:08 +08:00
|
|
|
let pool_address = crate::instruction::utils::bonk::get_pool_pda(
|
|
|
|
|
mint,
|
2025-09-07 21:36:57 +08:00
|
|
|
&crate::constants::WSOL_TOKEN_ACCOUNT,
|
2025-09-07 19:00:08 +08:00
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
let pool_data =
|
|
|
|
|
crate::instruction::utils::bonk::fetch_pool_state(rpc, &pool_address).await?;
|
2025-08-18 18:00:14 +08:00
|
|
|
let token_account = rpc.get_account(&pool_data.base_mint).await?;
|
2025-08-22 21:49:14 +08:00
|
|
|
let platform_associated_account =
|
2025-09-07 19:00:08 +08:00
|
|
|
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);
|
2025-08-22 21:49:14 +08:00
|
|
|
let platform_associated_account = platform_associated_account.unwrap();
|
|
|
|
|
let creator_associated_account = creator_associated_account.unwrap();
|
2025-08-18 18:00:14 +08:00
|
|
|
Ok(Self {
|
|
|
|
|
virtual_base: pool_data.virtual_base as u128,
|
|
|
|
|
virtual_quote: pool_data.virtual_quote as u128,
|
|
|
|
|
real_base: pool_data.real_base as u128,
|
|
|
|
|
real_quote: pool_data.real_quote as u128,
|
2025-09-08 18:29:05 +08:00
|
|
|
pool_state: pool_address,
|
|
|
|
|
base_vault: pool_data.base_vault,
|
|
|
|
|
quote_vault: pool_data.quote_vault,
|
2025-08-18 18:00:14 +08:00
|
|
|
mint_token_program: token_account.owner,
|
2025-08-30 23:51:20 +08:00
|
|
|
platform_config: pool_data.platform_config,
|
2025-08-22 21:49:14 +08:00
|
|
|
platform_associated_account,
|
|
|
|
|
creator_associated_account,
|
2025-09-09 17:35:09 +08:00
|
|
|
create_wsol_ata: true,
|
|
|
|
|
close_wsol_ata: true,
|
2025-08-18 18:00:14 +08:00
|
|
|
})
|
|
|
|
|
}
|
2025-07-10 18:14:21 +08:00
|
|
|
}
|
|
|
|
|
|
2025-07-10 00:23:29 +08:00
|
|
|
impl ProtocolParams for BonkParams {
|
2025-07-09 22:29:29 +08:00
|
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clone_box(&self) -> Box<dyn ProtocolParams> {
|
|
|
|
|
Box::new(self.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-18 18:00:14 +08:00
|
|
|
/// RaydiumCpmm protocol specific parameters
|
|
|
|
|
/// Configuration parameters specific to Raydium CPMM trading protocol
|
2025-07-16 22:54:23 +08:00
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct RaydiumCpmmParams {
|
2025-09-08 22:33:05 +08:00
|
|
|
/// Pool address
|
|
|
|
|
pub pool_state: Pubkey,
|
2025-08-18 18:00:14 +08:00
|
|
|
/// Base token mint address
|
|
|
|
|
pub base_mint: Pubkey,
|
|
|
|
|
/// Quote token mint address
|
|
|
|
|
pub quote_mint: Pubkey,
|
|
|
|
|
/// Base token reserve amount in the pool
|
|
|
|
|
pub base_reserve: u64,
|
|
|
|
|
/// Quote token reserve amount in the pool
|
|
|
|
|
pub quote_reserve: u64,
|
2025-09-08 22:33:05 +08:00
|
|
|
/// Base token vault address
|
|
|
|
|
pub base_vault: Pubkey,
|
|
|
|
|
/// Quote token vault address
|
|
|
|
|
pub quote_vault: Pubkey,
|
2025-08-18 18:00:14 +08:00
|
|
|
/// Base token program ID (usually spl_token::ID or spl_token_2022::ID)
|
|
|
|
|
pub base_token_program: Pubkey,
|
|
|
|
|
/// Quote token program ID (usually spl_token::ID or spl_token_2022::ID)
|
|
|
|
|
pub quote_token_program: Pubkey,
|
2025-09-08 22:33:05 +08:00
|
|
|
/// Observation state account
|
|
|
|
|
pub observation_state: Pubkey,
|
2025-09-09 17:35:09 +08:00
|
|
|
pub create_wsol_ata: bool,
|
|
|
|
|
pub close_wsol_ata: bool,
|
2025-07-16 22:54:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl RaydiumCpmmParams {
|
2025-09-08 22:33:05 +08:00
|
|
|
pub fn from_trade(
|
|
|
|
|
trade_info: RaydiumCpmmSwapEvent,
|
|
|
|
|
base_reserve: u64,
|
|
|
|
|
quote_reserve: u64,
|
|
|
|
|
) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
pool_state: trade_info.pool_state,
|
|
|
|
|
base_mint: trade_info.input_token_mint,
|
|
|
|
|
quote_mint: trade_info.output_token_mint,
|
|
|
|
|
base_reserve: base_reserve,
|
|
|
|
|
quote_reserve: quote_reserve,
|
|
|
|
|
base_vault: trade_info.input_vault,
|
|
|
|
|
quote_vault: trade_info.output_vault,
|
|
|
|
|
base_token_program: trade_info.input_token_program,
|
|
|
|
|
quote_token_program: trade_info.output_token_program,
|
|
|
|
|
observation_state: trade_info.observation_state,
|
2025-09-09 17:35:09 +08:00
|
|
|
create_wsol_ata: true,
|
|
|
|
|
close_wsol_ata: true,
|
2025-09-08 22:33:05 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-18 18:00:14 +08:00
|
|
|
pub async fn from_pool_address_by_rpc(
|
|
|
|
|
rpc: &SolanaRpcClient,
|
|
|
|
|
pool_address: &Pubkey,
|
|
|
|
|
) -> Result<Self, anyhow::Error> {
|
|
|
|
|
let pool =
|
2025-09-07 19:00:08 +08:00
|
|
|
crate::instruction::utils::raydium_cpmm::fetch_pool_state(rpc, pool_address).await?;
|
2025-08-18 18:00:14 +08:00
|
|
|
let (token0_balance, token1_balance) =
|
2025-09-07 19:00:08 +08:00
|
|
|
crate::instruction::utils::raydium_cpmm::get_pool_token_balances(
|
|
|
|
|
rpc,
|
|
|
|
|
pool_address,
|
|
|
|
|
&pool.token0_mint,
|
|
|
|
|
&pool.token1_mint,
|
|
|
|
|
)
|
|
|
|
|
.await?;
|
2025-08-18 18:00:14 +08:00
|
|
|
Ok(Self {
|
2025-09-08 22:33:05 +08:00
|
|
|
pool_state: pool_address.clone(),
|
2025-08-18 18:00:14 +08:00
|
|
|
base_mint: pool.token0_mint,
|
|
|
|
|
quote_mint: pool.token1_mint,
|
|
|
|
|
base_reserve: token0_balance,
|
|
|
|
|
quote_reserve: token1_balance,
|
2025-09-08 22:33:05 +08:00
|
|
|
base_vault: pool.token0_vault,
|
|
|
|
|
quote_vault: pool.token1_vault,
|
2025-08-18 18:00:14 +08:00
|
|
|
base_token_program: pool.token0_program,
|
|
|
|
|
quote_token_program: pool.token1_program,
|
2025-09-08 22:33:05 +08:00
|
|
|
observation_state: pool.observation_key,
|
2025-09-09 17:35:09 +08:00
|
|
|
create_wsol_ata: true,
|
|
|
|
|
close_wsol_ata: true,
|
2025-08-18 18:00:14 +08:00
|
|
|
})
|
2025-07-16 22:54:23 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ProtocolParams for RaydiumCpmmParams {
|
|
|
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clone_box(&self) -> Box<dyn ProtocolParams> {
|
|
|
|
|
Box::new(self.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-19 18:07:21 +08:00
|
|
|
/// RaydiumCpmm protocol specific parameters
|
|
|
|
|
/// Configuration parameters specific to Raydium CPMM trading protocol
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct RaydiumAmmV4Params {
|
|
|
|
|
/// AMM pool address
|
|
|
|
|
pub amm: Pubkey,
|
|
|
|
|
/// Base token (coin) mint address
|
|
|
|
|
pub coin_mint: Pubkey,
|
|
|
|
|
/// Quote token (pc) mint address
|
|
|
|
|
pub pc_mint: Pubkey,
|
|
|
|
|
/// Pool's coin token account address
|
|
|
|
|
pub token_coin: Pubkey,
|
|
|
|
|
/// Pool's pc token account address
|
|
|
|
|
pub token_pc: Pubkey,
|
|
|
|
|
/// Current coin reserve amount in the pool
|
|
|
|
|
pub coin_reserve: u64,
|
|
|
|
|
/// Current pc reserve amount in the pool
|
|
|
|
|
pub pc_reserve: u64,
|
2025-09-09 17:35:09 +08:00
|
|
|
pub create_wsol_ata: bool,
|
|
|
|
|
pub close_wsol_ata: bool,
|
2025-08-19 18:07:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl RaydiumAmmV4Params {
|
|
|
|
|
pub fn from_amm_info_and_reserves(
|
|
|
|
|
amm: Pubkey,
|
|
|
|
|
amm_info: AmmInfo,
|
|
|
|
|
coin_reserve: u64,
|
|
|
|
|
pc_reserve: u64,
|
|
|
|
|
) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
amm,
|
|
|
|
|
coin_mint: amm_info.coin_mint,
|
|
|
|
|
pc_mint: amm_info.pc_mint,
|
|
|
|
|
token_coin: amm_info.token_coin,
|
|
|
|
|
token_pc: amm_info.token_pc,
|
|
|
|
|
coin_reserve,
|
|
|
|
|
pc_reserve,
|
2025-09-09 17:35:09 +08:00
|
|
|
create_wsol_ata: true,
|
|
|
|
|
close_wsol_ata: true,
|
2025-08-19 18:07:21 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pub async fn from_amm_address_by_rpc(
|
|
|
|
|
rpc: &SolanaRpcClient,
|
|
|
|
|
amm: Pubkey,
|
|
|
|
|
) -> Result<Self, anyhow::Error> {
|
2025-09-07 19:00:08 +08:00
|
|
|
let amm_info = crate::instruction::utils::raydium_amm_v4::fetch_amm_info(rpc, amm).await?;
|
2025-08-19 18:07:21 +08:00
|
|
|
let (coin_reserve, pc_reserve) =
|
|
|
|
|
get_multi_token_balances(rpc, &amm_info.token_coin, &amm_info.token_pc).await?;
|
|
|
|
|
Ok(Self {
|
|
|
|
|
amm,
|
|
|
|
|
coin_mint: amm_info.coin_mint,
|
|
|
|
|
pc_mint: amm_info.pc_mint,
|
|
|
|
|
token_coin: amm_info.token_coin,
|
|
|
|
|
token_pc: amm_info.token_pc,
|
|
|
|
|
coin_reserve,
|
|
|
|
|
pc_reserve,
|
2025-09-09 17:35:09 +08:00
|
|
|
create_wsol_ata: true,
|
|
|
|
|
close_wsol_ata: true,
|
2025-08-19 18:07:21 +08:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ProtocolParams for RaydiumAmmV4Params {
|
|
|
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clone_box(&self) -> Box<dyn ProtocolParams> {
|
|
|
|
|
Box::new(self.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|