From 624b1843a2ac59208fe01a34459dc0f5d60bf623 Mon Sep 17 00:00:00 2001 From: Wood Date: Tue, 17 Mar 2026 13:11:33 +0800 Subject: [PATCH] Improve SDK and SWQOS logging: alignment, errors, duration format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename wait_transaction_confirmed to wait_tx_confirmed (params, lib, docs, examples) - SDK timing: use [SDK][provider] style with fixed-width labels; add newline before block - Move print_sdk_timing_block to common::sdk_log; unify SWQOS_LABEL_WIDTH - SWQOS submitted/failed: aligned [Provider] labels via log_swqos_submitted/submission_failed - Extract short error message from JSON (message/data) or quoted string; prefix with 'error: ' - Format elapsed as 'X.XXXX ms' or 'X.XXXX µs' (4 decimals, space before unit); use comma before error - Add SwqosType::as_str() for zero-allocation log labels; only parse JSON when input starts with '{' Made-with: Cursor --- docs/TRADING_PARAMETERS.md | 6 +- docs/TRADING_PARAMETERS_CN.md | 6 +- src/common/sdk_log.rs | 149 ++++++++++++++++++++++++++++++++++ src/lib.rs | 8 +- src/swqos/astralane.rs | 33 +++++--- src/swqos/blockrazor.rs | 15 ++-- src/swqos/bloxroute.rs | 16 ++-- src/swqos/flashblock.rs | 14 ++-- src/swqos/helius.rs | 18 ++-- src/swqos/jito.rs | 12 +-- src/swqos/lightspeed.rs | 14 ++-- src/swqos/mod.rs | 22 +++++ src/swqos/nextblock.rs | 14 ++-- src/swqos/node1.rs | 14 ++-- src/swqos/soyas.rs | 22 +++-- src/swqos/speedlanding.rs | 30 +++++-- src/swqos/stellium.rs | 14 ++-- src/swqos/temporal.rs | 8 +- src/swqos/zeroslot.rs | 10 +-- src/trading/core/executor.rs | 129 ++++++++++++++--------------- src/trading/core/params.rs | 2 +- 21 files changed, 387 insertions(+), 169 deletions(-) diff --git a/docs/TRADING_PARAMETERS.md b/docs/TRADING_PARAMETERS.md index debffd8..1f0f863 100644 --- a/docs/TRADING_PARAMETERS.md +++ b/docs/TRADING_PARAMETERS.md @@ -30,7 +30,7 @@ The `TradeBuyParams` struct contains all parameters required for executing buy o | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `address_lookup_table_account` | `Option` | ❌ | Address lookup table for transaction optimization | -| `wait_transaction_confirmed` | `bool` | ✅ | Whether to wait for transaction confirmation | +| `wait_tx_confirmed` | `bool` | ✅ | Whether to wait for transaction confirmation | | `create_input_token_ata` | `bool` | ✅ | Whether to create input token Associated Token Account | | `close_input_token_ata` | `bool` | ✅ | Whether to close input token ATA after transaction | | `create_mint_ata` | `bool` | ✅ | Whether to create token mint ATA | @@ -62,7 +62,7 @@ The `TradeSellParams` struct contains all parameters required for executing sell | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `address_lookup_table_account` | `Option` | ❌ | Address lookup table for transaction optimization | -| `wait_transaction_confirmed` | `bool` | ✅ | Whether to wait for transaction confirmation | +| `wait_tx_confirmed` | `bool` | ✅ | Whether to wait for transaction confirmation | | `create_output_token_ata` | `bool` | ✅ | Whether to create output token Associated Token Account | | `close_output_token_ata` | `bool` | ✅ | Whether to close output token ATA after transaction | | `durable_nonce` | `Option` | ❌ | Durable nonce information containing nonce account and current nonce value | @@ -88,7 +88,7 @@ These parameters are essential for defining the basic trading operation: These parameters control how the transaction is processed: - **slippage_basis_points**: Controls acceptable price slippage -- **wait_transaction_confirmed**: Controls whether to wait for confirmation +- **wait_tx_confirmed**: Controls whether to wait for confirmation ### 🔧 Account Management Parameters diff --git a/docs/TRADING_PARAMETERS_CN.md b/docs/TRADING_PARAMETERS_CN.md index e71e58b..f87d126 100644 --- a/docs/TRADING_PARAMETERS_CN.md +++ b/docs/TRADING_PARAMETERS_CN.md @@ -30,7 +30,7 @@ | 参数 | 类型 | 必需 | 描述 | |------|------|------|------| | `address_lookup_table_account` | `Option` | ❌ | 用于交易优化的地址查找表 | -| `wait_transaction_confirmed` | `bool` | ✅ | 是否等待交易确认 | +| `wait_tx_confirmed` | `bool` | ✅ | 是否等待交易确认 | | `create_input_token_ata` | `bool` | ✅ | 是否创建输入代币关联代币账户 | | `close_input_token_ata` | `bool` | ✅ | 交易后是否关闭输入代币 ATA | | `create_mint_ata` | `bool` | ✅ | 是否创建代币 mint ATA | @@ -62,7 +62,7 @@ | 参数 | 类型 | 必需 | 描述 | |------|------|------|------| | `address_lookup_table_account` | `Option` | ❌ | 用于交易优化的地址查找表 | -| `wait_transaction_confirmed` | `bool` | ✅ | 是否等待交易确认 | +| `wait_tx_confirmed` | `bool` | ✅ | 是否等待交易确认 | | `create_output_token_ata` | `bool` | ✅ | 是否创建输出代币关联代币账户 | | `close_output_token_ata` | `bool` | ✅ | 交易后是否关闭输出代币 ATA | | `durable_nonce` | `Option` | ❌ | 持久 nonce 信息,包含 nonce 账户和当前 nonce 值 | @@ -88,7 +88,7 @@ 这些参数控制交易的处理方式: - **slippage_basis_points**: 控制可接受的价格滑点 -- **wait_transaction_confirmed**: 控制是否等待确认 +- **wait_tx_confirmed**: 控制是否等待确认 ### 🔧 账户管理参数 diff --git a/src/common/sdk_log.rs b/src/common/sdk_log.rs index 96d4a7b..5dab5ae 100644 --- a/src/common/sdk_log.rs +++ b/src/common/sdk_log.rs @@ -3,10 +3,59 @@ //! Controlled by `TradeConfig::log_enabled`, set in `TradingClient::new`. //! All SDK logs (timing, SWQOS submit/confirm, WSOL, blacklist, etc.) should check this before output. +use std::fmt; use std::sync::atomic::{AtomicBool, Ordering}; +use std::time::Duration; + +/// Format duration for log: "97.9396 ms" or "13.936 µs", 4 decimal places, space before unit. +fn format_elapsed(d: Duration) -> String { + let secs = d.as_secs_f64(); + if secs < 0.001 { + format!("{:.4} µs", secs * 1_000_000.0) + } else { + format!("{:.4} ms", secs * 1000.0) + } +} + +/// Extract a short error message for SWQOS submission failed log. +/// Tries JSON "message"/"data" and quoted string; on any parse failure returns original (no panic). +fn extract_swqos_error_message(s: &str) -> String { + let s = s.trim(); + if s.is_empty() { + return String::new(); + } + // Plain double-quoted string (no inner JSON): unquote + if s.starts_with('"') && s.ends_with('"') && s.len() >= 2 { + let inner = &s[1..s.len() - 1]; + if !inner.contains('{') { + return inner.replace("\\\"", "\""); + } + } + // Try parse as JSON only when input looks like JSON (avoid parsing long non-JSON strings) + if s.starts_with('{') { + if let Ok(v) = serde_json::from_str::(s) { + let obj = v + .get("error") + .and_then(|e| e.as_object()) + .or_else(|| v.as_object()); + if let Some(o) = obj { + if let Some(m) = o.get("message").and_then(|x| x.as_str()) { + return m.to_string(); + } + if let Some(d) = o.get("data").and_then(|x| x.as_str()) { + return d.to_string(); + } + } + } + } + s.to_string() +} static SDK_LOG_ENABLED: AtomicBool = AtomicBool::new(true); +/// Width of [provider] label so SWQOS submit/confirm lines align (longest: Speedlanding). +pub const SWQOS_LABEL_WIDTH: usize = 12; + /// Whether SDK logging is enabled (set from TradeConfig.log_enabled in TradingClient::new). #[inline(always)] pub fn sdk_log_enabled() -> bool { @@ -17,3 +66,103 @@ pub fn sdk_log_enabled() -> bool { pub fn set_sdk_log_enabled(enabled: bool) { SDK_LOG_ENABLED.store(enabled, Ordering::Relaxed); } + +/// Aligned log: ` [Soyas ] Buy submitted: 13.936 µs`. Call only when sdk_log_enabled(). +#[inline] +pub fn log_swqos_submitted( + provider: &str, + trade_type: impl fmt::Display, + elapsed: Duration, +) { + println!( + " [{:width$}] {} submitted: {}", + provider, + trade_type, + format_elapsed(elapsed), + width = SWQOS_LABEL_WIDTH + ); +} + +/// Prints one SDK timing block (build_instructions, before_submit, per-channel submit_done). +/// When confirm_us is Some, prints confirmed + total; when None, prints "confirmed: -, total: submit_ms". +/// Call only when sdk_log_enabled(). +pub fn print_sdk_timing_block( + dir: &str, + start_us: Option, + build_end_us: Option, + before_submit_us: Option, + submit_timings: &[(crate::swqos::SwqosType, i64)], + confirm_us: Option, +) { + println!(); + let start_us = match start_us { + Some(u) => u, + None => return, + }; + if let Some(end_us) = build_end_us { + println!( + " [SDK][{:width$}] {} build_instructions: {:.4} ms", + "-", + dir, + (end_us - start_us) as f64 / 1000.0, + width = SWQOS_LABEL_WIDTH + ); + } + if let Some(end_us) = before_submit_us { + println!( + " [SDK][{:width$}] {} before_submit: {:.4} ms", + "-", + dir, + (end_us - start_us) as f64 / 1000.0, + width = SWQOS_LABEL_WIDTH + ); + } + if let Some(confirm_done_us) = confirm_us { + let total_ms = (confirm_done_us - start_us) as f64 / 1000.0; + for (swqos_type, submit_done_us) in submit_timings { + let submit_ms = (*submit_done_us - start_us).max(0) as f64 / 1000.0; + let confirmed_ms = (confirm_done_us - *submit_done_us).max(0) as f64 / 1000.0; + println!( + " [SDK][{:width$}] {} submit_done: {:.4} ms, confirmed: {:.4} ms, total: {:.4} ms", + swqos_type.as_str(), + dir, + submit_ms, + confirmed_ms, + total_ms, + width = SWQOS_LABEL_WIDTH + ); + } + } else { + for (swqos_type, submit_done_us) in submit_timings { + let submit_ms = (*submit_done_us - start_us).max(0) as f64 / 1000.0; + println!( + " [SDK][{:width$}] {} submit_done: {:.4} ms, confirmed: -, total: {:.4} ms", + swqos_type.as_str(), + dir, + submit_ms, + submit_ms, + width = SWQOS_LABEL_WIDTH + ); + } + } +} + +/// Aligned log: ` [Stellium ] Buy submission failed after 97.9396 ms: ...`. Call only when sdk_log_enabled(). +/// Error is normalized: JSON "message"/"data" or quoted string is shown; raw JSON is not. +#[inline] +pub fn log_swqos_submission_failed( + provider: &str, + trade_type: impl fmt::Display, + elapsed: Duration, + err: impl fmt::Display, +) { + let msg = extract_swqos_error_message(&format!("{}", err)); + eprintln!( + " [{:width$}] {} submission failed after {}, error: {}", + provider, + trade_type, + format_elapsed(elapsed), + msg, + width = SWQOS_LABEL_WIDTH + ); +} diff --git a/src/lib.rs b/src/lib.rs index c3ca99a..f51f5a6 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -277,7 +277,7 @@ pub struct TradeBuyParams { /// Optional address lookup table for transaction size optimization pub address_lookup_table_account: Option, /// Whether to wait for transaction confirmation before returning - pub wait_transaction_confirmed: bool, + pub wait_tx_confirmed: bool, /// Whether to create input token associated token account pub create_input_token_ata: bool, /// Whether to close input token associated token account after trade @@ -328,7 +328,7 @@ pub struct TradeSellParams { /// Optional address lookup table for transaction size optimization pub address_lookup_table_account: Option, /// Whether to wait for transaction confirmation before returning - pub wait_transaction_confirmed: bool, + pub wait_tx_confirmed: bool, /// Whether to create output token associated token account pub create_output_token_ata: bool, /// Whether to close output token associated token account after trade @@ -760,7 +760,7 @@ impl TradingClient { slippage_basis_points: params.slippage_basis_points, address_lookup_table_account: params.address_lookup_table_account, recent_blockhash: params.recent_blockhash, - wait_transaction_confirmed: params.wait_transaction_confirmed, + wait_tx_confirmed: params.wait_tx_confirmed, protocol_params, open_seed_optimize: self.use_seed_optimize, // 使用全局seed优化配置 swqos_clients: self.infrastructure.swqos_clients.clone(), @@ -867,7 +867,7 @@ impl TradingClient { slippage_basis_points: params.slippage_basis_points, address_lookup_table_account: params.address_lookup_table_account, recent_blockhash: params.recent_blockhash, - wait_transaction_confirmed: params.wait_transaction_confirmed, + wait_tx_confirmed: params.wait_tx_confirmed, protocol_params, with_tip: params.with_tip, open_seed_optimize: self.use_seed_optimize, // 使用全局seed优化配置 diff --git a/src/swqos/astralane.rs b/src/swqos/astralane.rs index b0032b5..18afb9a 100644 --- a/src/swqos/astralane.rs +++ b/src/swqos/astralane.rs @@ -2,7 +2,7 @@ use crate::swqos::common::{default_http_client_builder, poll_transaction_confirm use rand::seq::IndexedRandom; use reqwest::Client; use std::{sync::Arc, time::Instant}; -use tracing::{error, info, warn}; +use tracing::warn; use crate::swqos::SwqosClientTrait; use crate::swqos::{SwqosType, TradeType}; @@ -193,15 +193,26 @@ impl AstralaneClient { let status = response.status(); let _ = response.bytes().await; if status.is_success() { - info!(target: "sol_trade_sdk", "[astralane] {} submitted: {:?}", trade_type, start_time.elapsed()); + if crate::common::sdk_log::sdk_log_enabled() { + crate::common::sdk_log::log_swqos_submitted("Astralane", trade_type, start_time.elapsed()); + } } else { - error!(target: "sol_trade_sdk", "[astralane] {} submission failed: status {}", trade_type, status); + if crate::common::sdk_log::sdk_log_enabled() { + crate::common::sdk_log::log_swqos_submission_failed("Astralane", trade_type, start_time.elapsed(), format!("status {}", status)); + } return Err(anyhow::anyhow!("Astralane sendTransaction failed: {}", status)); } } AstralaneBackend::Quic(quic) => { - quic.send_transaction(&body_bytes).await?; - info!(target: "sol_trade_sdk", "[astralane-quic] {} submitted: {:?}", trade_type, start_time.elapsed()); + if let Err(e) = quic.send_transaction(&body_bytes).await { + if crate::common::sdk_log::sdk_log_enabled() { + crate::common::sdk_log::log_swqos_submission_failed("Astralane", trade_type, start_time.elapsed(), &e); + } + return Err(e); + } + if crate::common::sdk_log::sdk_log_enabled() { + crate::common::sdk_log::log_swqos_submitted("Astralane", trade_type, start_time.elapsed()); + } } } @@ -209,14 +220,16 @@ impl AstralaneClient { match poll_transaction_confirmation(&self.rpc_client, *signature, wait_confirmation).await { Ok(_) => (), Err(e) => { - info!(target: "sol_trade_sdk", "signature: {:?}", signature); - error!(target: "sol_trade_sdk", "[astralane] {} confirmation failed: {:?}", trade_type, start_time.elapsed()); + if crate::common::sdk_log::sdk_log_enabled() { + println!(" signature: {:?}", signature); + println!(" [{:width$}] {} confirmation failed: {:?}", "Astralane", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); + } return Err(e); } } - if wait_confirmation { - info!(target: "sol_trade_sdk", "signature: {:?}", signature); - info!(target: "sol_trade_sdk", "[astralane] {} confirmed: {:?}", trade_type, start_time.elapsed()); + if wait_confirmation && crate::common::sdk_log::sdk_log_enabled() { + println!(" signature: {:?}", signature); + println!(" [{:width$}] {} confirmed: {:?}", "Astralane", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) } diff --git a/src/swqos/blockrazor.rs b/src/swqos/blockrazor.rs index ec66b5c..57d6bb0 100644 --- a/src/swqos/blockrazor.rs +++ b/src/swqos/blockrazor.rs @@ -172,15 +172,12 @@ impl BlockRazorClient { if status.is_success() { let _ = response.bytes().await; if crate::common::sdk_log::sdk_log_enabled() { - println!(" [blockrazor] {} submitted: {:?}", trade_type, start_time.elapsed()); + crate::common::sdk_log::log_swqos_submitted("blockrazor", trade_type, start_time.elapsed()); } } else { let body = response.text().await.unwrap_or_default(); if crate::common::sdk_log::sdk_log_enabled() { - eprintln!( - " [blockrazor] {} submission failed: status {} body: {}", - trade_type, status, body - ); + crate::common::sdk_log::log_swqos_submission_failed("blockrazor", trade_type, start_time.elapsed(), format!("status {} body: {}", status, body)); } return Err(anyhow::anyhow!( "BlockRazor sendTransaction failed: status {} body: {}", @@ -196,9 +193,11 @@ impl BlockRazorClient { if crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); println!( - " [blockrazor] {} confirmation failed: {:?}", + " [{:width$}] {} confirmation failed: {:?}", + "blockrazor", trade_type, - start_time.elapsed() + start_time.elapsed(), + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); } return Err(e); @@ -206,7 +205,7 @@ impl BlockRazorClient { } if wait_confirmation && crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); - println!(" [blockrazor] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "blockrazor", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) diff --git a/src/swqos/bloxroute.rs b/src/swqos/bloxroute.rs index 1d4ee9c..44ffa38 100755 --- a/src/swqos/bloxroute.rs +++ b/src/swqos/bloxroute.rs @@ -100,13 +100,13 @@ impl BloxrouteClient { if let Ok(response_json) = serde_json::from_str::(&response_text) { if crate::common::sdk_log::sdk_log_enabled() { if response_json.get("result").is_some() { - println!(" [bloxroute] {} submitted: {:?}", trade_type, start_time.elapsed()); + crate::common::sdk_log::log_swqos_submitted("bloxroute", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" [bloxroute] {} submission failed: {:?}", trade_type, _error); + eprintln!(" [bloxroute] {} submission failed after {:?}: {:?}", trade_type, start_time.elapsed(), _error); } } } else if crate::common::sdk_log::sdk_log_enabled() { - eprintln!(" [bloxroute] {} submission failed: {:?}", trade_type, response_text); + crate::common::sdk_log::log_swqos_submission_failed("bloxroute", trade_type, start_time.elapsed(), response_text); } let start_time: Instant = Instant::now(); @@ -116,9 +116,11 @@ impl BloxrouteClient { if crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); println!( - " [bloxroute] {} confirmation failed: {:?}", + " [{:width$}] {} confirmation failed: {:?}", + "bloxroute", trade_type, - start_time.elapsed() + start_time.elapsed(), + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); } return Err(e); @@ -126,7 +128,7 @@ impl BloxrouteClient { } if wait_confirmation && crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); - println!(" [bloxroute] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "bloxroute", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) @@ -168,7 +170,7 @@ impl BloxrouteClient { if response_json.get("result").is_some() { println!(" bloxroute {} submitted: {:?}", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" bloxroute {} submission failed: {:?}", trade_type, _error); + eprintln!(" bloxroute {} submission failed after {:?}: {:?}", trade_type, start_time.elapsed(), _error); } } } diff --git a/src/swqos/flashblock.rs b/src/swqos/flashblock.rs index 6ea977c..ecd287c 100644 --- a/src/swqos/flashblock.rs +++ b/src/swqos/flashblock.rs @@ -97,12 +97,12 @@ impl FlashBlockClient { // 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] {} submitted: {:?}", trade_type, start_time.elapsed()); + crate::common::sdk_log::log_swqos_submitted("FlashBlock", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" [FlashBlock] {} submission failed: {:?}", trade_type, _error); + eprintln!(" [FlashBlock] {} submission failed after {:?}: {:?}", trade_type, start_time.elapsed(), _error); } } else { - eprintln!(" [FlashBlock] {} submission failed: {:?}", trade_type, response_text); + crate::common::sdk_log::log_swqos_submission_failed("FlashBlock", trade_type, start_time.elapsed(), response_text); } let start_time: Instant = Instant::now(); @@ -111,16 +111,18 @@ impl FlashBlockClient { Err(e) => { println!(" signature: {:?}", signature); println!( - " [FlashBlock] {} confirmation failed: {:?}", + " [{:width$}] {} confirmation failed: {:?}", + "FlashBlock", trade_type, - start_time.elapsed() + start_time.elapsed(), + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); return Err(e); } } if wait_confirmation { println!(" signature: {:?}", signature); - println!(" [FlashBlock] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "FlashBlock", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) diff --git a/src/swqos/helius.rs b/src/swqos/helius.rs index 432c0a2..d996691 100644 --- a/src/swqos/helius.rs +++ b/src/swqos/helius.rs @@ -106,8 +106,8 @@ impl HeliusClient { if !status.is_success() { if crate::common::sdk_log::sdk_log_enabled() { eprintln!( - " [helius] {} submission failed status={} body={}", - trade_type, status, response_text + " [helius] {} submission failed after {:?} status={} body={}", + trade_type, start_time.elapsed(), status, response_text ); } return Err(anyhow::anyhow!( @@ -124,15 +124,15 @@ impl HeliusClient { .and_then(|v| v.as_str()) .unwrap_or("unknown"); if crate::common::sdk_log::sdk_log_enabled() { - eprintln!(" [helius] {} submission error: {}", trade_type, err_msg); + crate::common::sdk_log::log_swqos_submission_failed("helius", trade_type, start_time.elapsed(), err_msg); } return Err(anyhow::anyhow!("Helius Sender error: {}", err_msg)); } if response_json.get("result").is_some() && crate::common::sdk_log::sdk_log_enabled() { - println!(" [helius] {} submitted: {:?}", trade_type, start_time.elapsed()); + crate::common::sdk_log::log_swqos_submitted("helius", trade_type, start_time.elapsed()); } } else if crate::common::sdk_log::sdk_log_enabled() { - eprintln!(" [helius] {} submission failed: {:?}", trade_type, response_text); + crate::common::sdk_log::log_swqos_submission_failed("helius", trade_type, start_time.elapsed(), response_text); } match poll_transaction_confirmation(&self.rpc_client, signature, wait_confirmation).await { @@ -140,9 +140,11 @@ impl HeliusClient { Err(e) => { if crate::common::sdk_log::sdk_log_enabled() { eprintln!( - " [helius] {} confirmation failed: {:?}", + " [{:width$}] {} confirmation failed: {:?}", + "helius", trade_type, - start_time.elapsed() + start_time.elapsed(), + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); } return Err(e); @@ -150,7 +152,7 @@ impl HeliusClient { } if wait_confirmation && crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); - println!(" [helius] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "helius", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) } diff --git a/src/swqos/jito.rs b/src/swqos/jito.rs index 904882e..01102c3 100755 --- a/src/swqos/jito.rs +++ b/src/swqos/jito.rs @@ -105,12 +105,12 @@ impl JitoClient { if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" [jito] {} submitted: {:?}", trade_type, start_time.elapsed()); + crate::common::sdk_log::log_swqos_submitted("jito", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" [jito] {} submission failed: {:?}", trade_type, _error); + eprintln!(" [jito] {} submission failed after {:?}: {:?}", trade_type, start_time.elapsed(), _error); } } else { - eprintln!(" [jito] {} submission failed: {:?}", trade_type, response_text); + crate::common::sdk_log::log_swqos_submission_failed("jito", trade_type, start_time.elapsed(), response_text); } let start_time: Instant = Instant::now(); @@ -118,13 +118,13 @@ impl JitoClient { Ok(_) => (), Err(e) => { println!(" signature: {:?}", signature); - println!(" [jito] {} confirmation failed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmation failed: {:?}", "jito", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); return Err(e); } } if wait_confirmation { println!(" signature: {:?}", signature); - println!(" [jito] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "jito", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) @@ -171,7 +171,7 @@ impl JitoClient { if response_json.get("result").is_some() { println!(" jito {} submitted: {:?}", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" jito {} submission failed: {:?}", trade_type, _error); + eprintln!(" jito {} submission failed after {:?}: {:?}", trade_type, start_time.elapsed(), _error); } } diff --git a/src/swqos/lightspeed.rs b/src/swqos/lightspeed.rs index 29ff631..44ca1fd 100644 --- a/src/swqos/lightspeed.rs +++ b/src/swqos/lightspeed.rs @@ -103,12 +103,12 @@ impl LightspeedClient { if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" [lightspeed] {} submitted: {:?}", trade_type, start_time.elapsed()); + crate::common::sdk_log::log_swqos_submitted("lightspeed", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" [lightspeed] {} submission failed: {:?}", trade_type, _error); + crate::common::sdk_log::log_swqos_submission_failed("lightspeed", trade_type, start_time.elapsed(), _error); } } else { - eprintln!(" [lightspeed] {} submission failed: {:?}", trade_type, response_text); + crate::common::sdk_log::log_swqos_submission_failed("lightspeed", trade_type, start_time.elapsed(), response_text); } let start_time: Instant = Instant::now(); @@ -117,16 +117,18 @@ impl LightspeedClient { Err(e) => { println!(" signature: {:?}", signature); println!( - " [lightspeed] {} confirmation failed: {:?}", + " [{:width$}] {} confirmation failed: {:?}", + "lightspeed", trade_type, - start_time.elapsed() + start_time.elapsed(), + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); return Err(e); } } if wait_confirmation { println!(" signature: {:?}", signature); - println!(" [lightspeed] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "lightspeed", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) diff --git a/src/swqos/mod.rs b/src/swqos/mod.rs index bfb6b9f..e82ece9 100755 --- a/src/swqos/mod.rs +++ b/src/swqos/mod.rs @@ -111,6 +111,28 @@ pub enum SwqosType { } impl SwqosType { + /// Label for log alignment; same as Debug output (e.g. "Soyas", "Speedlanding"). + #[inline] + pub fn as_str(self) -> &'static str { + match self { + Self::Jito => "Jito", + Self::NextBlock => "NextBlock", + Self::ZeroSlot => "ZeroSlot", + Self::Temporal => "Temporal", + Self::Bloxroute => "Bloxroute", + Self::Node1 => "Node1", + Self::FlashBlock => "FlashBlock", + Self::BlockRazor => "BlockRazor", + Self::Astralane => "Astralane", + Self::Stellium => "Stellium", + Self::Lightspeed => "Lightspeed", + Self::Soyas => "Soyas", + Self::Speedlanding => "Speedlanding", + Self::Helius => "Helius", + Self::Default => "Default", + } + } + pub fn values() -> Vec { vec![ Self::Jito, diff --git a/src/swqos/nextblock.rs b/src/swqos/nextblock.rs index 1512d27..b99087a 100755 --- a/src/swqos/nextblock.rs +++ b/src/swqos/nextblock.rs @@ -99,12 +99,12 @@ impl NextBlockClient { if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" [nextblock] {} submitted: {:?}", trade_type, start_time.elapsed()); + crate::common::sdk_log::log_swqos_submitted("nextblock", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" [nextblock] {} submission failed: {:?}", trade_type, _error); + crate::common::sdk_log::log_swqos_submission_failed("nextblock", trade_type, start_time.elapsed(), _error); } } else { - eprintln!(" [nextblock] {} submission failed: {:?}", trade_type, response_text); + crate::common::sdk_log::log_swqos_submission_failed("nextblock", trade_type, start_time.elapsed(), response_text); } let start_time: Instant = Instant::now(); @@ -113,16 +113,18 @@ impl NextBlockClient { Err(e) => { println!(" signature: {:?}", signature); println!( - " [nextblock] {} confirmation failed: {:?}", + " [{:width$}] {} confirmation failed: {:?}", + "nextblock", trade_type, - start_time.elapsed() + start_time.elapsed(), + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); return Err(e); } } if wait_confirmation { println!(" signature: {:?}", signature); - println!(" [nextblock] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "nextblock", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) diff --git a/src/swqos/node1.rs b/src/swqos/node1.rs index 967d14f..df2f9e7 100644 --- a/src/swqos/node1.rs +++ b/src/swqos/node1.rs @@ -184,13 +184,13 @@ impl Node1Client { if let Ok(response_json) = serde_json::from_str::(&response_text) { if crate::common::sdk_log::sdk_log_enabled() { if response_json.get("result").is_some() { - println!(" [node1] {} submitted: {:?}", trade_type, start_time.elapsed()); + crate::common::sdk_log::log_swqos_submitted("node1", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" [node1] {} submission failed: {:?}", trade_type, _error); + eprintln!(" [node1] {} submission failed after {:?}: {:?}", trade_type, start_time.elapsed(), _error); } } } else if crate::common::sdk_log::sdk_log_enabled() { - eprintln!(" [node1] {} submission failed: {:?}", trade_type, response_text); + crate::common::sdk_log::log_swqos_submission_failed("node1", trade_type, start_time.elapsed(), response_text); } let start_time: Instant = Instant::now(); @@ -200,9 +200,11 @@ impl Node1Client { if crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); println!( - " [node1] {} confirmation failed: {:?}", + " [{:width$}] {} confirmation failed: {:?}", + "node1", trade_type, - start_time.elapsed() + start_time.elapsed(), + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); } return Err(e); @@ -210,7 +212,7 @@ impl Node1Client { } if wait_confirmation && crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); - println!(" [node1] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "node1", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) diff --git a/src/swqos/soyas.rs b/src/swqos/soyas.rs index e1658e2..10b8e48 100644 --- a/src/swqos/soyas.rs +++ b/src/swqos/soyas.rs @@ -109,25 +109,35 @@ impl SwqosClientTrait for SoyasClient { let serialized_tx = bincode::serialize(transaction)?; let connection = self.connection.load_full(); if Self::try_send_bytes(&connection, &serialized_tx).await.is_err() { - eprintln!(" [soyas] {} submission failed, reconnecting", trade_type); + if crate::common::sdk_log::sdk_log_enabled() { + crate::common::sdk_log::log_swqos_submission_failed("Soyas", trade_type, start_time.elapsed(), "reconnecting"); + } self.reconnect().await?; let connection = self.connection.load_full(); if let Err(e) = Self::try_send_bytes(&connection, &serialized_tx).await { - eprintln!(" [soyas] {} submission failed: {:?}", trade_type, e); + if crate::common::sdk_log::sdk_log_enabled() { + crate::common::sdk_log::log_swqos_submission_failed("Soyas", trade_type, start_time.elapsed(), &e); + } return Err(e.into()); } } + if crate::common::sdk_log::sdk_log_enabled() { + crate::common::sdk_log::log_swqos_submitted("Soyas", trade_type, start_time.elapsed()); + } + let start_time = Instant::now(); match poll_transaction_confirmation(&self.rpc_client, *signature, wait_confirmation).await { Ok(_) => (), Err(e) => { - println!(" signature: {:?}", signature); - println!(" [soyas] {} confirmation failed: {:?}", trade_type, start_time.elapsed()); + if crate::common::sdk_log::sdk_log_enabled() { + println!(" signature: {:?}", signature); + println!(" [{:width$}] {} confirmation failed: {:?}", "Soyas", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); + } return Err(e); } } - if wait_confirmation { + if wait_confirmation && crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); - println!(" [soyas] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "Soyas", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) } diff --git a/src/swqos/speedlanding.rs b/src/swqos/speedlanding.rs index 660ca8f..c725624 100644 --- a/src/swqos/speedlanding.rs +++ b/src/swqos/speedlanding.rs @@ -161,22 +161,42 @@ impl SwqosClientTrait for SpeedlandingClient { }; if need_retry { if crate::common::sdk_log::sdk_log_enabled() { - eprintln!(" [speedlanding] {} send failed or timeout, reconnecting", trade_type); + eprintln!(" [Speedlanding] {} submission failed after {:?}, reconnecting", trade_type, start_time.elapsed()); } let connection = self.ensure_connected().await?; send_result = timeout(SEND_TIMEOUT, Self::try_send_bytes(&connection, &*buf_guard)).await; } - send_result.context("Speedlanding QUIC send timeout")??; + match send_result.context("Speedlanding QUIC send timeout") { + Ok(Ok(())) => { + if crate::common::sdk_log::sdk_log_enabled() { + crate::common::sdk_log::log_swqos_submitted("Speedlanding", trade_type, start_time.elapsed()); + } + } + Ok(Err(e)) => { + if crate::common::sdk_log::sdk_log_enabled() { + crate::common::sdk_log::log_swqos_submission_failed("Speedlanding", trade_type, start_time.elapsed(), &e); + } + return Err(e.into()); + } + Err(e) => { + if crate::common::sdk_log::sdk_log_enabled() { + crate::common::sdk_log::log_swqos_submission_failed("Speedlanding", trade_type, start_time.elapsed(), "timeout"); + } + return Err(e.into()); + } + } match poll_transaction_confirmation(&self.rpc_client, signature, wait_confirmation).await { Ok(_) => (), Err(e) => { if crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); println!( - " [speedlanding] {} confirmation failed: {:?}", + " [{:width$}] {} confirmation failed: {:?}", + "Speedlanding", trade_type, - start_time.elapsed() + start_time.elapsed(), + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); } return Err(e); @@ -184,7 +204,7 @@ impl SwqosClientTrait for SpeedlandingClient { } if wait_confirmation && crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); - println!(" [speedlanding] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "Speedlanding", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) } diff --git a/src/swqos/stellium.rs b/src/swqos/stellium.rs index 088c827..dca654a 100644 --- a/src/swqos/stellium.rs +++ b/src/swqos/stellium.rs @@ -168,13 +168,13 @@ impl StelliumClient { if let Ok(response_json) = serde_json::from_str::(&response_text) { if crate::common::sdk_log::sdk_log_enabled() { if response_json.get("result").is_some() { - println!(" [Stellium] {} submitted: {:?}", trade_type, start_time.elapsed()); + crate::common::sdk_log::log_swqos_submitted("Stellium", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" [Stellium] {} submission failed: {:?}", trade_type, _error); + crate::common::sdk_log::log_swqos_submission_failed("Stellium", trade_type, start_time.elapsed(), _error); } } } else if crate::common::sdk_log::sdk_log_enabled() { - eprintln!(" [Stellium] {} submission failed: {:?}", trade_type, response_text); + crate::common::sdk_log::log_swqos_submission_failed("Stellium", trade_type, start_time.elapsed(), response_text); } let start_time: Instant = Instant::now(); @@ -184,9 +184,11 @@ impl StelliumClient { if crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); println!( - " [Stellium] {} confirmation failed: {:?}", + " [{:width$}] {} confirmation failed: {:?}", + "Stellium", trade_type, - start_time.elapsed() + start_time.elapsed(), + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); } return Err(e); @@ -194,7 +196,7 @@ impl StelliumClient { } if wait_confirmation && crate::common::sdk_log::sdk_log_enabled() { println!(" signature: {:?}", signature); - println!(" [Stellium] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "Stellium", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) diff --git a/src/swqos/temporal.rs b/src/swqos/temporal.rs index aeb9904..ad061bf 100755 --- a/src/swqos/temporal.rs +++ b/src/swqos/temporal.rs @@ -209,12 +209,12 @@ impl TemporalClient { if let Ok(response_json) = serde_json::from_str::(&response_text) { if response_json.get("result").is_some() { - println!(" [nozomi] {} submitted: {:?}", trade_type, start_time.elapsed()); + crate::common::sdk_log::log_swqos_submitted("nozomi", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - // eprintln!("nozomi transaction submission failed: {:?}", _error); + crate::common::sdk_log::log_swqos_submission_failed("nozomi", trade_type, start_time.elapsed(), _error); } } else { - eprintln!(" [nozomi] {} submission failed: {:?}", trade_type, response_text); + crate::common::sdk_log::log_swqos_submission_failed("nozomi", trade_type, start_time.elapsed(), response_text); } let start_time: Instant = Instant::now(); @@ -232,7 +232,7 @@ impl TemporalClient { } if wait_confirmation { println!(" signature: {:?}", signature); - println!(" [nozomi] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "nozomi", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) diff --git a/src/swqos/zeroslot.rs b/src/swqos/zeroslot.rs index 3039741..42dc306 100755 --- a/src/swqos/zeroslot.rs +++ b/src/swqos/zeroslot.rs @@ -102,12 +102,12 @@ impl ZeroSlotClient { // 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] {} submitted: {:?}", trade_type, start_time.elapsed()); + crate::common::sdk_log::log_swqos_submitted("0slot", trade_type, start_time.elapsed()); } else if let Some(_error) = response_json.get("error") { - eprintln!(" [0slot] {} submission failed: {:?}", trade_type, _error); + eprintln!(" [0slot] {} submission failed after {:?}: {:?}", trade_type, start_time.elapsed(), _error); } } else { - eprintln!(" [0slot] {} submission failed: {:?}", trade_type, response_text); + crate::common::sdk_log::log_swqos_submission_failed("0slot", trade_type, start_time.elapsed(), response_text); } let start_time: Instant = Instant::now(); @@ -115,13 +115,13 @@ impl ZeroSlotClient { Ok(_) => (), Err(e) => { println!(" signature: {:?}", signature); - println!(" [0slot] {} confirmation failed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmation failed: {:?}", "0slot", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); return Err(e); } } if wait_confirmation { println!(" signature: {:?}", signature); - println!(" [0slot] {} confirmed: {:?}", trade_type, start_time.elapsed()); + println!(" [{:width$}] {} confirmed: {:?}", "0slot", trade_type, start_time.elapsed(), width = crate::common::sdk_log::SWQOS_LABEL_WIDTH); } Ok(()) diff --git a/src/trading/core/executor.rs b/src/trading/core/executor.rs index 3864617..724706a 100755 --- a/src/trading/core/executor.rs +++ b/src/trading/core/executor.rs @@ -118,32 +118,45 @@ impl TradeExecutor for GenericTradeExecutor { if crate::common::sdk_log::sdk_log_enabled() { let dir = if is_buy { "Buy" } else { "Sell" }; + println!(); if let (Some(start_us), Some(end_us)) = (timing_start_us, build_end_us) { println!( - " [SDK] {} build_instructions: {:.4} ms", + " [SDK][{:width$}] {} build_instructions: {:.4} ms", + "-", dir, - (end_us - start_us) as f64 / 1000.0 + (end_us - start_us) as f64 / 1000.0, + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); } if let (Some(start_us), Some(end_us)) = (timing_start_us, before_submit_us) { println!( - " [SDK] {} before_submit: {:.4} ms", + " [SDK][{:width$}] {} before_submit: {:.4} ms", + "-", dir, - (end_us - start_us) as f64 / 1000.0 + (end_us - start_us) as f64 / 1000.0, + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); } println!( - " [SDK] {} simulate (dry-run): {:.4} ms", + " [SDK][{:width$}] {} simulate (dry-run): {:.4} ms", + "-", dir, - send_elapsed.as_secs_f64() * 1000.0 + send_elapsed.as_secs_f64() * 1000.0, + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH + ); + println!( + " [SDK][{:width$}] {} total: {:.4} ms", + "-", + dir, + total_elapsed.as_secs_f64() * 1000.0, + width = crate::common::sdk_log::SWQOS_LABEL_WIDTH ); - println!(" [SDK] {} total: {:.4} ms", dir, total_elapsed.as_secs_f64() * 1000.0); } return result; } - let need_confirm = params.wait_transaction_confirmed; + let need_confirm = params.wait_tx_confirmed; let sender_config = params.sender_concurrency_config(); let result = execute_parallel( params.swqos_clients.as_slice(), @@ -185,32 +198,14 @@ impl TradeExecutor for GenericTradeExecutor { let confirm_done_us = log_enabled.then(crate::common::clock::now_micros); if log_enabled { let dir = if is_buy { "Buy" } else { "Sell" }; - if let Some(start_us) = timing_start_us { - if let Some(end_us) = build_end_us { - println!( - " [SDK] {} build_instructions: {:.4} ms", - dir, - (end_us - start_us) as f64 / 1000.0 - ); - } - if let Some(end_us) = before_submit_us { - println!( - " [SDK] {} before_submit: {:.4} ms", - dir, - (end_us - start_us) as f64 / 1000.0 - ); - } - if let Some(confirm_us) = confirm_done_us { - let total_ms = (confirm_us - start_us) as f64 / 1000.0; - for (swqos_type, submit_done_us) in submit_timings_ref { - let submit_ms = - (*submit_done_us - start_us).max(0) as f64 / 1000.0; - let confirmed_ms = - (confirm_us - *submit_done_us).max(0) as f64 / 1000.0; - println!(" [SDK] {} {:?} submit: {:.4} ms, confirmed: {:.4} ms, total: {:.4} ms", dir, swqos_type, submit_ms, confirmed_ms, total_ms); - } - } - } + crate::common::sdk_log::print_sdk_timing_block( + dir, + timing_start_us, + build_end_us, + before_submit_us, + submit_timings_ref, + confirm_done_us, + ); } match poll_res { Ok(_) => (true, signatures, None), @@ -222,31 +217,17 @@ impl TradeExecutor for GenericTradeExecutor { }; Ok(confirm_result) } else { + // Not waiting for confirmation: confirmed is not measured (-); total is per-channel submit time only. if log_enabled { let dir = if is_buy { "Buy" } else { "Sell" }; - if let Some(start_us) = timing_start_us { - if let Some(end_us) = build_end_us { - println!( - " [SDK] {} build_instructions: {:.4} ms", - dir, - (end_us - start_us) as f64 / 1000.0 - ); - } - if let Some(end_us) = before_submit_us { - println!( - " [SDK] {} before_submit: {:.4} ms", - dir, - (end_us - start_us) as f64 / 1000.0 - ); - } - for (swqos_type, submit_done_us) in submit_timings_ref { - let submit_ms = (*submit_done_us - start_us).max(0) as f64 / 1000.0; - println!( - " [SDK] {} {:?} submit: {:.4} ms, confirmed: -, total: {:.4} ms", - dir, swqos_type, submit_ms, submit_ms - ); - } - } + crate::common::sdk_log::print_sdk_timing_block( + dir, + timing_start_us, + build_end_us, + before_submit_us, + submit_timings_ref, + None, + ); } Ok((ok, signatures, err)) }; @@ -377,37 +358,47 @@ mod tests { let dir = "Buy"; let build_ms = 12.34; let before_submit_ms = 15.67; + let w = 12usize; // same as crate::common::sdk_log::SWQOS_LABEL_WIDTH println!("\n--- 1. 构建指令耗时 / 提交前耗时(各打印一次,统一 ms,保留 4 位小数)---\n"); - println!(" [SDK] {} build_instructions: {:.4} ms", dir, build_ms); - println!(" [SDK] {} before_submit: {:.4} ms", dir, before_submit_ms); + println!(" [SDK][{:width$}] {} build_instructions: {:.4} ms", "-", dir, build_ms, width = w); + println!(" [SDK][{:width$}] {} before_submit: {:.4} ms", "-", dir, before_submit_ms, width = w); - println!("\n--- 2. 每个 SWQOS 独立耗时:submit=起点→该通道返回, confirmed=该通道提交→链上确认, total=起点→链上确认 ---\n"); + println!("\n--- 2. 每个 SWQOS 独立耗时:submit_done=起点→该通道提交完成, confirmed=该通道提交→链上确认, total=起点→链上确认 ---\n"); for (swqos_type, submit_ms, confirmed_ms, total_ms) in [ (SwqosType::Jito, 45.12, 83.38, 128.50), (SwqosType::Helius, 52.30, 76.20, 128.50), (SwqosType::ZeroSlot, 48.90, 79.60, 128.50), ] { println!( - " [SDK] {} {:?} submit: {:.4} ms, confirmed: {:.4} ms, total: {:.4} ms", - dir, swqos_type, submit_ms, confirmed_ms, total_ms + " [SDK][{:width$}] {} submit_done: {:.4} ms, confirmed: {:.4} ms, total: {:.4} ms", + swqos_type.as_str(), + dir, + submit_ms, + confirmed_ms, + total_ms, + width = w ); } - println!("\n--- 3. 不等待链上确认时:每行 total = 该通道 submit 耗时(独立)---\n"); + println!("\n--- 3. 不等待链上确认时:每行 total = 该通道 submit_done(提交完成总耗时)---\n"); for (swqos_type, submit_ms, total_ms) in [(SwqosType::Jito, 44.20, 44.20), (SwqosType::Helius, 51.80, 51.80)] { println!( - " [SDK] {} {:?} submit: {:.4} ms, confirmed: -, total: {:.4} ms", - dir, swqos_type, submit_ms, total_ms + " [SDK][{:width$}] {} submit_done: {:.4} ms, confirmed: -, total: {:.4} ms", + swqos_type.as_str(), + dir, + submit_ms, + total_ms, + width = w ); } println!("\n--- 4. Simulate 模式(build/before_submit 仍从 grpc_recv_us 起算)---\n"); - println!(" [SDK] {} build_instructions: {:.4} ms", dir, build_ms); - println!(" [SDK] {} before_submit: {:.4} ms", dir, before_submit_ms); - println!(" [SDK] {} simulate (dry-run): {:.4} ms", dir, 8.50); - println!(" [SDK] {} total: {:.4} ms", dir, 36.51); + println!(" [SDK][{:width$}] {} build_instructions: {:.4} ms", "-", dir, build_ms, width = w); + println!(" [SDK][{:width$}] {} before_submit: {:.4} ms", "-", dir, before_submit_ms, width = w); + println!(" [SDK][{:width$}] {} simulate (dry-run): {:.4} ms", "-", dir, 8.50, width = w); + println!(" [SDK][{:width$}] {} total: {:.4} ms", "-", dir, 36.51, width = w); println!(); } } diff --git a/src/trading/core/params.rs b/src/trading/core/params.rs index 0701e0e..2fcf5bb 100755 --- a/src/trading/core/params.rs +++ b/src/trading/core/params.rs @@ -62,7 +62,7 @@ pub struct SwapParams { pub slippage_basis_points: Option, pub address_lookup_table_account: Option, pub recent_blockhash: Option, - pub wait_transaction_confirmed: bool, + pub wait_tx_confirmed: bool, pub protocol_params: DexParamEnum, pub open_seed_optimize: bool, /// Arc> so cloning from infrastructure is a single Arc clone.