Skip to main content

Method

async simulateTransaction(params: SwapSimulationParams): Promise<SimulationResult>
Simulates a transaction execution without broadcasting it to the blockchain. This allows you to preview asset changes, detect potential failures, and identify risks before executing the actual transaction.

Parameters

params
SwapSimulationParams
required
Transaction simulation parameters

Response

success
boolean
Whether the simulation was successful (transaction would succeed)
gasUsed
string
Estimated gas consumption
error
string
Error message if simulation failed
logs
any
Debug logs (when includeDebug is true)
assetChanges
array
Array of asset changes resulting from the transaction
risks
array
Array of detected risks

Example

Simulate Swap Transaction

import { OKXClient } from '@okxweb3/okx-api';

const client = new OKXClient({
  apiKey: 'your-api-key',
  secretKey: 'your-secret-key',
  apiPassphrase: 'your-passphrase',
  projectId: 'your-project-id'
});

// Get swap data
const swapData = await client.dex.getSwapData({
  chainIndex: '1',
  fromTokenAddress: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
  toTokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  amount: '1000000000000000000',
  slippagePercent: '0.005',
  userWalletAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e'
});

const tx = swapData.data[0].tx;

// Simulate the transaction
const simulation = await client.dex.simulateTransaction({
  fromAddress: tx.from,
  toAddress: tx.to,
  chainIndex: '1',
  txAmount: tx.value,
  extJson: {
    inputData: tx.data
  },
  gasPrice: tx.gasPrice,
  includeDebug: true
});

if (simulation.success) {
  console.log('Simulation successful!');
  console.log('Gas used:', simulation.gasUsed);
  console.log('Asset changes:', simulation.assetChanges);
} else {
  console.error('Simulation failed:', simulation.error);
}

Check Asset Changes

const simulation = await client.dex.simulateTransaction(params);

if (simulation.success) {
  simulation.assetChanges.forEach(change => {
    const humanAmount = parseFloat(change.amount) / Math.pow(10, change.decimals);
    console.log(
      `${change.direction}: ${humanAmount.toFixed(6)} ${change.symbol}`
    );
  });
}

Response Example

Successful Simulation

{
  "success": true,
  "gasUsed": "185432",
  "assetChanges": [
    {
      "direction": "SEND",
      "symbol": "ETH",
      "type": "native",
      "amount": "-1000000000000000000",
      "decimals": 18,
      "address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
    },
    {
      "direction": "RECEIVE",
      "symbol": "USDC",
      "type": "erc20",
      "amount": "2487500000",
      "decimals": 6,
      "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
    }
  ],
  "risks": []
}

Failed Simulation

{
  "success": false,
  "error": "execution reverted: insufficient balance",
  "assetChanges": [],
  "risks": []
}

With Risks Detected

{
  "success": true,
  "gasUsed": "200000",
  "assetChanges": [...],
  "risks": [
    {
      "addressType": "honeypot",
      "address": "0x..."
    }
  ]
}

Use Cases

Pre-flight Validation

async function validateSwapBeforeExecution(swapParams: SwapParams) {
  // Get swap data
  const swapData = await client.dex.getSwapData(swapParams);
  const tx = swapData.data[0].tx;

  // Simulate the transaction
  const simulation = await client.dex.simulateTransaction({
    fromAddress: tx.from,
    toAddress: tx.to,
    chainIndex: swapParams.chainIndex!,
    txAmount: tx.value,
    extJson: { inputData: tx.data },
    gasPrice: tx.gasPrice,
    includeDebug: false
  });

  if (!simulation.success) {
    throw new Error(`Transaction would fail: ${simulation.error}`);
  }

  if (simulation.risks.length > 0) {
    console.warn('Risks detected:', simulation.risks);
  }

  return simulation;
}

Display Preview to User

const simulation = await client.dex.simulateTransaction(params);

if (simulation.success) {
  console.log('Transaction Preview:');
  console.log('━'.repeat(50));

  simulation.assetChanges.forEach(change => {
    const amount = parseFloat(change.amount) / Math.pow(10, change.decimals);
    const prefix = change.direction === 'SEND' ? '-' : '+';
    console.log(`${prefix} ${Math.abs(amount).toFixed(6)} ${change.symbol}`);
  });

  console.log('━'.repeat(50));
  console.log(`Estimated Gas: ${simulation.gasUsed}`);

  if (simulation.risks.length > 0) {
    console.log('\n⚠️  Warnings:');
    simulation.risks.forEach(risk => {
      console.log(`  - ${risk.addressType}: ${risk.address}`);
    });
  }
}

Gas Estimation

const simulation = await client.dex.simulateTransaction(params);

if (simulation.success && simulation.gasUsed) {
  const gasLimit = Math.ceil(parseFloat(simulation.gasUsed) * 1.2); // Add 20% buffer
  console.log('Recommended gas limit:', gasLimit);
}

Slippage Verification

const simulation = await client.dex.simulateTransaction(params);

if (simulation.success) {
  const received = simulation.assetChanges.find(c => c.direction === 'RECEIVE');
  const expectedAmount = swapData.data[0].routerResult.toTokenAmount;

  if (received && BigInt(received.amount) < BigInt(expectedAmount)) {
    const slippage = (
      (parseFloat(expectedAmount) - parseFloat(received.amount)) /
      parseFloat(expectedAmount)
    ) * 100;
    console.log(`Actual slippage: ${slippage.toFixed(2)}%`);
  }
}

Risk Detection

async function checkTransactionRisks(params: SwapSimulationParams) {
  const simulation = await client.dex.simulateTransaction(params);

  const riskLevels = {
    honeypot: 'HIGH',
    scam: 'CRITICAL',
    suspicious: 'MEDIUM'
  };

  if (simulation.risks.length > 0) {
    const highestRisk = simulation.risks.reduce((max, risk) => {
      const currentLevel = riskLevels[risk.addressType] || 'LOW';
      return currentLevel > max ? currentLevel : max;
    }, 'LOW');

    return {
      hasRisks: true,
      riskLevel: highestRisk,
      risks: simulation.risks
    };
  }

  return { hasRisks: false };
}

Error Handling

try {
  const simulation = await client.dex.simulateTransaction(params);
  
  if (!simulation.success) {
    // Handle simulation failure
    if (simulation.error?.includes('insufficient')) {
      console.error('Insufficient balance');
    } else if (simulation.error?.includes('revert')) {
      console.error('Transaction would revert:', simulation.error);
    } else {
      console.error('Simulation failed:', simulation.error);
    }
  }
} catch (error) {
  console.error('Simulation request failed:', error.message);
}

Notes

  • Simulations are performed against the current blockchain state
  • Results may differ if blockchain state changes before actual execution
  • Gas estimates include a margin for safety
  • Risk detection helps identify potentially malicious contracts
  • Debug logs are only included when includeDebug is true
  • EVM chains only (not supported for Solana)

Build docs developers (and LLMs) love