TxWhy

Failed transaction in.
Working transaction out.

TxWhy finds the exact reason a Solana transaction failed, rebuilds it, and proves the rebuilt one works by simulating it against live chain state. For people, bots and AI agents.

Not sent yet? Repair it before you send, or watch a live demo →

Why this exists

On a busy day somewhere between one in eight and one in two Solana transactions fail. Bots and agents fail more than half of what they send, and the priority fee is burned every time. What they get back is a code like Custom(6001). Explorers and AI explainers tell you what happened. TxWhy hands you the transaction that works.

How it works

  1. 01

    Diagnose

    Replays the transaction, walks every inner call, and pins the exact step that broke and why.

  2. 02

    Rebuild

    Applies the fix that matches the cause and leaves everything else exactly as you wrote it.

  3. 03

    Prove

    Simulates the rebuilt transaction on live state. You only get it back if it passes.

The rebuilt transaction comes back unsigned. You sign it with your own wallet. TxWhy never sees a key.

What it handles today

When something cannot be fixed by rebuilding, TxWhy says so. It will never hand back a transaction that would fail again.

One line in your send loop

Most failures happen at simulation, before anything is sent. So that is where the repair belongs. If your transaction passes, it is signed and sent and TxWhy is never contacted. If it would fail, it comes back rebuilt, is checked on your machine, and only then reaches your signer.

npm i @txwhy/sdk
import { sendWithRepair } from "@txwhy/sdk";

// simulate -> repair if it would fail -> verify locally -> sign -> send
const { signature, repairs } = await sendWithRepair(
  connection,
  transaction,
  (tx) => wallet.signTransaction(tx),   // your keys never leave your process
);

From a terminal: npx @txwhy/sdk <signature>

On @solana/kit? The same loop, with no web3.js and with version 1 transactions included: import { sendWithRepair } from "@txwhy/sdk/kit" and pass your rpc, the transaction and your signer.

Proof, on chain

Two transactions on Solana mainnet you can open yourself. No screenshots, no staging.

You never have to trust us

Signing a transaction that a server rebuilt should make you nervous. So every repair comes with a proof, and the check behind it is open source, has no network access, and runs on your machine. A repaired transaction may differ from yours in exactly three ways:

Same fee payer, same signers, every other instruction byte for byte and in the same order. Anything else is refused. The test suite attacks it fifteen ways: an extra transfer, a redirected fee, a new signer, a widened slippage, swap proceeds sent to a stranger. All fifteen are caught. TxWhy runs the same check on its own output and will not return a transaction that fails it.

import { verifyRepair } from "@txwhy/sdk";

const check = await verifyRepair(connection, original, repaired);
if (!check.ok) throw new Error(check.violations.join(" "));  // never sign it

Free for people. A tenth of a cent for agents.

The website, the bot and /api/v1/repair are free and rate limited. Agents that need guaranteed capacity call /api/x402/repair instead: $0.001 in USDC per repair over x402, no account, no API key, charged only when the answer succeeds. A repaired transaction that lands costs less than the priority fee on one that does not.

For agents and bots

One call inside your send loop. When your RPC rejects a transaction at simulation, pass it here and get back a version that passes, typically in under a second. Most failures never reach the chain. They happen at this step, and this is where TxWhy sits.

curl -X POST https://txwhy.vercel.app/api/v1/repair \
  -H "content-type: application/json" \
  -d '{"transaction": "<base64, signed or unsigned>"}'
{
  "status": "repaired",
  "cause": { "title": "Compute budget exceeded", ... },
  "changes": [
    { "type": "compute_unit_limit", "before": "100", "after": "518" }
  ],
  "repairedTransaction": "<base64, unsigned>",
  "simulation": { "passed": true, "unitsConsumed": 450 }
}

Or plug it into any agent as a tool

TxWhy is an MCP server. Add the URL and your agent gets three tools: repair_transaction, diagnose_transaction and explain_error. No key, no account.

{
  "mcpServers": {
    "txwhy": { "url": "https://txwhy.vercel.app/api/mcp" }
  }
}

You can also pass {"signature": "..."} for a transaction that already landed and failed. Status is one of repaired, valid, needs_requote or not_repairable.