diff --git a/README.md b/README.md index ca1ba57..e595060 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ To run the basic transaction example: ```rust // Load the sender's keypair - let sender = load_keypair("/path/to/wallet.json")?; + let sender = Keypair::read_from_file(("/path/to/wallet.json").expect("Failed to read wallet file"); // Set up receiver pubkey let receiver = Pubkey::from_str("YOUR_RECEIVER_PUBKEY")?; @@ -79,7 +79,7 @@ To run the basic bundle example: ```rust // Load the sender's keypair - let sender = load_keypair("/path/to/wallet.json")?; + let sender = Keypair::read_from_file(("/path/to/wallet.json").expect("Failed to read wallet file"); // Set up receiver pubkey let receiver = Pubkey::from_str("YOUR_RECEIVER_PUBKEY")?; diff --git a/examples/basic_bundle.rs b/examples/basic_bundle.rs index 0d3850f..7407282 100644 --- a/examples/basic_bundle.rs +++ b/examples/basic_bundle.rs @@ -1,18 +1,16 @@ -use anyhow::{Result, anyhow}; +use anyhow::{anyhow, Result}; use jito_sdk_rust::JitoJsonRpcSDK; +use serde_json::json; use solana_client::rpc_client::RpcClient; use solana_sdk::{ + instruction::{AccountMeta, Instruction}, pubkey::Pubkey, signature::{Keypair, Signer}, + signer::EncodableKey, system_instruction, transaction::Transaction, - instruction::{Instruction, AccountMeta}, }; use std::str::FromStr; -use std::fs::File; -use std::io::BufReader; -use serde_json::json; -use bs58; use tokio::time::{sleep, Duration}; #[derive(Debug)] @@ -22,13 +20,6 @@ struct BundleStatus { transactions: Option>, } -fn load_keypair(path: &str) -> Result { - let file = File::open(path)?; - let reader = BufReader::new(file); - let wallet: Vec = serde_json::from_reader(reader)?; - Ok(Keypair::from_bytes(&wallet)?) -} - #[tokio::main] async fn main() -> Result<()> { // Set up Solana RPC client (for getting recent blockhash and confirming transaction) @@ -41,7 +32,8 @@ async fn main() -> Result<()> { //let jito_sdk = JitoJsonRpcSDK::new("https://mainnet.block-engine.jito.wtf/api/v1", "UUID-API-KEY"); // Load the sender's keypair - let sender = load_keypair("/path/to/wallet.json" )?; + let sender = + Keypair::read_from_file("/path/to/wallet.json").expect("Failed to read wallet file"); println!("Sender pubkey: {}", sender.pubkey()); // Set up receiver and Jito tip account @@ -54,16 +46,10 @@ async fn main() -> Result<()> { let jito_tip_amount = 1_000; // 0.000001 SOL // Create instructions - let main_transfer_ix = system_instruction::transfer( - &sender.pubkey(), - &receiver, - main_transfer_amount, - ); - let jito_tip_ix = system_instruction::transfer( - &sender.pubkey(), - &jito_tip_account, - jito_tip_amount, - ); + let main_transfer_ix = + system_instruction::transfer(&sender.pubkey(), &receiver, main_transfer_amount); + let jito_tip_ix = + system_instruction::transfer(&sender.pubkey(), &jito_tip_account, jito_tip_amount); // Create memo instruction let memo_program_id = Pubkey::from_str("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr")?; @@ -85,7 +71,7 @@ async fn main() -> Result<()> { // Serialize the transaction let serialized_tx = bs58::encode(bincode::serialize(&transaction)?).into_string(); - + // Prepare bundle for submission (array of transactions) let bundle = json!([serialized_tx]); @@ -93,95 +79,110 @@ async fn main() -> Result<()> { let uuid = None; // Send bundle using Jito SDK - println!("Sending bundle with 1 transaction..."); - let response = jito_sdk.send_bundle(Some(bundle), uuid).await?; - - // Extract bundle UUID from response - let bundle_uuid = response["result"] - .as_str() - .ok_or_else(|| anyhow!("Failed to get bundle UUID from response"))?; - println!("Bundle sent with UUID: {}", bundle_uuid); - - // Confirm bundle status - let max_retries = 10; - let retry_delay = Duration::from_secs(2); - - for attempt in 1..=max_retries { - println!("Checking bundle status (attempt {}/{})", attempt, max_retries); - - let status_response = jito_sdk.get_in_flight_bundle_statuses(vec![bundle_uuid.to_string()]).await?; - - if let Some(result) = status_response.get("result") { - if let Some(value) = result.get("value") { - if let Some(statuses) = value.as_array() { - if let Some(bundle_status) = statuses.get(0) { - if let Some(status) = bundle_status.get("status") { - match status.as_str() { - Some("Landed") => { - println!("Bundle landed on-chain. Checking final status..."); - return check_final_bundle_status(&jito_sdk, bundle_uuid).await; - }, - Some("Pending") => { - println!("Bundle is pending. Waiting..."); - }, - Some(status) => { - println!("Unexpected bundle status: {}. Waiting...", status); - }, - None => { - println!("Unable to parse bundle status. Waiting..."); - } - } - } else { - println!("Status field not found in bundle status. Waiting..."); - } - } else { - println!("Bundle status not found. Waiting..."); - } - } else { - println!("Unexpected value format. Waiting..."); - } - } else { - println!("Value field not found in result. Waiting..."); - - } - } else if let Some(error) = status_response.get("error") { - println!("Error checking bundle status: {:?}", error); - } else { - println!("Unexpected response format. Waiting..."); - } - - if attempt < max_retries { - sleep(retry_delay).await; - } - } - - Err(anyhow!("Failed to confirm bundle status after {} attempts", max_retries)) - } - - async fn check_final_bundle_status(jito_sdk: &JitoJsonRpcSDK, bundle_uuid: &str) -> Result<()> { + println!("Sending bundle with 1 transaction..."); + let response = jito_sdk.send_bundle(Some(bundle), uuid).await?; + + // Extract bundle UUID from response + let bundle_uuid = response["result"] + .as_str() + .ok_or_else(|| anyhow!("Failed to get bundle UUID from response"))?; + println!("Bundle sent with UUID: {}", bundle_uuid); + + // Confirm bundle status let max_retries = 10; let retry_delay = Duration::from_secs(2); for attempt in 1..=max_retries { - println!("Checking final bundle status (attempt {}/{})", attempt, max_retries); + println!( + "Checking bundle status (attempt {}/{})", + attempt, max_retries + ); + + let status_response = jito_sdk + .get_in_flight_bundle_statuses(vec![bundle_uuid.to_string()]) + .await?; + + if let Some(result) = status_response.get("result") { + if let Some(value) = result.get("value") { + if let Some(statuses) = value.as_array() { + if let Some(bundle_status) = statuses.first() { + if let Some(status) = bundle_status.get("status") { + match status.as_str() { + Some("Landed") => { + println!("Bundle landed on-chain. Checking final status..."); + return check_final_bundle_status(&jito_sdk, bundle_uuid).await; + } + Some("Pending") => { + println!("Bundle is pending. Waiting..."); + } + Some(status) => { + println!("Unexpected bundle status: {}. Waiting...", status); + } + None => { + println!("Unable to parse bundle status. Waiting..."); + } + } + } else { + println!("Status field not found in bundle status. Waiting..."); + } + } else { + println!("Bundle status not found. Waiting..."); + } + } else { + println!("Unexpected value format. Waiting..."); + } + } else { + println!("Value field not found in result. Waiting..."); + } + } else if let Some(error) = status_response.get("error") { + println!("Error checking bundle status: {:?}", error); + } else { + println!("Unexpected response format. Waiting..."); + } - let status_response = jito_sdk.get_bundle_statuses(vec![bundle_uuid.to_string()]).await?; + if attempt < max_retries { + sleep(retry_delay).await; + } + } + + Err(anyhow!( + "Failed to confirm bundle status after {} attempts", + max_retries + )) +} + +async fn check_final_bundle_status(jito_sdk: &JitoJsonRpcSDK, bundle_uuid: &str) -> Result<()> { + let max_retries = 10; + let retry_delay = Duration::from_secs(2); + + for attempt in 1..=max_retries { + println!( + "Checking final bundle status (attempt {}/{})", + attempt, max_retries + ); + + let status_response = jito_sdk + .get_bundle_statuses(vec![bundle_uuid.to_string()]) + .await?; let bundle_status = get_bundle_status(&status_response)?; match bundle_status.confirmation_status.as_deref() { Some("confirmed") => { println!("Bundle confirmed on-chain. Waiting for finalization..."); check_transaction_error(&bundle_status)?; - }, + } Some("finalized") => { println!("Bundle finalized on-chain successfully!"); check_transaction_error(&bundle_status)?; print_transaction_url(&bundle_status); return Ok(()); - }, + } Some(status) => { - println!("Unexpected final bundle status: {}. Continuing to poll...", status); - }, + println!( + "Unexpected final bundle status: {}. Continuing to poll...", + status + ); + } None => { println!("Unable to parse final bundle status. Continuing to poll..."); } @@ -192,7 +193,10 @@ async fn main() -> Result<()> { } } - Err(anyhow!("Failed to get finalized status after {} attempts", max_retries)) + Err(anyhow!( + "Failed to get finalized status after {} attempts", + max_retries + )) } fn get_bundle_status(status_response: &serde_json::Value) -> Result { @@ -200,14 +204,22 @@ fn get_bundle_status(status_response: &serde_json::Value) -> Result Result { - let file = File::open(path)?; - let reader = BufReader::new(file); - let wallet: Vec = serde_json::from_reader(reader)?; - Ok(Keypair::from_bytes(&wallet)?) -} #[tokio::main] async fn main() -> Result<()> { @@ -31,10 +23,11 @@ async fn main() -> Result<()> { // Setup client Jito Block Engine endpoint with UUID //let jito_sdk = JitoJsonRpcSDK::new("https://mainnet.block-engine.jito.wtf/api/v1", "UUID-API-KEY"); - + // Load the sender's keypair - let sender = load_keypair("/path/to/wallet.json" )?; - + let sender = + Keypair::read_from_file("/path/to/wallet.json").expect("Failed to read wallet file"); + println!("Sender pubkey: {}", sender.pubkey()); // Set up receiver and Jito tip account @@ -48,21 +41,12 @@ async fn main() -> Result<()> { let priority_fee_amount = 7_000; // 0.000007 SOL // Create instructions - let prior_fee_ix = system_instruction::transfer( - &sender.pubkey(), - &jito_tip_account, - priority_fee_amount, - ); - let main_transfer_ix = system_instruction::transfer( - &sender.pubkey(), - &receiver, - main_transfer_amount, - ); - let jito_tip_ix = system_instruction::transfer( - &sender.pubkey(), - &jito_tip_account, - jito_tip_amount, - ); + let prior_fee_ix = + system_instruction::transfer(&sender.pubkey(), &jito_tip_account, priority_fee_amount); + let main_transfer_ix = + system_instruction::transfer(&sender.pubkey(), &receiver, main_transfer_amount); + let jito_tip_ix = + system_instruction::transfer(&sender.pubkey(), &jito_tip_account, jito_tip_amount); // Create transaction with all instructions let mut transaction = Transaction::new_with_payer( @@ -93,14 +77,16 @@ async fn main() -> Result<()> { println!("Transaction sent with signature: {}", signature); // Confirm transaction - let confirmation = solana_rpc.confirm_transaction_with_spinner( + solana_rpc.confirm_transaction_with_spinner( &signature.parse()?, &solana_rpc.get_latest_blockhash()?, CommitmentConfig::confirmed(), )?; - println!("Transaction confirmed: {:?}", confirmation); - println!("View transaction on Solscan: https://solscan.io/tx/{}", signature); + println!( + "View transaction on Solscan: https://solscan.io/tx/{}", + signature + ); Ok(()) -} \ No newline at end of file +} diff --git a/examples/basic_usage.rs b/examples/basic_usage.rs index 897466a..9784b68 100644 --- a/examples/basic_usage.rs +++ b/examples/basic_usage.rs @@ -7,18 +7,18 @@ async fn main() -> Result<(), Box> { //Example with UUID(for rate limit approved) //let sdk = JitoJsonRpcSDK::new("https://mainnet.block-engine.jito.wtf/api/v1", ); - + match sdk.get_tip_accounts().await { Ok(tip_accounts) => { let pretty_tip_accounts = JitoJsonRpcSDK::prettify(tip_accounts); println!("Tip accounts:\n{}", pretty_tip_accounts); - }, + } Err(e) => eprintln!("Error: {:?}", e), } - + /* let random_tip_account = sdk.get_random_tip_account().await?; println!("Random tip account: {}", random_tip_account); */ Ok(()) -} \ No newline at end of file +}