UNPKG

@hubbleprotocol/farms-sdk

Version:
913 lines 81.8 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 __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var g = generator.apply(thisArg, _arguments || []), i, q = []; return i = {}, verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getAllBoosts = exports.calculatePointsPerDay = exports.calcAvgBoost = exports.Farms = exports.farmsId = void 0; exports.getCurrentTimeUnit = getCurrentTimeUnit; exports.getCurrentRps = getCurrentRps; exports.printMultisigTx = printMultisigTx; exports.printSimulateTx = printSimulateTx; const anchor_1 = require("@coral-xyz/anchor"); const farms_json_1 = __importDefault(require("./rpc_client/farms.json")); // @ts-ignore const base58_js_1 = require("base58-js"); const web3_js_1 = require("@solana/web3.js"); const utils_1 = require("./utils"); const utils_2 = require("./utils"); const accounts_1 = require("./rpc_client/accounts"); const accounts_2 = require("./rpc_client/accounts"); const farmOperations = __importStar(require("./utils/operations")); const decimal_js_1 = __importDefault(require("decimal.js")); const web3_js_2 = require("@solana/web3.js"); const index_1 = require("./rpc_client/types/index"); const programId_1 = require("./rpc_client/programId"); const scope_sdk_1 = require("@hubbleprotocol/scope-sdk"); const arrayUtils_1 = require("./utils/arrayUtils"); const klend_sdk_1 = require("@kamino-finance/klend-sdk"); const types_1 = require("@kamino-finance/klend-sdk/dist/idl_codegen/types"); const utils_3 = require("./commands/utils"); const market_1 = require("@project-serum/serum/lib/market"); const sendTransactionsUtils_1 = require("./utils/sendTransactionsUtils"); const spl_token_1 = require("@solana/spl-token"); exports.farmsId = new web3_js_1.PublicKey("FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr"); class Farms { constructor(connection) { this._connection = connection; this._provider = new anchor_1.AnchorProvider(connection, (0, utils_1.getReadOnlyWallet)(), { commitment: connection.commitment, }); this._farmsProgramId = exports.farmsId; this._farmsProgram = new anchor_1.Program(farms_json_1.default, this._farmsProgramId, this._provider); } getConnection() { return this._connection; } getProgramID() { return this._farmsProgramId; } getProgram() { return this._farmsProgram; } getAllUserStatesForUser(user) { return __awaiter(this, void 0, void 0, function* () { let filters = []; filters.push({ memcmp: { bytes: user.toBase58(), offset: 48, }, }); filters.push({ dataSize: accounts_1.UserState.layout.span + 8, }); const userStates = (yield this._farmsProgram.account.userState.all(filters)).map((x) => { let res = { userState: new accounts_1.UserState(x.account), key: x.publicKey, }; return res; }); return userStates; }); } getAllUserStates() { return __awaiter(this, void 0, void 0, function* () { return (yield this._farmsProgram.account.userState.all([ { dataSize: accounts_1.UserState.layout.span + 8, }, ])).map((x) => { const userAndKey = { userState: new accounts_1.UserState(x.account), key: x.publicKey, }; return userAndKey; }); }); } getAllUserStatesWithFilter(isFarmDelegated) { return __awaiter(this, void 0, void 0, function* () { return (yield this._farmsProgram.account.userState.all([ { dataSize: accounts_1.UserState.layout.span + 8, }, { memcmp: { bytes: isFarmDelegated ? "2" : "1", offset: 80 }, }, ])).map((x) => { const userAndKey = { userState: new accounts_1.UserState(x.account), key: x.publicKey, }; return userAndKey; }); }); } /** * Get all farms user states from an async generator filled with batches of max 100 user states each * @example * const userStateGenerator = farms.batchGetAllUserStates(); * for await (const userStates of userStateGenerator) { * console.log('got a batch of user states:', userStates.length); * } */ batchGetAllUserStates() { return __asyncGenerator(this, arguments, function* batchGetAllUserStates_1() { const userStatePubkeys = yield __await(this._connection.getProgramAccounts(this._farmsProgramId, { filters: [ { dataSize: accounts_1.UserState.layout.span + 8, }, ], dataSlice: { offset: 0, length: 0, }, })); for (const batch of (0, arrayUtils_1.chunks)(userStatePubkeys.map((x) => x.pubkey), 100)) { const userStateAccounts = yield __await(this._connection.getMultipleAccountsInfo(batch)); const userStateBatch = []; for (let i = 0; i < userStateAccounts.length; i++) { const userState = userStateAccounts[i]; const pubkey = batch[i]; if (userState === null) { continue; } const userStateAccount = accounts_1.UserState.decode(userState.data); if (!userStateAccount) { throw Error(`Could not decode user state account ${pubkey.toString()}`); } userStateBatch.push({ key: pubkey, userState: userStateAccount }); } yield yield __await(userStateBatch); } }); } getAllUserStatesForFarm(farm) { return __awaiter(this, void 0, void 0, function* () { return (yield this._farmsProgram.account.userState.all([ { dataSize: accounts_1.UserState.layout.span + 8, }, { memcmp: { offset: 8 + 8, bytes: farm.toBase58(), }, }, ])).map((x) => { const userAndKey = { userState: new accounts_1.UserState(x.account), key: x.publicKey, }; return userAndKey; }); }); } getFarmsForMint(mint) { return __awaiter(this, void 0, void 0, function* () { let filters = []; filters.push({ memcmp: { bytes: mint.toBase58(), offset: 72, }, }); filters.push({ dataSize: accounts_2.FarmState.layout.span + 8, }); const farms = (yield this._farmsProgram.account.farmState.all(filters)).map((x) => { let res = { farmState: new accounts_2.FarmState(x.account), key: x.publicKey, }; return res; }); return farms; }); } getAllFarmStates() { return __awaiter(this, void 0, void 0, function* () { return (yield this._farmsProgram.account.farmState.all([ { dataSize: accounts_2.FarmState.layout.span + 8, }, ])).map((x) => { const farmAndKey = { farmState: new accounts_2.FarmState(x.account), key: x.publicKey, }; return farmAndKey; }); }); } getAllFarmStatesByPubkeys(keys) { return __awaiter(this, void 0, void 0, function* () { const farmAndKeys = []; const farmStates = yield this.fetchMultipleFarmStatesWithCheckedSize(keys); farmStates.forEach((farmState, index) => { if (farmState) { farmAndKeys.push({ farmState: farmState, key: keys[index], }); } }); return farmAndKeys; }); } getStakedAmountForMintForFarm(mint, farm) { return __awaiter(this, void 0, void 0, function* () { const farms = yield this.getFarmsForMint(mint); for (let index = 0; index < farms.length; index++) { if (farms[index].key.equals(farm)) { return (0, utils_2.lamportsToCollDecimal)(new decimal_js_1.default((0, utils_2.scaleDownWads)(farms[index].farmState.totalActiveStakeScaled)), farms[index].farmState.token.decimals.toNumber()); } } throw Error("No Farm found"); }); } getStakedAmountForMint(mint) { return __awaiter(this, void 0, void 0, function* () { const farms = yield this.getFarmsForMint(mint); let totalStaked = new decimal_js_1.default(0); for (let index = 0; index < farms.length; index++) { totalStaked = totalStaked.add((0, utils_2.lamportsToCollDecimal)(new decimal_js_1.default(farms[index].farmState.totalStakedAmount.toString()), farms[index].farmState.token.decimals.toNumber())); } return totalStaked; }); } getLockupDurationAndExpiry(farm, user) { return __awaiter(this, void 0, void 0, function* () { let userStateAddress = (0, utils_2.getUserStatePDA)(this._farmsProgramId, farm, user); let userState = yield accounts_1.UserState.fetch(this._connection, userStateAddress); let farmState = yield accounts_2.FarmState.fetch(this._connection, farm); if (!farmState) { throw new Error("Error fetching farm state"); } let lockingMode = farmState === null || farmState === void 0 ? void 0 : farmState.lockingMode.toNumber(); let lockingDuration = farmState === null || farmState === void 0 ? void 0 : farmState.lockingDuration.toNumber(); let penalty = farmState.lockingEarlyWithdrawalPenaltyBps.toNumber(); if (penalty !== 0 && penalty !== 10000) { throw "Early withdrawal penalty is not supported yet"; } if (penalty > 10000) { throw "Early withdrawal penalty is too high"; } let lockingStart = 0; const slot = yield this._connection.getSlot(); const timestampNow = (yield this._connection.getBlockTime(slot)); if (lockingMode == index_1.LockingMode.None.discriminator) { return { farmLockupOriginalDuration: 0, farmLockupExpiry: 0, lockupRemainingDuration: 0, }; } if (lockingMode == index_1.LockingMode.WithExpiry.discriminator) { // Locking starts globally for the entire farm lockingStart = farmState === null || farmState === void 0 ? void 0 : farmState.lockingStartTimestamp.toNumber(); } if (lockingMode == index_1.LockingMode.Continuous.discriminator) { // Locking starts for each user individually at each stake // if the user has a state, else now if (userState === null) { lockingStart = timestampNow; } else { if (!userState) { throw new Error("Error fetching user state"); } lockingStart = userState.lastStakeTs.toNumber(); } } const timestampBeginning = lockingStart; const timestampMaturity = lockingStart + lockingDuration; if (timestampNow >= timestampMaturity) { // Time has passed, no remaining return { farmLockupOriginalDuration: farmState.lockingDuration.toNumber(), farmLockupExpiry: timestampMaturity, lockupRemainingDuration: 0, }; } if (timestampNow < timestampBeginning) { // Time has not started, no remaining return { farmLockupOriginalDuration: farmState.lockingDuration.toNumber(), farmLockupExpiry: timestampMaturity, lockupRemainingDuration: 0, }; } const timeRemaining = timestampMaturity - timestampNow; const remainingLockedDurationSeconds = Math.max(timeRemaining, 0); return { farmLockupOriginalDuration: farmState.lockingDuration.toNumber(), farmLockupExpiry: timestampMaturity, lockupRemainingDuration: remainingLockedDurationSeconds, }; }); } getUserStateKeysForDelegatedFarm(user, farm, delegatees) { return __awaiter(this, void 0, void 0, function* () { if (delegatees) { return this.getUserStateKeysForDelegatedFarmDeterministic(user, farm, delegatees); } const userStates = yield this.getAllUserStatesForUser(user); const userStateKeysForFarm = []; for (let index = 0; index < userStates.length; index++) { if (userStates[index].userState.farmState.equals(farm)) { userStateKeysForFarm.push(userStates[index]); } } if (userStateKeysForFarm.length === 0) { throw Error("No user state found for user " + user + " for farm " + farm); } else { return userStateKeysForFarm; } }); } getUserStateKeysForDelegatedFarmDeterministic(user, farm, delegatees) { return __awaiter(this, void 0, void 0, function* () { const userStateAddresses = []; const userStateKeysForFarm = []; delegatees.forEach((delegatee) => { const userStateAddress = (0, utils_2.getUserStatePDA)(this._farmsProgramId, farm, delegatee); userStateAddresses.push(userStateAddress); }); const userStates = yield accounts_1.UserState.fetchMultiple(this._connection, userStateAddresses); userStates.forEach((userState, index) => { if (userState && userState.farmState.equals(farm)) { userStateKeysForFarm.push({ key: userStateAddresses[index], userState: userState, }); } }); if (userStateKeysForFarm.length === 0) { throw Error("No user state found for user " + user + " for farm " + farm); } else { return userStateKeysForFarm; } }); } getAllFarmsForUser(user, strategiesToInclude) { return __awaiter(this, void 0, void 0, function* () { const userStates = yield this.getAllUserStatesForUser(user); const farmPks = new Array(); for (let i = 0; i < userStates.length; i++) { farmPks[i] = userStates[i].userState.farmState; } const farmStates = yield this.getAllFarmStatesByPubkeys(farmPks); if (!farmStates) { throw new Error("Error fetching farms"); } let farmStatesFiltered = []; if (strategiesToInclude) { farmStatesFiltered = farmStates.filter((farmStates) => { if (strategiesToInclude.contains(farmStates.farmState.strategyId)) { return true; } return false; }); } else { farmStatesFiltered = farmStates; } if (farmStatesFiltered.length === 0) { // Return empty if no serializable farm states found return new klend_sdk_1.PubkeyHashMap(); } const timestamp = new decimal_js_1.default((yield this._connection.getBlockTime(yield this._connection.getSlot()))); const userFarms = new klend_sdk_1.PubkeyHashMap(); for (let userState of userStates) { const userPendingRewardAmounts = []; let farmState = farmStatesFiltered.find((farmState) => farmState.key.equals(userState.userState.farmState)); if (!farmState) { // Skip farms that are not serializable anymore continue; } let oraclePrices = null; if (!farmState.farmState.scopePrices.equals(web3_js_1.PublicKey.default)) { oraclePrices = yield scope_sdk_1.OraclePrices.fetch(this._connection, farmState.farmState.scopePrices); if (!oraclePrices) { throw new Error("Error fetching oracle prices"); } } let hasReward = false; // calculate userState pending rewards for (let indexReward = 0; indexReward < farmState.farmState.rewardInfos.length; indexReward++) { userPendingRewardAmounts[indexReward] = (0, utils_1.calculatePendingRewards)(farmState.farmState, userState.userState, indexReward, timestamp, oraclePrices); if (userPendingRewardAmounts[indexReward].gt(0)) { hasReward = true; } } // add new userFarm state if non empty (has rewards or stake) and not already present if (!userFarms.has(userState.userState.farmState)) { const userFarm = { userStateAddress: userState.key, farm: userState.userState.farmState, strategyId: farmState.farmState.strategyId, delegateAuthority: farmState.farmState.delegateAuthority, stakedToken: farmState.farmState.token.mint, activeStakeByDelegatee: new klend_sdk_1.PubkeyHashMap(), pendingDepositStakeByDelegatee: new klend_sdk_1.PubkeyHashMap(), pendingWithdrawalUnstakeByDelegatee: new klend_sdk_1.PubkeyHashMap(), pendingRewards: new Array(farmState.farmState.rewardInfos.length) .fill(undefined) .map(function (value, index) { return { rewardTokenMint: new web3_js_1.PublicKey(0), rewardTokenProgramId: farmState.farmState.rewardInfos[index].token.tokenProgram, rewardType: (farmState === null || farmState === void 0 ? void 0 : farmState.farmState.rewardInfos[index].rewardType) || 0, cumulatedPendingRewards: new decimal_js_1.default(0), pendingRewardsByDelegatee: new klend_sdk_1.PubkeyHashMap(), }; }), }; if (new decimal_js_1.default((0, utils_2.scaleDownWads)(userState.userState.activeStakeScaled)).gt(0) || hasReward) { userFarms.set(userState.userState.farmState, userFarm); } else { // skip as we are not accounting for empty userFarms continue; } } // add new userFarm state if non empty (has rewards or stake) and not already present const refUserFarm = userFarms.get(userState.userState.farmState); if (!refUserFarm) { throw new Error("User farm state not loaded properly "); } const updatedUserFarm = Object.assign({}, refUserFarm); if (updatedUserFarm.activeStakeByDelegatee.has(userState.userState.delegatee)) { console.error("Delegatee for user for farm already present. There should be only one delegatee for this user for this farm"); continue; } // active stake by delegatee updatedUserFarm.activeStakeByDelegatee.set(userState.userState.delegatee, (0, utils_2.lamportsToCollDecimal)(new decimal_js_1.default((0, utils_2.scaleDownWads)(userState.userState.activeStakeScaled)), farmState.farmState.token.decimals.toNumber())); // pendingDepositStake by delegatee updatedUserFarm.pendingDepositStakeByDelegatee.set(userState.userState.delegatee, new decimal_js_1.default((0, utils_2.scaleDownWads)(userState.userState.pendingDepositStakeScaled))); // pendingWithdrawalUnstake by delegatee updatedUserFarm.pendingWithdrawalUnstakeByDelegatee.set(userState.userState.delegatee, new decimal_js_1.default((0, utils_2.scaleDownWads)(userState.userState.pendingWithdrawalUnstakeScaled))); // cummulating rewards for (let indexReward = 0; indexReward < farmState.farmState.rewardInfos.length; indexReward++) { updatedUserFarm.pendingRewards[indexReward].rewardTokenMint = farmState.farmState.rewardInfos[indexReward].token.mint; updatedUserFarm.pendingRewards[indexReward].cumulatedPendingRewards = updatedUserFarm.pendingRewards[indexReward].cumulatedPendingRewards.add(userPendingRewardAmounts[indexReward]); updatedUserFarm.pendingRewards[indexReward].pendingRewardsByDelegatee.set(userState.userState.delegatee, userPendingRewardAmounts[indexReward]); } // set updated userFarm userFarms.set(userState.userState.farmState, updatedUserFarm); } return userFarms; }); } getUserStateKeyForUndelegatedFarm(user, farmAddress) { return __awaiter(this, void 0, void 0, function* () { const userStateAddress = (0, utils_2.getUserStatePDA)(this._farmsProgramId, farmAddress, user); const userState = yield accounts_1.UserState.fetch(this._connection, userStateAddress); if (!userState) { throw new Error(`User state not found ${userStateAddress.toString()}`); } return { key: userStateAddress, userState: userState, }; }); } getUserForUndelegatedFarm(user, farmAddress) { return __awaiter(this, void 0, void 0, function* () { const farmState = yield accounts_2.FarmState.fetch(this._connection, farmAddress); if (!farmState) { throw new Error(`Farm not found ${farmAddress.toString()}`); } const userStateAddress = (0, utils_2.getUserStatePDA)(this._farmsProgramId, farmAddress, user); const userState = yield accounts_1.UserState.fetch(this._connection, userStateAddress); if (!userState) { throw new Error(`User state not found ${userStateAddress.toString()}`); } const userFarm = { userStateAddress: userStateAddress, farm: farmAddress, strategyId: farmState.strategyId, delegateAuthority: farmState.delegateAuthority, stakedToken: farmState.token.mint, activeStakeByDelegatee: new klend_sdk_1.PubkeyHashMap(), pendingDepositStakeByDelegatee: new klend_sdk_1.PubkeyHashMap(), pendingWithdrawalUnstakeByDelegatee: new klend_sdk_1.PubkeyHashMap(), pendingRewards: new Array(farmState.rewardInfos.length) .fill(undefined) .map(function (value, index) { return { rewardTokenMint: new web3_js_1.PublicKey(0), rewardTokenProgramId: farmState === null || farmState === void 0 ? void 0 : farmState.rewardInfos[index].token.tokenProgram, rewardType: (farmState === null || farmState === void 0 ? void 0 : farmState.rewardInfos[index].rewardType) || 0, cumulatedPendingRewards: new decimal_js_1.default(0), pendingRewardsByDelegatee: new klend_sdk_1.PubkeyHashMap(), }; }), }; // active stake userFarm.activeStakeByDelegatee.set(user, (0, utils_2.lamportsToCollDecimal)(new decimal_js_1.default((0, utils_2.scaleDownWads)(userState.activeStakeScaled)), farmState.token.decimals.toNumber())); // pendingDepositStake userFarm.pendingDepositStakeByDelegatee.set(user, new decimal_js_1.default((0, utils_2.scaleDownWads)(userState.pendingDepositStakeScaled))); // pendingWithdrawalUnstake userFarm.pendingWithdrawalUnstakeByDelegatee.set(user, new decimal_js_1.default((0, utils_2.scaleDownWads)(userState.pendingWithdrawalUnstakeScaled))); // get oraclePrices const timestamp = new decimal_js_1.default((yield this._connection.getBlockTime(yield this._connection.getSlot()))); let oraclePrices = null; if (!farmState.scopePrices.equals(web3_js_1.PublicKey.default)) { oraclePrices = yield scope_sdk_1.OraclePrices.fetch(this._connection, farmState.scopePrices); if (!oraclePrices) { throw new Error("Error fetching oracle prices"); } } const userPendingRewardAmounts = []; for (let indexReward = 0; indexReward < farmState.rewardInfos.length; indexReward++) { // calculate pending rewards userPendingRewardAmounts[indexReward] = (0, utils_1.calculatePendingRewards)(farmState, userState, indexReward, timestamp, oraclePrices); userFarm.pendingRewards[indexReward].rewardTokenMint = farmState.rewardInfos[indexReward].token.mint; userFarm.pendingRewards[indexReward].cumulatedPendingRewards = userPendingRewardAmounts[indexReward]; userFarm.pendingRewards[indexReward].pendingRewardsByDelegatee.set(user, userPendingRewardAmounts[indexReward]); } return userFarm; }); } executeTransaction(ix_1, signer_1) { return __awaiter(this, arguments, void 0, function* (ix, signer, extraSigners = [], web3Client, priorityFeeMultiplier = 0) { const microLamport = Math.pow(10, 6); // 1 lamport const computeUnits = 200000; const microLamportsPrioritizationFee = microLamport / computeUnits; const tx = new web3_js_1.Transaction(); let { blockhash } = yield this._connection.getLatestBlockhash(); if (priorityFeeMultiplier) { const priorityFeeIxn = (0, utils_3.createAddExtraComputeUnitFeeTransaction)(computeUnits, microLamportsPrioritizationFee * priorityFeeMultiplier); tx.add(...priorityFeeIxn); } tx.recentBlockhash = blockhash; tx.feePayer = signer.publicKey; tx.add(...ix); let sig; if (web3Client) { sig = yield (0, sendTransactionsUtils_1.signSendAndConfirmRawTransactionWithRetry)({ mainConnection: web3Client.sendConnection, extraConnections: web3Client.sendConnectionsExtra, tx: new web3_js_2.VersionedTransaction(tx.compileMessage()), signers: [signer, ...extraSigners], commitment: "confirmed", sendTransactionOptions: { skipPreflight: true, preflightCommitment: "confirmed", }, }); } else { sig = yield (0, web3_js_1.sendAndConfirmTransaction)(this._connection, tx, [signer, ...extraSigners], { skipPreflight: true, commitment: "confirmed" }); } return sig; }); } createNewUserIx(user, farm) { return __awaiter(this, void 0, void 0, function* () { const userState = (0, utils_2.getUserStatePDA)(this._farmsProgramId, farm, user); const ix = farmOperations.initializeUser(farm, user, userState); return ix; }); } createNewUser(user, farm, priorityFeeMultiplier, web3Client) { return __awaiter(this, void 0, void 0, function* () { const ix = yield this.createNewUserIx(user.publicKey, farm); let sig = yield this.executeTransaction([ix], user, [], web3Client, priorityFeeMultiplier); const userState = (0, utils_2.getUserStatePDA)(this._farmsProgramId, farm, user.publicKey); if (process.env.DEBUG === "true") { console.log("Initialize User: " + userState); console.log("Refresh Farm txn: " + sig.toString()); } return sig; }); } stakeIx(user, farm, amountLamports, stakeTokenMint, scopePrices) { return __awaiter(this, void 0, void 0, function* () { const farmVault = (0, utils_2.getFarmVaultPDA)(this._farmsProgramId, farm, stakeTokenMint); const userStatePk = (0, utils_2.getUserStatePDA)(this._farmsProgramId, farm, user); const userTokenAta = yield (0, utils_2.getAssociatedTokenAddress)(user, stakeTokenMint, spl_token_1.TOKEN_PROGRAM_ID); const ix = farmOperations.stake(user, userStatePk, userTokenAta, farm, farmVault, stakeTokenMint, scopePrices, new anchor_1.BN(amountLamports.toString())); return ix; }); } stake(user, farm, amountLamports, stakeTokenMint, priorityFeeMultiplier, web3Client) { return __awaiter(this, void 0, void 0, function* () { const ix = yield this.stakeIx(user.publicKey, farm, amountLamports, stakeTokenMint, programId_1.PROGRAM_ID); let increaseComputeIx = (0, utils_2.createAddExtraComputeUnitsTransaction)(user.publicKey, 400000); let sig = yield this.executeTransaction([increaseComputeIx, ix], user, [], web3Client, priorityFeeMultiplier); if (process.env.DEBUG === "true") { console.log("User " + " stake " + amountLamports); console.log("Stake txn: " + sig.toString()); } return sig; }); } unstakeIx(user, farm, amountLamports, scopePrices) { return __awaiter(this, void 0, void 0, function* () { const userStatePk = (0, utils_2.getUserStatePDA)(this._farmsProgramId, farm, user); const ix = farmOperations.unstake(user, userStatePk, farm, scopePrices, new anchor_1.BN(amountLamports)); return ix; }); } unstake(user, farm, sharesAmount, priorityFeeMultiplier, web3Client) { return __awaiter(this, void 0, void 0, function* () { const ix = yield this.unstakeIx(user.publicKey, farm, sharesAmount, programId_1.PROGRAM_ID); let sig = yield this.executeTransaction([ix], user, [], web3Client, priorityFeeMultiplier); if (process.env.DEBUG === "true") { console.log("Unstake " + sharesAmount); console.log("Unstake txn: " + sig.toString()); } return sig; }); } withdrawUnstakedDepositIx(user, userState, farmState, stakeTokenMint) { return __awaiter(this, void 0, void 0, function* () { const userTokenAta = yield (0, utils_2.getAssociatedTokenAddress)(user, stakeTokenMint, spl_token_1.TOKEN_PROGRAM_ID); const farmVault = (0, utils_2.getFarmVaultPDA)(this._farmsProgramId, farmState, stakeTokenMint); const farmVaultsAuthority = (0, utils_2.getFarmAuthorityPDA)(this._farmsProgramId, farmState); const ix = farmOperations.withdrawUnstakedDeposit(user, userState, farmState, userTokenAta, farmVault, farmVaultsAuthority); return ix; }); } withdrawUnstakedDeposit(user, farmState, tokenMint, userState, priorityFeeMultiplier, web3Client) { return __awaiter(this, void 0, void 0, function* () { const ix = yield this.withdrawUnstakedDepositIx(user.publicKey, userState, farmState, tokenMint); let sig = yield this.executeTransaction([ix], user, [], web3Client, priorityFeeMultiplier); if (process.env.DEBUG === "true") { console.log("User " + userState + " withdraw unstaked deposit "); console.log("Withdraw Unstaked Deposit txn: " + sig.toString()); } return sig; }); } claimForUserForFarmRewardIx(user_1, farm_1, rewardMint_1, isDelegated_1) { return __awaiter(this, arguments, void 0, function* (user, farm, rewardMint, isDelegated, rewardIndex = -1, delegatees) { const ixns = []; const ataIxns = []; const userStatesAndKeys = isDelegated ? yield this.getUserStateKeysForDelegatedFarm(user, farm, delegatees) : [yield this.getUserStateKeyForUndelegatedFarm(user, farm)]; const farmState = yield accounts_2.FarmState.fetch(this._connection, farm); if (!farmState) { throw new Error(`Farm not found ${farm.toString()}`); } const treasuryVault = (0, utils_2.getTreasuryVaultPDA)(this._farmsProgramId, farmState.globalConfig, rewardMint); // find rewardIndex if not defined if (rewardIndex === -1) { rewardIndex = farmState.rewardInfos.findIndex((r) => r.token.mint.equals(rewardMint)); } const rewardsTokenProgram = farmState.rewardInfos[rewardIndex].token.tokenProgram; const userRewardAta = yield (0, utils_2.getAssociatedTokenAddress)(user, rewardMint, rewardsTokenProgram); const ataExists = yield (0, utils_1.checkIfAccountExists)(this._connection, userRewardAta); if (!ataExists) { const [, ix] = yield (0, utils_1.createAssociatedTokenAccountIdempotentInstruction)(user, rewardMint, user, rewardsTokenProgram, userRewardAta); ataIxns.push([rewardMint, ix]); } for (let userStateIndex = 0; userStateIndex < userStatesAndKeys.length; userStateIndex++) { const ix = farmOperations.harvestReward(user, userStatesAndKeys[userStateIndex].key, userRewardAta, farmState.globalConfig, treasuryVault, farm, rewardMint, farmState.rewardInfos[rewardIndex].rewardsVault, farmState.farmVaultsAuthority, farmState.scopePrices.equals(web3_js_1.PublicKey.default) ? programId_1.PROGRAM_ID : farmState.scopePrices, rewardsTokenProgram, rewardIndex); ixns.push(ix); } return [ataIxns, ixns]; }); } claimForUserForFarmReward(user_1, farm_1, rewardMint_1, isDelegated_1) { return __awaiter(this, arguments, void 0, function* (user, farm, rewardMint, isDelegated, rewardIndex = -1, priorityFeeMultiplier, web3Client) { const [_ataIxns, ixns] = yield this.claimForUserForFarmRewardIx(user.publicKey, farm, rewardMint, isDelegated, rewardIndex); let sig = yield this.executeTransaction(ixns, user, [], web3Client, priorityFeeMultiplier); if (process.env.DEBUG === "true") { console.log("Harvest reward " + rewardIndex); console.log("HarvestReward txn: " + sig.toString()); } return sig; }); } claimForUserForFarmAllRewardsIx(user, farm, isDelegated, delegatees) { return __awaiter(this, void 0, void 0, function* () { const farmState = yield accounts_2.FarmState.fetch(this._connection, farm); const userStatesAndKeys = isDelegated ? yield this.getUserStateKeysForDelegatedFarm(user, farm, delegatees) : [yield this.getUserStateKeyForUndelegatedFarm(user, farm)]; const ixs = new Array(); // hardcoded as a hotfix for JTO release; // TODO: replace by proper fix const jitoFarm = new web3_js_1.PublicKey("Cik985zLyHYdv5Hs73BUWUcMHMhgfBNwbcCYyvBjV2tt"); if (!farmState) { throw new Error(`Farm not found ${farm.toString()}`); } for (let userStateIndex = 0; userStateIndex < userStatesAndKeys.length; userStateIndex++) { for (let rewardIndex = 0; rewardIndex < farmState.numRewardTokens.toNumber(); rewardIndex++) { if (!jitoFarm.equals(farm) && farmState.rewardInfos[rewardIndex].rewardType == index_1.RewardType.Constant.discriminator) { continue; } const rewardMint = farmState.rewardInfos[rewardIndex].token.mint; const rewardTokenProgram = farmState.rewardInfos[rewardIndex].token.tokenProgram; const userRewardAta = yield (0, utils_2.getAssociatedTokenAddress)(user, rewardMint, rewardTokenProgram); const treasuryVault = (0, utils_2.getTreasuryVaultPDA)(this._farmsProgramId, farmState.globalConfig, rewardMint); const ataExists = yield (0, utils_1.checkIfAccountExists)(this._connection, userRewardAta); if (!ataExists) { const [, ix] = yield (0, utils_1.createAssociatedTokenAccountIdempotentInstruction)(user, rewardMint, user, rewardTokenProgram, userRewardAta); ixs.push(ix); } ixs.push(farmOperations.harvestReward(user, userStatesAndKeys[userStateIndex].key, userRewardAta, farmState.globalConfig, treasuryVault, farm, rewardMint, farmState.rewardInfos[rewardIndex].rewardsVault, farmState.farmVaultsAuthority, farmState.scopePrices.equals(web3_js_1.PublicKey.default) ? programId_1.PROGRAM_ID : farmState.scopePrices, rewardTokenProgram, rewardIndex)); } } return ixs; }); } claimForUserForFarmAllRewards(user, farm, isDelegated, priorityFeeMultiplier, web3Client) { return __awaiter(this, void 0, void 0, function* () { const ixs = yield this.claimForUserForFarmAllRewardsIx(user.publicKey, farm, isDelegated); const sigs = new Array(); for (let i = 0; i < ixs.length; i++) { sigs[i] = yield this.executeTransaction([ixs[i]], user, [], web3Client, priorityFeeMultiplier); } return sigs; }); } transferOwnershipIx(user, userState, newUser) { return __awaiter(this, void 0, void 0, function* () { const ix = farmOperations.transferOwnership(user, userState, newUser); return ix; }); } transferOwnership(user, userState, newUser, priorityFeeMultiplier, web3Client) { return __awaiter(this, void 0, void 0, function* () { const ix = yield this.transferOwnershipIx(user.publicKey, userState, newUser); let sig = yield this.executeTransaction([ix], user, [], web3Client, priorityFeeMultiplier); if (process.env.DEBUG === "true") { console.log("Transfer User " + userState + " ownership from " + user.publicKey + " to " + newUser); console.log("Transfer User Ownership txn: " + sig.toString()); } return sig; }); } transferOwnershipAllUserStatesIx(user, newUser) { return __awaiter(this, void 0, void 0, function* () { const userStates = yield this.getAllUserStatesForUser(user); const ixs = new Array(); for (let index = 0; index < userStates.length; index++) { ixs[index] = farmOperations.transferOwnership(user, userStates[index].key, newUser); } return ixs; }); } transferOwnershipAllUserStates(user, newUser, priorityFeeMultiplier, web3Client) { return __awaiter(this, void 0, void 0, function* () { const ixs = yield this.transferOwnershipAllUserStatesIx(user.publicKey, newUser); const sigs = new Array(); for (let i = 0; i < ixs.length; i++) { sigs[i] = yield this.executeTransaction([ixs[i]], user, [], web3Client, priorityFeeMultiplier); } return sigs; }); } createFarmIx(admin, farm, globalConfig, stakeTokenMint) { return __awaiter(this, void 0, void 0, function* () { const farmVault = (0, utils_2.getFarmVaultPDA)(this._farmsProgramId, farm.publicKey, stakeTokenMint); const farmVaultAuthority = (0, utils_2.getFarmAuthorityPDA)(this._farmsProgramId, farm.publicKey); let ixs = []; ixs.push(yield (0, utils_2.createKeypairRentExemptIx)(this._provider.connection, admin, farm, utils_1.SIZE_FARM_STATE, this._farmsProgramId)); ixs.push(farmOperations.initializeFarm(globalConfig, admin, farm.publicKey, farmVault, farmVaultAuthority, stakeTokenMint)); return ixs; }); } createFarm(admin_1, globalConfig_1, farm_1, mint_1) { return __awaiter(this, arguments, void 0, function* (admin, globalConfig, farm, mint, mode = "execute", priorityFeeMultiplier, web3Client) { const ix = yield this.createFarmIx(mode === "multisig" ? new web3_js_1.PublicKey(process.env.MULTISIG) : admin.publicKey, farm, globalConfig, mint); const log = "Initialize Farm: " + farm.toString(); return this.processTxn(admin, ix, mode, priorityFeeMultiplier, log, [farm], web3Client); }); } addRewardToFarmIx(admin, globalConfig, farm, mint, tokenProgram) { return __awaiter(this, void 0, void 0, function* () { const globalConfigState = yield accounts_2.GlobalConfig.fetch(this._connection, globalConfig); if (!globalConfigState) { throw new Error("Could not fetch global config"); } const treasuryVault = (0, utils_2.getTreasuryVaultPDA)(this._farmsProgramId, globalConfig, mint); let farmVaultAuthority = (0, utils_2.getFarmAuthorityPDA)(this._farmsProgramId, farm); const rewardVault = (0, utils_2.getRewardVaultPDA)(this._farmsProgramId, farm, mint); const ix = farmOperations.initializeReward(globalConfig, globalConfigState.treasuryVaultsAuthority, treasuryVault, admin, farm, rewardVault, farmVaultAuthority, mint, tokenProgram); return ix; }); } addRewardToFarm(admin_1, globalConfig_1, farm_1, mint_1, tokenProgram_1) { return __awaiter(this, arguments, void 0, function* (admin, globalConfig, farm, mint, tokenProgram, mode = "execute", priorityFeeMultiplier, web3Client) { const ix = yield this.addRewardToFarmIx(mode === "multisig" ? new web3_js_1.PublicKey(process.env.MULTISIG) : admin.publicKey, globalConfig, farm, mint, tokenProgram); const log = "Initialize Reward: " + mint; return this.processTxn(admin, [ix], mode, priorityFeeMultiplier, log, [], web3Client); }); } addRewardAmountToFarmIx(payer_1, farm_1, mint_1, amount_1) { return __awaiter(this, arguments, void 0, function* (payer, farm, mint, amount, rewardIndexOverride = -1, decimalsOverride = -1, tokenProgramOverride = spl_token_1.TOKEN_PROGRAM_ID, scopePricesOverride = programId_1.PROGRAM_ID) { let decimals = decimalsOverride; let rewardIndex = rewardIndexOverride; let scopePrices = scopePricesOverride; let tokenProgram = tokenProgramOverride; if (rewardIndex == -1) { const farmState = yield accounts_2.FarmState.fetch(this._connection, farm); if (!farmState) { throw new Error(`Could not fetch farm state ${farm.toBase58()}`); } scopePrices = farmState.scopePrices.equals(web3_js_1.PublicKey.default) ? programId_1.PROGRAM_ID : farmState.scopePrices; for (let i = 0; farmState.rewardInfos.length; i++) { if (farmState.rewardInfos[i].token.mint.equals(mint)) { if (!farmState.rewardInfos[i].token.tokenProgram.equals(web3_js_1.PublicKey.default)) { tokenProgram = farmState.rewardInfos[i].token.tokenProgram; } rewardIndex = i; decimals = farmState.rewardInfos[i].token.decimals.toNumber(); break; } } } if (decimals == -1) { throw new Error(`Could not find reward token ${mint.toBase58()}`); } let amountLamports = new anchor_1.BN((0, utils_2.collToLamportsDecimal)(amount, decimals).floor().toString()); const payerRewardAta = yield (0, utils_2.getAssociatedTokenAddress)(payer, mint, tokenProgram); let rewardVault = (0, utils_2.getRewardVaultPDA)(this._farmsProgramId, farm, mint); let farmVaultsAuthority = (0, utils_2.getFarmAuthorityPDA)(this._farmsProgramId, farm); const ix = farmOperations.addReward(payer, farm, rewardVault, farmVaultsAuthority, payerRewardAta, mint, scopePrices, rewardIndex, tokenProgram, amountLamports); return ix; }); } withdrawRewardAmountFromFarmIx(payer_1, farm_1, mint_1, amount_1) { return __awaiter(this, arguments, void 0, function* (payer, farm, mint, amount, rewardIndexOverride = -1, decimalsOverride = -1, tokenProgramOverride = spl_token_1.TOKEN_PROGRAM_ID, scopePricesOverride = programId_1.PROGRAM_ID) { let decimals = decimalsOverride; let tokenProgram = tokenProgramOverride; let rewardInde