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
- Site web Kamino Finance
- Documentation Kamino
- klend-sdk GitHub
- kliquidity-sdk GitHub
- scope-sdk GitHub
- farms-sdk GitHub
- Discord Kamino
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 (
simulateTransactionou é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
getSignatureStatusesou 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