@kamino-finance/klend-sdk
Version:
Typescript SDK for interacting with the Kamino Lending (klend) protocol
1,551 lines • 85.8 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.KaminoReserve = exports.DEFAULT_RECENT_SLOT_DURATION_MS = void 0;
exports.createReserveIxs = createReserveIxs;
exports.updateReserveConfigIx = updateReserveConfigIx;
exports.updateEntireReserveConfigIx = updateEntireReserveConfigIx;
exports.parseForChangesReserveConfigAndGetIxs = parseForChangesReserveConfigAndGetIxs;
exports.updateReserveConfigEncodedValue = updateReserveConfigEncodedValue;
exports.serializeBorrowRateCurve = serializeBorrowRateCurve;
/* eslint-disable max-classes-per-file */
const web3_js_1 = require("@solana/web3.js");
const decimal_js_1 = __importDefault(require("decimal.js"));
const utils_1 = require("../utils");
const shared_1 = require("./shared");
const accounts_1 = require("../idl_codegen/accounts");
const types_1 = require("../idl_codegen/types");
const utils_2 = require("./utils");
const fraction_1 = require("./fraction");
const bn_js_1 = __importDefault(require("bn.js"));
const lib_1 = require("../lib");
const anchor = __importStar(require("@coral-xyz/anchor"));
const spl_token_1 = require("@solana/spl-token");
const UpdateConfigMode_1 = require("../idl_codegen/types/UpdateConfigMode");
const kliquidity_sdk_1 = require("@kamino-finance/kliquidity-sdk");
const farms_sdk_1 = require("@kamino-finance/farms-sdk");
exports.DEFAULT_RECENT_SLOT_DURATION_MS = 450;
class KaminoReserve {
state;
address;
symbol;
tokenOraclePrice;
stats;
farmData = { fetched: false, farmStates: [] };
buffer;
connection;
recentSlotDurationMs;
constructor(state, address, tokenOraclePrice, connection, recentSlotDurationMs) {
this.state = state;
this.address = address;
this.buffer = null;
this.tokenOraclePrice = tokenOraclePrice;
this.stats = {};
this.connection = connection;
this.symbol = (0, utils_2.parseTokenSymbol)(state.config.tokenInfo.name);
this.recentSlotDurationMs = recentSlotDurationMs;
}
static initialize(accountData, address, state, tokenOraclePrice, connection, recentSlotDurationMs) {
const reserve = new KaminoReserve(state, address, tokenOraclePrice, connection, recentSlotDurationMs);
reserve.setBuffer(accountData);
reserve.stats = reserve.formatReserveData(state);
return reserve;
}
/// GETTERS
/**
* @returns the parsed token symbol of the reserve
*/
getTokenSymbol() {
return (0, utils_2.parseTokenSymbol)(this.state.config.tokenInfo.name);
}
/**
* @returns the total borrowed amount of the reserve in lamports
*/
getBorrowedAmount() {
return new fraction_1.Fraction(this.state.liquidity.borrowedAmountSf).toDecimal();
}
/**
* @returns the available liquidity amount of the reserve in lamports
*/
getLiquidityAvailableAmount() {
return new decimal_js_1.default(this.state.liquidity.availableAmount.toString());
}
/**
*
* @returns the last cached price stored in the reserve in USD
*/
getReserveMarketPrice() {
return new fraction_1.Fraction(this.state.liquidity.marketPriceSf).toDecimal();
}
/**
* @returns the current market price of the reserve in USD
*/
getOracleMarketPrice() {
return this.tokenOraclePrice.price;
}
/**
* @returns the total accumulated protocol fees of the reserve
*/
getAccumulatedProtocolFees() {
return new fraction_1.Fraction(this.state.liquidity.accumulatedProtocolFeesSf).toDecimal();
}
/**
* @returns the total accumulated referrer fees of the reserve
*/
getAccumulatedReferrerFees() {
return new fraction_1.Fraction(this.state.liquidity.accumulatedReferrerFeesSf).toDecimal();
}
/**
* @returns the total pending referrer fees of the reserve
*/
getPendingReferrerFees() {
return new fraction_1.Fraction(this.state.liquidity.pendingReferrerFeesSf).toDecimal();
}
/**
*
* @returns the flash loan fee percentage of the reserve
*/
getFlashLoanFee = () => {
if (this.state.config.fees.flashLoanFeeSf.toString() === utils_1.U64_MAX) {
return new decimal_js_1.default('0');
}
return new fraction_1.Fraction(this.state.config.fees.flashLoanFeeSf).toDecimal();
};
/**
*
* @returns the origination fee percentage of the reserve
*/
getBorrowFee = () => {
return new fraction_1.Fraction(this.state.config.fees.borrowFeeSf).toDecimal();
};
/**
*
* @returns the fixed interest rate allocated to the host
*/
getFixedHostInterestRate = () => {
return new decimal_js_1.default(this.state.config.hostFixedInterestRateBps).div(10_000);
};
/**
* Use getEstimatedTotalSupply() for the most accurate value
* @returns the stale total liquidity supply of the reserve from the last refresh
*/
getTotalSupply() {
return this.getLiquidityAvailableAmount()
.add(this.getBorrowedAmount())
.sub(this.getAccumulatedProtocolFees())
.sub(this.getAccumulatedReferrerFees())
.sub(this.getPendingReferrerFees());
}
/**
* Calculates the total liquidity supply of the reserve
*/
getEstimatedTotalSupply(slot, referralFeeBps) {
const { totalSupply } = this.getEstimatedDebtAndSupply(slot, referralFeeBps);
return totalSupply;
}
/**
* Use getEstimatedCumulativeBorrowRate() for the most accurate value
* @returns the stale cumulative borrow rate of the reserve from the last refresh
*/
getCumulativeBorrowRate() {
const cumulativeBorrowRateBsf = this.state.liquidity.cumulativeBorrowRateBsf.value;
const accSf = cumulativeBorrowRateBsf.reduce((prev, curr, i) => prev.add(curr.shln(i * 64)), new bn_js_1.default(0));
return new fraction_1.Fraction(accSf).toDecimal();
}
/**
* @Returns estimated cumulative borrow rate of the reserve
*/
getEstimatedCumulativeBorrowRate(currentSlot, referralFeeBps) {
const currentBorrowRate = new decimal_js_1.default(this.calculateBorrowAPR(currentSlot, referralFeeBps));
const slotsElapsed = Math.max(currentSlot - this.state.lastUpdate.slot.toNumber(), 0);
const compoundInterest = this.approximateCompoundedInterest(currentBorrowRate, slotsElapsed);
const previousCumulativeBorrowRate = this.getCumulativeBorrowRate();
return previousCumulativeBorrowRate.mul(compoundInterest);
}
/**
* Use getEstimatedCollateralExchangeRate() for the most accurate value
* @returns the stale exchange rate between the collateral tokens and the liquidity - this is a decimal number scaled by 1e18
*/
getCollateralExchangeRate() {
const totalSupply = this.getTotalSupply();
const mintTotalSupply = this.state.collateral.mintTotalSupply;
if (mintTotalSupply.isZero() || totalSupply.isZero()) {
return utils_1.INITIAL_COLLATERAL_RATE;
}
else {
return new decimal_js_1.default(mintTotalSupply.toString()).dividedBy(totalSupply.toString());
}
}
/**
*
* @returns the estimated exchange rate between the collateral tokens and the liquidity - this is a decimal number scaled by 1e18
*/
getEstimatedCollateralExchangeRate(slot, referralFeeBps) {
const totalSupply = this.getEstimatedTotalSupply(slot, referralFeeBps);
const mintTotalSupply = this.state.collateral.mintTotalSupply;
if (mintTotalSupply.isZero() || totalSupply.isZero()) {
return utils_1.INITIAL_COLLATERAL_RATE;
}
else {
return new decimal_js_1.default(mintTotalSupply.toString()).dividedBy(totalSupply.toString());
}
}
/**
*
* @returns the total USD value of the existing collateral in the reserve
*/
getDepositTvl = () => {
return new decimal_js_1.default(this.getTotalSupply().toString()).mul(this.getOracleMarketPrice()).div(this.getMintFactor());
};
/**
*
* Get the total USD value of the borrowed assets from the reserve
*/
getBorrowTvl = () => {
return this.getBorrowedAmount().mul(this.getOracleMarketPrice()).div(this.getMintFactor());
};
/**
* @returns 10^mint_decimals
*/
getMintFactor() {
return new decimal_js_1.default(10).pow(this.state.liquidity.mintDecimals.toNumber());
}
/**
* @Returns true if the total liquidity supply of the reserve is greater than the deposit limit
*/
depositLimitCrossed() {
return this.getTotalSupply().gt(new decimal_js_1.default(this.state.config.depositLimit.toString()));
}
/**
* @Returns true if the total borrowed amount of the reserve is greater than the borrow limit
*/
borrowLimitCrossed() {
return this.getBorrowedAmount().gt(new decimal_js_1.default(this.state.config.borrowLimit.toString()));
}
/**
*
* @returns the max capacity of the daily deposit withdrawal cap
*/
getDepositWithdrawalCapCapacity() {
return new decimal_js_1.default(this.state.config.depositWithdrawalCap.configCapacity.toString());
}
/**
*
* @returns the current capacity of the daily deposit withdrawal cap
*/
getDepositWithdrawalCapCurrent(slot) {
const slotsElapsed = Math.max(slot - this.state.lastUpdate.slot.toNumber(), 0);
if (slotsElapsed > utils_1.SLOTS_PER_DAY) {
return new decimal_js_1.default(0);
}
else {
return new decimal_js_1.default(this.state.config.depositWithdrawalCap.currentTotal.toString());
}
}
/**
*
* @returns the max capacity of the daily debt withdrawal cap
*/
getDebtWithdrawalCapCapacity() {
return new decimal_js_1.default(this.state.config.debtWithdrawalCap.configCapacity.toString());
}
/**
*
* @returns the borrow limit of the reserve outside the elevation group
*/
getBorrowLimitOutsideElevationGroup() {
return new decimal_js_1.default(this.state.config.borrowLimitOutsideElevationGroup.toString());
}
/**
*
* @returns the borrowed amount of the reserve outside the elevation group
*/
getBorrowedAmountOutsideElevationGroup() {
return new decimal_js_1.default(this.state.borrowedAmountOutsideElevationGroup.toString());
}
/**
*
* @returns the borrow limit against the collateral reserve in the elevation group
*/
getBorrowLimitAgainstCollateralInElevationGroup(elevationGroupIndex) {
return new decimal_js_1.default(this.state.config.borrowLimitAgainstThisCollateralInElevationGroup[elevationGroupIndex].toString());
}
/**
*
* @returns the borrowed amount against the collateral reserve in the elevation group
*/
getBorrowedAmountAgainstCollateralInElevationGroup(elevationGroupIndex) {
return new decimal_js_1.default(this.state.borrowedAmountsAgainstThisReserveInElevationGroups[elevationGroupIndex].toString());
}
/**
*
* @returns the current capacity of the daily debt withdrawal cap
*/
getDebtWithdrawalCapCurrent(slot) {
const slotsElapsed = Math.max(slot - this.state.lastUpdate.slot.toNumber(), 0);
if (slotsElapsed > utils_1.SLOTS_PER_DAY) {
return new decimal_js_1.default(0);
}
else {
return new decimal_js_1.default(this.state.config.debtWithdrawalCap.currentTotal.toString());
}
}
getBorrowFactor() {
return new decimal_js_1.default(this.state.config.borrowFactorPct.toString()).div(100);
}
calculateSupplyAPR(slot, referralFeeBps) {
const currentUtilization = this.calculateUtilizationRatio();
const borrowRate = this.calculateEstimatedBorrowRate(slot, referralFeeBps);
const protocolTakeRatePct = 1 - this.state.config.protocolTakeRatePct / 100;
return currentUtilization * borrowRate * protocolTakeRatePct;
}
getEstimatedDebtAndSupply(slot, referralFeeBps) {
const slotsElapsed = Math.max(slot - this.state.lastUpdate.slot.toNumber(), 0);
let totalBorrow;
let totalSupply;
if (slotsElapsed === 0) {
totalBorrow = this.getBorrowedAmount();
totalSupply = this.getTotalSupply();
}
else {
const { newDebt, newAccProtocolFees, pendingReferralFees } = this.compoundInterest(slotsElapsed, referralFeeBps);
const newTotalSupply = this.getLiquidityAvailableAmount()
.add(newDebt)
.sub(newAccProtocolFees)
.sub(this.getAccumulatedReferrerFees())
.sub(pendingReferralFees);
totalBorrow = newDebt;
totalSupply = newTotalSupply;
}
return { totalBorrow, totalSupply };
}
getEstimatedAccumulatedProtocolFees(slot, referralFeeBps) {
const slotsElapsed = Math.max(slot - this.state.lastUpdate.slot.toNumber(), 0);
let accumulatedProtocolFees;
let compoundedVariableProtocolFee;
let compoundedFixedHostFee;
if (slotsElapsed === 0) {
accumulatedProtocolFees = this.getAccumulatedProtocolFees();
compoundedVariableProtocolFee = new decimal_js_1.default(0);
compoundedFixedHostFee = new decimal_js_1.default(0);
}
else {
const { newAccProtocolFees, variableProtocolFee, fixedHostFee } = this.compoundInterest(slotsElapsed, referralFeeBps);
accumulatedProtocolFees = newAccProtocolFees;
compoundedVariableProtocolFee = variableProtocolFee;
compoundedFixedHostFee = fixedHostFee;
}
return { accumulatedProtocolFees, compoundedVariableProtocolFee, compoundedFixedHostFee };
}
calculateUtilizationRatio() {
const totalBorrows = this.getBorrowedAmount();
const totalSupply = this.getTotalSupply();
if (totalSupply.eq(0)) {
return 0;
}
return totalBorrows.dividedBy(totalSupply).toNumber();
}
getEstimatedUtilizationRatio(slot, referralFeeBps) {
const { totalBorrow: estimatedTotalBorrowed, totalSupply: estimatedTotalSupply } = this.getEstimatedDebtAndSupply(slot, referralFeeBps);
if (estimatedTotalSupply.eq(0)) {
return 0;
}
return estimatedTotalBorrowed.dividedBy(estimatedTotalSupply).toNumber();
}
calcSimulatedUtilizationRatio(amount, action, slot, referralFeeBps, outflowAmount) {
const { totalBorrow: previousTotalBorrowed, totalSupply: previousTotalSupply } = this.getEstimatedDebtAndSupply(slot, referralFeeBps);
switch (action) {
case 'deposit': {
const newTotalSupply = previousTotalSupply.add(amount);
return previousTotalBorrowed.dividedBy(newTotalSupply).toNumber();
}
case 'withdraw': {
const newTotalSupply = previousTotalSupply.sub(amount);
if (newTotalSupply.eq(0)) {
return 0;
}
else {
return previousTotalBorrowed.dividedBy(newTotalSupply).toNumber();
}
}
case 'borrow': {
const newTotalBorrowed = previousTotalBorrowed.add(amount);
return newTotalBorrowed.dividedBy(previousTotalSupply).toNumber();
}
case 'repay': {
const newTotalBorrowed = previousTotalBorrowed.sub(amount);
return newTotalBorrowed.dividedBy(previousTotalSupply).toNumber();
}
case 'depositAndBorrow': {
const newTotalSupply = previousTotalSupply.add(amount);
const newTotalBorrowed = previousTotalBorrowed.add(outflowAmount);
return newTotalBorrowed.dividedBy(newTotalSupply).toNumber();
}
case 'repayAndWithdraw': {
const newTotalBorrowed = previousTotalBorrowed.sub(amount);
const newTotalSupply = previousTotalSupply.sub(outflowAmount);
if (newTotalSupply.eq(0)) {
return 0;
}
return newTotalBorrowed.dividedBy(newTotalSupply).toNumber();
}
case 'mint': {
const newTotalSupply = previousTotalSupply.add(amount);
return previousTotalBorrowed.dividedBy(newTotalSupply).toNumber();
}
case 'redeem': {
const newTotalSupply = previousTotalSupply.sub(amount);
return previousTotalBorrowed.dividedBy(newTotalSupply).toNumber();
}
default:
throw Error(`Invalid action type ${action} for simulatedUtilizationRatio`);
}
}
getMaxBorrowAmountWithCollReserve(market, collReserve, slot) {
const groupsColl = collReserve.state.config.elevationGroups;
const groupsDebt = this.state.config.elevationGroups;
const groups = market.state.elevationGroups;
const commonElevationGroups = [...groupsColl].filter((item) => groupsDebt.includes(item) && item !== 0 && groups[item - 1].debtReserve.equals(this.address));
let eModeGroup = 0;
if (commonElevationGroups.length !== 0) {
const eModeGroupWithMaxLtvAndDebtReserve = commonElevationGroups.reduce((prev, curr) => {
const prevGroup = groups.find((group) => group.id === prev);
const currGroup = groups.find((group) => group.id === curr);
return prevGroup.ltvPct > currGroup.ltvPct ? prev : curr;
});
eModeGroup = groups.find((group) => group.id === eModeGroupWithMaxLtvAndDebtReserve).id;
}
const elevationGroupActivated = this.state.config.elevationGroups.includes(eModeGroup) && eModeGroup !== 0;
const reserveAvailableAmount = this.getLiquidityAvailableAmount();
const reserveBorrowCapRemained = this.stats.reserveBorrowLimit.sub(this.getBorrowedAmount());
let maxBorrowAmount = decimal_js_1.default.min(reserveAvailableAmount, reserveBorrowCapRemained);
const debtWithdrawalCap = this.getDebtWithdrawalCapCapacity().sub(this.getDebtWithdrawalCapCurrent(slot));
maxBorrowAmount = this.getDebtWithdrawalCapCapacity().gt(0)
? decimal_js_1.default.min(maxBorrowAmount, debtWithdrawalCap)
: maxBorrowAmount;
let originationFeeRate = this.getBorrowFee();
// Inclusive fee rate
originationFeeRate = originationFeeRate.div(originationFeeRate.add(new decimal_js_1.default(1)));
const borrowFee = maxBorrowAmount.mul(originationFeeRate);
maxBorrowAmount = maxBorrowAmount.sub(borrowFee);
const utilizationRatioLimit = this.state.config.utilizationLimitBlockBorrowingAbove / 100;
const currentUtilizationRatio = this.calculateUtilizationRatio();
if (utilizationRatioLimit > 0 && currentUtilizationRatio > utilizationRatioLimit) {
return new decimal_js_1.default(0);
}
else if (utilizationRatioLimit > 0 && currentUtilizationRatio < utilizationRatioLimit) {
const maxBorrowBasedOnUtilization = new decimal_js_1.default(utilizationRatioLimit - currentUtilizationRatio).mul(this.getTotalSupply());
maxBorrowAmount = decimal_js_1.default.min(maxBorrowAmount, maxBorrowBasedOnUtilization);
}
let borrowLimitDependentOnElevationGroup = new decimal_js_1.default(utils_1.U64_MAX);
if (!elevationGroupActivated) {
borrowLimitDependentOnElevationGroup = this.getBorrowLimitOutsideElevationGroup().sub(this.getBorrowedAmountOutsideElevationGroup());
}
else {
let maxDebtTakenAgainstCollaterals = new decimal_js_1.default(utils_1.U64_MAX);
const maxDebtAllowedAgainstCollateral = collReserve
.getBorrowLimitAgainstCollateralInElevationGroup(eModeGroup - 1)
.sub(collReserve.getBorrowedAmountAgainstCollateralInElevationGroup(eModeGroup - 1));
maxDebtTakenAgainstCollaterals = decimal_js_1.default.max(new decimal_js_1.default(0), decimal_js_1.default.min(maxDebtAllowedAgainstCollateral, maxDebtTakenAgainstCollaterals));
borrowLimitDependentOnElevationGroup = maxDebtTakenAgainstCollaterals;
}
maxBorrowAmount = decimal_js_1.default.min(maxBorrowAmount, borrowLimitDependentOnElevationGroup);
return decimal_js_1.default.max(new decimal_js_1.default(0), maxBorrowAmount);
}
calcSimulatedBorrowRate(amount, action, slot, referralFeeBps, outflowAmount) {
const slotAdjustmentFactor = this.slotAdjustmentFactor();
const newUtilization = this.calcSimulatedUtilizationRatio(amount, action, slot, referralFeeBps, outflowAmount);
const curve = truncateBorrowCurve(this.state.config.borrowRateCurve.points);
return (0, utils_2.getBorrowRate)(newUtilization, curve) * slotAdjustmentFactor;
}
calcSimulatedBorrowAPR(amount, action, slot, referralFeeBps, outflowAmount) {
return (this.calcSimulatedBorrowRate(amount, action, slot, referralFeeBps, outflowAmount) +
this.getFixedHostInterestRate().toNumber());
}
calcSimulatedSupplyAPR(amount, action, slot, referralFeeBps, outflowAmount) {
const newUtilization = this.calcSimulatedUtilizationRatio(amount, action, slot, referralFeeBps, outflowAmount);
const simulatedBorrowAPR = this.calcSimulatedBorrowRate(amount, action, slot, referralFeeBps, outflowAmount);
const protocolTakeRatePct = 1 - this.state.config.protocolTakeRatePct / 100;
return newUtilization * simulatedBorrowAPR * protocolTakeRatePct;
}
slotAdjustmentFactor() {
return 1000 / utils_1.SLOTS_PER_SECOND / this.recentSlotDurationMs;
}
calculateBorrowRate() {
const slotAdjustmentFactor = this.slotAdjustmentFactor();
const currentUtilization = this.calculateUtilizationRatio();
const curve = truncateBorrowCurve(this.state.config.borrowRateCurve.points);
return (0, utils_2.getBorrowRate)(currentUtilization, curve) * slotAdjustmentFactor;
}
calculateEstimatedBorrowRate(slot, referralFeeBps) {
const slotAdjustmentFactor = this.slotAdjustmentFactor();
const estimatedCurrentUtilization = this.getEstimatedUtilizationRatio(slot, referralFeeBps);
const curve = truncateBorrowCurve(this.state.config.borrowRateCurve.points);
return (0, utils_2.getBorrowRate)(estimatedCurrentUtilization, curve) * slotAdjustmentFactor;
}
calculateBorrowAPR(slot, referralFeeBps) {
const borrowRate = this.calculateEstimatedBorrowRate(slot, referralFeeBps);
return borrowRate + this.getFixedHostInterestRate().toNumber();
}
/**
* @returns the mint of the reserve liquidity token
*/
getLiquidityMint() {
return this.state.liquidity.mintPubkey;
}
/**
* @returns the token program of the reserve liquidity mint
*/
getLiquidityTokenProgram() {
return this.state.liquidity.tokenProgram;
}
/**
* @returns the mint of the reserve collateral token , i.e. the cToken minted for depositing the liquidity token
*/
getCTokenMint() {
return this.state.collateral.mintPubkey;
}
calculateFees(amountLamports, borrowFeeRate, feeCalculation, referralFeeBps, hasReferrer) {
const referralFeeRate = new decimal_js_1.default(referralFeeBps).div(utils_1.ONE_HUNDRED_PCT_IN_BPS);
if (borrowFeeRate.gt('0') && amountLamports.gt('0')) {
const needToAssessReferralFee = referralFeeRate.gt('0') && hasReferrer;
const minimumFee = new decimal_js_1.default('1'); // 1 token to market owner, nothing to referrer
let borrowFeeAmount;
if (feeCalculation === shared_1.FeeCalculation.Exclusive) {
borrowFeeAmount = amountLamports.mul(borrowFeeRate);
}
else {
const borrowFeeFactor = borrowFeeRate.div(borrowFeeRate.add('1'));
borrowFeeAmount = amountLamports.mul(borrowFeeFactor);
}
const borrowFee = decimal_js_1.default.max(borrowFeeAmount, minimumFee);
if (borrowFee.gte(amountLamports)) {
throw Error('Borrow amount is too small to receive liquidity after fees');
}
const referralFee = needToAssessReferralFee
? referralFeeRate.eq(1)
? borrowFee
: borrowFee.mul(referralFeeRate).floor()
: new decimal_js_1.default(0);
const protocolFee = borrowFee.sub(referralFee);
return { protocolFees: protocolFee, referrerFees: referralFee };
}
else {
return { protocolFees: new decimal_js_1.default(0), referrerFees: new decimal_js_1.default(0) };
}
}
calculateFlashLoanFees(flashLoanAmountLamports, referralFeeBps, hasReferrer) {
return this.calculateFees(flashLoanAmountLamports, this.getFlashLoanFee(), shared_1.FeeCalculation.Exclusive, referralFeeBps, hasReferrer);
}
setBuffer(buffer) {
this.buffer = buffer;
}
async load(tokenOraclePrice) {
if (!this.buffer) {
this.setBuffer(await this.connection.getAccountInfo(this.address, 'processed'));
}
if (!this.buffer) {
throw Error(`Error requesting account info for ${this.symbol}`);
}
const parsedData = await accounts_1.Reserve.fetch(this.connection, this.address);
if (!parsedData) {
throw Error(`Unable to parse data of reserve ${this.symbol}`);
}
this.state = parsedData;
this.tokenOraclePrice = tokenOraclePrice;
this.stats = this.formatReserveData(parsedData);
}
totalSupplyAPY(currentSlot) {
const { stats } = this;
if (!stats) {
throw Error('KaminoMarket must call loadRewards.');
}
return (0, utils_2.calculateAPYFromAPR)(this.calculateSupplyAPR(currentSlot, 0));
}
totalBorrowAPY(currentSlot) {
const { stats } = this;
if (!stats) {
throw Error('KaminoMarket must call loadRewards.');
}
return (0, utils_2.calculateAPYFromAPR)(this.calculateBorrowAPR(currentSlot, 0));
}
async loadFarmStates() {
if (!this.farmData.fetched) {
const farmStates = [];
if (!this.state.farmDebt.equals(web3_js_1.PublicKey.default)) {
const farmState = await farms_sdk_1.FarmState.fetch(this.connection, this.state.farmDebt);
if (farmState !== null) {
farmStates.push(farmState);
}
}
if (!this.state.farmCollateral.equals(web3_js_1.PublicKey.default)) {
const farmState = await farms_sdk_1.FarmState.fetch(this.connection, this.state.farmCollateral);
if (farmState !== null) {
farmStates.push(farmState);
}
}
this.farmData.farmStates = farmStates;
this.farmData.fetched = true;
}
}
async getRewardYields(prices) {
const { stats } = this;
if (!stats) {
throw Error('KaminoMarket must call loadReserves.');
}
const isDebtReward = this.state.farmDebt.equals(this.address);
await this.loadFarmStates();
const yields = [];
for (const farmState of this.farmData.farmStates) {
for (const rewardInfo of farmState.rewardInfos.filter((x) => !x.token.mint.equals(web3_js_1.PublicKey.default) && !x.rewardsAvailable.isZero())) {
const { apy, apr } = this.calculateRewardYield(prices, rewardInfo, isDebtReward);
if (apy.isZero() && apr.isZero()) {
continue;
}
yields.push({ apy, apr, rewardInfo });
}
}
return yields;
}
calculateRewardYield(prices, rewardInfo, isDebtReward) {
const mintAddress = this.getLiquidityMint();
const rewardPerTimeUnitSecond = this.getRewardPerTimeUnitSecond(rewardInfo);
const reserveToken = prices.spot[mintAddress.toString()];
const rewardToken = prices.spot[rewardInfo.token.mint.toString()];
if (rewardPerTimeUnitSecond.isZero() || reserveToken === undefined || rewardToken === undefined) {
return { apy: new decimal_js_1.default(0), apr: new decimal_js_1.default(0) };
}
const { decimals } = this.stats;
const totalBorrows = this.getBorrowedAmount();
const totalSupply = this.getTotalSupply();
const totalAmount = isDebtReward
? (0, utils_2.lamportsToNumberDecimal)(totalBorrows, decimals)
: (0, utils_2.lamportsToNumberDecimal)(totalSupply, decimals);
const totalValue = totalAmount.mul(reserveToken.price);
const rewardsInYear = rewardPerTimeUnitSecond.mul(60 * 60 * 24 * 365);
const rewardsInYearValue = rewardsInYear.mul(rewardToken.price);
const apr = rewardsInYearValue.div(totalValue);
return { apy: (0, kliquidity_sdk_1.aprToApy)(apr, 365), apr };
}
getRewardPerTimeUnitSecond(reward) {
const now = new decimal_js_1.default(new Date().getTime()).div(1000);
let rewardPerTimeUnitSecond = new decimal_js_1.default(0);
for (let i = 0; i < reward.rewardScheduleCurve.points.length - 1; i++) {
const { tsStart: tsStartThisPoint, rewardPerTimeUnit } = reward.rewardScheduleCurve.points[i];
const { tsStart: tsStartNextPoint } = reward.rewardScheduleCurve.points[i + 1];
const thisPeriodStart = new decimal_js_1.default(tsStartThisPoint.toString());
const thisPeriodEnd = new decimal_js_1.default(tsStartNextPoint.toString());
const rps = new decimal_js_1.default(rewardPerTimeUnit.toString());
if (thisPeriodStart <= now && thisPeriodEnd >= now) {
rewardPerTimeUnitSecond = rps;
break;
}
else if (thisPeriodStart > now && thisPeriodEnd > now) {
rewardPerTimeUnitSecond = rps;
break;
}
}
const rewardTokenDecimals = reward.token.decimals.toNumber();
const rewardAmountPerUnitDecimals = new decimal_js_1.default(10).pow(reward.rewardsPerSecondDecimals.toString());
const rewardAmountPerUnitLamports = new decimal_js_1.default(10).pow(rewardTokenDecimals.toString());
const rpsAdjusted = new decimal_js_1.default(rewardPerTimeUnitSecond.toString())
.div(rewardAmountPerUnitDecimals)
.div(rewardAmountPerUnitLamports);
return rewardPerTimeUnitSecond ? rpsAdjusted : new decimal_js_1.default(0);
}
formatReserveData(parsedData) {
const mintTotalSupply = new decimal_js_1.default(parsedData.collateral.mintTotalSupply.toString()).div(this.getMintFactor());
let reserveStatus = shared_1.ReserveStatus.Active;
switch (parsedData.config.status) {
case 0:
reserveStatus = shared_1.ReserveStatus.Active;
break;
case 1:
reserveStatus = shared_1.ReserveStatus.Obsolete;
break;
case 2:
reserveStatus = shared_1.ReserveStatus.Hidden;
break;
}
return {
// Reserve config
status: reserveStatus,
mintAddress: parsedData.liquidity.mintPubkey,
borrowCurve: truncateBorrowCurve(parsedData.config.borrowRateCurve.points),
loanToValue: parsedData.config.loanToValuePct / 100,
maxLiquidationBonus: parsedData.config.maxLiquidationBonusBps / 10000,
minLiquidationBonus: parsedData.config.minLiquidationBonusBps / 10000,
liquidationThreshold: parsedData.config.liquidationThresholdPct / 100,
protocolTakeRate: parsedData.config.protocolTakeRatePct / 100,
reserveDepositLimit: new decimal_js_1.default(parsedData.config.depositLimit.toString()),
reserveBorrowLimit: new decimal_js_1.default(parsedData.config.borrowLimit.toString()),
// Reserve info
symbol: (0, utils_2.parseTokenSymbol)(parsedData.config.tokenInfo.name),
decimals: this.state.liquidity.mintDecimals.toNumber(),
accumulatedProtocolFees: this.getAccumulatedProtocolFees().div(this.getMintFactor()),
mintTotalSupply,
depositLimitCrossedSlot: parsedData.liquidity.depositLimitCrossedSlot.toNumber(),
borrowLimitCrossedSlot: parsedData.liquidity.borrowLimitCrossedSlot.toNumber(),
borrowFactor: parsedData.config.borrowFactorPct.toNumber(),
};
}
/**
* Compound current borrow rate over elapsed slots
*
* This also calculates protocol fees, which are taken for all obligations that have borrowed from current reserve.
*
* This also calculates referral fees, which are taken into pendingReferralFees.
*
* https://github.com/Kamino-Finance/klend/blob/release/1.3.0/programs/klend/src/state/reserve.rs#L517
*
* @param slotsElapsed
* @param referralFeeBps
*/
compoundInterest(slotsElapsed, referralFeeBps) {
const currentBorrowRate = this.calculateBorrowRate();
const protocolTakeRate = new decimal_js_1.default(this.state.config.protocolTakeRatePct).div(100);
const referralRate = new decimal_js_1.default(referralFeeBps).div(10_000);
const fixedHostInterestRate = this.getFixedHostInterestRate();
const compoundedInterestRate = this.approximateCompoundedInterest(new decimal_js_1.default(currentBorrowRate).plus(fixedHostInterestRate), slotsElapsed);
const compoundedFixedRate = this.approximateCompoundedInterest(fixedHostInterestRate, slotsElapsed);
const previousDebt = this.getBorrowedAmount();
const newDebt = previousDebt.mul(compoundedInterestRate);
const fixedHostFee = previousDebt.mul(compoundedFixedRate).sub(previousDebt);
const netNewDebt = newDebt.sub(previousDebt).sub(fixedHostFee);
const variableProtocolFee = netNewDebt.mul(protocolTakeRate);
const absoluteReferralFee = protocolTakeRate.mul(referralRate);
const maxReferralFees = netNewDebt.mul(absoluteReferralFee);
const newAccProtocolFees = variableProtocolFee
.add(fixedHostFee)
.sub(maxReferralFees)
.add(this.getAccumulatedProtocolFees());
const pendingReferralFees = this.getPendingReferrerFees().add(maxReferralFees);
return {
newDebt,
netNewDebt,
variableProtocolFee,
fixedHostFee,
absoluteReferralFee,
maxReferralFees,
newAccProtocolFees,
pendingReferralFees,
};
}
/**
* Approximation to match the smart contract calculation
* https://github.com/Kamino-Finance/klend/blob/release/1.3.0/programs/klend/src/state/reserve.rs#L1026
* @param rate
* @param elapsedSlots
* @private
*/
approximateCompoundedInterest(rate, elapsedSlots) {
const base = rate.div(utils_1.SLOTS_PER_YEAR);
switch (elapsedSlots) {
case 0:
return new decimal_js_1.default(1);
case 1:
return base.add(1);
case 2:
return base.add(1).mul(base.add(1));
case 3:
return base.add(1).mul(base.add(1)).mul(base.add(1));
case 4:
// eslint-disable-next-line no-case-declarations
const pow2 = base.add(1).mul(base.add(1));
return pow2.mul(pow2);
}
const exp = elapsedSlots;
const expMinus1 = exp - 1;
const expMinus2 = exp - 2;
const basePow2 = base.mul(base);
const basePow3 = basePow2.mul(base);
const firstTerm = base.mul(exp);
const secondTerm = basePow2.mul(exp).mul(expMinus1).div(2);
const thirdTerm = basePow3.mul(exp).mul(expMinus1).mul(expMinus2).div(6);
return new decimal_js_1.default(1).add(firstTerm).add(secondTerm).add(thirdTerm);
}
getBorrowCapForReserve(market) {
// Utilization cap
const utilizationCap = this.state.config.utilizationLimitBlockBorrowingAbove;
const utilizationCurrentValue = this.calculateUtilizationRatio();
// Daily borrow cap
const withdrawalCap = this.state.config.debtWithdrawalCap;
// Debt against collaterals in elevation groups
const debtAgainstCollateralReserveCaps = market
.getMarketElevationGroupDescriptions()
.filter((x) => x.debtReserve.equals(this.address))
.map((elevationGroupDescription) => elevationGroupDescription.collateralReserves.toArray().map((collateralReserveAddress) => {
const collRes = market.reserves.get(new web3_js_1.PublicKey(collateralReserveAddress));
const debtLimitAgainstThisCollInGroup = collRes.state.config.borrowLimitAgainstThisCollateralInElevationGroup[elevationGroupDescription.elevationGroup - 1].toString();
const debtCounterAgainstThisCollInGroup = collRes.state.borrowedAmountsAgainstThisReserveInElevationGroups[elevationGroupDescription.elevationGroup - 1].toString();
return {
collateralReserve: collRes.address,
elevationGroup: elevationGroupDescription.elevationGroup,
maxDebt: new decimal_js_1.default(debtLimitAgainstThisCollInGroup),
currentValue: new decimal_js_1.default(debtCounterAgainstThisCollInGroup),
};
}))
.flat();
const caps = {
// Utilization cap
utilizationCap: new decimal_js_1.default(utilizationCap > 0 ? utilizationCap / 100 : 1),
utilizationCurrentValue: new decimal_js_1.default(utilizationCurrentValue),
// Daily borrow cap
netWithdrawalCap: new decimal_js_1.default(withdrawalCap.configCapacity.toString()),
netWithdrawalCurrentValue: new decimal_js_1.default(withdrawalCap.currentTotal.toString()),
netWithdrawalLastUpdateTs: new decimal_js_1.default(withdrawalCap.lastIntervalStartTimestamp.toString()),
netWithdrawalIntervalDurationSeconds: new decimal_js_1.default(withdrawalCap.configIntervalLengthSeconds.toString()),
// Global cap
globalDebtCap: new decimal_js_1.default(this.state.config.borrowLimit.toString()),
globalTotalBorrowed: this.getBorrowedAmount(),
// Debt outside emode cap
debtOutsideEmodeCap: new decimal_js_1.default(this.state.config.borrowLimitOutsideElevationGroup.toString()),
borrowedOutsideEmode: this.getBorrowedAmountOutsideElevationGroup(),
debtAgainstCollateralReserveCaps: debtAgainstCollateralReserveCaps,
};
return caps;
}
/* This takes into account all the caps */
getLiquidityAvailableForDebtReserveGivenCaps(market, elevationGroups, collateralReserves = []) {
const caps = this.getBorrowCapForReserve(market);
const liquidityAvailable = this.getLiquidityAvailableAmount();
// Cap this to utilization cap first
const utilizationRatioLimit = caps.utilizationCap;
const currentUtilizationRatio = this.calculateUtilizationRatio();
const liquidityGivenUtilizationCap = this.getTotalSupply().mul(utilizationRatioLimit.minus(currentUtilizationRatio));
const remainingDailyCap = caps.netWithdrawalIntervalDurationSeconds.eq(new decimal_js_1.default(0))
? new decimal_js_1.default(utils_1.U64_MAX)
: caps.netWithdrawalCap.minus(caps.netWithdrawalCurrentValue);
const remainingGlobalCap = caps.globalDebtCap.minus(caps.globalTotalBorrowed);
const remainingOutsideEmodeCap = caps.debtOutsideEmodeCap.minus(caps.borrowedOutsideEmode);
const available = elevationGroups.map((elevationGroup) => {
if (elevationGroup === 0) {
const availableInCrossMode = decimal_js_1.default.min((0, utils_2.positiveOrZero)(liquidityAvailable), (0, utils_2.positiveOrZero)(remainingOutsideEmodeCap), (0, utils_2.positiveOrZero)(remainingDailyCap), (0, utils_2.positiveOrZero)(remainingGlobalCap), (0, utils_2.positiveOrZero)(liquidityGivenUtilizationCap));
return availableInCrossMode;
}
else {
let remainingInsideEmodeCaps = new decimal_js_1.default(0);
const capsGivenEgroup = caps.debtAgainstCollateralReserveCaps.filter((x) => x.elevationGroup === elevationGroup);
if (capsGivenEgroup.length > 0) {
remainingInsideEmodeCaps = decimal_js_1.default.min(...capsGivenEgroup.map((x) => {
// check reserve is part of collReserves array
if (collateralReserves.find((collateralReserve) => collateralReserve.equals(x.collateralReserve))) {
return x.maxDebt.minus(x.currentValue);
}
else {
return new decimal_js_1.default(utils_1.U64_MAX);
}
}));
}
return decimal_js_1.default.min((0, utils_2.positiveOrZero)(liquidityAvailable), (0, utils_2.positiveOrZero)(remainingInsideEmodeCaps), (0, utils_2.positiveOrZero)(remainingDailyCap), (0, utils_2.positiveOrZero)(remainingGlobalCap), (0, utils_2.positiveOrZero)(liquidityGivenUtilizationCap));
}
});
return available;
}
}
exports.KaminoReserve = KaminoReserve;
const truncateBorrowCurve = (points) => {
const curve = [];
for (const { utilizationRateBps, borrowRateBps } of points) {
curve.push([utilizationRateBps / utils_1.ONE_HUNDRED_PCT_IN_BPS, borrowRateBps / utils_1.ONE_HUNDRED_PCT_IN_BPS]);
if (utilizationRateBps === utils_1.ONE_HUNDRED_PCT_IN_BPS) {
break;
}
}
return curve;
};
async function createReserveIxs(connection, owner, lendingMarket, liquidityMint, reserveAddress, programId) {
const size = accounts_1.Reserve.layout.span + 8;
const createReserveIx = web3_js_1.SystemProgram.createAccount({
fromPubkey: owner,
newAccountPubkey: reserveAddress,
lamports: await connection.getMinimumBalanceForRentExemption(size),
space: size,
programId: programId,
});
const { liquiditySupplyVault, collateralMint, collateralSupplyVault, feeVault } = (0, utils_1.reservePdas)(programId, lendingMarket, liquidityMint);
const [lendingMarketAuthority, _] = (0, utils_1.lendingMarketAuthPda)(lendingMarket, programId);
const accounts = {
lendingMarketOwner: owner,
lendingMarket: lendingMarket,
lendingMarketAuthority: lendingMarketAuthority,
reserve: reserveAddress,
reserveLiquidityMint: liquidityMint,
reserveLiquiditySupply: liquiditySupplyVault,
feeReceiver: feeVault,
reserveCollateralMint: collateralMint,
reserveCollateralSupply: collateralSupplyVault,
liquidityTokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
collateralTokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
systemProgram: web3_js_1.SystemProgram.programId,
rent: web3_js_1.SYSVAR_RENT_PUBKEY,
};
const initReserveIx = (0, lib_1.initReserve)(accounts, programId);
return [createReserveIx, initReserveIx];
}
function updateReserveConfigIx(marketWithAddress, reserveAddress, modeDiscriminator, value, programId) {
value;
const args = {
mode: new anchor.BN(modeDiscriminator),
value: value,
skipValidation: false,
};
const accounts = {
lendingMarketOwner: marketWithAddress.state.lendingMarketOwner,
lendingMarket: marketWithAddress.address,
reserve: reserveAddress,
};
const ix = (0, lib_1.updateReserveConfig)(args, accounts, programId);
return ix;
}
function updateEntireReserveConfigIx(marketWithAddress, reserveAddress, reserveConfig, programId) {
const layout = types_1.ReserveConfig.layout();
const data = Buffer.alloc(1000);
const len = layout.encode(reserveConfig.toEncodable(), data);
const value = Uint8Array.from([...data.subarray(0, len)]);
const args = {
mode: new anchor.BN(25),
value: value,
skipValidation: true,
};
const accounts = {
lendingMarketOwner: marketWithAddress.state.lendingMarketOwner,
lendingMarket: marketWithAddress.address,
reserve: reserveAddress,
};
const ix = (0, lib_1.updateReserveConfig)(args, accounts, programId);
return ix;
}
function parseForChangesReserveConfigAndGetIxs(marketWithAddress, reserve, reserveAddress, reserveConfig, programId) {
const updateReserveIxnsArgs = [];
for (const key in reserveConfig.toEncodable()) {
if (key === 'borrowRateCurve') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: UpdateConfigMode_1.UpdateBorrowRateCurve.discriminator,
value: updateReserveConfigEncodedValue(UpdateConfigMode_1.UpdateBorrowRateCurve.discriminator, reserveConfig.borrowRateCurve),
});
}
else {
for (let i = 0; i < reserveConfig.borrowRateCurve.points.length; i++) {
if (reserve.config.borrowRateCurve.points[i].utilizationRateBps !==
reserveConfig.borrowRateCurve.points[i].utilizationRateBps ||
reserve.config.borrowRateCurve.points[i].borrowRateBps !==
reserveConfig.borrowRateCurve.points[i].borrowRateBps) {
updateReserveIxnsArgs.push({
mode: UpdateConfigMode_1.UpdateBorrowRateCurve.discriminator,
value: updateReserveConfigEncodedValue(UpdateConfigMode_1.UpdateBorrowRateCurve.discriminator, reserveConfig.borrowRateCurve),
});
break;
}
}
}
}
else if (key === 'fees') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateFeesBorrowFee.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateFeesBorrowFee.discriminator, reserveConfig.fees.borrowFeeSf.toNumber()),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateFeesFlashLoanFee.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateFeesFlashLoanFee.discriminator, reserveConfig.fees.flashLoanFeeSf.toNumber()),
});
}
else if (!reserve.config.fees.borrowFeeSf.eq(reserveConfig.fees.borrowFeeSf)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateFeesBorrowFee.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateFeesBorrowFee.discriminator, reserveConfig.fees.borrowFeeSf.toNumber()),
});
}
else if (!reserve.config.fees.flashLoanFeeSf.eq(reserveConfig.fees.flashLoanFeeSf)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateFeesFlashLoanFee.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateFeesFlashLoanFee.discriminator, reserveConfig.fees.flashLoanFeeSf.toNumber()),
});
}
}
else if (key === 'depositLimit') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDepositLimit.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDepositLimit.discriminator, reserveConfig.depositLimit.toNumber()),
});
}
else if (!reserve.config.depositLimit.eq(reserveConfig.depositLimit)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDepositLimit.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDepositLimit.discriminator, reserveConfig.depositLimit.toNumber()),
});
}
}
else if (key === 'borrowLimit') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateBorrowLimit.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateBorrowLimit.discriminator, reserveConfig.borrowLimit.toNumber()),
});
}
else if (!reserve.config.borrowLimit.eq(reserveConfig.borrowLimit)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateBorrowLimit.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateBorrowLimit.discriminator, reserveConfig.borrowLimit.toNumber()),
});
}
}
else if (key === 'maxLiquidationBonusBps') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateMaxLiquidationBonusBps.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateMaxLiquidationBonusBps.discriminator, reserveConfig.maxLiquidationBonusBps),
});
}
else if (reserve.config.maxLiquidationBonusBps !== reserveConfig.maxLiquidationBonusBps) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateMaxLiquidationBonusBps.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateMaxLiquidationBonusBps.discriminator, reserveConfig.maxLiquidationBonusBps),
});
}
}
else if (key === 'minLiquidationBonusBps') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateMinLiquidationBonusBps.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateMinLiquidationBonusBps.discriminator, reserveConfig.minLiquidationBonusBps),
});
}
else if (reserve.config.minLiquidationBonusBps !== reserveConfig.minLiquidationBonusBps) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateMinLiquidationBonusBps.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateMinLiquidationBonusBps.discriminator, reserveConfig.minLiquidationBonusBps),
});
}
}
else if (key === 'badDebtLiquidationBonusBps') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateBadDebtLiquidationBonusBps.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateBadDebtLiquidationBonusBps.discriminator, reserveConfig.badDebtLiquidationBonusBps),
});
}
else if (reserve.config.badDebtLiquidationBonusBps !== reserveConfig.badDebtLiquidationBonusBps) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateBadDebtLiquidationBonusBps.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateBadDebtLiquidationBonusBps.discriminator, reserveConfig.badDebtLiquidationBonusBps),
});
}
}
else if (key === 'liquidationThresholdPct') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateLiquidationThresholdPct.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateLiquidationThresholdPct.discriminator, reserveConfig.liquidationThresholdPct),
});
}
else if (reserve.config.liquidationThresholdPct !== reserveConfig.liquidationThresholdPct) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateLiquidationThresholdPct.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateLiquidationThresholdPct.discriminator, reserveConfig.liquidationThresholdPct),
});
}
}
else if (key === 'protocolTakeRatePct') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateProtocolTakeRate.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateProtocolTakeRate.discriminator, reserveConfig.protocolTakeRatePct),
});
}
else if (reserve.config.protocolTakeRatePct !== reserveConfig.protocolTakeRatePct) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateProtocolTakeRate.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateProtocolTakeRate.discriminator, reserveConfig.protocolTakeRatePct),
});
}
}
else if (key === 'status') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateReserveStatus.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateReserveStatus.discriminator, reserveConfig.status),
});
}
else if (reserve.config.status !== reserveConfig.status) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateReserveStatus.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateReserveStatus.discriminator, reserveConfig.status),
});
}
}
else if (key === 'disableUsageAsCollOutsideEmode') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDisableUsageAsCollateralOutsideEmode.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDisableUsageAsCollateralOutsideEmode.discriminator, reserveConfig.disableUsageAsCollOutsideEmode),
});
}
else if (reserve.config.disableUsageAsCollOutsideEmode !== reserveConfig.disableUsageAsCollOutsideEmode) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDisableUsageAsCollateralOutsideEmode.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDisableUsageAsCollateralOutsideEmode.discriminator, reserveConfig.disableUsageAsCollOutsideEmode),
});
}
}
else if (key === 'utilizationLimitBlockBorrowingAbove') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateBlockBorrowingAboveUtilization.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateBlockBorrowingAboveUtilization.discriminator, reserveConfig.utilizationLimitBlockBorrowingAbove),
});
}
else if (reserve.config.utilizationLimitBlockBorrowingAbove !== reserveConfig.utilizationLimitBlockBorrowingAbove) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateBlockBorrowingAboveUtilization.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateBlockBorrowingAboveUtilization.discriminator, reserveConfig.utilizationLimitBlockBorrowingAbove),
});
}
}
else if (key === 'deleveragingThresholdSlotsPerBps') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.DeleveragingThresholdSlotsPerBps.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.DeleveragingThresholdSlotsPerBps.discriminator, reserveConfig.deleveragingThresholdSlotsPerBps.toNumber()),
});
}
else if (!reserve.config.deleveragingThresholdSlotsPerBps.eq(reserveConfig.deleveragingThresholdSlotsPerBps)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.DeleveragingThresholdSlotsPerBps.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.DeleveragingThresholdSlotsPerBps.discriminator, reserveConfig.deleveragingThresholdSlotsPerBps.toNumber()),
});
}
}
else if (key === 'depositWithdrawalCap') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDepositWithdrawalCap.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDepositWithdrawalCap.discriminator, [
reserveConfig.depositWithdrawalCap.configCapacity.toNumber(),
reserveConfig.depositWithdrawalCap.configIntervalLengthSeconds.toNumber(),
]),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDepositWithdrawalCapCurrentTotal.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDepositWithdrawalCap.discriminator, reserveConfig.depositWithdrawalCap.currentTotal.toNumber()),
});
}
else if (!reserve.config.depositWithdrawalCap.configCapacity.eq(reserveConfig.depositWithdrawalCap.configCapacity) ||
!reserve.config.depositWithdrawalCap.configIntervalLengthSeconds.eq(reserveConfig.depositWithdrawalCap.configIntervalLengthSeconds)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDepositWithdrawalCap.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDepositWithdrawalCap.discriminator, [
reserveConfig.depositWithdrawalCap.configCapacity.toNumber(),
reserveConfig.depositWithdrawalCap.configIntervalLengthSeconds.toNumber(),
]),
});
}
else if (!reserve.config.depositWithdrawalCap.currentTotal.eq(reserveConfig.depositWithdrawalCap.currentTotal)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDepositWithdrawalCapCurrentTotal.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDepositWithdrawalCap.discriminator, reserveConfig.depositWithdrawalCap.currentTotal.toNumber()),
});
}
}
else if (key === 'debtWithdrawalCap') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDebtWithdrawalCap.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDebtWithdrawalCap.discriminator, [
reserveConfig.debtWithdrawalCap.configCapacity.toNumber(),
reserveConfig.debtWithdrawalCap.configIntervalLengthSeconds.toNumber(),
]),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDebtWithdrawalCapCurrentTotal.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDebtWithdrawalCap.discriminator, reserveConfig.debtWithdrawalCap.currentTotal.toNumber()),
});
}
else if (!reserve.config.debtWithdrawalCap.configCapacity.eq(reserveConfig.debtWithdrawalCap.configCapacity) ||
!reserve.config.debtWithdrawalCap.configIntervalLengthSeconds.eq(reserveConfig.debtWithdrawalCap.configIntervalLengthSeconds)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDebtWithdrawalCap.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDebtWithdrawalCap.discriminator, [
reserveConfig.debtWithdrawalCap.configCapacity.toNumber(),
reserveConfig.debtWithdrawalCap.configIntervalLengthSeconds.toNumber(),
]),
});
}
else if (!reserve.config.debtWithdrawalCap.currentTotal.eq(reserveConfig.debtWithdrawalCap.currentTotal)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateDebtWithdrawalCapCurrentTotal.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateDebtWithdrawalCap.discriminator, reserveConfig.debtWithdrawalCap.currentTotal.toNumber()),
});
}
}
else if (key === 'elevationGroups') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateElevationGroup.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateElevationGroup.discriminator, reserveConfig.elevationGroups),
});
}
else {
for (let i = 0; i < reserveConfig.elevationGroups.length; i++) {
if (reserve.config.elevationGroups[i] !== reserveConfig.elevationGroups[i]) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateElevationGroup.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateElevationGroup.discriminator, reserveConfig.elevationGroups),
});
break;
}
}
}
}
else if (key === 'borrowFactorPct') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateBorrowFactor.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateBorrowFactor.discriminator, reserveConfig.borrowFactorPct.toNumber()),
});
}
else if (!reserve.config.borrowFactorPct.eq(reserveConfig.borrowFactorPct)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateBorrowFactor.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateBorrowFactor.discriminator, reserveConfig.borrowFactorPct.toNumber()),
});
}
}
else if (key === 'loanToValuePct') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateLoanToValuePct.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateLoanToValuePct.discriminator, reserveConfig.loanToValuePct),
});
}
else if (reserve.config.loanToValuePct !== reserveConfig.loanToValuePct) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateLoanToValuePct.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateLoanToValuePct.discriminator, reserveConfig.loanToValuePct),
});
}
}
else if (key === 'protocolLiquidationFeePct') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateProtocolLiquidationFee.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateProtocolLiquidationFee.discriminator, reserveConfig.protocolLiquidationFeePct),
});
}
else if (reserve.config.protocolLiquidationFeePct !== reserveConfig.protocolLiquidationFeePct) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateProtocolLiquidationFee.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateProtocolLiquidationFee.discriminator, reserveConfig.protocolLiquidationFeePct),
});
}
}
else if (key === 'deleveragingMarginCallPeriodSecs') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.DeleveragingMarginCallPeriod.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.DeleveragingMarginCallPeriod.discriminator, reserveConfig.deleveragingMarginCallPeriodSecs.toNumber()),
});
}
else if (!reserve.config.deleveragingMarginCallPeriodSecs.eq(reserveConfig.deleveragingMarginCallPeriodSecs)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.DeleveragingMarginCallPeriod.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.DeleveragingMarginCallPeriod.discriminator, reserveConfig.deleveragingMarginCallPeriodSecs.toNumber()),
});
}
}
else if (key === 'assetTier') {
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateAssetTier.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateAssetTier.discriminator, reserveConfig.assetTier),
});
}
else if (reserve.config.assetTier !== reserveConfig.assetTier) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateAssetTier.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateAssetTier.discriminator, reserveConfig.assetTier),
});
}
}
else if (key === 'tokenInfo') {
const tokenInfo = reserveConfig.tokenInfo;
if (reserve === undefined) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoName.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoName.discriminator, tokenInfo.name),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoLowerHeuristic.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoLowerHeuristic.discriminator, tokenInfo.heuristic.lower.toNumber()),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoUpperHeuristic.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoUpperHeuristic.discriminator, tokenInfo.heuristic.upper.toNumber()),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoExpHeuristic.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoExpHeuristic.discriminator, tokenInfo.heuristic.exp.toNumber()),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoTwapDivergence.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoTwapDivergence.discriminator, tokenInfo.maxTwapDivergenceBps.toNumber()),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoPriceMaxAge.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoPriceMaxAge.discriminator, tokenInfo.maxAgePriceSeconds.toNumber()),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoTwapMaxAge.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoTwapMaxAge.discriminator, tokenInfo.maxAgeTwapSeconds.toNumber()),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoScopeChain.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoScopeChain.discriminator, tokenInfo.scopeConfiguration.priceChain),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoScopeTwap.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoScopeTwap.discriminator, tokenInfo.scopeConfiguration.twapChain),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateSwitchboardFeed.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateSwitchboardFeed.discriminator, tokenInfo.switchboardConfiguration.priceAggregator),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateSwitchboardTwapFeed.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateSwitchboardTwapFeed.discriminator, tokenInfo.switchboardConfiguration.twapAggregator),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdatePythPrice.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdatePythPrice.discriminator, tokenInfo.pythConfiguration.price),
});
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateBlockPriceUsage.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateBlockPriceUsage.discriminator, tokenInfo.blockPriceUsage),
});
}
else {
if (!(0, utils_2.sameLengthArrayEquals)(reserve.config.tokenInfo.name, tokenInfo.name)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoName.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoName.discriminator, tokenInfo.name),
});
}
if (!reserve.config.tokenInfo.heuristic.lower.eq(tokenInfo.heuristic.lower)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoLowerHeuristic.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoLowerHeuristic.discriminator, tokenInfo.heuristic.lower.toNumber()),
});
}
if (!reserve.config.tokenInfo.heuristic.upper.eq(tokenInfo.heuristic.upper)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoUpperHeuristic.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoUpperHeuristic.discriminator, tokenInfo.heuristic.upper.toNumber()),
});
}
if (!reserve.config.tokenInfo.heuristic.exp.eq(tokenInfo.heuristic.exp)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoExpHeuristic.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoExpHeuristic.discriminator, tokenInfo.heuristic.exp.toNumber()),
});
}
if (!reserve.config.tokenInfo.maxTwapDivergenceBps.eq(tokenInfo.maxTwapDivergenceBps)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoTwapDivergence.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoTwapDivergence.discriminator, tokenInfo.maxTwapDivergenceBps.toNumber()),
});
}
if (!reserve.config.tokenInfo.maxAgePriceSeconds.eq(tokenInfo.maxAgePriceSeconds)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoPriceMaxAge.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoPriceMaxAge.discriminator, tokenInfo.maxAgePriceSeconds.toNumber()),
});
}
if (!reserve.config.tokenInfo.maxAgeTwapSeconds.eq(tokenInfo.maxAgeTwapSeconds)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoTwapMaxAge.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoTwapMaxAge.discriminator, tokenInfo.maxAgeTwapSeconds.toNumber()),
});
}
if (!(0, utils_2.sameLengthArrayEquals)(reserve.config.tokenInfo.scopeConfiguration.priceChain, tokenInfo.scopeConfiguration.priceChain)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoScopeChain.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoScopeChain.discriminator, tokenInfo.scopeConfiguration.priceChain),
});
}
if (!(0, utils_2.sameLengthArrayEquals)(reserve.config.tokenInfo.scopeConfiguration.twapChain, tokenInfo.scopeConfiguration.twapChain)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateTokenInfoScopeTwap.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateTokenInfoScopeTwap.discriminator, tokenInfo.scopeConfiguration.twapChain),
});
}
if (!reserve.config.tokenInfo.switchboardConfiguration.priceAggregator.equals(tokenInfo.switchboardConfiguration.priceAggregator)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateSwitchboardFeed.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateSwitchboardFeed.discriminator, tokenInfo.switchboardConfiguration.priceAggregator),
});
}
if (!reserve.config.tokenInfo.switchboardConfiguration.twapAggregator.equals(tokenInfo.switchboardConfiguration.twapAggregator)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateSwitchboardTwapFeed.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateSwitchboardTwapFeed.discriminator, tokenInfo.switchboardConfiguration.twapAggregator),
});
}
if (!reserve.config.tokenInfo.pythConfiguration.price.equals(tokenInfo.pythConfiguration.price)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdatePythPrice.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdatePythPrice.discriminator, tokenInfo.pythConfiguration.price),
});
}
if (reserve.config.tokenInfo.blockPriceUsage !== tokenInfo.blockPriceUsage) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateBlockPriceUsage.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateBlockPriceUsage.discriminator, tokenInfo.blockPriceUsage),
});
}
if (!reserve.config.tokenInfo.scopeConfiguration.priceFeed.equals(tokenInfo.scopeConfiguration.priceFeed)) {
updateReserveIxnsArgs.push({
mode: types_1.UpdateConfigMode.UpdateScopePriceFeed.discriminator,
value: updateReserveConfigEncodedValue(types_1.UpdateConfigMode.UpdateScopePriceFeed.discriminator, tokenInfo.scopeConfiguration.priceFeed),
});
}
}
}
} // for loop
const ixns = [];
updateReserveIxnsArgs.forEach((updateReserveConfigArgs) => {
ixns.push(updateReserveConfigIx(marketWithAddress, reserveAddress, updateReserveConfigArgs.mode + 1, updateReserveConfigArgs.value, programId));
});
return ixns;
}
function updateReserveConfigEncodedValue(discriminator, value) {
let buffer;
let valueArray = [];
switch (discriminator) {
case types_1.UpdateConfigMode.UpdateLoanToValuePct.discriminator:
case types_1.UpdateConfigMode.UpdateLiquidationThresholdPct.discriminator:
case types_1.UpdateConfigMode.UpdateProtocolLiquidationFee.discriminator:
case types_1.UpdateConfigMode.UpdateProtocolTakeRate.discriminator:
case types_1.UpdateConfigMode.UpdateAssetTier.discriminator:
case types_1.UpdateConfigMode.UpdateReserveStatus.discriminator:
case types_1.UpdateConfigMode.UpdateDisableUsageAsCollateralOutsideEmode.discriminator:
case types_1.UpdateConfigMode.UpdateBlockBorrowingAboveUtilization.discriminator:
case types_1.UpdateConfigMode.UpdateBlockPriceUsage.discriminator:
buffer = Buffer.alloc(1);
buffer.writeUIntLE(value, 0, 1);
break;
case types_1.UpdateConfigMode.UpdateMaxLiquidationBonusBps.discriminator:
case types_1.UpdateConfigMode.UpdateBadDebtLiquidationBonusBps.discriminator:
case types_1.UpdateConfigMode.UpdateMinLiquidationBonusBps.discriminator:
buffer = Buffer.alloc(2);
buffer.writeUInt16LE(value, 0);
break;
case types_1.UpdateConfigMode.UpdateFeesBorrowFee.discriminator:
case types_1.UpdateConfigMode.UpdateFeesFlashLoanFee.discriminator:
case types_1.UpdateConfigMode.UpdateDepositLimit.discriminator:
case types_1.UpdateConfigMode.UpdateBorrowLimit.discriminator:
case types_1.UpdateConfigMode.UpdateTokenInfoLowerHeuristic.discriminator:
case types_1.UpdateConfigMode.UpdateTokenInfoUpperHeuristic.discriminator:
case types_1.UpdateConfigMode.UpdateTokenInfoExpHeuristic.discriminator:
case types_1.UpdateConfigMode.UpdateTokenInfoTwapDivergence.discriminator:
case types_1.UpdateConfigMode.UpdateTokenInfoPriceMaxAge.discriminator:
case types_1.UpdateConfigMode.UpdateTokenInfoTwapMaxAge.discriminator:
case types_1.UpdateConfigMode.UpdateDebtWithdrawalCapCurrentTotal.discriminator:
case types_1.UpdateConfigMode.UpdateDepositWithdrawalCapCurrentTotal.discriminator:
case types_1.UpdateConfigMode.DeleveragingMarginCallPeriod.discriminator:
case types_1.UpdateConfigMode.UpdateBorrowFactor.discriminator:
case types_1.UpdateConfigMode.DeleveragingThresholdSlotsPerBps.discriminator:
case types_1.UpdateConfigMode.UpdateBorrowLimitOutsideElevationGroup.discriminator:
value = value;
buffer = Buffer.alloc(8);
buffer.writeBigUint64LE(BigInt(value), 0);
break;
case types_1.UpdateConfigMode.UpdateTokenInfoScopeChain.discriminator:
case types_1.UpdateConfigMode.UpdateTokenInfoScopeTwap.discriminator:
valueArray = value;
buffer = Buffer.alloc(8);
for (let i = 0; i < valueArray.length; i++) {
buffer.writeUInt16LE(valueArray[i], 2 * i);
}
break;
case types_1.UpdateConfigMode.UpdateTokenInfoName.discriminator:
valueArray = value;
buffer = Buffer.alloc(32);
for (let i = 0; i < valueArray.length; i++) {
buffer.writeUIntLE(valueArray[i], i, 1);
}
break;
case types_1.UpdateConfigMode.UpdateScopePriceFeed.discriminator:
case types_1.UpdateConfigMode.UpdatePythPrice.discriminator:
case types_1.UpdateConfigMode.UpdateSwitchboardFeed.discriminator:
case types_1.UpdateConfigMode.UpdateSwitchboardTwapFeed.discriminator:
case types_1.UpdateConfigMode.UpdateFarmCollateral.discriminator:
case types_1.UpdateConfigMode.UpdateFarmDebt.discriminator:
buffer = value.toBuffer();
break;
case types_1.UpdateConfigMode.UpdateBorrowRateCurve.discriminator:
buffer = serializeBorrowRateCurve(value);
break;
case types_1.UpdateConfigMode.UpdateDebtWithdrawalCap.discriminator:
case types_1.UpdateConfigMode.UpdateDepositWithdrawalCap.discriminator:
valueArray = value;
buffer = Buffer.alloc(16);
buffer.writeBigUint64LE(BigInt(valueArray[0]), 0);
buffer.writeBigUInt64LE(BigInt(valueArray[1]), 8);
break;
case types_1.UpdateConfigMode.UpdateElevationGroup.discriminator:
valueArray = value;
buffer = Buffer.alloc(20);
for (let i = 0; i < valueArray.length; i++) {
buffer.writeUIntLE(valueArray[i], i, 1);
}
break;
case types_1.UpdateConfigMode.UpdateBorrowLimitsInElevationGroupAgainstThisReserve.discriminator:
valueArray = value;
buffer = Buffer.alloc(32 * 8);
for (let i = 0; i < valueArray.length; i++) {
buffer.writeBigUint64LE(BigInt(valueArray[i]), i * 8);
}
break;
default:
buffer = Buffer.alloc(0);
}
return Uint8Array.from([...buffer]);
}
function serializeBorrowRateCurve(curve) {
const buffer = Buffer.alloc(4 + 8 * curve.points.length);
buffer.writeUInt32LE(curve.points.length, 0);
for (let i = 0; i < curve.points.length; i++) {
buffer.writeUInt32LE(curve.points[i].utilizationRateBps, 4 + 8 * i);
buffer.writeUInt32LE(curve.points[i].borrowRateBps, 8 + 8 * i);
}
return buffer;
}
//# sourceMappingURL=reserve.js.map