simulateTransaction
Simulate sending a transaction
Common use cases
| Pre-flight transaction validation | Test transaction logic and program behavior without broadcasting to network or consuming fees. Catch instruction errors, account access violations, and compute limit issues before submission to prevent wasted transaction costs. |
| Compute budget estimation | Determine exact compute units consumed by transaction execution. Essential for setting appropriate ComputeBudgetProgram limits—real-world pattern adds 10-20% buffer to simulation result for production transactions. |
| Wallet transaction preview | Display expected balance changes and account state mutations to users before transaction approval. Requires fetching pre-simulation account states separately and comparing with simulation results to calculate deltas. |
| Program development debugging | Inspect detailed program logs and account state changes during smart contract development without deploying to devnet. Use sigVerify:false to test logic without signature requirements. |
Parameters
transaction (string, required)
Transaction, as an encoded string. The transaction must have a valid blockhash, but is not required to be signed.
config (object, optional)
Configuration object containing the following fields:
Fields:
commitment(string): Commitment level to simulate the transaction at. See Configuring State Commitment. Defaultfinalized.encoding(string): Encoding used for the transaction data. Values:base58(slow, DEPRECATED), orbase64.replaceRecentBlockhash(bool): Iftruethe transaction recent blockhash will be replaced with the most recent blockhash (conflicts withsigVerify)sigVerify(bool): Iftruethe transaction signatures will be verified (conflicts withreplaceRecentBlockhash)minContextSlot(number): The minimum slot that the request can be evaluated atinnerInstructions(bool): Iftruethe response will include inner instructions. These inner instructions will bejsonParsedwhere possible, otherwisejson.accounts(object): Accounts configuration object containing the following fields:addresses: An array of accounts to return, as base-58 encoded stringsencoding: Encoding for returned Account data. Note:jsonParsedencoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. IfjsonParsedis requested but a parser cannot be found, the field falls back tobase64encoding, detectable when the returnedaccounts.datafield is typestring.
Request
- cURL
- JavaScript
- Python
curl https://solana-mainnet.api.syndica.io/api-key/YOUR_API_KEY \
-X POST \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "simulateTransaction",
"params": [
"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEEjNmKiZGiOtSZ+g0
{
"commitment": "confirmed",
"encoding": "base64",
"replaceRecentBlockhash": true
}
]
}'
// Using fetch
const response = await fetch('https://solana-mainnet.api.syndica.io/api-key/YOUR_API_KEY', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
"jsonrpc": "2.0",
"id": 1,
"method": "simulateTransaction",
"params": [
"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEEjNmKiZGiOtSZ+g0
{
"commitment": "confirmed",
"encoding": "base64",
"replaceRecentBlockhash": true
}
]
})
});
const data = await response.json();
console.log(data);
import requests
import json
url = 'https://solana-mainnet.api.syndica.io/api-key/YOUR_API_KEY'
headers = {'Content-Type': 'application/json'}
data = {
"jsonrpc": "2.0",
"id": 1,
"method": "simulateTransaction",
"params": [
"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEEjNmKiZGiOtSZ+g0
{
"commitment": "confirmed",
"encoding": "base64",
"replaceRecentBlockhash": true
}
]
}
response = requests.post(url, headers=headers, data=json.dumps(data))
print(response.json())
Replace mainnet with devnet in the URL to query devnet instead.
Response
{
"jsonrpc": "2.0",
"result": {
"context": {
"apiVersion": "2.3.3",
"slot": 393226680
},
"value": {
"accounts": null,
"err": null,
"innerInstructions": null,
"loadedAccountsDataSize": 413,
"logs": [
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [1]",
"Program log: Instruction: Transfer",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1714 of 200000 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success"
],
"replacementBlockhash": {
"blockhash": "6oFLsE7kmgJx9PjR4R63VRNtpAVJ648gCTr3nq5Hihit",
"lastValidBlockHeight": 381186895
},
"returnData": null,
"unitsConsumed": 1714
}
},
"id": 1
}
Response Fields
accounts (array|null)
Array of accounts with the same length as the accounts.addresses array in the request. Each element is either:
null- if the account doesn't exist or iferris not null- An object containing:
lamports: <u64>- number of lamports assigned to this accountowner: <string>- base-58 encoded Pubkey of the program this account has been assigned todata: <[string, encoding]|object>- data associated with the account, either as encoded binary data or JSON format{<program>: <state>}executable: <bool>- boolean indicating if the account contains a programrentEpoch: <u64>- the epoch at which this account will next owe rent
err (object|string|null)
Error if transaction failed, null if transaction succeeded. See TransactionError definitions
innerInstructions (object|undefined)
Defined only if innerInstructions was set to true. The value is a list of inner instructions.
loadedAccountsDataSize (u32|undefined)
The number of bytes of all accounts loaded by this transaction
logs (array|null)
Array of log messages the transaction instructions output during execution, null if simulation failed before the transaction was able to execute
replacementBlockhash (object|null)
The blockhash used to simulate the transaction, containing:
blockhash: <string>- the blockhash used to simulate the transactionlastValidBlockHeight: <u64>- the last valid block height at which the blockhash is valid
returnData (object|null)
The most-recent return data generated by an instruction in the transaction, containing:
programId: <string>- the program that generated the return data, as base-58 encoded Pubkeydata: <[string, encoding]>- the return data itself, as base-64 encoded binary data
unitsConsumed (u64|undefined)
The number of compute budget units consumed during the processing of this transaction
FAQ and Troubleshooting
Why doesn't simulateTransaction return balance changes directly?
The method returns post-execution account states in the accounts array. To calculate balance changes, you must fetch account states before simulation using getAccountInfo and manually compare the lamports field or token balances (bytes 64-72 for SPL tokens).
How do I simulate a transaction without triggering wallet signature prompts?
Set "sigVerify": false in the config options. This skips signature verification and allows simulation without valid signatures—essential for UI previews and testing scenarios where you don't have access to private keys.
Why do I only see some accounts in the simulation result?
You must specify which accounts you want in the response using the accounts.addresses config array. Without this parameter, only accounts directly written to by the transaction are returned—accounts that are only read will not appear.
Can simulateTransaction override account balances for testing scenarios?
No, the current implementation always uses actual on-chain state. You cannot simulate with arbitrary token balances or modified account data—simulation reflects the real current state of accounts.
Does simulation guarantee the same result when I send the transaction?
No. Blockchain state can change between simulation and execution. Use simulation for pre-flight validation and estimation, but understand that network conditions, account states, or slot context may differ during actual execution.
Related Methods
sendTransaction
Broadcasts transactions to network after simulation validates logic. Standard workflow: simulate first to catch errors and estimate compute units, then send with appropriate compute budget limits.
getAccountInfo
Fetches account state before simulation to enable balance change calculations. simulateTransaction returns post-execution state only—compare with getAccountInfo results to determine deltas.
getFeeForMessage
Estimates transaction fees based on message content. Use together with simulateTransaction's unitsConsumed to calculate total transaction cost including priority fees.
getLatestBlockhash
Provides valid recent blockhash required for transaction construction. When simulating, set replaceRecentBlockhash:true to bypass blockhash expiration validation.
getRecentPrioritizationFees
Returns recent priority fees from network. Combine with simulateTransaction's compute unit estimates to set optimal ComputeUnitPrice for transaction landing success.