Files
sol-trade-sdk/src/jito/mod.rs
T

106 lines
3.1 KiB
Rust
Raw Normal View History

2025-02-15 18:53:17 +08:00
use std::str::FromStr;
2025-01-14 19:18:48 +08:00
2025-02-12 20:12:14 +08:00
use anyhow::{anyhow, Result};
2025-02-12 22:46:09 +08:00
use api::TipAccountResult;
2025-02-15 18:53:17 +08:00
use rand::seq::IteratorRandom;
2025-02-13 20:44:20 +08:00
use solana_sdk::{
pubkey::Pubkey,
transaction::{Transaction, VersionedTransaction},
2025-01-03 14:43:26 +08:00
};
2025-02-13 20:44:20 +08:00
use tokio::sync::RwLock;
use tracing::error;
2025-01-08 16:33:43 +08:00
2025-02-12 20:12:14 +08:00
pub mod api;
2025-02-13 20:44:20 +08:00
pub mod client_error;
pub mod http_sender;
pub mod request;
pub mod rpc_client;
pub mod rpc_sender;
use crate::jito::rpc_client::RpcClient;
2025-02-12 20:12:14 +08:00
2025-01-03 14:43:26 +08:00
pub struct JitoClient {
2025-01-14 19:18:48 +08:00
base_url: String,
2025-02-12 20:12:14 +08:00
tip_accounts: RwLock<Vec<String>>,
2025-02-13 20:44:20 +08:00
client: RpcClient,
2025-01-14 19:18:48 +08:00
}
2025-02-12 20:12:14 +08:00
impl Clone for JitoClient {
fn clone(&self) -> Self {
Self {
base_url: self.base_url.clone(),
tip_accounts: RwLock::new(Vec::new()),
2025-02-13 20:44:20 +08:00
client: RpcClient::new(self.base_url.clone()),
2025-02-12 20:12:14 +08:00
}
}
}
2025-01-03 14:43:26 +08:00
impl JitoClient {
2025-02-15 18:53:17 +08:00
pub fn new(jito_url: &str, _uuid: Option<String>) -> Self {
2025-01-03 14:43:26 +08:00
Self {
2025-02-13 20:44:20 +08:00
base_url: jito_url.to_string(),
2025-02-12 20:12:14 +08:00
tip_accounts: RwLock::new(vec![]),
2025-02-13 20:44:20 +08:00
client: RpcClient::new(jito_url.to_string()),
2025-01-03 14:43:26 +08:00
}
}
2025-02-12 22:46:09 +08:00
pub async fn get_tip_accounts(&self) -> Result<TipAccountResult> {
2025-02-13 20:44:20 +08:00
let result = self.client.get_tip_accounts().await?;
2025-02-15 18:53:17 +08:00
TipAccountResult::from(result).map_err(|e| anyhow!(e))
2025-02-12 22:46:09 +08:00
}
2025-02-12 20:12:14 +08:00
pub async fn init_tip_accounts(&self) -> Result<()> {
2025-02-12 22:46:09 +08:00
let accounts = self.get_tip_accounts().await?;
2025-02-12 20:12:14 +08:00
let mut tip_accounts = self.tip_accounts.write().await;
2025-02-15 18:53:17 +08:00
*tip_accounts = accounts.accounts.iter().map(|a| a.to_string()).collect();
2025-02-12 20:12:14 +08:00
Ok(())
2025-01-14 19:18:48 +08:00
}
2025-02-12 20:12:14 +08:00
pub async fn get_tip_account(&self) -> Result<Pubkey> {
{
let accounts = self.tip_accounts.read().await;
if !accounts.is_empty() {
2025-02-21 20:47:28 +08:00
if let Some(acc) = accounts.iter().choose(&mut rand::rng()) {
2025-02-15 18:53:17 +08:00
return Pubkey::from_str(acc)
.map_err(|err| {
error!("jito: failed to parse Pubkey: {:?}", err);
anyhow!("Invalid pubkey format")
});
2025-02-12 20:12:14 +08:00
}
}
2025-02-13 20:44:20 +08:00
}
2025-01-14 19:18:48 +08:00
2025-02-12 20:12:14 +08:00
self.init_tip_accounts().await?;
let accounts = self.tip_accounts.read().await;
2025-02-15 18:53:17 +08:00
accounts
.iter()
.choose(&mut rand::rng())
.ok_or_else(|| anyhow!("jito: no tip accounts available"))
.and_then(|acc| {
Pubkey::from_str(acc).map_err(|err| {
error!("jito: failed to parse Pubkey: {:?}", err);
anyhow!("Invalid pubkey format")
})
})
2025-01-14 19:18:48 +08:00
}
2025-01-03 14:43:26 +08:00
pub async fn send_transaction(
&self,
transaction: &Transaction,
2025-02-12 22:46:09 +08:00
) -> Result<String, anyhow::Error> {
2025-02-13 20:44:20 +08:00
let bundles = vec![VersionedTransaction::from(transaction.clone())];
Ok(self.client.send_bundle(&bundles).await?)
2025-02-12 20:12:14 +08:00
}
2025-02-16 14:21:42 +08:00
pub async fn send_transactions(
&self,
transactions: &Vec<Transaction>,
) -> Result<String, anyhow::Error> {
let bundles: Vec<VersionedTransaction> = transactions.iter()
.map(|t| VersionedTransaction::from(t.clone()))
.collect(); // 显式指定类型
Ok(self.client.send_bundle(&bundles).await?)
}
2025-02-12 20:12:14 +08:00
}