UNPKG

@kamino-finance/klend-sdk

Version:

Typescript SDK for interacting with the Kamino Lending (klend) protocol

241 lines (228 loc) 10.2 kB
/* eslint-disable @typescript-eslint/no-unused-vars */ import { address, Address, fetchEncodedAccount, fetchEncodedAccounts, GetAccountInfoApi, GetMultipleAccountsApi, Rpc, } from "@solana/kit" /* eslint-enable @typescript-eslint/no-unused-vars */ import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars import * as borsh from "@coral-xyz/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars import { borshAddress } from "../utils" // eslint-disable-line @typescript-eslint/no-unused-vars import * as types from "../../../@codegen/klend/types" // eslint-disable-line @typescript-eslint/no-unused-vars import { PROGRAM_ID } from "../../../@codegen/klend/programId" import { Obligation, ObligationFields } from '../../../@codegen/klend/accounts'; /** Lending market obligation state */ export class ObligationZP { /** Version of the struct */ readonly tag: BN /** Last update to collateral, liquidity, or their market values */ readonly lastUpdate: types.LastUpdate /** Lending market address */ readonly lendingMarket: Address /** Owner authority which can borrow liquidity */ readonly owner: Address /** Deposited collateral for the obligation, unique by deposit reserve address */ readonly deposits: Array<types.ObligationCollateral> /** Worst LTV for the collaterals backing the loan, represented as a percentage */ readonly lowestReserveDepositLiquidationLtv: BN /** Market value of deposits (scaled fraction) */ readonly depositedValueSf: BN /** Borrowed liquidity for the obligation, unique by borrow reserve address */ readonly borrows: Array<types.ObligationLiquidity> /** Risk adjusted market value of borrows/debt (sum of price * borrowed_amount * borrow_factor) (scaled fraction) */ readonly borrowFactorAdjustedDebtValueSf: BN /** Market value of borrows - used for max_liquidatable_borrowed_amount (scaled fraction) */ readonly borrowedAssetsMarketValueSf: BN /** The maximum borrow value at the weighted average loan to value ratio (scaled fraction) */ readonly allowedBorrowValueSf: BN /** The dangerous borrow value at the weighted average liquidation threshold (scaled fraction) */ readonly unhealthyBorrowValueSf: BN /** The asset tier of the deposits */ readonly paddingDeprecatedAssetTiers: Array<number> /** The elevation group id the obligation opted into. */ readonly elevationGroup: number /** The number of obsolete reserves the obligation has a deposit in */ readonly numOfObsoleteDepositReserves: number /** Marked = 1 if borrows array is not empty, 0 = borrows empty */ readonly hasDebt: number /** Wallet address of the referrer */ readonly referrer: Address /** Marked = 1 if borrowing disabled, 0 = borrowing enabled */ readonly borrowingDisabled: number /** * A target LTV set by the risk council when marking this obligation for deleveraging. * Only effective when `deleveraging_margin_call_started_slot != 0`. */ readonly autodeleverageTargetLtvPct: number /** The lowest max LTV found amongst the collateral deposits */ readonly lowestReserveDepositMaxLtvPct: number /** The number of obsolete reserves the obligation has a borrow in */ readonly numOfObsoleteBorrowReserves: number readonly reserved: Array<number> readonly highestBorrowFactorPct: BN /** * A timestamp at which the risk council most-recently marked this obligation for deleveraging. * Zero if not currently subject to deleveraging. */ readonly autodeleverageMarginCallStartedTimestamp: BN /** * Owner-defined, permissionlessly-executed repay orders. * Typical use-cases would be a stop-loss and a take-profit (possibly co-existing). */ readonly obligationOrders: Array<types.ObligationOrder> /** * Owner-defined, permissionlessly-executed borrow order applicable to this obligation. * Non-zeroed only on a newly-initialized fixed-rate, fixed-term obligation. */ readonly borrowOrder: types.BorrowOrder readonly padding3: Array<BN> = new Array(0) static readonly layout = borsh.struct<ObligationZP>([ borsh.u64("tag"), types.LastUpdate.layout("lastUpdate"), borshAddress("lendingMarket"), borshAddress("owner"), borsh.array(types.ObligationCollateral.layout(), 8, "deposits"), borsh.u64("lowestReserveDepositLiquidationLtv"), borsh.u128("depositedValueSf"), borsh.array(types.ObligationLiquidity.layout(), 5, "borrows"), borsh.u128("borrowFactorAdjustedDebtValueSf"), borsh.u128("borrowedAssetsMarketValueSf"), borsh.u128("allowedBorrowValueSf"), borsh.u128("unhealthyBorrowValueSf"), borsh.array(borsh.u8(), 13, "paddingDeprecatedAssetTiers"), borsh.u8("elevationGroup"), borsh.u8("numOfObsoleteDepositReserves"), borsh.u8("hasDebt"), borshAddress("referrer"), borsh.u8("borrowingDisabled"), borsh.u8("autodeleverageTargetLtvPct"), borsh.u8("lowestReserveDepositMaxLtvPct"), borsh.u8("numOfObsoleteBorrowReserves"), borsh.array(borsh.u8(), 4, "reserved"), borsh.u64("highestBorrowFactorPct"), borsh.u64("autodeleverageMarginCallStartedTimestamp"), borsh.array(types.ObligationOrder.layout(), 2, "obligationOrders"), types.BorrowOrder.layout("borrowOrder"), ]) constructor(fields: ObligationFields) { this.tag = fields.tag this.lastUpdate = new types.LastUpdate({ ...fields.lastUpdate }) this.lendingMarket = fields.lendingMarket this.owner = fields.owner this.deposits = fields.deposits.map( (item) => new types.ObligationCollateral({ ...item }) ) this.lowestReserveDepositLiquidationLtv = fields.lowestReserveDepositLiquidationLtv this.depositedValueSf = fields.depositedValueSf this.borrows = fields.borrows.map( (item) => new types.ObligationLiquidity({ ...item }) ) this.borrowFactorAdjustedDebtValueSf = fields.borrowFactorAdjustedDebtValueSf this.borrowedAssetsMarketValueSf = fields.borrowedAssetsMarketValueSf this.allowedBorrowValueSf = fields.allowedBorrowValueSf this.unhealthyBorrowValueSf = fields.unhealthyBorrowValueSf this.paddingDeprecatedAssetTiers = fields.paddingDeprecatedAssetTiers this.elevationGroup = fields.elevationGroup this.numOfObsoleteDepositReserves = fields.numOfObsoleteDepositReserves this.hasDebt = fields.hasDebt this.referrer = fields.referrer this.borrowingDisabled = fields.borrowingDisabled this.autodeleverageTargetLtvPct = fields.autodeleverageTargetLtvPct this.lowestReserveDepositMaxLtvPct = fields.lowestReserveDepositMaxLtvPct this.numOfObsoleteBorrowReserves = fields.numOfObsoleteBorrowReserves this.reserved = new Array<number>(0) this.highestBorrowFactorPct = fields.highestBorrowFactorPct this.autodeleverageMarginCallStartedTimestamp = fields.autodeleverageMarginCallStartedTimestamp this.obligationOrders = fields.obligationOrders.map( (item) => new types.ObligationOrder({ ...item }) ) this.borrowOrder = new types.BorrowOrder({ ...fields.borrowOrder }) this.padding3 = new Array<BN>(0); } static async fetch( rpc: Rpc<GetAccountInfoApi>, address: Address, programId: Address = PROGRAM_ID ): Promise<Obligation | null> { const info = await fetchEncodedAccount(rpc, address) if (!info.exists) { return null } if (info.programAddress !== programId) { throw new Error("account doesn't belong to this program") } return this.decode(Buffer.from(info.data)) } static async fetchMultiple( rpc: Rpc<GetMultipleAccountsApi>, addresses: Address[], programId: Address = PROGRAM_ID ): Promise<Array<Obligation | null>> { const infos = await fetchEncodedAccounts(rpc, addresses) return infos.map((info) => { if (!info.exists) { return null } if (info.programAddress !== programId) { throw new Error("account doesn't belong to this program") } return this.decode(Buffer.from(info.data)) }) } static decode(data: Buffer): Obligation { if (!data.slice(0, 8).equals(Obligation.discriminator)) { throw new Error("invalid account discriminator") } const dec = ObligationZP.layout.decode(data.slice(8)) return new Obligation({ tag: dec.tag, lastUpdate: types.LastUpdate.fromDecoded(dec.lastUpdate), lendingMarket: dec.lendingMarket, owner: dec.owner, deposits: dec.deposits.map( ( item: any /* eslint-disable-line @typescript-eslint/no-explicit-any */ ) => types.ObligationCollateral.fromDecoded(item) ), lowestReserveDepositLiquidationLtv: dec.lowestReserveDepositLiquidationLtv, depositedValueSf: dec.depositedValueSf, borrows: dec.borrows.map( ( item: any /* eslint-disable-line @typescript-eslint/no-explicit-any */ ) => types.ObligationLiquidity.fromDecoded(item) ), borrowFactorAdjustedDebtValueSf: dec.borrowFactorAdjustedDebtValueSf, borrowedAssetsMarketValueSf: dec.borrowedAssetsMarketValueSf, allowedBorrowValueSf: dec.allowedBorrowValueSf, unhealthyBorrowValueSf: dec.unhealthyBorrowValueSf, paddingDeprecatedAssetTiers: dec.paddingDeprecatedAssetTiers, elevationGroup: dec.elevationGroup, numOfObsoleteDepositReserves: dec.numOfObsoleteDepositReserves, hasDebt: dec.hasDebt, referrer: dec.referrer, borrowingDisabled: dec.borrowingDisabled, autodeleverageTargetLtvPct: dec.autodeleverageTargetLtvPct, lowestReserveDepositMaxLtvPct: dec.lowestReserveDepositMaxLtvPct, numOfObsoleteBorrowReserves: dec.numOfObsoleteBorrowReserves, reserved: dec.reserved, highestBorrowFactorPct: dec.highestBorrowFactorPct, autodeleverageMarginCallStartedTimestamp: dec.autodeleverageMarginCallStartedTimestamp, obligationOrders: dec.obligationOrders.map( ( item: any /* eslint-disable-line @typescript-eslint/no-explicit-any */ ) => types.ObligationOrder.fromDecoded(item) ), borrowOrder: types.BorrowOrder.fromDecoded(dec.borrowOrder), padding3: [], }) } }