Created
April 6, 2024 02:29
-
-
Save adilcpm/4b142929ad17d4348d4b62f7cf90e45d to your computer and use it in GitHub Desktop.
send modified with jito
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use reqwest::Client; | |
use serde_json::json; | |
use solana_client::{ | |
client_error::{ClientError, ClientErrorKind, Result as ClientResult}, | |
nonblocking::rpc_client::RpcClient, | |
rpc_config::RpcSimulateTransactionConfig, | |
}; | |
use solana_program::instruction::Instruction; | |
use solana_sdk::{ | |
commitment_config::CommitmentConfig, | |
compute_budget::ComputeBudgetInstruction, | |
signature::{Signature, Signer}, | |
transaction::Transaction, | |
}; | |
use solana_transaction_status::{TransactionConfirmationStatus, UiTransactionEncoding}; | |
use std::{ | |
io::{stdout, Write}, | |
str::FromStr, | |
time::Duration, | |
}; | |
use crate::Miner; | |
use base64; // Add this line to import the base64 crate | |
const RPC_RETRIES: usize = 0; | |
const GATEWAY_RETRIES: usize = 4; | |
const CONFIRM_RETRIES: usize = 4; | |
impl Miner { | |
pub async fn send_and_confirm( | |
&self, | |
ixs: &[Instruction], | |
dynamic_cus: bool, | |
skip_confirm: bool, | |
) -> ClientResult<Signature> { | |
let mut stdout = stdout(); | |
let signer = self.signer(); | |
let client = | |
RpcClient::new_with_commitment(self.cluster.clone(), CommitmentConfig::confirmed()); | |
let jito_rpc_url = "https://mainnet.block-engine.jito.wtf/api/v1/transactions"; | |
// Return error if balance is zero | |
let balance = client | |
.get_balance_with_commitment(&signer.pubkey(), CommitmentConfig::confirmed()) | |
.await | |
.unwrap(); | |
if balance.value <= 0 { | |
return Err(ClientError { | |
request: None, | |
kind: ClientErrorKind::Custom("Insufficient SOL balance".into()), | |
}); | |
} | |
// Build tx | |
let (mut hash, mut slot) = client | |
.get_latest_blockhash_with_commitment(CommitmentConfig::confirmed()) | |
.await | |
.unwrap(); | |
// let mut send_cfg = RpcSendTransactionConfig { | |
// skip_preflight: true, | |
// preflight_commitment: Some(CommitmentLevel::Confirmed), | |
// encoding: Some(UiTransactionEncoding::Base64), | |
// max_retries: Some(RPC_RETRIES), | |
// min_context_slot: Some(slot), | |
// }; | |
let mut tx = Transaction::new_with_payer(ixs, Some(&signer.pubkey())); | |
// Simulate if necessary | |
if dynamic_cus { | |
let sim_res = client | |
.simulate_transaction_with_config( | |
&tx, | |
RpcSimulateTransactionConfig { | |
sig_verify: false, | |
replace_recent_blockhash: false, | |
commitment: Some(CommitmentConfig::confirmed()), | |
encoding: Some(UiTransactionEncoding::Base64), | |
accounts: None, | |
min_context_slot: Some(slot), | |
inner_instructions: false, | |
}, | |
) | |
.await; | |
if let Ok(sim_res) = sim_res { | |
if let Some(units_consumed) = sim_res.value.units_consumed { | |
let cu_budget_ix = ComputeBudgetInstruction::set_compute_unit_limit( | |
units_consumed as u32 + 1000, | |
); | |
let cu_price_ix = | |
ComputeBudgetInstruction::set_compute_unit_price(self.priority_fee); | |
let mut final_ixs = vec![]; | |
final_ixs.extend_from_slice(&[cu_budget_ix, cu_price_ix]); | |
final_ixs.extend_from_slice(ixs); | |
tx = Transaction::new_with_payer(&final_ixs, Some(&signer.pubkey())); | |
} | |
} | |
} | |
// Submit tx | |
tx.sign(&[&signer], hash); | |
let mut sigs = vec![]; | |
let mut attempts = 0; | |
loop { | |
println!("Attempt: {:?}", attempts); | |
let tx_base64 = base64::encode(bincode::serialize(&tx).unwrap()); | |
// Create a reqwest client | |
let http_client = Client::new(); | |
// Send the transaction | |
let response = http_client | |
.post(jito_rpc_url) | |
.header("Content-Type", "application/json") | |
.json(&json!({ | |
"jsonrpc": "2.0", | |
"id": 4141, | |
"method": "sendTransaction", | |
"params": [tx_base64, { | |
"encoding": "base64", | |
"commitment": "confirmed", | |
"skipPreflight": true, | |
"preflightCommitment": "confirmed", | |
"maxRetries": RPC_RETRIES, | |
"minContextSlot": slot, | |
}], | |
"bundleOnly": true, | |
})) | |
.send() | |
.await?; | |
match response.status().is_success() { | |
true => { | |
let response_json: serde_json::Value = response.json().await?; | |
let sig = | |
Signature::from_str(response_json["result"].as_str().unwrap()).unwrap(); | |
sigs.push(sig); | |
println!("{:?}", sig); | |
// Confirm tx | |
if skip_confirm { | |
return Ok(sig); | |
} | |
for _ in 0..CONFIRM_RETRIES { | |
std::thread::sleep(Duration::from_millis(2000)); | |
match client.get_signature_statuses(&sigs).await { | |
Ok(signature_statuses) => { | |
println!("Confirms: {:?}", signature_statuses.value); | |
for signature_status in signature_statuses.value { | |
if let Some(signature_status) = signature_status.as_ref() { | |
if signature_status.confirmation_status.is_some() { | |
let current_commitment = signature_status | |
.confirmation_status | |
.as_ref() | |
.unwrap(); | |
match current_commitment { | |
TransactionConfirmationStatus::Processed => {} | |
TransactionConfirmationStatus::Confirmed | |
| TransactionConfirmationStatus::Finalized => { | |
println!("Transaction landed!"); | |
return Ok(sig); | |
} | |
} | |
} else { | |
println!("No status"); | |
} | |
} | |
} | |
} | |
// Handle confirmation errors | |
Err(err) => { | |
println!("Error: {:?}", err); | |
} | |
} | |
} | |
println!("Transaction did not land"); | |
} | |
// Handle submit errors | |
false => { | |
println!("Error {:?}", response.status()); | |
} | |
} | |
stdout.flush().ok(); | |
// Retry | |
std::thread::sleep(Duration::from_millis(2000)); | |
(hash, slot) = client | |
.get_latest_blockhash_with_commitment(CommitmentConfig::confirmed()) | |
.await | |
.unwrap(); | |
tx.sign(&[&signer], hash); | |
attempts += 1; | |
if attempts > GATEWAY_RETRIES { | |
return Err(ClientError { | |
request: None, | |
kind: ClientErrorKind::Custom("Max retries".into()), | |
}); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment