fbonds-core
Version:
Banx protocol sdk
496 lines (495 loc) • 22.2 kB
JavaScript
;
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.calcRepayFeeAprFromBondTradeTransaction = exports.calcLenderTokenApr = exports.calcBorrowerTokenAPR = exports.getUpfrontFeeFromHadomarket = exports.sortCompareBN = exports.calculatePriorityFees = exports.getMaxLoanValueFromBondOfferBN = exports.mapProof = exports.findRuleSetPDA = exports.findTokenRecordPda = exports.getRuleset = exports.getMetaplexMetadata = exports.calculatePricesArray = exports.calculateNextSpotPrice = exports.calculateNextSpotPriceBN = exports.enumToAnchorEnum = exports.nowInSeconds = exports.enumToAnchorEnumNew = exports.createDecodeEnum = exports.getMetaplexMetadataPda = exports.getMetaplexEditionPda = exports.anchorRawBNsAndPubkeysToNumsAndStringsWithType = exports.anchorRawBNsAndPubkeysToNumsAndStrings = exports.returnAnchorProgramSanctum = exports.returnAnchorProgram = exports.ParseType = void 0;
exports.getAsset = getAsset;
exports.getTreeCanopyDepth = getTreeCanopyDepth;
exports.getAssetProof = getAssetProof;
exports.decode64 = decode64;
exports.decode = decode;
exports.bufferToArray = bufferToArray;
const common_1 = require("../common");
const SanctumIDL = __importStar(require("./../idls/s_controller.json"));
const constants_1 = require("./constants");
const governance_1 = require("./functions/governance");
const types_1 = require("./types");
const anchor_1 = require("@coral-xyz/anchor");
const anchor = __importStar(require("@coral-xyz/anchor"));
const anchor_2 = require("@coral-xyz/anchor");
const bytes_1 = require("@coral-xyz/anchor/dist/cjs/utils/bytes");
const mpl_token_metadata_1 = require("@metaplex-foundation/mpl-token-metadata");
const spl_account_compression_1 = require("@solana/spl-account-compression");
const axios_1 = __importDefault(require("axios"));
const bs58 = __importStar(require("bs58"));
const lodash_1 = require("lodash");
var ParseType;
(function (ParseType) {
ParseType["Number"] = "number";
ParseType["String"] = "string";
})(ParseType || (exports.ParseType = ParseType = {}));
const returnAnchorProgram = (connection) => {
return new anchor_1.Program(constants_1.IDL, new anchor_1.AnchorProvider(connection, (0, common_1.createFakeWallet)()));
};
exports.returnAnchorProgram = returnAnchorProgram;
const returnAnchorProgramSanctum = (programId, connection) => new anchor_1.Program(SanctumIDL, new anchor.AnchorProvider(connection, (0, common_1.createFakeWallet)(), anchor.AnchorProvider.defaultOptions()));
exports.returnAnchorProgramSanctum = returnAnchorProgramSanctum;
const anchorRawBNsAndPubkeysToNumsAndStrings = (rawAccount) => {
const copyRawAccount = Object.assign({}, rawAccount);
const newAccount = parseRawAccount(rawAccount.account);
return Object.assign(Object.assign({}, newAccount), { publicKey: new anchor.web3.PublicKey(copyRawAccount.publicKey) });
};
exports.anchorRawBNsAndPubkeysToNumsAndStrings = anchorRawBNsAndPubkeysToNumsAndStrings;
const anchorRawBNsAndPubkeysToNumsAndStringsWithType = (rawAccount, parseType) => {
const copyRawAccount = Object.assign({}, rawAccount);
const newAccount = parseRawAccountWithType(rawAccount.account, parseType);
return Object.assign(Object.assign({}, newAccount), { publicKey: copyRawAccount.publicKey.toString() });
};
exports.anchorRawBNsAndPubkeysToNumsAndStringsWithType = anchorRawBNsAndPubkeysToNumsAndStringsWithType;
const parseRawAccount = (rawAccount) => {
const copyRawAccount = Object.assign({}, rawAccount);
for (const key in copyRawAccount) {
if (copyRawAccount[key] === null || copyRawAccount[key] === undefined)
continue;
if (key === 'roundValue') {
copyRawAccount[key] = copyRawAccount[key].toString();
continue;
}
if (key === 'creatorHash') {
copyRawAccount[key] = bs58.encode(copyRawAccount[key]);
continue;
}
if (key === 'name') {
copyRawAccount[key] = (0, governance_1.decodeProposalName)(copyRawAccount[key]);
continue;
}
if (copyRawAccount[key].toBase58) {
copyRawAccount[key] = new anchor.web3.PublicKey(copyRawAccount[key].toBase58());
continue;
}
if (copyRawAccount[key].toNumber) {
try {
if (anchor_2.BN.isBN(copyRawAccount[key])) {
copyRawAccount[key] = new anchor_2.BN(copyRawAccount[key]);
continue;
}
else {
copyRawAccount[key] = copyRawAccount[key].toNumber();
}
}
catch (err) {
copyRawAccount[key] = 0;
}
}
if (typeof copyRawAccount[key] === 'object' && Object.keys(copyRawAccount[key]).length === 1) {
copyRawAccount[key] = Object.keys(copyRawAccount[key])[0];
}
else if (typeof copyRawAccount[key] === 'object') {
copyRawAccount[key] = parseRawAccount(copyRawAccount[key]);
}
}
return copyRawAccount;
};
const parseRawAccountWithType = (rawAccount, parseType) => {
const copyRawAccount = Object.assign({}, rawAccount);
for (const key in copyRawAccount) {
if (copyRawAccount[key] === null || copyRawAccount[key] === undefined)
continue;
if (key === 'roundValue') {
copyRawAccount[key] = copyRawAccount[key].toString();
continue;
}
if (key === 'creatorHash') {
copyRawAccount[key] = bs58.encode(copyRawAccount[key]);
continue;
}
if (parseType == ParseType.String &&
key != 'adventureSubscriptionState' &&
key != 'adventureState' &&
key != 'banxStakingSettingsState' &&
key != 'banxStakeState') {
copyRawAccount[key] = copyRawAccount[key].toString();
}
if (parseType == ParseType.Number) {
if (copyRawAccount[key].toNumber) {
try {
copyRawAccount[key] = copyRawAccount[key].toNumber();
}
catch (err) {
copyRawAccount[key] = 0;
}
}
}
if (copyRawAccount[key].toBase58) {
copyRawAccount[key] = copyRawAccount[key].toBase58();
}
if (typeof copyRawAccount[key] === 'object' && Object.keys(copyRawAccount[key]).length === 1) {
copyRawAccount[key] = Object.keys(copyRawAccount[key])[0];
}
else if (typeof copyRawAccount[key] === 'object') {
copyRawAccount[key] = parseRawAccount(copyRawAccount[key]);
}
}
return copyRawAccount;
};
const getMetaplexEditionPda = (mintPubkey) => {
const editionPda = anchor.web3.PublicKey.findProgramAddressSync([
Buffer.from(constants_1.METADATA_PREFIX),
constants_1.METADATA_PROGRAM_PUBKEY.toBuffer(),
new anchor.web3.PublicKey(mintPubkey).toBuffer(),
Buffer.from(constants_1.EDITION_PREFIX),
], constants_1.METADATA_PROGRAM_PUBKEY);
return editionPda[0];
};
exports.getMetaplexEditionPda = getMetaplexEditionPda;
const getMetaplexMetadataPda = (mintPubkey) => {
const metaPda = anchor.web3.PublicKey.findProgramAddress([
Buffer.from(constants_1.METADATA_PREFIX),
constants_1.METADATA_PROGRAM_PUBKEY.toBuffer(),
new anchor.web3.PublicKey(mintPubkey).toBuffer(),
], constants_1.METADATA_PROGRAM_PUBKEY);
return metaPda[0];
};
exports.getMetaplexMetadataPda = getMetaplexMetadataPda;
// Универсальная функция для создания DecodeEnum
const createDecodeEnum = (enumValue, decodedEnumType) => {
return { [enumValue]: undefined };
};
exports.createDecodeEnum = createDecodeEnum;
const enumToAnchorEnumNew = (enumValue, enumObject) => {
return { [enumValue]: {} };
};
exports.enumToAnchorEnumNew = enumToAnchorEnumNew;
const nowInSeconds = () => Math.floor((0, lodash_1.now)() / 1000);
exports.nowInSeconds = nowInSeconds;
const enumToAnchorEnum = (anyEnum) => ({ [anyEnum.toString()]: {} });
exports.enumToAnchorEnum = enumToAnchorEnum;
const calculateNextSpotPriceBN = ({ orderType, 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.add(orderType === types_1.OrderType.Buy ? new anchor_2.BN(1) : new anchor_2.BN(-1));
if (targetCounter >= new anchor_2.BN(0)) {
// 0
for (let i = 0; new anchor_2.BN(i) < targetCounter.abs(); i++) {
current_price = current_price.add(delta);
}
}
else {
for (let i = 0; new anchor_2.BN(i) < targetCounter.abs(); i++) {
current_price = current_price.sub(delta);
}
}
return current_price;
}
else if (bondingCurveType === types_1.BondingCurveType.Exponential ||
bondingCurveType === types_1.BondingCurveType.ExponentialUsdc) {
const newCounter = orderType === types_1.OrderType.Buy ? counter.add(new anchor_2.BN(1)) : counter.sub(new anchor_2.BN(1));
const newDelta = newCounter > new anchor_2.BN(0)
? delta.add(new anchor_2.BN(1e4)).div(new anchor_2.BN(1e4))
: new anchor_2.BN(1).div(delta.add(new anchor_2.BN(1e4)).div(new anchor_2.BN(1e4)));
return spotPrice.mul(newDelta.pow(newCounter.abs()));
}
return new anchor_2.BN(0);
};
exports.calculateNextSpotPriceBN = calculateNextSpotPriceBN;
const calculateNextSpotPrice = ({ orderType, 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 + (orderType === types_1.OrderType.Buy ? 1 : -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 ||
bondingCurveType === types_1.BondingCurveType.ExponentialUsdc) {
const newCounter = orderType === types_1.OrderType.Buy ? counter + 1 : counter - 1;
const newDelta = newCounter > 0 ? (delta + 1e4) / 1e4 : 1 / ((delta + 1e4) / 1e4);
return spotPrice * Math.pow(newDelta, Math.abs(newCounter));
}
return 0;
};
exports.calculateNextSpotPrice = calculateNextSpotPrice;
// if quantity_of_orders == 0 {
// return 0;
// }
// counter = counter.checked_add(1).unwrap();
// let mut starting_spot_price = spot_price; // 1
// let mut next_smallest_buy_order_price = spot_price; //1
// let mut sum: u64 = 0; //1
// for _ in 0..(quantity_of_orders) {
// next_smallest_buy_order_price = BondingCurve::calculate_next_spot_price(
// bonding_type,
// delta,
// starting_spot_price,
// false,
// counter,
// );
// sum = sum.checked_add(next_smallest_buy_order_price).unwrap();
// counter = counter.checked_sub(1).unwrap();
// }
// sum
const calculatePricesArray = ({ starting_spot_price, delta, amount, bondingCurveType, orderType, counter, }) => {
const array = [];
let newCounter = orderType === types_1.OrderType.Sell ? counter + 1 : counter;
for (let i = 0; i < amount; i++) {
const next_price = (0, exports.calculateNextSpotPrice)({
orderType,
delta,
bondingCurveType,
spotPrice: starting_spot_price,
counter: newCounter,
});
array.push(next_price);
newCounter = orderType === types_1.OrderType.Buy ? newCounter + 1 : newCounter - 1;
}
const total = array.reduce((acc, price) => acc + price, 0);
return { array, total };
};
exports.calculatePricesArray = calculatePricesArray;
const getMetaplexMetadata = (mintPubkey) => {
const [metadata] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from(constants_1.METADATA_PREFIX), constants_1.METADATA_PROGRAM_PUBKEY.toBuffer(), mintPubkey.toBuffer()], constants_1.METADATA_PROGRAM_PUBKEY);
return metadata;
};
exports.getMetaplexMetadata = getMetaplexMetadata;
const getRuleset = (mintPubkey, connection) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b;
try {
const nftMetadata = (0, exports.getMetaplexMetadata)(new anchor.web3.PublicKey(mintPubkey));
const meta = yield mpl_token_metadata_1.Metadata.fromAccountAddress(connection, nftMetadata);
return (_b = (_a = meta.programmableConfig) === null || _a === void 0 ? void 0 : _a.ruleSet) !== null && _b !== void 0 ? _b : undefined;
}
catch (_c) {
return undefined;
}
});
exports.getRuleset = getRuleset;
const findTokenRecordPda = (mint, token) => {
return anchor.web3.PublicKey.findProgramAddressSync([
Buffer.from(constants_1.METADATA_PREFIX),
constants_1.METADATA_PROGRAM_PUBKEY.toBuffer(),
mint.toBuffer(),
Buffer.from(constants_1.TOKEN_RECORD),
token.toBuffer(),
], constants_1.METADATA_PROGRAM_PUBKEY)[0];
};
exports.findTokenRecordPda = findTokenRecordPda;
const findRuleSetPDA = (payer, name) => {
return anchor.web3.PublicKey.findProgramAddressSync([Buffer.from('rule_set'), payer.toBuffer(), Buffer.from(name)], constants_1.AUTHORIZATION_RULES_PROGRAM)[0];
};
exports.findRuleSetPDA = findRuleSetPDA;
function getAsset(assetId, rpcUrl) {
return __awaiter(this, void 0, void 0, function* () {
try {
const axiosInstance = axios_1.default.create({
baseURL: rpcUrl,
});
const response = yield axiosInstance.post(rpcUrl, {
jsonrpc: '2.0',
method: 'getAsset',
id: 'rpd-op-123',
params: {
id: assetId,
},
});
return response.data.result;
}
catch (error) {
console.error(error);
}
});
}
function getTreeCanopyDepth(treeAddress, connection) {
return __awaiter(this, void 0, void 0, function* () {
const treeAccount = yield spl_account_compression_1.ConcurrentMerkleTreeAccount.fromAccountAddress(connection, treeAddress);
const canopyDepth = treeAccount.getCanopyDepth();
return canopyDepth;
});
}
function getAssetProof(assetId, rpcUrl) {
return __awaiter(this, void 0, void 0, function* () {
try {
const axiosInstance = axios_1.default.create({
baseURL: rpcUrl,
});
const response = yield axiosInstance.post(rpcUrl, {
jsonrpc: '2.0',
method: 'getAssetProof',
id: 'rpd-op-123',
params: {
id: assetId,
},
});
return response.data.result;
}
catch (error) {
console.error(error);
}
});
}
const mapProof = (assetProof, canopyDepth) => {
if (!assetProof.proof || assetProof.proof.length === 0) {
throw new Error('Proof is empty');
}
return assetProof.proof.slice(0, assetProof.proof.length - (!!canopyDepth ? canopyDepth : 0)).map((node) => ({
pubkey: new anchor.web3.PublicKey(node),
isSigner: false,
isWritable: false,
}));
};
exports.mapProof = mapProof;
function decode64(stuff) {
// return bufferToArray(Buffer.from(stuff, 'base64'));
return bufferToArray(bytes_1.base64.decode(stuff));
}
function decode(stuff) {
return bufferToArray(bs58.decode(stuff));
}
function bufferToArray(buffer) {
const nums = [];
for (let i = 0; i < buffer.length; i++) {
nums.push(buffer[i]);
}
return nums;
}
const getMaxLoanValueFromBondOfferBN = (bondOffer) => anchor_2.BN.min((bondOffer.buyOrdersQuantity > new anchor_2.BN(0) ? bondOffer.currentSpotPrice : new anchor_2.BN(0)).add(bondOffer.bidSettlement), bondOffer.validation.loanToValueFilter);
exports.getMaxLoanValueFromBondOfferBN = getMaxLoanValueFromBondOfferBN;
const fetch = require('node-fetch');
const calculatePriorityFees = (connection) => __awaiter(void 0, void 0, void 0, function* () {
try {
const response = yield fetch(connection.rpcEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 'my-id',
method: 'getPriorityFeeEstimate',
params: [
{
accountKeys: [constants_1.BONDS_PROGRAM_PUBKEY, 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'],
options: {
includeAllPriorityFeeLevels: true,
},
},
],
}),
});
const { result } = yield response.json();
return result.priorityFeeLevels.veryHigh < constants_1.MAX_PRIORITY_FEES
? result.priorityFeeLevels.veryHigh
: constants_1.MAX_PRIORITY_FEES;
}
catch (_a) {
return constants_1.BASE_PRIORITY_FEES;
}
});
exports.calculatePriorityFees = calculatePriorityFees;
const sortCompareBN = (a, b, order = 'desc') => {
const res = a.sub(b);
if (order === 'asc') {
if (res.gt(constants_1.ZERO_BN))
return 1;
if (res.lt(constants_1.ZERO_BN))
return -1;
return 0;
}
if (res.gt(constants_1.ZERO_BN))
return -1;
if (res.lt(constants_1.ZERO_BN))
return 1;
return 0;
};
exports.sortCompareBN = sortCompareBN;
const getRepayFeeFromHadomarket = (hadoMarket) => {
let repay_fee_apr = Number(hadoMarket.interestFee);
return repay_fee_apr;
};
const getUpfrontFeeFromHadomarket = (hadoMarket) => {
let upfrontFee = Number(hadoMarket.upfrontFee);
return upfrontFee;
};
exports.getUpfrontFeeFromHadomarket = getUpfrontFeeFromHadomarket;
/**
* @param amountOfBonds lender apr
* @returns lenderApr + (lenderApr * REPAY_FEE_APR_TOKEN_PROTOCOL)
*/
const calcBorrowerTokenAPR = (amountOfBonds, interestFeeFromHadoMarket, isSplFeature = true) => {
const repay_fee_apr = interestFeeFromHadoMarket;
return isSplFeature ? amountOfBonds * ((constants_1.BASE_POINTS + repay_fee_apr) / constants_1.BASE_POINTS) : amountOfBonds + repay_fee_apr;
};
exports.calcBorrowerTokenAPR = calcBorrowerTokenAPR;
/**
* @param borrowAprRate borrow apr
* @returns borrowAprRate / (1 + REPAY_FEE_APR_TOKEN_PROTOCOL / BASE_POINTS)
*/
const calcLenderTokenApr = (borrowAprRate, interestFeeFromHadoMarket, isSplFeature = true) => {
const repay_fee_apr = interestFeeFromHadoMarket;
return isSplFeature ? borrowAprRate / (1 + repay_fee_apr / constants_1.BASE_POINTS) : borrowAprRate - interestFeeFromHadoMarket;
};
exports.calcLenderTokenApr = calcLenderTokenApr;
const calcRepayFeeAprFromBondTradeTransaction = (bondTradeTransaction, hadoMarket) => {
const REPAY_FEE_APR = 620;
const REPAY_FEE_APR_TOKEN_PROTOCOL = 3300;
if (Number(bondTradeTransaction.protocolInterestFee) == 0) {
if (constants_1.CUSTOM_FEE_APR_HADO_MARKETS.find(market => market == hadoMarket.toString())) {
return Number(constants_1.REPAY_FEE_APR_PERCENT_SPL_JUP_USDC);
}
else {
if (bondTradeTransaction.bondTradeTransactionType == types_1.BondTradeTransactionV2Type.AutoReceiveAndReceiveSpl) {
return REPAY_FEE_APR_TOKEN_PROTOCOL;
}
else {
return REPAY_FEE_APR;
}
}
}
return Number(bondTradeTransaction.protocolInterestFee);
};
exports.calcRepayFeeAprFromBondTradeTransaction = calcRepayFeeAprFromBondTradeTransaction;