From 3d062279d9015025a39711c6bd6918b6e1579808 Mon Sep 17 00:00:00 2001 From: Wood Date: Fri, 27 Feb 2026 02:30:52 +0800 Subject: [PATCH] chore: release v3.5.4 - Bump version to 3.5.4; update README and README_CN - Astralane: irisb binary API (no Base64), POST /irisb with query api-key&method; constants use /irisb endpoints; ping POST getHealth - BlockRazor: Send Transaction v2 (plain Base64 body, Content-Type text/plain, auth in URI only); ping POST /v2/health; use default_http_client_builder - SWQOS: all clients use default_http_client_builder (nextblock, temporal, zeroslot, astralane, lightspeed, jito, flashblock); remove unused Duration imports Made-with: Cursor --- Cargo.toml | 2 +- README.md | 4 +- README_CN.md | 4 +- src/constants/swqos.rs | 36 +++++++++------- src/swqos/astralane.rs | 96 +++++++++++++---------------------------- src/swqos/blockrazor.rs | 88 +++++++++++-------------------------- src/swqos/flashblock.rs | 17 +------- src/swqos/jito.rs | 17 +------- src/swqos/lightspeed.rs | 17 +------- src/swqos/nextblock.rs | 17 +------- src/swqos/temporal.rs | 16 +------ src/swqos/zeroslot.rs | 17 +------- 12 files changed, 93 insertions(+), 238 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4dd6bc1..18f5dac 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sol-trade-sdk" -version = "3.5.3" +version = "3.5.4" edition = "2021" authors = [ "William ", diff --git a/README.md b/README.md index d2322ea..fea6692 100644 --- a/README.md +++ b/README.md @@ -89,14 +89,14 @@ Add the dependency to your `Cargo.toml`: ```toml # Add to your Cargo.toml -sol-trade-sdk = { path = "./sol-trade-sdk", version = "3.5.3" } +sol-trade-sdk = { path = "./sol-trade-sdk", version = "3.5.4" } ``` ### Use crates.io ```toml # Add to your Cargo.toml -sol-trade-sdk = "3.5.3" +sol-trade-sdk = "3.5.4" ``` ## 🛠️ Usage Examples diff --git a/README_CN.md b/README_CN.md index 8e3058f..1db3ac1 100755 --- a/README_CN.md +++ b/README_CN.md @@ -89,14 +89,14 @@ git clone https://github.com/0xfnzero/sol-trade-sdk ```toml # 添加到您的 Cargo.toml -sol-trade-sdk = { path = "./sol-trade-sdk", version = "3.5.3" } +sol-trade-sdk = { path = "./sol-trade-sdk", version = "3.5.4" } ``` ### 使用 crates.io ```toml # 添加到您的 Cargo.toml -sol-trade-sdk = "3.5.3" +sol-trade-sdk = "3.5.4" ``` ## 🛠️ 使用示例 diff --git a/src/constants/swqos.rs b/src/constants/swqos.rs index 9429c6a..4348d45 100755 --- a/src/constants/swqos.rs +++ b/src/constants/swqos.rs @@ -227,26 +227,30 @@ pub const SWQOS_ENDPOINTS_FLASHBLOCK: [&str; 8] = [ "http://ny.flashblock.trade", ]; +/// BlockRazor Send Transaction v2: plain-text Base64 body, auth in URI, Content-Type: text/plain. Keep-alive: POST /v2/health. pub const SWQOS_ENDPOINTS_BLOCKRAZOR: [&str; 8] = [ - "http://newyork.solana.blockrazor.xyz:443/sendTransaction", - "http://frankfurt.solana.blockrazor.xyz:443/sendTransaction", - "http://amsterdam.solana.blockrazor.xyz:443/sendTransaction", - "http://newyork.solana.blockrazor.xyz:443/sendTransaction", - "http://tokyo.solana.blockrazor.xyz:443/sendTransaction", - "http://frankfurt.solana.blockrazor.xyz:443/sendTransaction", - "http://newyork.solana.blockrazor.xyz:443/sendTransaction", - "http://frankfurt.solana.blockrazor.xyz:443/sendTransaction", + "http://newyork.solana.blockrazor.xyz:443/v2/sendTransaction", + "http://frankfurt.solana.blockrazor.xyz:443/v2/sendTransaction", + "http://amsterdam.solana.blockrazor.xyz:443/v2/sendTransaction", + "http://newyork.solana.blockrazor.xyz:443/v2/sendTransaction", + "http://tokyo.solana.blockrazor.xyz:443/v2/sendTransaction", + "http://london.solana.blockrazor.xyz:443/v2/sendTransaction", + "http://newyork.solana.blockrazor.xyz:443/v2/sendTransaction", + "http://frankfurt.solana.blockrazor.xyz:443/v2/sendTransaction", ]; +/// Astralane binary API path (no Base64; use with ?api-key=...&method=sendTransaction|getHealth). +pub const ASTRALANE_PATH_IRISB: &str = "irisb"; + pub const SWQOS_ENDPOINTS_ASTRALANE: [&str; 8] = [ - "http://ny.gateway.astralane.io/iris", - "http://fr.gateway.astralane.io/iris", - "http://ams.gateway.astralane.io/iris", - "http://ny.gateway.astralane.io/iris", - "http://jp.gateway.astralane.io/iris", - "http://ny.gateway.astralane.io/iris", - "http://lax.gateway.astralane.io/iris", - "http://lim.gateway.astralane.io/iris", + "http://ny.gateway.astralane.io/irisb", + "http://fr.gateway.astralane.io/irisb", + "http://ams.gateway.astralane.io/irisb", + "http://ny.gateway.astralane.io/irisb", + "http://jp.gateway.astralane.io/irisb", + "http://ny.gateway.astralane.io/irisb", + "http://lax.gateway.astralane.io/irisb", + "http://lim.gateway.astralane.io/irisb", ]; pub const SWQOS_ENDPOINTS_STELLIUM: [&str; 8] = [ diff --git a/src/swqos/astralane.rs b/src/swqos/astralane.rs index c32a9fd..ce0f5ee 100644 --- a/src/swqos/astralane.rs +++ b/src/swqos/astralane.rs @@ -1,13 +1,12 @@ -use crate::swqos::common::{poll_transaction_confirmation, serialize_transaction_and_encode}; +use crate::swqos::common::{default_http_client_builder, poll_transaction_confirmation}; use rand::seq::IndexedRandom; use reqwest::Client; -use serde_json::json; use std::{sync::Arc, time::Instant}; use std::time::Duration; -use solana_transaction_status::UiTransactionEncoding; - use anyhow::Result; +use bincode::serialize as bincode_serialize; +use solana_client::rpc_client::SerializableTransaction; use solana_sdk::transaction::VersionedTransaction; use crate::swqos::{SwqosType, TradeType}; use crate::swqos::SwqosClientTrait; @@ -17,6 +16,9 @@ use crate::{common::SolanaRpcClient, constants::swqos::ASTRALANE_TIP_ACCOUNTS}; use tokio::task::JoinHandle; use std::sync::atomic::{AtomicBool, Ordering}; +/// Empty body for getHealth POST; avoid per-request allocation. +static PING_BODY: &[u8] = &[]; + #[derive(Clone)] pub struct AstralaneClient { pub endpoint: String, @@ -50,19 +52,7 @@ impl SwqosClientTrait for AstralaneClient { impl AstralaneClient { pub fn new(rpc_url: String, endpoint: String, auth_token: String) -> Self { let rpc_client = SolanaRpcClient::new(rpc_url); - let http_client = Client::builder() - // Optimized connection pool settings for high performance - .pool_idle_timeout(Duration::from_secs(300)) - .pool_max_idle_per_host(4) - .tcp_keepalive(Some(Duration::from_secs(60))) // Reduced from 1200 to 60 - .tcp_nodelay(true) // Disable Nagle's algorithm for lower latency - .http2_keep_alive_interval(Duration::from_secs(10)) - .http2_keep_alive_timeout(Duration::from_secs(5)) - .http2_adaptive_window(true) // Enable adaptive flow control - .timeout(Duration::from_millis(3000)) // Reduced from 10s to 3s - .connect_timeout(Duration::from_millis(2000)) // Reduced from 5s to 2s - .build() - .unwrap(); + let http_client = default_http_client_builder().build().unwrap(); let client = Self { rpc_client: Arc::new(rpc_client), @@ -90,13 +80,9 @@ impl AstralaneClient { let stop_ping = self.stop_ping.clone(); let handle = tokio::spawn(async move { - // Immediate first ping to warm connection and reduce first-submit cold start latency - if let Err(e) = Self::send_ping_request(&http_client, &endpoint, &auth_token).await { - eprintln!("Astralane ping request failed: {}", e); - } let mut interval = tokio::time::interval(Duration::from_secs(30)); loop { - interval.tick().await; + interval.tick().await; // first tick completes immediately → one ping at start if stop_ping.load(Ordering::Relaxed) { break; } @@ -116,71 +102,49 @@ impl AstralaneClient { } } - /// Send ping request to /gethealth endpoint + /// Send ping request: POST endpoint?api-key=...&method=getHealth (endpoint is irisb from constants). async fn send_ping_request(http_client: &Client, endpoint: &str, auth_token: &str) -> Result<()> { - // Build ping URL by replacing /iris with /gethealth - let ping_url = if endpoint.ends_with("/iris") { - endpoint.replace("/iris", "/gethealth") - } else if endpoint.ends_with("/iris/") { - endpoint.replace("/iris/", "/gethealth") - } else if endpoint.ends_with('/') { - format!("{}gethealth", endpoint) - } else { - format!("{}/gethealth", endpoint) - }; - - // Short timeout for ping; consume body so connection is returned to pool for reuse by submit - let response = http_client.get(&ping_url) - .header("api_key", auth_token) + let response = http_client + .post(endpoint) + .query(&[("api-key", auth_token), ("method", "getHealth")]) .timeout(Duration::from_millis(1500)) + .body(PING_BODY) .send() .await?; let status = response.status(); - let _ = response.bytes().await; + let _ = response.bytes().await; // consume body so connection returns to pool if !status.is_success() { eprintln!("Astralane ping request returned non-success status: {}", status); } Ok(()) } + /// Send transaction via /irisb binary API (no Base64; lower latency). pub async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction, wait_confirmation: bool) -> Result<()> { let start_time = Instant::now(); - let (content, signature) = serialize_transaction_and_encode(transaction, UiTransactionEncoding::Base64)?; + let signature = transaction.get_signature(); - let request_body = serde_json::to_string(&json!({ - "jsonrpc": "2.0", - "id": 1, - "method": "sendTransaction", - "params": [ - content, - { "encoding": "base64", "skipPreflight": true }, - { "mevProtect": false } - ] - }))?; + let body_bytes = bincode_serialize(transaction).map_err(|e| anyhow::anyhow!("Astralane binary serialize failed: {}", e))?; - // Send request with api_key header - let response_text = self.http_client.post(&self.endpoint) - .body(request_body) - .header("Content-Type", "application/json") - .header("api_key", &self.auth_token) + let response = self.http_client + .post(&self.endpoint) + .query(&[("api-key", self.auth_token.as_str()), ("method", "sendTransaction")]) + .header("Content-Type", "application/octet-stream") + .body(body_bytes) .send() - .await? - .text() .await?; - // Parse JSON response - if let Ok(response_json) = serde_json::from_str::(&response_text) { - if response_json.get("result").is_some() { - println!(" [astralane] {} submitted: {:?}", trade_type, start_time.elapsed()); - } else if let Some(_error) = response_json.get("error") { - eprintln!(" [astralane] {} submission failed: {:?}", trade_type, _error); - } + let status = response.status(); + let _ = response.bytes().await; + if status.is_success() { + println!(" [astralane] {} submitted: {:?}", trade_type, start_time.elapsed()); } else { - eprintln!(" [astralane] {} submission failed: {:?}", trade_type, response_text); + eprintln!(" [astralane] {} submission failed: status {}", trade_type, status); + return Err(anyhow::anyhow!("Astralane sendTransaction failed: {}", status)); } - let start_time: Instant = Instant::now(); - match poll_transaction_confirmation(&self.rpc_client, signature, wait_confirmation).await { + let start_time = Instant::now(); + match poll_transaction_confirmation(&self.rpc_client, *signature, wait_confirmation).await { Ok(_) => (), Err(e) => { println!(" signature: {:?}", signature); diff --git a/src/swqos/blockrazor.rs b/src/swqos/blockrazor.rs index 3745929..ed9c52c 100644 --- a/src/swqos/blockrazor.rs +++ b/src/swqos/blockrazor.rs @@ -1,7 +1,6 @@ -use crate::swqos::common::{poll_transaction_confirmation, serialize_transaction_and_encode}; +use crate::swqos::common::{default_http_client_builder, poll_transaction_confirmation, serialize_transaction_and_encode}; use rand::seq::IndexedRandom; -use reqwest::{Client, header::{HeaderMap, HeaderValue, CONTENT_TYPE}}; -use serde_json::json; +use reqwest::Client; use std::{sync::Arc, time::Instant}; use std::time::Duration; @@ -50,19 +49,7 @@ impl SwqosClientTrait for BlockRazorClient { impl BlockRazorClient { pub fn new(rpc_url: String, endpoint: String, auth_token: String) -> Self { let rpc_client = SolanaRpcClient::new(rpc_url); - let http_client = Client::builder() - // Optimized connection pool settings for high performance - .pool_idle_timeout(Duration::from_secs(300)) // 5min so ping-kept connection is not evicted early - .pool_max_idle_per_host(4) // Few connections so submit reuses same connection as ping, avoiding cold connection after ~5min server idle close - .tcp_keepalive(Some(Duration::from_secs(60))) // Reduced from 1200 to 60 - .tcp_nodelay(true) // Disable Nagle's algorithm for lower latency - .http2_keep_alive_interval(Duration::from_secs(10)) - .http2_keep_alive_timeout(Duration::from_secs(5)) - .http2_adaptive_window(true) // Enable adaptive flow control - .timeout(Duration::from_millis(3000)) // Reduced from 10s to 3s - .connect_timeout(Duration::from_millis(2000)) // Reduced from 5s to 2s - .build() - .unwrap(); + let http_client = default_http_client_builder().build().unwrap(); let client = Self { rpc_client: Arc::new(rpc_client), @@ -120,31 +107,15 @@ impl BlockRazorClient { } } - /// Send ping request to /health endpoint + /// Send ping request: POST /v2/health?auth=... (Keep Alive). Only required param: auth. async fn send_ping_request(http_client: &Client, endpoint: &str, auth_token: &str) -> Result<()> { - // Build health URL by replacing sendTransaction with health - let ping_url = if endpoint.ends_with("sendTransaction") { - endpoint.replace("sendTransaction", "health") - } else if endpoint.ends_with("/sendTransaction") { - endpoint.replace("/sendTransaction", "/health") - } else { - // Fallback to original logic if endpoint doesn't end with sendTransaction - if endpoint.ends_with('/') { - format!("{}health", endpoint) - } else { - format!("{}/health", endpoint) - } - }; - - // Prepare headers - let mut headers = HeaderMap::new(); - headers.insert("apikey", HeaderValue::from_str(auth_token)?); - headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json")); - - // Short timeout for ping; consume body so connection is returned to pool for reuse by submit - let response = http_client.get(&ping_url) - .headers(headers) + let ping_url = endpoint.replace("/v2/sendTransaction", "/v2/health"); + let response = http_client + .post(&ping_url) + .query(&[("auth", auth_token)]) + .header("Content-Type", "text/plain") .timeout(Duration::from_millis(1500)) + .body(&[] as &[u8]) .send() .await?; let status = response.status(); @@ -155,40 +126,33 @@ impl BlockRazorClient { Ok(()) } + /// Send transaction via v2 API: plain Base64 body, Content-Type: text/plain. Only required URI param: auth. pub async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction, wait_confirmation: bool) -> Result<()> { let start_time = Instant::now(); let (content, signature) = serialize_transaction_and_encode(transaction, UiTransactionEncoding::Base64)?; - // BlockRazor fast-mode request format - let request_body = serde_json::to_string(&json!({ - "transaction": content, - "mode": "fast" - }))?; - - // BlockRazor uses apikey header - let response_text = self.http_client.post(&self.endpoint) - .body(request_body) - .header("Content-Type", "application/json") - .header("apikey", &self.auth_token) + let response = self.http_client + .post(&self.endpoint) + .query(&[("auth", self.auth_token.as_str())]) + .header("Content-Type", "text/plain") + .body(content) .send() - .await? - .text() .await?; - // Parse JSON response - if let Ok(response_json) = serde_json::from_str::(&response_text) { + let status = response.status(); + let _ = response.bytes().await; + if status.is_success() { if crate::common::sdk_log::sdk_log_enabled() { - if response_json.get("result").is_some() || response_json.get("signature").is_some() { - println!(" [blockrazor] {} submitted: {:?}", trade_type, start_time.elapsed()); - } else if let Some(_error) = response_json.get("error") { - eprintln!(" [blockrazor] {} submission failed: {:?}", trade_type, _error); - } + println!(" [blockrazor] {} submitted: {:?}", trade_type, start_time.elapsed()); } - } else if crate::common::sdk_log::sdk_log_enabled() { - eprintln!(" [blockrazor] {} submission failed: {:?}", trade_type, response_text); + } else { + if crate::common::sdk_log::sdk_log_enabled() { + eprintln!(" [blockrazor] {} submission failed: status {}", trade_type, status); + } + return Err(anyhow::anyhow!("BlockRazor sendTransaction failed: {}", status)); } - let start_time: Instant = Instant::now(); + let start_time = Instant::now(); match poll_transaction_confirmation(&self.rpc_client, signature, wait_confirmation).await { Ok(_) => (), Err(e) => { diff --git a/src/swqos/flashblock.rs b/src/swqos/flashblock.rs index 253e6d1..2c81329 100644 --- a/src/swqos/flashblock.rs +++ b/src/swqos/flashblock.rs @@ -1,10 +1,9 @@ -use crate::swqos::common::{poll_transaction_confirmation, serialize_transaction_and_encode}; +use crate::swqos::common::{default_http_client_builder, poll_transaction_confirmation, serialize_transaction_and_encode}; use rand::seq::IndexedRandom; use reqwest::Client; use serde_json::json; use std::{sync::Arc, time::Instant}; -use std::time::Duration; use solana_transaction_status::UiTransactionEncoding; use anyhow::Result; @@ -46,19 +45,7 @@ impl SwqosClientTrait for FlashBlockClient { impl FlashBlockClient { pub fn new(rpc_url: String, endpoint: String, auth_token: String) -> Self { let rpc_client = SolanaRpcClient::new(rpc_url); - let http_client = Client::builder() - // Optimized connection pool settings for high performance - .pool_idle_timeout(Duration::from_secs(120)) - .pool_max_idle_per_host(256) // Increased from 64 to 256 - .tcp_keepalive(Some(Duration::from_secs(60))) // Reduced from 1200 to 60 - .tcp_nodelay(true) // Disable Nagle's algorithm for lower latency - .http2_keep_alive_interval(Duration::from_secs(10)) - .http2_keep_alive_timeout(Duration::from_secs(5)) - .http2_adaptive_window(true) // Enable adaptive flow control - .timeout(Duration::from_millis(3000)) // Reduced from 10s to 3s - .connect_timeout(Duration::from_millis(2000)) // Reduced from 5s to 2s - .build() - .unwrap(); + let http_client = default_http_client_builder().build().unwrap(); Self { rpc_client: Arc::new(rpc_client), endpoint, auth_token, http_client } } diff --git a/src/swqos/jito.rs b/src/swqos/jito.rs index 70028b1..6453152 100755 --- a/src/swqos/jito.rs +++ b/src/swqos/jito.rs @@ -1,11 +1,10 @@ -use crate::swqos::common::{poll_transaction_confirmation, serialize_transaction_and_encode, FormatBase64VersionedTransaction}; +use crate::swqos::common::{default_http_client_builder, poll_transaction_confirmation, serialize_transaction_and_encode, FormatBase64VersionedTransaction}; use rand::seq::IndexedRandom; use reqwest::Client; use serde_json::json; use std::{sync::Arc, time::Instant}; -use std::time::Duration; use solana_transaction_status::UiTransactionEncoding; use anyhow::Result; @@ -49,19 +48,7 @@ impl SwqosClientTrait for JitoClient { impl JitoClient { pub fn new(rpc_url: String, endpoint: String, auth_token: String) -> Self { let rpc_client = SolanaRpcClient::new(rpc_url); - let http_client = Client::builder() - // Optimized connection pool settings for high performance - .pool_idle_timeout(Duration::from_secs(120)) - .pool_max_idle_per_host(256) // Increased from 64 to 256 - .tcp_keepalive(Some(Duration::from_secs(60))) // Reduced from 1200 to 60 - .tcp_nodelay(true) // Disable Nagle's algorithm for lower latency - .http2_keep_alive_interval(Duration::from_secs(10)) - .http2_keep_alive_timeout(Duration::from_secs(5)) - .http2_adaptive_window(true) // Enable adaptive flow control - .timeout(Duration::from_millis(3000)) // Reduced from 10s to 3s - .connect_timeout(Duration::from_millis(2000)) // Reduced from 5s to 2s - .build() - .unwrap(); + let http_client = default_http_client_builder().build().unwrap(); Self { rpc_client: Arc::new(rpc_client), endpoint, auth_token, http_client } } diff --git a/src/swqos/lightspeed.rs b/src/swqos/lightspeed.rs index 8fcd57c..7834ea9 100644 --- a/src/swqos/lightspeed.rs +++ b/src/swqos/lightspeed.rs @@ -1,10 +1,9 @@ -use crate::swqos::common::{poll_transaction_confirmation, serialize_transaction_and_encode}; +use crate::swqos::common::{default_http_client_builder, poll_transaction_confirmation, serialize_transaction_and_encode}; use rand::seq::IndexedRandom; use reqwest::Client; use serde_json::json; use std::{sync::Arc, time::Instant}; -use std::time::Duration; use solana_transaction_status::UiTransactionEncoding; use anyhow::Result; @@ -47,19 +46,7 @@ impl LightspeedClient { // Lightspeed endpoint should already include /lightspeed path // Format: https://.rpc.solanavibestation.com/lightspeed?api_key= let rpc_client = SolanaRpcClient::new(rpc_url); - let http_client = Client::builder() - // Optimized connection pool settings for high performance - .pool_idle_timeout(Duration::from_secs(120)) - .pool_max_idle_per_host(256) - .tcp_keepalive(Some(Duration::from_secs(60))) - .tcp_nodelay(true) // Disable Nagle's algorithm for lower latency - .http2_keep_alive_interval(Duration::from_secs(10)) - .http2_keep_alive_timeout(Duration::from_secs(5)) - .http2_adaptive_window(true) // Enable adaptive flow control - .timeout(Duration::from_millis(3000)) - .connect_timeout(Duration::from_millis(2000)) - .build() - .unwrap(); + let http_client = default_http_client_builder().build().unwrap(); Self { rpc_client: Arc::new(rpc_client), endpoint, auth_token, http_client } } diff --git a/src/swqos/nextblock.rs b/src/swqos/nextblock.rs index 96545ec..a1ca6c7 100755 --- a/src/swqos/nextblock.rs +++ b/src/swqos/nextblock.rs @@ -1,10 +1,9 @@ -use crate::swqos::common::{poll_transaction_confirmation, serialize_transaction_and_encode}; +use crate::swqos::common::{default_http_client_builder, poll_transaction_confirmation, serialize_transaction_and_encode}; use rand::seq::IndexedRandom; use reqwest::Client; use serde_json::json; use std::{sync::Arc, time::Instant}; -use std::time::Duration; use solana_transaction_status::UiTransactionEncoding; use anyhow::Result; @@ -51,19 +50,7 @@ impl NextBlockClient { format!("{}/api/v2/submit", endpoint.trim_end_matches('/')) }; let rpc_client = SolanaRpcClient::new(rpc_url); - let http_client = Client::builder() - // Optimized connection pool settings for high performance - .pool_idle_timeout(Duration::from_secs(120)) - .pool_max_idle_per_host(256) // Increased from 64 to 256 - .tcp_keepalive(Some(Duration::from_secs(60))) // Reduced from 1200 to 60 - .tcp_nodelay(true) // Disable Nagle's algorithm for lower latency - .http2_keep_alive_interval(Duration::from_secs(10)) - .http2_keep_alive_timeout(Duration::from_secs(5)) - .http2_adaptive_window(true) // Enable adaptive flow control - .timeout(Duration::from_millis(3000)) // Reduced from 10s to 3s - .connect_timeout(Duration::from_millis(2000)) // Reduced from 5s to 2s - .build() - .unwrap(); + let http_client = default_http_client_builder().build().unwrap(); Self { rpc_client: Arc::new(rpc_client), endpoint, auth_token, http_client } } diff --git a/src/swqos/temporal.rs b/src/swqos/temporal.rs index 838af3d..9f418ee 100755 --- a/src/swqos/temporal.rs +++ b/src/swqos/temporal.rs @@ -1,5 +1,5 @@ -use crate::swqos::common::{poll_transaction_confirmation, serialize_transaction_and_encode}; +use crate::swqos::common::{default_http_client_builder, poll_transaction_confirmation, serialize_transaction_and_encode}; use rand::seq::IndexedRandom; use reqwest::Client; use serde_json::json; @@ -76,19 +76,7 @@ impl SwqosClientTrait for TemporalClient { impl TemporalClient { pub fn new(rpc_url: String, endpoint: String, auth_token: String) -> Self { let rpc_client = SolanaRpcClient::new(rpc_url); - let http_client = Client::builder() - // Optimized connection pool settings for high performance - .pool_idle_timeout(Duration::from_secs(300)) - .pool_max_idle_per_host(4) - .tcp_keepalive(Some(Duration::from_secs(60))) // Reduced from 1200 to 60 - .tcp_nodelay(true) // Disable Nagle's algorithm for lower latency - .http2_keep_alive_interval(Duration::from_secs(10)) - .http2_keep_alive_timeout(Duration::from_secs(5)) - .http2_adaptive_window(true) // Enable adaptive flow control - .timeout(Duration::from_millis(3000)) // Reduced from 10s to 3s - .connect_timeout(Duration::from_millis(2000)) // Reduced from 5s to 2s - .build() - .unwrap(); + let http_client = default_http_client_builder().build().unwrap(); let client = Self { rpc_client: Arc::new(rpc_client), diff --git a/src/swqos/zeroslot.rs b/src/swqos/zeroslot.rs index fa84cbc..e2dbf00 100755 --- a/src/swqos/zeroslot.rs +++ b/src/swqos/zeroslot.rs @@ -1,10 +1,9 @@ -use crate::swqos::common::{poll_transaction_confirmation, serialize_transaction_and_encode}; +use crate::swqos::common::{default_http_client_builder, poll_transaction_confirmation, serialize_transaction_and_encode}; use rand::seq::IndexedRandom; use reqwest::Client; use serde_json::json; use std::{sync::Arc, time::Instant}; -use std::time::Duration; use solana_transaction_status::UiTransactionEncoding; use anyhow::Result; @@ -46,19 +45,7 @@ impl SwqosClientTrait for ZeroSlotClient { impl ZeroSlotClient { pub fn new(rpc_url: String, endpoint: String, auth_token: String) -> Self { let rpc_client = SolanaRpcClient::new(rpc_url); - let http_client = Client::builder() - // Optimized connection pool settings for high performance - .pool_idle_timeout(Duration::from_secs(120)) - .pool_max_idle_per_host(256) // Increased from 64 to 256 - .tcp_keepalive(Some(Duration::from_secs(60))) // Reduced from 1200 to 60 - .tcp_nodelay(true) // Disable Nagle's algorithm for lower latency - .http2_keep_alive_interval(Duration::from_secs(10)) - .http2_keep_alive_timeout(Duration::from_secs(5)) - .http2_adaptive_window(true) // Enable adaptive flow control - .timeout(Duration::from_millis(3000)) // Reduced from 10s to 3s - .connect_timeout(Duration::from_millis(2000)) // Reduced from 5s to 2s - .build() - .unwrap(); + let http_client = default_http_client_builder().build().unwrap(); Self { rpc_client: Arc::new(rpc_client), endpoint, auth_token, http_client } }