Skip to main content
When using /build, you can add your own instructions alongside the swap. This page covers common instructions and how to compose them.

Instruction ordering

When building your transaction, follow this order:
  1. Compute budget instructions (from /build response)
  2. Setup instructions (from /build response)
  3. Your pre-swap instructions (e.g. create token accounts)
  4. Swap instruction (from /build response)
  5. Your post-swap instructions (e.g. transfer, memo, close accounts)
  6. Cleanup instruction (from /build response, if present)

Create associated token account

If the recipient does not have a token account for the output mint, create one before the swap. Use createAssociatedTokenAccountIdempotent to safely handle the case where the account already exists.
import { getCreateAssociatedTokenIdempotentInstruction } from "@solana-program/associated-token";
import { TOKEN_PROGRAM_ADDRESS } from "@solana-program/token";

const createAtaIx = getCreateAssociatedTokenIdempotentInstruction({
  payer: signer,
  owner: address(recipientAddress),
  mint: address(outputMint),
  tokenProgram: TOKEN_PROGRAM_ADDRESS,
});

// Add before the swap instruction

Close token account

After a swap, you may want to close a token account to reclaim its rent. This is common when swapping to native SOL (the wrapped SOL account can be closed after unwrapping).
import { getCloseAccountInstruction } from "@solana-program/token";

const closeIx = getCloseAccountInstruction({
  account: address(tokenAccountToClose),
  destination: signer.address, // Rent refund destination
  owner: signer,
});

// Add after the swap instruction

SOL transfer

Add a SOL transfer to tip a validator, pay a fee, or send funds alongside the swap.
import { getTransferSolInstruction } from "@solana-program/system";

const transferIx = getTransferSolInstruction({
  source: signer,
  destination: address(recipientAddress),
  amount: 1_000_000n, // 0.001 SOL in lamports
});

// Add before or after the swap instruction

Memo instruction

Attach a memo to the transaction for tracking, tagging, or compliance purposes.
import { getAddMemoInstruction } from "@solana-program/memo";

const memoIx = getAddMemoInstruction({
  memo: "swap-order-12345",
});

// Add anywhere in the transaction

CPI (Cross-Program Invocation)

For protocols that need to invoke the Jupiter swap from within their own onchain program, use the swap instruction from /build as the inner instruction in a CPI call.

How CPI swaps work

A typical CPI swap transaction:
  1. Borrow enough SOL from your program to open a wSOL account that the program owns
  2. Swap token X from the user to wSOL on Jupiter via CPI
  3. Close the wSOL account and send SOL to the program
  4. The program transfers the SOL back to the user

Considerations

  • CPI cannot use Address Lookup Tables (ALTs), which limits the number of accounts in the transaction. Jupiter’s complex routing often requires many accounts. If you exceed the 1232-byte transaction size limit, consider using Flash Fill instead (see below).
  • Use maxAccounts on /build to control route complexity and keep the transaction within size limits.
  • Set your own compute budget, as CPI adds overhead.

CPI with jupiter-cpi crate

Add the jupiter-cpi crate to your Anchor program:
[dependencies]
jupiter-cpi = { git = "https://github.com/jup-ag/jupiter-cpi", rev = "5eb8977" }
use jupiter_cpi;

let signer_seeds: &[&[&[u8]]] = &[...];

// Pass accounts to context one-by-one and construct accounts here
// Or in practice, it may be easier to use remaining_accounts
// https://book.anchor-lang.com/anchor_in_depth/the_program_module.html

let accounts = jupiter_cpi::cpi::accounts::SharedAccountsRoute {
    token_program: ,
    program_authority: ,
    user_transfer_authority: ,
    source_token_account: ,
    program_source_token_account: ,
    program_destination_token_account: ,
    destination_token_account: ,
    source_mint: ,
    destination_mint: ,
    platform_fee_account: ,
    token_2022_program: ,
};

let cpi_ctx = CpiContext::new_with_signer(
    ctx.accounts.jup.to_account_info(),
    accounts,
    signer_seeds,
);

jupiter_cpi::cpi::shared_accounts_route(
    cpi_ctx,
    id,
    route_plan,
    in_amount,
    quoted_out_amount,
    slippage_bps,
    platform_fee_bps,
);

Flash Fill (alternative to CPI)

Flash Fill allows the use of Versioned Transactions and ALTs, avoiding the account limit constraints of CPI. The flow:
  1. Borrow enough SOL for opening the wSOL account from the Flash Fill program
  2. Create the wSOL account for the borrower
  3. Swap token X to wSOL
  4. Close the wSOL account and send SOL to the borrower
  5. Repay the SOL for opening the wSOL account back to the program

References