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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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已存在(无需创建)");
|
||||
}
|
||||
|
||||
@@ -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!({
|
||||
|
||||
@@ -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>,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user