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.
Return borrowed assets to reduce or close positions. The SDK handles transaction building, instruction creation for debt repayment.
Repay
Return borrowed assets into the reserve.
Import Dependencies Import the required packages for Solana RPC communication, Kamino SDK operations, and Kit transaction building. import "dotenv/config" ;
import {
createSolanaRpc ,
createSolanaRpcSubscriptions ,
address ,
pipe ,
createTransactionMessage ,
setTransactionMessageFeePayerSigner ,
setTransactionMessageLifetimeUsingBlockhash ,
appendTransactionMessageInstructions ,
signTransactionMessageWithSigners ,
sendAndConfirmTransactionFactory ,
getSignatureFromTransaction ,
} from "@solana/kit" ;
import {
KaminoMarket ,
KaminoAction ,
VanillaObligation ,
PROGRAM_ID ,
} from "@kamino-finance/klend-sdk" ;
import BN from "bn.js" ;
import { getKeypair } from "../../utils/keypair" ;
@solana/kit provides modern utilities for RPC, transaction building, and
signing. @kamino-finance/klend-sdk contains market operation methods.
Initialize RPC and Load Market Initialize the RPC connection and load the Kamino market instance. const signer = await getKeypair ();
const rpc = createSolanaRpc ( "https://api.mainnet-beta.solana.com" );
const rpcSubscriptions = createSolanaRpcSubscriptions ( "wss://api.mainnet-beta.solana.com" );
const marketPubkey = address ( "7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF" );
const market = await KaminoMarket . load ( rpc , marketPubkey , 400 );
KaminoMarket.load() fetches the current market state including all reserve
data and configuration.
Fetch Obligation and Build Repay Instructions Fetch the existing obligation and generate repay instructions for the specified token and amount. const usdtMint = address ( "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB" );
const repayAmount = new BN ( 1_000_000 ); // 1.00 USDT (6 decimals)
const currentSlot = await rpc . getSlot (). send ();
// Fetch the existing obligation from the blockchain
const obligation = await market ! . getObligationByWallet (
address ( signer . address ),
new VanillaObligation ( PROGRAM_ID )
);
if ( ! obligation ) {
throw new Error (
"No obligation found for this wallet. You must have an active borrow to repay."
);
}
const repayAction = await KaminoAction . buildRepayTxns (
market ! ,
repayAmount ,
usdtMint ,
signer ,
new VanillaObligation ( PROGRAM_ID ),
true , // useV2Ixs
undefined , // scopeRefreshConfig
currentSlot , // currentSlot
signer , // payer
1_000_000 , // extraComputeBudget
true , // includeAtaIxs
false // requestElevationGroup
);
Build and Sign Transaction Combine all instructions and build the transaction using Kit’s functional pipe pattern. // Combine all instructions
const allInstructions = [
... ( repayAction . setupIxs || []),
... ( repayAction . lendingIxs || []),
... ( repayAction . cleanupIxs || []),
];
// Get fresh blockhash
const { value : latestBlockhash } = await rpc
. getLatestBlockhash ({
commitment: "finalized" ,
})
. send ();
// Build transaction using functional pipe pattern
const transactionMessage = pipe (
createTransactionMessage ({ version: 0 }),
( tx ) => setTransactionMessageFeePayerSigner ( signer , tx ),
( tx ) => setTransactionMessageLifetimeUsingBlockhash ( latestBlockhash , tx ),
( tx ) => appendTransactionMessageInstructions ( allInstructions , tx )
);
// Sign transaction
const signedTransaction = await signTransactionMessageWithSigners (
transactionMessage
);
All setup, lending, and cleanup instructions are combined in a single
transaction for repayment.
Send and Confirm Transaction Send the transaction and confirm it using WebSocket. // Send and confirm transaction
const signature = getSignatureFromTransaction ( signedTransaction );
await sendAndConfirmTransactionFactory ({ rpc , rpcSubscriptions })( signedTransaction , {
commitment: "confirmed" ,
skipPreflight: true ,
});
console . log ( "Repay successful! Signature:" , signature );
Repaying reduces your debt and improves your loan-to-value (LTV) ratio, making
your position healthier and reducing liquidation risk.
klend-interface is a lightweight Rust instruction builder — it creates Vec<Instruction> with required refresh instructions prepended automatically. Use ReserveInfo::from_account_data(pubkey, &data) to construct reserve info from raw RPC account bytes. For obligation-based operations, ObligationContext is the recommended approach — it fetches the obligation and its associated reserves, then provides convenient .deposit(), .borrow(), .repay(), and .withdraw() methods.
Add Dependencies [ dependencies ]
klend-interface = "0.1.0"
solana-pubkey = "2.1"
solana-instruction = "2.1"
solana-sdk = "~2.3"
solana-client = "~2.3"
spl-token = "7"
spl-associated-token-account = "6"
Set Up RPC Client use solana_client :: rpc_client :: RpcClient ;
use solana_sdk :: signer :: keypair :: read_keypair_file;
use solana_sdk :: signer :: Signer ;
let rpc_client = RpcClient :: new ( "https://api.mainnet-beta.solana.com" );
let signer = read_keypair_file ( "/path/to/your/keypair.json" )
. expect ( "Failed to read keypair file" );
let owner = signer . pubkey ();
Build Obligation Context use klend_interface :: ObligationContext ;
use klend_interface :: pda;
use klend_interface :: KLEND_PROGRAM_ID ;
use solana_pubkey :: Pubkey ;
use std :: str :: FromStr ;
let lending_market = Pubkey :: from_str ( "7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF" ) . unwrap ();
let repay_reserve_pubkey = Pubkey :: from_str ( "FBSyPnxtHKLBZ4UeeUyAnbtFuAmTHLtso9YtsqRDRWpM" ) . unwrap ();
// Derive the obligation PDA
let ( obligation_pubkey , _ ) = pda :: obligation (
& KLEND_PROGRAM_ID , 0 , 0 , & owner , & lending_market ,
& Pubkey :: default (), & Pubkey :: default (),
);
// Fetch the obligation account
let obligation_data = rpc_client . get_account ( & obligation_pubkey ) ? ;
// Discover which reserves the obligation references
let reserve_addrs = ObligationContext :: reserve_addresses_for_obligation ( & obligation_data . data) ? ;
// Fetch all reserve accounts in one RPC call
let reserve_accounts = rpc_client . get_multiple_accounts ( & reserve_addrs ) ? ;
// Build the context
let reserves : Vec <( Pubkey , & [ u8 ])> = reserve_addrs . iter ()
. zip ( reserve_accounts . iter ())
. filter_map ( | ( addr , acc ) | acc . as_ref () . map ( | a | ( * addr , a . data . as_slice ())))
. collect ();
let ctx = ObligationContext :: from_account_data (
obligation_pubkey , & obligation_data . data, & reserves
) ? ;
Derive Token Accounts use spl_associated_token_account :: get_associated_token_address;
// User's ATA for the repay token (e.g. USDT)
let repay_liquidity_mint = Pubkey :: from_str ( "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB" ) . unwrap ();
let user_source_liquidity = get_associated_token_address ( & owner , & repay_liquidity_mint );
Build Instructions let instructions = ctx . repay (
owner ,
& repay_reserve_pubkey ,
user_source_liquidity ,
1_000_000 , // 1 USDT (6 decimals)
) ? ;
// Returns: [refresh_reserves..., refresh_obligation, repay_obligation_liquidity_v2]
Build and Send Transaction use solana_sdk :: transaction :: Transaction ;
use solana_sdk :: message :: Message ;
let message = Message :: new ( & instructions , Some ( & owner ));
let recent_blockhash = rpc_client . get_latest_blockhash () ? ;
let tx = Transaction :: new ( & [ & signer ], message , recent_blockhash );
let signature = rpc_client . send_and_confirm_transaction ( & tx ) ? ;
println! ( "Repay successful! Signature: {signature}" );
Repaying reduces your debt and improves your loan-to-value (LTV) ratio, making your position healthier and reducing liquidation risk.
View Code
What Happens When You Repay?
Assets are transferred from your wallet to the reserve pool
Your borrow amount decreases in your obligation
You stop paying interest on the repaid amount
Your loan-to-value (LTV) ratio decreases (healthier position)
Your available borrowing capacity increases
Repay some of your debt to improve your LTV:
Repaying entire borrowed amount + accrued interest eliminates debt
Full repayment allows you to withdraw all collateral
You must repay the principal + accrued interest
Interest accrues continuously