fbonds-core
Version:
Banx protocol sdk
173 lines (172 loc) • 8.89 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.calcOptimisticBasedOnBulkSimulation = exports.optimisticUpdateBondOfferBonding = exports.calculateLenderPartialPartFromBorrowerBN = exports.calculateLenderPartialPartFromBorrower = exports.getLendingTokenType = exports.optimisticInitializeBondOfferBonding = exports.calculateNextSpotPriceBN = exports.calculateNextSpotPrice = void 0;
const constants_1 = require("../../../constants");
const types_1 = require("../../../types");
const helpers_1 = require("./helpers");
const anchor_1 = require("@coral-xyz/anchor");
const lodash_1 = require("lodash");
const calculateNextSpotPrice = ({ spotPrice, delta, bondingCurveType, counter, }) => {
if (bondingCurveType === types_1.BondingCurveType.Linear || bondingCurveType === types_1.BondingCurveType.LinearUsdc || bondingCurveType === types_1.BondingCurveType.LinearBanxSol) {
let current_price = spotPrice; // 1
const targetCounter = counter + -1;
if (targetCounter >= 0) {
// 0
for (let i = 0; i < Math.abs(targetCounter); i++) {
current_price += delta;
}
}
else {
for (let i = 0; i < Math.abs(targetCounter); i++) {
current_price -= delta;
}
}
return current_price;
}
else if (bondingCurveType === types_1.BondingCurveType.Exponential) {
const newCounter = counter - 1;
let newDelta = newCounter > 0 ? (delta + 1e4) / 1e4 : 1 / ((delta + 1e4) / 1e4);
return spotPrice * Math.pow(newDelta, Math.abs(newCounter));
}
else {
return 0;
}
};
exports.calculateNextSpotPrice = calculateNextSpotPrice;
const calculateNextSpotPriceBN = ({ spotPrice, delta, bondingCurveType, counter, }) => {
if (bondingCurveType === types_1.BondingCurveType.Linear || bondingCurveType === types_1.BondingCurveType.LinearUsdc || bondingCurveType === types_1.BondingCurveType.LinearBanxSol) {
let current_price = spotPrice; // 1
const targetCounter = counter.sub(new anchor_1.BN(1));
if (targetCounter >= new anchor_1.BN(0)) {
// 0
for (let i = 0; new anchor_1.BN(i) < targetCounter.abs(); i++) {
current_price = current_price.add(delta);
}
}
else {
for (let i = 0; new anchor_1.BN(i) < targetCounter.abs(); i++) {
current_price = current_price.sub(delta);
}
}
return current_price;
}
else if (bondingCurveType === types_1.BondingCurveType.Exponential) {
const newCounter = counter.sub(new anchor_1.BN(1));
let newDelta = newCounter > new anchor_1.BN(0) ? (delta.add(new anchor_1.BN(1e4))).div(new anchor_1.BN(1e4)) : new anchor_1.BN(1).div((delta.add(new anchor_1.BN(1e4))).div(new anchor_1.BN(1e4)));
return spotPrice.mul(newDelta.pow(newCounter.abs()));
}
else {
return new anchor_1.BN(0);
}
};
exports.calculateNextSpotPriceBN = calculateNextSpotPriceBN;
const optimisticInitializeBondOfferBonding = (args) => ({
hadoMarket: args.hadoMarket,
pairState: types_1.PairState.PerpetualBondingCurveOnMarket,
bondingCurve: { delta: new anchor_1.BN(0), bondingType: args.bondingType },
baseSpotPrice: new anchor_1.BN(0),
mathCounter: new anchor_1.BN(0),
currentSpotPrice: new anchor_1.BN(0),
concentrationIndex: new anchor_1.BN(0),
bidCap: new anchor_1.BN(0),
bidSettlement: new anchor_1.BN(0),
edgeSettlement: new anchor_1.BN(0),
fundsSolOrTokenBalance: new anchor_1.BN(0),
buyOrdersQuantity: new anchor_1.BN(0),
lastTransactedAt: new anchor_1.BN((0, helpers_1.nowInSeconds)()),
assetReceiver: args.assetReceiver,
validation: {
loanToValueFilter: new anchor_1.BN(0),
collateralsPerToken: new anchor_1.BN(0),
maxReturnAmountFilter: new anchor_1.BN(0),
bondFeatures: args.isSplFeature ? types_1.BondFeatures.AutoReceiveAndReceiveSpl : types_1.BondFeatures.AutoReceiveAndReceiveNft,
},
publicKey: args.bondOffer,
loanApr: new anchor_1.BN(0),
liquidationLtvBp: new anchor_1.BN(0),
offerLtvBp: new anchor_1.BN(0)
});
exports.optimisticInitializeBondOfferBonding = optimisticInitializeBondOfferBonding;
const getLendingTokenType = (bondingCurveType) => {
let lendingTokenType = types_1.LendingTokenType.NativeSol;
switch (bondingCurveType) {
case types_1.BondingCurveType.Linear || types_1.BondingCurveType.Exponential: {
lendingTokenType = types_1.LendingTokenType.BanxSol;
break;
}
case types_1.BondingCurveType.LinearUsdc || types_1.BondingCurveType.ExponentialUsdc: {
lendingTokenType = types_1.LendingTokenType.Usdc;
break;
}
case types_1.BondingCurveType.LinearBanxSol || types_1.BondingCurveType.ExponentialBanxSol: {
lendingTokenType = types_1.LendingTokenType.BanxSol;
break;
}
}
;
return lendingTokenType;
};
exports.getLendingTokenType = getLendingTokenType;
const calculateLenderPartialPartFromBorrower = (args) => {
const loanTime = (0, helpers_1.nowInSeconds)() - args.soldAt;
const partOfYear = loanTime / constants_1.SECONDS_IN_YEAR;
const partOfLoan = args.borrowerPart / (1 + (args.lenderApr + args.protocolRepayFeeApr) * partOfYear / constants_1.BASE_POINTS);
const pureInterest = (0, helpers_1.calculateCurrentInterestSolPure)({
loanValue: partOfLoan,
startTime: args.soldAt,
currentTime: (0, helpers_1.nowInSeconds)(),
rateBasePoints: args.lenderApr,
});
return partOfLoan + pureInterest;
};
exports.calculateLenderPartialPartFromBorrower = calculateLenderPartialPartFromBorrower;
const calculateLenderPartialPartFromBorrowerBN = (args) => {
const loanTime = new anchor_1.BN((0, helpers_1.nowInSeconds)()).sub(args.soldAt);
const partOfYear = loanTime.div(new anchor_1.BN(constants_1.SECONDS_IN_YEAR));
const partOfLoan = args.borrowerPart.div(new anchor_1.BN(1).add((args.lenderApr.add(args.protocolRepayFeeApr)).mul(partOfYear).div(new anchor_1.BN(constants_1.BASE_POINTS))));
const pureInterest = (0, helpers_1.calculateCurrentInterestSolPureBN)({
loanValue: partOfLoan,
startTime: args.soldAt,
currentTime: new anchor_1.BN((0, helpers_1.nowInSeconds)()),
rateBasePoints: args.lenderApr,
});
return partOfLoan.add(pureInterest);
};
exports.calculateLenderPartialPartFromBorrowerBN = calculateLenderPartialPartFromBorrowerBN;
const optimisticUpdateBondOfferBonding = ({ bondOffer, newLoanValue, newQuantityOfLoans, collateralsPerToken, tokenLendingApr, }) => {
const newBaseSpotPrice = newLoanValue;
const newBuyOrdersSize = newLoanValue.mul(newQuantityOfLoans);
return Object.assign(Object.assign({}, bondOffer), { fundsSolOrTokenBalance: newBuyOrdersSize, baseSpotPrice: newBaseSpotPrice, bondingCurve: { delta: constants_1.ZERO_BN, bondingType: bondOffer.bondingCurve.bondingType }, currentSpotPrice: newLoanValue, buyOrdersQuantity: newQuantityOfLoans, bidSettlement: constants_1.ZERO_BN, bidCap: constants_1.ZERO_BN, validation: Object.assign(Object.assign({}, bondOffer.validation), { collateralsPerToken: collateralsPerToken, loanToValueFilter: newLoanValue }), loanApr: tokenLendingApr, lastTransactedAt: new anchor_1.BN((0, helpers_1.nowInSeconds)()) });
};
exports.optimisticUpdateBondOfferBonding = optimisticUpdateBondOfferBonding;
const calcObjectsDiff = (objectA, objectB, ignoreFields, diffMethod = 'sub') => {
return (0, lodash_1.chain)(objectA)
.toPairs()
.map(([fieldName, fieldValue]) => {
if (ignoreFields.includes(fieldName)) {
return [fieldName, objectB[fieldName]];
}
if (anchor_1.BN.isBN(fieldValue)) {
if (diffMethod === 'add') {
return [fieldName, fieldValue.add(objectB[fieldName])];
}
return [fieldName, fieldValue.sub(objectB[fieldName])];
}
if ((0, lodash_1.isObject)(fieldValue)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return calcObjectsDiff(fieldValue, objectB[fieldName], ignoreFields, diffMethod);
}
return [fieldName, objectB[fieldName]];
})
.fromPairs()
.value();
};
const calcOptimisticBasedOnBulkSimulation = (account, simulatedAccounts, ignoreFields = []) => {
const diffs = simulatedAccounts.map((simulatedAccount) => calcObjectsDiff(account, simulatedAccount, ignoreFields, 'sub'));
return (0, lodash_1.chain)(diffs)
.reduce((acc, diff) => {
return calcObjectsDiff(acc, diff, ignoreFields, 'sub');
}, account)
.value();
};
exports.calcOptimisticBasedOnBulkSimulation = calcOptimisticBasedOnBulkSimulation;