2025-04-02 13:39:59 +08:00
|
|
|
pub mod common;
|
2025-07-06 22:06:44 +08:00
|
|
|
pub mod solana_rpc;
|
|
|
|
|
pub mod jito;
|
|
|
|
|
pub mod nextblock;
|
|
|
|
|
pub mod zeroslot;
|
2025-07-06 23:36:18 +08:00
|
|
|
pub mod temporal;
|
2025-07-07 02:06:52 +08:00
|
|
|
pub mod bloxroute;
|
2025-07-06 22:06:44 +08:00
|
|
|
|
2025-07-07 03:28:02 +08:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
|
|
use solana_sdk::{commitment_config::CommitmentConfig, transaction::VersionedTransaction};
|
2025-07-06 22:06:44 +08:00
|
|
|
use tokio::sync::RwLock;
|
|
|
|
|
|
|
|
|
|
use anyhow::Result;
|
2025-02-13 20:44:20 +08:00
|
|
|
|
2025-07-07 03:28:02 +08:00
|
|
|
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}};
|
2025-07-06 23:36:18 +08:00
|
|
|
|
2025-04-02 13:39:59 +08:00
|
|
|
lazy_static::lazy_static! {
|
|
|
|
|
static ref TIP_ACCOUNT_CACHE: RwLock<Vec<String>> = RwLock::new(Vec::new());
|
2025-01-14 19:18:48 +08:00
|
|
|
}
|
|
|
|
|
|
2025-04-02 13:39:59 +08:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
2025-05-29 18:53:58 +08:00
|
|
|
pub enum TradeType {
|
|
|
|
|
Create,
|
|
|
|
|
CreateAndBuy,
|
|
|
|
|
Buy,
|
|
|
|
|
Sell,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Display for TradeType {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
let s = match self {
|
|
|
|
|
TradeType::Create => "创建",
|
|
|
|
|
TradeType::CreateAndBuy => "创建并买入",
|
|
|
|
|
TradeType::Buy => "买入",
|
|
|
|
|
TradeType::Sell => "卖出",
|
|
|
|
|
};
|
|
|
|
|
write!(f, "{}", s)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-06 23:36:18 +08:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
|
pub enum SwqosType {
|
2025-04-02 13:39:59 +08:00
|
|
|
Jito,
|
|
|
|
|
NextBlock,
|
|
|
|
|
ZeroSlot,
|
2025-07-06 23:36:18 +08:00
|
|
|
Temporal,
|
2025-07-07 02:06:52 +08:00
|
|
|
Bloxroute,
|
2025-07-07 03:28:02 +08:00
|
|
|
Default,
|
2025-04-02 13:39:59 +08:00
|
|
|
}
|
|
|
|
|
|
2025-07-06 22:06:44 +08:00
|
|
|
pub type SwqosClient = dyn SwqosClientTrait + Send + Sync + 'static;
|
2025-04-02 13:39:59 +08:00
|
|
|
|
|
|
|
|
#[async_trait::async_trait]
|
2025-07-06 22:06:44 +08:00
|
|
|
pub trait SwqosClientTrait {
|
2025-07-07 01:01:38 +08:00
|
|
|
async fn send_transaction(&self, trade_type: TradeType, transaction: &VersionedTransaction) -> Result<()>;
|
|
|
|
|
async fn send_transactions(&self, trade_type: TradeType, transactions: &Vec<VersionedTransaction>) -> Result<()>;
|
2025-05-29 18:53:58 +08:00
|
|
|
fn get_tip_account(&self) -> Result<String>;
|
2025-07-06 23:36:18 +08:00
|
|
|
fn get_swqos_type(&self) -> SwqosType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
|
pub enum SwqosRegion {
|
|
|
|
|
NewYork,
|
|
|
|
|
Frankfurt,
|
2025-07-07 01:19:12 +08:00
|
|
|
Amsterdam,
|
|
|
|
|
SLC,
|
|
|
|
|
Tokyo,
|
|
|
|
|
London,
|
|
|
|
|
LosAngeles,
|
|
|
|
|
Default,
|
2025-07-06 23:36:18 +08:00
|
|
|
}
|
|
|
|
|
|
2025-07-07 03:28:02 +08:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
|
pub enum SwqosConfig {
|
|
|
|
|
Default(String),
|
2025-08-04 21:11:06 +08:00
|
|
|
Jito(String, SwqosRegion),
|
2025-07-07 03:28:02 +08:00
|
|
|
NextBlock(String, SwqosRegion),
|
|
|
|
|
Bloxroute(String, SwqosRegion),
|
|
|
|
|
Temporal(String, SwqosRegion),
|
|
|
|
|
ZeroSlot(String, SwqosRegion),
|
2025-07-06 23:36:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl SwqosConfig {
|
2025-07-07 03:28:02 +08:00
|
|
|
pub fn get_endpoint(swqos_type: SwqosType, region: SwqosRegion) -> String {
|
|
|
|
|
match swqos_type {
|
2025-07-06 23:36:18 +08:00
|
|
|
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(),
|
2025-07-07 02:06:52 +08:00
|
|
|
SwqosType::Bloxroute => SWQOS_ENDPOINTS_BLOX[region as usize].to_string(),
|
2025-07-07 03:28:02 +08:00
|
|
|
SwqosType::Default => "".to_string(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-06 23:36:18 +08:00
|
|
|
|
2025-07-07 03:28:02 +08:00
|
|
|
pub fn get_swqos_client(rpc_url: String, commitment: CommitmentConfig, swqos_config: SwqosConfig) -> Arc<SwqosClient> {
|
|
|
|
|
match swqos_config {
|
2025-08-04 21:11:06 +08:00
|
|
|
SwqosConfig::Jito(auth_token, region) => {
|
2025-07-07 03:28:02 +08:00
|
|
|
let endpoint = SwqosConfig::get_endpoint(SwqosType::Jito, region);
|
|
|
|
|
let jito_client = JitoClient::new(
|
|
|
|
|
rpc_url.clone(),
|
|
|
|
|
endpoint,
|
2025-08-04 21:11:06 +08:00
|
|
|
auth_token
|
2025-07-07 03:28:02 +08:00
|
|
|
);
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-06 23:36:18 +08:00
|
|
|
}
|
2025-04-02 13:39:59 +08:00
|
|
|
}
|