UNPKG

fbonds-core

Version:

Banx protocol sdk

496 lines (495 loc) 22.2 kB
"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 __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;