diff --git a/src/common/types.rs b/src/common/types.rs index 8b6b6f4..a15d61e 100755 --- a/src/common/types.rs +++ b/src/common/types.rs @@ -3,71 +3,32 @@ use std::sync::Arc; use solana_client::rpc_client::RpcClient; use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey, signature::Keypair}; use serde::Deserialize; -use crate::{constants::pumpfun::trade::{DEFAULT_BUY_TIP_FEE, DEFAULT_COMPUTE_UNIT_LIMIT, DEFAULT_COMPUTE_UNIT_PRICE, DEFAULT_RPC_UNIT_LIMIT, DEFAULT_RPC_UNIT_PRICE, DEFAULT_SELL_TIP_FEE}, swqos::SwqosClient}; - -#[derive(Debug, Clone, PartialEq)] -pub enum SwqosType { - Jito, - NextBlock, - ZeroSlot, - Nozomi, - Rpc, -} +use crate::{constants::pumpfun::trade::{DEFAULT_BUY_TIP_FEE, DEFAULT_COMPUTE_UNIT_LIMIT, DEFAULT_COMPUTE_UNIT_PRICE, DEFAULT_RPC_UNIT_LIMIT, DEFAULT_RPC_UNIT_PRICE, DEFAULT_SELL_TIP_FEE}, swqos::{SwqosClient, SwqosConfig, SwqosRegion}}; #[derive(Debug, Clone)] -pub struct Cluster { +pub struct TradeConfig { pub rpc_url: String, - pub block_engine_url: String, - pub nextblock_url: String, - pub nextblock_auth_token: String, - pub zeroslot_url: String, - pub zeroslot_auth_token: String, - pub nozomi_url: String, - pub nozomi_auth_token: String, - pub use_jito: bool, - pub use_nextblock: bool, - pub use_zeroslot: bool, - pub use_nozomi: bool, + pub swqos_configs: Vec, pub priority_fee: PriorityFee, pub commitment: CommitmentConfig, pub lookup_table_key: Option, pub use_rpc: bool, } -impl Cluster { +impl TradeConfig { pub fn new( rpc_url: String, - block_engine_url: - String, nextblock_url: - String, nextblock_auth_token: - String, zeroslot_url: String, - zeroslot_auth_token: String, - nozomi_url: String, - nozomi_auth_token: String, + swqos_configs: Vec, priority_fee: PriorityFee, commitment: CommitmentConfig, - use_jito: bool, - use_nextblock: bool, - use_zeroslot: bool, - use_nozomi: bool, lookup_table_key: Option, use_rpc: bool, ) -> Self { Self { rpc_url, - block_engine_url, - nextblock_url, - nextblock_auth_token, - zeroslot_url, - zeroslot_auth_token, - nozomi_url, - nozomi_auth_token, + swqos_configs, priority_fee, commitment, - use_jito, - use_nextblock, - use_zeroslot, - use_nozomi, lookup_table_key, use_rpc, } @@ -117,4 +78,3 @@ impl MethodArgs { } pub type AnyResult = anyhow::Result; - diff --git a/src/lib.rs b/src/lib.rs index e11202d..c939407 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,17 +22,18 @@ use solana_sdk::{ signature::{Keypair, Signer}, }; -use common::{pumpfun::logs_data::TradeInfo, pumpfun::logs_events::PumpfunEvent, pumpfun::logs_subscribe, Cluster, PriorityFee, SolanaRpcClient}; +use common::{pumpfun::logs_data::TradeInfo, pumpfun::logs_events::PumpfunEvent, pumpfun::logs_subscribe, TradeConfig, PriorityFee, SolanaRpcClient}; use common::pumpfun::logs_subscribe::SubscriptionHandle; use constants::trade_type::{COPY_BUY, SNIPER_BUY}; -use constants::trade_platform::{PUMPFUN, PUMPFUN_SWAP, RAYDIUM}; +use constants::trade_platform::{PUMPFUN, PUMPFUN_SWAP}; use accounts::BondingCurveAccount; +use crate::swqos::SwqosType; use crate::swqos::jito::JitoClient; use crate::swqos::nextblock::NextBlockClient; -use crate::swqos::nozomi::NozomiClient; use crate::swqos::solana_rpc::SolRpcClient; +use crate::swqos::temporal::TemporalClient; use crate::swqos::zeroslot::ZeroSlotClient; use crate::trading::core::params::PumpFunParams; use crate::trading::core::params::PumpFunSellParams; @@ -46,7 +47,7 @@ pub struct SolanaTrade { pub rpc: Arc, pub swqos_clients: Vec>, pub priority_fee: PriorityFee, - pub cluster: Cluster, + pub trade_config: TradeConfig, } static INSTANCE: Mutex>> = Mutex::new(None); @@ -58,7 +59,7 @@ impl Clone for SolanaTrade { rpc: self.rpc.clone(), swqos_clients: self.swqos_clients.clone(), priority_fee: self.priority_fee.clone(), - cluster: self.cluster.clone(), + trade_config: self.trade_config.clone(), } } } @@ -67,7 +68,7 @@ impl SolanaTrade { #[inline] pub async fn new( payer: Arc, - cluster: &Cluster, + trade_config: TradeConfig, ) -> Self { if CryptoProvider::get_default().is_none() { let _ = default_provider() @@ -75,62 +76,68 @@ impl SolanaTrade { .map_err(|e| anyhow::anyhow!("Failed to install crypto provider: {:?}", e)); } + let rpc_url = trade_config.rpc_url.clone(); + let swqos_configs = trade_config.swqos_configs.clone(); + let priority_fee = trade_config.priority_fee.clone(); + let commitment = trade_config.commitment.clone(); + let rpc = SolanaRpcClient::new_with_commitment( - cluster.clone().rpc_url, - cluster.clone().commitment + rpc_url.clone(), + commitment ); let rpc = Arc::new(rpc); + let mut swqos_clients: Vec> = vec![]; - if cluster.clone().use_jito { - let jito_client = JitoClient::new( - cluster.clone().rpc_url, - cluster.clone().block_engine_url - ).await.expect("Failed to create Jito client"); - swqos_clients.push(Arc::new(jito_client)); - } - - if cluster.clone().use_zeroslot { - let zeroslot_client = ZeroSlotClient::new( - cluster.clone().rpc_url, - cluster.clone().zeroslot_url, - cluster.clone().zeroslot_auth_token - ); - - swqos_clients.push(Arc::new(zeroslot_client)); - } - - if cluster.clone().use_nozomi { - let nozomi_client = NozomiClient::new( - cluster.clone().rpc_url, - cluster.clone().nozomi_url, - cluster.clone().nozomi_auth_token - ); - - swqos_clients.push(Arc::new(nozomi_client)); - } - - if cluster.clone().use_nextblock { - let nextblock_client = NextBlockClient::new( - cluster.clone().rpc_url, - cluster.clone().nextblock_url, - cluster.clone().nextblock_auth_token - ); - - swqos_clients.push(Arc::new(nextblock_client)); - } - - if cluster.clone().use_rpc { - let rpc_client = SolRpcClient::new(rpc.clone()); - swqos_clients.push(Arc::new(rpc_client)); + for swqos in swqos_configs { + match swqos.swqos_type { + SwqosType::Jito => { + let jito_client = JitoClient::new( + rpc_url.clone(), + swqos.endpoint, + ).await.expect("Failed to create Jito client"); + 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 instance = Self { payer, rpc, swqos_clients, - priority_fee: cluster.clone().priority_fee, - cluster: cluster.clone(), + priority_fee, + trade_config: trade_config.clone(), }; let mut current = INSTANCE.lock().unwrap(); @@ -168,7 +175,7 @@ impl SolanaTrade { buy_sol_cost, slippage_basis_points, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, bonding_curve, SNIPER_BUY.to_string(), @@ -194,7 +201,7 @@ impl SolanaTrade { buy_sol_cost, slippage_basis_points, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, bonding_curve, COPY_BUY.to_string(), @@ -208,7 +215,7 @@ impl SolanaTrade { buy_sol_cost, slippage_basis_points, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, None, None, @@ -249,7 +256,7 @@ impl SolanaTrade { buy_sol_cost, slippage_basis_points, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, protocol_params.bonding_curve.clone(), COPY_BUY.to_string(), @@ -266,7 +273,7 @@ impl SolanaTrade { buy_sol_cost, slippage_basis_points, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, protocol_params.pool.clone(), protocol_params.pool_base_token_account.clone(), @@ -304,7 +311,7 @@ impl SolanaTrade { buy_sol_cost, slippage_basis_points, priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, bonding_curve, SNIPER_BUY.to_string(), @@ -338,7 +345,7 @@ impl SolanaTrade { buy_sol_cost, slippage_basis_points, priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, protocol_params.bonding_curve.clone(), COPY_BUY.to_string(), @@ -356,7 +363,7 @@ impl SolanaTrade { buy_sol_cost, slippage_basis_points, priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, protocol_params.pool.clone(), protocol_params.pool_base_token_account.clone(), @@ -395,7 +402,7 @@ impl SolanaTrade { buy_sol_cost, slippage_basis_points, priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, bonding_curve, COPY_BUY.to_string(), @@ -410,7 +417,7 @@ impl SolanaTrade { buy_sol_cost, slippage_basis_points, priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, None, None, @@ -439,7 +446,7 @@ impl SolanaTrade { creator, amount_token, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, ).await } @@ -463,7 +470,7 @@ impl SolanaTrade { percent, amount_token, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, ).await } else if trade_platform == PUMPFUN_SWAP { @@ -475,7 +482,7 @@ impl SolanaTrade { percent, None, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, None, None, @@ -505,7 +512,7 @@ impl SolanaTrade { creator, amount, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, ).await } else if trade_platform == PUMPFUN_SWAP { @@ -517,7 +524,7 @@ impl SolanaTrade { amount, None, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, None, None, @@ -549,7 +556,7 @@ impl SolanaTrade { percent, amount_token, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, ).await } else if trade_platform == PUMPFUN_SWAP { @@ -562,7 +569,7 @@ impl SolanaTrade { percent, None, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, None, None, @@ -592,7 +599,7 @@ impl SolanaTrade { creator, amount, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, ).await } else if trade_platform == PUMPFUN_SWAP { @@ -605,7 +612,7 @@ impl SolanaTrade { amount, None, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, None, None, @@ -634,7 +641,7 @@ impl SolanaTrade { creator, amount_token, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, ).await } @@ -664,7 +671,7 @@ impl SolanaTrade { percent, amount_token.unwrap_or(0), self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, ).await } else if let Some(protocol_params) = sell_params @@ -679,7 +686,7 @@ impl SolanaTrade { percent, None, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, protocol_params.pool.clone(), protocol_params.pool_base_token_account.clone(), @@ -712,7 +719,7 @@ impl SolanaTrade { creator, amount.unwrap_or(0), self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, ).await } else if let Some(protocol_params) = sell_params @@ -727,7 +734,7 @@ impl SolanaTrade { amount.unwrap_or(0), None, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, protocol_params.pool.clone(), protocol_params.pool_base_token_account.clone(), @@ -762,7 +769,7 @@ impl SolanaTrade { percent, amount_token.unwrap_or(0), self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, ).await } else if let Some(protocol_params) = sell_params @@ -778,7 +785,7 @@ impl SolanaTrade { percent, sell_params.slippage_basis_points, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, protocol_params.pool.clone(), protocol_params.pool_base_token_account.clone(), @@ -811,7 +818,7 @@ impl SolanaTrade { creator, amount.unwrap_or(0), self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, ).await } else if let Some(protocol_params) = sell_params @@ -827,7 +834,7 @@ impl SolanaTrade { amount.unwrap_or(0), sell_params.slippage_basis_points, self.priority_fee.clone(), - self.cluster.clone().lookup_table_key, + self.trade_config.lookup_table_key, recent_blockhash, protocol_params.pool.clone(), protocol_params.pool_base_token_account.clone(), @@ -871,7 +878,7 @@ impl SolanaTrade { #[inline] pub async fn get_token_balance(&self, payer: &Pubkey, mint: &Pubkey) -> Result { - println!("get_token_balance payer: {}, mint: {}, cluster: {}", payer, mint, self.cluster.rpc_url); + println!("get_token_balance payer: {}, mint: {}, rpc_url: {}", payer, mint, self.trade_config.rpc_url); pumpfun::common::get_token_balance(&self.rpc, payer, mint).await } diff --git a/src/main.rs b/src/main.rs index 58f2a15..199a3f1 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,23 +1,8 @@ use std::{str::FromStr, sync::Arc}; -use sol_trade_sdk::{ - accounts::BondingCurveAccount, common::{ - pumpfun::{ - self, - logs_events::PumpfunEvent, - logs_subscribe::{stop_subscription, tokens_subscription}, TradeInfo, - }, - pumpswap::{self, PumpSwapEvent}, - raydium::{self, RaydiumEvent}, - AnyResult, Cluster, PriorityFee, - }, constants::pumpfun::global_constants::TOKEN_TOTAL_SUPPLY, grpc::{ShredStreamGrpc, YellowstoneGrpc}, pumpfun::common::get_bonding_curve_pda, SolanaTrade -}; +use sol_trade_sdk::{accounts::BondingCurveAccount, common::{pumpfun::PumpfunEvent, pumpswap::PumpSwapEvent, raydium::RaydiumEvent, AnyResult, PriorityFee, TradeConfig}, constants::pumpfun::global_constants::TOKEN_TOTAL_SUPPLY, grpc::{ShredStreamGrpc, YellowstoneGrpc}, pumpfun::common::get_bonding_curve_pda, swqos::{SwqosConfig, SwqosRegion, SwqosType}, SolanaTrade}; use solana_client::rpc_client::RpcClient; -use solana_hash::Hash; -use solana_sdk::{ - commitment_config::CommitmentConfig, pubkey::Pubkey, signature::Keypair, - transaction::VersionedTransaction, -}; +use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey, signature::Keypair}; #[tokio::main] async fn main() -> Result<(), Box> { @@ -259,31 +244,28 @@ 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(); + // Define cluster configuration - let cluster = Cluster { - rpc_url: "https://mainnet.helius-rpc.com/?api-key=f2f194bb-6bd6-4f20-9a94-7fe0799ade0b" - .to_string(), + let trade_config = TradeConfig { + rpc_url: rpc_url.clone(), commitment: CommitmentConfig::confirmed(), priority_fee: PriorityFee::default(), - use_jito: false, - use_zeroslot: false, - use_nozomi: false, - use_nextblock: false, - block_engine_url: "".to_string(), - zeroslot_url: "".to_string(), - zeroslot_auth_token: "".to_string(), - nozomi_url: "".to_string(), - nozomi_auth_token: "".to_string(), - nextblock_url: "".to_string(), - nextblock_auth_token: "".to_string(), + swqos_configs, lookup_table_key: None, use_rpc: true, }; - let solana_trade_client = SolanaTrade::new(Arc::new(payer), &cluster).await; + let solana_trade_client = SolanaTrade::new(Arc::new(payer), trade_config).await; let creator = Pubkey::from_str("xxx")?; // dev account let buy_sol_cost = 500_000; // 0.0005 SOL let slippage_basis_points = Some(100); - let rpc = RpcClient::new(cluster.rpc_url); + let rpc = RpcClient::new(rpc_url); let recent_blockhash = rpc.get_latest_blockhash().unwrap(); let mint_pubkey = Pubkey::from_str("xxx")?; // token mint println!("Sniping buy tokens from PumpFun..."); @@ -306,31 +288,30 @@ 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(); + // Define cluster configuration - let cluster = Cluster { - rpc_url: "https://mainnet.helius-rpc.com/?api-key=f2f194bb-6bd6-4f20-9a94-7fe0799ade0b" - .to_string(), + let trade_config = TradeConfig { + rpc_url: rpc_url.clone(), commitment: CommitmentConfig::confirmed(), priority_fee: PriorityFee::default(), - use_jito: false, - use_zeroslot: false, - use_nozomi: false, - use_nextblock: false, - block_engine_url: "".to_string(), - zeroslot_url: "".to_string(), - zeroslot_auth_token: "".to_string(), - nozomi_url: "".to_string(), - nozomi_auth_token: "".to_string(), - nextblock_url: "".to_string(), - nextblock_auth_token: "".to_string(), + swqos_configs, lookup_table_key: None, use_rpc: true, }; - let solana_trade_client = SolanaTrade::new(Arc::new(payer), &cluster).await; + + let solana_trade_client = SolanaTrade::new(Arc::new(payer), trade_config).await; let creator = Pubkey::from_str("xxx")?; // dev account let buy_sol_cost = 500_000; // 0.0005 SOL let slippage_basis_points = Some(100); - let rpc = RpcClient::new(cluster.rpc_url); + let rpc = RpcClient::new(rpc_url); let recent_blockhash = rpc.get_latest_blockhash().unwrap(); let trade_platform = "pumpfun".to_string(); let mint_pubkey = Pubkey::from_str("xxx")?; // token mint @@ -379,31 +360,29 @@ 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(); + // Define cluster configuration - let cluster = Cluster { - rpc_url: "https://mainnet.helius-rpc.com/?api-key=f2f194bb-6bd6-4f20-9a94-7fe0799ade0b" - .to_string(), + let trade_config = TradeConfig { + rpc_url: rpc_url.clone(), commitment: CommitmentConfig::confirmed(), priority_fee: PriorityFee::default(), - use_jito: false, - use_zeroslot: false, - use_nozomi: false, - use_nextblock: false, - block_engine_url: "".to_string(), - zeroslot_url: "".to_string(), - zeroslot_auth_token: "".to_string(), - nozomi_url: "".to_string(), - nozomi_auth_token: "".to_string(), - nextblock_url: "".to_string(), - nextblock_auth_token: "".to_string(), + swqos_configs, lookup_table_key: None, use_rpc: true, }; - let solana_trade_client = SolanaTrade::new(Arc::new(payer), &cluster).await; + let solana_trade_client = SolanaTrade::new(Arc::new(payer), trade_config).await; let creator = Pubkey::from_str("11111111111111111111111111111111")?; // dev account let buy_sol_cost = 500_000; // 0.0005 SOL let slippage_basis_points = Some(100); - let rpc = RpcClient::new(cluster.rpc_url); + let rpc = RpcClient::new(rpc_url); let recent_blockhash = rpc.get_latest_blockhash().unwrap(); let trade_platform = "pumpswap".to_string(); let mint_pubkey = Pubkey::from_str("2zMMhcVQEXDtdE6vsFS7S7D5oUodfJHE8vd1gnBouauv")?; // token mint diff --git a/src/swqos/define.rs b/src/swqos/define.rs new file mode 100755 index 0000000..46e3134 --- /dev/null +++ b/src/swqos/define.rs @@ -0,0 +1,23 @@ +pub const SWQOS_ENDPOINTS_JITO: [&str; 3] = [ + "https://ny.mainnet.block-engine.jito.wtf/api/v1/bundles", + "https://ams.block-engine.jito.wtf/api/v1/bundles", + "https://frankfurt.mainnet.block-engine.jito.wtf/api/v1/bundles", +]; + +pub const SWQOS_ENDPOINTS_NEXTBLOCK: [&str; 3] = [ + "https://fra.nextblock.io", + "https://ams.nextblock.io", + "https://ny.nextblock.io", +]; + +pub const SWQOS_ENDPOINTS_ZERO_SLOT: [&str; 3] = [ + "http://de1.0slot.trade", + "http://ams.0slot.trade", + "http://ny.0slot.trade", +]; + +pub const SWQOS_ENDPOINTS_TEMPORAL: [&str; 3] = [ + "http://fra2.nozomi.temporal.xyz", + "http://ams2.nozomi.temporal.xyz", + "http://ny2.nozomi.temporal.xyz", +]; \ No newline at end of file diff --git a/src/swqos/jito.rs b/src/swqos/jito.rs index f46cd2b..d66c341 100755 --- a/src/swqos/jito.rs +++ b/src/swqos/jito.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use solana_sdk::{transaction::VersionedTransaction, signature::Signature}; use crate::protos::searcher::searcher_service_client::SearcherServiceClient; use crate::protos::searcher_client::{self, get_searcher_client_no_auth, send_bundle_with_confirmation}; -use crate::swqos::{ClientType, TradeType}; +use crate::swqos::{SwqosType, TradeType}; use crate::swqos::SwqosClientTrait; use crate::{common::SolanaRpcClient, constants::pumpfun::accounts::JITO_TIP_ACCOUNTS}; @@ -37,8 +37,8 @@ impl SwqosClientTrait for JitoClient { } } - fn get_client_type(&self) -> ClientType { - ClientType::Jito + fn get_swqos_type(&self) -> SwqosType { + SwqosType::Jito } } diff --git a/src/swqos/mod.rs b/src/swqos/mod.rs index 9adc709..f1b79c2 100755 --- a/src/swqos/mod.rs +++ b/src/swqos/mod.rs @@ -4,8 +4,8 @@ pub mod solana_rpc; pub mod jito; pub mod nextblock; pub mod zeroslot; -pub mod nozomi; -pub mod types; +pub mod temporal; +pub mod define; use solana_sdk::signature::Signature; use solana_sdk::transaction::VersionedTransaction; @@ -13,6 +13,8 @@ use tokio::sync::RwLock; use anyhow::Result; +use crate::swqos::define::{SWQOS_ENDPOINTS_JITO, SWQOS_ENDPOINTS_NEXTBLOCK, SWQOS_ENDPOINTS_TEMPORAL, SWQOS_ENDPOINTS_ZERO_SLOT}; + lazy_static::lazy_static! { static ref TIP_ACCOUNT_CACHE: RwLock> = RwLock::new(Vec::new()); } @@ -37,12 +39,12 @@ impl std::fmt::Display for TradeType { } } -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum ClientType { +#[derive(Debug, Clone, PartialEq)] +pub enum SwqosType { Jito, NextBlock, ZeroSlot, - Nozomi, + Temporal, Rpc, } @@ -53,5 +55,35 @@ pub trait SwqosClientTrait { async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction) -> Result; async fn send_transactions(&self, trade_type: TradeType, transactions: &Vec) -> Result>; fn get_tip_account(&self) -> Result; - fn get_client_type(&self) -> ClientType; + fn get_swqos_type(&self) -> SwqosType; +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum SwqosRegion { + NewYork, + Amsterdam, + Frankfurt, +} + +#[derive(Debug, Clone)] +pub struct SwqosConfig { + pub endpoint: String, + pub auth_token: String, + pub swqos_type: SwqosType, +} + +impl SwqosConfig { + pub fn new(endpoint: Option, auth_token: Option, swqos_type: SwqosType, region: SwqosRegion) -> Self { + let endpoint = endpoint.unwrap_or_else(|| 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::Rpc => "".to_string(), + }); + + let auth_token = auth_token.unwrap(); + + Self { endpoint, auth_token, swqos_type } + } } \ No newline at end of file diff --git a/src/swqos/nextblock.rs b/src/swqos/nextblock.rs index ba990fd..ca4b830 100755 --- a/src/swqos/nextblock.rs +++ b/src/swqos/nextblock.rs @@ -18,7 +18,7 @@ use tonic::transport::ClientTlsConfig; use anyhow::Result; use solana_sdk::transaction::VersionedTransaction; -use crate::swqos::{ClientType, TradeType}; +use crate::swqos::{SwqosType, TradeType}; use crate::swqos::SwqosClientTrait; use crate::{common::SolanaRpcClient, constants::pumpfun::accounts::NEXTBLOCK_TIP_ACCOUNTS}; @@ -67,8 +67,8 @@ impl SwqosClientTrait for NextBlockClient { Ok(tip_account.to_string()) } - fn get_client_type(&self) -> ClientType { - ClientType::NextBlock + fn get_swqos_type(&self) -> SwqosType { + SwqosType::NextBlock } } diff --git a/src/swqos/solana_rpc.rs b/src/swqos/solana_rpc.rs index c282439..ede0fd5 100755 --- a/src/swqos/solana_rpc.rs +++ b/src/swqos/solana_rpc.rs @@ -8,7 +8,7 @@ use solana_sdk::{ }; use solana_transaction_status::UiTransactionEncoding; -use crate::{common::SolanaRpcClient, swqos::{common::poll_transaction_confirmation, ClientType, TradeType}}; +use crate::{common::SolanaRpcClient, swqos::{common::poll_transaction_confirmation, SwqosType, TradeType}}; use crate::swqos::SwqosClientTrait; use anyhow::Result; @@ -52,8 +52,8 @@ impl SwqosClientTrait for SolRpcClient { Ok("".to_string()) } - fn get_client_type(&self) -> ClientType { - ClientType::Rpc + fn get_swqos_type(&self) -> SwqosType { + SwqosType::Rpc } } diff --git a/src/swqos/nozomi.rs b/src/swqos/temporal.rs similarity index 95% rename from src/swqos/nozomi.rs rename to src/swqos/temporal.rs index 062d7c8..088c7e2 100755 --- a/src/swqos/nozomi.rs +++ b/src/swqos/temporal.rs @@ -12,14 +12,14 @@ use solana_transaction_status::UiTransactionEncoding; use anyhow::Result; use solana_sdk::transaction::VersionedTransaction; -use crate::swqos::{ClientType, TradeType}; +use crate::swqos::{SwqosType, TradeType}; use crate::swqos::SwqosClientTrait; use crate::{common::SolanaRpcClient, constants::pumpfun::accounts::NOZOMI_TIP_ACCOUNTS}; #[derive(Clone)] -pub struct NozomiClient { +pub struct TemporalClient { pub rpc_client: Arc, pub endpoint: String, pub auth_token: String, @@ -27,7 +27,7 @@ pub struct NozomiClient { } #[async_trait::async_trait] -impl SwqosClientTrait for NozomiClient { +impl SwqosClientTrait for TemporalClient { async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction) -> Result { self.send_transaction(trade_type, transaction).await } @@ -41,12 +41,12 @@ impl SwqosClientTrait for NozomiClient { Ok(tip_account.to_string()) } - fn get_client_type(&self) -> ClientType { - ClientType::Nozomi + fn get_swqos_type(&self) -> SwqosType { + SwqosType::Temporal } } -impl NozomiClient { +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() diff --git a/src/swqos/types.rs b/src/swqos/types.rs deleted file mode 100755 index e69de29..0000000 diff --git a/src/swqos/zeroslot.rs b/src/swqos/zeroslot.rs index f98e0e5..6dbde85 100755 --- a/src/swqos/zeroslot.rs +++ b/src/swqos/zeroslot.rs @@ -10,7 +10,7 @@ use solana_transaction_status::UiTransactionEncoding; use anyhow::Result; use solana_sdk::signature::Signature; use solana_sdk::transaction::VersionedTransaction; -use crate::swqos::{ClientType, TradeType}; +use crate::swqos::{SwqosType, TradeType}; use crate::swqos::SwqosClientTrait; use crate::{common::SolanaRpcClient, constants::pumpfun::accounts::ZEROSLOT_TIP_ACCOUNTS}; @@ -39,8 +39,8 @@ impl SwqosClientTrait for ZeroSlotClient { Ok(tip_account.to_string()) } - fn get_client_type(&self) -> ClientType { - ClientType::ZeroSlot + fn get_swqos_type(&self) -> SwqosType { + SwqosType::ZeroSlot } } diff --git a/src/trading/core/parallel.rs b/src/trading/core/parallel.rs index dbd2bb6..e2b7060 100755 --- a/src/trading/core/parallel.rs +++ b/src/trading/core/parallel.rs @@ -6,7 +6,7 @@ use tokio::task::JoinHandle; use crate::{ common::PriorityFee, - swqos::{ClientType, SwqosClient, TradeType}, + swqos::{SwqosType, SwqosClient, TradeType}, trading::common::{ build_rpc_transaction, build_sell_tip_transaction_with_priority_fee, build_sell_transaction, build_tip_transaction_with_priority_fee, @@ -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_client_type() == ClientType::Rpc + && swqos_client.get_swqos_type() == SwqosType::Rpc { 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_client_type() != ClientType::Rpc + && swqos_client.get_swqos_type() != SwqosType::Rpc { 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_client_type() == ClientType::Rpc { + } else if swqos_client.get_swqos_type() == SwqosType::Rpc { build_rpc_transaction( payer, &priority_fee,