{"name":"check_tx","oldName":"preflight_transaction","title":"Safe to sign?","category":"transactions","useWhen":"Run on every transaction before you sign it. Shows what each wallet gains and loses, blocks drainer tricks, and catches failures and expired blockhashes before you pay a fee.","benefit":{"kind":"money","text":"Catches a drainer approval or a transaction that will fail, before you sign. Failed transactions still cost fees. One hidden approval can empty a wallet."},"description":"Decodes every step, dry-runs the transaction on live mainnet, works out each wallet's SOL and token changes, and answers OK, REVIEW or BLOCK with the reasons.","price":"$0.02","priceText":"25 free calls a day, then $0.02 USDC per call (x402)","http":{"method":"POST","path":"/api/tools/check_tx","body":"JSON object with the inputs below"},"mcp":{"method":"tools/call","name":"check_tx"},"inputs":[{"name":"tx","type":"string (base64)","required":true,"lookingFor":"The transaction, base64-encoded. Signed or not. Legacy and v0 both work.","whereToGet":"From your wallet SDK before signing: Buffer.from(tx.serialize({ requireAllSignatures: false })).toString('base64'). Or the swap transaction an aggregator API gave you."},{"name":"network","type":"\"mainnet-beta\" | \"devnet\"","required":false,"lookingFor":"Which Solana network to read. Default \"mainnet-beta\" (real money).","whereToGet":"Leave it out for mainnet. Use \"devnet\" only for test wallets."}],"outputs":[{"field":"verdict","type":"\"OK\" | \"REVIEW\" | \"BLOCK\"","is":"The answer. BLOCK: don't sign. REVIEW: a person or your rules should look first. OK: nothing wrong found.","howWorkedOut":"The worst check wins: any fail is BLOCK, any warn is REVIEW, otherwise OK."},{"field":"summary","type":"string","is":"One sentence: the verdict and the main reason.","howWorkedOut":"Built from the worst check and what your wallet sends."},{"field":"fee_payer / signers","type":"string / string[]","is":"The wallet paying the fee, and every wallet that signs.","howWorkedOut":"Read from the transaction."},{"field":"checks[].name","type":"string","is":"Which check: simulation, blockhash, fee_payer_balance, token_approval, authority_change, wallet_reassigned, close_to_other, unknown_programs, priority_fee or outflow.","howWorkedOut":"A fixed list."},{"field":"checks[].result","type":"\"pass\" | \"info\" | \"warn\" | \"fail\"","is":"How the check came out.","howWorkedOut":"simulation fails if the dry run errors. blockhash warns if expired. fee_payer_balance fails if the payer can't cover fees. Approvals to non-signers, authority changes, reassigning a signer and closing to a non-signer fail. Unknown programs warn. A priority fee over 0.01 SOL warns. Money leaving your wallet is info."},{"field":"checks[].detail","type":"string","is":"What the check found, in plain words.","howWorkedOut":"Built from the decoded steps and the dry run."},{"field":"balance_changes[].wallet","type":"string","is":"The wallet whose balance changes.","howWorkedOut":"For SOL, the account itself. For tokens, the owner of the token account."},{"field":"balance_changes[].is_you","type":"boolean","is":"True when this wallet signs the transaction, so it's you.","howWorkedOut":"The wallet is one of the required signers."},{"field":"balance_changes[].token / symbol","type":"string","is":"\"SOL\" or the token address, and its ticker.","howWorkedOut":"From the account data. Ticker from Jupiter."},{"field":"balance_changes[].before / after / change","type":"string (decimal)","is":"Balance before, after, and the difference. Negative means the wallet loses it.","howWorkedOut":"Before: live account data. After: the dry run's account data. Exact decimals. SOL changes include fees."},{"field":"balance_changes[].raw_change / decimals","type":"string / number","is":"The change in raw units, and the token's decimals.","howWorkedOut":"after minus before, in base units."},{"field":"steps[]","type":"object[]","is":"Every instruction, decoded: step number, program, type (sol_transfer, token_transfer, token_approve, token_set_authority, token_close_account, create_token_account, set_compute_unit_price, unknown_program and more) and its key details.","howWorkedOut":"Decoded for the System, Token, Token-2022, Compute Budget, Associated Token Account and Memo programs."},{"field":"fee.base_lamports / priority_lamports / total_lamports / total_sol","type":"string","is":"What this transaction costs in fees.","howWorkedOut":"Base: 5000 lamports per signature. Priority: compute_unit_price x compute_unit_limit / 1,000,000, rounded up."},{"field":"fee.compute_unit_limit / compute_unit_limit_from / compute_unit_price","type":"number | string","is":"The compute settings the fee is charged on. compute_unit_price is in micro-lamports per compute unit.","howWorkedOut":"From the transaction's Compute Budget steps, or the runtime default when there are none."},{"field":"simulation.worked / error / compute_used / logs","type":"object","is":"The raw dry run: whether it worked, the error, compute used, and the last 25 log lines.","howWorkedOut":"simulateTransaction with signature checks off and a fresh blockhash."},{"field":"simulation.error_explained","type":"object | null","is":"What the failure means, in plain words.","howWorkedOut":"why_failed run on the dry-run error."}],"notes":["The dry run uses the chain as it is now. If things change before you send, the real result can differ.","Balance changes cover up to 64 writable accounts."],"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"tx":{"type":"string","minLength":20},"network":{"default":"mainnet-beta","type":"string","enum":["mainnet-beta","devnet"]}},"required":["tx"]}}