klend
program). A lending market holds one reserve per token: gNTB’s reserve accepts it as
collateral, and cNGN’s reserve is what lenders supply and borrowers draw. A borrower’s
position is an obligation account that records its deposits and borrows.
The gNTB / cNGN market (devnet)
These are read from the reserve accounts; re-read them before relying on them.
Using the Kamino SDK
The simplest client is Kamino’s TypeScript SDK,@kamino-finance/klend-sdk. Load the
market by its address and build actions with KaminoAction
(buildDepositTxns, buildBorrowTxns, buildRepayTxns, buildWithdrawTxns): the SDK
adds the refresh instructions described below for you.
The SDK resolves prices through Kamino’s mainnet Scope program by default. On
devnet, our feed lives on Kamino’s devnet Scope program
(
3Vw8Ngkh1MVJTPHthmUbmU2XKtFEkjYvJzMqrv2rh9yX), so SDK helpers that compute prices
client-side may not find it. Building and sending transactions is unaffected: the
klend program reads the feed itself.The instructions
If you build transactions yourself, klend refuses an action on stale state, so every action is preceded in the same transaction by:refresh_reservefor every reserve the obligation touches, plus the one you act on. Accounts: reserve, lending market, then the Pyth / Switchboard price / Switchboard TWAP slots (pass the klend program id for “none”), then the Scope prices account.refresh_obligation, with the obligation’s deposit reserves, then its borrow reserves, in the order the obligation lists them, as remaining accounts.
Posting collateral and borrowing can share one transaction: deposit, then refresh again
(the obligation now lists the gNTB deposit), then borrow.
Accounts you derive
Reserve vaults (liquidity supply, fee receiver, collateral mint, collateral supply) are
stored on the reserve account: read them from it. The gNTB and cNGN reserves have no
rewards farm, so the
_v2 instructions’ farm accounts are the klend program id, with the
farms program FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr.
kTokens
Deposits are tracked in the reserve’s collateral token (kTokens). One kToken is worthtotal supply ÷ kToken supply of the underlying, where total supply = available
liquidity + borrowed − accumulated fees. It starts at 1 and grows as interest is paid, so
convert amounts to kTokens before withdrawing (round down).
The price feed
Each reserve reads its price from a Scope feed on Kamino’s oracle program. Ours is aFixedPrice entry that GetEquity updates to gNTB’s accrued price in cNGN (entry 0), with
cNGN fixed at 1 (entry 1). Read an entry from the prices account at byte offset
40 + 56 × index: value (u64), exp (u64), then the slot and unix timestamp it was
last refreshed.
A reserve refuses a price older than its maxAgePriceSeconds. On devnet this is set
generously (7 days) for testing; a mainnet market would require a short age and a
running updater.
Liquidation
When a position’s borrowed value exceeds the liquidation threshold (77%) of its collateral value, anyone may callliquidate_obligation_and_redeem_reserve_collateral to repay part
of the debt and receive gNTB worth the repaid amount plus the 7.4% bonus. Kamino’s
liquidation rules (how much can be repaid at once) are in its
documentation.