npx skills add ...
npx skills add jup-ag/agent-skills --skill jupiter-lend
Interact with Jupiter Lend Protocol. Read-only SDK (@jup-ag/lend-read) for querying liquidity pools, lending markets (jlTokens), and vaults. Write SDK (@jup-ag/lend) for lending (deposit/withdraw) and vault operations (deposit collateral, borrow, repay, manage positions).
npx skills add jup-ag/agent-skills --skill 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:
@jup-ag/lend-read: Read-only queries for all programs (Liquidity, Lending, Vaults)@jup-ag/lend: Write operations (deposit, withdraw, borrow, repay)Example prompts you can use to demo Jupiter Lend integrations:
Understanding the architecture and terminology of Jupiter Lend will help you build better integrations.
jlUSDC). As interest accrues, the exchange rate increases, making your jlToken worth more underlying USDC.MAX_WITHDRAW_AMOUNT and MAX_REPAY_AMOUNT that tell the protocol to dynamically calculate and withdraw/repay the maximum mathematically possible amount for a position.All SDK amounts use base units (smallest token unit, e.g. 1_000_000 = 1 USDC for 6 decimals).
Jupiter Earn allows users to supply assets to earn yield. In return, users receive yield-bearing jlTokens (e.g., jlUSDC).
Access jlToken (Jupiter Lend token) markets, exchange prices, and user positions.
Deposit underlying assets to receive yield-bearing tokens, or withdraw them.
Vaults handle collateral deposits and debt borrowing.
Access vault configurations, positions, exchange prices, and liquidation data. This is crucial for dynamically listing all available leverage markets.
Before making Vault operations (like deposit, borrow, or repay), you need to know a user's existing positionId (which maps to an NFT).
Vaults handle collateral deposits and debt borrowing. All vault operations use the getOperateIx function.
The direction of the operation is determined by the sign of colAmount and debtAmount:
colAmount > 0, debtAmount = 0colAmount < 0, debtAmount = 0colAmount = 0, debtAmount > 0colAmount = 0, debtAmount < 0Sentinels: MAX_REPAY_AMOUNT and MAX_WITHDRAW_AMOUNT are already signed (negative); pass them as-is—do not call .neg() on them.
Important: If positionId is 0, a new position NFT is created, and the SDK returns the new positionId.
1. Deposit Collateral
2. Borrow Debt
3. Repay Debt (Using Max Sentinel)
When users want to repay their entire debt, do not try to calculate exact dust amounts. Use the MAX_REPAY_AMOUNT sentinel exported by the SDK.
4. Withdraw Collateral (Using Max Sentinel)
Similarly, to withdraw all available collateral, use the MAX_WITHDRAW_AMOUNT sentinel.
5. Combined operate
You can batch multiple operations—such as depositing + borrowing, or repaying + withdrawing—in a single transaction using getOperateIx:
colAmount and debtAmount to deposit collateral and borrow simultaneously.
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.
The @jup-ag/lend SDK provides simple helper functions to retrieve the instructions needed to execute a flashloan. The most convenient way is using getFlashloanIx.
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.
Access liquidity pool data, interest rates, and user supply/borrow positions.
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
Copy-paste-ready scripts. Install dependencies:
npm install @solana/web3.js bn.js @jup-ag/lend @jup-ag/lend-read
This example demonstrates how to use the read-only SDK (@jup-ag/lend-read) 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 (@jup-ag/lend) to deposit collateral into the position.
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 getOperateIx function in a follow-up transaction. It also shows the critical step of deduplicating Address Lookup Tables (ALTs) when merging multiple instruction sets.
@jup-ag/lend-read): NPM | Read-only SDK for querying liquidity pools, lending markets (jlTokens), and vaults@jup-ag/lend): NPM | Core SDK for building write transactions (deposits, withdraws, operates)/target folder)| Program | Address |
|---|---|
| Liquidity | jupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC |
| Lending(Earn) | jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9 |
| Lending Reward Rate Model | jup7TthsMgcR9Y3L277b8Eo9uboVSmu1utkuXHNUKar |
| Vaults(Borrow) | jupr81YtYssSyPt8jbnGuiWon5f6x9TcDEFxYe3Bdzi |
| Oracle | jupnw4B6Eqs7ft6rxpzYLJZYSnrpRgPcr589n5Kv4oc |
| Flashloan | jupgfSgfuAXv4B6R2Uxu85Z1qdzgju79s6MfZekN6XS |
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,
});// 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;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()}`);
});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,
});// 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,
});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,
});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,
});