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). No API keys needed for on-chain interactions.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "jupiter-lend" with this command: npx skills add jup-ag/agent-skills/jup-ag-agent-skills-jupiter-lend

Jupiter Lend Protocol

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)

SDK Installation

# For read operations (queries, prices, positions)
npm install @jup-ag/lend-read

# For write operations (transactions)
npm install @jup-ag/lend

1. Key Concepts & Protocol Jargon

Understanding the architecture and terminology of Jupiter Lend will help you build better integrations.

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

Terminology

  • jlToken (Jupiter Lend Token): The yield-bearing asset you receive when supplying tokens to the Lending protocol (e.g., jlUSDC). As interest accrues, the exchange rate increases, making your jlToken worth more underlying 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 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.

2. Reading Data (@jup-ag/lend-read)

The read SDK uses a unified Client to query Liquidity, Lending, and Vault modules. All queries are read-only and fetch decoded on-chain accounts via RPC. This is how integrators find available markets, rates, and existing user positions.

Quick Start (Read SDK)

import { Client } from "@jup-ag/lend-read";
import { Connection, PublicKey } from "@solana/web3.js";

// Initialize with a connection
const connection = new Connection("https://api.mainnet-beta.solana.com");
const client = new Client(connection);

Finding User Vault Positions

Before making Vault operations (like deposit, borrow, or repay), you need to know a user's existing positionId (which maps to an NFT).

const userPublicKey = new PublicKey("YOUR_WALLET_PUBKEY");

// Retrieve all positions owned by the user
// Returns both the user position details and the corresponding Vault data
const { userPositions_, vaultsData_ } = await client.vault.positionsByUser(userPublicKey);

for (let i = 0; i < userPositions_.length; i++) {
  console.log(`Position ID (nftId): ${userPositions_[i].nftId}`);
  console.log(`Vault ID: ${vaultsData_[i].constantVariables.vaultId}`);
  console.log(`Collateral Supplied: ${userPositions_[i].supply}`);
  console.log(`Debt Borrowed: ${userPositions_[i].borrow}`);
}

Liquidity Module

Access liquidity pool data, interest rates, and user supply/borrow positions.

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;

Lending Module (jlTokens)

Access jlToken (Jupiter Lend token) markets, exchange prices, and user positions.

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

Vault Module & Discovery

Access vault configurations, positions, exchange prices, and liquidation data. This is crucial for dynamically listing all available leverage markets.

// Discover all available vaults
const allVaults = await client.vault.getAllVaultsAddresses();
const totalVaults = await client.vault.getTotalVaults();

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

3. Writing Data (@jup-ag/lend)

All write operations generate instructions (ixs) and Address Lookup Tables (addressLookupTableAccounts) that must be wrapped in a versioned (v0) transaction.

Lending (Earn)

Deposit underlying assets to receive yield-bearing tokens, or withdraw them.

import { getDepositIxs, getWithdrawIxs } from "@jup-ag/lend/earn";
import BN from "bn.js";

// Deposit 1 USDC (assuming 6 decimals)
const { ixs: depositIxs } = await getDepositIxs({
  amount: new BN(1_000_000),
  asset: USDC_PUBKEY,
  signer: userPublicKey,
  connection,
});

// Withdraw
const { ixs: withdrawIxs } = await getWithdrawIxs({
  amount: new BN(100_000),
  asset: USDC_PUBKEY,
  signer: userPublicKey,
  connection,
});

Vaults (Borrow)

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:

  • Deposit: colAmount > 0, debtAmount = 0
  • Withdraw: colAmount < 0, debtAmount = 0
  • Borrow: colAmount = 0, debtAmount > 0
  • Repay: colAmount = 0, debtAmount < 0

Important: If positionId is 0, a new position NFT is created, and the SDK returns the new positionId.

Common Vault Patterns

1. Deposit Collateral

import { getOperateIx } from "@jup-ag/lend/borrow";

// Deposit 1 token (base units)
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

// Borrow 0.5 tokens against existing position
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
  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 MAX_REPAY_AMOUNT sentinel exported by the SDK.

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 MAX_WITHDRAW_AMOUNT sentinel.

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 colAmount and debtAmount to deposit collateral and borrow simultaneously.

    const { ixs, addressLookupTableAccounts } = await getOperateIx({
      vaultId: 1,
      positionId: 0, // Create new position
      colAmount: new BN(1_000_000), // Deposit collateral
      debtAmount: new BN(500_000),  // Borrow
      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.

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

4. Jupiter Lend Build Kit

The Jupiter Lend Build Kit provides UI components, utilities, and extensive documentation to easily integrate Jupiter Lend into your application. It serves as a comprehensive reference for both humans and AI agents.

(Note: The build kit is currently in development on staging. Production URLs will be updated here once officially deployed.)

Build Kit Documentation Index

The Build Kit documentation covers the following core integration topics. When referencing the build kit, you can explore these pages for specific examples and concepts:

Developers & Core Concepts:

  • overview: Core concepts and getting started.
  • api-vs-sdk: Guidance on choosing between the Jupiter API and the @jup-ag/lend SDKs for integration.

Earn Module (Lending):

  • earn-overview: Fetching market configurations, supply caps, and yield metrics for tokens.
  • user-position: Fetching a user's supplied balance and accrued yield.
  • Operations:
    • deposit-earn: Supplying assets to the protocol.
    • withdraw-earn: Removing supplied assets and yield.

Borrow Module (Vaults):

  • overview-borrow: Core Vault concepts, LTV limits, and borrowing caps.
  • vault-data: Fetching dynamic vault configurations, risk metrics, rates, and limits.
  • Operations:
    • create-position: Minting a new position NFT to start borrowing.
    • deposit-borrow: Supplying collateral to a specific vault.
    • borrow: Drawing debt against deposited collateral.
    • repay: Repaying outstanding debt.
    • withdraw-borrow: Withdrawing deposited collateral.
    • operate-combined: Batching multiple actions (e.g., Deposit + Borrow, Repay + Withdraw) in a single transaction.
    • liquidate: Mechanics of liquidating unhealthy positions.

Flashloan Module:

  • flashloan-overview: Core concepts and use cases for flashloans.
  • flashloan-operate: Executing flashloans using getFlashloanIx with custom intermediate logic.

Resources:

  • program-addresses: Official Mainnet Program IDs for Liquidity, Lending, Vaults, and Oracles.
  • idl-and-types: Accessing raw IDLs for building CPIs and parsing on-chain state.

5. Complete Working Examples

Copy-paste-ready scripts. Install dependencies: npm install @solana/web3.js bn.js @jup-ag/lend @jup-ag/lend-read

Example 1 — Discover Position and Deposit (Read then Write)

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.

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);

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 { userPositions_, vaultsData_ } = await client.vault.positionsByUser(signer);

  let targetPositionId = 0; // Default to 0 (create new position)

  // Find an existing position for our target Vault ID
  for (let i = 0; i < userPositions_.length; i++) {
    if (vaultsData_[i].constantVariables.vaultId === VAULT_ID) {
      targetPositionId = userPositions_[i].nftId;
      console.log(`Found existing position NFT: ${targetPositionId}`);
      break;
    }
  }

  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);

Example 2 — Combined Operations (Deposit, Borrow, Repay, Withdraw)

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.

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);
const BORROW_AMOUNT = new BN(500_000);
const REPAY_AMOUNT = new BN(100_000);
const WITHDRAW_AMOUNT = new BN(200_000);

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);

Resources

API Documentation

SDKs

  • Read SDK (@jup-ag/lend-read): NPM | Read-only SDK for querying liquidity pools, lending markets (jlTokens), and vaults
  • Write SDK (@jup-ag/lend): NPM | Core SDK for building write transactions (deposits, withdraws, operates)

Smart Contracts

Program IDs (Mainnet)

ProgramAddress
LiquidityjupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC
Lendingjup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9
Lending Reward Rate Modeljup7TthsMgcR9Y3L277b8Eo9uboVSmu1utkuXHNUKar
Vaultsjupr81YtYssSyPt8jbnGuiWon5f6x9TcDEFxYe3Bdzi
Oraclejupnw4B6Eqs7ft6rxpzYLJZYSnrpRgPcr589n5Kv4oc
FlashloanjupgfSgfuAXv4B6R2Uxu85Z1qdzgju79s6MfZekN6XS

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Web3

iseclaw-intel

Indonesian Web3 intelligence via Iseclaw ACP agent. Real-time market data, token signals, TGE research, and GameFi analysis from Southeast Asia's first transparent AI agent.

Archived SourceRecently Updated
Automation

integrating-jupiter

No summary provided by upstream source.

Repository SourceNeeds Review
Web3

helius-phantom

Build frontend Solana applications with Phantom Connect SDK and Helius infrastructure. Covers React, React Native, and browser SDK integration, transaction signing via Helius Sender, API key proxying, token gating, NFT minting, crypto payments, real-time updates, and secure frontend architecture.

Archived SourceRecently Updated
Web3

helius-dflow

Build Solana trading applications combining DFlow trading APIs with Helius infrastructure. Covers spot swaps (imperative and declarative), prediction markets, real-time market streaming, Proof KYC, transaction submission via Sender, fee optimization, shred-level streaming via LaserStream, and wallet intelligence.

Archived SourceRecently Updated