From 9438172029b171ee23d1b52a3083dc9009898cac Mon Sep 17 00:00:00 2001 From: ysq Date: Wed, 27 Aug 2025 14:27:26 +0800 Subject: [PATCH] feat: upgrade to v0.5.2 --- Cargo.toml | 2 +- README.md | 4 +-- README_CN.md | 4 +-- src/swqos/bloxroute.rs | 20 ++++++----- src/swqos/common.rs | 10 +++--- src/swqos/flashblock.rs | 18 +++++----- src/swqos/jito.rs | 16 +++++---- src/swqos/mod.rs | 8 ++--- src/swqos/nextblock.rs | 12 ++++--- src/swqos/node1.rs | 64 +++++++++++++++++++----------------- src/swqos/solana_rpc.rs | 50 ++++++++++++++++++---------- src/swqos/temporal.rs | 14 ++++---- src/swqos/zeroslot.rs | 20 ++++++----- src/trading/core/executor.rs | 44 ++++++++++++------------- src/trading/core/parallel.rs | 29 +++++++++------- src/trading/core/timer.rs | 33 +++++++++---------- 16 files changed, 189 insertions(+), 159 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b5d200d..f26d9db 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sol-trade-sdk" -version = "0.5.1" +version = "0.5.2" edition = "2021" authors = [ "William ", diff --git a/README.md b/README.md index 39478e2..167b404 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,14 @@ Add the dependency to your `Cargo.toml`: ```toml # Add to your Cargo.toml -sol-trade-sdk = { path = "./sol-trade-sdk", version = "0.5.1" } +sol-trade-sdk = { path = "./sol-trade-sdk", version = "0.5.2" } ``` ### Use crates.io ```toml # Add to your Cargo.toml -sol-trade-sdk = "0.5.1" +sol-trade-sdk = "0.5.2" ``` ## Usage Examples diff --git a/README_CN.md b/README_CN.md index dd362f3..8f6f941 100755 --- a/README_CN.md +++ b/README_CN.md @@ -33,14 +33,14 @@ git clone https://github.com/0xfnzero/sol-trade-sdk ```toml # 添加到您的 Cargo.toml -sol-trade-sdk = { path = "./sol-trade-sdk", version = "0.5.1" } +sol-trade-sdk = { path = "./sol-trade-sdk", version = "0.5.2" } ``` ### 使用 crates.io ```toml # 添加到您的 Cargo.toml -sol-trade-sdk = "0.5.1" +sol-trade-sdk = "0.5.2" ``` ## 使用示例 diff --git a/src/swqos/bloxroute.rs b/src/swqos/bloxroute.rs index 9a7f78e..1aabed5 100755 --- a/src/swqos/bloxroute.rs +++ b/src/swqos/bloxroute.rs @@ -60,7 +60,7 @@ impl BloxrouteClient { pub async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction) -> Result<()> { let start_time = Instant::now(); let (content, signature) = serialize_transaction_and_encode(transaction, UiTransactionEncoding::Base64).await?; - println!(" 交易编码base64: {:?}", start_time.elapsed()); + println!(" Transaction encoded to base64: {:?}", start_time.elapsed()); let body = serde_json::json!({ "transaction": { @@ -80,32 +80,34 @@ impl BloxrouteClient { .text() .await?; - // 5. 用 `serde_json::from_str()` 解析 JSON,减少 `.json().await?` 额外等待 + // 5. Use `serde_json::from_str()` to parse JSON, reducing extra wait from `.json().await?` if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" bloxroute{}提交: {:?}", trade_type, start_time.elapsed()); + println!(" bloxroute {} submitted: {:?}", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" bloxroute{}提交失败: {:?}", trade_type, _error); + eprintln!(" bloxroute {} submission failed: {:?}", trade_type, _error); } + } else { + eprintln!(" bloxroute {} submission failed: {:?}", trade_type, response_text); } let start_time: Instant = Instant::now(); match poll_transaction_confirmation(&self.rpc_client, signature).await { Ok(_) => (), Err(e) => { - println!(" bloxroute{}确认失败: {:?}", trade_type, start_time.elapsed()); + println!(" bloxroute {} confirmation failed: {:?}", trade_type, start_time.elapsed()); return Err(e); }, } - println!(" bloxroute{}确认: {:?}", trade_type, start_time.elapsed()); + println!(" bloxroute {} confirmed: {:?}", trade_type, start_time.elapsed()); Ok(()) } pub async fn send_transactions(&self, trade_type: TradeType, transactions: &Vec) -> Result<()> { let start_time = Instant::now(); - println!(" 交易编码base64: {:?}", start_time.elapsed()); + println!(" Transaction encoded to base64: {:?}", start_time.elapsed()); let body = serde_json::json!({ "entries": transactions @@ -132,9 +134,9 @@ impl BloxrouteClient { if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" bloxroute{}提交: {:?}", trade_type, start_time.elapsed()); + println!(" bloxroute {} submitted: {:?}", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" bloxroute{}提交失败: {:?}", trade_type, _error); + eprintln!(" bloxroute {} submission failed: {:?}", trade_type, _error); } } diff --git a/src/swqos/common.rs b/src/swqos/common.rs index ec45623..c042726 100755 --- a/src/swqos/common.rs +++ b/src/swqos/common.rs @@ -59,7 +59,7 @@ pub async fn poll_transaction_confirmation(rpc: &SolanaRpcClient, txt_sig: Signa pub async fn send_nb_transaction(client: Client, endpoint: &str, auth_token: &str, transaction: &Transaction) -> Result { // 序列化交易 let serialized = bincode::serialize(transaction) - .map_err(|e| anyhow::anyhow!("序列化交易失败: {}", e))?; + .map_err(|e| anyhow::anyhow!("Transaction serialization failed: {}", e))?; // Base64编码 let encoded = STANDARD.encode(serialized); @@ -79,20 +79,20 @@ pub async fn send_nb_transaction(client: Client, endpoint: &str, auth_token: &st .json(&request_data) .send() .await - .map_err(|e| anyhow::anyhow!("请求失败: {}", e))?; + .map_err(|e| anyhow::anyhow!("Request failed: {}", e))?; let resp = response.json::().await - .map_err(|e| anyhow::anyhow!("解析响应失败: {}", e))?; + .map_err(|e| anyhow::anyhow!("Response parsing failed: {}", e))?; if let Some(reason) = resp["reason"].as_str() { return Err(anyhow::anyhow!(reason.to_string())); } let signature = resp["signature"].as_str() - .ok_or_else(|| anyhow::anyhow!("响应中缺少signature字段"))?; + .ok_or_else(|| anyhow::anyhow!("Missing signature field in response"))?; let signature = Signature::from_str(signature) - .map_err(|e| anyhow::anyhow!("无效的签名: {}", e))?; + .map_err(|e| anyhow::anyhow!("Invalid signature: {}", e))?; Ok(signature) } diff --git a/src/swqos/flashblock.rs b/src/swqos/flashblock.rs index 0eb2b56..7284704 100644 --- a/src/swqos/flashblock.rs +++ b/src/swqos/flashblock.rs @@ -61,16 +61,16 @@ impl FlashBlockClient { pub async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction) -> Result<()> { let start_time = Instant::now(); let (content, signature) = serialize_transaction_and_encode(transaction, UiTransactionEncoding::Base64).await?; - println!(" 交易编码base64: {:?}", start_time.elapsed()); + println!(" Transaction encoded to base64: {:?}", start_time.elapsed()); - // FlashBlock API格式 + // FlashBlock API format let request_body = serde_json::to_string(&json!({ "transactions": [content] }))?; let url = format!("{}/api/v2/submit-batch", self.endpoint); - // 发送请求到FlashBlock + // Send request to FlashBlock let response_text = self.http_client.post(&url) .body(request_body) .header("Authorization", &self.auth_token) @@ -80,25 +80,27 @@ impl FlashBlockClient { .text() .await?; - // 解析响应 + // Parse response if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("success").is_some() || response_json.get("result").is_some() { - println!(" FlashBlock{}提交: {:?}", trade_type, start_time.elapsed()); + println!(" FlashBlock {} submitted: {:?}", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" FlashBlock{}提交失败: {:?}", trade_type, _error); + eprintln!(" FlashBlock {} submission failed: {:?}", trade_type, _error); } + } else { + eprintln!(" FlashBlock {} submission failed: {:?}", trade_type, response_text); } let start_time: Instant = Instant::now(); match poll_transaction_confirmation(&self.rpc_client, signature).await { Ok(_) => (), Err(e) => { - println!(" FlashBlock{}确认失败: {:?}", trade_type, start_time.elapsed()); + println!(" FlashBlock {} confirmation failed: {:?}", trade_type, start_time.elapsed()); return Err(e); }, } - println!(" FlashBlock{}确认: {:?}", trade_type, start_time.elapsed()); + println!(" FlashBlock {} confirmed: {:?}", trade_type, start_time.elapsed()); Ok(()) } diff --git a/src/swqos/jito.rs b/src/swqos/jito.rs index bbe4d0b..8ba320a 100755 --- a/src/swqos/jito.rs +++ b/src/swqos/jito.rs @@ -64,7 +64,7 @@ impl JitoClient { pub async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction) -> Result<()> { let start_time = Instant::now(); let (content, signature) = serialize_transaction_and_encode(transaction, UiTransactionEncoding::Base64).await?; - println!(" 交易编码base64: {:?}", start_time.elapsed()); + println!(" Transaction encoded to base64: {:?}", start_time.elapsed()); let request_body = serde_json::to_string(&json!({ "id": 1, @@ -99,22 +99,24 @@ impl JitoClient { if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" jito{}提交: {:?}", trade_type, start_time.elapsed()); + println!(" jito {} submitted: {:?}", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" jito{}提交失败: {:?}", trade_type, _error); + eprintln!(" jito {} submission failed: {:?}", trade_type, _error); } + } else { + eprintln!(" jito {} submission failed: {:?}", trade_type, response_text); } let start_time: Instant = Instant::now(); match poll_transaction_confirmation(&self.rpc_client, signature).await { Ok(_) => (), Err(e) => { - println!(" jito{}确认失败: {:?}", trade_type, start_time.elapsed()); + println!(" jito {} confirmation failed: {:?}", trade_type, start_time.elapsed()); return Err(e); }, } - println!(" jito{}确认: {:?}", trade_type, start_time.elapsed()); + println!(" jito {} confirmed: {:?}", trade_type, start_time.elapsed()); Ok(()) } @@ -153,9 +155,9 @@ impl JitoClient { if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" jito{}提交: {:?}", trade_type, start_time.elapsed()); + println!(" jito {} submitted: {:?}", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" jito{}提交失败: {:?}", trade_type, _error); + eprintln!(" jito {} submission failed: {:?}", trade_type, _error); } } diff --git a/src/swqos/mod.rs b/src/swqos/mod.rs index 8cabba8..17014d0 100755 --- a/src/swqos/mod.rs +++ b/src/swqos/mod.rs @@ -53,10 +53,10 @@ pub enum TradeType { impl std::fmt::Display for TradeType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { - TradeType::Create => "创建", - TradeType::CreateAndBuy => "创建并买入", - TradeType::Buy => "买入", - TradeType::Sell => "卖出", + TradeType::Create => "Create", + TradeType::CreateAndBuy => "Create and Buy", + TradeType::Buy => "Buy", + TradeType::Sell => "Sell", }; write!(f, "{}", s) } diff --git a/src/swqos/nextblock.rs b/src/swqos/nextblock.rs index 67ca398..43c70a0 100755 --- a/src/swqos/nextblock.rs +++ b/src/swqos/nextblock.rs @@ -60,7 +60,7 @@ impl NextBlockClient { pub async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction) -> Result<()> { let start_time = Instant::now(); let (content, signature) = serialize_transaction_and_encode(transaction, UiTransactionEncoding::Base64).await?; - println!(" 交易编码base64: {:?}", start_time.elapsed()); + println!(" Transaction encoded to base64: {:?}", start_time.elapsed()); let request_body = serde_json::to_string(&json!({ "transaction": { @@ -80,22 +80,24 @@ impl NextBlockClient { if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" nextblock{}提交: {:?}", trade_type, start_time.elapsed()); + println!(" nextblock {} submitted: {:?}", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" nextblock{}提交失败: {:?}", trade_type, _error); + eprintln!(" nextblock {} submission failed: {:?}", trade_type, _error); } + } else { + eprintln!(" nextblock {} submission failed: {:?}", trade_type, response_text); } let start_time: Instant = Instant::now(); match poll_transaction_confirmation(&self.rpc_client, signature).await { Ok(_) => (), Err(e) => { - println!(" nextblock{}确认失败: {:?}", trade_type, start_time.elapsed()); + println!(" nextblock {} confirmation failed: {:?}", trade_type, start_time.elapsed()); return Err(e); }, } - println!(" nextblock{}确认: {:?}", trade_type, start_time.elapsed()); + println!(" nextblock {} confirmed: {:?}", trade_type, start_time.elapsed()); Ok(()) } diff --git a/src/swqos/node1.rs b/src/swqos/node1.rs index 94dfe21..52e9fe8 100644 --- a/src/swqos/node1.rs +++ b/src/swqos/node1.rs @@ -51,15 +51,15 @@ impl Node1Client { pub fn new(rpc_url: String, endpoint: String, auth_token: String) -> Self { let rpc_client = SolanaRpcClient::new(rpc_url); let http_client = Client::builder() - // 由于有 ping 机制,可以延长连接池空闲超时 - .pool_idle_timeout(Duration::from_secs(300)) // 5分钟,比 ping 间隔更长 - .pool_max_idle_per_host(32) // 减少连接数,因为连接会更稳定 - // TCP keepalive 可以设置得更长,因为 ping 会主动保持连接 - .tcp_keepalive(Some(Duration::from_secs(300))) // 5分钟 - // HTTP/2 keepalive 间隔可以更长 - .http2_keep_alive_interval(Duration::from_secs(30)) // 30秒 - // 请求超时可以适当延长,因为连接更稳定 - .timeout(Duration::from_secs(15)) // 15秒 + // Due to ping mechanism, can extend connection pool idle timeout + .pool_idle_timeout(Duration::from_secs(300)) // 5 minutes, longer than ping interval + .pool_max_idle_per_host(32) // Reduce connections as they will be more stable + // TCP keepalive can be set longer as ping will actively maintain connections + .tcp_keepalive(Some(Duration::from_secs(300))) // 5 minutes + // HTTP/2 keepalive interval can be longer + .http2_keep_alive_interval(Duration::from_secs(30)) // 30 seconds + // Request timeout can be appropriately extended as connections are more stable + .timeout(Duration::from_secs(15)) // 15 seconds .connect_timeout(Duration::from_secs(5)) .build() .unwrap(); @@ -73,7 +73,7 @@ impl Node1Client { stop_ping: Arc::new(AtomicBool::new(false)), }; - // 启动 ping 任务 + // Start ping task let client_clone = client.clone(); tokio::spawn(async move { client_clone.start_ping_task().await; @@ -82,7 +82,7 @@ impl Node1Client { client } - /// 启动定期 ping 任务以保持连接活跃 + /// Start periodic ping task to keep connections active async fn start_ping_task(&self) { let endpoint = self.endpoint.clone(); let auth_token = self.auth_token.clone(); @@ -90,7 +90,7 @@ impl Node1Client { let stop_ping = self.stop_ping.clone(); let handle = tokio::spawn(async move { - let mut interval = tokio::time::interval(Duration::from_secs(60)); // 每60秒ping一次 + let mut interval = tokio::time::interval(Duration::from_secs(60)); // Ping every 60 seconds loop { interval.tick().await; @@ -99,14 +99,14 @@ impl Node1Client { break; } - // 发送 ping 请求 + // Send ping request if let Err(e) = Self::send_ping_request(&http_client, &endpoint, &auth_token).await { - eprintln!("Node1 ping 请求失败: {}", e); + eprintln!("Node1 ping request failed: {}", e); } } }); - // 更新 ping_handle - 使用 Mutex 来安全地更新 + // Update ping_handle - use Mutex to safely update { let mut ping_guard = self.ping_handle.lock().await; if let Some(old_handle) = ping_guard.as_ref() { @@ -116,25 +116,25 @@ impl Node1Client { } } - /// 发送 ping 请求到 /ping 端点 + /// Send ping request to /ping endpoint async fn send_ping_request(http_client: &Client, endpoint: &str, _auth_token: &str) -> Result<()> { - // 构建 ping URL + // Build ping URL let ping_url = if endpoint.ends_with('/') { format!("{}ping", endpoint) } else { format!("{}/ping", endpoint) }; - // 发送 GET 请求到 /ping 端点(不需要 api-key) + // Send GET request to /ping endpoint (no api-key required) let response = http_client.get(&ping_url) .send() .await?; if response.status().is_success() { - // ping 成功,连接保持活跃 - // 可以选择性地记录日志,但为了减少噪音,这里不打印 + // ping successful, connection remains active + // Can optionally log, but to reduce noise, not printing here } else { - eprintln!("Node1 ping 请求返回非成功状态: {}", response.status()); + eprintln!("Node1 ping request returned non-success status: {}", response.status()); } Ok(()) @@ -143,7 +143,7 @@ impl Node1Client { pub async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction) -> Result<()> { let start_time = Instant::now(); let (content, signature) = serialize_transaction_and_encode(transaction, UiTransactionEncoding::Base64).await?; - println!(" 交易编码base64: {:?}", start_time.elapsed()); + println!(" Transaction encoded to base64: {:?}", start_time.elapsed()); let request_body = serde_json::to_string(&json!({ "jsonrpc": "2.0", @@ -155,7 +155,7 @@ impl Node1Client { ] }))?; - // Node1使用api-key header而不是URL参数 + // Node1 uses api-key header instead of URL parameter let response_text = self.http_client.post(&self.endpoint) .body(request_body) .header("Content-Type", "application/json") @@ -165,25 +165,27 @@ impl Node1Client { .text() .await?; - // 解析JSON响应 + // Parse JSON response if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" node1{}提交: {:?}", trade_type, start_time.elapsed()); + println!(" node1 {} submitted: {:?}", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" node1{}提交失败: {:?}", trade_type, _error); + eprintln!(" node1 {} submission failed: {:?}", trade_type, _error); } + } else { + eprintln!(" node1 {} submission failed: {:?}", trade_type, response_text); } let start_time: Instant = Instant::now(); match poll_transaction_confirmation(&self.rpc_client, signature).await { Ok(_) => (), Err(e) => { - println!(" node1{}确认失败: {:?}", trade_type, start_time.elapsed()); + println!(" node1 {} confirmation failed: {:?}", trade_type, start_time.elapsed()); return Err(e); }, } - println!(" node1{}确认: {:?}", trade_type, start_time.elapsed()); + println!(" node1 {} confirmed: {:?}", trade_type, start_time.elapsed()); Ok(()) } @@ -198,11 +200,11 @@ impl Node1Client { impl Drop for Node1Client { fn drop(&mut self) { - // 确保在客户端被销毁时停止 ping 任务 + // Ensure ping task stops when client is destroyed self.stop_ping.store(true, Ordering::Relaxed); - // 尝试立即停止 ping 任务 - // 使用 tokio::spawn 来避免阻塞 Drop + // Try to stop ping task immediately + // Use tokio::spawn to avoid blocking Drop let ping_handle = self.ping_handle.clone(); tokio::spawn(async move { let mut ping_guard = ping_handle.lock().await; diff --git a/src/swqos/solana_rpc.rs b/src/swqos/solana_rpc.rs index 44398c4..a6654d3 100755 --- a/src/swqos/solana_rpc.rs +++ b/src/swqos/solana_rpc.rs @@ -1,14 +1,14 @@ use std::{sync::Arc, time::Instant}; use solana_client::rpc_config::RpcSendTransactionConfig; -use solana_sdk::{ - commitment_config::CommitmentLevel, - transaction::VersionedTransaction, -}; +use solana_sdk::{commitment_config::CommitmentLevel, transaction::VersionedTransaction}; use solana_transaction_status::UiTransactionEncoding; -use crate::{common::SolanaRpcClient, swqos::{common::poll_transaction_confirmation, SwqosType, TradeType}}; use crate::swqos::SwqosClientTrait; +use crate::{ + common::SolanaRpcClient, + swqos::{common::poll_transaction_confirmation, SwqosType, TradeType}, +}; use anyhow::Result; #[derive(Clone)] @@ -18,30 +18,44 @@ pub struct SolRpcClient { #[async_trait::async_trait] impl SwqosClientTrait for SolRpcClient { - async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction) -> Result<()> { - let signature = self.rpc_client.send_transaction_with_config(transaction, RpcSendTransactionConfig{ - skip_preflight: true, - preflight_commitment: Some(CommitmentLevel::Processed), - encoding: Some(UiTransactionEncoding::Base64), - max_retries: Some(3), - min_context_slot: Some(0), - }).await?; + async fn send_transaction( + &self, + trade_type: TradeType, + transaction: &VersionedTransaction, + ) -> Result<()> { + let signature = self + .rpc_client + .send_transaction_with_config( + transaction, + RpcSendTransactionConfig { + skip_preflight: true, + preflight_commitment: Some(CommitmentLevel::Processed), + encoding: Some(UiTransactionEncoding::Base64), + max_retries: Some(3), + min_context_slot: Some(0), + }, + ) + .await?; let start_time = Instant::now(); match poll_transaction_confirmation(&self.rpc_client, signature).await { Ok(_) => (), Err(e) => { - println!(" rpc{}确认失败: {:?}", trade_type, start_time.elapsed()); + println!(" rpc{} confirmation failed: {:?}", trade_type, start_time.elapsed()); return Err(e); - }, + } } println!(" signature: {:?}", signature); - println!(" rpc{}确认: {:?}", trade_type, start_time.elapsed()); + println!(" rpc{} confirmed: {:?}", trade_type, start_time.elapsed()); Ok(()) } - async fn send_transactions(&self, trade_type: TradeType, transactions: &Vec) -> Result<()> { + async fn send_transactions( + &self, + trade_type: TradeType, + transactions: &Vec, + ) -> Result<()> { for transaction in transactions { self.send_transaction(trade_type, transaction).await?; } @@ -61,4 +75,4 @@ impl SolRpcClient { pub fn new(rpc_client: Arc) -> Self { Self { rpc_client } } -} \ No newline at end of file +} diff --git a/src/swqos/temporal.rs b/src/swqos/temporal.rs index c190c45..81ecc9c 100755 --- a/src/swqos/temporal.rs +++ b/src/swqos/temporal.rs @@ -61,9 +61,9 @@ impl TemporalClient { pub async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction) -> Result<()> { let start_time = Instant::now(); let (content, signature) = serialize_transaction_and_encode(transaction, UiTransactionEncoding::Base64).await?; - println!(" 交易编码base64: {:?}", start_time.elapsed()); + println!(" Transaction encoded to base64: {:?}", start_time.elapsed()); - // 按照 Nozomi 文档要求构建请求体 + // Build request body according to Nozomi documentation requirements let request_body = serde_json::to_string(&json!({ "jsonrpc": "2.0", "id": 1, @@ -89,22 +89,24 @@ impl TemporalClient { if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" nozomi{}提交: {:?}", trade_type, start_time.elapsed()); + println!(" nozomi {} submitted: {:?}", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - // eprintln!("nozomi交易提交失败: {:?}", _error); + // eprintln!("nozomi transaction submission failed: {:?}", _error); } + } else { + eprintln!(" nozomi {} submission failed: {:?}", trade_type, response_text); } let start_time: Instant = Instant::now(); match poll_transaction_confirmation(&self.rpc_client, signature).await { Ok(_) => (), Err(e) => { - println!(" nozomi{}确认失败: {:?}", trade_type, start_time.elapsed()); + println!(" nozomi {} confirmation failed: {:?}", trade_type, start_time.elapsed()); return Err(e); }, } - println!(" nozomi{}确认: {:?}", trade_type, start_time.elapsed()); + println!(" nozomi {} confirmed: {:?}", trade_type, start_time.elapsed()); Ok(()) } diff --git a/src/swqos/zeroslot.rs b/src/swqos/zeroslot.rs index 8b11b3f..b06e651 100755 --- a/src/swqos/zeroslot.rs +++ b/src/swqos/zeroslot.rs @@ -61,7 +61,7 @@ impl ZeroSlotClient { pub async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction) -> Result<()> { let start_time = Instant::now(); let (content, signature) = serialize_transaction_and_encode(transaction, UiTransactionEncoding::Base64).await?; - println!(" 交易编码base64: {:?}", start_time.elapsed()); + println!(" Transaction encoded to base64: {:?}", start_time.elapsed()); let request_body = serde_json::to_string(&json!({ "jsonrpc": "2.0", @@ -78,34 +78,36 @@ impl ZeroSlotClient { url.push_str("/?api-key="); url.push_str(&self.auth_token); - // 4. 直接使用 `text().await?`,避免 `json().await?` 的异步 JSON 解析 + // 4. Use `text().await?` directly, avoiding async JSON parsing from `json().await?` let response_text = self.http_client.post(&url) - .body(request_body) // 直接传字符串,避免 `json()` 开销 - .header("Content-Type", "application/json") // 显式指定 JSON 头 + .body(request_body) // Pass string directly, avoiding `json()` overhead + .header("Content-Type", "application/json") // Explicitly specify JSON header .send() .await? .text() .await?; - // 5. 用 `serde_json::from_str()` 解析 JSON,减少 `.json().await?` 额外等待 + // 5. Use `serde_json::from_str()` to parse JSON, reducing extra wait from `.json().await?` if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" 0slot{}提交: {:?}", trade_type, start_time.elapsed()); + println!(" 0slot {} submitted: {:?}", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" 0slot{}提交失败: {:?}", trade_type, _error); + eprintln!(" 0slot {} submission failed: {:?}", trade_type, _error); } + } else { + eprintln!(" 0slot {} submission failed: {:?}", trade_type, response_text); } let start_time: Instant = Instant::now(); match poll_transaction_confirmation(&self.rpc_client, signature).await { Ok(_) => (), Err(e) => { - println!(" 0slot{}确认失败: {:?}", trade_type, start_time.elapsed()); + println!(" 0slot {} confirmation failed: {:?}", trade_type, start_time.elapsed()); return Err(e); }, } - println!(" 0slot{}确认: {:?}", trade_type, start_time.elapsed()); + println!(" 0slot {} confirmed: {:?}", trade_type, start_time.elapsed()); Ok(()) } diff --git a/src/trading/core/executor.rs b/src/trading/core/executor.rs index 192f398..51f5ab4 100755 --- a/src/trading/core/executor.rs +++ b/src/trading/core/executor.rs @@ -17,7 +17,7 @@ use crate::{ const MAX_LOADED_ACCOUNTS_DATA_SIZE_LIMIT: u32 = 256 * 1024; -/// 通用交易执行器实现 +/// Generic trade executor implementation pub struct GenericTradeExecutor { instruction_builder: Arc, protocol_name: &'static str, @@ -46,8 +46,8 @@ impl TradeExecutor for GenericTradeExecutor { return Err(anyhow!("RPC is not set")); } let rpc = params.rpc.as_ref().unwrap().clone(); - let mut timer = TradeTimer::new("构建买入交易指令"); - // 构建指令 + let mut timer = TradeTimer::new("Building buy transaction instructions"); + // Build instructions let instructions = self.instruction_builder.build_buy_instructions(¶ms).await?; let final_instructions = match middleware_manager.clone() { Some(middleware_manager) => middleware_manager @@ -58,9 +58,9 @@ impl TradeExecutor for GenericTradeExecutor { )?, None => instructions, }; - timer.stage("构建rpc交易指令"); + timer.stage("Building RPC transaction instructions"); - // 构建交易 + // Build transaction let transaction = build_rpc_transaction( params.payer.clone(), ¶ms.priority_fee, @@ -73,13 +73,13 @@ impl TradeExecutor for GenericTradeExecutor { true, ) .await?; - timer.stage("rpc提交确认"); + timer.stage("RPC submission confirmation"); - // 发送交易 + // Send transaction if params.wait_transaction_confirmed { rpc.send_and_confirm_transaction(&transaction).await?; } else { - // 异步发送交易 + // Send transaction asynchronously rpc.send_transaction(&transaction).await?; } timer.finish(); @@ -95,9 +95,9 @@ impl TradeExecutor for GenericTradeExecutor { if params.data_size_limit == 0 { params.data_size_limit = MAX_LOADED_ACCOUNTS_DATA_SIZE_LIMIT; } - let timer = TradeTimer::new("构建买入交易指令"); + let timer = TradeTimer::new("Building buy transaction instructions"); - // 验证参数 - 转换为BuyParams进行验证 + // Validate parameters - convert to BuyParams for validation let buy_params = BuyParams { rpc: params.rpc, payer: params.payer.clone(), @@ -112,7 +112,7 @@ impl TradeExecutor for GenericTradeExecutor { protocol_params: params.protocol_params.clone(), }; - // 构建指令 + // Build instructions let instructions = self.instruction_builder.build_buy_instructions(&buy_params).await?; let final_instructions = match middleware_manager.clone() { Some(middleware_manager) => middleware_manager @@ -126,7 +126,7 @@ impl TradeExecutor for GenericTradeExecutor { timer.finish(); - // 并行执行交易 + // Execute transactions in parallel parallel_execute_with_tips( params.swqos_clients, params.payer, @@ -155,9 +155,9 @@ impl TradeExecutor for GenericTradeExecutor { return Err(anyhow!("RPC is not set")); } let rpc = params.rpc.as_ref().unwrap().clone(); - let mut timer = TradeTimer::new("构建卖出交易指令"); + let mut timer = TradeTimer::new("Building sell transaction instructions"); - // 构建指令 + // Build instructions let instructions = self.instruction_builder.build_sell_instructions(¶ms).await?; let final_instructions = match middleware_manager.clone() { Some(middleware_manager) => middleware_manager @@ -168,9 +168,9 @@ impl TradeExecutor for GenericTradeExecutor { )?, None => instructions, }; - timer.stage("卖出交易指令"); + timer.stage("Sell transaction instructions"); - // 构建交易 + // Build transaction let transaction = build_sell_transaction( params.payer.clone(), ¶ms.priority_fee, @@ -182,9 +182,9 @@ impl TradeExecutor for GenericTradeExecutor { false, ) .await?; - timer.stage("卖出交易签名"); + timer.stage("Sell transaction signing"); - // 发送交易 + // Send transaction if params.wait_transaction_confirmed { rpc.send_and_confirm_transaction(&transaction).await?; } else { @@ -200,9 +200,9 @@ impl TradeExecutor for GenericTradeExecutor { params: SellWithTipParams, middleware_manager: Option>, ) -> Result<()> { - let timer = TradeTimer::new("构建卖出交易指令"); + let timer = TradeTimer::new("Building sell transaction instructions"); - // 转换为SellParams进行指令构建 + // Convert to SellParams for instruction building let sell_params = SellParams { rpc: params.rpc, payer: params.payer.clone(), @@ -216,7 +216,7 @@ impl TradeExecutor for GenericTradeExecutor { protocol_params: params.protocol_params.clone(), }; - // 构建指令 + // Build instructions let instructions = self.instruction_builder.build_sell_instructions(&sell_params).await?; let final_instructions = match middleware_manager.clone() { Some(middleware_manager) => middleware_manager @@ -230,7 +230,7 @@ impl TradeExecutor for GenericTradeExecutor { timer.finish(); - // 并行执行交易 + // Execute transactions in parallel parallel_execute_with_tips( params.swqos_clients, params.payer, diff --git a/src/trading/core/parallel.rs b/src/trading/core/parallel.rs index 93ed0a0..029c0b1 100755 --- a/src/trading/core/parallel.rs +++ b/src/trading/core/parallel.rs @@ -18,7 +18,7 @@ use crate::{ }, }; -/// 并行执行交易的通用函数 +/// Generic function for parallel transaction execution pub async fn parallel_execute_with_tips( swqos_clients: Vec>, payer: Arc, @@ -49,8 +49,10 @@ pub async fn parallel_execute_with_tips( let handle = tokio::spawn(async move { core_affinity::set_for_current(core_id); - let mut timer = - TradeTimer::new(format!("构建交易指令: {:?}", swqos_client.get_swqos_type())); + let mut timer = TradeTimer::new(format!( + "Building transaction instructions: {:?}", + swqos_client.get_swqos_type() + )); let transaction = if matches!(trade_type, TradeType::Sell) && swqos_client.get_swqos_type() == SwqosType::Default @@ -99,7 +101,8 @@ pub async fn parallel_execute_with_tips( } else { let tip_account = swqos_client.get_tip_account()?; let tip_account = Arc::new(Pubkey::from_str(&tip_account).map_err(|e| anyhow!(e))?); - priority_fee.buy_tip_fee = priority_fee.buy_tip_fees[i % priority_fee.buy_tip_fees.len()]; + priority_fee.buy_tip_fee = + priority_fee.buy_tip_fees[i % priority_fee.buy_tip_fees.len()]; build_tip_transaction_with_priority_fee( payer, @@ -116,7 +119,10 @@ pub async fn parallel_execute_with_tips( .await? }; - timer.stage(format!("提交交易指令: {:?}", swqos_client.get_swqos_type())); + timer.stage(format!( + "Submitting transaction instructions: {:?}", + swqos_client.get_swqos_type() + )); swqos_client.send_transaction(trade_type, &transaction).await?; @@ -126,11 +132,10 @@ pub async fn parallel_execute_with_tips( handles.push(handle); } - - // 任意一个成功即返回 + // Return as soon as any one succeeds let (tx, mut rx) = mpsc::channel(swqos_clients.len()); - // 启动监听任务 + // Start monitoring tasks for handle in handles { let tx = tx.clone(); tokio::spawn(async move { @@ -138,9 +143,9 @@ pub async fn parallel_execute_with_tips( let _ = tx.send(result).await; }); } - drop(tx); // 关闭发送端 + drop(tx); // Close the sender - // 等待第一个成功的结果 + // Wait for the first successful result let mut errors = Vec::new(); if !wait_transaction_confirmed { @@ -157,6 +162,6 @@ pub async fn parallel_execute_with_tips( } } - // 如果没有成功的,返回错误 - return Err(anyhow!("所有交易都失败了: {:?}", errors)); + // If no success, return error + return Err(anyhow!("All transactions failed: {:?}", errors)); } diff --git a/src/trading/core/timer.rs b/src/trading/core/timer.rs index 3841fe8..3a81315 100755 --- a/src/trading/core/timer.rs +++ b/src/trading/core/timer.rs @@ -1,6 +1,6 @@ use std::time::Instant; -/// 交易时间测量器 +/// Trade time measurement tool #[derive(Clone)] pub struct TradeTimer { start_time: Instant, @@ -8,31 +8,28 @@ pub struct TradeTimer { } impl TradeTimer { - /// 创建新的计时器 + /// Create a new timer pub fn new(stage: impl Into) -> Self { - Self { - start_time: Instant::now(), - stage: stage.into(), - } + Self { start_time: Instant::now(), stage: stage.into() } } - - /// 记录当前阶段耗时并开始新阶段 + + /// Record current stage time and start a new stage pub fn stage(&mut self, new_stage: impl Into) { let elapsed = self.start_time.elapsed(); - println!(" {} 耗时: {:?}", self.stage, elapsed); - + println!(" {} time cost: {:?}", self.stage, elapsed); + self.start_time = Instant::now(); self.stage = new_stage.into(); } - - /// 完成计时并输出最终耗时 + + /// Complete timing and output final time cost pub fn finish(mut self) { let elapsed = self.start_time.elapsed(); - println!(" {} 耗时: {:?}", self.stage, elapsed); - self.stage.clear(); // 清空stage,避免Drop时重复打印 + println!(" {} time cost: {:?}", self.stage, elapsed); + self.stage.clear(); // Clear stage to avoid duplicate printing in Drop } - - /// 获取当前阶段的耗时(不重置计时器) + + /// Get the elapsed time of current stage (without resetting the timer) pub fn elapsed(&self) -> std::time::Duration { self.start_time.elapsed() } @@ -42,7 +39,7 @@ impl Drop for TradeTimer { fn drop(&mut self) { if !self.stage.is_empty() { let elapsed = self.start_time.elapsed(); - println!(" {} 耗时: {:?}", self.stage, elapsed); + println!(" {} time cost: {:?}", self.stage, elapsed); } } -} \ No newline at end of file +}