simulateBundle — Solana JSON-RPC
Dry-runs an MEV bundle — an ordered list of Solana transactions — against the current chain state without broadcasting any of them.
https://triport.io/sol- Network
- Solana
- Scope
- sol_sim_bundle
- Auth
- x-token: $TRIPORT_API_KEY (or Authorization: Bearer)
- Rate limit
- pro+ — 5 / 15 RPS sustained · short burst 10 / 30 (pro / business); Burst capacity
Endpoint and plans: Solana RPC endpoint.
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]objectrequiredbundle (params[0])objectencodedTransactionsstring[]requiredResponse
The result is an open object (
context/value); additional per-transaction fields may appear beyond those documented below.
resultobjectadditionalProperties allowed).result.contextobjectresult.context.slotintegerresult.context.apiVersionstringresult.valueobjectresult.value.summarystring | objectresult.value.transactionResultsobject[]result.value.transactionResults[].errobject | nullnull if the transaction simulated successfully, otherwise the transaction error.result.value.transactionResults[].logsstring[]result.value.transactionResults[].unitsConsumedintegerErrors
Errors are returned in the standard JSON-RPC error envelope. See the shared errors reference for the full envelope shape and shared codes.
| Code | Meaning | When it happens |
|---|---|---|
-32602 | Invalid params | params[0] is missing/malformed, encodedTransactions is missing ("missing field encodedTransactions")/empty/not an array, or a transaction is not decodable as base64. |
403 | Tier insufficient | The key's tier is below pro. An HTTP error with a plain JSON body — there is no JSON-RPC envelope: {"error":"tier_insufficient", …} with current_tier, required_tier, method, category (sol_sim_bundle) and upgrade_url, plus an X-Required-Tier header. |
429 | Rate limited | More than your tier's sustained RPS on sol_sim_bundle (5 pro / 15 business). Body {"error":"rate_limited", …} with limit_rps, burst_capacity and retry_after_sec; honour Retry-After (and X-RateLimit-Reset). |
401 | Unauthorized | Missing or invalid Authorization: Bearer key. |
A tier-insufficient response is an HTTP 403 with a plain body — there is no JSON-RPC envelope:
{
"error": "tier_insufficient",
"message": "Method 'simulateBundle' requires pro tier or higher",
"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");Notes
- Encoding: transactions must be base64-encoded strings inside
encodedTransactions. The resultvalueenvelope is open — new per-transaction fields may be added over time. - Pro tier only:
sol_sim_bundlehas 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:
simulateBundlenever broadcasts. Once a bundle simulates cleanly, submit it with the Solana bundle-submission methods. - Related methods: use
simulateTransactionto dry-run a single transaction independently, andsendTransactionto broadcast one transaction at a time.