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.
Withdraw Referrer Fees
- TypeScript
- Rust
Import Dependencies
Import the required packages for Solana RPC communication, Kamino SDK operations, and Kit transaction building.import {
createSolanaRpc,
createSolanaRpcSubscriptions,
address,
pipe,
createTransactionMessage,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstructions,
signTransactionMessageWithSigners,
sendAndConfirmTransactionFactory,
getSignatureFromTransaction,
} from '@solana/kit';
import { KaminoMarket, KaminoAction, parseKeypairFile } from '@kamino-finance/klend-sdk';
Load Market and Initialize RPC
Load the keypair, initialize RPC connections, and load the Kamino market.const KEYPAIR_FILE = '/path/to/your/keypair.json';
const signer = await parseKeypairFile(KEYPAIR_FILE);
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);
const usdcMint = address('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
Check Accumulated Fees
Check all accumulated fees across all tokens.const allFees = await market!.getAllReferrerFeesCumulative(signer.address);
for (const [mint, fees] of allFees.entries()) {
console.log(`Token ${mint}: ${fees.toString()}`);
}
const usdcReserve = market!.getReserveByMint(usdcMint);
if (usdcReserve) {
const cumulativeFees = await market!.getReferrerFeesCumulativeForReserve(signer.address, usdcReserve);
const unclaimedFees = await market!.getReferrerFeesUnclaimedForReserve(signer.address, usdcReserve);
console.log(`USDC Cumulative: ${cumulativeFees.toString()}`);
console.log(`USDC Unclaimed: ${unclaimedFees.toString()}`);
}
Build Withdraw Instructions
Generate instructions to withdraw accumulated referral fees for USDC.const withdrawAction = await KaminoAction.buildWithdrawReferrerFeeTxns(signer, usdcMint, market!);
const instructions = [...withdrawAction.setupIxs, ...withdrawAction.lendingIxs, ...withdrawAction.cleanupIxs];
Send Withdraw Transaction
Fetch the latest blockhash and build the transaction message.const { value: withdrawBlockhash } = await rpc.getLatestBlockhash({ commitment: 'finalized' }).send();
const withdrawTx = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(signer, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(withdrawBlockhash, tx),
(tx) => appendTransactionMessageInstructions(instructions, tx)
);
const withdrawSigned = await signTransactionMessageWithSigners(withdrawTx);
const withdrawSignature = getSignatureFromTransaction(withdrawSigned);
await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(withdrawSigned, {
commitment: 'confirmed',
skipPreflight: true,
});
console.log(`Withdraw fees successful! Signature: ${withdrawSignature}`);
Fee withdrawal complete. The accumulated referral fees have been transferred to the referrer wallet.
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();
Derive PDAs and Build Instruction
use klend_interface::instructions::referrer::{
withdraw_referrer_fees,
WithdrawReferrerFeesAccounts,
};
use klend_interface::pda::{self, ReservePdas};
use klend_interface::KLEND_PROGRAM_ID;
use solana_pubkey::Pubkey;
use std::str::FromStr;
use spl_associated_token_account::get_associated_token_address;
let referrer = signer.pubkey();
let lending_market = Pubkey::from_str("7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF").unwrap();
let reserve_pubkey = Pubkey::from_str("D6q6wuQSrifJKZYpR1M8R4YawnLDtDsMmWM1NbBmgJ59").unwrap();
let reserve_liquidity_mint = Pubkey::from_str("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v").unwrap();
// Derive PDAs
let (referrer_token_state, _) = pda::referrer_token_state(
&KLEND_PROGRAM_ID, &referrer, &reserve_pubkey
);
let (lending_market_authority, _) = pda::lending_market_authority(
&KLEND_PROGRAM_ID, &lending_market
);
let reserve_pdas = ReservePdas::derive(&KLEND_PROGRAM_ID, &reserve_pubkey);
// Derive referrer's ATA for the reserve liquidity mint
let referrer_token_account = get_associated_token_address(&referrer, &reserve_liquidity_mint);
let ix = withdraw_referrer_fees(WithdrawReferrerFeesAccounts {
referrer,
referrer_token_state,
reserve: reserve_pubkey,
reserve_liquidity_mint,
reserve_supply_liquidity: reserve_pdas.liquidity_supply_vault,
referrer_token_account,
lending_market,
lending_market_authority,
token_program: spl_token::ID,
});
Send Transaction
use solana_sdk::transaction::Transaction;
use solana_sdk::message::Message;
let message = Message::new(&[ix], Some(&referrer));
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!("Withdraw fees successful! Signature: {signature}");