jupiter swap
Execute multiple Jupiter swaps as an atomic bundle.
Use Case
Bundle multiple swaps together:
- Multi-hop arbitrage
- Portfolio rebalancing
- Atomic DEX aggregation
JavaScript Example
javascript
import {
Connection,
Keypair,
PublicKey,
SystemProgram,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
const BLOCKSPRINT_ENDPOINT = "https://fra.blocksprint.io/bundle/v1/YOUR_API_KEY";
const JUPITER_API = "https://api.jup.ag/swap/v1";
// BlockSprint tip address, tip at least 0.001 SOL
const TIP_ADDRESS = new PublicKey("Sp4JHSh9cksfzXbgK7Pq2ovtn8LirLQydaJKTsiNT77");
export async function getJupiterSwapTransaction(
inputMint,
outputMint,
amount,
userPublicKey,
options = {}
) {
// Get quote
const dexes = options.dexes ? `&dexes=${options.dexes.join(",")}` : "";
const quoteResponse = await fetch(
`${JUPITER_API}/quote?inputMint=${inputMint}&outputMint=${outputMint}&amount=${amount}&slippageBps=50${dexes}`
);
const quote = await quoteResponse.json();
// Get swap transaction
const swapResponse = await fetch(`${JUPITER_API}/swap`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
quoteResponse: quote,
userPublicKey: userPublicKey.toString(),
wrapAndUnwrapSol: true,
}),
});
const { swapTransaction } = await swapResponse.json();
return VersionedTransaction.deserialize(
Buffer.from(swapTransaction, "base64")
);
}
// Tip transaction: 0.001 SOL to a BlockSprint tip address
export function buildTipTransaction(wallet, recentBlockhash) {
const message = new TransactionMessage({
payerKey: wallet.publicKey,
recentBlockhash,
instructions: [
SystemProgram.transfer({
fromPubkey: wallet.publicKey,
toPubkey: TIP_ADDRESS,
lamports: 1_000_000,
}),
],
}).compileToLegacyMessage();
const tx = new VersionedTransaction(message);
tx.sign([wallet]);
return tx;
}
export async function sendBundle(transactions) {
const serializedTxs = transactions.map((tx) =>
Buffer.from(tx.serialize()).toString("base64")
);
const response = await fetch(BLOCKSPRINT_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "sendBundle",
params: [
serializedTxs,
{ encoding: "base64", skipPreflight: true },
],
}),
});
const result = await response.json();
if (result.error) throw new Error(result.error.message);
return result.result;
}
async function executeSwapBundle(wallet, swaps) {
// Build all swap transactions
const transactions = await Promise.all(
swaps.map((swap) =>
getJupiterSwapTransaction(
swap.inputMint,
swap.outputMint,
swap.amount,
wallet.publicKey
)
)
);
// Sign all transactions
transactions.forEach((tx) => tx.sign([wallet]));
// Add the tip transaction
transactions.push(
buildTipTransaction(wallet, transactions[0].message.recentBlockhash)
);
// Send as bundle
const result = await sendBundle(transactions);
console.log("Bundle ID:", result.bundle_id);
result.signatures.forEach((sig, i) => {
console.log(`Swap ${i + 1}: https://solscan.io/tx/${sig}`);
});
return result;
}
// Example: Swap SOL -> USDC and USDC -> BONK atomically
async function main() {
const wallet = Keypair.fromSecretKey(/* your key */);
const SOL = "So11111111111111111111111111111111111111112";
const USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
const BONK = "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263";
await executeSwapBundle(wallet, [
{ inputMint: SOL, outputMint: USDC, amount: 100_000_000 },
{ inputMint: USDC, outputMint: BONK, amount: 10_000_000 },
]);
}Arbitrage Bundle
Execute a buy and sell atomically:
javascript
import {
buildTipTransaction,
getJupiterSwapTransaction,
sendBundle,
} from "./jupiter-bundle.js";
const SOL_MINT = "So11111111111111111111111111111111111111112";
async function executeArbitrage(wallet, token, buyDex, sellDex, amount, expectedTokenAmount) {
// Get buy swap (SOL -> Token on DEX A)
const buyTx = await getJupiterSwapTransaction(
SOL_MINT,
token,
amount,
wallet.publicKey,
{ dexes: [buyDex] }
);
// Get sell swap (Token -> SOL on DEX B)
const sellTx = await getJupiterSwapTransaction(
token,
SOL_MINT,
expectedTokenAmount,
wallet.publicKey,
{ dexes: [sellDex] }
);
// Sign both
buyTx.sign([wallet]);
sellTx.sign([wallet]);
// Send as atomic bundle (with the tip transaction)
// If sell fails, buy also reverts - no stuck inventory
return sendBundle([
buyTx,
sellTx,
buildTipTransaction(wallet, buyTx.message.recentBlockhash),
]);
}Python Example
python
import requests
import base64
from solders.keypair import Keypair
from solders.pubkey import Pubkey
from solders.system_program import TransferParams, transfer
from solders.transaction import Transaction, VersionedTransaction
BLOCKSPRINT_ENDPOINT = "https://fra.blocksprint.io/bundle/v1/YOUR_API_KEY"
JUPITER_API = "https://api.jup.ag/swap/v1"
TIP_ADDRESS = Pubkey.from_string("Sp4JHSh9cksfzXbgK7Pq2ovtn8LirLQydaJKTsiNT77") # BlockSprint tip address
def get_jupiter_swap_tx(input_mint, output_mint, amount, user_pubkey):
# Get quote
quote = requests.get(
f"{JUPITER_API}/quote",
params={
"inputMint": input_mint,
"outputMint": output_mint,
"amount": str(amount),
"slippageBps": "50",
}
).json()
# Get swap transaction
swap = requests.post(
f"{JUPITER_API}/swap",
json={
"quoteResponse": quote,
"userPublicKey": user_pubkey,
"wrapAndUnwrapSol": True,
}
).json()
return swap["swapTransaction"]
def send_bundle(transactions_base64):
response = requests.post(
BLOCKSPRINT_ENDPOINT,
json={
"jsonrpc": "2.0",
"id": 1,
"method": "sendBundle",
"params": [
transactions_base64,
{"encoding": "base64", "skipPreflight": True}
]
}
)
result = response.json()
if "error" in result:
raise Exception(result["error"]["message"])
return result["result"]
# Example
def execute_swap_bundle(wallet: Keypair, swaps):
transactions = [
get_jupiter_swap_tx(
swap["input"],
swap["output"],
swap["amount"],
str(wallet.pubkey())
)
for swap in swaps
]
# Sign the swap transactions
signed = []
for tx_base64 in transactions:
tx = VersionedTransaction.from_bytes(base64.b64decode(tx_base64))
signed.append(VersionedTransaction(tx.message, [wallet]))
# Tip transaction: 0.001 SOL to a BlockSprint tip address
tip = transfer(TransferParams(from_pubkey=wallet.pubkey(), to_pubkey=TIP_ADDRESS, lamports=1_000_000))
signed.append(Transaction.new_signed_with_payer(
[tip], wallet.pubkey(), [wallet], signed[0].message.recent_blockhash
))
result = send_bundle([base64.b64encode(bytes(tx)).decode("utf-8") for tx in signed])
print(f"Bundle ID: {result['bundle_id']}")
return result