kamino

Par elophanto · elophanto

Guide complet pour Kamino Finance - le principal protocole DeFi de Solana pour le prêt, l'emprunt, la gestion de liquidité et le trading avec levier. Couvre klend-sdk (prêt), kliquidity-sdk (stratégies de liquidité automatisées), scope-sdk (agrégateur d'oracle), les opérations multiply/levier, les vaults et les ordres d'obligation.

npx skills add https://github.com/elophanto/elophanto --skill kamino

Guide de développement Kamino Finance

Construisez des applications DeFi sophistiquées sur Solana avec Kamino Finance - un protocole DeFi complet offrant le prêt, l'emprunt, la gestion de liquidité automatisée, le trading à effet de levier et l'agrégation d'oracles.

Aperçu

Kamino Finance fournit :

  • Kamino Lend (K-Lend) : Protocole de prêt et d'emprunt avec marchés isolés
  • Kamino Liquidity (K-Liquidity) : Stratégies automatisées de gestion de liquidité CLMM
  • Scope Oracle : Agrégateur d'oracles de prix pour une tarification fiable
  • Multiply/Leverage : Positions longues/courtes à effet de levier sur les actifs
  • Vaults : Stratégies de vault générateur de rendement
  • Obligation Orders : Exécution automatisée d'ordres basée sur LTV et prix

Démarrage rapide

Installation

# Lending SDK
npm install @kamino-finance/klend-sdk

# Liquidity SDK
npm install @kamino-finance/kliquidity-sdk

# Oracle SDK
npm install @kamino-finance/scope-sdk

# Dépendances peer requises
npm install @solana/web3.js @coral-xyz/anchor decimal.js

Configuration de l'environnement

# Fichier .env
SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
WALLET_KEYPAIR_PATH=./keypair.json

Kamino Lending (klend-sdk)

Le SDK de prêt permet l'interaction avec les marchés de prêt de Kamino pour les dépôts, emprunts, remboursements et liquidations.

Classes principales

Classe Objectif
KaminoMarket Charger et interagir avec les marchés de prêt
KaminoAction Construire les transactions de prêt (dépôt, emprunt, remboursement, retrait)
KaminoObligation Gérer les obligations utilisateur (positions)
KaminoReserve Accéder aux configurations et statistiques de réserve
VanillaObligation Type d'obligation standard

Initialiser le marché

import { KaminoMarket } from "@kamino-finance/klend-sdk";
import { Connection, PublicKey } from "@solana/web3.js";

const connection = new Connection("https://api.mainnet-beta.solana.com");

// Adresse du marché de prêt principal
const MAIN_MARKET = new PublicKey("7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF");

// Charger le marché avec les données de base
const market = await KaminoMarket.load(connection, MAIN_MARKET);

// Charger les réserves pour les données détaillées
await market.loadReserves();

// Obtenir une réserve spécifique
const usdcReserve = market.getReserve("USDC");
console.log("Total Dépôts:", usdcReserve?.stats.totalDepositsWads.toString());
console.log("LTV:", usdcReserve?.stats.loanToValueRatio);
console.log("APY Emprunt:", usdcReserve?.stats.borrowInterestAPY);
console.log("APY Approvisionnement:", usdcReserve?.stats.supplyInterestAPY);

// Actualiser toutes les données incluant les obligations
await market.refreshAll();

Déposer des garanties

import { KaminoAction, VanillaObligation, PROGRAM_ID } from "@kamino-finance/klend-sdk";
import { Keypair, sendAndConfirmTransaction } from "@solana/web3.js";
import Decimal from "decimal.js";

async function deposit(
  market: KaminoMarket,
  wallet: Keypair,
  tokenSymbol: string,
  amount: Decimal
) {
  // Construire la transaction de dépôt
  const kaminoAction = await KaminoAction.buildDepositTxns(
    market,
    amount.toString(),           // Montant en unités de base
    tokenSymbol,                  // p. ex. "USDC", "SOL"
    wallet.publicKey,
    new VanillaObligation(PROGRAM_ID),
    0,                            // Budget de calcul supplémentaire (optionnel)
    true,                         // Inclure les instructions d'initialisation Ata
    undefined,                    // Référent (optionnel)
    undefined,                    // Slot courant (optionnel)
    "finalized"                   // Engagement
  );

  // Obtenir toutes les instructions
  const instructions = [
    ...kaminoAction.setupIxs,
    ...kaminoAction.lendingIxs,
    ...kaminoAction.cleanupIxs,
  ];

  // Créer et envoyer la transaction
  const tx = new Transaction().add(...instructions);
  const signature = await sendAndConfirmTransaction(connection, tx, [wallet]);

  return signature;
}

Emprunter des actifs

async function borrow(
  market: KaminoMarket,
  wallet: Keypair,
  tokenSymbol: string,
  amount: Decimal
) {
  const kaminoAction = await KaminoAction.buildBorrowTxns(
    market,
    amount.toString(),
    tokenSymbol,
    wallet.publicKey,
    new VanillaObligation(PROGRAM_ID),
    0,
    true,
    false,                        // Inclure le dépôt pour les frais (optionnel)
    undefined,
    undefined,
    "finalized"
  );

  const instructions = [
    ...kaminoAction.setupIxs,
    ...kaminoAction.lendingIxs,
    ...kaminoAction.cleanupIxs,
  ];

  const tx = new Transaction().add(...instructions);
  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

Rembourser un emprunt

async function repay(
  market: KaminoMarket,
  wallet: Keypair,
  tokenSymbol: string,
  amount: Decimal | "max"
) {
  const repayAmount = amount === "max" ? "max" : amount.toString();

  const kaminoAction = await KaminoAction.buildRepayTxns(
    market,
    repayAmount,
    tokenSymbol,
    wallet.publicKey,
    new VanillaObligation(PROGRAM_ID),
    0,
    true,
    undefined,
    "finalized"
  );

  const instructions = [
    ...kaminoAction.setupIxs,
    ...kaminoAction.lendingIxs,
    ...kaminoAction.cleanupIxs,
  ];

  const tx = new Transaction().add(...instructions);
  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

Retirer des garanties

async function withdraw(
  market: KaminoMarket,
  wallet: Keypair,
  tokenSymbol: string,
  amount: Decimal | "max"
) {
  const withdrawAmount = amount === "max" ? "max" : amount.toString();

  const kaminoAction = await KaminoAction.buildWithdrawTxns(
    market,
    withdrawAmount,
    tokenSymbol,
    wallet.publicKey,
    new VanillaObligation(PROGRAM_ID),
    0,
    true,
    undefined,
    "finalized"
  );

  const instructions = [
    ...kaminoAction.setupIxs,
    ...kaminoAction.lendingIxs,
    ...kaminoAction.cleanupIxs,
  ];

  const tx = new Transaction().add(...instructions);
  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

Obtenir les obligations utilisateur

// Obtenir une seule obligation vanilla pour l'utilisateur
const obligation = await market.getUserVanillaObligation(wallet.publicKey);

if (obligation) {
  console.log("Dépôts:", obligation.state.deposits);
  console.log("Emprunts:", obligation.state.borrows);
  console.log("Facteur de santé:", obligation.refreshedStats.borrowLimit);
}

// Obtenir toutes les obligations pour l'utilisateur
const allObligations = await market.getAllUserObligations(wallet.publicKey);

// Obtenir les obligations pour une réserve spécifique
const reserveObligations = await market.getAllUserObligationsForReserve(
  wallet.publicKey,
  usdcReserve
);

// Vérifier si la réserve fait partie de l'obligation
const isReserveInObligation = market.isReserveInObligation(
  obligation,
  usdcReserve
);

Liquidation

async function liquidate(
  market: KaminoMarket,
  liquidator: Keypair,
  obligationOwner: PublicKey,
  repayTokenSymbol: string,
  withdrawTokenSymbol: string,
  repayAmount: Decimal
) {
  const kaminoAction = await KaminoAction.buildLiquidateTxns(
    market,
    repayAmount.toString(),
    repayTokenSymbol,
    withdrawTokenSymbol,
    obligationOwner,
    liquidator.publicKey,
    new VanillaObligation(PROGRAM_ID),
    0,
    true,
    "finalized"
  );

  const instructions = [
    ...kaminoAction.setupIxs,
    ...kaminoAction.lendingIxs,
    ...kaminoAction.cleanupIxs,
  ];

  const tx = new Transaction().add(...instructions);
  return await sendAndConfirmTransaction(connection, tx, [liquidator]);
}

Opérations d'effet de levier/Multiply

Kamino supporte les positions à effet de levier via la fonctionnalité multiply.

Ouvrir une position à effet de levier

import {
  getLeverageDepositIxns,
  getLeverageWithdrawIxns,
  calculateLeverageMultiplier
} from "@kamino-finance/klend-sdk/leverage";

async function openLeveragedPosition(
  market: KaminoMarket,
  wallet: Keypair,
  collateralToken: string,
  borrowToken: string,
  depositAmount: Decimal,
  targetLeverage: number  // p. ex. 2x, 3x
) {
  // Calculer les paramètres pour l'effet de levier cible
  const leverageParams = await calculateLeverageMultiplier(
    market,
    collateralToken,
    borrowToken,
    depositAmount,
    targetLeverage
  );

  // Construire les instructions de dépôt à effet de levier
  const { instructions, lookupTables } = await getLeverageDepositIxns(
    market,
    wallet.publicKey,
    collateralToken,
    borrowToken,
    depositAmount,
    leverageParams,
    new VanillaObligation(PROGRAM_ID)
  );

  // Exécuter la transaction avec les tables de recherche d'adresses
  const tx = new VersionedTransaction(/* ... */);
  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

Fermer une position à effet de levier

async function closeLeveragedPosition(
  market: KaminoMarket,
  wallet: Keypair,
  collateralToken: string,
  borrowToken: string
) {
  const { instructions, lookupTables } = await getLeverageWithdrawIxns(
    market,
    wallet.publicKey,
    collateralToken,
    borrowToken,
    "max",  // Retirer la position complète
    new VanillaObligation(PROGRAM_ID)
  );

  const tx = new VersionedTransaction(/* ... */);
  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

Obligation Orders

Automatiser les actions basées sur les seuils de LTV ou de prix.

Ordres basés sur LTV

import {
  createLtvBasedOrder,
  LtvOrderType
} from "@kamino-finance/klend-sdk/obligation_orders";

// Créer un ordre pour rembourser quand le LTV dépasse le seuil
async function createLtvOrder(
  market: KaminoMarket,
  wallet: Keypair,
  targetLtv: number,  // p. ex. 0,8 pour 80 %
  repayToken: string,
  repayAmount: Decimal
) {
  const orderIx = await createLtvBasedOrder(
    market,
    wallet.publicKey,
    new VanillaObligation(PROGRAM_ID),
    {
      type: LtvOrderType.REPAY_ON_HIGH_LTV,
      triggerLtv: targetLtv,
      repayToken,
      repayAmount: repayAmount.toString(),
    }
  );

  const tx = new Transaction().add(orderIx);
  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

Ordres basés sur le prix

import {
  createPriceBasedOrder,
  PriceOrderType
} from "@kamino-finance/klend-sdk/obligation_orders";

// Créer un ordre de stop-loss
async function createStopLossOrder(
  market: KaminoMarket,
  wallet: Keypair,
  tokenSymbol: string,
  triggerPrice: Decimal,
  action: "repay" | "withdraw"
) {
  const orderIx = await createPriceBasedOrder(
    market,
    wallet.publicKey,
    new VanillaObligation(PROGRAM_ID),
    {
      type: PriceOrderType.STOP_LOSS,
      tokenSymbol,
      triggerPrice: triggerPrice.toString(),
      action,
    }
  );

  const tx = new Transaction().add(orderIx);
  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

Kamino Liquidity (kliquidity-sdk)

Gestion de liquidité automatisée pour les positions de liquidité concentrée sur Orca, Raydium et Meteora.

Initialiser le SDK

import { Kamino } from "@kamino-finance/kliquidity-sdk";
import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection(clusterApiUrl("mainnet-beta"));
const kamino = new Kamino("mainnet-beta", connection);

Récupérer les stratégies

// Obtenir toutes les stratégies
const strategies = await kamino.getStrategies();

// Obtenir la stratégie par adresse
const strategy = await kamino.getStrategyByAddress(
  new PublicKey("strategy_address")
);

// Obtenir la stratégie par kToken mint
const strategyByMint = await kamino.getStrategyByKTokenMint(
  new PublicKey("ktoken_mint")
);

// Obtenir les stratégies avec filtres
const filteredStrategies = await kamino.getAllStrategiesWithFilters({
  strategyType: "NON_PEGGED",   // NON_PEGGED, PEGGED, STABLE
  status: "LIVE",               // LIVE, STAGING, DEPRECATED
  tokenA: new PublicKey("..."), // Filtrer par token A
  tokenB: new PublicKey("..."), // Filtrer par token B
});

Types de stratégie

Type Description Paires d'exemple
NON_PEGGED Actifs non corrélés SOL-BONK, SOL-USDC
PEGGED Faiblement corrélés BSOL-JitoSOL, mSOL-SOL
STABLE Prix stable USDC-USDT, USDH-USDC

Obtenir les données de stratégie

// Obtenir le prix de la part
const sharePrice = await kamino.getStrategySharePrice(strategy);
console.log("Prix de la part:", sharePrice.toString());

// Obtenir les données de la part
const shareData = await kamino.getStrategyShareData(strategy);
console.log("Parts totales:", shareData.totalShares);
console.log("Token A par part:", shareData.tokenAPerShare);
console.log("Token B par part:", shareData.tokenBPerShare);

// Obtenir les montants de token par part
const tokenAmounts = await kamino.getTokenAAndBPerShare(strategy);
console.log("Token A:", tokenAmounts.tokenA);
console.log("Token B:", tokenAmounts.tokenB);

// Obtenir la plage de prix de la stratégie
const range = await kamino.getStrategyRange(strategy);
console.log("Prix inférieur:", range.lowerPrice);
console.log("Prix supérieur:", range.upperPrice);
console.log("Prix actuel:", range.currentPrice);

Déposer dans une stratégie

import Decimal from "decimal.js";

async function depositToStrategy(
  kamino: Kamino,
  wallet: Keypair,
  strategyAddress: PublicKey,
  tokenAAmount: Decimal,
  tokenBAmount: Decimal,
  slippage: Decimal  // p. ex. new Decimal(0.01) pour 1 %
) {
  const strategy = await kamino.getStrategyByAddress(strategyAddress);

  // Construire les instructions de dépôt
  const depositIxs = await kamino.deposit(
    strategy,
    wallet.publicKey,
    tokenAAmount,
    tokenBAmount,
    slippage
  );

  // Créer la transaction avec un budget de calcul supplémentaire
  const tx = kamino.createTransactionWithExtraBudget();
  tx.add(...depositIxs);

  await kamino.assignBlockInfoToTransaction(tx);

  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

Dépôt avec un seul token

async function singleTokenDeposit(
  kamino: Kamino,
  wallet: Keypair,
  strategyAddress: PublicKey,
  tokenAmount: Decimal,
  isTokenA: boolean,  // true pour Token A, false pour Token B
  slippage: Decimal
) {
  const strategy = await kamino.getStrategyByAddress(strategyAddress);

  const depositIxs = await kamino.singleTokenDeposit(
    strategy,
    wallet.publicKey,
    tokenAmount,
    isTokenA,
    slippage
  );

  const tx = kamino.createTransactionWithExtraBudget();
  tx.add(...depositIxs);

  await kamino.assignBlockInfoToTransaction(tx);

  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

Retirer d'une stratégie

async function withdrawFromStrategy(
  kamino: Kamino,
  wallet: Keypair,
  strategyAddress: PublicKey,
  shareAmount: Decimal,  // Nombre de parts à retirer
  slippage: Decimal
) {
  const strategy = await kamino.getStrategyByAddress(strategyAddress);

  const withdrawIxs = await kamino.withdraw(
    strategy,
    wallet.publicKey,
    shareAmount,
    slippage
  );

  const tx = kamino.createTransactionWithExtraBudget();
  tx.add(...withdrawIxs);

  await kamino.assignBlockInfoToTransaction(tx);

  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

// Retirer toutes les parts
async function withdrawAllShares(
  kamino: Kamino,
  wallet: Keypair,
  strategyAddress: PublicKey,
  slippage: Decimal
) {
  const strategy = await kamino.getStrategyByAddress(strategyAddress);

  const withdrawIxs = await kamino.withdrawAllShares(
    strategy,
    wallet.publicKey,
    slippage
  );

  const tx = kamino.createTransactionWithExtraBudget();
  tx.add(...withdrawIxs);

  await kamino.assignBlockInfoToTransaction(tx);

  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

Collecter les frais et les récompenses

async function collectFeesAndRewards(
  kamino: Kamino,
  wallet: Keypair,
  strategyAddress: PublicKey
) {
  const strategy = await kamino.getStrategyByAddress(strategyAddress);

  const collectIxs = await kamino.collectFeesAndRewards(
    strategy,
    wallet.publicKey
  );

  const tx = kamino.createTransactionWithExtraBudget();
  tx.add(...collectIxs);

  await kamino.assignBlockInfoToTransaction(tx);

  return await sendAndConfirmTransaction(connection, tx, [wallet]);
}

Obtenir les informations de pool

// Obtenir les DEX supportés
const dexes = kamino.getSupportedDexes();
// Retourne : ["ORCA", "RAYDIUM", "METEORA"]

// Obtenir les échelons de frais pour DEX
const feeTiers = kamino.getFeeTiersForDex("ORCA");

// Obtenir les pools pour une paire de tokens
const orcaPools = await kamino.getOrcaPoolsForTokens(tokenAMint, tokenBMint);
const raydiumPools = await kamino.getRaydiumPoolsForTokens(tokenAMint, tokenBMint);
const meteoraPools = await kamino.getMeteoraPoolsForTokens(tokenAMint, tokenBMint);

// Obtenir le prix actuel pour une paire
const price = await kamino.getPriceForPair("ORCA", tokenAMint, tokenBMint);

Méthodes de rééquilibrage

// Obtenir les méthodes de rééquilibrage disponibles
const methods = kamino.getRebalanceMethods();
// Retourne : ["MANUAL", "DRIFT", "TAKE_PROFIT", "PERIODIC", "PRICE_PERCENTAGE", ...]

// Obtenir les méthodes activées
const enabledMethods = kamino.getEnabledRebalanceMethods();

// Obtenir la méthode par défaut
const defaultMethod = kamino.getDefaultRebalanceMethod();

// Lire les paramètres de rééquilibrage pour la stratégie
const driftParams = await kamino.readDriftRebalanceParams(strategy);
const periodicParams = await kamino.readPeriodicRebalanceParams(strategy);
const priceParams = await kamino.readPricePercentageParams(strategy);

Créer une nouvelle stratégie

async function createStrategy(
  kamino: Kamino,
  admin: Keypair,
  params: {
    dex: "ORCA" | "RAYDIUM" | "METEORA";
    tokenAMint: PublicKey;
    tokenBMint: PublicKey;
    feeTierBps: Decimal;
    rebalanceMethod: string;
  }
) {
  const strategyKeypair = Keypair.generate();

  // Vérifier que les comptes de token existent
  const tokenAAccount = await kamino.getAssociatedTokenAddressAndData(
    params.tokenAMint,
    admin.publicKey
  );
  const tokenBAccount = await kamino.getAssociatedTokenAddressAndData(
    params.tokenBMint,
    admin.publicKey
  );

  // Créer le compte de stratégie
  const createAccountIx = await kamino.createStrategyAccount(
    strategyKeypair.publicKey
  );

  // Initialiser la stratégie
  const initIxs = await kamino.initializeStrategy(
    strategyKeypair.publicKey,
    admin.publicKey,
    params
  );

  const tx = kamino.createTransactionWithExtraBudget();
  tx.add(createAccountIx, ...initIxs);

  await kamino.assignBlockInfoToTransaction(tx);

  return await sendAndConfirmTransaction(
    connection,
    tx,
    [admin, strategyKeypair],
    { commitment: "finalized" }
  );
}

Scope Oracle (scope-sdk)

Agrégateur d'oracles de prix fournissant des données de tarification fiables.

Initialiser Scope

import { Scope } from "@kamino-finance/scope-sdk";
import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection(clusterApiUrl("mainnet-beta"));
const scope = new Scope("mainnet-beta", connection);

Obtenir les prix oracle

// Obtenir tous les prix oracle
const prices = await scope.getOraclePrices();

// Prix indexés par token
console.log("Prix SOL:", prices.get("SOL"));
console.log("Prix USDC:", prices.get("USDC"));

// Obtenir un prix spécifique
const solPrice = await scope.getPrice("SOL");
console.log("SOL/USD:", solPrice.price.toString());
console.log("Horodatage:", solPrice.timestamp);
console.log("Confiance:", solPrice.confidence);

Flux de prix

Scope agrège à partir de plusieurs sources d'oracle :

  • Pyth : Prix de marché en temps réel
  • Switchboard : Réseau d'oracle décentralisé
  • TWAP : Prix moyens pondérés dans le temps
  • CLMM Prices : Prix dérivés du DEX
// Obtenir le prix avec les informations de source
const priceData = await scope.getPriceWithMetadata("SOL");
console.log("Prix:", priceData.price);
console.log("Source:", priceData.source);
console.log("Âge (slots):", priceData.ageSlots);

Commandes CLI

CLI de prêt

# Déposer des tokens
yarn cli deposit --url <RPC> --owner ./keypair.json --token USDC --amount 100

# Afficher tous les comptes du marché de prêt
yarn cli print-all-lending-market-accounts --rpc <RPC>

# Afficher tous les comptes de réserve
yarn cli print-all-reserve-accounts --rpc <RPC>

# Afficher tous les comptes d'obligation
yarn cli print-all-obligation-accounts --rpc <RPC>

# Filtrer avec jq
yarn cli print-all-reserve-accounts --rpc <RPC> | jq '.lastUpdateSlot'
yarn cli print-all-obligation-accounts --rpc <RPC> | jq --stream 'select(.[0][1] == "owner")'

Adresses du programme

Mainnet

Programme Adresse
Kamino Lending KLend2g3cP87ber41qQDzWpAFuqP2tCxDqC8S3k7L1U
Marché principal 7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF
Kamino Liquidity KLIQ... (varie)
Scope Oracle ScopE... (varie)

Configuration de réserve

Chaque réserve a des paramètres configurables :

interface ReserveConfig {
  // Configuration des garanties
  loanToValueRatio: number;        // Puissance d'emprunt max (p. ex. 0,8 = 80 %)
  liquidationThreshold: number;     // Déclencheur de liquidation (p. ex. 0,85 = 85 %)
  liquidationBonus: number;         // Récompense du liquidateur (p. ex. 0,05 = 5 %)

  // Modèle de taux d'intérêt
  optimalUtilizationRate: number;   // Utilisation cible
  borrowRateCurve: {
    baseRate: number;
    optimalRate: number;
    maxRate: number;
  };

  // Frais
  protocolTakeRate: number;         // Frais du protocole sur les intérêts
  hostFeeRate: number;              // Frais d'intégration du host

  // Limites
  depositLimit: number;             // Dépôts max
  borrowLimit: number;              // Emprunts max

  // Statut
  depositEnabled: boolean;
  borrowEnabled: boolean;
  withdrawEnabled: boolean;
}

Gestion des erreurs

import { KaminoError, ErrorCode } from "@kamino-finance/klend-sdk";

try {
  await kaminoAction.execute();
} catch (error) {
  if (error instanceof KaminoError) {
    switch (error.code) {
      case ErrorCode.InsufficientCollateral:
        console.error("Pas assez de garantie pour cet emprunt");
        break;
      case ErrorCode.BorrowLimitExceeded:
        console.error("Limite d'emprunt atteinte pour cette réserve");
        break;
      case ErrorCode.LiquidationThresholdExceeded:
        console.error("La position est à risque de liquidation");
        break;
      case ErrorCode.InvalidObligation:
        console.error("Compte d'obligation introuvable ou invalide");
        break;
      default:
        console.error("Erreur Kamino:", error.message);
    }
  } else {
    throw error;
  }
}

Bonnes pratiques

Surveillance du facteur de santé

async function checkHealthFactor(
  market: KaminoMarket,
  wallet: PublicKey
): Promise<number> {
  await market.refreshAll();
  const obligation = await market.getUserVanillaObligation(wallet);

  if (!obligation) return Infinity;

  const stats = obligation.refreshedStats;
  const healthFactor = stats.borrowLimit / stats.borrowedValue;

  if (healthFactor < 1.1) {
    console.warn("AVERTISSEMENT : Facteur de santé inférieur à 1,1, envisagez d'ajouter des garanties");
  }

  return healthFactor;
}

Optimisation des transactions

// Utiliser les tables de recherche pour les transactions plus petites
const { instructions, lookupTables } = await kaminoAction.buildWithLookupTables();

// Créer une transaction versionnée
const messageV0 = new TransactionMessage({
  payerKey: wallet.publicKey,
  recentBlockhash: (await connection.getLatestBlockhash()).blockhash,
  instructions,
}).compileToV0Message(lookupTables);

const tx = new VersionedTransaction(messageV0);
tx.sign([wallet]);

await sendAndConfirmTransaction(connection, tx, [wallet]);

Protection contre le glissement

// Pour les opérations de liquidité, toujours utiliser la protection contre le glissement
const slippage = new Decimal(0.005); // Glissement max 0,5 %

const depositIxs = await kamino.deposit(
  strategy,
  wallet.publicKey,
  tokenAAmount,
  tokenBAmount,
  slippage  // Protège contre le mouvement de prix
);

Types TypeScript

import type {
  // Types de prêt
  KaminoMarket,
  KaminoAction,
  KaminoObligation,
  KaminoReserve,
  VanillaObligation,
  ReserveConfig,
  ObligationStats,

  // Types de liquidité
  Kamino,
  WhirlpoolStrategy,
  StrategyWithAddress,
  ShareData,
  PositionRange,
  RebalanceMethod,
  StrategiesFilters,

  // Types d'oracle
  Scope,
  OraclePrices,
  PriceData,
} from "@kamino-finance/klend-sdk";

Kamino 2.0 / K-Lend (Nouvelles fonctionnalités)

Mises à jour architecturales

Kamino 2.0 a introduit une application entièrement intégrée avec deux couches clés :

  • Couche du marché : Marchés de prêt de base avec paramètres de risque avancés
  • Couche du vault : Stratégies de vault gérées par des conservateurs pour un rendement optimisé

Nouveau support de garanties (2025)

Actif Type Notes
nxSOL LST Jeton de staking liquide Nansen
Huma RWA RWA Garantie adossée à des actifs réels
JitoSOL LST Jeton de staking liquide Jito

Fonctionnalités K-Lend V2 (Q4 2025)

  • Prêt modulaire : Marchés isolés pour les RWA et usage institutionnel
  • Moteur de risque amélioré : Paramètres de liquidation améliorés
  • Positions multi-garanties : Emprunter contre plusieurs actifs

Gouvernance (Q1 2026)

La prise de décision décentralisée via les détenteurs de tokens KMNO sera activée, permettant aux titulaires de tokens de voter sur :

  • Les paramètres de réserve
  • Les nouvelles listes de marché
  • Les frais du protocole

Jalons de sécurité

  • Quatrième vérification de protocole complétée (octobre 2025)
  • Programme de prime aux bugs de 1,5 M$ actif

Ressources

Structure de skill

kamino/
├── SKILL.md                        # Ce fichier
├── resources/
│   ├── klend-api-reference.md      # API de prêt complet
│   ├── kliquidity-api-reference.md # API de liquidité complet
│   ├── scope-api-reference.md      # Référence API Oracle
│   ├── reserve-configs.md          # Configurations de réserve
│   └── program-addresses.md        # Toutes les adresses du programme
├── examples/
│   ├── lending/
│   │   ├── deposit-withdraw.md     # Exemples de dépôt et retrait
│   │   ├── borrow-repay.md         # Exemples d'emprunt
│   │   ├── leverage.md             # Exemples Multiply/leverage
│   │   └── liquidation.md          # Exemple de bot de liquidation
│   ├── liquidity/
│   │   ├── strategy-management.md  # Opérations de stratégie
│   │   ├── deposits-withdrawals.md # Opérations LP
│   │   └── rebalancing.md          # Stratégies de rééquilibrage
│   └── oracle/
│       └── price-feeds.md          # Exemples d'utilisation d'oracle
├── templates/
│   ├── lending-setup.ts            # Initialisation de prêt
│   ├── liquidity-setup.ts          # Initialisation de liquidité
│   └── full-integration.ts         # Intégration complète
└── docs/
    ├── troubleshooting.md          # Problèmes courants
    └── advanced-patterns.md        # Modèles complexes

Vérifier

  • Un appel RPC/SDK réel a été émis (mainnet, devnet ou validateur local) et la charge utile de réponse est capturée dans la transcription, non simplement paraphrasée
  • Chaque transaction a été simulée (simulateTransaction ou équivalent) avant toute étape de signature/envoi ; les journaux de simulation sont joints
  • Pour toute transaction signée/envoyée, la signature résultante est enregistrée et confirmée en chaîne (statut retourné par getSignatureStatuses ou une URL d'explorateur)
  • Le glissement, les frais prioritaires et les limites d'unités de calcul ont été définis explicitement avec des valeurs numériques concrètes, non laissés aux valeurs par défaut de la bibliothèque
  • Les adresses de compte, les mints et les ID de programme utilisés dans l'exécution correspondent aux adresses de kamino-lending documentées pour le cluster cible (pas de mélange mainnet/devnet)
  • Le chemin d'échec a été exercé au moins une fois (solde insuffisant, oracle périmé, blockhash expiré, etc.) et la gestion des erreurs de l'agent a produit un message lisible

Skills similaires