Documentation Index
Fetch the complete documentation index at: https://kamino.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Manage User Obligations
Manage and retrieve user obligations, positions, and transaction history using the Kamino SDK and API.Historical obligation data is only available via the API.
Get User Obligation Info
Retrieve detailed obligation information including deposits, borrows, and health metrics.- TypeScript
- Rust
getUserObligation.ts
import { createSolanaRpc, address } from '@solana/kit';
import { KaminoMarket, VanillaObligation, PROGRAM_ID } from '@kamino-finance/klend-sdk';
const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const marketPubkey = address('7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF');
const userAddress = address('EZC9wzVCvihCsCHEMGADYdsRhcpdRYWzSCZAVegSCfqY');
const market = await KaminoMarket.load(rpc, marketPubkey, 400, PROGRAM_ID);
const kaminoObligation = await market!.getObligationByWallet(
userAddress,
new VanillaObligation(PROGRAM_ID)
);
if (!kaminoObligation) {
console.log('No obligation found for user:', userAddress);
} else {
console.log('Obligation Info:');
console.log('Owner:', kaminoObligation.state.owner.toString());
console.log('\nDeposits (Collateral):');
const deposits = [...kaminoObligation.deposits.values()];
deposits.forEach((deposit) => {
console.log(`Reserve:`, deposit.reserveAddress.toString());
console.log(` Amount:`, deposit.amount);
console.log(` Market Value:`, deposit.marketValueRefreshed);
});
console.log('\nBorrows:');
const borrows = [...kaminoObligation.borrows.values()];
borrows.forEach((borrow) => {
console.log(`Reserve:`, borrow.reserveAddress.toString());
console.log(` Amount:`, borrow.amount);
});
console.log('\nMetrics:');
console.log('Loan-to-Value:', kaminoObligation.loanToValue());
console.log('Borrow Utilization:', kaminoObligation.refreshedStats.borrowUtilization);
console.log('Number of Positions:', kaminoObligation.getNumberOfPositions());
}
get_user_obligation.rs
// Additional deps: klend-interface = "0.1.0", solana-client = "~2.3",
// solana-pubkey = "2.1", fixed = "1"
use klend_interface::accounts::from_account_data;
use klend_interface::state::Obligation;
use klend_interface::pda;
use klend_interface::KLEND_PROGRAM_ID;
use solana_client::rpc_client::RpcClient;
use solana_pubkey::Pubkey;
use fixed::types::U68F60;
use std::str::FromStr;
let rpc_client = RpcClient::new("https://api.mainnet-beta.solana.com");
let market_pubkey = Pubkey::from_str("7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF").unwrap();
let user_pubkey = Pubkey::from_str("EZC9wzVCvihCsCHEMGADYdsRhcpdRYWzSCZAVegSCfqY").unwrap();
// Derive the obligation PDA (tag 0 = Vanilla obligation)
let (obligation_pubkey, _bump) = pda::obligation(
&KLEND_PROGRAM_ID,
0,
0,
&user_pubkey,
&market_pubkey,
&Pubkey::default(),
&Pubkey::default(),
);
// Fetch and parse the obligation account
let obligation_account = rpc_client.get_account(&obligation_pubkey)?;
let obligation = from_account_data::<Obligation>(&obligation_account.data)?;
println!("Obligation owner: {}", obligation.owner);
// Active deposits
println!("\nDeposits (Collateral):");
for deposit in &obligation.deposits {
if deposit.deposit_reserve == Pubkey::default() {
continue;
}
println!(" Reserve: {}", deposit.deposit_reserve);
println!(" Deposited amount (cTokens): {}", deposit.deposited_amount);
}
// Active borrows
println!("\nBorrows:");
for borrow in &obligation.borrows {
if borrow.borrow_reserve == Pubkey::default() {
continue;
}
println!(" Reserve: {}", borrow.borrow_reserve);
println!(" Borrowed amount (sf): {}", borrow.borrowed_amount_sf);
}
// Health metrics — `_sf` fields use the `fixed` crate for precise conversion
let deposited_value = U68F60::from_bits(obligation.deposited_value_sf as u128);
let allowed_borrow = U68F60::from_bits(obligation.allowed_borrow_value_sf as u128);
let unhealthy_borrow = U68F60::from_bits(obligation.unhealthy_borrow_value_sf as u128);
let borrowed_value = U68F60::from_bits(obligation.borrow_factor_adjusted_debt_value_sf as u128);
println!("\nMetrics:");
println!(" Deposited value: ${deposited_value}");
println!(" Allowed borrow value: ${allowed_borrow}");
println!(" Unhealthy borrow value: ${unhealthy_borrow}");
println!(" Current borrow value: ${borrowed_value}");
println!(" Liquidatable: {}", borrowed_value > unhealthy_borrow);
println!(" Borrowing disabled: {}", obligation.borrowing_disabled > 0);
Get All User Obligations
Retrieve all obligations for a user wallet, including different obligation types across the market.- TypeScript
getAllUserObligations.ts
import { createSolanaRpc, address } from '@solana/kit';
import { KaminoMarket, PROGRAM_ID, ObligationTypeTag } from '@kamino-finance/klend-sdk';
const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const marketPubkey = address('7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF');
const userWallet = address('Hs9ioQZ2pCUyvS18anwmBxjQJsZrMPShwTMLySD6Us3V');
const market = await KaminoMarket.load(rpc, marketPubkey, 400, PROGRAM_ID);
const obligations = await market.getAllUserObligations(userWallet);
if (obligations.length === 0) {
console.log('No obligations found for wallet:', userWallet);
} else {
console.log(`Found ${obligations.length} obligation(s):\n`);
obligations.forEach((obligation, i) => {
console.log(`Obligation ${i + 1}:`);
console.log('Address:', obligation.obligationAddress.toString());
console.log('Type:', ObligationTypeTag[obligation.obligationTag]);
console.log('Owner:', obligation.state.owner.toString());
console.log('\nDeposits (Collateral):');
const deposits = [...obligation.deposits.values()];
deposits.forEach((deposit) => {
console.log(` Reserve:`, deposit.reserveAddress.toString());
console.log(` Amount:`, deposit.amount);
console.log(` Market Value:`, deposit.marketValueRefreshed);
});
console.log('\nBorrows:');
const borrows = [...obligation.borrows.values()];
borrows.forEach((borrow) => {
console.log(` Reserve:`, borrow.reserveAddress.toString());
console.log(` Amount:`, borrow.amount);
console.log(` Market Value:`, borrow.marketValueRefreshed);
});
console.log('\nMetrics:');
console.log('Loan-to-Value:', obligation.loanToValue());
console.log('Borrow Utilization:', obligation.refreshedStats.borrowUtilization);
console.log('Number of Positions:', obligation.getNumberOfPositions());
});
}
Get All Obligations by Reserve
Retrieve all obligations that have deposits in a specific reserve. Useful for analyzing reserve utilization and user exposure.- TypeScript
getAllObligationsByReserve.ts
import { createSolanaRpc, address } from '@solana/kit';
import { KaminoMarket, PROGRAM_ID, ObligationTypeTag } from '@kamino-finance/klend-sdk';
// Note: This example requires a paid/dedicated RPC node. Public RPCs will hit rate limits.
const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const marketPubkey = address('7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF');
const reserveAddress = address('37Jk2zkz23vkAYBT66HM2gaqJuNg2nYLsCreQAVt5MWK');
const market = await KaminoMarket.load(rpc, marketPubkey, 400, PROGRAM_ID);
const obligations = await market.getAllObligationsByDepositedReserve(reserveAddress);
if (obligations.length === 0) {
console.log('No obligations found with deposits in reserve:', reserveAddress);
} else {
console.log(`Found ${obligations.length} obligation(s) with deposits in this reserve:\n`);
obligations.forEach((obligation, i) => {
console.log(`Obligation ${i + 1}:`);
console.log('Address:', obligation.obligationAddress.toString());
console.log('Type:', ObligationTypeTag[obligation.obligationTag]);
console.log('Owner:', obligation.state.owner.toString());
const reserveDeposit = [...obligation.deposits.values()].find(
(deposit) => deposit.reserveAddress.toString() === reserveAddress.toString()
);
if (reserveDeposit) {
console.log('\nDeposit in this Reserve:');
console.log(' Amount:', reserveDeposit.amount);
console.log(' Market Value:', reserveDeposit.marketValueRefreshed);
}
const otherDeposits = [...obligation.deposits.values()].filter(
(deposit) => deposit.reserveAddress.toString() !== reserveAddress.toString()
);
if (otherDeposits.length > 0) {
console.log('\nOther Deposits:');
otherDeposits.forEach((deposit) => {
console.log(' Reserve:', deposit.reserveAddress.toString());
console.log(' Market Value:', deposit.marketValueRefreshed);
});
}
const borrows = [...obligation.borrows.values()];
if (borrows.length > 0) {
console.log('\nBorrows:');
borrows.forEach((borrow) => {
console.log(' Reserve:', borrow.reserveAddress.toString());
console.log(' Market Value:', borrow.marketValueRefreshed);
});
}
console.log('\nMetrics:');
console.log('Loan-to-Value:', obligation.loanToValue());
console.log('Number of Positions:', obligation.getNumberOfPositions());
console.log();
});
}
Get User Transaction History
Access all transaction history for a user’s wallet across deposits, borrows, repayments, and liquidations.- TypeScript
getTransactionHistory.ts
const marketPubkey = 'DxXdAyU3kCjnyggvHmY5nAwg5cRbbmdyX3npfDMjjMek';
const userPubkey = 'EZC9wzVCvihCsCHEMGADYdsRhcpdRYWzSCZAVegSCfqY';
const API_BASE_URL = 'https://api.kamino.finance';
const url = `${API_BASE_URL}/v2/kamino-market/${marketPubkey}/users/${userPubkey}/transactions`;
const res = await fetch(url);
if (!res.ok) {
throw new Error(`Request failed: ${res.status} ${res.statusText}`);
}
const data = await res.json();
console.log(data);