xiaohongshu
xiaohongshu
jupiter-swap-integration
Integrate Jupiter aggregator for swaps - API usage, route optimization, slippage handling, and frontend/bot implementation. Use when building swap UIs or trading bots.
Full skill instructions
Role framing: You are a Jupiter integration specialist who builds swap interfaces and trading bots. Your goal is to implement reliable, efficient swaps with proper error handling and user experience.
onlyDirectRoutes: false for better fills.// Base URLs
const JUPITER_API = 'https://quote-api.jup.ag/v6';
const JUPITER_PRICE_API = 'https://price.jup.ag/v6';
// No API key required for basic usage
// For high volume, contact Jupiter for dedicated endpoints
// Rate limits (free tier):
// - Quote API: 60 requests/minute
// - Price API: 600 requests/minute
interface QuoteParams {
inputMint: string; // Token to sell
outputMint: string; // Token to buy
amount: string; // Amount in smallest units (lamports/base units)
slippageBps: number; // Slippage in basis points (100 = 1%)
onlyDirectRoutes?: boolean; // false = better routes, true = simpler
asLegacyTransaction?: boolean; // false = versioned tx (recommended)
}
async function getQuote(params: QuoteParams) {
const url = new URL(`${JUPITER_API}/quote`);
url.searchParams.set('inputMint', params.inputMint);
url.searchParams.set('outputMint', params.outputMint);
url.searchParams.set('amount', params.amount);
url.searchParams.set('slippageBps', params.slippageBps.toString());
const response = await fetch(url.toString());
if (!response.ok) {
throw new Error(`Quote failed: ${response.status}`);
}
return response.json();
}
// Example: Swap 1 SOL to USDC
const quote = await getQuote({
inputMint: 'So11111111111111111111111111111111111111112', // SOL
outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
amount: '1000000000', // 1 SOL in lamports
slippageBps: 50, // 0.5%
});
// Quote response includes:
// - inAmount: input amount
// - outAmount: expected output (before slippage)
// - otherAmountThreshold: minimum output (after slippage)
// - routePlan: array of swap steps
// - priceImpactPct: price impact percentage
interface SwapParams {
quoteResponse: any;
userPublicKey: string;
wrapAndUnwrapSol?: boolean; // true = auto wrap/unwrap SOL
computeUnitPriceMicroLamports?: number; // priority fee
dynamicComputeUnitLimit?: boolean; // auto-size compute
}
async function getSwapTransaction(params: SwapParams) {
const response = await fetch(`${JUPITER_API}/swap`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
quoteResponse: params.quoteResponse,
userPublicKey: params.userPublicKey,
wrapAndUnwrapSol: params.wrapAndUnwrapSol ?? true,
computeUnitPriceMicroLamports: params.computeUnitPriceMicroLamports ?? 1000,
dynamicComputeUnitLimit: params.dynamicComputeUnitLimit ?? true,
}),
});
const { swapTransaction } = await response.json();
return swapTransaction; // Base64 encoded versioned transaction
}
import { VersionedTransaction, Connection } from '@solana/web3.js';
async function executeSwap(
swapTransaction: string,
wallet: any, // Wallet adapter
connection: Connection
) {
// Decode the transaction
const txBuffer = Buffer.from(swapTransaction, 'base64');
const tx = VersionedTransaction.deserialize(txBuffer);
// Sign with wallet
const signedTx = await wallet.signTransaction(tx);
// Send with retry logic
const signature = await connection.sendTransaction(signedTx, {
skipPreflight: false,
maxRetries: 3,
});
// Confirm transaction
const confirmation = await connection.confirmTransaction(signature, 'confirmed');
if (confirmation.value.err) {
throw new Error(`Transaction failed: ${JSON.stringify(confirmation.value.err)}`);
}
return signature;
}
| Token Type | Suggested Slippage | Reasoning |
|---|---|---|
| SOL/USDC | 0.1-0.3% | Deep liquidity, stable |
| Major tokens (JUP, BONK) | 0.5-1% | Good liquidity |
| Mid-cap memecoins | 1-3% | Variable liquidity |
| New/low-cap tokens | 3-10% | Thin liquidity, volatile |
| Pump.fun tokens | 5-15% | Extremely volatile |
// Estimate priority fee based on network conditions
async function estimatePriorityFee(connection: Connection): Promise<number> {
const recentFees = await connection.getRecentPrioritizationFees();
if (recentFees.length === 0) return 1000; // default 1000 micro-lamports
// Use 75th percentile for reliability
const sorted = recentFees.map(f => f.prioritizationFee).sort((a, b) => a - b);
const p75Index = Math.floor(sorted.length * 0.75);
return Math.max(sorted[p75Index], 1000);
}
// Priority fee tiers:
// - 1,000 micro-lamports: Normal conditions
// - 10,000 micro-lamports: Moderate congestion
// - 100,000 micro-lamports: High congestion
// - 1,000,000+ micro-lamports: Extreme (minting events, etc.)
async function swapWithRetry(
params: SwapParams,
maxRetries: number = 3
): Promise<string> {
let lastError: Error | null = null;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
// Get fresh quote (prices change)
const quote = await getQuote(params.quoteParams);
// Check if price moved too much
if (quote.priceImpactPct > 5) {
throw new Error(`Price impact too high: ${quote.priceImpactPct}%`);
}
// Get swap transaction
const swapTx = await getSwapTransaction({
quoteResponse: quote,
userPublicKey: params.userPublicKey,
computeUnitPriceMicroLamports: params.priorityFee * attempt, // Increase fee on retry
});
// Execute
return await executeSwap(swapTx, params.wallet, params.connection);
} catch (error: any) {
lastError = error;
// Don't retry on certain errors
if (error.message.includes('insufficient funds')) throw error;
if (error.message.includes('slippage')) throw error;
// Wait before retry (exponential backoff)
await new Promise(r => setTimeout(r, 1000 * attempt));
}
}
throw lastError || new Error('Swap failed after retries');
}
// State management
interface SwapState {
inputToken: Token | null;
outputToken: Token | null;
inputAmount: string;
quote: QuoteResponse | null;
loading: boolean;
error: string | null;
txStatus: 'idle' | 'signing' | 'confirming' | 'success' | 'failed';
}
// Component flow:
// 1. User selects tokens → fetch quote
// 2. User enters amount → debounced quote refresh
// 3. Display: output amount, price impact, route
// 4. User clicks swap → sign → send → confirm
// 5. Show success/failure with tx link
// Quote refresh interval: 10-15 seconds (balance freshness vs rate limits)
interface BotSwapConfig {
// Execution
maxSlippageBps: number;
minPriorityFeeMicroLamports: number;
maxPriorityFeeMicroLamports: number;
maxRetries: number;
// Safety
maxTradeSize: number; // In USD
maxPriceImpact: number; // Percentage
cooldownMs: number; // Between trades
// Monitoring
logAllQuotes: boolean;
alertOnFailure: boolean;
}
const defaultBotConfig: BotSwapConfig = {
maxSlippageBps: 100,
minPriorityFeeMicroLamports: 1000,
maxPriorityFeeMicroLamports: 100000,
maxRetries: 3,
maxTradeSize: 1000,
maxPriceImpact: 3,
cooldownMs: 1000,
logAllQuotes: true,
alertOnFailure: true,
};
function assessPriceImpact(impactPct: number): {
level: 'low' | 'medium' | 'high' | 'extreme';
warning: string | null;
} {
if (impactPct < 0.5) return { level: 'low', warning: null };
if (impactPct < 2) return { level: 'medium', warning: 'Moderate price impact' };
if (impactPct < 5) return { level: 'high', warning: 'High price impact - consider smaller trade' };
return { level: 'extreme', warning: 'Extreme price impact - trade size too large for liquidity' };
}
skipPreflight: falseonlyDirectRoutes: true or increase compute budgetIntegration is complete when:
Provide:
Input: "Create a function to swap SOL to any token"
Output:
import { Connection, PublicKey, VersionedTransaction } from '@solana/web3.js';
const JUPITER_API = 'https://quote-api.jup.ag/v6';
const SOL_MINT = 'So11111111111111111111111111111111111111112';
interface SwapSolParams {
outputMint: string;
amountLamports: number;
slippageBps: number;
userPublicKey: PublicKey;
signTransaction: (tx: VersionedTransaction) => Promise<VersionedTransaction>;
connection: Connection;
}
export async function swapSolToToken(params: SwapSolParams): Promise<string> {
// 1. Get quote
const quoteUrl = `${JUPITER_API}/quote?inputMint=${SOL_MINT}&outputMint=${params.outputMint}&amount=${params.amountLamports}&slippageBps=${params.slippageBps}`;
const quoteResponse = await fetch(quoteUrl);
if (!quoteResponse.ok) throw new Error('Failed to get quote');
const quote = await quoteResponse.json();
// 2. Get swap transaction
const swapResponse = await fetch(`${JUPITER_API}/swap`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
quoteResponse: quote,
userPublicKey: params.userPublicKey.toBase58(),
wrapAndUnwrapSol: true,
computeUnitPriceMicroLamports: 5000, // 0.000005 SOL priority
}),
});
const { swapTransaction } = await swapResponse.json();
// 3. Sign and send
const tx = VersionedTransaction.deserialize(Buffer.from(swapTransaction, 'base64'));
const signedTx = await params.signTransaction(tx);
const signature = await params.connection.sendTransaction(signedTx);
await params.connection.confirmTransaction(signature, 'confirmed');
return signature;
}
Input: "Build a swap service with retries, rate limiting, and monitoring"
Output:
// See full implementation in examples/swap-service.ts
// Key features:
// - Request queue with rate limiting (60/min)
// - Exponential backoff on failures
// - Priority fee escalation on retries
// - Quote caching (10s TTL)
// - Prometheus metrics export
// - Structured logging
// - Health check endpoint
class JupiterSwapService {
private requestQueue: RequestQueue;
private quoteCache: LRUCache<string, Quote>;
private metrics: SwapMetrics;
async swap(params: SwapParams): Promise<SwapResult> {
const startTime = Date.now();
try {
// Check rate limit
await this.requestQueue.acquire();
// Get or refresh quote
const quote = await this.getQuoteWithCache(params);
// Validate
this.validateQuote(quote, params);
// Execute with retries
const signature = await this.executeWithRetry(quote, params);
// Record success
this.metrics.recordSwap('success', Date.now() - startTime);
return { success: true, signature, quote };
} catch (error) {
this.metrics.recordSwap('failure', Date.now() - startTime);
throw error;
}
}
}
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience