Jupiter Swap via CPI
To integrate your program with Jupiter Swap you can take two approaches. One is Flash Filling or you can utilize Cross Program Invocation (CPI).
As of August 2023, taking the CPI approach has some tradeoffs. Due to Solana's transaction limit of 1232 bytes, swaps via CPI will likely fail at runtime since Jupiter routes may involve multiple DEXes in order to reduce price impact. You could set a limit to the number of accounts used for swaps via Jupiter's swap API to fit it within your needs. However, limiting the accounts will likely incur greater price impact.
Note: when using Jupiter's API, you can set maxAccounts to reduce the number of accounts.
Instead, we recommend taking the flash-fill approach. The flash-fill approach takes advantage of Versioned Transaction in combination with Address Lookup Tables to allow for more accounts per transaction while keeping within the 1232 bytes limit.
Example​
Here we show an example transaction on how to utilize Jupiter Swap via CPI to swap from any tokens to SOL. This works even if the user doesn't have enough SOL. You can even allow a third-party payer if the user doesn't have any SOL at all.
How does this work?​
For a CPI to work, the transaction will be composed of these instructions:
- Borrow enough SOL from the program to open a wSOL account that the program owns.
- Swap X token from the user to wSOL on Jupiter via CPI.
- Close the wSOL account and send it to the program.
- The program then transfers the SOL back to the user.
Code Repo​
Here is the GitHub repo: https://github.com/jup-ag/sol-swap-cpi. You should check out the program code and the client code.
Here is the transaction on chain on how this works.
Rust Crate​
To ease integration via CPI, you may add the following crate jupiter-cpi to your program.
Cargo.toml
[dependencies]
jupiter-cpi = { git = "https://github.com/jup-ag/jupiter-cpi", rev = "5eb8977" }
... other dependencies
use jupiter_cpi;
...
let signer_seeds: &[&[&[u8]]] = &[...];
// pass accounts to context one-by-one and construct accounts here.
// Or in practise, 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,
)?;
...