Skip to main content
Mint cTokens (collateral tokens) by depositing assets into Kamino lending reserves. cTokens represent your deposit and accrue interest over time, which can be redeemed later for the underlying asset plus earned interest.

Minting cTokens

Deposit reserve liquidity to receive cTokens in your wallet.
1

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,
  type Signature,
} from '@solana/kit';
import { KaminoMarket, KaminoAction, VanillaObligation, PROGRAM_ID, parseKeypairFile } from '@kamino-finance/klend-sdk';
import BN from 'bn.js';
2

Load Signer and Initialize Market

Load your keypair from a file and initialize RPC connections and 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('DxXdAyU3kCjnyggvHmY5nAwg5cRbbmdyX3npfDMjjMek');
const market = await KaminoMarket.load(rpc, marketPubkey, 100);
Replace /path/to/your/keypair.json with the actual path to your keypair file. The KaminoMarket.load() method fetches the current market state including all reserve data.
3

Build Deposit Reserve Liquidity Instructions

Generate instructions to deposit USDC and receive cTokens (kV-STKUSDC) in your wallet.
const usdcMint = address('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
const depositAmount = new BN(1_000_000); // 1 USDC (6 decimals)

const action = await KaminoAction.buildDepositReserveLiquidityTxns(
  market!,
  depositAmount,
  usdcMint,
  signer,
  new VanillaObligation(PROGRAM_ID),
  undefined
);
The buildDepositReserveLiquidityTxns method creates instructions to deposit liquidity into the reserve. This will mint cTokens (e.g., kV-STKUSDC) to your wallet representing your deposit plus accrued interest.
4

Send Setup Transaction (If Needed)

If setup instructions are present, send the setup transaction first and wait for confirmation.
let setupSignature: Signature | undefined;

if (action.setupIxs && action.setupIxs.length > 0) {
  const { value: setupBlockhash } = await rpc.getLatestBlockhash({ commitment: 'finalized' }).send();
  const setupTxMessage = pipe(
    createTransactionMessage({ version: 0 }),
    (tx) => setTransactionMessageFeePayerSigner(signer, tx),
    (tx) => setTransactionMessageLifetimeUsingBlockhash(setupBlockhash, tx),
    (tx) => appendTransactionMessageInstructions(action.setupIxs, tx)
  );

  const setupSignedTx = await signTransactionMessageWithSigners(setupTxMessage);
  setupSignature = getSignatureFromTransaction(setupSignedTx);

  await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(setupSignedTx, {
    commitment: 'confirmed',
    skipPreflight: true,
  });

  // Wait for accounts to settle and LUT activation
  await new Promise((resolve) => setTimeout(resolve, 2000));
}
Setup transactions must be confirmed and Address Lookup Tables (ALTs) must be activated before sending the main deposit transaction. Waiting 2 seconds ensures account settlement.
5

Build and Sign Deposit Transaction

Build and sign the main deposit transaction with a fresh blockhash.
const lendingInstructions = [...action.computeBudgetIxs, ...action.lendingIxs, ...action.cleanupIxs];

if (!lendingInstructions.length) {
  throw new Error('No instructions returned by Kamino SDK');
}

const { value: latestBlockhash } = await rpc.getLatestBlockhash({ commitment: 'finalized' }).send();

const transactionMessage = pipe(
  createTransactionMessage({ version: 0 }),
  (tx) => setTransactionMessageFeePayerSigner(signer, tx),
  (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
  (tx) => appendTransactionMessageInstructions(lendingInstructions, tx)
);

const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
A fresh blockhash is fetched for the main transaction to ensure it remains valid after the setup transaction completes.
6

Send and Confirm Transaction

Send the deposit transaction and wait for confirmation to receive your cTokens.
const signature = getSignatureFromTransaction(signedTransaction);

await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction, {
  commitment: 'confirmed',
  skipPreflight: true,
});

console.log(
  `Deposit successful! You should now have kUSDC cTokens in your wallet. Signature: ${signature}${
    setupSignature ? `\nSetup transaction: https://solscan.io/tx/${setupSignature}` : ''
  }`
);
Once the transaction is confirmed, cTokens (kV-STKUSDC) will appear in your wallet. These tokens represent your deposit and will accrue interest over time. You can redeem them later for the underlying asset plus earned interest.