rust
Send a bundle using Rust.
Dependencies
toml
[dependencies]
solana-sdk = "1.18"
solana-client = "1.18"
reqwest = { version = "0.11", features = ["json", "blocking"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
base64 = "0.21"
bincode = "1.3"Types
rust
use serde::{Deserialize, Serialize};
#[derive(Serialize)]
pub struct BundleParams {
pub encoding: String,
#[serde(rename = "skipPreflight")]
pub skip_preflight: bool,
}
#[derive(Serialize)]
pub struct JsonRpcRequest {
pub jsonrpc: String,
pub id: u64,
pub method: String,
pub params: (Vec<String>, BundleParams),
}
#[derive(Deserialize)]
pub struct BundleResult {
pub bundle_id: String,
pub signatures: Vec<String>,
}
#[derive(Deserialize)]
pub struct JsonRpcResponse {
pub result: Option<BundleResult>,
pub error: Option<RpcError>,
}
#[derive(Deserialize)]
pub struct RpcError {
pub code: i32,
pub message: String,
}Send Bundle Function
rust
use reqwest::blocking::Client;
use solana_sdk::transaction::Transaction;
use crate::types::*;
pub const ENDPOINT: &str = "https://fra.blocksprint.io/bundle/v1/YOUR_API_KEY";
pub fn send_bundle(transactions: Vec<Transaction>) -> Result<BundleResult, Box<dyn std::error::Error>> {
let client = Client::new();
// Serialize transactions to base64
let serialized_txs: Vec<String> = transactions
.iter()
.map(|tx| base64::encode(bincode::serialize(tx).unwrap()))
.collect();
let request = JsonRpcRequest {
jsonrpc: "2.0".to_string(),
id: 1,
method: "sendBundle".to_string(),
params: (
serialized_txs,
BundleParams {
encoding: "base64".to_string(),
skip_preflight: true,
},
),
};
let response: JsonRpcResponse = client
.post(ENDPOINT)
.header("Content-Type", "application/json")
.json(&request)
.send()?
.json()?;
if let Some(error) = response.error {
return Err(format!("RPC error {}: {}", error.code, error.message).into());
}
Ok(response.result.unwrap())
}Full Example
rust
mod send_bundle;
mod types;
use send_bundle::send_bundle;
use solana_client::rpc_client::RpcClient;
use solana_sdk::{
commitment_config::CommitmentConfig,
message::Message,
pubkey::Pubkey,
signature::{Keypair, Signer},
system_instruction,
transaction::Transaction,
};
use std::str::FromStr;
// Your Solana RPC (for the blockhash)
const RPC_URL: &str = "https://api.mainnet-beta.solana.com";
// BlockSprint tip address, tip at least 0.001 SOL
const TIP_ADDRESS: &str = "Sp4JHSh9cksfzXbgK7Pq2ovtn8LirLQydaJKTsiNT77";
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = RpcClient::new_with_commitment(
RPC_URL.to_string(),
CommitmentConfig::confirmed(),
);
let wallet = Keypair::new();
let recipient = Pubkey::from_str("RECIPIENT")?;
let tip_address = Pubkey::from_str(TIP_ADDRESS)?;
// Get blockhash (same for all transactions)
let blockhash = client.get_latest_blockhash()?;
// Transaction 1
let tx1 = Transaction::new_signed_with_payer(
&[system_instruction::transfer(&wallet.pubkey(), &recipient, 1_000_000)],
Some(&wallet.pubkey()),
&[&wallet],
blockhash,
);
// Transaction 2 (with the 0.001 SOL tip)
let tx2 = Transaction::new_signed_with_payer(
&[
system_instruction::transfer(&wallet.pubkey(), &recipient, 2_000_000),
system_instruction::transfer(&wallet.pubkey(), &tip_address, 1_000_000),
],
Some(&wallet.pubkey()),
&[&wallet],
blockhash,
);
// Send bundle
let result = send_bundle(vec![tx1, tx2])?;
println!("Bundle ID: {}", result.bundle_id);
for (i, sig) in result.signatures.iter().enumerate() {
println!("Tx {}: {}", i + 1, sig);
}
Ok(())
}Async Version
rust
use reqwest::Client;
use solana_sdk::transaction::Transaction;
use crate::send_bundle::ENDPOINT;
use crate::types::*;
pub async fn send_bundle_async(
transactions: Vec<Transaction>,
) -> Result<BundleResult, Box<dyn std::error::Error>> {
let client = Client::new();
let serialized_txs: Vec<String> = transactions
.iter()
.map(|tx| base64::encode(bincode::serialize(tx).unwrap()))
.collect();
let request = JsonRpcRequest {
jsonrpc: "2.0".to_string(),
id: 1,
method: "sendBundle".to_string(),
params: (
serialized_txs,
BundleParams {
encoding: "base64".to_string(),
skip_preflight: true,
},
),
};
let response: JsonRpcResponse = client
.post(ENDPOINT)
.header("Content-Type", "application/json")
.json(&request)
.send()
.await?
.json()
.await?;
if let Some(error) = response.error {
return Err(format!("RPC error {}: {}", error.code, error.message).into());
}
Ok(response.result.unwrap())
}