文章介绍了在 Solana 上集成 Jupiter 作为 DEX 聚合器的完整流程,涵盖获取报价、构建并签名交换交易、以及在 React 中进行封装集成。内容还说明了滑点、优先费、版本化交易和生产环境安全实践等关键问题。

Jupiter 不再通过单个 DEX 路由,而是将你的 swap 拆分,
并在多个 liquidity source 之间同时进行优化,
从而尽量降低 price impact 和 slippage。
从获取你的第一个 quote,到签名生产级 swap transaction——这是 Web3 工程师将 Jupiter 集成到 Solana dApp 所需的一切。
这是每个 Solana 开发者迟早都会遇到的场景:你的用户想把 Token A 换成 Token B。你调用 Raydium 的 SDK,硬编码 pool,然后发布上线。两周后,某个用户在一笔 200 美元的 swap 中因为 slippage 损失了 40 美元,而你当时路由的是一个较浅的 pool,实际上在 Orca、Lifinity 和一个 CLMM pool 之间存在更优路径——而且这些路径还可以同时执行。
这就是 liquidity fragmentation。并且在 Solana 上,超过 20 个活跃的 DEX protocol 争夺 volume,这不是边缘情况——而是默认状态。
这正是 Jupiter 解决的问题。在本指南中,你将学习如何正确地将它接入你的 dApp——从获取 quote,到签名并广播 transaction——并全程使用生产级 TypeScript。
Solana 的速度和低费用使它成为 DEX 创新的温床。Raydium、Orca、Meteora、Phoenix、Lifinity、OpenBook——每个都提供不同的 pool 类型(AMM、CLMM、DLMM、order book)、不同的 fee tier,以及根据 token pair 不同而差异巨大的 liquidity depth。
对于任意一次 swap,最优路径可能是:
手动计算这件事不仅繁琐——计算成本也很高,而且每隔几秒就会发生变化。你需要一个 aggregator。
Jupiter(jup.ag)是 Solana 领先的 DEX aggregator,负责路由链上大部分 swap volume。它聚合了几乎所有主要 Solana DEX 的 liquidity,并为任意 swap 找到最优执行路径——综合考虑 price impact、fee 和 route depth。
从开发者角度看,Jupiter 提供了一个简洁的 REST API(称为 Quote API 和 Swap API),帮你处理所有路由复杂性。你只需要问:“我如何把 1 SOL 换成 USDC?” —— Jupiter 就会返回最佳 route 和一个可直接签名的 transaction。
核心能力:
截至 2025 年末,所有层级都需要 API key——包括免费层。
Jupiter 已弃用旧的无 key lite-api.jup.ag endpoint,并将所有内容迁移到 api.jup.ag。免费层仍然可用且零成本,但你必须先注册并生成一个 key。
如何获取你的 API key(免费):
const headers = {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.JUPITER_API_KEY}`,
};
同时更新你的 base URL。 旧的 quote-api.jup.ag/v6 已经是 legacy。当前统一 endpoint(Swap API V2,于 2026 年 3 月发布)是:
https://api.jup.ag/swap/v2
Swap API V2 有三个 endpoint:
GET /order2. Endpoint: GET /build
3. Endpoint: POST /execute
/order 生成的 transaction 提供托管式 transaction landing。从 /order 开始——它能提供最佳执行价格,因为所有 router 都在竞争。只有当你需要修改 transaction 本身时,才降级使用 /build(例如,把它与你自己的 program instruction 组合)。
免费层限制: 足以满足开发和中等规模 production 流量。对于高流量集成,可通过 portal 升级以获得更高的 rate limit 和 SLA 保障。
记住我,以便更快登录
安全提示: 将你的 key 存储在 environment variable 中(JUPITER_API_KEY )。切勿在 frontend code 中硬编码它——如果你的应用是 client-side,请通过 backend 转发 swap 调用。
Quote API 会返回某个 swap 的最佳可用 route。你需要指定输入 token、输出 token 和数量(以 token 的 base unit 计——例如 SOL 的 lamports 等)。
import axios from "axios";
// Swap API V2 — api.jup.ag(所有层级都需要 API key)
const QUOTE_API = "https://api.jup.ag/swap/v2/order";
const API_KEY = process.env.JUPITER_API_KEY!;
const authHeaders = {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`,
};
interface QuoteParams {
inputMint: string;
outputMint: string;
amount: number; // 以 base units 计(例如 lamports)
slippageBps: number; // basis points:50 = 0.5%
}
async function getQuote(params: QuoteParams) {
const { data } = await axios.get(QUOTE_API, {
headers: authHeaders,
params: {
inputMint: params.inputMint,
outputMint: params.outputMint,
amount: params.amount,
slippageBps: params.slippageBps,
},
});
return data;
}
// 示例:Swap 0.1 SOL → USDC
const SOL_MINT = "So11111111111111111111111111111111111111112";
const USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
const quote = await getQuote({
inputMint: SOL_MINT,
outputMint: USDC_MINT,
amount: 100_000_000, // 0.1 SOL,以 lamports 计
slippageBps: 50, // 0.5% slippage
});
console.log("Out amount:", quote.outAmount);
console.log("Price impact:", quote.priceImpactPct, "%");
console.log("Route plan:", quote.routePlan.map((r: any) => r.swapInfo.label));
响应会给你 outAmount、priceImpactPct,以及描述每一跳的完整 routePlan。务必向用户展示 priceImpactPct——这是一个关键的 UX 信号。
一旦你拿到 quote,就把它传给 Swap API,以接收一个序列化、可直接签名的 transaction。
import { Connection, VersionedTransaction, PublicKey } from "@solana/web3.js";
const SWAP_API = "https://api.jup.ag/swap/v2/execute"; // 用于组装好的 transactions
const RPC_URL = "https://api.mainnet-beta.solana.com"; // 生产环境使用私有 RPC
async function buildSwapTransaction(
quoteResponse: any,
userPublicKey: string
): Promise<VersionedTransaction> {
const { data } = await axios.post(SWAP_API, {
quoteResponse,
userPublicKey,
wrapAndUnwrapSol: true, // 自动处理 wSOL wrapping
dynamicComputeUnitLimit: true, // 让 Jupiter 优化 CU budget
prioritizationFeeLamports: "auto", // 动态 priority fee
});
// 反序列化 base64 编码的 versioned transaction
const swapTransactionBuf = Buffer.from(data.swapTransaction, "base64");
return VersionedTransaction.deserialize(swapTransactionBuf);
}
const connection = new Connection(RPC_URL, "confirmed");
const userPubkey = "YOUR_WALLET_PUBLIC_KEY";
const transaction = await buildSwapTransaction(quote, userPubkey);
有几个选项值得理解:
| Option | What It Does |
| ----------------------------------- | ---------------------------------------------------- |
| `wrapAndUnwrapSol` | 自动处理 SOL ↔ wSOL |
| `dynamicComputeUnitLimit` | 为不同 route complexity 设置最优 compute units |
| `prioritizationFeeLamports: "auto"` | 动态选择 priority fee 以提升 landing 速度 |
import { Keypair } from "@solana/web3.js";
// 在真实应用中,请使用 wallet adapter(Phantom、Backpack 等)
// 这里展示用于 Node.js/backend 场景的 keypair signing
async function signAndSend(
transaction: VersionedTransaction,
signer: Keypair
): Promise<string> {
// 对 transaction 签名
transaction.sign([signer]);
// 发送时禁用 preflight checks 以提升速度
const signature = await connection.sendRawTransaction(
transaction.serialize(),
{
skipPreflight: false,
maxRetries: 3,
}
);
// 确认 transaction
const confirmation = await connection.confirmTransaction(
{ signature, ...await connection.getLatestBlockhash() },
"confirmed"
);
if (confirmation.value.err) {
throw new Error(`Transaction failed: ${JSON.stringify(confirmation.value.err)}`);
}
return signature;
}
对于使用 wallet adapter 的 React 应用,将 transaction.sign([signer]) 替换为:
const signedTx = await wallet.signTransaction(transaction);
const sig = await connection.sendRawTransaction(signedTx.serialize());
下面是一个最小但具备 production 形态的 React hook,将这三个步骤连接起来:
// hooks/useJupiterSwap.ts
import { useState } from "react";
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { VersionedTransaction } from "@solana/web3.js";
import axios from "axios";
export function useJupiterSwap() {
const { connection } = useConnection();
const { publicKey, signTransaction } = useWallet();
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const swap = async (
inputMint: string,
outputMint: string,
amountLamports: number,
slippageBps = 50
) => {
if (!publicKey || !signTransaction) return;
setLoading(true);
setError(null);
try {
// 1. Quote(Swap API V2 /order)
const { data: quote } = await axios.get("https://api.jup.ag/swap/v2/order", {
headers: { Authorization: `Bearer ${process.env.NEXT_PUBLIC_JUPITER_API_KEY}` },
params: { inputMint, outputMint, amount: amountLamports, slippageBps },
});
// 2. /order endpoint 直接返回组装好的 transaction
// 如果要进行自定义 transaction composition,请使用 /build
// 3. 签名并发送
const tx = VersionedTransaction.deserialize(
Buffer.from(swapData.swapTransaction, "base64")
);
const signed = await signTransaction(tx);
const sig = await connection.sendRawTransaction(signed.serialize());
await connection.confirmTransaction(sig, "confirmed");
return sig;
} catch (err: any) {
setError(err.message || "Swap failed");
} finally {
setLoading(false);
}
};
return { swap, loading, error };
}
Slippage: 根据 token volatility 设置 slippageBps。对于 stablecoin,10bps 就可以。对于波动较大的 memecoin,100–300bps 更合适。始终向用户展示预期接收数量与最小接收数量。
Priority fee: 在拥堵的 Solana 上,没有 priority fee 的 transaction 会静默失败。在对延迟不敏感的流程中,使用 prioritizationFeeLamports: "auto"。对于对速度敏感的应用,可查询 connection.getRecentPrioritizationFees() 并手动设置。
需要处理的 transaction failure:
0x1771 — Slippage 容忍度超出。提示用户重试或提高 slippage。getLatestBlockhash() 刷新 transaction。1. 复用过期的 quote。 Jupiter quote 会在约 30 秒后过期。务必在构建 swap transaction 之前立即获取新的 quote,而不是在用户第一次打开 swap UI 时就获取。
2. 在生产环境使用 HTTP RPC。 公共 RPC 节点很快就会被 rate limit。生产环境请使用专用 provider(Helius、Triton、QuickNode)。你的 swap confirmation 会感谢你。
3. 忽略 priceImpactPct 。 在大额 swap 中,5%+ 的 price impact 是危险信号。提醒用户,并考虑 partial fill 或 route splitting。
4. 没有处理 versioned transaction。 Jupiter 返回的是 VersionedTransaction,而不是传统的 Transaction 类型。确保你的 wallet adapter 版本支持它(@solana/wallet-adapter-\* ≥ 0.15)。
5. 硬编码 compute limit。 不同的 swap route 计算成本差异巨大。始终使用 dynamicComputeUnitLimit: true。
connection.simulateTransaction() 在交易上链并浪费 fee 之前捕获失败。Solana 400ms 的 slot time 意味着你的 UI 需要足够快。这里有一些建议:
connection.onSignature())而不是轮询确认状态。Jupiter 的 API 将原本复杂的多 DEX routing 问题转化为三个简洁的 API 调用。Quote API 找到最佳价格,Swap API 返回一个可直接签名的 transaction,而 @solana/web3.js 负责其余部分。无需 API key、无需复杂的 SDK 引导——只有 REST 调用和标准的 Solana transaction 机制。
对于 production 系统来说,真正的工作在于细节:slippage UX、priority fee、RPC 可靠性,以及优雅的 failure handling。但核心集成确实和你用过的任何 API 一样简洁。
Solana 的 liquidity ecosystem 还会持续扩张。有了 Jupiter 在底层,你的 dApp 会自动获得每一个新上线 protocol 的最佳执行——无需任何代码更改。
如果这篇指南帮助你更快交付,请在 Medium 上关注我,获取更多关于 Solana 开发、DeFi infrastructure 和 Web3 engineering 的深度内容。有什么问题,或者想让我讲解什么?请在下方留言——我会阅读每一条。
标签:Solana ·Jupiter ·Web3 ·DeFi ·Blockchain Development
- 原文链接: medium.com/@chavanrutik1...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!
作者暂未设置收款二维码