Skip to main content
Preflight answers one question before a signature exists: will this transaction succeed? It is not fee estimation, and it does not replace the integrity checks that run inside signing.
Chains with a virtual machine (EVM, Solana, Tron) are executed against a node. Bitcoin and XRP have nothing to execute, so their transactions are checked by reproducing the ledger’s own arithmetic, and so is a plain TRX send. The check field on every result says which one happened.

Why it is separate from fee estimation

estimateFee answers “what will this cost” and pads the gas price so the quote survives a few blocks. Preflight’s affordability check uses the lower price the sender actually signs, because borrowing the padded estimate would falsely block every “send all” transfer.

The two entry points

null means “not applicable”, never “checked and safe”. Both methods return null when no checker covers this chain, method or state. Gating a signing button on truthiness silently treats “nothing was checked” as a pass. Gate on preflightBlocksSigning(result, isRunning) instead.

PreflightResult

code, title and reason are populated only on fail, and inconclusiveReason only on inconclusive.

Decision table

A check that is still running blocks: preflightBlocksSigning(null, true) is true. Enabling the signing control before the verdict lands would let a user outrun it. A null result on its own does not block, so preflightBlocksSigning(null, false) is false.
Every check is bounded at 12 seconds. A node that never answers resolves to inconclusive with "The network did not respond in time." rather than holding the gate shut. Locking a user out of their own funds for as long as a node stays silent would be worse than reporting that the check could not be made.

Failure codes

decimals_mismatch fails an SPL send whose decimals differ from the mint’s. The send scales the amount by the decimals you pass and the token transfer does not check them, so it would move a different amount than the one typed. Bitcoin’s dust thresholds are Bitcoin Core’s, per output type:

Coverage

preflightOrder

Two EVM guards are deliberate nulls rather than failures:
  • An undeployed vault has no code to execute the call, so simulating from its address would report a failure that says nothing about the order.
  • An order behind others in the queue executes against state those earlier orders produce. Simulating it against state as it stands today can revert for a reason that will not exist by the time it runs, and a verdict that blocks signing must never rest on that.
An EVM order is simulated as the vault, and the vault is held only to the order’s value: the gas is paid by the member who executes it. A vault with no native balance therefore passes a zero-value order. When the executor’s balance cannot cover the gas, the result is insufficient_funds with the title Executor cannot pay the network fee, reported ahead of the simulation’s own verdict. On Solana, “the account is not on chain yet” is reported as inconclusive rather than as a failure: a proposal the node has not caught up to answers as though it were never written, and reading that as proof of failure would lock a co-signer out of a healthy order until the lag clears. For the same reason, a node that has not seen the transaction’s recent blockhash, or has not yet seen the final approval of a proposal being executed, gives inconclusive.

preflightSend

preflightSend also returns null for an unparseable amount, or an amount that resolves to zero or less.

Worked example: preflight, inspect, sign or abort

A personal send follows the same shape:

Signing-time integrity checks

Preflight asks will it succeed. A separate family of checks asks is this the transaction I was shown. These throw rather than returning a verdict, and they run inside signing on every chain, so you get them by signing through the SDK. Three things are enforced. The recipient and amount decoded from the transaction are compared with the recipient and amount the order put in front of the co-signer, and a disagreement throws SignatureIntentMismatchError instead of producing a signature. On EVM vaults the digest presented for signature is recomputed from the readable order fields, so an opaque hash cannot stand for a different transaction than the one displayed. And the key rebuilt for the signature must derive the wallet’s own address. Together that is what makes signing “what you see is what you sign”: the user consents to what they were shown, so a payload that pays someone else never reaches the signing key.
These checks cannot defend against a backend that lies consistently in both the order fields and the payload, and nothing on the client can. They defend against the payload and the display diverging.

Things worth surfacing to a signer

Some properties of an order are not failures but do change what the signer is agreeing to. Show them alongside the order:
When a token’s decimals are not known, the amount is reported in base units and the amount comparison is skipped rather than run against a guess, so an honest order does not fail on a missing scale. The recipient is still checked either way, so an address swap is caught regardless. Supply the token’s decimals to get the amount checked too.

Next

Orders

Create, sign, and execute multisig orders

Errors

SignatureIntentMismatchError and the rest of the error surface

Transactions

Personal sends, fees, memos, and spend authorization

Multisig Fees

Accurate per-chain vault fee estimation
Last modified on September 30, 2026