Skip to main content
The validate endpoint ensures that the unsigned transaction you’re about to sign matches exactly what was simulated. Each field is checked independently, so you know precisely what changed if validation fails.
POST https://shield.api.enso.build/api/v1/validate

Request Parameters

FieldTypeRequiredDescription
simulationIdstring (UUID)YesThe simulationId from a prior /simulate call
transaction.datastringYesHex-encoded calldata
transaction.tostringYesTarget contract address
transaction.fromstringYesSender address
transaction.valuestringYesNative token value in wei
transaction.chainIdnumberYesChain ID

Response

FieldTypeDescription
validbooleantrue only when all checks pass
simulationIdstringThe simulation ID validated against
checks.chainIdbooleanChain ID matches
checks.databooleanCalldata hash matches
checks.tobooleanTarget contract address matches
checks.frombooleanSender address matches
checks.valuebooleanNative token value matches

Examples

Successful Validation

curl -X POST https://shield.api.enso.build/api/v1/validate \
  -H "Authorization: Bearer $ENSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "simulationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "transaction": {
      "data": "0x3593564c...",
      "to": "0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E",
      "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
      "value": "1000000000000000000",
      "chainId": 1
    }
  }'
Response:
{
  "valid": true,
  "simulationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "checks": {
    "chainId": true,
    "data": true,
    "to": true,
    "value": true,
    "from": true
  }
}

Failed Validation (Tampered Data)

If the calldata has been modified since simulation, the data check will fail:
{
  "valid": false,
  "simulationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "checks": {
    "chainId": true,
    "data": false,
    "to": true,
    "value": true,
    "from": true
  }
}

Interpreting Failed Checks

CheckWhen falseLikely Cause
dataCalldata was modifiedTransaction payload was tampered with, or a different function/arguments were encoded
toTarget contract changedThe transaction is being sent to a different contract than simulated
fromSender changedA different account is submitting the transaction
valueETH value changedThe native token amount was modified
chainIdWrong chainThe transaction is targeting a different chain than simulated
If any check fails, do not sign the transaction. Re-simulate to get a fresh simulationId, or investigate why the transaction changed.

Cache Expiry

Simulations are cached for 5 minutes. If you call /validate after the simulation has expired, you’ll receive a 404 error:
{
  "statusCode": 404,
  "message": "Simulation a1b2c3d4-e5f6-7890-abcd-ef1234567890 not found or expired"
}
Re-simulate to get a fresh simulationId and try again.

Best Practices

  • Validate immediately before signing — Don’t validate far in advance. Validate as close to the signing moment as possible within the 5-minute window.
  • Log the simulationId — Store simulation IDs for debugging and audit trails.
  • Re-simulate on failure — If validation fails, re-simulate to get a fresh result rather than retrying the same validation.
  • Check individual fields — When valid is false, inspect the checks object to understand exactly what changed.
async function safeSign(simulationId: string, tx: UnsignedTransaction) {
  const validation = await validate(simulationId, tx);

  if (!validation.valid) {
    const failedChecks = Object.entries(validation.checks)
      .filter(([, passed]) => !passed)
      .map(([field]) => field);

    throw new Error(`Validation failed for: ${failedChecks.join(", ")}`);
  }

  return await wallet.sendTransaction(tx);
}

Updated