simulateBundle
https://api.triport.io/v1/solDry-runs an MEV bundle — an ordered list of Solana transactions — against the current chain state without broadcasting any of them.
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
The parameter schema is provisional (scaffold — finalized in a later spec version). The shape below reflects the intended contract.
JSON-RPC params is a positional array: [bundle, config?].
bundleobjectrequiredtransactionsstring[]requiredconfigobjectoptionalencodingstringoptionalbundle.transactions — base64 (recommended) or base58.commitmentstringoptionalprocessed, confirmed, or finalized.Response
The result schema is provisional (scaffold — finalized in a later spec version). The shape below reflects the intended contract; the result is an open object, so additional fields may appear.
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 | bundle is missing/malformed, transactions is empty or not an array, or a transaction is not decodable under the chosen encoding. |
-32002 | Tier 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. |
-32003 | Rate 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. |
401 | Unauthorized | Missing 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://api.triport.io/v1/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: [
{ transactions: [base64Tx1, base64Tx2] },
{ encoding: "base64", commitment: "confirmed" },
],
}),
});
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(
{ transactions: [base64Tx1, base64Tx2] },
{ encoding: "base64", commitment: "confirmed" }
);
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(
{"transactions": [base64_tx_1, base64_tx_2]},
encoding="base64",
commitment="confirmed",
)
ok = all(t["err"] is None for t in result["value"]["transactionResults"])
print("bundle simulated clean" if ok else "bundle would revert")Notes
- Scaffold / provisional: params and result are finalized in spec
api.2.2/2.3/2.4. Treat the shapes on this page as the intended contract and re-pin once a published schema version is available. - 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.