fix: WSOL ATA creation in background with retry/timeout; silence unused and deprecated warnings

- lib: WSOL ATA creation moved to background to avoid blocking startup; ensure_wsol_ata adds 3 retries and 10s timeout
- lib: cfg(feature = "perf-trace") for DEFAULT_SLIPPAGE usage
- gas_fee_strategy, bloxroute, transaction_builder, async_executor, executor: prefix unused vars/params with underscore or allow
- pumpswap: add allow(deprecated) for get_program_accounts_with_config

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Wood
2026-02-12 23:32:55 +08:00
parent 710a8d482f
commit feaac5ddd2
7 changed files with 90 additions and 27 deletions
+4 -4
View File
@@ -300,7 +300,7 @@ impl GasFeeStrategy {
pub fn update_buy_tip(&self, buy_tip: f64) {
self.strategies.rcu(|current_map| {
let mut new_map = (**current_map).clone();
for ((swqos_type, trade_type, strategy_type), value) in new_map.iter_mut() {
for ((_swqos_type, trade_type, _strategy_type), value) in new_map.iter_mut() {
if *trade_type == TradeType::Buy {
value.tip = buy_tip;
}
@@ -314,7 +314,7 @@ impl GasFeeStrategy {
pub fn update_sell_tip(&self, sell_tip: f64) {
self.strategies.rcu(|current_map| {
let mut new_map = (**current_map).clone();
for ((swqos_type, trade_type, strategy_type), value) in new_map.iter_mut() {
for ((_swqos_type, trade_type, _strategy_type), value) in new_map.iter_mut() {
if *trade_type == TradeType::Sell {
value.tip = sell_tip;
}
@@ -328,7 +328,7 @@ impl GasFeeStrategy {
pub fn update_buy_cu_price(&self, buy_cu_price: u64) {
self.strategies.rcu(|current_map| {
let mut new_map = (**current_map).clone();
for ((swqos_type, trade_type, strategy_type), value) in new_map.iter_mut() {
for ((_swqos_type, trade_type, _strategy_type), value) in new_map.iter_mut() {
if *trade_type == TradeType::Buy {
value.cu_price = buy_cu_price;
}
@@ -342,7 +342,7 @@ impl GasFeeStrategy {
pub fn update_sell_cu_price(&self, sell_cu_price: u64) {
self.strategies.rcu(|current_map| {
let mut new_map = (**current_map).clone();
for ((swqos_type, trade_type, strategy_type), value) in new_map.iter_mut() {
for ((_swqos_type, trade_type, _strategy_type), value) in new_map.iter_mut() {
if *trade_type == TradeType::Sell {
value.cu_price = sell_cu_price;
}
+2
View File
@@ -227,6 +227,7 @@ pub async fn find_by_base_mint(
sort_results: None,
};
let program_id = accounts::AMM_PROGRAM;
#[allow(deprecated)]
let accounts = rpc.get_program_accounts_with_config(&program_id, config).await?;
if accounts.is_empty() {
return Err(anyhow!("No pool found for mint {}", base_mint));
@@ -277,6 +278,7 @@ pub async fn find_by_quote_mint(
sort_results: None,
};
let program_id = accounts::AMM_PROGRAM;
#[allow(deprecated)]
let accounts = rpc.get_program_accounts_with_config(&program_id, config).await?;
if accounts.is_empty() {
return Err(anyhow!("No pool found for mint {}", quote_mint));
+79 -19
View File
@@ -8,6 +8,7 @@ pub mod utils;
use crate::common::nonce_cache::DurableNonceInfo;
use crate::common::GasFeeStrategy;
use crate::common::{TradeConfig, InfrastructureConfig};
#[cfg(feature = "perf-trace")]
use crate::constants::trade::trade::DEFAULT_SLIPPAGE;
use crate::constants::SOL_TOKEN_ACCOUNT;
use crate::constants::USD1_TOKEN_ACCOUNT;
@@ -286,7 +287,13 @@ impl TradingClient {
crate::common::fast_fn::fast_init(&payer.pubkey());
if create_wsol_ata {
Self::ensure_wsol_ata(&payer, &infrastructure.rpc).await;
// 在后台异步创建 WSOL ATA,不阻塞启动
let payer_clone = payer.clone();
let rpc_clone = infrastructure.rpc.clone();
tokio::spawn(async move {
Self::ensure_wsol_ata(&payer_clone, &rpc_clone).await;
});
println!("ℹ️ WSOL ATA 创建已在后台启动,不阻塞机器人启动");
}
Self {
@@ -309,6 +316,7 @@ impl TradingClient {
match rpc.get_account(&wsol_ata).await {
Ok(_) => {
println!("✅ WSOL ATA已存在: {}", wsol_ata);
return;
}
Err(_) => {
println!("🔨 创建WSOL ATA: {}", wsol_ata);
@@ -317,35 +325,87 @@ impl TradingClient {
if !create_ata_ixs.is_empty() {
use solana_sdk::transaction::Transaction;
let recent_blockhash = rpc.get_latest_blockhash().await.unwrap();
let tx = Transaction::new_signed_with_payer(
&create_ata_ixs,
Some(&payer.pubkey()),
&[payer.as_ref()],
recent_blockhash,
);
match rpc.send_and_confirm_transaction(&tx).await {
Ok(signature) => {
println!("✅ WSOL ATA创建成功: {}", signature);
// 重试逻辑:最多尝试3次,每次超时10秒
const MAX_RETRIES: usize = 3;
const TIMEOUT_SECS: u64 = 10;
let mut last_error = None;
for attempt in 1..=MAX_RETRIES {
if attempt > 1 {
println!("🔄 重试创建WSOL ATA (第{}/{}次)...", attempt, MAX_RETRIES);
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
}
Err(e) => {
match rpc.get_account(&wsol_ata).await {
Ok(_) => {
let recent_blockhash = match rpc.get_latest_blockhash().await {
Ok(hash) => hash,
Err(e) => {
eprintln!("⚠️ 获取最新blockhash失败: {}", e);
last_error = Some(format!("获取blockhash失败: {}", e));
continue;
}
};
let tx = Transaction::new_signed_with_payer(
&create_ata_ixs,
Some(&payer.pubkey()),
&[payer.as_ref()],
recent_blockhash,
);
// 使用超时包装 send_and_confirm_transaction
let send_result = tokio::time::timeout(
tokio::time::Duration::from_secs(TIMEOUT_SECS),
rpc.send_and_confirm_transaction(&tx)
).await;
match send_result {
Ok(Ok(signature)) => {
println!("✅ WSOL ATA创建成功: {}", signature);
return;
}
Ok(Err(e)) => {
last_error = Some(format!("{}", e));
// 检查账户是否实际已存在
if let Ok(_) = rpc.get_account(&wsol_ata).await {
println!(
"✅ WSOL ATA已存在(交易失败但账户存在): {}",
wsol_ata
);
return;
}
Err(_) => {
panic!(
"❌ WSOL ATA创建失败且账户不存在: {}. 错误: {}",
wsol_ata, e
);
if attempt < MAX_RETRIES {
eprintln!("⚠️ 第{}次尝试失败: {}", attempt, e);
}
}
Err(_) => {
last_error = Some(format!("交易确认超时({}秒)", TIMEOUT_SECS));
eprintln!("⚠️ 第{}次尝试超时", attempt);
}
}
}
// 所有重试都失败了
if let Some(err) = last_error {
eprintln!("❌ WSOL ATA创建失败(已重试{}次): {}", MAX_RETRIES, wsol_ata);
eprintln!(" 错误详情: {}", err);
eprintln!(" 💡 可能原因:");
eprintln!(" 1. 钱包SOL余额不足(需要约0.002 SOL用于租金豁免)");
eprintln!(" 2. RPC节点响应超时或网络拥堵");
eprintln!(" 3. 交易费用不足");
eprintln!(" 🔧 解决方案:");
eprintln!(" 1. 给钱包充值至少0.1 SOL");
eprintln!(" 2. 等待几秒后重试");
eprintln!(" 3. 检查RPC节点连接");
eprintln!(" ⚠️ 程序将在5秒后退出,请解决上述问题后重启");
std::thread::sleep(std::time::Duration::from_secs(5));
panic!(
"❌ WSOL ATA创建失败且账户不存在: {}. 错误: {}",
wsol_ata, err
);
}
} else {
println!("ℹ️ WSOL ATA已存在(无需创建)");
}
+1 -1
View File
@@ -111,7 +111,7 @@ impl BloxrouteClient {
Ok(())
}
pub async fn send_transactions(&self, trade_type: TradeType, transactions: &Vec<VersionedTransaction>, wait_confirmation: bool) -> Result<()> {
pub async fn send_transactions(&self, trade_type: TradeType, transactions: &Vec<VersionedTransaction>, _wait_confirmation: bool) -> Result<()> {
let start_time = Instant::now();
let body = serde_json::json!({
+1 -2
View File
@@ -11,14 +11,13 @@ use super::{
};
use crate::{
common::{nonce_cache::DurableNonceInfo, SolanaRpcClient},
constants::swqos::NODE1_TIP_ACCOUNTS,
trading::{MiddlewareManager, core::transaction_pool::{acquire_builder, release_builder}},
};
/// Build standard RPC transaction
pub async fn build_transaction(
payer: Arc<Keypair>,
rpc: Option<Arc<SolanaRpcClient>>,
_rpc: Option<Arc<SolanaRpcClient>>,
unit_limit: u32,
unit_price: u64,
business_instructions: Vec<Instruction>,
+2
View File
@@ -38,6 +38,7 @@ struct TaskResult {
success: bool,
signature: Signature,
error: Option<anyhow::Error>,
#[allow(dead_code)]
swqos_type: SwqosType, // 🔧 增加:记录SWQOS类型
landed_on_chain: bool, // 🔧 Whether tx landed on-chain (even if failed)
}
@@ -349,6 +350,7 @@ pub async fn execute_parallel(
let _send_start = Instant::now();
let mut err: Option<anyhow::Error> = None;
#[allow(unused_assignments)]
let mut landed_on_chain = false;
let success = match swqos_client
.send_transaction(
+1 -1
View File
@@ -11,7 +11,7 @@ use crate::{
perf::syscall_bypass::SystemCallBypassManager,
trading::core::{
async_executor::execute_parallel,
execution::{ExecutionPath, InstructionProcessor, Prefetch},
execution::{InstructionProcessor, Prefetch},
traits::TradeExecutor,
},
trading::MiddlewareManager,