diff --git a/src/lib.rs b/src/lib.rs index aae5c57..1fba8fb 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ use common::{PriorityFee, SolanaRpcClient, TradeConfig}; use parking_lot::Mutex; use rustls::crypto::{ring::default_provider, CryptoProvider}; use solana_sdk::hash::Hash; -use solana_sdk::{pubkey::Pubkey, signature::Keypair}; +use solana_sdk::{pubkey::Pubkey, signature::Keypair, signature::Signature}; use std::sync::Arc; use swqos::SwqosClient; @@ -157,7 +157,7 @@ impl SolanaTrade { lookup_table_key: Option, wait_transaction_confirmed: bool, open_seed_optimize: bool, - ) -> Result<(), anyhow::Error> { + ) -> Result { if slippage_basis_points.is_none() { println!( "slippage_basis_points is none, use default slippage basis points: {}", @@ -249,7 +249,7 @@ impl SolanaTrade { lookup_table_key: Option, wait_transaction_confirmed: bool, open_seed_optimize: bool, - ) -> Result<(), anyhow::Error> { + ) -> Result { if slippage_basis_points.is_none() { println!( "slippage_basis_points is none, use default slippage basis points: {}", @@ -355,7 +355,7 @@ impl SolanaTrade { lookup_table_key: Option, wait_transaction_confirmed: bool, open_seed_optimize: bool, - ) -> Result<(), anyhow::Error> { + ) -> Result { if percent == 0 || percent > 100 { return Err(anyhow::anyhow!("Percentage must be between 1 and 100")); } diff --git a/src/trading/core/executor.rs b/src/trading/core/executor.rs index 77c4b7a..2a94407 100755 --- a/src/trading/core/executor.rs +++ b/src/trading/core/executor.rs @@ -1,4 +1,5 @@ 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}; @@ -25,7 +26,7 @@ impl GenericTradeExecutor { #[async_trait::async_trait] impl TradeExecutor for GenericTradeExecutor { - async fn buy_with_tip(&self, params: BuyParams) -> Result<()> { + async fn buy_with_tip(&self, params: BuyParams) -> Result { let start = Instant::now(); // Build instructions directly from params to avoid unnecessary cloning @@ -43,12 +44,10 @@ impl TradeExecutor for GenericTradeExecutor { println!("Building buy transaction instructions time cost: {:?}", start.elapsed()); // Execute transactions in parallel - buy_parallel_execute(params, final_instructions, self.protocol_name).await?; - - Ok(()) + buy_parallel_execute(params, final_instructions, self.protocol_name).await } - async fn sell_with_tip(&self, params: SellParams) -> Result<()> { + async fn sell_with_tip(&self, params: SellParams) -> Result { let start = Instant::now(); // Build instructions directly from params to avoid unnecessary cloning @@ -66,9 +65,7 @@ impl TradeExecutor for GenericTradeExecutor { println!("Building sell transaction instructions time cost: {:?}", start.elapsed()); // Execute transactions in parallel - sell_parallel_execute(params, final_instructions, self.protocol_name).await?; - - Ok(()) + sell_parallel_execute(params, final_instructions, self.protocol_name).await } fn protocol_name(&self) -> &'static str { diff --git a/src/trading/core/parallel.rs b/src/trading/core/parallel.rs index c9fa778..07b10b0 100755 --- a/src/trading/core/parallel.rs +++ b/src/trading/core/parallel.rs @@ -1,6 +1,8 @@ use anyhow::{anyhow, Result}; use solana_hash::Hash; -use solana_sdk::{instruction::Instruction, pubkey::Pubkey, signature::Keypair}; +use solana_sdk::{ + instruction::Instruction, pubkey::Pubkey, signature::Keypair, signature::Signature, +}; use std::{str::FromStr, sync::Arc, time::Instant}; use tokio::sync::mpsc; use tokio::task::JoinHandle; @@ -15,7 +17,7 @@ pub async fn buy_parallel_execute( params: BuyParams, instructions: Vec, protocol_name: &'static str, -) -> Result<()> { +) -> Result { parallel_execute( params.swqos_clients, params.payer, @@ -37,7 +39,7 @@ pub async fn sell_parallel_execute( params: SellParams, instructions: Vec, protocol_name: &'static str, -) -> Result<()> { +) -> Result { parallel_execute( params.swqos_clients, params.payer, @@ -69,9 +71,9 @@ async fn parallel_execute( is_buy: bool, wait_transaction_confirmed: bool, with_tip: bool, -) -> Result<()> { +) -> Result { let cores = core_affinity::get_core_ids().unwrap(); - let mut handles: Vec>> = Vec::with_capacity(swqos_clients.len()); + let mut handles: Vec>> = Vec::with_capacity(swqos_clients.len()); if is_buy && (swqos_clients.len() > priority_fee.buy_tip_fees.len() || priority_fee.buy_tip_fees.is_empty()) @@ -147,7 +149,11 @@ async fn parallel_execute( start.elapsed() ); - Ok::<(), anyhow::Error>(()) + transaction + .signatures + .first() + .ok_or_else(|| anyhow!("Transaction has no signatures")) + .cloned() }); handles.push(handle); @@ -169,13 +175,20 @@ async fn parallel_execute( let mut errors = Vec::new(); if !wait_transaction_confirmed { - return Ok(()); + if let Some(result) = rx.recv().await { + match result { + Ok(Ok(sig)) => return Ok(sig), + Ok(Err(e)) => errors.push(format!("Task error: {}", e)), + Err(e) => errors.push(format!("Join error: {}", e)), + } + } + return Err(anyhow!("No transaction signature available")); } while let Some(result) = rx.recv().await { match result { - Ok(Ok(_)) => { - return Ok(()); + Ok(Ok(sig)) => { + return Ok(sig); } Ok(Err(e)) => errors.push(format!("Task error: {}", e)), Err(e) => errors.push(format!("Join error: {}", e)), diff --git a/src/trading/core/traits.rs b/src/trading/core/traits.rs index 3abdec9..273b2f2 100755 --- a/src/trading/core/traits.rs +++ b/src/trading/core/traits.rs @@ -1,14 +1,14 @@ use super::params::{BuyParams, SellParams}; use anyhow::Result; -use solana_sdk::instruction::Instruction; +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<()>; + async fn buy_with_tip(&self, params: BuyParams) -> Result; /// 使用MEV服务执行卖出交易 - async fn sell_with_tip(&self, params: SellParams) -> Result<()>; + async fn sell_with_tip(&self, params: SellParams) -> Result; /// 获取协议名称 fn protocol_name(&self) -> &'static str; }