Loading...
Loading...
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 skill4agent add jup-ag/agent-skills jupiter-lend@jup-ag/lend-read@jup-ag/lend# For read operations (queries, prices, positions)
npm install @jup-ag/lend-read
# For write operations (transactions)
npm install @jup-ag/lendjlUSDCjlTokenUSDCMAX_WITHDRAW_AMOUNTMAX_REPAY_AMOUNT1_000_000jlTokensjlUSDC// 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);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;positionIdconst 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()}`);
});getOperateIxcolAmountdebtAmountcolAmountdebtAmountcolAmountdebtAmountcolAmountdebtAmountcolAmountdebtAmountMAX_REPAY_AMOUNTMAX_WITHDRAW_AMOUNT.neg()positionId0positionIdimport { 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,
});MAX_REPAY_AMOUNTimport { 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,
});MAX_WITHDRAW_AMOUNTimport { 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,
});getOperateIxcolAmountdebtAmountconst { 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,
});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,
});@jup-ag/lendgetFlashloanIximport { 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...
}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;Copy-paste-ready scripts. Install dependencies:npm install @solana/web3.js bn.js @jup-ag/lend @jup-ag/lend-read
@jup-ag/lend-read@jup-ag/lendimport {
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);getOperateIximport {
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);@jup-ag/lend-read@jup-ag/lend/target| Program | Address |
|---|---|
| Liquidity | |
| Lending(Earn) | |
| Lending Reward Rate Model | |
| Vaults(Borrow) | |
| Oracle | |
| Flashloan | |