mcpField
J
jupiter-lend

jupiter-lend

github.com/jup-agその他85319 回インストール16 週間前に更新
リポジトリ

jupiter-lend について

Jupiter Lend は、Solana のレンディングプロトコルを利用する開発者向けの統合スキルです。Earn、Vault、流動性データを対象に、読み取り用と書き込み用の SDK の使い方を案内します。

主な機能

  1. 01jlToken 市場とユーザーのポジション照会
  2. 02Vault とユーザーポジションの検出
  3. 03担保・借入・返済操作の構築
  4. 04流動性金利と市場データの取得
  5. 05同一トランザクション内のフラッシュローン

活用シーン

  1. 01利用可能な Vault とポジションの表示
  2. 02担保預入と借入を行うトランザクションの構築
  3. 03トークンの供給金利と借入金利の確認
  4. 04裁定取引や清算向けフラッシュローンの構築

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jup-ag/agent-skills --skill jupiter-lend

インストール後、Claude Code で/jupiter-lendを入力して読み込まれたか確認します。

同梱ファイルREADME.md

詳細

Jupiter Lend プロトコル

Jupiter Lend(Fluid Protocol を利用)は、Solana 上の貸し出し・借り入れプロトコルです。Liquidity Pools、Lending Markets(jlTokens)、およびレバレッジポジション向けの Vaults を提供します。

このプロトコルでは、主に 2 つの SDK を使用します。

  • @jup-ag/lend-read:すべてのプログラム(Liquidity、Lending、Vaults)に対する読み取り専用クエリ
  • @jup-ag/lend:書き込み操作(預け入れ、引き出し、借り入れ、返済)

エージェントの使用方法

Jupiter Lend との連携をデモする際に使用できるプロンプトの例:

  • 利用可能なすべての Vault を見つけて一覧表示する
  • ユーザーのすべての Vault ポジションを取得する
  • 1 つのトランザクションで担保を預け入れて借り入れる
  • ポジションの負債を全額返済し、担保を最大額引き出す
  • ユーザーの Earn(jlToken)ポジションと基礎資産の残高を取得する
  • アービトラージまたは清算のためのフラッシュローンを構築する
  • トークンの流動性レートと APY を取得する
  • 新しい Vault ポジション(positionId 0)を作成し、担保を預け入れて借り入れる

SDK のインストール

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

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

1. 主な概念とプロトコル用語

Jupiter Lend のアーキテクチャと用語を理解すると、より優れた連携を構築できます。

アーキテクチャ:2 層モデル
  • Liquidity Layer(単一オーダーブック):すべての資産が保管される基盤レイヤーです。トークンの上限、金利カーブ、統合された流動性を管理します。ユーザーがこのレイヤーを直接操作することはありません。
  • Protocol Layer:Liquidity Layer の上に位置し、CPI(Cross-Program Invocation)を介して連携する、ユーザー向けのモジュール(Lending と Vaults)です。
用語
  • jlToken(Jupiter Lend Token):Lending プロトコルにトークンを供給した際に受け取る、利回りが得られる資産です(例:jlUSDC)。利息が蓄積するにつれて交換レートが上昇し、保有する jlToken の基礎資産である USDC に対する価値が高まります。
  • Exchange Price:「生の」保存額と実際のトークン額を換算するために使用する交換レートです。供給に対する利息の獲得や負債に対する利息の発生に伴い、継続的に上昇します。
  • Collateral Factor(CF):ポジションの開始または管理時に許容される、最大ローン・トゥ・バリュー(LTV)比率です。
  • Liquidation Threshold(LT):ポジションが担保不足となり、清算可能になる LTV です。
  • Liquidation Max Limit(LML):LTV の絶対的な上限です。ポジションのリスク比率がこの境界を超えると、流動性プロバイダーを保護するため、プロトコルによって自動的に吸収されます。
  • Liquidation Penalty:リスクのあるポジションの負債を清算人が代わりに返済する際に適用される割引率です。
  • Rebalance:上位のプロトコルレイヤー(Vaults/Lending)の会計を、Liquidity レイヤー上の実際のポジションと同期する操作です。また、発生済みの報酬を反映するため、オーダーブックも同期します。
  • Tick-based Architecture:Vaults プロトコルは、リスクレベル(負債と担保の比率)に応じてポジションを「ティック」に分類します。これにより、プロトコルはリスクを効率的に管理し、大規模な清算を処理できます。
  • Dust Borrow:除算時の丸め処理の複雑さに対応するため、ポジションに意図的に残されるごく少額の負債です。
  • Sentinel Values:MAX_WITHDRAW_AMOUNT や MAX_REPAY_AMOUNT のような定数です。ポジションに対して数学的に可能な最大額をプロトコルが動的に計算し、引き出しまたは返済するよう指示します。
金額と単位

すべての SDK の金額は基本単位(トークンの最小単位。例:小数点以下の桁数が 6 の場合、1_000_000 = 1 USDC)を使用します。


2. Jupiter Earn(Lending)

Jupiter Earn では、ユーザーは資産を供給して利回りを得られます。その見返りとして、利回りが得られる jlToken(例:jlUSDC)を受け取ります。

Lending モジュール(jlTokens)

jlToken(Jupiter Lend token)市場、交換価格、ユーザーポジションにアクセスします。

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

Lending(Earn)

基礎資産を預け入れて利回りが得られるトークンを受け取るか、トークンを引き出します。

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

3. Jupiter Borrow(Vaults)

Vaults は担保の預け入れと負債の借り入れを処理します。

Vault モジュールと検出

Vault の設定、ポジション、取引所価格、清算データにアクセスします。利用可能なすべてのレバレッジ市場を動的に一覧表示するうえで重要です。

// 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 ポジションの検索

Vault の操作(入金、借入、返済など)を行う前に、ユーザーが既に保有している positionId(NFT に対応する ID)を把握する必要があります。

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(借入)

Vault は担保の入金と負債の借入を管理します。すべての Vault 操作で getOperateIx 関数を使用します。

操作の方向は、colAmount と debtAmount の符号で決まります。

  • 入金:colAmount > 0、debtAmount = 0
  • 引き出し:colAmount < 0、debtAmount = 0
  • 借入:colAmount = 0、debtAmount > 0
  • 返済:colAmount = 0、debtAmount < 0

センチネル値:MAX_REPAY_AMOUNT と MAX_WITHDRAW_AMOUNT には既に負の符号が付いています。そのまま渡してください。.neg() を呼び出さないでください。

重要:positionId が 0 の場合、新しいポジション NFT が作成され、SDK から新しい positionId が返されます。

Vault の一般的なパターン

1. 担保の入金

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 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. 負債の返済(最大値のセンチネルを使用) ユーザーが負債の 全額 を返済する場合、細かな端数を正確に計算しようとしないでください。SDK が提供する MAX_REPAY_AMOUNT センチネル値を使用します。

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. 担保の引き出し(最大値のセンチネルを使用) 同様に、引き出し可能な担保をすべて引き出すには、MAX_WITHDRAW_AMOUNT センチネル値を使用します。

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. 複合操作

getOperateIx を使用すると、入金+借入、返済+引き出しなど、複数の操作を1つのトランザクションにまとめられます。

  • a. 1つの Tx で入金+借入: colAmount と debtAmount の両方を渡すと、担保の入金と借入を同時に行えます。
    const { 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. 1つの Tx で返済+引き出し: 負債の返済と担保の引き出しを同時に行います。全額を返済する場合や、引き出し可能な最大額を引き出す場合は、最大値のセンチネルを使用します。
    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. フラッシュローン

フラッシュローンを利用すると、事前の担保なしでプロトコルから流動性を借りられます。借りた金額は必ず同じトランザクション内で返済してください。フラッシュローン手数料はありません。裁定取引、清算、その他のユースケースで必要な資産を直接借り入れられます。

フラッシュローンの実行(@jup-ag/lend)

@jup-ag/lend SDK には、フラッシュローンの実行に必要な命令を取得するための便利なヘルパー関数が用意されています。最も便利な方法は getFlashloanIx を使用することです。

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

5. 流動性

流動性レイヤーは Jupiter Lend の基盤であり、すべての原資産を保持しています。通常は Earn レイヤーと Borrow レイヤーを利用しますが、流動性レイヤーを直接クエリすると、分析、ダッシュボード、APY アグリゲーターに役立ちます。

流動性モジュール

流動性プールのデータ、金利、ユーザーの供給・借入ポジションにアクセスします。

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;

6. Jupiter Lend Build Kit

Jupiter Lend Build Kit は、Jupiter Lend を効率的に活用し、統合するための開発者向けコンポーネント、高機能なユーティリティ、詳細なドキュメントを提供します。

ベース URL:https://developers.jup.ag/docs/lend

Build Kit ドキュメント索引

7. 完全な動作サンプル

コピーしてそのまま実行できるスクリプトです。依存関係をインストールします:npm install @solana/web3.js bn.js @jup-ag/lend @jup-ag/lend-read

例 1 — ポジションの検出と入金(読み取り後に書き込み)

この例では、読み取り専用 SDK(@jup-ag/lend-read)を使って、ユーザーが保有する既存のボールトポジションを照会する方法を示します。対象のボールトのポジションが存在する場合は、その NFT ID を使用します。存在しない場合は、新しいポジションを作成します。最後に、書き込み用 SDK(@jup-ag/lend)を使って、ポジションに担保を入金します。

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

例 2 — 複合操作(入金、借入、返済、出金)

この例では、1 回のトランザクションでポジションを作成し、担保を入金して、負債を借り入れる方法を示します。その後、後続のトランザクションで、まったく同じ getOperateIx 関数を使って負債を返済し、担保を出金します。また、複数の命令セットをマージする際に、Address Lookup Tables(ALT)を重複排除する重要な手順も示します。

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

8. リソース

API ドキュメント

  • Jupiter Lend の概要:developers.jup.ag/docs/lend
  • Lend API(Earn):api-reference/lend/earn | Earn 操作用の REST API(入金/出金/ミント/償還、トークン、ポジション、収益)
  • Lend API(Borrow):(近日公開)

SDK

  • 読み取り SDK(@jup-ag/lend-read):NPM | 流動性プール、貸付市場(jlTokens)、ボルトを照会するための読み取り専用 SDK
  • 書き込み SDK(@jup-ag/lend):NPM | 書き込みトランザクション(預け入れ、引き出し、運用)を構築するためのコア SDK

スマートコントラクト

プログラム ID(メインネット)

プログラムアドレス
流動性jupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC
貸付(Earn)jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9
貸付報酬レートモデルjup7TthsMgcR9Y3L277b8Eo9uboVSmu1utkuXHNUKar
ボルト(借入)jupr81YtYssSyPt8jbnGuiWon5f6x9TcDEFxYe3Bdzi
オラクルjupnw4B6Eqs7ft6rxpzYLJZYSnrpRgPcr589n5Kv4oc
フラッシュローンjupgfSgfuAXv4B6R2Uxu85Z1qdzgju79s6MfZekN6XS

コメント