alchemy_simulateAssetChanges — Ethereum JSON-RPC

Status: Available

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.

POSThttps://triport.io/eth
Network
Ethereum
Auth
x-token: $TRIPORT_API_KEY (or Authorization: Bearer)
Rate limit
Pro — 5 RPS sustained · up to 10 burst · Business — 15 RPS sustained · up to 30 burst (with burst); Burst capacity

Endpoint and plans: Ethereum RPC endpoint.

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 is rejected with HTTP 403 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
403tier_insufficientYour plan is below the Pro tier required for alchemy_simulateAssetChanges. A plain HTTP error rejected before the RPC layer: the body carries current_tier, required_tier and upgrade_url at the top level, plus an X-Required-Tier header.
429rate_limitedYou exceeded your tier's RPS limit (5 RPS sustained · up to 10 burst on Pro, 15 RPS sustained · up to 30 burst on Business). A plain HTTP error: the body carries limit_rps, burst_capacity and retry_after_sec, plus Retry-After and X-RateLimit-Reset headers.

Example response body (tier too low) — HTTP 403, a plain body with no JSON-RPC envelope:

{
  "error": "tier_insufficient",
  "message": "tier insufficient for method alchemy_simulateAssetChanges",
  "method": "alchemy_simulateAssetChanges",
  "category": "eth_trace",
  "chain": "eth",
  "current_tier": "free",
  "required_tier": "pro",
  "upgrade_url": "https://triport.io/upgrade"
}

Example response body (rate limited) — HTTP 429, also a plain body:

{
  "error": "rate_limited",
  "message": "Rate limit exceeded: 5 RPS sustained on eth_trace (pro tier)",
  "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://triport.io/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}`);
}

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 is rejected with HTTP 403 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.