TriportRPC

simulateBundle

POSThttps://triport.io/sol

Dry-runs an MEV bundle — an ordered list of Solana transactions — against the current chain state without broadcasting any of them.

Solanasol_sim_bundlepro+ — 5 / 15 RPS (pro / business)

simulateBundle simulates the execution of an ordered bundle of Solana transactions exactly as they would run if landed back-to-back in a single block, and returns the per-transaction outcome — without submitting anything to the network. Use it to validate an MEV / atomic-arbitrage bundle (or any sequence of dependent transactions) before paying to send it with the bundle-submission methods.

Because the transactions are simulated in order against the same working state, later transactions in the bundle observe the account changes produced by earlier ones. This is the key difference from calling simulateTransaction on each transaction independently: a bundle that only succeeds atomically (for example, a swap that funds a later repay) can be validated as a whole.

This is a pro-tier-only method. It is rate-limited under the sol_sim_bundle category at 5 RPS (pro) / 15 RPS (business), with burst headroom of twice the sustained limit.

Parameters

JSON-RPC params is a positional array with a single bundle object: [{ "encodedTransactions": [...] }].

params[0]objectrequired
The bundle to simulate (see below).
bundle (params[0])object
encodedTransactionsstring[]required
Ordered list of fully-signed, base64-encoded transactions. Simulated in array order against a shared working state, so a later transaction observes the account changes of earlier ones.

Response

The result is an open object (context / value); additional per-transaction fields may appear beyond those documented below.

resultobject
Open response envelope (additionalProperties allowed).
result.contextobject
The context the bundle was simulated against.
result.context.slotinteger
The slot at which the bundle was simulated.
result.context.apiVersionstring
The node software version that served the request.
result.valueobject
The simulation outcome.
result.value.summarystring | object
Overall bundle result — succeeds only if every transaction succeeds in order.
result.value.transactionResultsobject[]
Per-transaction results, in bundle order.
result.value.transactionResults[].errobject | null
null if the transaction simulated successfully, otherwise the transaction error.
result.value.transactionResults[].logsstring[]
Program log output captured during simulation.
result.value.transactionResults[].unitsConsumedinteger
Compute units consumed by the transaction.

Errors

Errors are returned in the standard JSON-RPC error envelope. See the shared errors reference for the full envelope shape and shared codes.

CodeMeaningWhen it happens
-32602Invalid paramsparams[0] is missing/malformed, encodedTransactions is missing ("missing field encodedTransactions")/empty/not an array, or a transaction is not decodable as base64.
-32002Tier insufficient (HTTP 403)The key's tier is below pro. The error data includes current_tier, required_tier, category (sol_sim_bundle), and an upgrade_url.
-32003Rate limited (HTTP 429)More than your tier's sustained RPS on sol_sim_bundle (5 pro / 15 business). data includes limit_rps and burst_capacity; honor the Retry-After header.
401UnauthorizedMissing or invalid Authorization: Bearer key.

A tier-insufficient response looks like:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32002,
    "message": "Method 'simulateBundle' requires pro tier or higher",
    "data": {
      "current_tier": "free",
      "required_tier": "pro",
      "method": "simulateBundle",
      "category": "sol_sim_bundle",
      "upgrade_url": "https://triport.io/upgrade/pro"
    }
  }
}

Examples

JavaScript (fetch)

const res = await fetch("https://triport.io/sol", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.TRIPORT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "simulateBundle",
    params: [{ encodedTransactions: [base64Tx1, base64Tx2] }],
  }),
});


const { result, error } = await res.json();
if (error) throw new Error(`${error.code}: ${error.message}`);


const ok = result.value.transactionResults.every((t) => t.err === null);
console.log(ok ? "bundle simulated clean" : "bundle would revert");

TypeScript SDK (@triport/sdk)

import { TriportClient } from "@triport/sdk";


// simulateBundle requires a pro-tier (or higher) API key.
const client = new TriportClient({ apiKey: process.env.TRIPORT_API_KEY });


const { value } = await client.solana.simulateBundle(
  { encodedTransactions: [base64Tx1, base64Tx2] }
);


const ok = value.transactionResults.every((t) => t.err === null);
console.log(`bundle ${ok ? "OK" : "would fail"}`);

Python (triport-sdk)

import os
from triport import TriportClient


# simulateBundle requires a pro-tier (or higher) API key.
client = TriportClient(api_key=os.environ["TRIPORT_API_KEY"])


result = client.solana.simulate_bundle(
    {"encodedTransactions": [base64_tx_1, base64_tx_2]},
)


ok = all(t["err"] is None for t in result["value"]["transactionResults"])
print("bundle simulated clean" if ok else "bundle would revert")

Notes

  • Encoding: transactions must be base64-encoded strings inside encodedTransactions. The result value envelope is open — new per-transaction fields may be added over time.
  • Pro tier only: sol_sim_bundle has no free or basic access — see rate limits and tiers.
  • Ordering matters: transactions are simulated in array order against a shared state, so a later transaction sees earlier transactions' effects. This is what makes it suitable for validating atomic bundles.
  • Dry-run only: simulateBundle never broadcasts. Once a bundle simulates cleanly, submit it with the Solana bundle-submission methods.
  • Related methods: use simulateTransaction to dry-run a single transaction independently, and sendTransaction to broadcast one transaction at a time.