refactor: unify trading parameters and add USD1 token pool support
- Merge BuyParams and SellParams into unified SwapParams structure - Add USD1 token pool support with related constants and configurations - Refactor trade executor by combining buy_with_tip and sell_with_tip into swap method - Update all protocol instruction builders to support new parameter structure - Standardize ATA creation/closing parameter naming conventions - Update example code to use new API interfaces - Optimize trading logic with automatic direction detection based on input token type
This commit is contained in:
@@ -2,13 +2,13 @@ use anyhow::Result;
|
||||
use solana_sdk::signature::Signature;
|
||||
use std::{sync::Arc, time::Instant};
|
||||
|
||||
use crate::trading::core::parallel::{buy_parallel_execute, sell_parallel_execute};
|
||||
|
||||
use super::{
|
||||
params::{BuyParams, SellParams},
|
||||
traits::{InstructionBuilder, TradeExecutor},
|
||||
use crate::trading::core::{
|
||||
parallel::{buy_parallel_execute, sell_parallel_execute},
|
||||
traits::TradeExecutor,
|
||||
};
|
||||
|
||||
use super::{params::SwapParams, traits::InstructionBuilder};
|
||||
|
||||
/// Generic trade executor implementation
|
||||
pub struct GenericTradeExecutor {
|
||||
instruction_builder: Arc<dyn InstructionBuilder>,
|
||||
@@ -26,46 +26,35 @@ impl GenericTradeExecutor {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl TradeExecutor for GenericTradeExecutor {
|
||||
async fn buy_with_tip(&self, params: BuyParams) -> Result<Signature> {
|
||||
async fn swap(&self, params: SwapParams) -> Result<Signature> {
|
||||
let start = Instant::now();
|
||||
|
||||
// 暂时支持这三种。后续重构扩展builder 支持所有的 swap
|
||||
let is_buy = params.input_mint == crate::constants::SOL_TOKEN_ACCOUNT
|
||||
|| params.input_mint == crate::constants::WSOL_TOKEN_ACCOUNT
|
||||
|| (params.input_mint == crate::constants::USD1_TOKEN_ACCOUNT
|
||||
&& params.output_mint != crate::constants::WSOL_TOKEN_ACCOUNT);
|
||||
// Build instructions directly from params to avoid unnecessary cloning
|
||||
let instructions = self.instruction_builder.build_buy_instructions(¶ms).await?;
|
||||
let instructions = if is_buy {
|
||||
self.instruction_builder.build_buy_instructions(¶ms).await?
|
||||
} else {
|
||||
self.instruction_builder.build_sell_instructions(¶ms).await?
|
||||
};
|
||||
let final_instructions = match ¶ms.middleware_manager {
|
||||
Some(middleware_manager) => middleware_manager
|
||||
.apply_middlewares_process_protocol_instructions(
|
||||
instructions,
|
||||
self.protocol_name.to_string(),
|
||||
true,
|
||||
is_buy,
|
||||
)?,
|
||||
None => instructions,
|
||||
};
|
||||
|
||||
println!("Building buy transaction instructions time cost: {:?}", start.elapsed());
|
||||
|
||||
println!("Building swap transaction instructions time cost: {:?}", start.elapsed());
|
||||
// Execute transactions in parallel
|
||||
buy_parallel_execute(params, final_instructions, self.protocol_name).await
|
||||
}
|
||||
|
||||
async fn sell_with_tip(&self, params: SellParams) -> Result<Signature> {
|
||||
let start = Instant::now();
|
||||
|
||||
// Build instructions directly from params to avoid unnecessary cloning
|
||||
let instructions = self.instruction_builder.build_sell_instructions(¶ms).await?;
|
||||
let final_instructions = match ¶ms.middleware_manager {
|
||||
Some(middleware_manager) => middleware_manager
|
||||
.apply_middlewares_process_protocol_instructions(
|
||||
instructions,
|
||||
self.protocol_name.to_string(),
|
||||
false,
|
||||
)?,
|
||||
None => instructions,
|
||||
};
|
||||
|
||||
println!("Building sell transaction instructions time cost: {:?}", start.elapsed());
|
||||
|
||||
// Execute transactions in parallel
|
||||
sell_parallel_execute(params, final_instructions, self.protocol_name).await
|
||||
if is_buy {
|
||||
buy_parallel_execute(params, final_instructions, self.protocol_name).await
|
||||
} else {
|
||||
sell_parallel_execute(params, final_instructions, self.protocol_name).await
|
||||
}
|
||||
}
|
||||
|
||||
fn protocol_name(&self) -> &'static str {
|
||||
|
||||
@@ -8,14 +8,14 @@ use tokio::sync::mpsc;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
use crate::{
|
||||
common::{GasFeeStrategy, SolanaRpcClient},
|
||||
common::nonce_cache::DurableNonceInfo,
|
||||
common::{GasFeeStrategy, SolanaRpcClient},
|
||||
swqos::{SwqosClient, SwqosType, TradeType},
|
||||
trading::{common::build_transaction, BuyParams, MiddlewareManager, SellParams},
|
||||
trading::{common::build_transaction, MiddlewareManager, SwapParams},
|
||||
};
|
||||
|
||||
pub async fn buy_parallel_execute(
|
||||
params: BuyParams,
|
||||
params: SwapParams,
|
||||
instructions: Vec<Instruction>,
|
||||
protocol_name: &'static str,
|
||||
) -> Result<Signature> {
|
||||
@@ -26,9 +26,7 @@ pub async fn buy_parallel_execute(
|
||||
instructions,
|
||||
params.lookup_table_key,
|
||||
params.recent_blockhash,
|
||||
params.durable_nonce.clone(),
|
||||
// params.nonce_account,
|
||||
// params.current_nonce,
|
||||
params.durable_nonce,
|
||||
params.data_size_limit,
|
||||
params.middleware_manager,
|
||||
protocol_name,
|
||||
@@ -40,7 +38,7 @@ pub async fn buy_parallel_execute(
|
||||
}
|
||||
|
||||
pub async fn sell_parallel_execute(
|
||||
params: SellParams,
|
||||
params: SwapParams,
|
||||
instructions: Vec<Instruction>,
|
||||
protocol_name: &'static str,
|
||||
) -> Result<Signature> {
|
||||
@@ -51,9 +49,7 @@ pub async fn sell_parallel_execute(
|
||||
instructions,
|
||||
params.lookup_table_key,
|
||||
params.recent_blockhash,
|
||||
params.durable_nonce.clone(),
|
||||
// params.nonce_account,
|
||||
// params.current_nonce,
|
||||
params.durable_nonce,
|
||||
0,
|
||||
params.middleware_manager,
|
||||
protocol_name,
|
||||
@@ -73,8 +69,6 @@ async fn parallel_execute(
|
||||
lookup_table_key: Option<Pubkey>,
|
||||
recent_blockhash: Option<Hash>,
|
||||
durable_nonce: Option<DurableNonceInfo>,
|
||||
// nonce_account: Option<Pubkey>,
|
||||
// current_nonce: Option<Hash>,
|
||||
data_size_limit: u32,
|
||||
middleware_manager: Option<Arc<MiddlewareManager>>,
|
||||
protocol_name: &'static str,
|
||||
|
||||
+27
-41
@@ -1,7 +1,7 @@
|
||||
use super::traits::ProtocolParams;
|
||||
use crate::common::bonding_curve::BondingCurveAccount;
|
||||
use crate::common::SolanaRpcClient;
|
||||
use crate::common::nonce_cache::DurableNonceInfo;
|
||||
use crate::common::SolanaRpcClient;
|
||||
use crate::solana_streamer_sdk::streaming::event_parser::common::EventType;
|
||||
use crate::solana_streamer_sdk::streaming::event_parser::protocols::bonk::BonkTradeEvent;
|
||||
use crate::swqos::SwqosClient;
|
||||
@@ -17,13 +17,17 @@ use solana_streamer_sdk::streaming::event_parser::protocols::raydium_amm_v4::typ
|
||||
use solana_streamer_sdk::streaming::event_parser::protocols::raydium_cpmm::RaydiumCpmmSwapEvent;
|
||||
use spl_associated_token_account::get_associated_token_address;
|
||||
use std::sync::Arc;
|
||||
/// Buy parameters
|
||||
|
||||
/// Swap parameters
|
||||
#[derive(Clone)]
|
||||
pub struct BuyParams {
|
||||
pub struct SwapParams {
|
||||
pub rpc: Option<Arc<SolanaRpcClient>>,
|
||||
pub payer: Arc<Keypair>,
|
||||
pub mint: Pubkey,
|
||||
pub sol_amount: u64,
|
||||
pub input_mint: Pubkey,
|
||||
pub input_token_program: Option<Pubkey>,
|
||||
pub output_mint: Pubkey,
|
||||
pub output_token_program: Option<Pubkey>,
|
||||
pub input_amount: Option<u64>,
|
||||
pub slippage_basis_points: Option<u64>,
|
||||
pub lookup_table_key: Option<Pubkey>,
|
||||
pub recent_blockhash: Option<Hash>,
|
||||
@@ -33,46 +37,17 @@ pub struct BuyParams {
|
||||
pub open_seed_optimize: bool,
|
||||
pub swqos_clients: Vec<Arc<SwqosClient>>,
|
||||
pub middleware_manager: Option<Arc<MiddlewareManager>>,
|
||||
pub create_wsol_ata: bool,
|
||||
pub close_wsol_ata: bool,
|
||||
pub create_mint_ata: bool,
|
||||
// pub nonce_account: Option<Pubkey>,
|
||||
// pub current_nonce: Option<Hash>,
|
||||
pub durable_nonce: Option<DurableNonceInfo>,
|
||||
}
|
||||
|
||||
/// Sell parameters
|
||||
#[derive(Clone)]
|
||||
pub struct SellParams {
|
||||
pub rpc: Option<Arc<SolanaRpcClient>>,
|
||||
pub payer: Arc<Keypair>,
|
||||
pub mint: Pubkey,
|
||||
pub token_amount: Option<u64>,
|
||||
pub slippage_basis_points: Option<u64>,
|
||||
pub lookup_table_key: Option<Pubkey>,
|
||||
pub recent_blockhash: Option<Hash>,
|
||||
pub wait_transaction_confirmed: bool,
|
||||
pub with_tip: bool,
|
||||
pub protocol_params: Box<dyn ProtocolParams>,
|
||||
pub open_seed_optimize: bool,
|
||||
pub swqos_clients: Vec<Arc<SwqosClient>>,
|
||||
pub middleware_manager: Option<Arc<MiddlewareManager>>,
|
||||
pub create_wsol_ata: bool,
|
||||
pub close_wsol_ata: bool,
|
||||
// pub nonce_account: Option<Pubkey>,
|
||||
// pub current_nonce: Option<Hash>,
|
||||
pub durable_nonce: Option<DurableNonceInfo>,
|
||||
pub create_input_mint_ata: bool,
|
||||
pub close_input_mint_ata: bool,
|
||||
pub create_output_mint_ata: bool,
|
||||
pub close_output_mint_ata: bool,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for BuyParams {
|
||||
impl std::fmt::Debug for SwapParams {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "BuyParams: {:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SellParams {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "SellParams: {:?}", self)
|
||||
write!(f, "SwapParams: {:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,6 +307,7 @@ pub struct BonkParams {
|
||||
pub platform_config: Pubkey,
|
||||
pub platform_associated_account: Pubkey,
|
||||
pub creator_associated_account: Pubkey,
|
||||
pub global_config: Pubkey,
|
||||
}
|
||||
|
||||
impl BonkParams {
|
||||
@@ -340,12 +316,14 @@ impl BonkParams {
|
||||
platform_config: Pubkey,
|
||||
platform_associated_account: Pubkey,
|
||||
creator_associated_account: Pubkey,
|
||||
global_config: Pubkey,
|
||||
) -> Self {
|
||||
Self {
|
||||
mint_token_program,
|
||||
platform_config,
|
||||
platform_associated_account,
|
||||
creator_associated_account,
|
||||
global_config,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
@@ -362,6 +340,7 @@ impl BonkParams {
|
||||
platform_config: trade_info.platform_config,
|
||||
platform_associated_account: trade_info.platform_associated_account,
|
||||
creator_associated_account: trade_info.creator_associated_account,
|
||||
global_config: trade_info.global_config,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,16 +396,22 @@ impl BonkParams {
|
||||
platform_config: trade_info.platform_config,
|
||||
platform_associated_account: trade_info.platform_associated_account,
|
||||
creator_associated_account: trade_info.creator_associated_account,
|
||||
global_config: trade_info.global_config,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn from_mint_by_rpc(
|
||||
rpc: &SolanaRpcClient,
|
||||
mint: &Pubkey,
|
||||
usd1_pool: bool,
|
||||
) -> Result<Self, anyhow::Error> {
|
||||
let pool_address = crate::instruction::utils::bonk::get_pool_pda(
|
||||
mint,
|
||||
&crate::constants::WSOL_TOKEN_ACCOUNT,
|
||||
if usd1_pool {
|
||||
&crate::constants::USD1_TOKEN_ACCOUNT
|
||||
} else {
|
||||
&crate::constants::WSOL_TOKEN_ACCOUNT
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let pool_data =
|
||||
@@ -452,6 +437,7 @@ impl BonkParams {
|
||||
platform_config: pool_data.platform_config,
|
||||
platform_associated_account,
|
||||
creator_associated_account,
|
||||
global_config: pool_data.global_config,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
use super::params::{BuyParams, SellParams};
|
||||
use crate::trading::SwapParams;
|
||||
use anyhow::Result;
|
||||
use solana_sdk::{instruction::Instruction, signature::Signature};
|
||||
|
||||
/// 交易执行器trait - 定义了所有交易协议都需要实现的核心方法
|
||||
#[async_trait::async_trait]
|
||||
pub trait TradeExecutor: Send + Sync {
|
||||
/// 使用MEV服务执行买入交易
|
||||
async fn buy_with_tip(&self, params: BuyParams) -> Result<Signature>;
|
||||
/// 使用MEV服务执行卖出交易
|
||||
async fn sell_with_tip(&self, params: SellParams) -> Result<Signature>;
|
||||
async fn swap(&self, params: SwapParams) -> Result<Signature>;
|
||||
/// 获取协议名称
|
||||
fn protocol_name(&self) -> &'static str;
|
||||
}
|
||||
@@ -17,10 +14,10 @@ pub trait TradeExecutor: Send + Sync {
|
||||
#[async_trait::async_trait]
|
||||
pub trait InstructionBuilder: Send + Sync {
|
||||
/// 构建买入指令
|
||||
async fn build_buy_instructions(&self, params: &BuyParams) -> Result<Vec<Instruction>>;
|
||||
async fn build_buy_instructions(&self, params: &SwapParams) -> Result<Vec<Instruction>>;
|
||||
|
||||
/// 构建卖出指令
|
||||
async fn build_sell_instructions(&self, params: &SellParams) -> Result<Vec<Instruction>>;
|
||||
async fn build_sell_instructions(&self, params: &SwapParams) -> Result<Vec<Instruction>>;
|
||||
}
|
||||
|
||||
/// 协议特定参数trait - 允许每个协议定义自己的参数
|
||||
|
||||
Reference in New Issue
Block a user