Tx Preflight
by TxGuard in Onchain & crypto
Explain and preflight an unsigned Base transaction, EIP-712 typed data, or an EIP-3009 x402 payment authorization before you sign it. Decodes intent against verified ABIs, resolves proxies, classifies approvals, and checks a payment authorization against the quote it claims to pay: recipient, amount, asset, chain, freshness, and nonce replay. Returns unknown rather than guessing when a selector is ambiguous. Not a guarantee that a transaction is safe or profitable.
https://txguard.schemasure.com/v1/tx/preflight- Price
- $0.02
- per call in USDC
- Uptime
- 100%
- last 30 days
- Response time
- 363 ms
- 442 ms slowest 5%
- Last check
- Passed
- 2 h ago, next any minute now
Reliability
How to call it
POST https://txguard.schemasure.com/v1/tx/preflight
Each call costs $0.02 in USDC on Base, paid with the request over x402.
Run a free test callOne unpaid request, the way an agent sends it. You see the payment challenge it gets back. Nothing is charged.
Example request
From the listing.
POST https://txguard.schemasure.com/v1/tx/preflight
content-type: application/json
{
"expected_quote": {
"amount": "10000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"extra": {
"name": "USD Coin",
"version": "2"
},
"maxTimeoutSeconds": 60,
"network": "eip155:8453",
"payTo": "0x1a2B3c4D5E6F7a8B9c0D1e2F3A4b5C6d7E8F9a0b",
"scheme": "exact"
},
"unsigned_tx": {
"data": "0xa9059cbb0000000000000000000000005d3e1a9b7c2f4e8a0b6d3c5f9e1a7b4d2c8f0a6e0000000000000000000000000000000000000000000000000000000000002710",
"from": "0x9F2C5E4A8db1C3a7E6B0d4f8C1E2a5b7D9C0e3F4",
"to": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"value": "0"
}
}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
authorization | object | No | An EIP-3009 authorization, which is what an x402 `exact` payment is. value in base units, validAfter/validBefore in unix seconds, nonce 32 random bytes not a counter. |
expected_quote | object | No | The x402 quote this payment claims to satisfy. Enables the comparison checks. |
simulate | boolean | No | Run eth_simulateV1 with asset tracing. Priced at $0.03 instead of $0.02, and targets P50 2s / P95 5s rather than the static path's 500ms / 2s. Default: false. |
tx_hash | string | No | An existing Base transaction to explain. |
typed_data | object | No | EIP-712 payload. TransferWithAuthorization and ReceiveWithAuthorization get the x402 check table; any other primaryType is reported unrecognised, not analysed. |
unsigned_tx | object | No | A transaction you are about to sign. `to: null` is a deployment. |
Example response
The provider's example. We can't check it without paying.
Example response, 158 lines
{
"confidence": 1,
"data_versions": {
"abi_packs": "2026-08-03.1",
"chain": "eip155:8453",
"denylist": "2026-08-03.1",
"policy": "2026-08-03",
"signature_index": "2026-08-03.1"
},
"evidence": [
{
"code": "RECIPIENT_MISMATCH",
"data": {
"actual": "0x5D3e1a9b7c2f4E8A0b6d3c5F9E1A7b4D2C8f0a6E",
"expected": "0x1a2B3c4D5E6F7a8B9c0D1e2F3A4b5C6d7E8F9a0b",
"field": "payTo"
},
"detail": "Pays 0x5D3e1a9b7c2f4E8A0b6d3c5F9E1A7b4D2C8f0a6E, but the quote names 0x1a2B3c4D5E6F7a8B9c0D1e2F3A4b5C6d7E8F9a0b. Signing this pays someone other than the party you are buying from.",
"severity": "critical",
"source": "quote-comparison"
},
{
"code": "RPC_UNAVAILABLE",
"detail": "No Base RPC endpoint is configured, so chain-dependent fields are unknown rather than assumed. See result.unresolved.",
"severity": "medium",
"source": "rpc"
}
],
"ok": true,
"policy_version": "2026-08-03",
"request_hash": "sha256:6d5c717eb5eede165dada2645ad0944430ff492739cf58d0c2dad2b812f0ddb4",
"result": {
"approvals": [],
"authorization_checks": [],
"candidate_signatures": [],
"chain": "eip155:8453",
"denylist_hits": [],
"expected_transfers": [
{
"amount": "10000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"asset_kind": "erc20",
"from": "0x9f2C5E4a8DB1C3A7e6b0d4f8C1e2A5b7d9c0E3f4",
"source": "decode",
"to": "0x5D3e1a9b7c2f4E8A0b6d3c5F9E1A7b4D2C8f0a6E",
"token_id": null
}
],
"input_shape": "unsigned_tx",
"intent": {
"args": [
{
"name": "to",
"type": "address",
"value": "0x5D3e1a9b7c2f4E8A0b6d3c5F9E1A7b4D2C8f0a6E"
},
{
"name": "amount",
"type": "uint256",
"value": "10000"
}
],
"calls": [],
"decode_source": "bundled-abi",
"depth": 0,
"function_name": "transfer",
"kind": "erc20_transfer",
"selector": "0xa9059cbb",
"signature": "transfer(address,uint256)",
"standard": "erc20",
"summary": "Transfer 10000 base units of token 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 to 0x5D3e1a9b7c2f4E8A0b6d3c5F9E1A7b4D2C8f0a6E.",
"target": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"truncated": false,
"value_wei": "0"
},
"permit_scope": null,
"proxy": {
"address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"admin": null,
"beacon": null,
"detail": "no RPC endpoint is configured, so no slot could be read",
"implementation": null,
"kind": "unknown",
"slots_probed": [],
"upgradeable": null
},
"quote_comparison": {
"detail": "2 of 3 comparable fields match",
"fields": [
{
"actual": "0x5D3e1a9b7c2f4E8A0b6d3c5F9E1A7b4D2C8f0a6E",
"expected": "0x1a2B3c4D5E6F7a8B9c0D1e2F3A4b5C6d7E8F9a0b",
"field": "payTo",
"matches": false
},
{
"actual": "10000",
"expected": "10000",
"field": "amount",
"matches": true
},
{
"actual": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"expected": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"field": "asset",
"matches": true
},
{
"actual": null,
"expected": "8453",
"field": "chainId",
"matches": null
},
{
"actual": null,
"expected": "USD Coin",
"field": "extra.name",
"matches": null
},
{
"actual": null,
"expected": "2",
"field": "extra.version",
"matches": null
}
],
"matches": false,
"present": true
},
"rpc": {
"configured": false,
"endpoints": [],
"reachable": null
},
"simulation": {
"asset_changes": [],
"block_number": null,
"detail": "simulation was not requested; send simulate: true to run one",
"gas_used": null,
"requested": false,
"status": "not_requested"
},
"spender": {
"address": null,
"detail": "this transaction grants no allowance, so it has no spender",
"is_contract": null
},
"unresolved": [
"proxy status of 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 is unknown: no RPC endpoint is configured, so no slot could be read"
]
},
"risk_codes": [
"RECIPIENT_MISMATCH",
"RPC_UNAVAILABLE"
],
"verdict": "block",
"warnings": []
}Call it from code
The curl command shows the payment challenge. The JavaScript and Python versions pay and call, and never pay more than $0.02.
curl: see the payment challenge
# bash or zsh: see the payment challenge. Nothing is charged.
curl -sS -g -i -X POST 'https://txguard.schemasure.com/v1/tx/preflight' \
-H 'content-type: application/json' \
--data-raw '{"expected_quote":{"amount":"10000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"name":"USD Coin","version":"2"},"maxTimeoutSeconds":60,"network":"eip155:8453","payTo":"0x1a2B3c4D5E6F7a8B9c0D1e2F3A4b5C6d7E8F9a0b","scheme":"exact"},"unsigned_tx":{"data":"0xa9059cbb0000000000000000000000005d3e1a9b7c2f4e8a0b6d3c5f9e1a7b4d2c8f0a6e0000000000000000000000000000000000000000000000000000000000002710","from":"0x9F2C5E4A8db1C3a7E6B0d4f8C1E2a5b7D9C0e3F4","to":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","value":"0"}}'
# x402 v2 sends the challenge base64-encoded in the PAYMENT-REQUIRED header (v1 sends it in the body).
# To read the header:
curl -sS -g -o /dev/null -D - -X POST 'https://txguard.schemasure.com/v1/tx/preflight' \
-H 'content-type: application/json' \
--data-raw '{"expected_quote":{"amount":"10000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"name":"USD Coin","version":"2"},"maxTimeoutSeconds":60,"network":"eip155:8453","payTo":"0x1a2B3c4D5E6F7a8B9c0D1e2F3A4b5C6d7E8F9a0b","scheme":"exact"},"unsigned_tx":{"data":"0xa9059cbb0000000000000000000000005d3e1a9b7c2f4e8a0b6d3c5f9e1a7b4d2c8f0a6e0000000000000000000000000000000000000000000000000000000000002710","from":"0x9F2C5E4A8db1C3a7E6B0d4f8C1E2a5b7D9C0e3F4","to":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","value":"0"}}' \
| grep -i '^payment-required:' | cut -d' ' -f2 | tr -d '\r' | base64 --decodeJavaScript: pay and call
// npm i @x402/fetch @x402/evm viem
import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
// Pays at most $0.02 per call.
const client = new x402Client().setSpendControls({ maxAmountPerPayment: "$0.02" });
registerExactEvmScheme(client, { signer: privateKeyToAccount(process.env.EVM_PRIVATE_KEY) });
const pay = wrapFetchWithPayment(fetch, client);
// Not sure it's safe to pay? ToolVet checks it first for $0.005. Pay for that from a separate
// client: this one is capped at $0.02 per payment. GET https://toolvet.app/api/v1/check?url=https%3A%2F%2Ftxguard.schemasure.com%2Fv1%2Ftx%2Fpreflight&method=POST
const res = await pay("https://txguard.schemasure.com/v1/tx/preflight", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
"expected_quote": {
"amount": "10000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"extra": {
"name": "USD Coin",
"version": "2"
},
"maxTimeoutSeconds": 60,
"network": "eip155:8453",
"payTo": "0x1a2B3c4D5E6F7a8B9c0D1e2F3A4b5C6d7E8F9a0b",
"scheme": "exact"
},
"unsigned_tx": {
"data": "0xa9059cbb0000000000000000000000005d3e1a9b7c2f4e8a0b6d3c5f9e1a7b4d2c8f0a6e0000000000000000000000000000000000000000000000000000000000002710",
"from": "0x9F2C5E4A8db1C3a7E6B0d4f8C1E2a5b7D9C0e3F4",
"to": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"value": "0"
}
}),
});
console.log(res.status, await res.text());Python: pay and call
# pip install "x402[requests,evm]"
import os
from eth_account import Account
from x402 import x402ClientSync
from x402.http.clients import x402_requests
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
# Pays at most $0.02 per call.
client = x402ClientSync().set_spend_controls({"max_amount_per_payment": "$0.02"})
register_exact_evm_client(client, EthAccountSigner(Account.from_key(os.environ["EVM_PRIVATE_KEY"])))
with x402_requests(client) as session:
res = session.post(
"https://txguard.schemasure.com/v1/tx/preflight",
json={
"expected_quote": {
"amount": "10000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"extra": {
"name": "USD Coin",
"version": "2",
},
"maxTimeoutSeconds": 60,
"network": "eip155:8453",
"payTo": "0x1a2B3c4D5E6F7a8B9c0D1e2F3A4b5C6d7E8F9a0b",
"scheme": "exact",
},
"unsigned_tx": {
"data": "0xa9059cbb0000000000000000000000005d3e1a9b7c2f4e8a0b6d3c5f9e1a7b4d2c8f0a6e0000000000000000000000000000000000000000000000000000000000002710",
"from": "0x9F2C5E4A8db1C3a7E6B0d4f8C1E2a5b7D9C0e3F4",
"to": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"value": "0",
},
},
)
print(res.status_code, res.text)Security scan
No findings
We scan names, descriptions and tool definitions for hidden instructions and other prompt-injection patterns.
Recent checks
| When | Result | HTTP | Time | Price |
|---|---|---|---|---|
| 2 h ago | Passed | 402 | 338 ms | $0.02 |
| 6 h ago | Passed | 402 | 376 ms | $0.02 |
| 10 h ago | Passed | 402 | 402 ms | $0.02 |
| 14 h ago | Passed | 402 | 442 ms | $0.02 |
| 18 h ago | Passed | 402 | 354 ms | $0.02 |
Show 10 older checks
| 22 h ago | Passed | 402 | 385 ms | $0.02 |
| 25 h ago | Passed | 402 | 319 ms | $0.02 |
| 29 h ago | Passed | 402 | 363 ms | $0.02 |
| 33 h ago | Passed | 402 | 503 ms | $0.02 |
| 36 h ago | Passed | 402 | 336 ms | $0.02 |
| 40 h ago | Passed | 402 | 361 ms | $0.02 |
| 44 h ago | Passed | 402 | 276 ms | $0.02 |
| 47 h ago | Passed | 402 | 338 ms | $0.02 |
| 2 days ago | Passed | 402 | 363 ms | $0.02 |
| 2 days ago | Passed | 402 | 340 ms | $0.02 |