This tutorial shows how to build gasless DEX swaps using Raydium and LazorKit.
A swap interface where users can trade tokens on Raydium without paying any gas fees.
- LazorKit provider configured (Getting Started)
- Basic understanding of DEX mechanics
Use Raydium's Trade API to get real-time pricing. We request txVersion=LEGACY to get transaction instructions in a format that's straightforward to extract and process:
import { DEV_API_URLS } from '@raydium-io/raydium-sdk-v2';
const getQuote = async (inputMint: string, outputMint: string, amount: number) => {
const response = await fetch(
`${DEV_API_URLS.SWAP_HOST}/compute/swap-base-in?` +
`inputMint=${inputMint}&` +
`outputMint=${outputMint}&` +
`amount=${amount}&` +
`slippageBps=50&` +
`txVersion=LEGACY`
);
return response.json();
};Request the transaction from Raydium:
import axios from 'axios';
const buildSwapTransaction = async (quoteData: any, walletAddress: string) => {
const { data } = await axios.post(
`${DEV_API_URLS.SWAP_HOST}/transaction/swap-base-in`,
{
swapResponse: quoteData,
txVersion: 'LEGACY',
wallet: walletAddress,
wrapSol: true, // Wrap SOL if needed
unwrapSol: true, // Unwrap SOL if needed
}
);
return data;
};Raydium's SDK adds ComputeBudget instructions and doesn't include the LazorKit smart wallet in all accounts. We use processInstructionsForLazorKit to handle this (see Cookbook Patterns for details):
import { Transaction } from '@solana/web3.js';
import { processInstructionsForLazorKit } from '@/lib/lazorkit-utils';
const executeSwap = async () => {
// Get quote
const quoteData = await getQuote(inputMint, outputMint, amount);
// Build transaction
const swapData = await buildSwapTransaction(quoteData.data, wallet.smartWallet);
// Deserialize transaction
const txBuffer = Buffer.from(swapData.data[0].transaction, 'base64');
const legacyTx = Transaction.from(txBuffer);
// Process for LazorKit
const instructions = processInstructionsForLazorKit(
legacyTx.instructions,
wallet.smartWallet
);
// Send gasless transaction
const signature = await signAndSendTransaction({
instructions,
transactionOptions: { computeUnitLimit: 600_000 }
});
return signature;
};'use client';
import { useState } from 'react';
import { Transaction } from '@solana/web3.js';
import { DEV_API_URLS } from '@raydium-io/raydium-sdk-v2';
import axios from 'axios';
import { useLazorkitWalletConnect } from '@/hooks/useLazorkitWalletConnect';
import { useBalances } from '@/hooks/useBalances';
import { processInstructionsForLazorKit } from '@/lib/lazorkit-utils';
const TOKENS = {
SOL: { mint: 'So11111111111111111111111111111111111111112', decimals: 9 },
USDC: { mint: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU', decimals: 6 },
};
export default function SwapPage() {
const { wallet, isConnected, signAndSendTransaction } = useLazorkitWalletConnect();
const { fetchBalances } = useBalances(wallet?.smartWallet);
const [swapping, setSwapping] = useState(false);
const handleSwap = async (inputAmount: number) => {
if (!wallet) return;
setSwapping(true);
try {
// 1. Get quote
const quoteRes = await fetch(
`${DEV_API_URLS.SWAP_HOST}/compute/swap-base-in?` +
`inputMint=${TOKENS.SOL.mint}&outputMint=${TOKENS.USDC.mint}&` +
`amount=${inputAmount * 10 ** TOKENS.SOL.decimals}&slippageBps=50&txVersion=LEGACY`
);
const quoteData = await quoteRes.json();
// 2. Build transaction
const { data: swapData } = await axios.post(
`${DEV_API_URLS.SWAP_HOST}/transaction/swap-base-in`,
{ swapResponse: quoteData.data, txVersion: 'LEGACY', wallet: wallet.smartWallet }
);
// 3. Process for LazorKit
const legacyTx = Transaction.from(Buffer.from(swapData.data[0].transaction, 'base64'));
const instructions = processInstructionsForLazorKit(legacyTx.instructions, wallet.smartWallet);
// 4. Send gasless
await signAndSendTransaction({
instructions,
transactionOptions: { computeUnitLimit: 600_000 }
});
await fetchBalances();
alert('Swap successful! No gas fees paid.');
} catch (err) {
console.error('Swap error:', err);
} finally {
setSwapping(false);
}
};
return (
<button onClick={() => handleSwap(0.1)} disabled={swapping || !isConnected}>
{swapping ? 'Swapping...' : 'Swap 0.1 SOL → USDC (Gasless)'}
</button>
);
}// Devnet tokens
const TOKENS = {
SOL: {
symbol: 'SOL',
mint: 'So11111111111111111111111111111111111111112',
decimals: 9,
},
USDC: {
symbol: 'USDC',
mint: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',
decimals: 6,
},
};- Example 04 README - Full implementation details
- Example 04 Source Code
- Live Demo
- Raydium Trade API Docs