simulateCall
Simulates a new message call without creating a transaction on the blockchain.
Usage
example.ts
import { client } from './config'
const result = await client.simulateCall({
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data: '0xa9059cbb0000000000000000000000001234567890123456789012345678901234567890000000000000000000000000000000000000000000000000000000000000000a',
gas: '0xD6D8'
})Checking Balances
const result = await client.simulateCall({
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
data: '0x70a08231000000000000000000000000742d35cc6634c0532925a3b844bc9e7595f06e8c' // balanceOf
})
if (result.isSuccess()) {
const balance = BigInt(result.calls[0].returnData)
console.log('USDC Balance:', (Number(balance) / 1e6).toFixed(6))
}Simulating Transfers
const result = await client.simulateCall({
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
data: '0xa9059cbb0000000000000000000000001234567890123456789012345678901234567890000000000000000000000000000000000000000000000000000000000000000a' // transfer 10 USDC
})
console.log('Transfer simulation:', result.isSuccess() ? 'Success' : 'Failed')
console.log('Gas estimate:', result.getTotalGasUsed())Builder Pattern
For more complex simulations, use the builder pattern.
const result = await client.simulate()
.call({
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data: '0xa9059cbb0000000000000000000000001234567890123456789012345678901234567890000000000000000000000000000000000000000000000000000000000000000a'
})
.forAccount('0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c')
.withAssetChanges(true)
.withValidation(true)
.atBlock('latest')
.execute()
// Asset changes tracking
if (result.assetChanges) {
const summary = result.getAssetChangesSummary()
summary.forEach(change => {
console.log(`${change.symbol}: ${change.netChange} (${change.type})`)
})
}Returns
ExtendedSimulationResult
The simulation result with helper methods.
Parameters
call
- Type:
TransactionCall
The transaction call to simulate.
const result = await client.simulateCall({
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data: '0x095ea7b3...'
})options.blockTag (optional)
- Type:
'latest' | 'earliest' | 'pending' | 'safe' | 'finalized' - Default:
'latest'
The block tag to simulate against.
const result = await client.simulateCall(
{ /* transaction */ },
{ blockTag: 'safe' }
)options.validation (optional)
- Type:
boolean - Default:
true
Enable or disable EVM validation.
const result = await client.simulateCall(
{ /* transaction */ },
{ validation: false }
)options.traceAssetChanges (optional)
- Type:
boolean - Default:
false
Track token balance changes. Requires account parameter.
const result = await client.simulateCall(
{ /* transaction */ },
{
account: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
traceAssetChanges: true
}
)State Overrides
Modify account states before simulation.
const result = await client.simulate()
.call({
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data: '0xa9059cbb...'
})
.withStateOverrides([{
address: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
balance: '0x1bc16d674ec80000', // 2 ETH
nonce: 10
}, {
address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
code: '0x608060405...', // Override bytecode
storage: {
'0x0': '0x1234' // Set storage slot
}
}])
.execute()Block Overrides
Modify block parameters for simulation.
const result = await client.simulate()
.call({ /* transaction */ })
.withBlockOverrides({
timestamp: Math.floor(Date.now() / 1000) + 3600,
number: '0x1234567',
baseFeePerGas: '0x3b9aca00',
gasLimit: '0x1c9c380' // 30M gas
})
.execute()Batch Simulations
Sequential Batch
const config = {
simulations: [
{
params: {
calls: [{
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data: '0x70a08231...'
}]
},
options: null
},
{
params: {
calls: [{
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
data: '0x70a08231...'
}]
},
options: null
}
],
stopOnFailure: true
}
const batch = await client.simulateBatch(config)
console.log(`Success: ${batch.successCount}/${batch.results.length}`)Batch API
const results = await client.simulateBatchAPI([
{
params: {
calls: [{ /* transaction 1 */ }],
blockNumber: '0x1234567'
},
options: null
},
{
params: {
calls: [{ /* transaction 2 */ }],
blockNumber: '0x1234567'
},
options: null
}
])
results.forEach((result, i) => {
console.log(`Simulation ${i + 1}:`, result.isSuccess() ? 'Success' : 'Failed')
})Error Handling
import { AltitraceApiError, ValidationError } from '@altitrace/sdk'
try {
const result = await client.simulateCall({
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data: '0xa9059cbb...'
})
if (result.isFailed()) {
const errors = result.getErrors()
errors.forEach(error => {
console.error(`Error: ${error.reason} (${error.errorType})`)
})
}
} catch (error) {
if (error instanceof ValidationError) {
console.error('Invalid input:', error.message)
} else if (error instanceof AltitraceApiError) {
console.error('API error:', error.code, error.message)
}
}Types
interface TransactionCall {
from?: string | null
to?: string | null
data?: string | null
value?: string | null
gas?: string | null
accessList?: AccessList | null
}
interface ExtendedSimulationResult {
simulationId: string
status: 'success' | 'reverted' | 'failed'
blockNumber: string
gasUsed: string
blockGasUsed: string
calls: CallResult[]
assetChanges?: AssetChange[] | null
// Helper methods
isSuccess(): boolean
isFailed(): boolean
getTotalGasUsed(): bigint
getCallGasUsed(callIndex: number): bigint
getErrors(): CallError[]
getAssetChangesSummary(): AssetChangeSummary[]
getDecodedEvents(): DecodedEvent[]
getLogCount(): number
}