feat: upgrade to v3.3.1 with enhanced error handling

Major changes:
- Bump version from 3.3.0 to 3.3.1
- Update GasFeeStrategy API with min/max data size parameters
- Enhance trade return values with Optional<anyhow::Error> in buy/sell/sell_percent methods
- Fix PumpFun Mayhem mode fee recipient constant bug
- Standardize gas fee strategy parameters across all examples
- Update all examples to handle new triple return value (bool, Signature, Option<Error>)
This commit is contained in:
ysq
2025-11-16 23:46:58 +08:00
parent 5c99a31179
commit bee7f5b78c
23 changed files with 62 additions and 60 deletions
+1 -1
View File
@@ -61,7 +61,7 @@ pub mod global_constants {
pubkey!("GesfTA3X2arioaHp8bbKdjG9vJtskViWACZoYvxp4twS");
pub const MAYHEM_FEE_RECIPIENT_META: solana_sdk::instruction::AccountMeta =
solana_sdk::instruction::AccountMeta {
pubkey: FEE_RECIPIENT,
pubkey: MAYHEM_FEE_RECIPIENT,
is_signer: false,
is_writable: true,
};
+3 -3
View File
@@ -345,7 +345,7 @@ impl SolanaTrade {
/// - Network or RPC errors occur
/// - Insufficient SOL balance for the purchase
/// - Required accounts cannot be created or accessed
pub async fn buy(&self, params: TradeBuyParams) -> Result<(bool, Signature), anyhow::Error> {
pub async fn buy(&self, params: TradeBuyParams) -> Result<(bool, Signature, Option<anyhow::Error>), anyhow::Error> {
if params.slippage_basis_points.is_none() {
println!(
"slippage_basis_points is none, use default slippage basis points: {}",
@@ -445,7 +445,7 @@ impl SolanaTrade {
/// - Insufficient token balance for the sale
/// - Token account doesn't exist or is not properly initialized
/// - Required accounts cannot be created or accessed
pub async fn sell(&self, params: TradeSellParams) -> Result<(bool, Signature), anyhow::Error> {
pub async fn sell(&self, params: TradeSellParams) -> Result<(bool, Signature, Option<anyhow::Error>), anyhow::Error> {
if params.slippage_basis_points.is_none() {
println!(
"slippage_basis_points is none, use default slippage basis points: {}",
@@ -557,7 +557,7 @@ impl SolanaTrade {
mut params: TradeSellParams,
amount_token: u64,
percent: u64,
) -> Result<(bool, Signature), anyhow::Error> {
) -> Result<(bool, Signature, Option<anyhow::Error>), anyhow::Error> {
if percent == 0 || percent > 100 {
return Err(anyhow::anyhow!("Percentage must be between 1 and 100"));
}
+12 -10
View File
@@ -21,7 +21,7 @@ use crate::{
struct TaskResult {
success: bool,
signature: Signature,
_error: Option<anyhow::Error>,
error: Option<anyhow::Error>,
}
struct ResultCollector {
@@ -54,7 +54,7 @@ impl ResultCollector {
self.completed_count.fetch_add(1, Ordering::Release);
}
async fn wait_for_success(&self) -> Option<(bool, Signature)> {
async fn wait_for_success(&self) -> Option<(bool, Signature, Option<anyhow::Error>)> {
let start = Instant::now();
let timeout = std::time::Duration::from_secs(30);
@@ -63,7 +63,7 @@ impl ResultCollector {
if self.success_flag.load(Ordering::Acquire) {
while let Some(result) = self.results.pop() {
if result.success {
return Some((true, result.signature));
return Some((true, result.signature, None));
}
}
}
@@ -71,7 +71,7 @@ impl ResultCollector {
let completed = self.completed_count.load(Ordering::Acquire);
if completed >= self.total_tasks {
while let Some(result) = self.results.pop() {
return Some((result.success, result.signature));
return Some((result.success, result.signature, result.error));
}
return None;
}
@@ -83,9 +83,9 @@ impl ResultCollector {
}
}
fn get_first(&self) -> Option<(bool, Signature)> {
fn get_first(&self) -> Option<(bool, Signature, Option<anyhow::Error>,)> {
if let Some(result) = self.results.pop() {
Some((result.success, result.signature))
Some((result.success, result.signature, result.error))
} else {
None
}
@@ -107,7 +107,7 @@ pub async fn execute_parallel(
wait_transaction_confirmed: bool,
with_tip: bool,
gas_fee_strategy: GasFeeStrategy,
) -> Result<(bool, Signature)> {
) -> Result<(bool, Signature, Option<anyhow::Error>)> {
let _exec_start = Instant::now();
if swqos_clients.is_empty() {
@@ -208,7 +208,7 @@ pub async fn execute_parallel(
collector.submit(TaskResult {
success: false,
signature: Signature::default(),
_error: Some(e),
error: Some(e),
});
return;
}
@@ -217,6 +217,7 @@ pub async fn execute_parallel(
// Transaction built
let _send_start = Instant::now();
let mut err = None;
let success = match swqos_client
.send_transaction(
if is_buy { TradeType::Buy } else { TradeType::Sell },
@@ -225,7 +226,8 @@ pub async fn execute_parallel(
.await
{
Ok(()) => true,
Err(_e) => {
Err(e) => {
err = Some(e);
// Send transaction failed
false
}
@@ -234,7 +236,7 @@ pub async fn execute_parallel(
// Transaction sent
if let Some(signature) = transaction.signatures.first() {
collector.submit(TaskResult { success, signature: *signature, _error: None });
collector.submit(TaskResult { success, signature: *signature, error: err });
}
});
}
+4 -4
View File
@@ -44,7 +44,7 @@ impl GenericTradeExecutor {
#[async_trait::async_trait]
impl TradeExecutor for GenericTradeExecutor {
async fn swap(&self, params: SwapParams) -> Result<(bool, Signature)> {
async fn swap(&self, params: SwapParams) -> Result<(bool, Signature, Option<anyhow::Error>)> {
let total_start = Instant::now();
// 判断买卖方向
@@ -201,7 +201,7 @@ async fn simulate_transaction(
is_buy: bool,
with_tip: bool,
gas_fee_strategy: GasFeeStrategy,
) -> Result<(bool, Signature)> {
) -> Result<(bool, Signature, Option<anyhow::Error>)> {
use crate::trading::common::build_transaction;
use solana_client::rpc_config::RpcSimulateTransactionConfig;
use solana_commitment_config::CommitmentLevel;
@@ -288,7 +288,7 @@ async fn simulate_transaction(
}
println!("=========================================\n");
return Ok((false, signature));
return Ok((false, signature, Some(anyhow::anyhow!("{:?}", err))));
}
// Simulation succeeded
@@ -308,5 +308,5 @@ async fn simulate_transaction(
println!("============================================\n");
Ok((true, signature))
Ok((true, signature, None))
}
+1 -1
View File
@@ -5,7 +5,7 @@ use solana_sdk::{instruction::Instruction, signature::Signature};
/// 交易执行器trait - 定义了所有交易协议都需要实现的核心方法
#[async_trait::async_trait]
pub trait TradeExecutor: Send + Sync {
async fn swap(&self, params: SwapParams) -> Result<(bool, Signature)>;
async fn swap(&self, params: SwapParams) -> Result<(bool, Signature, Option<anyhow::Error>)>;
/// 获取协议名称
fn protocol_name(&self) -> &'static str;
}