Jupiter swap

Jupiter swap is signed: failed trade recovery after wallet confirmation

Jupiter swap is a quote-to-settlement workflow where wallet approval signs a Solana transaction, yet the signature and on-chain status decide whether the exchange actually completed. After confirmation, record the signature, check whether it appears as confirmed with no execution error, compare the output mint and balance change, and only then consider another quote. If the transaction failed or expired, obtain a fresh route and sign a new transaction rather than reusing stale quote data.

Published:

What's inside

Follow a Jupiter swap from quote to final balance

The Jupiter Meta-Aggregator turns four inputs - input mint, output mint, raw input amount, and taker address - into an order, an unsigned transaction, and a request ID. Its three-stage path is order, wallet signature, and execute; the returned message is a version 0 Solana transaction whose instructions represent the selected route.

Metis, JupiterZ, Dflow, and OKX compete at the router layer, so pool selection happens before the confirmation prompt. Metis routes may traverse liquidity on venues such as Raydium, Orca, and Meteora, while JupiterZ uses a request-for-quote model with a market maker. The visible route label matters when diagnosing a failure because aggregator and RFQ responses use different code families.

Quote amounts arrive as integers in each token's smallest unit. SOL uses 9 decimal places, making 1 SOL equal to 1,000,000,000 lamports, while native USDC on Solana uses 6 decimal places, making 1 USDC equal to 1,000,000 base units. Preserve those raw amounts when comparing the order, execution response, and wallet balance.


The signature is the dividing line

A Solana transaction signature identifies the exact message approved by the wallet; wallet confirmation alone does not prove that a validator accepted or executed it. Each Ed25519 signature occupies 64 bytes, the first signature serves as the transaction ID, and the full serialized transaction cannot exceed 1,232 bytes.

Solana executes a transaction atomically, so every instruction succeeds together or all state changes roll back. A route that creates an associated token account, performs several swaps, and unwraps SOL therefore does not leave a half-completed exchange when a later instruction fails, although a landed failure still consumes its network fee.

Save the signature before taking another action. Rebroadcasting the identical signed bytes preserves the same transaction ID, whereas requesting a new order creates a new message and a new signature that could settle separately while the first attempt remains unresolved. The next part of this is set out in Jupiter swap step by step.

Read processed, confirmed, and finalized correctly

Solana commitment status has three named levels: processed, confirmed, and finalized. Processed means a node has observed the transaction in its recent block, confirmed means a supermajority has voted on that block, and finalized means the block has reached maximum lockout.

Read commitment together with the transaction error field. A confirmed or finalized signature with a null error completed successfully; a recorded signature with a non-null error landed and failed; no record remains unresolved until the recent blockhash expires. Jupiter's execute response expresses the same top-level distinction as Success or Failed, with code 0 reserved for success.

Solana Explorer and Solscan expose the signature record independently of a wallet's activity screen. Phantom and Solflare may refresh their portfolio views on a different schedule, so the transaction record and mint-specific account balance carry more weight than a lingering spinner.

Verify output at the token-account level

Jupiter output verification should use the destination mint and its on-chain token account, not the ticker or a portfolio valuation. The Associated Token Program derives one canonical associated token account for each owner, mint, and token-program combination, while the original SPL Token Program and Token-2022 Program maintain separate account ownership rules.

Once that is set, Jupiter's execute response exposes four accounting fields: totalInputAmount, inputAmountResult, outputAmountResult, and totalOutputAmount. The total fields describe the amounts reflected in the wallet, while the result fields describe the route before an input- or output-denominated platform fee. For the received asset, compare totalOutputAmount with the balance change for the exact output mint.

SOL needs one extra distinction. When route instructions wrap or unwrap the native asset, Wrapped SOL appears inside the execution path, yet the final value may return to the wallet's native SOL balance rather than remain in a token-account row. A successful token output that is absent from the wallet interface should be located by mint address before any retry.

Match execution codes to the next action

Crucially, Jupiter execution codes separate stale order data, signing faults, landing failures, and program errors. Code 0 means success; code -1 identifies a missing cached order, code -2 an invalid signed transaction, and code -3 invalid message bytes. The first requires a new order, while the latter two require signing the unmodified transaction returned with that order.

Aggregator code -1000 means the transaction failed to land, -1003 means it was not fully signed, and -1004 marks an invalid block height. Codes -1005 and -1006 identify expiry and timeout. A signature accompanying any of these responses must be checked on Solana before a replacement order is signed, because the response label and chain record answer different questions.

Program code 6001 denotes exceeded slippage tolerance in the Jupiter V6 Aggregator Program. That failure rolls back the route's token movements, so recovery begins with a fresh quote based on current liquidity rather than a repeat of the old signed message. An error from another liquidity program may appear as a numeric custom program code; retain the route and signature when recording it.


Expiry requires a fresh quote and blockhash

A Solana recent blockhash limits how long the signed swap remains processable. The BlockhashQueue stores 300 hashes, validators accept a maximum processing age of 150, and zero-based indexing makes the newest 151 hashes eligible; with slots running about 400 to 600 milliseconds, the usable window is approximately 60 to 90 seconds.

Aggregator orders identify their hard boundary with lastValidBlockHeight, while a JupiterZ RFQ order carries an expireAt timestamp set for that market-maker quote. Neither value extends when a wallet prompt sits open. Once the relevant boundary passes, the old serialized transaction cannot be revived: request a new order, review its amount and route, then create a new signature.


A failed transaction still spends network fees

A failed Solana transaction that landed still charges its network fee because signature verification and scheduling occurred before program execution returned an error. Solana charges 5,000 lamports per signature as the base fee, and that fee remains charged when execution fails. One SOL contains 1,000,000,000 lamports; half of the base fee is burned and half goes to the validator.

The optional priority fee equals the requested compute-unit price multiplied by the compute-unit limit, divided by 1,000,000 micro-lamports per lamport and rounded up. A nonbuilt-in instruction receives a default limit of 200,000 compute units, while one transaction is capped at 1,400,000. Jupiter Beam manages landing and priority strategy for managed execution, and a gasless order identifies when the user is not the network fee payer.


Retry only after this evidence check

A Jupiter swap retry should follow the existing attempt's evidence, not the interface timer. Use the signature, error field, expiry boundary, output mint, and balance change as a short decision record, then take the matching action.

  • If the signature is confirmed with a null error, stop and refresh the exact output mint balance; the exchange completed.
  • If the signature is recorded with a non-null error, save that error and request a fresh order rather than resending old bytes.
  • If the signature has no record and its blockhash remains valid, wait or rebroadcast the identical signed transaction without rebuilding it.
  • If lastValidBlockHeight or expireAt has passed, discard the stale order and review a newly generated route before signing.
  • If the output exists on-chain but the wallet omits it, locate the associated token account by mint and avoid a duplicate trade.

This sequence also separates a display delay from an execution failure. It prevents two independent swaps from being created merely because one application view refreshed later than the underlying Solana account.

Where this recovery method earns its keep

The signature-first recovery method suits wallet users handling a stalled confirmation, integrators reconciling Jupiter order and execute responses, and operations teams that need an auditable decision before retrying. It is especially valuable when an aggregator route spans several programs or a JupiterZ order expires on a different rule from a Metis order.

Keep the signature, final on-chain status, and mint-specific balance together as three parts of one record. Those facts show whether the trade settled, failed after landing, or expired before execution, and each state points to a different next action without reopening the broader quote-selection decision.

Key questions about Jupiter swap

Does closing the wallet after signing cancel a submitted Jupiter transaction?

No. Closing Phantom or Solflare after the signed bytes were submitted does not revoke the transaction; Solana processes it until it lands or its recent blockhash expires. Save or recover the signature from wallet activity, then query that signature. If the wallet closed before submission and no signature exists, there is no transaction ID to follow.

Why is a Jupiter request ID different from the Solana transaction signature?

A Jupiter request ID identifies cached order data used by execute, whereas the Solana transaction signature identifies the signed on-chain attempt. The request ID has meaning inside Jupiter's execution workflow and does not locate a transaction in an explorer. Keep both during troubleshooting, but use the signature to prove landing, failure, and commitment.

Which record belongs in an accounting export after a recovered swap?

The confirmed Solana transaction record belongs at the center of an accounting export. Pair its signature, slot, error field, input mint, output mint, and token balance changes with Jupiter's totalInputAmount and totalOutputAmount. A quote alone records an intention, while inputAmountResult and outputAmountResult describe route accounting rather than the wallet's final reflected amounts.

Is rebroadcasting identical signed bytes the same as approving another trade?

No. Identical signed bytes retain the same first signature and represent the same Solana transaction, while a fresh Jupiter order contains a new message and requires a new signature. Rebroadcast only while its blockhash remains valid. Requoting and resigning creates a separate execution attempt, so resolve the first signature before approving it.

What happens if the output associated token account did not exist before confirmation?

The swap transaction can include an instruction to create the output associated token account before depositing tokens. Solana treats account creation and route execution atomically: both complete, or their state changes roll back together. A landed failure still pays its network fee, but it does not leave a funded output account from a partially executed route.

Why does Solana Explorer show success before Phantom updates the balance?

Solana Explorer reads an on-chain transaction at a chosen commitment, while Phantom refreshes portfolio data through its own indexing and display pipeline. Confirm that the transaction error is null, then inspect the destination mint's token account and balance. If those records show the output, another swap is unnecessary even while the wallet view catches up.

Jupiter graphic reads Trade Any Token On Solana with trade button