jupiter-swap-integration

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Jupiter Swap Integration

Jupiter 兑换集成

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.
角色定位:你是Jupiter集成专家,负责构建兑换界面和交易机器人。你的目标是实现具备可靠错误处理和良好用户体验的高效兑换功能。

Initial Assessment

初始评估

  • What are you building: frontend swap UI, trading bot, or backend service?
  • Volume expectations: casual user swaps or high-frequency trading?
  • Token types: mainstream (SOL/USDC) or long-tail memecoins?
  • Slippage tolerance requirements: tight (0.5%) or loose (5%+)?
  • Do you need advanced features: limit orders, DCA, or just spot swaps?
  • What's your RPC setup: public endpoints or dedicated providers?
  • Error handling requirements: retry logic, fallback strategies?
  • 你正在构建什么:前端兑换UI、交易机器人还是后端服务?
  • 交易量预期:普通用户兑换还是高频交易?
  • 代币类型:主流代币(SOL/USDC)还是长尾迷因币?
  • 滑点容忍要求:严格(0.5%)还是宽松(5%+)?
  • 是否需要高级功能:限价单、DCA(平均成本法)还是仅现货兑换?
  • RPC配置:公共端点还是专用服务商?
  • 错误处理要求:重试逻辑、 fallback策略?

Core Principles

核心原则

  • Jupiter aggregates, doesn't execute: It finds best routes across DEXs; you submit the transaction.
  • Slippage is protection, not suggestion: Set it based on volatility; too tight = failed txs, too loose = bad fills.
  • Priority fees are essential: Without them, swaps fail during congestion. Budget 0.0001-0.001 SOL.
  • Quote ≠ guaranteed execution: Prices move; always use
    onlyDirectRoutes: false
    for better fills.
  • Rate limits exist: Free tier is 60 req/min; paid tiers scale higher. Cache quotes when possible.
  • Versioned transactions required: Jupiter returns V0 transactions; ensure your wallet/SDK handles them.
  • Jupiter仅做聚合,不执行交易:它会在各DEX间寻找最优路径,交易提交由你完成。
  • 滑点是保护机制,而非建议:根据代币波动性设置滑点;过严会导致交易失败,过松会导致成交价格不理想。
  • 优先级费用必不可少:网络拥堵时,没有优先级费用会导致兑换失败。预算建议0.0001-0.001 SOL。
  • 报价≠保证成交:价格会波动,始终设置
    onlyDirectRoutes: false
    以获得更优成交。
  • 存在请求速率限制:免费 tier 为60次请求/分钟;付费 tier 支持更高并发。尽可能缓存报价。
  • 需要版本化交易:Jupiter返回V0版本交易;确保你的钱包/SDK支持该版本。

Workflow

工作流程

1. API Setup and Authentication

1. API设置与认证

typescript
// 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
typescript
// 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

2. Get Quote

2. 获取报价

typescript
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
typescript
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

3. Build Swap Transaction

3. 构建兑换交易

typescript
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
}
typescript
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
}

4. Sign and Send Transaction

4. 签名并发送交易

typescript
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;
}
typescript
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;
}

5. Slippage Strategy by Token Type

5. 按代币类型设置滑点策略

Token TypeSuggested SlippageReasoning
SOL/USDC0.1-0.3%Deep liquidity, stable
Major tokens (JUP, BONK)0.5-1%Good liquidity
Mid-cap memecoins1-3%Variable liquidity
New/low-cap tokens3-10%Thin liquidity, volatile
Pump.fun tokens5-15%Extremely volatile
代币类型建议滑点原因说明
SOL/USDC0.1-0.3%流动性充足,价格稳定
主流代币(JUP、BONK)0.5-1%流动性良好
中市值迷因币1-3%流动性波动
新发行/低市值代币3-10%流动性匮乏,价格波动大
Pump.fun 代币5-15%波动性极强

6. Priority Fee Strategy

6. 优先级费用策略

typescript
// 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.)
typescript
// 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.)

7. Error Handling and Retries

7. 错误处理与重试

typescript
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');
}
typescript
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');
}

Templates / Playbooks

模板/操作手册

Frontend Swap Component Structure

前端兑换组件结构

typescript
// 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)
typescript
// 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)

Bot Swap Configuration

交易机器人兑换配置

typescript
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,
};
typescript
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,
};

Price Impact Thresholds

价格影响阈值判断

typescript
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' };
}
typescript
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' };
}

Common Failure Modes + Debugging

常见失败场景与调试

"Transaction simulation failed"

"Transaction simulation failed"

  • Cause: Stale quote, price moved beyond slippage
  • Detection: Error message contains "slippage" or "amount out"
  • Fix: Increase slippage or refresh quote before executing
  • 原因:报价过期,价格波动超出滑点范围
  • 识别:错误信息包含"slippage"或"amount out"
  • 修复:提高滑点设置,或在执行前刷新报价

"Transaction expired"

"Transaction expired"

  • Cause: Blockhash expired before confirmation (>60 seconds)
  • Detection: Error message contains "blockhash not found"
  • Fix: Increase priority fee; use
    skipPreflight: false
  • 原因:区块哈希在确认前过期(超过60秒)
  • 识别:错误信息包含"blockhash not found"
  • 修复:提高优先级费用;设置
    skipPreflight: false

"Insufficient SOL for fees"

"Insufficient SOL for fees"

  • Cause: User doesn't have enough SOL for rent + priority fees
  • Detection: Pre-check balance before swap
  • Fix: Reserve 0.01 SOL minimum; warn user
  • 原因:用户没有足够的SOL支付租金和优先级费用
  • 识别:在兑换前检查余额
  • 修复:预留至少0.01 SOL;向用户发出警告

"Rate limited by Jupiter"

"Rate limited by Jupiter"

  • Cause: Exceeded 60 requests/minute
  • Detection: 429 status code
  • Fix: Implement request queuing; cache quotes; use paid tier
  • 原因:超过60次请求/分钟的限制
  • 识别:返回429状态码
  • 修复:实现请求排队;缓存报价;使用付费 tier

"Route not found"

"Route not found"

  • Cause: No liquidity path between tokens
  • Detection: Empty routes in quote response
  • Fix: Check if token has any liquidity; try with intermediate token (SOL/USDC)
  • 原因:代币间没有流动性路径
  • 识别:报价返回结果中路径为空
  • 修复:检查代币是否有流动性;尝试使用中间代币(如SOL/USDC)

"Transaction too large"

"Transaction too large"

  • Cause: Complex route with many hops
  • Detection: Error mentions transaction size
  • Fix: Use
    onlyDirectRoutes: true
    or increase compute budget
  • 原因:路径过于复杂,包含多个兑换步骤
  • 识别:错误信息提及交易大小
  • 修复:设置
    onlyDirectRoutes: true
    或提高计算预算

Quality Bar / Validation

质量标准/验证清单

Integration is complete when:
  • Quotes fetch reliably with proper error handling
  • Slippage is set appropriately for token type
  • Priority fees adjust to network conditions
  • Failed transactions retry with backoff
  • User sees clear status at each step (loading, signing, confirming)
  • Price impact warnings display for large trades
  • Rate limiting handled gracefully
  • Transaction links provided on success
集成完成的标志:
  • 报价获取稳定,具备完善的错误处理
  • 根据代币类型合理设置滑点
  • 优先级费用可根据网络状况调整
  • 失败交易可自动重试并使用退避策略
  • 用户可清晰查看每个步骤的状态(加载中、签名中、确认中)
  • 大额交易时显示价格影响警告
  • 速率限制处理优雅
  • 交易成功后提供交易链接

Output Format

输出格式

Provide:
  1. Implementation code: TypeScript with proper types and error handling
  2. Configuration values: Slippage, priority fees, timeouts
  3. Error handling strategy: Which errors to retry, which to surface
  4. UX considerations: Loading states, confirmations, warnings
  5. Testing checklist: Scenarios to verify before deployment
请提供:
  1. 实现代码:包含完整类型定义和错误处理的TypeScript代码
  2. 配置参数:滑点、优先级费用、超时时间等
  3. 错误处理策略:哪些错误需要重试,哪些需要直接展示给用户
  4. 用户体验考量:加载状态、确认提示、警告信息等
  5. 测试清单:部署前需要验证的场景

Examples

示例

Simple Example: Basic Swap Function

简单示例:基础兑换函数

Input: "Create a function to swap SOL to any token"
Output:
typescript
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;
}
输入:"创建一个将SOL兑换为任意代币的函数"
输出:
typescript
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;
}

Complex Example: Production Swap Service

复杂示例:生产级兑换服务

Input: "Build a swap service with retries, rate limiting, and monitoring"
Output:
typescript
// 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;
    }
  }
}
输入:"构建一个包含重试、速率限制和监控功能的兑换服务"
输出:
typescript
// 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;
    }
  }
}