feat: Add Raydium AMM V4 support and middleware system

- Add Raydium AMM V4 trading protocol support
- Implement instruction middleware system for dynamic processing
- Refactor trade executors to support middleware parameters
- Add fee calculation and slippage protection mechanisms
- Maintain backward compatibility with optional middleware
This commit is contained in:
ysq
2025-08-19 18:07:21 +08:00
parent 4b74d3cfb4
commit d27a44735a
23 changed files with 1534 additions and 168 deletions
+62 -5
View File
@@ -20,8 +20,9 @@ use super::{
};
use crate::{
common::PriorityFee,
trading::common::{
add_sell_compute_budget_instructions, add_sell_tip_compute_budget_instructions,
trading::{
common::{add_sell_compute_budget_instructions, add_sell_tip_compute_budget_instructions},
MiddlewareManager,
},
};
@@ -33,6 +34,9 @@ pub async fn build_rpc_transaction(
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
data_size_limit: u32,
middleware_manager: Option<Arc<MiddlewareManager>>,
protocol_name: String,
is_buy: bool,
) -> Result<VersionedTransaction, anyhow::Error> {
let mut instructions = vec![];
@@ -54,7 +58,16 @@ pub async fn build_rpc_transaction(
let address_lookup_table_accounts = get_address_lookup_table_accounts(lookup_table_key).await;
// 构建交易
build_versioned_transaction(payer, instructions, address_lookup_table_accounts, blockhash).await
build_versioned_transaction(
payer,
instructions,
address_lookup_table_accounts,
blockhash,
middleware_manager,
protocol_name,
is_buy,
)
.await
}
/// 构建带小费的交易
@@ -67,6 +80,9 @@ pub async fn build_tip_transaction(
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
data_size_limit: u32,
middleware_manager: Option<Arc<MiddlewareManager>>,
protocol_name: String,
is_buy: bool,
) -> Result<VersionedTransaction, anyhow::Error> {
let mut instructions = vec![];
@@ -95,7 +111,16 @@ pub async fn build_tip_transaction(
let address_lookup_table_accounts = get_address_lookup_table_accounts(lookup_table_key).await;
// 构建交易
build_versioned_transaction(payer, instructions, address_lookup_table_accounts, blockhash).await
build_versioned_transaction(
payer,
instructions,
address_lookup_table_accounts,
blockhash,
middleware_manager,
protocol_name,
is_buy,
)
.await
}
/// 构建版本化交易的底层函数
@@ -104,10 +129,18 @@ async fn build_versioned_transaction(
instructions: Vec<Instruction>,
address_lookup_table_accounts: Vec<solana_sdk::message::AddressLookupTableAccount>,
blockhash: Hash,
middleware_manager: Option<Arc<MiddlewareManager>>,
protocol_name: String,
is_buy: bool,
) -> Result<VersionedTransaction, anyhow::Error> {
let full_instructions = match middleware_manager {
Some(middleware_manager) => middleware_manager
.apply_middlewares_process_full_instructions(instructions, protocol_name, is_buy)?,
None => instructions,
};
let v0_message: v0::Message = v0::Message::try_compile(
&payer.pubkey(),
&instructions,
&full_instructions,
&address_lookup_table_accounts,
blockhash,
)?;
@@ -127,6 +160,9 @@ pub async fn build_tip_transaction_with_priority_fee(
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
data_size_limit: u32,
middleware_manager: Option<Arc<MiddlewareManager>>,
protocol_name: String,
is_buy: bool,
) -> Result<VersionedTransaction, anyhow::Error> {
build_tip_transaction(
payer,
@@ -137,6 +173,9 @@ pub async fn build_tip_transaction_with_priority_fee(
lookup_table_key,
recent_blockhash,
data_size_limit,
middleware_manager,
protocol_name,
is_buy,
)
.await
}
@@ -148,6 +187,9 @@ pub async fn build_sell_transaction(
business_instructions: Vec<Instruction>,
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
middleware_manager: Option<Arc<MiddlewareManager>>,
protocol_name: String,
is_buy: bool,
) -> Result<VersionedTransaction, anyhow::Error> {
let mut instructions = vec![];
@@ -166,6 +208,9 @@ pub async fn build_sell_transaction(
instructions,
address_lookup_table_accounts,
recent_blockhash,
middleware_manager,
protocol_name,
is_buy,
)
.await
}
@@ -178,6 +223,9 @@ pub async fn build_sell_tip_transaction(
tip_amount: f64,
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
middleware_manager: Option<Arc<MiddlewareManager>>,
protocol_name: String,
is_buy: bool,
) -> Result<VersionedTransaction, anyhow::Error> {
let mut instructions = vec![];
@@ -203,6 +251,9 @@ pub async fn build_sell_tip_transaction(
instructions,
address_lookup_table_accounts,
recent_blockhash,
middleware_manager,
protocol_name,
is_buy,
)
.await
}
@@ -214,6 +265,9 @@ pub async fn build_sell_tip_transaction_with_priority_fee(
tip_account: &Pubkey,
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
middleware_manager: Option<Arc<MiddlewareManager>>,
protocol_name: String,
is_buy: bool,
) -> Result<VersionedTransaction, anyhow::Error> {
build_sell_tip_transaction(
payer,
@@ -223,6 +277,9 @@ pub async fn build_sell_tip_transaction_with_priority_fee(
priority_fee.sell_tip_fee,
lookup_table_key,
recent_blockhash,
middleware_manager,
protocol_name,
is_buy,
)
.await
}
+19
View File
@@ -6,6 +6,25 @@ use spl_token::instruction::close_account;
use crate::common::SolanaRpcClient;
use anyhow::anyhow;
/// Get the balances of two tokens in the pool
///
/// # Returns
/// Returns token0_balance, token1_balance
pub async fn get_multi_token_balances(
rpc: &SolanaRpcClient,
token0_vault: &Pubkey,
token1_vault: &Pubkey,
) -> Result<(u64, u64), anyhow::Error> {
let token0_balance = rpc.get_token_account_balance(&token0_vault).await?;
let token1_balance = rpc.get_token_account_balance(&token1_vault).await?;
// Parse balance string to u64
let token0_amount =
token0_balance.amount.parse::<u64>().map_err(|e| anyhow!("Failed to parse token0 balance: {}", e))?;
let token1_amount =
token1_balance.amount.parse::<u64>().map_err(|e| anyhow!("Failed to parse token1 balance: {}", e))?;
Ok((token0_amount, token1_amount))
}
#[inline]
pub async fn get_token_balance(
rpc: &SolanaRpcClient,