update trade config and swqos

This commit is contained in:
wood
2025-07-06 23:36:18 +08:00
parent ecbdbc5890
commit d13c382a46
12 changed files with 220 additions and 219 deletions
+6 -46
View File
@@ -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<SwqosConfig>,
pub priority_fee: PriorityFee,
pub commitment: CommitmentConfig,
pub lookup_table_key: Option<Pubkey>,
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<SwqosConfig>,
priority_fee: PriorityFee,
commitment: CommitmentConfig,
use_jito: bool,
use_nextblock: bool,
use_zeroslot: bool,
use_nozomi: bool,
lookup_table_key: Option<Pubkey>,
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<T> = anyhow::Result<T>;
+87 -80
View File
@@ -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<SolanaRpcClient>,
pub swqos_clients: Vec<Arc<SwqosClient>>,
pub priority_fee: PriorityFee,
pub cluster: Cluster,
pub trade_config: TradeConfig,
}
static INSTANCE: Mutex<Option<Arc<SolanaTrade>>> = 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<Keypair>,
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<Arc<SwqosClient>> = 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<u64, anyhow::Error> {
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
}
+44 -65
View File
@@ -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<dyn std::error::Error>> {
@@ -259,31 +244,28 @@ async fn test_raydium_with_grpc() -> Result<(), Box<dyn std::error::Error>> {
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
+23
View File
@@ -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",
];
+3 -3
View File
@@ -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
}
}
+38 -6
View File
@@ -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<Vec<String>> = 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<Signature>;
async fn send_transactions(&self, trade_type: TradeType, transactions: &Vec<VersionedTransaction>) -> Result<Vec<Signature>>;
fn get_tip_account(&self) -> Result<String>;
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<String>, auth_token: Option<String>, 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 }
}
}
+3 -3
View File
@@ -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
}
}
+3 -3
View File
@@ -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
}
}
@@ -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<SolanaRpcClient>,
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<Signature> {
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()
View File
+3 -3
View File
@@ -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
}
}
+4 -4
View File
@@ -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,