1use log::info;
2use rand::rngs::ThreadRng;
3use rand::thread_rng;
4use rand::Rng;
5use serde::Deserialize;
6use serde_json::json;
7use solana_sdk::pubkey::Pubkey;
8use solana_sdk::transaction::Transaction;
9use solana_transaction_status::{
10 Encodable, EncodedTransaction, UiTransactionEncoding,
11};
12use std::cell::RefCell;
13use std::str::FromStr;
14
15#[derive(Debug, Deserialize)]
16pub struct JitoResponse {
17 pub jsonrpc: String,
18 pub result: String,
19 pub id: i64,
20}
21
22#[timed::timed(duration(printer = "info!"))]
24pub async fn send_jito_tx(
25 tx: Transaction,
26) -> Result<String, Box<dyn std::error::Error>> {
27 let client = reqwest::Client::new();
28
29 let encoded_tx = match tx.encode(UiTransactionEncoding::Binary) {
30 EncodedTransaction::LegacyBinary(b) => b,
31 _ => return Err("Failed to encode transaction".into()),
32 };
33
34 let res = client
35 .post("https://mainnet.block-engine.jito.wtf/api/v1/transactions")
36 .header("content-type", "application/json")
37 .json(&json!({
38 "jsonrpc": "2.0",
39 "id": 1,
40 "method": "sendTransaction",
41 "params": [encoded_tx]
42 }))
43 .send()
44 .await
45 .expect("send tx");
46
47 let jito_response = res.json::<JitoResponse>().await?;
48
49 Ok(jito_response.result)
50}
51
52thread_local! {
53 static RNG: RefCell<ThreadRng> = RefCell::new(thread_rng());
54}
55
56#[inline(always)]
57pub fn fast_random_0_to_7() -> u8 {
58 RNG.with(|rng| rng.borrow_mut().gen_range(0..8))
59}
60
61pub fn get_jito_tip_pubkey() -> Pubkey {
62 const PUBKEYS: [&str; 8] = [
63 "96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
64 "HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe",
65 "Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY",
66 "ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49",
67 "DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh",
68 "ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt",
69 "DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL",
70 "3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT",
71 ];
72 let index = fast_random_0_to_7();
73 Pubkey::from_str(PUBKEYS[index as usize]).expect("parse tip pubkey")
74}
75
76#[cfg(test)]
77mod tests {
78 #[test]
79 fn bench_get_jito_tip_pubkey() {
80 for _ in 0..100 {
81 let start = std::time::Instant::now();
82 let _ = super::get_jito_tip_pubkey();
83 let elapsed = start.elapsed();
84 println!("elapsed: {:?}", elapsed);
85 }
86 }
87}