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.
How Referral Codes Work
Kamino’s referral system allows referrers to earn commission from the borrowing activity of referred users. Each referrer creates a unique referral code that can be shared publicly without revealing a wallet address, providing a user-friendly way to distribute referral codes.
In the SDK, the shortUrl field represents the referral code.
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 {
getInitReferrerStateAndShortUrlIxs,
getReferrerForShortUrl,
PROGRAM_ID,
} from '@kamino-finance/klend-sdk';
import { parseKeypairFile } from '@kamino-finance/klend-sdk/dist/utils/signer.js';
Initialize RPC
Load the keypair and initialize RPC connections.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');
Create Referrer State with Short URL
Generate a unique short URL and create the referrer state initialization instruction.const shortUrl = `ref-${Date.now()}`;
const initReferrerIx = await getInitReferrerStateAndShortUrlIxs({
referrer: signer,
shortUrl,
programId: PROGRAM_ID,
});
The short URL must be unique, contain a maximum of 32 characters, and use only ASCII alphanumeric characters plus underscore and hyphen.
Send Referrer Setup Transaction
Build and send the transaction to initialize the referrer state on-chain.const { value: setupBlockhash } = await rpc
.getLatestBlockhash({ commitment: 'finalized' })
.send();
const setupTx = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(signer, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(setupBlockhash, tx),
(tx) => appendTransactionMessageInstructions([initReferrerIx], tx)
);
const setupSigned = await signTransactionMessageWithSigners(setupTx);
const setupSignature = getSignatureFromTransaction(setupSigned);
await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(setupSigned, {
commitment: 'confirmed',
skipPreflight: true,
});
console.log(`Referrer setup successful! Signature: ${setupSignature}`);
Verify Short URL Resolution
Confirm that the short URL correctly resolves to the referrer wallet address.const lookedUpReferrer = await getReferrerForShortUrl(rpc, shortUrl, PROGRAM_ID);
console.log(`Short URL "${shortUrl}" resolves to: ${lookedUpReferrer}`);
Referrer setup complete. The short URL is active and can be shared with users to establish referral relationships.
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::{
init_referrer_state_and_short_url,
InitReferrerStateAndShortUrlAccounts,
};
use klend_interface::pda;
use klend_interface::KLEND_PROGRAM_ID;
use solana_pubkey::Pubkey;
let referrer = signer.pubkey();
let short_url = format!("ref-{}", std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs());
// Derive required PDAs
let (referrer_state, _) = pda::referrer_state(&KLEND_PROGRAM_ID, &referrer);
let (referrer_short_url, _) = pda::referrer_short_url(&KLEND_PROGRAM_ID, &short_url);
let (referrer_user_metadata, _) = pda::user_metadata(&KLEND_PROGRAM_ID, &referrer);
let ix = init_referrer_state_and_short_url(
InitReferrerStateAndShortUrlAccounts {
referrer,
referrer_state,
referrer_short_url,
referrer_user_metadata,
},
short_url.clone(),
);
The short URL must be unique, contain a maximum of 32 characters, and use only ASCII alphanumeric characters plus underscore and hyphen.
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!("Referrer setup successful! Short URL: {short_url}");
println!("Signature: {signature}");