Skip to main content

Overview

Build lending applications on Solana using the Kamino SDK. This guide covers everything from basic setup to advanced transaction building for deposit, borrow, repay, and withdraw operations.

Key Components of Borrow Integration

Lending Operations

Deposit collateral, borrow assets, repay debt, and withdraw - complete lending lifecycle management.

Loan Management

LTV ratios, health factors, obligation status and position monitoring for safe lending.

Market Analytics

APY tracking, utilization rates, reserve metrics from API and on-chain data.

Ways to Fetch Data

Public API

Access market data, borrow rates, reserve liquidity, and obligation status.

SDK

Execute borrow operations: deposit collateral, borrow, repay, and withdraw.

Deposit

import { createSolanaRpc, address, createNoopSigner } from '@solana/kit';
import { KaminoMarket, KaminoAction, LendingObligation } from '@kamino-finance/klend-sdk';
import { simulateTx } from '../../utils/tx';
import BN from 'bn.js';

const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const marketPubkey = address('DxXdAyU3kCjnyggvHmY5nAwg5cRbbmdyX3npfDMjjMek');
const usdcMint = address('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');

const market = await KaminoMarket.load(rpc, marketPubkey, 100);
const user = address('EZC9wzVCvihCsCHEMGADYdsRhcpdRYWzSCZAVegSCfqY'); // user

// Create a LendingObligation for depositing to earn interest
const obligation = new LendingObligation(usdcMint, market!.programId, 0);

const action = await KaminoAction.buildDepositReserveLiquidityTxns(
  market!,
  new BN(1_000_000), // Deposit 1 USDC * 10^6 decimals
  usdcMint,
  createNoopSigner(user),
  obligation,
  undefined
);

const res = await simulateTx(rpc, user, [
  ...action.computeBudgetIxs,
  ...action.setupIxs,
  ...action.lendingIxs,
  ...action.cleanupIxs,
], []);

console.log('Simulation Result:', res);

View Code
For the full deposit example, including transaction sending and confirmation, check out Deposit Operations.

Withdraw

import { createSolanaRpc, address, createNoopSigner } from '@solana/kit';
import { KaminoMarket, KaminoAction, VanillaObligation, PROGRAM_ID } from '@kamino-finance/klend-sdk';
import { simulateTx } from '../../utils/tx';
import BN from 'bn.js';

const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const marketPubkey = address('DxXdAyU3kCjnyggvHmY5nAwg5cRbbmdyX3npfDMjjMek');
const usdcMint = address('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');

const market = await KaminoMarket.load(rpc, marketPubkey, 100);
const user = address('EZC9wzVCvihCsCHEMGADYdsRhcpdRYWzSCZAVegSCfqY');

// Fetch the existing obligation from the blockchain
const obligation = await market!.getObligationByWallet(
  user,
  new VanillaObligation(PROGRAM_ID)
);

if (!obligation) {
  throw new Error('No obligation found for this wallet. You must deposit first.');
}

const action = await KaminoAction.buildWithdrawTxns(
  market!,
  new BN(1_000_000), // Withdraw 1 USDC * 10^6 decimals
  usdcMint,
  createNoopSigner(user),
  obligation,
  true, // useV2Ixs
  undefined // scopeRefreshConfig
);

const res = await simulateTx(rpc, user, [
  ...action.computeBudgetIxs,
  ...action.setupIxs,
  ...action.lendingIxs,
  ...action.cleanupIxs,
], []);

console.log('Simulation Result:', res);
View Code
For the full withdraw example, including transaction sending and confirmation, check out Withdraw Operations.

Key Data Structures

Obligation
class Obligation {
	tag: BN;
	lastUpdate: types.LastUpdate;
	lendingMarket: Address;
	owner: Address;
	deposits: Array<types.ObligationCollateral>;
	lowestReserveDepositLiquidationLtv: BN;
	depositedValueSf: BN;
	borrows: Array<types.ObligationLiquidity>;
	borrowFactorAdjustedDebtValueSf: BN;
	borrowedAssetsMarketValueSf: BN;
	allowedBorrowValueSf: BN;
	unhealthyBorrowValueSf: BN;
	depositsAssetTiers: Array<number>;
	borrowsAssetTiers: Array<number>;
	elevationGroup: number;
	numOfObsoleteDepositReserves: number;
	hasDebt: number;
	referrer: Address;
	borrowingDisabled: number;
	autodeleverageTargetLtvPct: number;
	lowestReserveDepositMaxLtvPct: number;
	numOfObsoleteBorrowReserves: number;
	reserved: Array<number>;
	highestBorrowFactorPct: BN;
	autodeleverageMarginCallStartedTimestamp: BN;
	orders: Array<types.ObligationOrder>;
}
View Full Typescript Obligation