Skip to content

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
}