TriportRPC

alchemy_simulateAssetChanges

POSThttps://api.triport.io/v1/eth

Simulates a single transaction against the latest state and returns the asset balance changes (ETH, ERC-20, ERC-721, ERC-1155) it would produce — without broadcasting it.

EthereumPro — 5 RPS · Business — 15 RPS (with burst)

alchemy_simulateAssetChanges runs a transaction through the EVM against the current chain state and reports the asset movements it would cause if it were mined now. Use it to preview the effect of a transaction — how much ETH and which tokens leave or enter each address — before asking a user to sign, so you can show an accurate "you will send / you will receive" summary and catch unexpected approvals or transfers.

The simulation is read-only: the transaction is not submitted to the network and no gas is spent. Results reflect the latest committed state at the time of the call, so a transaction that simulates cleanly can still revert or produce different changes once on-chain if state shifts in between.

This method belongs to the eth_trace category and is available on the Pro tier (5 RPS) and Business tier (15 RPS). A request from a lower tier returns -32002 (tier_insufficient).

Parameters

A single positional parameter: the transaction object to simulate. Fields use the same hex-quantity and hex-data encoding as eth_call / eth_sendTransaction.

transactionobjectrequired
The transaction to simulate.
transaction.fromstring (address)required
Sender address; balance changes are computed relative to this account.
transaction.tostring (address)optional
Recipient or contract address. Omit for contract-creation simulations.
transaction.valuestring (hex quantity)optional
Wei to send, hex-encoded (e.g. "0xde0b6b3a7640000" for 1 ETH). Defaults to 0x0.
transaction.datastring (hex data)optional
Call data / encoded function call.
transaction.gasstring (hex quantity)optional
Gas limit for the simulation.

Response

Response fields

FieldTypeDescription
jsonrpcstringJSON-RPC protocol version, always "2.0".
idnumber | stringEchoes the request id.
resultobjectThe simulation outcome.
result.changesarrayOne entry per asset movement the transaction would cause. Empty if it moves no assets.
result.changes[].assetTypestringAsset class: NATIVE (ETH), ERC20, ERC721, or ERC1155.
result.changes[].changeTypestringTRANSFER or APPROVE.
result.changes[].fromstring (address)Address the asset leaves.
result.changes[].tostring (address)Address the asset arrives at.
result.changes[].rawAmountstringAmount in base units (no decimal scaling).
result.changes[].amountstringHuman-readable amount, scaled by decimals.
result.changes[].symbolstring | nullToken symbol, when known.
result.changes[].decimalsnumber | nullToken decimals, when known.
result.changes[].contractAddressstring | nullToken contract; null for native ETH.
result.changes[].tokenIdstring | nullToken id for ERC-721 / ERC-1155; null otherwise.
result.gasUsedstring (hex quantity)Gas the transaction consumed in simulation.
result.errorstring | nullRevert reason if the transaction would revert; null on success.

Errors

CodeMeaningWhen it happens
-32002tier_insufficientYour plan is below the Pro tier required for alchemy_simulateAssetChanges. The error data includes current_tier, required_tier, and an upgrade_url.
-32003rate_limitedYou exceeded your tier's RPS limit (5 RPS on Pro, 15 RPS on Business). The error data includes limit_rps, burst_capacity, and retry_after_sec.

Example error envelope (tier too low):

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32002,
    "message": "tier insufficient for method alchemy_simulateAssetChanges",
    "data": {
      "method": "alchemy_simulateAssetChanges",
      "category": "eth_trace",
      "chain": "eth",
      "current_tier": "free",
      "required_tier": "pro",
      "upgrade_url": "https://api.triport.io/upgrade"
    }
  }
}

Example error envelope (rate limited):

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32003,
    "message": "Rate limit exceeded: 5 RPS sustained on eth_trace (pro tier)",
    "data": {
      "current_tier": "pro",
      "category": "eth_trace",
      "limit_rps": 5,
      "burst_capacity": 10,
      "retry_after_sec": 1
    }
  }
}

A 429 also carries a Retry-After header. See errors.md for the full error envelope and the shared error-code reference.

Examples

JavaScript (fetch)

const res = await fetch("https://api.triport.io/v1/eth", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.TRIPORT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "alchemy_simulateAssetChanges",
    params: [
      {
        from: "0xf1a726210550c306a9964b251cbcd3fa5ecb275d",
        to: "0x2e2ed0cfd3ad2f1d34481277b3204d807ca2f8c2",
        value: "0xde0b6b3a7640000",
        data: "0x",
      },
    ],
  }),
});


const { result } = await res.json();
for (const change of result.changes) {
  console.log(`${change.amount} ${change.symbol}: ${change.from} -> ${change.to}`);
}

TypeScript SDK (@triport/sdk)

import { Triport } from "@triport/sdk";


const client = new Triport({ apiKey: process.env.TRIPORT_API_KEY });


const result = await client.eth.request("alchemy_simulateAssetChanges", [
  {
    from: "0xf1a726210550c306a9964b251cbcd3fa5ecb275d",
    to: "0x2e2ed0cfd3ad2f1d34481277b3204d807ca2f8c2",
    value: "0xde0b6b3a7640000",
    data: "0x",
  },
]);


console.log(result.changes);

Python (triport-sdk)

import os
from triport import Triport


client = Triport(api_key=os.environ["TRIPORT_API_KEY"])


result = client.eth.request("alchemy_simulateAssetChanges", [
    {
        "from": "0xf1a726210550c306a9964b251cbcd3fa5ecb275d",
        "to": "0x2e2ed0cfd3ad2f1d34481277b3204d807ca2f8c2",
        "value": "0xde0b6b3a7640000",
        "data": "0x",
    },
])


for change in result["changes"]:
    print(change["amount"], change["symbol"], change["from"], "->", change["to"])

Notes

  • The transaction is simulated against the latest committed state and is never broadcast — re-simulate just before signing for time-sensitive flows, since state can move between the call and the on-chain inclusion.
  • If the transaction would revert, result.error carries the revert reason and result.changes reflects only the changes up to the revert point.
  • Requires the Pro tier or higher; a lower tier returns -32002 (tier_insufficient).
  • Rate limiting is RPS-per-tier with burst; there is no daily quota.
  • To simulate a sequence of transactions together rather than a single one, see alchemy_simulateExecutionBundle.