UNPKG

@kamino-finance/klend-sdk

Version:

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

376 lines (358 loc) 16.8 kB
import { PublicKey, Connection } from "@solana/web3.js" 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 * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars import { PROGRAM_ID } from "../programId" export interface LendingMarketFields { /** Version of lending market */ version: BN /** Bump seed for derived authority address */ bumpSeed: BN /** Owner authority which can add new reserves */ lendingMarketOwner: PublicKey /** Temporary cache of the lending market owner, used in update_lending_market_owner */ lendingMarketOwnerCached: PublicKey /** * Currency market prices are quoted in * e.g. "USD" null padded (`*b"USD\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"`) or a SPL token mint pubkey */ quoteCurrency: Array<number> /** Referral fee for the lending market, as bps out of the total protocol fee */ referralFeeBps: number emergencyMode: number autodeleverageEnabled: number borrowDisabled: number /** * Refresh price from oracle only if it's older than this percentage of the price max age. * e.g. if the max age is set to 100s and this is set to 80%, the price will be refreshed if it's older than 80s. * Price is always refreshed if this set to 0. */ priceRefreshTriggerToMaxAgePct: number /** Percentage of the total borrowed value in an obligation available for liquidation */ liquidationMaxDebtCloseFactorPct: number /** Minimum acceptable unhealthy LTV before max_debt_close_factor_pct becomes 100% */ insolvencyRiskUnhealthyLtvPct: number /** Minimum liquidation value threshold triggering full liquidation for an obligation */ minFullLiquidationValueThreshold: BN /** Max allowed liquidation value in one ix call */ maxLiquidatableDebtMarketValueAtOnce: BN /** Global maximum unhealthy borrow value allowed for any obligation */ globalUnhealthyBorrowValue: BN /** Global maximum allowed borrow value allowed for any obligation */ globalAllowedBorrowValue: BN /** The address of the risk council, in charge of making parameter and risk decisions on behalf of the protocol */ riskCouncil: PublicKey /** [DEPRECATED] Reward points multiplier per obligation type */ reserved1: Array<number> /** Elevation groups are used to group together reserves that have the same risk parameters and can bump the ltv and liquidation threshold */ elevationGroups: Array<types.ElevationGroupFields> elevationGroupPadding: Array<BN> /** Min net value accepted to be found in a position after any lending action in an obligation (scaled by quote currency decimals) */ minNetValueInObligationSf: BN minValueSkipLiquidationLtvBfChecks: BN /** Market name, zero-padded. */ name: Array<number> padding1: Array<BN> } export interface LendingMarketJSON { /** Version of lending market */ version: string /** Bump seed for derived authority address */ bumpSeed: string /** Owner authority which can add new reserves */ lendingMarketOwner: string /** Temporary cache of the lending market owner, used in update_lending_market_owner */ lendingMarketOwnerCached: string /** * Currency market prices are quoted in * e.g. "USD" null padded (`*b"USD\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"`) or a SPL token mint pubkey */ quoteCurrency: Array<number> /** Referral fee for the lending market, as bps out of the total protocol fee */ referralFeeBps: number emergencyMode: number autodeleverageEnabled: number borrowDisabled: number /** * Refresh price from oracle only if it's older than this percentage of the price max age. * e.g. if the max age is set to 100s and this is set to 80%, the price will be refreshed if it's older than 80s. * Price is always refreshed if this set to 0. */ priceRefreshTriggerToMaxAgePct: number /** Percentage of the total borrowed value in an obligation available for liquidation */ liquidationMaxDebtCloseFactorPct: number /** Minimum acceptable unhealthy LTV before max_debt_close_factor_pct becomes 100% */ insolvencyRiskUnhealthyLtvPct: number /** Minimum liquidation value threshold triggering full liquidation for an obligation */ minFullLiquidationValueThreshold: string /** Max allowed liquidation value in one ix call */ maxLiquidatableDebtMarketValueAtOnce: string /** Global maximum unhealthy borrow value allowed for any obligation */ globalUnhealthyBorrowValue: string /** Global maximum allowed borrow value allowed for any obligation */ globalAllowedBorrowValue: string /** The address of the risk council, in charge of making parameter and risk decisions on behalf of the protocol */ riskCouncil: string /** [DEPRECATED] Reward points multiplier per obligation type */ reserved1: Array<number> /** Elevation groups are used to group together reserves that have the same risk parameters and can bump the ltv and liquidation threshold */ elevationGroups: Array<types.ElevationGroupJSON> elevationGroupPadding: Array<string> /** Min net value accepted to be found in a position after any lending action in an obligation (scaled by quote currency decimals) */ minNetValueInObligationSf: string minValueSkipLiquidationLtvBfChecks: string /** Market name, zero-padded. */ name: Array<number> padding1: Array<string> } export class LendingMarket { /** Version of lending market */ readonly version: BN /** Bump seed for derived authority address */ readonly bumpSeed: BN /** Owner authority which can add new reserves */ readonly lendingMarketOwner: PublicKey /** Temporary cache of the lending market owner, used in update_lending_market_owner */ readonly lendingMarketOwnerCached: PublicKey /** * Currency market prices are quoted in * e.g. "USD" null padded (`*b"USD\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"`) or a SPL token mint pubkey */ readonly quoteCurrency: Array<number> /** Referral fee for the lending market, as bps out of the total protocol fee */ readonly referralFeeBps: number readonly emergencyMode: number readonly autodeleverageEnabled: number readonly borrowDisabled: number /** * Refresh price from oracle only if it's older than this percentage of the price max age. * e.g. if the max age is set to 100s and this is set to 80%, the price will be refreshed if it's older than 80s. * Price is always refreshed if this set to 0. */ readonly priceRefreshTriggerToMaxAgePct: number /** Percentage of the total borrowed value in an obligation available for liquidation */ readonly liquidationMaxDebtCloseFactorPct: number /** Minimum acceptable unhealthy LTV before max_debt_close_factor_pct becomes 100% */ readonly insolvencyRiskUnhealthyLtvPct: number /** Minimum liquidation value threshold triggering full liquidation for an obligation */ readonly minFullLiquidationValueThreshold: BN /** Max allowed liquidation value in one ix call */ readonly maxLiquidatableDebtMarketValueAtOnce: BN /** Global maximum unhealthy borrow value allowed for any obligation */ readonly globalUnhealthyBorrowValue: BN /** Global maximum allowed borrow value allowed for any obligation */ readonly globalAllowedBorrowValue: BN /** The address of the risk council, in charge of making parameter and risk decisions on behalf of the protocol */ readonly riskCouncil: PublicKey /** [DEPRECATED] Reward points multiplier per obligation type */ readonly reserved1: Array<number> /** Elevation groups are used to group together reserves that have the same risk parameters and can bump the ltv and liquidation threshold */ readonly elevationGroups: Array<types.ElevationGroup> readonly elevationGroupPadding: Array<BN> /** Min net value accepted to be found in a position after any lending action in an obligation (scaled by quote currency decimals) */ readonly minNetValueInObligationSf: BN readonly minValueSkipLiquidationLtvBfChecks: BN /** Market name, zero-padded. */ readonly name: Array<number> readonly padding1: Array<BN> static readonly discriminator = Buffer.from([ 246, 114, 50, 98, 72, 157, 28, 120, ]) static readonly layout = borsh.struct([ borsh.u64("version"), borsh.u64("bumpSeed"), borsh.publicKey("lendingMarketOwner"), borsh.publicKey("lendingMarketOwnerCached"), borsh.array(borsh.u8(), 32, "quoteCurrency"), borsh.u16("referralFeeBps"), borsh.u8("emergencyMode"), borsh.u8("autodeleverageEnabled"), borsh.u8("borrowDisabled"), borsh.u8("priceRefreshTriggerToMaxAgePct"), borsh.u8("liquidationMaxDebtCloseFactorPct"), borsh.u8("insolvencyRiskUnhealthyLtvPct"), borsh.u64("minFullLiquidationValueThreshold"), borsh.u64("maxLiquidatableDebtMarketValueAtOnce"), borsh.u64("globalUnhealthyBorrowValue"), borsh.u64("globalAllowedBorrowValue"), borsh.publicKey("riskCouncil"), borsh.array(borsh.u8(), 8, "reserved1"), borsh.array(types.ElevationGroup.layout(), 32, "elevationGroups"), borsh.array(borsh.u64(), 90, "elevationGroupPadding"), borsh.u128("minNetValueInObligationSf"), borsh.u64("minValueSkipLiquidationLtvBfChecks"), borsh.array(borsh.u8(), 32, "name"), borsh.array(borsh.u64(), 173, "padding1"), ]) constructor(fields: LendingMarketFields) { this.version = fields.version this.bumpSeed = fields.bumpSeed this.lendingMarketOwner = fields.lendingMarketOwner this.lendingMarketOwnerCached = fields.lendingMarketOwnerCached this.quoteCurrency = fields.quoteCurrency this.referralFeeBps = fields.referralFeeBps this.emergencyMode = fields.emergencyMode this.autodeleverageEnabled = fields.autodeleverageEnabled this.borrowDisabled = fields.borrowDisabled this.priceRefreshTriggerToMaxAgePct = fields.priceRefreshTriggerToMaxAgePct this.liquidationMaxDebtCloseFactorPct = fields.liquidationMaxDebtCloseFactorPct this.insolvencyRiskUnhealthyLtvPct = fields.insolvencyRiskUnhealthyLtvPct this.minFullLiquidationValueThreshold = fields.minFullLiquidationValueThreshold this.maxLiquidatableDebtMarketValueAtOnce = fields.maxLiquidatableDebtMarketValueAtOnce this.globalUnhealthyBorrowValue = fields.globalUnhealthyBorrowValue this.globalAllowedBorrowValue = fields.globalAllowedBorrowValue this.riskCouncil = fields.riskCouncil this.reserved1 = fields.reserved1 this.elevationGroups = fields.elevationGroups.map( (item) => new types.ElevationGroup({ ...item }) ) this.elevationGroupPadding = fields.elevationGroupPadding this.minNetValueInObligationSf = fields.minNetValueInObligationSf this.minValueSkipLiquidationLtvBfChecks = fields.minValueSkipLiquidationLtvBfChecks this.name = fields.name this.padding1 = fields.padding1 } static async fetch( c: Connection, address: PublicKey, programId: PublicKey = PROGRAM_ID ): Promise<LendingMarket | null> { const info = await c.getAccountInfo(address) if (info === null) { return null } if (!info.owner.equals(programId)) { throw new Error("account doesn't belong to this program") } return this.decode(info.data) } static async fetchMultiple( c: Connection, addresses: PublicKey[], programId: PublicKey = PROGRAM_ID ): Promise<Array<LendingMarket | null>> { const infos = await c.getMultipleAccountsInfo(addresses) return infos.map((info) => { if (info === null) { return null } if (!info.owner.equals(programId)) { throw new Error("account doesn't belong to this program") } return this.decode(info.data) }) } static decode(data: Buffer): LendingMarket { if (!data.slice(0, 8).equals(LendingMarket.discriminator)) { throw new Error("invalid account discriminator") } const dec = LendingMarket.layout.decode(data.slice(8)) return new LendingMarket({ version: dec.version, bumpSeed: dec.bumpSeed, lendingMarketOwner: dec.lendingMarketOwner, lendingMarketOwnerCached: dec.lendingMarketOwnerCached, quoteCurrency: dec.quoteCurrency, referralFeeBps: dec.referralFeeBps, emergencyMode: dec.emergencyMode, autodeleverageEnabled: dec.autodeleverageEnabled, borrowDisabled: dec.borrowDisabled, priceRefreshTriggerToMaxAgePct: dec.priceRefreshTriggerToMaxAgePct, liquidationMaxDebtCloseFactorPct: dec.liquidationMaxDebtCloseFactorPct, insolvencyRiskUnhealthyLtvPct: dec.insolvencyRiskUnhealthyLtvPct, minFullLiquidationValueThreshold: dec.minFullLiquidationValueThreshold, maxLiquidatableDebtMarketValueAtOnce: dec.maxLiquidatableDebtMarketValueAtOnce, globalUnhealthyBorrowValue: dec.globalUnhealthyBorrowValue, globalAllowedBorrowValue: dec.globalAllowedBorrowValue, riskCouncil: dec.riskCouncil, reserved1: dec.reserved1, elevationGroups: dec.elevationGroups.map( ( item: any /* eslint-disable-line @typescript-eslint/no-explicit-any */ ) => types.ElevationGroup.fromDecoded(item) ), elevationGroupPadding: dec.elevationGroupPadding, minNetValueInObligationSf: dec.minNetValueInObligationSf, minValueSkipLiquidationLtvBfChecks: dec.minValueSkipLiquidationLtvBfChecks, name: dec.name, padding1: dec.padding1, }) } toJSON(): LendingMarketJSON { return { version: this.version.toString(), bumpSeed: this.bumpSeed.toString(), lendingMarketOwner: this.lendingMarketOwner.toString(), lendingMarketOwnerCached: this.lendingMarketOwnerCached.toString(), quoteCurrency: this.quoteCurrency, referralFeeBps: this.referralFeeBps, emergencyMode: this.emergencyMode, autodeleverageEnabled: this.autodeleverageEnabled, borrowDisabled: this.borrowDisabled, priceRefreshTriggerToMaxAgePct: this.priceRefreshTriggerToMaxAgePct, liquidationMaxDebtCloseFactorPct: this.liquidationMaxDebtCloseFactorPct, insolvencyRiskUnhealthyLtvPct: this.insolvencyRiskUnhealthyLtvPct, minFullLiquidationValueThreshold: this.minFullLiquidationValueThreshold.toString(), maxLiquidatableDebtMarketValueAtOnce: this.maxLiquidatableDebtMarketValueAtOnce.toString(), globalUnhealthyBorrowValue: this.globalUnhealthyBorrowValue.toString(), globalAllowedBorrowValue: this.globalAllowedBorrowValue.toString(), riskCouncil: this.riskCouncil.toString(), reserved1: this.reserved1, elevationGroups: this.elevationGroups.map((item) => item.toJSON()), elevationGroupPadding: this.elevationGroupPadding.map((item) => item.toString() ), minNetValueInObligationSf: this.minNetValueInObligationSf.toString(), minValueSkipLiquidationLtvBfChecks: this.minValueSkipLiquidationLtvBfChecks.toString(), name: this.name, padding1: this.padding1.map((item) => item.toString()), } } static fromJSON(obj: LendingMarketJSON): LendingMarket { return new LendingMarket({ version: new BN(obj.version), bumpSeed: new BN(obj.bumpSeed), lendingMarketOwner: new PublicKey(obj.lendingMarketOwner), lendingMarketOwnerCached: new PublicKey(obj.lendingMarketOwnerCached), quoteCurrency: obj.quoteCurrency, referralFeeBps: obj.referralFeeBps, emergencyMode: obj.emergencyMode, autodeleverageEnabled: obj.autodeleverageEnabled, borrowDisabled: obj.borrowDisabled, priceRefreshTriggerToMaxAgePct: obj.priceRefreshTriggerToMaxAgePct, liquidationMaxDebtCloseFactorPct: obj.liquidationMaxDebtCloseFactorPct, insolvencyRiskUnhealthyLtvPct: obj.insolvencyRiskUnhealthyLtvPct, minFullLiquidationValueThreshold: new BN( obj.minFullLiquidationValueThreshold ), maxLiquidatableDebtMarketValueAtOnce: new BN( obj.maxLiquidatableDebtMarketValueAtOnce ), globalUnhealthyBorrowValue: new BN(obj.globalUnhealthyBorrowValue), globalAllowedBorrowValue: new BN(obj.globalAllowedBorrowValue), riskCouncil: new PublicKey(obj.riskCouncil), reserved1: obj.reserved1, elevationGroups: obj.elevationGroups.map((item) => types.ElevationGroup.fromJSON(item) ), elevationGroupPadding: obj.elevationGroupPadding.map( (item) => new BN(item) ), minNetValueInObligationSf: new BN(obj.minNetValueInObligationSf), minValueSkipLiquidationLtvBfChecks: new BN( obj.minValueSkipLiquidationLtvBfChecks ), name: obj.name, padding1: obj.padding1.map((item) => new BN(item)), }) } }