Skip to main content

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.

A market is created by a single transaction. The transaction initializes a LendingMarket account on-chain with default settings and your wallet (or a multisig) as the owner. Reserves, oracles, and feature flags are configured in subsequent steps. The market is empty (no reserves) until you add reserves, and cannot accept deposits or borrows until at least one reserve is active.

Create a market via SDK

Use KaminoManager from @kamino-finance/klend-sdk to build and submit the create-market instruction.
1

Import dependencies

import {
  createSolanaRpc,
  createSolanaRpcSubscriptions,
  pipe,
  createTransactionMessage,
  setTransactionMessageFeePayerSigner,
  setTransactionMessageLifetimeUsingBlockhash,
  appendTransactionMessageInstructions,
  signTransactionMessageWithSigners,
  sendAndConfirmTransactionFactory,
} from '@solana/kit';
import {
  KaminoManager,
  DEFAULT_RECENT_SLOT_DURATION_MS,
  PROGRAM_ID,
} from '@kamino-finance/klend-sdk';
import { parseKeypairFile } from '@kamino-finance/klend-sdk/dist/utils/signer.js';
2

Initialize KaminoManager

const adminSigner = await parseKeypairFile('/path/to/admin.json');

const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const rpcSubscriptions = createSolanaRpcSubscriptions('wss://api.mainnet-beta.solana.com');

const kaminoManager = new KaminoManager(rpc, DEFAULT_RECENT_SLOT_DURATION_MS, PROGRAM_ID);
Use a private RPC endpoint for production. Public RPCs are rate-limited.
3

Build the create-market instructions

const { market: marketSigner, ixs: createMarketIxs } = await kaminoManager.createMarketIxs({
  admin: adminSigner,
});

console.log('New market address:', marketSigner.address);
createMarketIxs returns:
  • market: a TransactionSigner for the market account; its address is the new market’s pubkey
  • ixs: the instructions needed to create and initialize the market
Save the marketSigner.address value — every subsequent operation references it.
4

Sign and send the transaction

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

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

const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);

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

console.log('Market created:', marketSigner.address);
The market signer (marketSigner) is automatically included as a signer because KaminoManager.createMarketIxs returns it as a TransactionSigner.

Targeting staging or devnet

Pass the staging or devnet program ID when constructing KaminoManager:
import { STAGING_PROGRAM_ID } from '@kamino-finance/klend-sdk';

const kaminoManager = new KaminoManager(rpc, DEFAULT_RECENT_SLOT_DURATION_MS, STAGING_PROGRAM_ID);
For devnet, point the RPC at https://api.devnet.solana.com and use the devnet program ID from your environment.

Multisig from the start

If you want the market owned by a multisig from inception, pass the multisig pubkey as a noop signer for admin:
import { noopSigner, address } from '@kamino-finance/klend-sdk';

const multisigAdmin = noopSigner(address('<SQUADS_MULTISIG_PUBKEY>'));

const { market, ixs } = await kaminoManager.createMarketIxs({
  admin: multisigAdmin,
});

// Don't sign and send. Instead, encode the transaction as base58 and submit it
// as a Squads proposal. The multisig itself will sign and execute.
For most curators, the simpler path is to create under a hot wallet, add reserves, validate, then transfer to a multisig.

What happens on-chain

The instruction initializes a LendingMarket account with:
  • lending_market_owner set to your admin
  • quote_currency set to a default (override later via update-lending-market-from-config)
  • All feature flags (borrow_disabled, emergency_mode, withdraw_ticket_*, borrow_order_*, obligation_order_*, autodeleverage_enabled, immutable) initialized to 0
  • All elevation groups empty
  • Default values for liquidation tunables and minimum deposit thresholds
Every default is overridable post-creation via Market settings.

What’s next

Add reserves

Add the first asset to your market with a reserve config.

Configure oracles

Wire each reserve to a price feed (Scope, Pyth, or Switchboard).

Reference