simulateTransaction — Solana JSON-RPC
Simulates sending a Solana transaction without submitting it to the cluster, returning the would-be execution result, logs, and compute usage.
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). No free or basic access.; Burst capacity
Endpoint and plans: Solana RPC endpoint.
simulateTransaction runs a transaction against the current bank state and
returns the result it would produce if submitted, without ever broadcasting
it. Use it to pre-flight a transaction: confirm it would succeed, read the
program logs it would emit, measure the compute units it would consume, and
inspect the post-execution state of selected accounts.
This is the right call before sendTransaction when you want to surface errors
to the user, estimate a compute-unit budget, or decode a program's return data
without paying fees. Because simulation reflects live bank state, the result is
advisory — a transaction that simulates cleanly can still fail on submission if
state changes in the interim.
By default the transaction's recent blockhash must be valid for simulation to
succeed. Set replaceRecentBlockhash: true to have the node substitute the most
recent blockhash before simulating, which lets you simulate a transaction whose
own blockhash has already expired.
Tier note: this method belongs to the
sol_sim_bundlecategory and is available on pro and business tiers only. Free- and basic-tier keys are rejected with HTTP403tier_insufficient(plus anX-Required-Tierheader) before the request reaches the RPC layer — see Errors.
Parameters
JSON-RPC params is a positional array: [transaction, config?].
transactionstringrequiredencoding field of config.configobjectoptionalsigVerifybooleanoptionaltrue, verify the transaction signatures. Mutually exclusive with replaceRecentBlockhash.commitmentstringoptionalprocessed, confirmed, or finalized.encodingstringoptionaltransaction string: base58 or base64. base64 is recommended.replaceRecentBlockhashbooleanoptionaltrue, replace the transaction's recent blockhash with the most recent blockhash before simulating. Mutually exclusive with sigVerify.minContextSlotintegeroptionalinnerInstructionsbooleanoptionaltrue, include inner instructions in the response.accountsobjectoptionalconfig.accountsobjectaddressesstring[]optionalencodingstringoptionalbase58, base64, base64+zstd, or jsonParsed.Response
Response fields
| Field | Type | Description |
|---|---|---|
result | object | SimulateTransactionResponse envelope. |
result.context | object | The context the simulation was evaluated against. |
result.context.slot | integer | The slot at which the transaction was simulated. |
result.context.apiVersion | string | The node software version that served the request. |
result.value | object | The simulation result. |
result.value.err | object | null | null if the transaction would succeed; otherwise the error that caused it to fail. |
result.value.logs | string[] | Program log messages emitted during simulation. |
result.value.accounts | array | null | Post-simulation account states, one per address in config.accounts.addresses (in order), or null if accounts was not requested. |
result.value.unitsConsumed | integer | The number of compute units consumed by the transaction. |
result.value.returnData | object | null | The most recent return data generated by an instruction, if any. |
result.value.returnData.programId | string (base-58) | The program that generated the return data. |
result.value.returnData.data | array | The return data, as [data, encoding]. |
result.value.innerInstructions | array | Inner instructions, present only when innerInstructions: true was set. |
Each entry in result.value.accounts is an AccountInfo object with
data, executable, lamports, owner, rentEpoch, and space fields.
Errors
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 | transaction is missing, the encoding does not match config.encoding, or config is malformed (e.g. both sigVerify and replaceRecentBlockhash set). |
403 | Tier insufficient | Your key's tier is below pro: simulateTransaction requires pro+ for the sol_sim_bundle category. An HTTP error with a plain JSON body — there is no JSON-RPC envelope: {"error":"tier_insufficient", …} with current_tier, required_tier, method, category and upgrade_url, plus an X-Required-Tier header. |
429 | Rate limited | More than your tier's RPS for 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 failing simulation (e.g. an instruction error) is not a JSON-RPC error:
the request returns 200 with result.value.err populated and the relevant
logs.
Examples
JavaScript (fetch)
const tx = "AVXo5X7UMtwHFeqHfwopBLrCftbS5UfPiDoXNi8gO1r..."; // base64-encoded tx
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: "simulateTransaction",
params: [tx, { encoding: "base64", replaceRecentBlockhash: true }],
}),
});
const { result } = await res.json();
if (result.value.err) {
console.error("Simulation failed:", result.value.err, result.value.logs);
} else {
console.log(`OK — ${result.value.unitsConsumed} compute units consumed`);
}Notes
sigVerifyvsreplaceRecentBlockhash: these are mutually exclusive. SetsigVerify: trueonly when you have a fully signed transaction and want the signatures checked; usereplaceRecentBlockhash: trueto simulate an unsigned or stale-blockhash transaction.- Compute budgeting: read
value.unitsConsumedto size aComputeBudgetinstruction before submitting the real transaction withsendTransaction. - Reading account state: pass
config.accounts.addressesto get the post-executionAccountInfofor specific accounts — useful for verifying the effect of a transaction before broadcasting it. - Advisory result: a clean simulation does not guarantee on-chain success; state can change between simulation and submission.
- Related methods:
sendTransactionto submit,getFeeForMessageto price a message, and the bundle simulation methods for multi-transaction pre-flight.