jupiter-lend
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseJupiter Lend Protocol
Jupiter Lend协议
Jupiter Lend (powered by Fluid Protocol) is a lending and borrowing protocol on Solana. It offers Liquidity Pools, Lending Markets (jlTokens), and Vaults for leveraged positions.
The protocol uses two main SDKs:
- : Read-only queries for all programs (Liquidity, Lending, Vaults)
@jup-ag/lend-read - : Write operations (deposit, withdraw, borrow, repay)
@jup-ag/lend
Jupiter Lend(由Fluid Protocol提供支持)是Solana上的一款借贷协议,提供流动性池、借贷市场(jlTokens)和用于杠杆仓位的Vault。
该协议使用两个核心SDK:
- :用于所有程序(流动性、借贷、Vault)的只读查询
@jup-ag/lend-read - :用于写入操作(存入、取出、借款、还款)
@jup-ag/lend
Agent usage
Agent使用示例
Example prompts you can use to demo Jupiter Lend integrations:
- Discover all available vaults and list them
- Fetch all vault positions for a user
- Deposit collateral and borrow in a single transaction
- Repay max debt and withdraw max collateral for a position
- Get user Earn (jlToken) positions and underlying balances
- Build a flashloan for arbitrage or liquidation
- Get liquidity rates and APY for a token
- Create a new vault position (positionId 0), deposit collateral, and borrow
可用于演示Jupiter Lend集成的示例指令:
- 发现并列出所有可用的Vault
- 获取用户的所有Vault仓位
- 在单笔交易中完成存入抵押品并借款
- 偿还最大债务并取出最大抵押品
- 获取用户的Earn(jlToken)仓位及基础资产余额
- 构建用于套利或清算的闪贷
- 获取代币的流动性利率和APY
- 创建新的Vault仓位(positionId为0),存入抵押品并借款
SDK Installation
SDK安装
bash
undefinedbash
undefinedFor read operations (queries, prices, positions)
用于只读操作(查询、价格、仓位)
npm install @jup-ag/lend-read
npm install @jup-ag/lend-read
For write operations (transactions)
用于写入操作(交易)
npm install @jup-ag/lend
---npm install @jup-ag/lend
---1. Key Concepts & Protocol Jargon
1. 核心概念与协议术语
Understanding the architecture and terminology of Jupiter Lend will help you build better integrations.
理解Jupiter Lend的架构和术语有助于构建更优质的集成。
Architecture: The Two-Layer Model
架构:双层模型
- Liquidity Layer (Single Orderbook): The foundational layer where all assets reside. It manages token limits, rate curves, and unified liquidity. Users never interact with this directly.
- Protocol Layer: User-facing modules (Lending and Vaults) that sit on top of the Liquidity Layer and interact with it via Cross-Program Invocations (CPIs).
- 流动性层(单一订单簿):所有资产所在的基础层,管理代币限额、利率曲线和统一流动性。用户不会直接与该层交互。
- 协议层:面向用户的模块(借贷和Vault),位于流动性层之上,通过跨程序调用(CPIs)与流动性层交互。
Terminology
术语
- jlToken (Jupiter Lend Token): The yield-bearing asset you receive when supplying tokens to the Lending protocol (e.g., ). As interest accrues, the exchange rate increases, making your
jlUSDCworth more underlyingjlToken.USDC - Exchange Price: The conversion rate used to translate between "raw" stored amounts and actual token amounts. It continuously increases as interest is earned on supply or accrued on debt.
- Collateral Factor (CF): The maximum Loan-to-Value (LTV) ratio allowed when opening or managing a position.
- Liquidation Threshold (LT): The LTV at which a position becomes undercollateralized and eligible for liquidation.
- Liquidation Max Limit (LML): The absolute maximum LTV limit. If a position's risk ratio exceeds this boundary, it is automatically absorbed by the protocol to protect liquidity providers.
- Liquidation Penalty: The discount percentage offered to liquidators when they repay debt on behalf of a risky position.
- Rebalance: An operation that synchronizes the upper protocol layer's accounting (Vaults/Lending) with its actual position on the Liquidity layer. It also syncs the orderbook to account for any active accrued rewards.
- Tick-based Architecture: The Vaults protocol groups positions into "ticks" based on their risk level (debt-to-collateral ratio). This allows the protocol to efficiently manage risk and process liquidations at scale.
- Dust Borrow: A tiny residual amount of debt intentionally kept on positions to handle division rounding complexities.
- Sentinel Values: Constants like and
MAX_WITHDRAW_AMOUNTthat tell the protocol to dynamically calculate and withdraw/repay the maximum mathematically possible amount for a position.MAX_REPAY_AMOUNT
- jlToken(Jupiter Lend Token):向借贷协议提供代币时获得的生息资产(例如)。随着利息累积,兑换率会上升,使你的
jlUSDC对应的基础jlToken价值更高。USDC - 兑换价格:用于转换“原始”存储金额与实际代币金额的汇率。随着供应利息的赚取或债务利息的累积,该价格会持续上升。
- 抵押系数(CF):开立或管理仓位时允许的最大贷款价值比(LTV)。
- 清算阈值(LT):仓位变为抵押不足且符合清算条件时的LTV。
- 最大清算限额(LML):绝对最大LTV限制。若仓位的风险比率超过此边界,将被协议自动接管以保护流动性提供者。
- 清算惩罚:清算人代表风险仓位偿还债务时可享受的折扣百分比。
- 重新平衡:将上层协议层(Vault/借贷)的记账与流动性层的实际仓位同步的操作,同时同步订单簿以计入所有累积的奖励。
- 基于Tick的架构:Vault协议根据仓位的风险水平(债务抵押比)将其分组为“Tick”,使协议能够高效管理风险并大规模处理清算。
- 小额债务残留:为处理除法舍入复杂性而故意保留在仓位中的少量剩余债务。
- 哨兵值:如和
MAX_WITHDRAW_AMOUNT这样的常量,指示协议动态计算并取出/偿还仓位在数学上的最大可能金额。MAX_REPAY_AMOUNT
Amounts and units
金额与单位
All SDK amounts use base units (smallest token unit, e.g. = 1 USDC for 6 decimals).
1_000_000所有SDK金额均使用基础单位(代币的最小单位,例如6位小数的代币中等于1 USDC)。
1_000_0002. Jupiter Earn (Lending)
2. Jupiter Earn(借贷)
Jupiter Earn allows users to supply assets to earn yield. In return, users receive yield-bearing (e.g., ).
jlTokensjlUSDCJupiter Earn允许用户提供资产以赚取收益,作为回报,用户将获得生息(例如)。
jlTokensjlUSDCLending Module (jlTokens)
借贷模块(jlTokens)
Access jlToken (Jupiter Lend token) markets, exchange prices, and user positions.
typescript
// Get all jlToken details at once
const allDetails = await client.lending.getAllJlTokenDetails();
// Get user's jlToken balance
const position = await client.lending.getUserPosition(USDC, userPublicKey);访问jlToken(Jupiter Lend代币)市场、兑换价格和用户仓位。
typescript
// 一次性获取所有jlToken详情
const allDetails = await client.lending.getAllJlTokenDetails();
// 获取用户的jlToken余额
const position = await client.lending.getUserPosition(USDC, userPublicKey);Lending (Earn)
借贷(Earn)
Deposit underlying assets to receive yield-bearing tokens, or withdraw them.
typescript
import { getDepositIxs, getWithdrawIxs } from "@jup-ag/lend/earn";
import BN from "bn.js";
// Deposit 1 USDC (base units: 1_000_000 for 6 decimals)
const { ixs: depositIxs } = await getDepositIxs({
amount: new BN(1_000_000),
asset: USDC_PUBKEY,
signer: userPublicKey,
connection,
});
// Withdraw 0.1 USDC (100_000 base units @ 6 decimals)
const { ixs: withdrawIxs } = await getWithdrawIxs({
amount: new BN(100_000),
asset: USDC_PUBKEY,
signer: userPublicKey,
connection,
});存入基础资产以获得生息代币,或取出资产。
typescript
import { getDepositIxs, getWithdrawIxs } from "@jup-ag/lend/earn";
import BN from "bn.js";
// 存入1 USDC(基础单位:6位小数对应1_000_000)
const { ixs: depositIxs } = await getDepositIxs({
amount: new BN(1_000_000),
asset: USDC_PUBKEY,
signer: userPublicKey,
connection,
});
// 取出0.1 USDC(6位小数对应100_000基础单位)
const { ixs: withdrawIxs } = await getWithdrawIxs({
amount: new BN(100_000),
asset: USDC_PUBKEY,
signer: userPublicKey,
connection,
});3. Jupiter Borrow (Vaults)
3. Jupiter Borrow(Vault)
Vaults handle collateral deposits and debt borrowing.
Vault负责处理抵押品存入和债务借款。
Vault Module & Discovery
Vault模块与发现
Access vault configurations, positions, exchange prices, and liquidation data. This is crucial for dynamically listing all available leverage markets.
typescript
// Discover all available vaults
const allVaults = await client.vault.getAllVaults();
const totalVaults = allVaults.length;
// Get comprehensive vault data (config + state + rates + limits) for a specific vault
const vaultId = 1;
const vaultData = await client.vault.getVaultByVaultId(vaultId);
// Check borrowing limits dynamically before prompting users
const borrowLimit = vaultData.limitsAndAvailability.borrowLimit;
const borrowable = vaultData.limitsAndAvailability.borrowable;访问Vault配置、仓位、兑换价格和清算数据,这对于动态列出所有可用杠杆市场至关重要。
typescript
// 发现所有可用的Vault
const allVaults = await client.vault.getAllVaults();
const totalVaults = allVaults.length;
// 获取特定Vault的综合数据(配置+状态+利率+限额)
const vaultId = 1;
const vaultData = await client.vault.getVaultByVaultId(vaultId);
// 在提示用户前动态检查借款限额
const borrowLimit = vaultData.limitsAndAvailability.borrowLimit;
const borrowable = vaultData.limitsAndAvailability.borrowable;Finding User Vault Positions
查询用户Vault仓位
Before making Vault operations (like deposit, borrow, or repay), you need to know a user's existing (which maps to an NFT).
positionIdtypescript
const userPublicKey = new PublicKey("YOUR_WALLET_PUBKEY");
// Retrieve all positions owned by the user
// Each position includes full vault data: NftPosition & { vault: VaultEntireData }
const positions = await client.vault.getAllUserPositions(userPublicKey);
positions.forEach((p) => {
console.log(`Position ID (nftId): ${p.nftId}`);
console.log(`Vault ID: ${p.vault.constantViews.vaultId}`);
console.log(`Collateral Supplied: ${p.supply.toString()}`);
console.log(`Debt Borrowed: ${p.borrow.toString()}`);
});在执行Vault操作(如存入、借款或还款)前,你需要了解用户现有的(对应NFT)。
positionIdtypescript
const userPublicKey = new PublicKey("YOUR_WALLET_PUBKEY");
// 获取用户拥有的所有仓位
// 每个仓位包含完整的Vault数据:NftPosition & { vault: VaultEntireData }
const positions = await client.vault.getAllUserPositions(userPublicKey);
positions.forEach((p) => {
console.log(`仓位ID(nftId):${p.nftId}`);
console.log(`Vault ID:${p.vault.constantViews.vaultId}`);
console.log(`提供的抵押品:${p.supply.toString()}`);
console.log(`借入的债务:${p.borrow.toString()}`);
});Vaults (Borrow)
Vault(Borrow)
Vaults handle collateral deposits and debt borrowing. All vault operations use the function.
getOperateIxThe direction of the operation is determined by the sign of and :
colAmountdebtAmount- Deposit: > 0,
colAmount= 0debtAmount - Withdraw: < 0,
colAmount= 0debtAmount - Borrow: = 0,
colAmount> 0debtAmount - Repay: = 0,
colAmount< 0debtAmount
Sentinels: and are already signed (negative); pass them as-is—do not call on them.
MAX_REPAY_AMOUNTMAX_WITHDRAW_AMOUNT.neg()Important: If is , a new position NFT is created, and the SDK returns the new .
positionId0positionIdVault负责处理抵押品存入和债务借款。所有Vault操作均使用函数。
getOperateIx操作方向由和的符号决定:
colAmountdebtAmount- 存入:> 0,
colAmount= 0debtAmount - 取出:< 0,
colAmount= 0debtAmount - 借款:= 0,
colAmount> 0debtAmount - 还款:= 0,
colAmount< 0debtAmount
哨兵值:和已为负值;直接传入即可,无需调用。
MAX_REPAY_AMOUNTMAX_WITHDRAW_AMOUNT.neg()重要提示:若为,将创建新的仓位NFT,SDK会返回新的。
positionId0positionIdCommon Vault Patterns
常见Vault操作模式
1. Deposit Collateral
typescript
import { getOperateIx } from "@jup-ag/lend/borrow";
// Deposit 1 USDC (base units: 1_000_000 for 6 decimals)
const { ixs, addressLookupTableAccounts, positionId: newPositionId } = await getOperateIx({
vaultId: 1,
positionId: 0, // 0 = create new position
colAmount: new BN(1_000_000), // Positive = Deposit
debtAmount: new BN(0),
connection,
signer,
});2. Borrow Debt
typescript
// Borrow 0.5 USDC (500_000 base units @ 6 decimals)
const { ixs, addressLookupTableAccounts } = await getOperateIx({
vaultId: 1,
positionId: EXISTING_POSITION_ID, // Use the nftId retrieved from the read SDK
colAmount: new BN(0),
debtAmount: new BN(500_000), // Positive = Borrow (0.5 USDC @ 6 decimals)
connection,
signer,
});3. Repay Debt (Using Max Sentinel)
When users want to repay their entire debt, do not try to calculate exact dust amounts. Use the sentinel exported by the SDK.
MAX_REPAY_AMOUNTtypescript
import { getOperateIx, MAX_REPAY_AMOUNT } from "@jup-ag/lend/borrow";
const { ixs, addressLookupTableAccounts } = await getOperateIx({
vaultId: 1,
positionId: EXISTING_POSITION_ID,
colAmount: new BN(0),
debtAmount: MAX_REPAY_AMOUNT, // Tells the protocol to clear the full debt
connection,
signer,
});4. Withdraw Collateral (Using Max Sentinel)
Similarly, to withdraw all available collateral, use the sentinel.
MAX_WITHDRAW_AMOUNTtypescript
import { getOperateIx, MAX_WITHDRAW_AMOUNT } from "@jup-ag/lend/borrow";
const { ixs, addressLookupTableAccounts } = await getOperateIx({
vaultId: 1,
positionId: EXISTING_POSITION_ID,
colAmount: MAX_WITHDRAW_AMOUNT, // Tells the protocol to withdraw everything
debtAmount: new BN(0),
connection,
signer,
});5. Combined operate
You can batch multiple operations—such as depositing + borrowing, or repaying + withdrawing—in a single transaction using :
getOperateIx- a. Deposit + Borrow in one Tx:
Pass both and
colAmountto deposit collateral and borrow simultaneously.debtAmounttypescriptconst { ixs, addressLookupTableAccounts } = await getOperateIx({ vaultId: 1, positionId: 0, // Create new position colAmount: new BN(1_000_000), // Deposit 1 USDC (6 decimals) debtAmount: new BN(500_000), // Borrow 0.5 USDC (6 decimals) connection, signer, }); - b. Repay + Withdraw in one Tx:
Repay debt and withdraw collateral at once. Use max sentinels for a full repayment or to withdraw the maximum available.
typescript
import { getOperateIx, MAX_WITHDRAW_AMOUNT, MAX_REPAY_AMOUNT } from "@jup-ag/lend/borrow"; const { ixs, addressLookupTableAccounts } = await getOperateIx({ vaultId: 1, positionId: EXISTING_POSITION_ID, colAmount: MAX_WITHDRAW_AMOUNT, // Withdraw all collateral debtAmount: MAX_REPAY_AMOUNT, // Repay all debt connection, signer, });
1. 存入抵押品
typescript
import { getOperateIx } from "@jup-ag/lend/borrow";
// 存入1 USDC(基础单位:6位小数对应1_000_000)
const { ixs, addressLookupTableAccounts, positionId: newPositionId } = await getOperateIx({
vaultId: 1,
positionId: 0, // 0 = 创建新仓位
colAmount: new BN(1_000_000), // 正数 = 存入
debtAmount: new BN(0),
connection,
signer,
});2. 借入债务
typescript
// 借入0.5 USDC(6位小数对应500_000基础单位)
const { ixs, addressLookupTableAccounts } = await getOperateIx({
vaultId: 1,
positionId: EXISTING_POSITION_ID, // 使用从只读SDK获取的nftId
colAmount: new BN(0),
debtAmount: new BN(500_000), // 正数 = 借入(6位小数对应0.5 USDC)
connection,
signer,
});3. 偿还债务(使用最大哨兵值)
当用户想要偿还全部债务时,无需尝试计算精确的小额残留金额,直接使用SDK导出的哨兵值。
MAX_REPAY_AMOUNTtypescript
import { getOperateIx, MAX_REPAY_AMOUNT } from "@jup-ag/lend/borrow";
const { ixs, addressLookupTableAccounts } = await getOperateIx({
vaultId: 1,
positionId: EXISTING_POSITION_ID,
colAmount: new BN(0),
debtAmount: MAX_REPAY_AMOUNT, // 指示协议清除全部债务
connection,
signer,
});4. 取出抵押品(使用最大哨兵值)
同样,若要取出所有可用抵押品,使用哨兵值。
MAX_WITHDRAW_AMOUNTtypescript
import { getOperateIx, MAX_WITHDRAW_AMOUNT } from "@jup-ag/lend/borrow";
const { ixs, addressLookupTableAccounts } = await getOperateIx({
vaultId: 1,
positionId: EXISTING_POSITION_ID,
colAmount: MAX_WITHDRAW_AMOUNT, // 指示协议取出所有抵押品
debtAmount: new BN(0),
connection,
signer,
});5. 组合操作
你可以使用在单笔交易中批量执行多个操作,例如存入+借款,或还款+取出:
getOperateIx- a. 存入+借款单笔交易:
同时传入和
colAmount,完成存入抵押品并借款。debtAmounttypescriptconst { ixs, addressLookupTableAccounts } = await getOperateIx({ vaultId: 1, positionId: 0, // 创建新仓位 colAmount: new BN(1_000_000), // 存入1 USDC(6位小数) debtAmount: new BN(500_000), // 借入0.5 USDC(6位小数) connection, signer, }); - b. 还款+取出单笔交易:
同时偿还债务并取出抵押品。使用最大哨兵值以完成全额还款或取出最大可用金额。
typescript
import { getOperateIx, MAX_WITHDRAW_AMOUNT, MAX_REPAY_AMOUNT } from "@jup-ag/lend/borrow"; const { ixs, addressLookupTableAccounts } = await getOperateIx({ vaultId: 1, positionId: EXISTING_POSITION_ID, colAmount: MAX_WITHDRAW_AMOUNT, // 取出所有抵押品 debtAmount: MAX_REPAY_AMOUNT, // 偿还所有债务 connection, signer, });
4. Flashloans
4. 闪贷
Flashloans allow you to borrow liquidity from the protocol without requiring upfront collateral. Return the borrowed amount within the exact same transaction—there are no flashloan fees. Borrow the asset you need directly for arbitrage, liquidations, or other use cases.
闪贷允许你无需预先提供抵押品即可从协议借入流动性,只需在同一交易内归还借入金额——无闪贷费用。可直接借入所需资产用于套利、清算或其他场景。
Executing a Flashloan (@jup-ag/lend)
执行闪贷(@jup-ag/lend)
The SDK provides simple helper functions to retrieve the instructions needed to execute a flashloan. The most convenient way is using .
@jup-ag/lendgetFlashloanIxtypescript
import { getFlashloanIx } from "@jup-ag/lend/flashloan";
import { Connection, PublicKey, TransactionMessage, VersionedTransaction } from "@solana/web3.js";
import BN from "bn.js";
async function executeFlashloan() {
const connection = new Connection("https://api.mainnet-beta.solana.com");
const signer = new PublicKey("YOUR_WALLET_PUBKEY");
const asset = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); // USDC
const borrowAmount = new BN(100_000_000); // 100 USDC (base units, 6 decimals)
// 1. Get the borrow and payback instructions
const { borrowIx, paybackIx } = await getFlashloanIx({
connection,
signer,
asset,
amount: borrowAmount,
});
// 2. Define your custom instructions that utilize the borrowed funds
const myCustomArbitrageInstructions = [
// ... your instructions here
];
// 3. Assemble the transaction: Borrow -> Custom Logic -> Payback
const instructions = [
borrowIx,
...myCustomArbitrageInstructions,
paybackIx
];
const latestBlockhash = await connection.getLatestBlockhash();
const message = new TransactionMessage({
payerKey: signer,
recentBlockhash: latestBlockhash.blockhash,
instructions,
}).compileToV0Message();
const transaction = new VersionedTransaction(message);
// Sign and send...
}@jup-ag/lendgetFlashloanIxtypescript
import { getFlashloanIx } from "@jup-ag/lend/flashloan";
import { Connection, PublicKey, TransactionMessage, VersionedTransaction } from "@solana/web3.js";
import BN from "bn.js";
async function executeFlashloan() {
const connection = new Connection("https://api.mainnet-beta.solana.com");
const signer = new PublicKey("YOUR_WALLET_PUBKEY");
const asset = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); // USDC
const borrowAmount = new BN(100_000_000); // 100 USDC(基础单位,6位小数)
// 1. 获取借入和归还指令
const { borrowIx, paybackIx } = await getFlashloanIx({
connection,
signer,
asset,
amount: borrowAmount,
});
// 2. 定义使用借入资金的自定义指令
const myCustomArbitrageInstructions = [
// ... 你的指令代码
];
// 3. 组装交易:借入 -> 自定义逻辑 -> 归还
const instructions = [
borrowIx,
...myCustomArbitrageInstructions,
paybackIx
];
const latestBlockhash = await connection.getLatestBlockhash();
const message = new TransactionMessage({
payerKey: signer,
recentBlockhash: latestBlockhash.blockhash,
instructions,
}).compileToV0Message();
const transaction = new VersionedTransaction(message);
// 签名并发送...
}5. Liquidity
5. 流动性
The Liquidity layer is the foundation of Jupiter Lend, holding all the underlying assets. While you usually interact with the Earn and Borrow layers, querying the Liquidity layer directly is highly useful for analytics, dashboards, and APY aggregators.
流动性层是Jupiter Lend的基础,持有所有基础资产。虽然你通常与Earn和Borrow层交互,但直接查询流动性层对分析、仪表盘和APY聚合器非常有用。
Liquidity Module
流动性模块
Access liquidity pool data, interest rates, and user supply/borrow positions.
typescript
const USDC = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
// Get market data for a token (rates, prices, utilization)
const data = await client.liquidity.getOverallTokenData(USDC);
// View rates (basis points: 10000 = 100%)
const supplyApr = Number(data.supplyRate) / 100;
const borrowApr = Number(data.borrowRate) / 100;访问流动性池数据、利率和用户供应/借款仓位。
typescript
const USDC = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
// 获取代币的市场数据(利率、价格、利用率)
const data = await client.liquidity.getOverallTokenData(USDC);
// 查看利率(基点:10000 = 100%)
const supplyApr = Number(data.supplyRate) / 100;
const borrowApr = Number(data.borrowRate) / 100;6. Jupiter Lend Build Kit
6. Jupiter Lend开发工具包
The Jupiter Lend Build Kit offers developer components, powerful utilities, and in-depth documentation to help you build and integrate with Jupiter Lend efficiently.
Base URL: https://developers.jup.ag/docs/lend
Jupiter Lend开发工具包提供开发者组件、强大的工具和详细文档,帮助你高效构建并集成Jupiter Lend。
Build Kit Documentation Index
开发工具包文档索引
- Getting started: overview, API vs SDK
- Earn: overview, deposit, withdraw, read data
- Wallet integrations (Privy): Earn with Privy, Borrow with Privy
- Borrow: overview, create position, deposit, borrow, repay, withdraw, combined operate, liquidate, read vault data
- Flashloan: overview, execute
- Advanced: advanced/multiply, advanced/unwind, advanced/repay-withdraw-collateral, advanced/vault-swap, advanced/utilization-after-deposit, advanced/native-staked-vault/overview, advanced/native-staked-vault/deposit, advanced/native-staked-vault/withdraw
- Liquidity: liquidity/analytics
- Resources: resources/program-addresses, resources/idl-and-types, resources/dune
- 入门指南:概述、API vs SDK
- Earn:概述、存入、取出、读取数据
- 钱包集成(Privy):使用Privy进行Earn、使用Privy进行Borrow
- Borrow:概述、创建仓位、存入、借款、还款、取出、组合操作、清算、读取Vault数据
- 闪贷:概述、执行
- 高级功能:高级/杠杆倍数、高级/平仓、高级/还款并取出抵押品、高级/Vault兑换、高级/存入后的利用率、高级/原生质押Vault/概述、高级/原生质押Vault/存入、高级/原生质押Vault/取出
- 流动性:流动性/分析
- 资源:资源/程序地址、资源/IDL和类型、资源/Dune
7. Complete Working Examples
7. 完整工作示例
Copy-paste-ready scripts. Install dependencies:npm install @solana/web3.js bn.js @jup-ag/lend @jup-ag/lend-read
可直接复制粘贴的脚本。安装依赖:npm install @solana/web3.js bn.js @jup-ag/lend @jup-ag/lend-read
Example 1 — Discover Position and Deposit (Read then Write)
示例1 — 发现仓位并存入(先读再写)
This example demonstrates how to use the read-only SDK () to query a user's existing vault positions. If a position for the target vault exists, it uses that NFT ID. If not, it falls back to creating a new position. Finally, it uses the write SDK () to deposit collateral into the position.
@jup-ag/lend-read@jup-ag/lendtypescript
import {
Connection,
Keypair,
PublicKey,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import BN from "bn.js";
import { Client } from "@jup-ag/lend-read";
import { getOperateIx } from "@jup-ag/lend/borrow";
import fs from "fs";
import path from "path";
const KEYPAIR_PATH = "/path/to/your/keypair.json";
const RPC_URL = "https://api.mainnet-beta.solana.com";
const VAULT_ID = 1;
const DEPOSIT_AMOUNT = new BN(1_000_000); // 1 USDC @ 6 decimals
function loadKeypair(keypairPath: string): Keypair {
const fullPath = path.resolve(keypairPath);
const secret = JSON.parse(fs.readFileSync(fullPath, "utf8"));
return Keypair.fromSecretKey(new Uint8Array(secret));
}
async function main() {
const userKeypair = loadKeypair(KEYPAIR_PATH);
const connection = new Connection(RPC_URL, { commitment: "confirmed" });
const signer = userKeypair.publicKey;
// 1. Read Data: Find existing user positions for the vault
const client = new Client(connection);
const positions = await client.vault.getAllUserPositions(signer);
let targetPositionId = 0; // 0 = create new position
const existing = positions.find((p) => p.vault.constantViews.vaultId === VAULT_ID);
if (existing) {
targetPositionId = existing.nftId;
console.log(`Found existing position NFT: ${targetPositionId}`);
}
if (targetPositionId === 0) {
console.log("No existing position found. Will create a new one.");
}
// 2. Write Data: Execute deposit
const { ixs, addressLookupTableAccounts, nftId } = await getOperateIx({
vaultId: VAULT_ID,
positionId: targetPositionId,
colAmount: DEPOSIT_AMOUNT,
debtAmount: new BN(0), // Deposit only
connection,
signer,
});
if (!ixs?.length) throw new Error("No instructions returned.");
// 3. Build the V0 Transaction Message
const latestBlockhash = await connection.getLatestBlockhash();
const message = new TransactionMessage({
payerKey: signer,
recentBlockhash: latestBlockhash.blockhash,
instructions: ixs,
}).compileToV0Message(addressLookupTableAccounts ?? []);
// 4. Sign and Send
const transaction = new VersionedTransaction(message);
transaction.sign([userKeypair]);
const signature = await connection.sendTransaction(transaction, {
skipPreflight: false,
maxRetries: 3,
preflightCommitment: "confirmed",
});
await connection.confirmTransaction({ signature, ...latestBlockhash }, "confirmed");
console.log(`Deposit successful! Signature: ${signature}`);
if (targetPositionId === 0) {
console.log(`New position created with NFT ID: ${nftId}`);
}
}
main().catch(console.error);本示例演示如何使用只读SDK()查询用户现有的Vault仓位。若目标Vault存在仓位,则使用该NFT ID;若不存在,则创建新仓位。最后使用写入SDK()将抵押品存入仓位。
@jup-ag/lend-read@jup-ag/lendtypescript
import {
Connection,
Keypair,
PublicKey,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import BN from "bn.js";
import { Client } from "@jup-ag/lend-read";
import { getOperateIx } from "@jup-ag/lend/borrow";
import fs from "fs";
import path from "path";
const KEYPAIR_PATH = "/path/to/your/keypair.json";
const RPC_URL = "https://api.mainnet-beta.solana.com";
const VAULT_ID = 1;
const DEPOSIT_AMOUNT = new BN(1_000_000); // 1 USDC @ 6位小数
function loadKeypair(keypairPath: string): Keypair {
const fullPath = path.resolve(keypairPath);
const secret = JSON.parse(fs.readFileSync(fullPath, "utf8"));
return Keypair.fromSecretKey(new Uint8Array(secret));
}
async function main() {
const userKeypair = loadKeypair(KEYPAIR_PATH);
const connection = new Connection(RPC_URL, { commitment: "confirmed" });
const signer = userKeypair.publicKey;
// 1. 读取数据:查找用户在该Vault的现有仓位
const client = new Client(connection);
const positions = await client.vault.getAllUserPositions(signer);
let targetPositionId = 0; // 0 = 创建新仓位
const existing = positions.find((p) => p.vault.constantViews.vaultId === VAULT_ID);
if (existing) {
targetPositionId = existing.nftId;
console.log(`找到现有仓位NFT:${targetPositionId}`);
}
if (targetPositionId === 0) {
console.log("未找到现有仓位,将创建新仓位。");
}
// 2. 写入数据:执行存入操作
const { ixs, addressLookupTableAccounts, nftId } = await getOperateIx({
vaultId: VAULT_ID,
positionId: targetPositionId,
colAmount: DEPOSIT_AMOUNT,
debtAmount: new BN(0), // 仅存入
connection,
signer,
});
if (!ixs?.length) throw new Error("未返回任何指令。");
// 3. 构建V0交易消息
const latestBlockhash = await connection.getLatestBlockhash();
const message = new TransactionMessage({
payerKey: signer,
recentBlockhash: latestBlockhash.blockhash,
instructions: ixs,
}).compileToV0Message(addressLookupTableAccounts ?? []);
// 4. 签名并发送
const transaction = new VersionedTransaction(message);
transaction.sign([userKeypair]);
const signature = await connection.sendTransaction(transaction, {
skipPreflight: false,
maxRetries: 3,
preflightCommitment: "confirmed",
});
await connection.confirmTransaction({ signature, ...latestBlockhash }, "confirmed");
console.log(`存入成功!交易签名:${signature}`);
if (targetPositionId === 0) {
console.log(`新仓位已创建,NFT ID:${nftId}`);
}
}
main().catch(console.error);Example 2 — Combined Operations (Deposit, Borrow, Repay, Withdraw)
示例2 — 组合操作(存入、借款、还款、取出)
This example demonstrates how to create a position, deposit collateral, and borrow debt in a single transaction. Then, it repays the debt and withdraws the collateral using the exact same function in a follow-up transaction. It also shows the critical step of deduplicating Address Lookup Tables (ALTs) when merging multiple instruction sets.
getOperateIxtypescript
import {
Connection,
Keypair,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import BN from "bn.js";
import { getOperateIx } from "@jup-ag/lend/borrow";
import fs from "fs";
import path from "path";
const KEYPAIR_PATH = "/path/to/your/keypair.json";
const RPC_URL = "https://api.mainnet-beta.solana.com";
const VAULT_ID = 1;
const DEPOSIT_AMOUNT = new BN(1_000_000); // 1 USDC @ 6 decimals
const BORROW_AMOUNT = new BN(500_000); // 0.5 USDC @ 6 decimals
const REPAY_AMOUNT = new BN(100_000); // 0.1 USDC @ 6 decimals
const WITHDRAW_AMOUNT = new BN(200_000); // 0.2 USDC @ 6 decimals
function loadKeypair(keypairPath: string): Keypair {
const fullPath = path.resolve(keypairPath);
const secret = JSON.parse(fs.readFileSync(fullPath, "utf8"));
return Keypair.fromSecretKey(new Uint8Array(secret));
}
async function main() {
const userKeypair = loadKeypair(KEYPAIR_PATH);
const connection = new Connection(RPC_URL, { commitment: "confirmed" });
const signer = userKeypair.publicKey;
// 1. Create position + Deposit + Borrow
const { ixs: depositBorrowIxs, addressLookupTableAccounts: depositBorrowAlts, positionId } = await getOperateIx({
vaultId: VAULT_ID,
positionId: 0,
colAmount: DEPOSIT_AMOUNT,
debtAmount: BORROW_AMOUNT,
connection,
signer,
});
// 2. Repay + Withdraw
const repayWithdrawResult = await getOperateIx({
vaultId: VAULT_ID,
positionId: positionId!,
colAmount: WITHDRAW_AMOUNT.neg(),
debtAmount: REPAY_AMOUNT.neg(),
connection,
signer,
});
// Merge instructions
const allIxs = [...(depositBorrowIxs ?? []), ...(repayWithdrawResult.ixs ?? [])];
// Merge and Deduplicate Address Lookup Tables (ALTs)
const allAlts = [
...(depositBorrowAlts ?? []),
...(repayWithdrawResult.addressLookupTableAccounts ?? []),
];
const seenKeys = new Set<string>();
const mergedAlts = allAlts.filter((alt) => {
const k = alt.key.toString();
if (seenKeys.has(k)) return false;
seenKeys.add(k);
return true;
});
if (!allIxs.length) throw new Error("No instructions returned.");
// Build the V0 Transaction Message
const latestBlockhash = await connection.getLatestBlockhash();
const message = new TransactionMessage({
payerKey: signer,
recentBlockhash: latestBlockhash.blockhash,
instructions: allIxs,
}).compileToV0Message(mergedAlts);
// Sign and Send
const transaction = new VersionedTransaction(message);
transaction.sign([userKeypair]);
const signature = await connection.sendTransaction(transaction, {
skipPreflight: false,
maxRetries: 3,
preflightCommitment: "confirmed",
});
await connection.confirmTransaction({ signature, ...latestBlockhash }, "confirmed");
console.log("Combined operate successful! Signature:", signature);
}
main().catch(console.error);本示例演示如何在单笔交易中创建仓位、存入抵押品并借入债务。然后在后续交易中使用相同的函数偿还债务并取出抵押品。同时展示了合并多个指令集时**去重地址查找表(ALT)**的关键步骤。
getOperateIxtypescript
import {
Connection,
Keypair,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import BN from "bn.js";
import { getOperateIx } from "@jup-ag/lend/borrow";
import fs from "fs";
import path from "path";
const KEYPAIR_PATH = "/path/to/your/keypair.json";
const RPC_URL = "https://api.mainnet-beta.solana.com";
const VAULT_ID = 1;
const DEPOSIT_AMOUNT = new BN(1_000_000); // 1 USDC @ 6位小数
const BORROW_AMOUNT = new BN(500_000); // 0.5 USDC @ 6位小数
const REPAY_AMOUNT = new BN(100_000); // 0.1 USDC @ 6位小数
const WITHDRAW_AMOUNT = new BN(200_000); // 0.2 USDC @ 6位小数
function loadKeypair(keypairPath: string): Keypair {
const fullPath = path.resolve(keypairPath);
const secret = JSON.parse(fs.readFileSync(fullPath, "utf8"));
return Keypair.fromSecretKey(new Uint8Array(secret));
}
async function main() {
const userKeypair = loadKeypair(KEYPAIR_PATH);
const connection = new Connection(RPC_URL, { commitment: "confirmed" });
const signer = userKeypair.publicKey;
// 1. 创建仓位 + 存入 + 借款
const { ixs: depositBorrowIxs, addressLookupTableAccounts: depositBorrowAlts, positionId } = await getOperateIx({
vaultId: VAULT_ID,
positionId: 0,
colAmount: DEPOSIT_AMOUNT,
debtAmount: BORROW_AMOUNT,
connection,
signer,
});
// 2. 还款 + 取出
const repayWithdrawResult = await getOperateIx({
vaultId: VAULT_ID,
positionId: positionId!,
colAmount: WITHDRAW_AMOUNT.neg(),
debtAmount: REPAY_AMOUNT.neg(),
connection,
signer,
});
// 合并指令
const allIxs = [...(depositBorrowIxs ?? []), ...(repayWithdrawResult.ixs ?? [])];
// 合并并去重地址查找表(ALT)
const allAlts = [
...(depositBorrowAlts ?? []),
...(repayWithdrawResult.addressLookupTableAccounts ?? []),
];
const seenKeys = new Set<string>();
const mergedAlts = allAlts.filter((alt) => {
const k = alt.key.toString();
if (seenKeys.has(k)) return false;
seenKeys.add(k);
return true;
});
if (!allIxs.length) throw new Error("未返回任何指令。");
// 构建V0交易消息
const latestBlockhash = await connection.getLatestBlockhash();
const message = new TransactionMessage({
payerKey: signer,
recentBlockhash: latestBlockhash.blockhash,
instructions: allIxs,
}).compileToV0Message(mergedAlts);
// 签名并发送
const transaction = new VersionedTransaction(message);
transaction.sign([userKeypair]);
const signature = await connection.sendTransaction(transaction, {
skipPreflight: false,
maxRetries: 3,
preflightCommitment: "confirmed",
});
await connection.confirmTransaction({ signature, ...latestBlockhash }, "confirmed");
console.log("组合操作成功!交易签名:", signature);
}
main().catch(console.error);8. Resources
8. 资源
API Documentation
API文档
- Jupiter Lend Overview: developers.jup.ag/docs/lend
- Lend API (Earn): api-reference/lend/earn | REST API for Earn operations (deposit/withdraw/mint/redeem, tokens, positions, earnings)
- Lend API (Borrow): (Coming Soon)
- Jupiter Lend概述:developers.jup.ag/docs/lend
- Lend API(Earn):api-reference/lend/earn | 用于Earn操作(存入/取出/铸造/赎回、代币、仓位、收益)的REST API
- Lend API(Borrow):(即将推出)
SDKs
SDK
Smart Contracts
智能合约
- Public Repository: Instadapp/fluid-solana-programs
- IDLs and Types: IDLs & types (folder)
/target
- 公开仓库:Instadapp/fluid-solana-programs
- IDL和类型:IDLs & 类型(文件夹)
/target
Program IDs (Mainnet)
主网程序ID
| Program | Address |
|---|---|
| Liquidity | |
| Lending(Earn) | |
| Lending Reward Rate Model | |
| Vaults(Borrow) | |
| Oracle | |
| Flashloan | |
| 程序 | 地址 |
|---|---|
| Liquidity | |
| Lending(Earn) | |
| Lending Reward Rate Model | |
| Vaults(Borrow) | |
| Oracle | |
| Flashloan | |