Skip to main content
Pending tool calls can include a SimulationResult that previews what should happen when the transaction executes.

When simulation data is available

Check simulated and simulation on each pending tool:
const result = await sdk.sendMessage(
  'Swap 1 ETH to USDC on Base',
  { userContext: { address: '0x1234...' } },
)

if (result.response.isError) {
  throw new Error(result.response.error.message)
}

for (const tool of result.response.data.pendingTools ?? []) {
  if (tool.simulated && tool.simulation) {
    showConfirmation(tool)
  } else {
    executeDirectly(tool)
  }
}

Building a confirmation screen

Asset changes

assetChanges lists the expected token balance changes:
function renderAssetChanges(simulation: SimulationResult) {
  for (const change of simulation.assetChanges) {
    const sign = change.direction === 'out' ? '-' : '+'
    console.log(`${sign}${change.formattedAmount} ${change.tokenSymbol} ($${change.usdValue})`)
  }
}
Useful fields:
  • tokenSymbol
  • tokenName
  • formattedAmount
  • rawAmount
  • usdValue
  • direction
  • logoUrl

Gas estimate

function renderGas(simulation: SimulationResult) {
  const gas = simulation.gasEstimate
  const symbol = simulation.nativeTokenSymbol ?? 'ETH'
  console.log(`Network fee: ${gas.gasCostNative} ${symbol} ($${gas.gasCostUsd})`)
}

Failure prediction

if (!simulation.willSucceed) {
  console.warn('This transaction is likely to fail.')
  if (simulation.errorExplanation) {
    console.warn('Reason:', simulation.errorExplanation)
  }
}

Action type context

Use actionType to adapt the UI by operation type:
switch (simulation.actionType) {
  case 'swap':
    renderSwapPreview(simulation)
    break
  case 'bridge':
    renderBridgePreview(simulation)
    break
  case 'transfer':
    renderTransferPreview(simulation)
    break
  default:
    renderGenericPreview(simulation)
}

Cross-chain operations

For bridge-style previews, sourceChainId and destChainId identify the chains involved:
if (simulation.actionType === 'bridge') {
  console.log(`From chain ${simulation.sourceChainId} to chain ${simulation.destChainId}`)
}

Fallback metadata

When asset changes are unavailable, actionMetadata still gives you structured UI hints:
if (simulation.assetChanges.length === 0 && simulation.actionMetadata) {
  const meta = simulation.actionMetadata
  console.log(`${meta.inputAmount} ${meta.inputToken} -> ${meta.outputAmount} ${meta.outputToken}`)
  if (meta.protocol) console.log(`via ${meta.protocol}`)
}

Simulation is display-only

Simulation data should not drive execution logic. Always execute using tool.input as the source of truth.

See also