Jupiter swap is a Solana signing workflow with failed-transaction recovery
Jupiter swap is a three-stage Solana transaction workflow: a live quote selects an execution route, the wallet signs the assembled message, and Jupiter submits it for confirmation. If the quote expires or the transaction fails, recovery starts by separating wallet rejection, network non-landing, and on-chain execution failure; only an expired or changed message needs a fresh quote and signature. A successful response should then be checked directly against the settled token-account balances.
Updated:
Bottom line: A blockhash remains processable through 151 recent hashes, so an expired signature needs a newly assembled transaction.
From four quote fields to one signed transaction
The managed Jupiter order flow turns a quote request into one unsigned Solana transaction, then accepts the wallet's signature for execution. The sequence has three stages - order, sign, execute - and the order response carries both a Base64-encoded versioned transaction and a request ID. Jupiter compares the available paths from Metis, JupiterZ, Dflow, and OKX before returning the selected router and expected output. The wallet signs the transaction message, not a free-standing promise to trade at a displayed number. Submission sends the signed bytes and matching request ID to managed execution, where Jupiter Beam broadcasts, monitors confirmation, and returns Success or Failed. No later stage can silently rewrite the signed message; any change to accounts, amount, instructions, or blockhash produces different message bytes and therefore needs another signature.
Set the four quote inputs before opening the wallet
The quote request needs four core inputs: the input mint, output mint, amount, and taker address. Mint addresses identify the assets, while the amount is expressed in the input token's smallest unit. A taker-free request returns price information but no transaction, because Jupiter cannot assemble the signer and account set without the wallet address.
Decimals turn the human amount into the integer placed in the order. Native SOL uses 9 decimal places, so 1 SOL equals 1,000,000,000 lamports and 0.25 SOL becomes 250,000,000 lamports. Solana USDC uses 6 decimal places, making 25 USDC equal to 25,000,000 base units. Changing even 1 base unit changes the order, so edit the amount before signing rather than after serialization.
Read the winning route as a plan, not a settled receipt
The route plan records how Jupiter intends to source the quoted output at that moment. Swap API V2 expresses route weights canonically in basis points: 10,000 basis points represent 100%, 1 basis point is 0.01%, and a 50-basis-point threshold equals 0.5%. The quoted
outAmount
is an expectation; the
otherAmountThreshold
is the minimum acceptable output for an exact-input route.
An on-chain path may divide liquidity among Orca Whirlpools, Raydium CLMM, and Meteora DLMM, while JupiterZ supplies a request-for-quote path from a market maker. Metis searches and constructs pool routes; Dflow and OKX are additional routing engines in the meta-aggregator. A split does not create separate user approvals. Those legs become instructions inside one atomic transaction, so the route either completes as assembled or the state changes are rolled back.
Optional order fields also affect that competition. Supplying a separate receiver, referral configuration, or external payer removes JupiterZ from eligibility, so compare the returned router and output again after introducing one of those fields. The route response records what actually won; a venue preference does not.
What the wallet signature actually authorizes
A wallet signature authorizes the exact Solana message shown in the signing request: account keys, recent blockhash, compiled instructions, and fee payer. Jupiter's managed order returns a versioned transaction using message version 0. Each Solana address occupies 32 bytes, each signer contributes one 64-byte Ed25519 signature, and the first signature also serves as the transaction identifier.
The whole serialized transaction, including signatures and message, is capped at 1,232 bytes. Solana charges a base fee of 5,000 lamports for each required signature, separate from any optional prioritization fee embedded through compute-budget instructions. With a JupiterZ route, a market maker may supply another required signature after submission; the user's wallet still fills only its assigned signer position. Phantom, Solflare, and Backpack handle the user's authorization through their own confirmation interfaces.
Follow processed, confirmed, and finalized without confusing the states
Solana confirmation exposes three commitment levels: processed, confirmed, and finalized. Processed means a validator has observed the transaction in its current fork; confirmed adds a supermajority vote; finalized indicates the block has reached the cluster's maximum lockout. A Jupiter execution response with status Success and code 0 means the transaction was confirmed, even if a wallet interface continues waiting for a stronger display state.
Solana's maximum blockhash processing age is 150, so 151 recent hashes qualify because the queue counts age from zero.
At slot durations of about 400 to 600 milliseconds, that produces a practical validity window near 60 to 90 seconds. The authoritative boundary is
lastValidBlockHeight, not a stopwatch. Once the cluster passes that height, validators reject the old message even when its quote still looks attractive. Until that boundary, a signature lookup with no confirmed record is inconclusive; broadcast may still be propagating, or the queried RPC service may not yet expose the requested commitment.
Recover an order after its blockhash or RFQ expires
Blockhash expiry requires a newly assembled transaction and a new signature. Replacing the recent blockhash inside old signed bytes invalidates the Ed25519 signature, while reusing the expired bytes cannot revive the order. Request a fresh order, review its output and route again, then sign the new version 0 transaction.
An unknown response before expiry deserves a different action. Check the existing transaction signature, or resubmit the identical signed transaction with the same request ID while its validity window remains open; the unchanged signature identifies the same Solana transaction and does not create a second swap.
Error code -1004 marks an invalid block height, and -2003 marks an expired JupiterZ quote. Both point to re-quoting, whereas a temporary missing status calls for lookup before replacement.
Separate wallet rejection, non-landing, and on-chain failure
A rejected wallet request stops before broadcast, so it produces no transaction signature, no network fee, and no token movement. Non-landing means the signed transaction never reached a confirmed block before its validity boundary. An on-chain execution failure is different: Solana processed the message, one instruction returned an error, and the transaction fee remains charged. A simulation error occurs earlier and carries no network fee because the message never entered a block. This distinction explains whether any SOL fee debit should exist.
A Jupiter swap is atomic at the Solana transaction level. If a Raydium, Orca, Meteora, SPL Token Program, or Token-2022 instruction fails, successful earlier instructions in that same transaction do not leave partial balance changes. Preserve any returned signature and inspect the transaction error before retrying. An unchanged balance alone cannot distinguish a wallet rejection from an expired broadcast or a recorded execution error.
Map execution codes to the next recovery action
The Jupiter execution response pairs status with a numeric code, signature, error text, and settled amount fields. Code 0 means confirmation succeeded. Code -1 means the cached order is missing or expired, -2 identifies an invalid signed transaction, and -3 identifies invalid message bytes. These three failures occur around order retrieval, serialization, and submission rather than pool execution.
Aggregator code -1000 means the transaction failed to land, while -1003 means it was not fully signed. Code -1004 rejects invalid block-height data. Within the request-for-quote path, -2003 means the quote expired and -2004 means the swap was rejected. Re-quote for missing or expired state; correct serialization for -2 or -3; complete the required signer set for -1003. For a landing code, check the signature and validity height before deciding whether the next attempt needs a fresh order.
Verify output by mint, token account, and settled amount
The output check starts with the execution response, not the pre-signing estimate. Compare
inputAmountResult
and
outputAmountResult
with the intended mints, then use the signature and confirmed slot to inspect balance changes in Solscan. The quoted
outAmount
remains useful for comparison, but it is not the final accounting field.
Solana stores tokens in token accounts rather than directly on the wallet address. An Associated Token Account is the one canonical derived address for a specific owner, mint, and token program - a combination of three inputs. Because the token program participates in that derivation, mints owned by the original SPL Token Program and mints owned by Token-2022 use their respective program identifiers. Setup instructions may create the output account inside the swap, while cleanup instructions can unwrap wrapped SOL back to native SOL.
If a wallet's portfolio view lags, search the confirmed transaction by signature and match the output mint instead of relying on the ticker. A Success response with the expected
outputAmountResult
and corresponding token-account increase is the operational proof of settlement. A missing display label does not reverse the recorded balance.
Choose managed execution or a custom-built transaction
Jupiter's managed
/order
and
/execute
path fits a swap that accepts the assembled message and delegates broadcasting, priority strategy, and confirmation polling. The meta-aggregator lets Metis, JupiterZ, Dflow, and OKX compete, then returns one transaction for the wallet to sign. Recovery remains tied to the request ID, signature, execution code, and block-height boundary.
The
/build
path serves integrations that must add custom instructions, compose through a cross-program invocation, or control transaction submission. It returns Metis-routed instructions, Address Lookup Table data, and blockhash metadata rather than the finished managed order. Its
maxAccounts
setting accepts 1 through 64 and defaults to 64; lowering it leaves room under Solana's 1,232-byte cap but may remove viable or efficient pool routes. Custom assembly also transfers confirmation and retry logic to the integrator.
The five checks that decide whether to sign, wait, or re-quote
The pre-signing checklist determines whether the current order is ready, stale, or mismatched. Sign only when all five concrete conditions hold; after submission, wait on the existing signature until confirmation or expiry resolves its state.
- The input and output mint addresses match the intended SOL, USDC, JUP, or other assets.
- The raw integer amount converts to the human quantity using each mint's declared decimals.
- The route, expected output, and minimum-output threshold still match the decision you just made.
- The expected wallet is the signer, and the fee payer has enough SOL for the assembled transaction.
-
The transaction is still below its
lastValidBlockHeight; an expired message goes back for a fresh order.
Keep both the transaction signature and request ID once the wallet approves. If Jupiter returns Success, reconcile the settled amount fields with token-account balances. If status remains unknown, query the same signature until it appears or the validity boundary passes. Only the latter outcome calls for a new quote rather than another check of the existing transaction.
Jupiter swap questions, answered
Does a standard Jupiter order require a separate SPL token approval?
A standard Jupiter order does not use the separate ERC-20 approval pattern familiar from EVM chains. The Solana wallet signs the assembled transaction as the authority for its input token account, and the SPL Token Program or Token-2022 instruction executes within that transaction. If an integration adds custom instructions through the build path, review those instructions as part of the same signing request.
Why does a split route still need only one wallet confirmation?
A split route is compiled into one atomic Solana transaction, so the user's signer authorizes every included leg at once. Metis may allocate route weight across Orca, Raydium, or Meteora pools without creating separate wallet transactions. JupiterZ RFQ routes may add a market-maker signer through managed execution, but that does not become a second user confirmation.
Must the output wallet match the signing wallet?
The output wallet does not have to match the signer when an integration deliberately supplies a receiver or destination token account. The signed message fixes that destination, and the account must be valid for the output mint and token program. Because receiver settings can change which routers are eligible, the destination should be chosen before requesting and comparing the final order.
Which hardware-wallet capability matters for a Jupiter order?
The hardware wallet must support Solana version 0 transactions and the instructions included in the assembled message. Device firmware and companion-wallet support determine what details appear on screen. Long review time matters operationally: if the transaction crosses its last valid block height before broadcast, the unchanged signature is expired and the user must approve a freshly assembled order.
Is a Mainnet quote reusable on Devnet or Testnet?
A Mainnet quote cannot be reused on Devnet or Testnet. The signed Solana message contains cluster-specific account addresses and a recent blockhash from one ledger, so another cluster cannot validate it as equivalent. Jupiter's production routing targets Mainnet; changing an RPC endpoint after signing does not transform the order, route, mint accounts, or signature for a test cluster.
Why can Phantom and Solflare show different status timing for the same signature?
Phantom and Solflare may read from different RPC infrastructure or display different commitment thresholds, so their progress labels need not update simultaneously. The transaction signature itself is unchanged. Once the same signature resolves to a confirmed transaction with successful metadata and the expected token-balance delta, both interfaces are describing one settled ledger event rather than two executions.