From def16e6b9239b07cdb50c4e05d15bf06429a5b1e Mon Sep 17 00:00:00 2001 From: wood Date: Mon, 7 Jul 2025 03:28:02 +0800 Subject: [PATCH] update swqos config --- README.md | 28 +++++++----- README_CN.md | 28 +++++++----- src/lib.rs | 56 ++++------------------- src/main.rs | 43 ++++++++++-------- src/swqos/mod.rs | 88 ++++++++++++++++++++++++++++++------ src/swqos/solana_rpc.rs | 2 +- src/trading/core/parallel.rs | 6 +-- 7 files changed, 144 insertions(+), 107 deletions(-) diff --git a/README.md b/README.md index 0035913..5d8a5d9 100755 --- a/README.md +++ b/README.md @@ -90,13 +90,15 @@ let priority_fee = PriorityFee { }; // Configure multiple swqos in single region, can send transactions concurrently -let swqos_configs = vec![ - SwqosConfig::new(None, None, SwqosType::Jito, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token".to_string()), SwqosType::ZeroSlot, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token".to_string()), SwqosType::Temporal, SwqosRegion::Frankfurt), -]; - let rpc_url = "https://mainnet.helius-rpc.com/?api-key=xxxxxx".to_string(); +let swqos_configs = vec![ + SwqosConfig::Jito(SwqosRegion::Frankfurt), + SwqosConfig::NextBlock("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Bloxroute("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::ZeroSlot("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Temporal("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Default(rpc_url.clone()), +]; // Define sdk configuration let trade_config = TradeConfig { @@ -302,13 +304,15 @@ use solana_client::rpc_client::RpcClient; use sol_trade_sdk::{common::{Cluster, PriorityFee}, SolanaTrade}; // Configure multiple swqos in single region, can send transactions concurrently -let swqos_configs = vec![ - SwqosConfig::new(None, None, SwqosType::Jito, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token".to_string()), SwqosType::ZeroSlot, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token".to_string()), SwqosType::Temporal, SwqosRegion::Frankfurt), -]; - let rpc_url = "https://mainnet.helius-rpc.com/?api-key=xxxxxx".to_string(); +let swqos_configs = vec![ + SwqosConfig::Jito(SwqosRegion::Frankfurt), + SwqosConfig::NextBlock("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Bloxroute("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::ZeroSlot("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Temporal("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Default(rpc_url.clone()), +]; // Define sdk configuration let trade_config = TradeConfig { diff --git a/README_CN.md b/README_CN.md index 123c037..712f733 100755 --- a/README_CN.md +++ b/README_CN.md @@ -90,13 +90,15 @@ let priority_fee = PriorityFee { }; // 单区域配置多个swqos,可同时发送交易 -let swqos_configs = vec![ - SwqosConfig::new(None, None, SwqosType::Jito, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token".to_string()), SwqosType::ZeroSlot, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token".to_string()), SwqosType::Temporal, SwqosRegion::Frankfurt), -]; - let rpc_url = "https://mainnet.helius-rpc.com/?api-key=xxxxxx".to_string(); +let swqos_configs = vec![ + SwqosConfig::Jito(SwqosRegion::Frankfurt), + SwqosConfig::NextBlock("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Bloxroute("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::ZeroSlot("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Temporal("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Default(rpc_url.clone()), +]; // 定义sdk配置参数 let trade_config = TradeConfig { @@ -302,13 +304,15 @@ use solana_client::rpc_client::RpcClient; use sol_trade_sdk::{common::{Cluster, PriorityFee}, SolanaTrade}; // 单区域配置多个swqos,可同时发送交易 -let swqos_configs = vec![ - SwqosConfig::new(None, None, SwqosType::Jito, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token".to_string()), SwqosType::ZeroSlot, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token".to_string()), SwqosType::Temporal, SwqosRegion::Frankfurt), -]; - let rpc_url = "https://mainnet.helius-rpc.com/?api-key=xxxxxx".to_string(); +let swqos_configs = vec![ + SwqosConfig::Jito(SwqosRegion::Frankfurt), + SwqosConfig::NextBlock("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Bloxroute("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::ZeroSlot("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Temporal("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Default(rpc_url.clone()), +]; // 定义sdk配置参数 let trade_config = TradeConfig { diff --git a/src/lib.rs b/src/lib.rs index c518b21..056cb49 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,8 @@ use constants::trade_type::{COPY_BUY, SNIPER_BUY}; use constants::trade_platform::{PUMPFUN, PUMPFUN_SWAP}; use accounts::BondingCurveAccount; +use crate::swqos::bloxroute::BloxrouteClient; +use crate::swqos::SwqosConfig; use crate::swqos::SwqosType; use crate::swqos::jito::JitoClient; use crate::swqos::nextblock::NextBlockClient; @@ -81,58 +83,18 @@ impl SolanaTrade { let priority_fee = trade_config.priority_fee.clone(); let commitment = trade_config.commitment.clone(); - let rpc = SolanaRpcClient::new_with_commitment( - rpc_url.clone(), - commitment - ); - let rpc = Arc::new(rpc); - let mut swqos_clients: Vec> = vec![]; for swqos in swqos_configs { - match swqos.swqos_type { - SwqosType::Jito => { - let jito_client = JitoClient::new( - rpc_url.clone(), - swqos.endpoint, - swqos.auth_token - ); - swqos_clients.push(Arc::new(jito_client)); - } - SwqosType::NextBlock => { - let nextblock_client = NextBlockClient::new( - rpc_url.clone(), - swqos.endpoint, - swqos.auth_token - ); - swqos_clients.push(Arc::new(nextblock_client)); - } - SwqosType::ZeroSlot => { - let zeroslot_client = ZeroSlotClient::new( - rpc_url.clone(), - swqos.endpoint, - swqos.auth_token - ); - swqos_clients.push(Arc::new(zeroslot_client)); - } - SwqosType::Temporal => { - let temporal_client = TemporalClient::new( - rpc_url.clone(), - swqos.endpoint, - swqos.auth_token - ); - swqos_clients.push(Arc::new(temporal_client)); - } - SwqosType::Rpc => { - let rpc_client = SolRpcClient::new(rpc.clone()); - swqos_clients.push(Arc::new(rpc_client)); - } - _ => { - println!("Unsupported swqos type: {:?}", swqos.swqos_type); - } - } + let swqos_client = SwqosConfig::get_swqos_client(rpc_url.clone(), commitment.clone(), swqos.clone()); + swqos_clients.push(swqos_client); } + let rpc = Arc::new(SolanaRpcClient::new_with_commitment( + rpc_url.clone(), + commitment + )); + let instance = Self { payer, rpc, diff --git a/src/main.rs b/src/main.rs index 7b716b4..b1fa65d 100755 --- a/src/main.rs +++ b/src/main.rs @@ -245,13 +245,16 @@ async fn test_raydium_with_grpc() -> Result<(), Box> { async fn test_pumpfun_sniper() -> AnyResult<()> { // 创建一个随机账户作为交易者 let payer = Keypair::new(); - let swqos_configs = vec![ - SwqosConfig::new(None, Some("your auth_token for jito".to_string()), SwqosType::Jito, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token for zeroslot".to_string()), SwqosType::ZeroSlot, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token for temporal".to_string()), SwqosType::Temporal, SwqosRegion::Frankfurt), - ]; - + let rpc_url = "https://mainnet.helius-rpc.com/?api-key=xxxxxx".to_string(); + let swqos_configs = vec![ + SwqosConfig::Jito(SwqosRegion::Frankfurt), + SwqosConfig::NextBlock("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Bloxroute("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::ZeroSlot("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Temporal("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Default(rpc_url.clone()), + ]; // Define cluster configuration let trade_config = TradeConfig { @@ -291,13 +294,15 @@ async fn test_pumpfun_sniper() -> AnyResult<()> { async fn test_pumpfun() -> AnyResult<()> { let payer = Keypair::new(); - let swqos_configs = vec![ - SwqosConfig::new(None, Some("your auth_token for jito".to_string()), SwqosType::Jito, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token for zeroslot".to_string()), SwqosType::ZeroSlot, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token for temporal".to_string()), SwqosType::Temporal, SwqosRegion::Frankfurt), - ]; - let rpc_url = "https://mainnet.helius-rpc.com/?api-key=xxxxxx".to_string(); + let swqos_configs = vec![ + SwqosConfig::Jito(SwqosRegion::Frankfurt), + SwqosConfig::NextBlock("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Bloxroute("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::ZeroSlot("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Temporal("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Default(rpc_url.clone()), + ]; // Define cluster configuration let trade_config = TradeConfig { @@ -362,13 +367,15 @@ async fn test_pumpfun() -> AnyResult<()> { async fn test_pumpswap() -> AnyResult<()> { let payer = Keypair::new(); - let swqos_configs = vec![ - SwqosConfig::new(None, Some("your auth_token for jito".to_string()), SwqosType::Jito, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token for zeroslot".to_string()), SwqosType::ZeroSlot, SwqosRegion::Frankfurt), - SwqosConfig::new(None, Some("your auth_token for temporal".to_string()), SwqosType::Temporal, SwqosRegion::Frankfurt), - ]; - let rpc_url = "https://mainnet.helius-rpc.com/?api-key=xxxxxx".to_string(); + let swqos_configs = vec![ + SwqosConfig::Jito(SwqosRegion::Frankfurt), + SwqosConfig::NextBlock("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Bloxroute("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::ZeroSlot("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Temporal("your api_token".to_string(), SwqosRegion::Frankfurt), + SwqosConfig::Default(rpc_url.clone()), + ]; // Define cluster configuration let trade_config = TradeConfig { diff --git a/src/swqos/mod.rs b/src/swqos/mod.rs index 1e0987d..5a3a2f5 100755 --- a/src/swqos/mod.rs +++ b/src/swqos/mod.rs @@ -6,12 +6,14 @@ pub mod zeroslot; pub mod temporal; pub mod bloxroute; -use solana_sdk::transaction::VersionedTransaction; +use std::sync::Arc; + +use solana_sdk::{commitment_config::CommitmentConfig, transaction::VersionedTransaction}; use tokio::sync::RwLock; use anyhow::Result; -use crate::constants::swqos::{SWQOS_ENDPOINTS_BLOX, SWQOS_ENDPOINTS_JITO, SWQOS_ENDPOINTS_NEXTBLOCK, SWQOS_ENDPOINTS_TEMPORAL, SWQOS_ENDPOINTS_ZERO_SLOT}; +use crate::{common::SolanaRpcClient, constants::swqos::{SWQOS_ENDPOINTS_BLOX, SWQOS_ENDPOINTS_JITO, SWQOS_ENDPOINTS_NEXTBLOCK, SWQOS_ENDPOINTS_TEMPORAL, SWQOS_ENDPOINTS_ZERO_SLOT}, swqos::{bloxroute::BloxrouteClient, jito::JitoClient, nextblock::NextBlockClient, solana_rpc::SolRpcClient, temporal::TemporalClient, zeroslot::ZeroSlotClient}}; lazy_static::lazy_static! { static ref TIP_ACCOUNT_CACHE: RwLock> = RwLock::new(Vec::new()); @@ -44,7 +46,7 @@ pub enum SwqosType { ZeroSlot, Temporal, Bloxroute, - Rpc, + Default, } pub type SwqosClient = dyn SwqosClientTrait + Send + Sync + 'static; @@ -69,25 +71,83 @@ pub enum SwqosRegion { Default, } -#[derive(Debug, Clone)] -pub struct SwqosConfig { - pub endpoint: String, - pub auth_token: String, - pub swqos_type: SwqosType, +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum SwqosConfig { + Default(String), + Jito(SwqosRegion), + NextBlock(String, SwqosRegion), + Bloxroute(String, SwqosRegion), + Temporal(String, SwqosRegion), + ZeroSlot(String, SwqosRegion), } impl SwqosConfig { - pub fn new(endpoint: Option, auth_token: Option, swqos_type: SwqosType, region: SwqosRegion) -> Self { - let auth_token = auth_token.unwrap_or_else(|| "".to_string()); - let endpoint = endpoint.unwrap_or_else(|| match swqos_type { + pub fn get_endpoint(swqos_type: SwqosType, region: SwqosRegion) -> String { + match swqos_type { SwqosType::Jito => SWQOS_ENDPOINTS_JITO[region as usize].to_string(), SwqosType::NextBlock => SWQOS_ENDPOINTS_NEXTBLOCK[region as usize].to_string(), SwqosType::ZeroSlot => SWQOS_ENDPOINTS_ZERO_SLOT[region as usize].to_string(), SwqosType::Temporal => SWQOS_ENDPOINTS_TEMPORAL[region as usize].to_string(), SwqosType::Bloxroute => SWQOS_ENDPOINTS_BLOX[region as usize].to_string(), - SwqosType::Rpc => "".to_string(), - }); + SwqosType::Default => "".to_string(), + } + } - Self { endpoint, auth_token, swqos_type } + pub fn get_swqos_client(rpc_url: String, commitment: CommitmentConfig, swqos_config: SwqosConfig) -> Arc { + match swqos_config { + SwqosConfig::Jito(region) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::Jito, region); + let jito_client = JitoClient::new( + rpc_url.clone(), + endpoint, + "".to_string() + ); + Arc::new(jito_client) + } + SwqosConfig::NextBlock(auth_token, region) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::NextBlock, region); + let nextblock_client = NextBlockClient::new( + rpc_url.clone(), + endpoint.to_string(), + auth_token + ); + Arc::new(nextblock_client) + }, + SwqosConfig::ZeroSlot(auth_token, region) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::ZeroSlot, region); + let zeroslot_client = ZeroSlotClient::new( + rpc_url.clone(), + endpoint.to_string(), + auth_token + ); + Arc::new(zeroslot_client) + }, + SwqosConfig::Temporal(auth_token, region) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::Temporal, region); + let temporal_client = TemporalClient::new( + rpc_url.clone(), + endpoint.to_string(), + auth_token + ); + Arc::new(temporal_client) + }, + SwqosConfig::Bloxroute(auth_token, region) => { + let endpoint = SwqosConfig::get_endpoint(SwqosType::Bloxroute, region); + let bloxroute_client = BloxrouteClient::new( + rpc_url.clone(), + endpoint.to_string(), + auth_token + ); + Arc::new(bloxroute_client) + }, + SwqosConfig::Default(endpoint) => { + let rpc = SolanaRpcClient::new_with_commitment( + endpoint, + commitment + ); + let rpc_client = SolRpcClient::new(Arc::new(rpc)); + Arc::new(rpc_client) + } + } } } \ No newline at end of file diff --git a/src/swqos/solana_rpc.rs b/src/swqos/solana_rpc.rs index 911c5b8..5307e05 100755 --- a/src/swqos/solana_rpc.rs +++ b/src/swqos/solana_rpc.rs @@ -50,7 +50,7 @@ impl SwqosClientTrait for SolRpcClient { } fn get_swqos_type(&self) -> SwqosType { - SwqosType::Rpc + SwqosType::Default } } diff --git a/src/trading/core/parallel.rs b/src/trading/core/parallel.rs index e2b7060..9f378ad 100755 --- a/src/trading/core/parallel.rs +++ b/src/trading/core/parallel.rs @@ -37,7 +37,7 @@ pub async fn parallel_execute_with_tips( let handle = tokio::spawn(async move { core_affinity::set_for_current(core_id); let transaction = if matches!(trade_type, TradeType::Sell) - && swqos_client.get_swqos_type() == SwqosType::Rpc + && swqos_client.get_swqos_type() == SwqosType::Default { build_sell_transaction( payer, @@ -48,7 +48,7 @@ pub async fn parallel_execute_with_tips( ) .await? } else if matches!(trade_type, TradeType::Sell) - && swqos_client.get_swqos_type() != SwqosType::Rpc + && swqos_client.get_swqos_type() != SwqosType::Default { let tip_account = swqos_client.get_tip_account()?; let tip_account = Arc::new(Pubkey::from_str(&tip_account).map_err(|e| anyhow!(e))?); @@ -61,7 +61,7 @@ pub async fn parallel_execute_with_tips( recent_blockhash, ) .await? - } else if swqos_client.get_swqos_type() == SwqosType::Rpc { + } else if swqos_client.get_swqos_type() == SwqosType::Default { build_rpc_transaction( payer, &priority_fee,