Submit Transactions

How to submit transaction

Astralane provides a multitude of options for your needs, here are some of RPC methods we offer for Transaction sending.


sendTransation

This RPC call is fully compatible with all Solana libraries , making it a simple drop-in replacement for your existing workflows. It routes through our partner SWQoS clients, including Jito and Paladin (higher min tip), ensuring optimized transaction processing and maximum reliability.

Just insert the URL where you would place a RPC URL and send your txns how you send normally. The only change is to add an instruction to tip.


const TIP: Pubkey = pubkey!("astra4uejePWneqNaJKuFFA8oonqCE1sqF6b45kDMZm"); // Use tip wallet depending on region of access
const MIN_TIP_AMOUNT: u64 = 100_000; // added for spam prevention

fn send_tx_tipped(
    ixs: &mut Vec<Instruction>,
    signer: &Keypair,
    rpc_client: &RpcClient, // https://api.mainnet-beta.solana.com
    astralane_txn_sender: &RpcClient // Astralane RPC 
) {
    let tip_ix = system_instruction::transfer(&signer.pubkey(), &TIP, MIN_TIP_AMOUNT);
    ixs.push(tip_ix);

    let blockhash = rpc_client.get_latest_blockhash().unwrap();
    let tx = Transaction::new_signed_with_payer(ixs, Some(&signer.pubkey()), &[signer], blockhash);

    astralane_txn_sender.send_transaction_with_config(
                &transaction,
                RpcSendTransactionConfig {
                    skip_preflight: true,
                    encoding: Some(UiTransactionEncoding::Base64),
                },
            ).unwrap();
}

Please do note that the sendTransaction endpoint supports max_retries: None and min_context_slot: None feature which is useful for traders which don't want our staked nodes to retry their txns. Reach out to us for more info on ideal use cases.

**New - The endpoint can be used to broadcast to paladin as well, if the Min tip satisfies the min tip requirement for sending to Paladin. Read more on advantages below.


sendBundle

If your operation depends on atomic txn execution then use our sendBundle endpoint to send atomically executing transactions.

Send up to 4 transactions in a single atomic bundle. These transactions are executed sequentially , ensuring precision and reliability. If any transaction fails, the entire bundle is reverted—guaranteeing consistency and eliminating partial failures.

const TIP: Pubkey = pubkey!("astra4uejePWneqNaJKuFFA8oonqCE1sqF6b45kDMZm"); // Use tip wallet depending on region of access
const MIN_TIP_AMOUNT: u64 = 100_000; // added for spam prevention

async fn send_bundle(
    ixs: &mut Vec<Instruction>,
    signer: &Keypair,
    client: reqwest::Client,
    blockhash: Hash,
    url: String,
) {
    let tip_ix = system_instruction::transfer(&signer.pubkey(), &TIP, MIN_TIP_AMOUNT);
    ixs.push(tip_ix);
    let tx = Transaction::new_signed_with_payer(ixs, Some(&signer.pubkey()), &[signer], blockhash);
    let encoded_tx = base64::prelude::BASE64_STANDARD.encode(&bincode::serialize(tx).unwrap());
    let response = client
        .post(url)
        .header("api_key", "xxx")
        .json(&json! ({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "sendBundle",
            "params": [[encoded_tx]],
        }))
        .send()
        .await;
}

Request:

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "sendBundle",
  "params": [
    [
      "base64_encoded_txn1",
      "base64_encoded_txn2",
      "base64_encoded_txn3"
    ],
    {
      "encoding": "base64",
      "mevProtect": true
    }
  ]
}

Response:

List of signatures for your transaction

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": [
        "37Dxw2nJYw3T8JVqenPQMf39VJ9CNZYCyQm67b6nRj6fa6UjQ1UuLqFvh3wJ2G7LcMuZn4oq5kDt2A2CEXfi8D8"
    ]
}

Note: MAX_TRANSACTIONS_IN_BUNDLE = 4


sendIdeal

Perfect for snipers! Due to the segregation in validators as JITO validators and normal ones, traders are often conflicted between spending more on jito tips vs more in priority fees. Durable nonces offer a way to mitigate this issue.

Our sendIdeal RPC method accepts two transactions:

  • One with a high priority fee + min tip

  • Another with a high tip + lower priority fee

We route them through our advanced SWQoS and bundling pipelines. Using durable nonces, once one transaction lands, the other is automatically canceled—ensuring optimal efficiency and cost savings. if you don't want to manage the durable nonce accounts on your own we also provide a managed service for this, We create a nonce account for each api-key you use and you can query them using our getNonce rpc call. Follow the below integration steps for best utilization of this feature:

Step 1 : Generate Nonce instruction

use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{EncodableKey, Keypair, Signer};

async fn get_nonce(
    client: reqwest::Client,
    url: String,
    auth_key: String,
) {
    let response = client
        .post(url)
        .header("api_key", "xxx")
        .json(&json! ({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getNonce",
            "params": [api_key], // provided during onboarding
        }))
        .send()
        .await;
    let result = response["result"].clone();
    let nonce = result["nonce"].as_str().unwrap();
    let nonce_account = Pubkey::from_str(result["nonceAccount"].as_str().unwrap()).unwrap();
    let nonce_authority =
        Pubkey::from_str(result["nonceAuthority"].as_str().unwrap()).unwrap();
    let nonce_as_hash = Hash::from_str(nonce).unwrap();
}

if you already have an existing nonce account, you can just pass in your nonce account, you can simply pass in your nonce account public key instead of the API key. The response will still include your parsed nonce.

To use this nonce, just include an advance nonce instruction as the first instruction in your transactions.

Step 2 : Generate your txn and Partial Sign it before submission

const TIP: Pubkey = pubkey!("astra4uejePWneqNaJKuFFA8oonqCE1sqF6b45kDMZm"); // Use tip wallet depending on region of access
const MIN_TIP_AMOUNT: u64 = 100_000; // added for spam prevention

async fn send_ideal(
    signer: &Keypair,
    client: reqwest::Client,
    nonce: Hash,
    instructions: Vec<Instruction>,
    nonce_authority: &Pubkey,
    nonce_account: &Pubkey,
) {
    // add advance nonce instruction
    let advance_nonce = solana_sdk::system_instruction::advance_nonce_account(nonce_account, nonce_authority);

    let low_tip_high_fee_ixs = vec![
        advance_nonce.clone(),
        solana_sdk::compute_budget::ComputeBudgetInstruction::set_compute_unit_price(
            10 * MICRO_LAMPORTS_PER_LAMPORTS,
        ),
        // add your instructions here
        solana_sdk::system_instruction::transfer(&signer.pubkey(), &TIP, MIN_TIP_AMOUNT),
    ];

    let high_tip_low_fee_ixs = vec![
        advance_nonce,
        solana_sdk::compute_budget::ComputeBudgetInstruction::set_compute_unit_price(
            100,
        ),
        // add your instructions here
        solana_sdk::system_instruction::transfer(&signer.pubkey(), &TIP, 100 * MIN_TIP_AMOUNT),
    ];


    //add high  transaction priority fee and min tip
    let mut low_tip_high_fee_tx = Transaction::new_with_payer(&low_tip_high_fee_ixs, Some(&signer.pubkey()));
    low_tip_high_fee_tx.partial_sign(&[&signer], nonce);

    let mut high_tip_low_fee_tx = Transaction::new_with_payer(&high_tip_low_fee_ixs, Some(&signer.pubkey()));
    high_tip_low_fee_tx.partial_sign(&[&signer], nonce);

    let low_tip_high_fee_tx_encoded = base64::prelude::BASE64_STANDARD.encode(&bincode::serialize(low_tip_high_fee_tx).unwrap());
    let high_tip_low_fee_tx_encoded = base64::prelude::BASE64_STANDARD.encode(&bincode::serialize(high_tip_low_fee_tx).unwrap());

    let response = client
        .post(url)
        .json(&json! ({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "sendIdeal",
            "params": [[low_tip_high_fee_tx_encoded, high_tip_low_fee_tx_encoded]],
        }))
        .send()
        .await;
}

When using Astralane's managed nonce accounts, ensure that you use the partial_sign method to sign your transactions. If you are not utilizing managed nonce accounts, proceed with the standard sign method.

**New - The endpoint can be used to broadcast to paladin as well, if the Min tip satisfies the min tip requirement for sending to Paladin. Read more on advantages below.

Request:

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "sendIdeal",
  "params": [[
    "transction_with_large_tip_low_priority_fee",
    "transaction_with_large_priority_fee_low_tip"
  ]]
}

Response:

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": [
        "<signature A>",
        "<signature B>"
    ]
}

The latency performance for your transactions will depend on current network dynamics. Kindly reach out to us on telegram for recommendations on ideal setup for your operation


sendPaladin (Beta)

Paladin is a custom TPU port implementation which provides a more efficient way to send your transactions directly to the leaders. The paladin client is currently running on 10% of the Solana network (as per 10th March 2025). Read more

Step 1 : Tracking Paladin leaders

Since paladin validators are not present for all slots, we provided a paladin leader tracker endpoint which can be used for knowing which slots we have a paladin leader. Here are some general guidelines for tracker integration to dynamically send txns based on leader info:

  1. Fetch all Palidator public keys for current epoch

⚔️ GET /api/palidators
[
    "Ss...Z77",
    "ACv...mi",
    "7Z...Z84",
]

  1. Get next Palidator leader slots

⚔️ GET /api/next_palidator
{
  "pubkey": "Csd...def",
  "leader_slot": 42424242,
  "context_slot": 42424242
}

  1. Get next leader Palidator on or after given slot

⚔️ GET /api/next_palidator/{slot}
{
  "pubkey": "Csd...def",
  "leader_slot": 42424242,
  "context_slot": 42424242
}

Step 2: Crafting paladin transaction

Use the sendPaladin method, to send the transactions during these slots. Please make sure to respect the min tip requirements and min priority fee requirements while sending txns on this endpoint.

All transactions sent to this endpoint, go through a small auction and the ordering will based on:

  1. Priority fees

  2. Any tiebreakers will be decided by tip to Astralane tip addresses

Parameter
Type
Description
revertProtection

Boolean

Optional, A failed transaction will be dropped rather than landed as failed when enabled. Default is false

enableFallback

Boolean

Optional, When enabled, if your transaction has not been able to win the paladin auction, they will be sent via SwQOS / JITO. Default is false

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "sendPaladin",
  "params": [
    "<base 64 tx>",
    {
      "revertProtection": false,
      "enableFallback" : false
    }
  ]
}
{
    "jsonrpc": "2.0",
    "id": 1,
    "result": [
        "<signature A>",
    ]
}

Inorder to use this efficiently, make sure to use our Paladin Leader API endpoints to track active leaders and slot timings and adjust your tips/fees accordingly. Update your configurations via dedicated endpoints for optimal cost control.


Need Help?

Join our Discord for technical guides, integration support, and live updates.

Last updated