Skip to main content

Flash Loans

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,
  none,
  getProgramDerivedAddress,
  getAddressEncoder,
} from '@solana/kit';
import {
  KaminoMarket,
  PROGRAM_ID,
  getFlashLoanInstructions
} from '@kamino-finance/klend-sdk';
import { parseKeypairFile } from '@kamino-finance/klend-sdk/dist/utils/signer.js';
import { getAddMemoInstruction } from '@solana-program/memo';
import Decimal from 'decimal.js';
2

Setup Market and Signer

Load your 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'); // Main Market
const market = await KaminoMarket.load(rpc, marketPubkey, 100);
3

Configure Flash Loan Parameters

Set the token mint, flash loan amount, and derive the user’s token account address.
const usdcMint = address('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); // USDC
const usdcReserve = market!.getReserveByMint(usdcMint)!;

// Flash loan amount: 1 USDC
const flashLoanAmount = new Decimal(1_000_000);

// Derive user's USDC token account (ATA)
const ASSOCIATED_TOKEN_PROGRAM = address('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL');
const TOKEN_PROGRAM = usdcReserve.getLiquidityTokenProgram();

const addressEncoder = getAddressEncoder();
const [usdcAta] = await getProgramDerivedAddress({
  programAddress: ASSOCIATED_TOKEN_PROGRAM,
  seeds: [
    addressEncoder.encode(signer.address),
    addressEncoder.encode(TOKEN_PROGRAM),
    addressEncoder.encode(usdcMint)
  ],
});
4

Build Flash Loan Instructions

Generate the flash borrow and flash repay instructions using the Kamino SDK.
// Build flash loan instructions
const lendingMarketAuthority = await market!.getLendingMarketAuthority();

const { flashBorrowIx, flashRepayIx } = getFlashLoanInstructions({
  borrowIxIndex: 0,
  userTransferAuthority: signer,
  lendingMarketAuthority,
  lendingMarketAddress: market!.getAddress(),
  reserve: usdcReserve,
  amountLamports: flashLoanAmount,
  destinationAta: usdcAta,
  referrerAccount: none(),
  referrerTokenState: none(),
  programId: PROGRAM_ID,
});
The borrowIxIndex:0 parameter specifies that the flash borrow instruction is at index 0 in the transaction. The SDK uses this to validate that repayment occurs in the same transaction.
5

Add Your Custom Instructions

Create your custom instructions to execute with the borrowed funds. In this example, we use a simple memo instruction.
// Create memo instruction
const memoIx = getAddMemoInstruction({ memo: 'Hello Kamino' });

// Arrange instructions: flash borrow → your instructions → flash repay
const allInstructions = [flashBorrowIx, memoIx, flashRepayIx];
Replace the memo instruction with your actual business logic.
6

Build and Send Transaction

Build the transaction with a fresh blockhash and send it to the network.
// Get fresh blockhash
const { value: latestBlockhash } = await rpc
  .getLatestBlockhash({ commitment: 'finalized' })
  .send();

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

const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);

const signature = getSignatureFromTransaction(signedTransaction);

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

console.log(`Flash loan successful! Signature: ${signature}`);
Your flash loan transaction is complete! The borrowed funds were used for your operations and automatically repaid within the same atomic transaction.