UNPKG

@hubbleprotocol/farms-sdk

Version:
105 lines 5.48 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculatePendingRewards = calculatePendingRewards; exports.calculateCurrentRewardPerToken = calculateCurrentRewardPerToken; exports.calculateNewRewardToBeIssued = calculateNewRewardToBeIssued; exports.scopePriceForFarm = scopePriceForFarm; const decimal_js_1 = __importDefault(require("decimal.js")); const utils_1 = require("./utils"); const web3_js_1 = require("@solana/web3.js"); const types_1 = require("../rpc_client/types"); function calculatePendingRewards(farmState, userState, rewardIndex, ts, scopePrices) { let scopePrice = scopePriceForFarm(farmState, scopePrices); const newRewardPerToken = calculateRewardPerStake(farmState, ts, rewardIndex, scopePrice); const rewardTally = new decimal_js_1.default(userState.rewardsTallyScaled[rewardIndex].toString()).div(utils_1.WAD); let activeStakeScaled = new decimal_js_1.default(0); if (farmState.delegateAuthority.equals(web3_js_1.PublicKey.default)) { activeStakeScaled = new decimal_js_1.default(userState.activeStakeScaled.toString()).div(utils_1.WAD); } else { activeStakeScaled = new decimal_js_1.default(userState.activeStakeScaled.toString()); } const newRewardTally = activeStakeScaled.mul(newRewardPerToken); const newReward = new decimal_js_1.default(newRewardTally.sub(rewardTally).toFixed(0)); const prevReward = new decimal_js_1.default(userState.rewardsIssuedUnclaimed[rewardIndex].toString()); const finalReward = prevReward.add(newReward); return finalReward; } function calculateCurrentRewardPerToken(rewardInfo, currentTimeUnit) { const rewardCurve = rewardInfo.rewardScheduleCurve; let index = 0; for (let i = 0; i < rewardCurve.points.length; i++) { if (new decimal_js_1.default(rewardCurve.points[i].tsStart.toString()).lte(currentTimeUnit)) { index = i; } else { break; } } return rewardCurve.points[index].rewardPerTimeUnit.toNumber(); } function calculateRewardPerStake(farmState, ts, rewardIndex, scopePrice) { const rewardInfo = farmState.rewardInfos[rewardIndex]; const newRewards = calculateNewRewardToBeIssued(farmState, ts, rewardIndex, scopePrice); let scaledRewards = newRewards.mul(utils_1.WAD); let rewardPerTokenScaled = new decimal_js_1.default(rewardInfo.rewardPerShareScaled.toString()).div(utils_1.WAD); let rewardPerTokenScaledAdded = new decimal_js_1.default(0); const totalActiveStakeScaled = new decimal_js_1.default(farmState.totalActiveStakeScaled.toString()); if (farmState.delegateAuthority.equals(web3_js_1.PublicKey.default)) { rewardPerTokenScaledAdded = scaledRewards.div(totalActiveStakeScaled); } else { if (scaledRewards.gt(new decimal_js_1.default(0)) && totalActiveStakeScaled.gt(new decimal_js_1.default(0))) { rewardPerTokenScaledAdded = scaledRewards .div(totalActiveStakeScaled) .div(utils_1.WAD); } } const finalRewardPerToken = rewardPerTokenScaled.add(rewardPerTokenScaledAdded); return finalRewardPerToken; } function calculateNewRewardToBeIssued(farmState, ts, rewardIndex, scopePrice) { const rewardInfo = farmState.rewardInfos[rewardIndex]; const tsDiff = ts.sub(new decimal_js_1.default(rewardInfo.lastIssuanceTs.toString())); let rps = calculateCurrentRewardPerToken(rewardInfo, ts); let rpsDecimal = new decimal_js_1.default(Math.pow(10, rewardInfo.rewardsPerSecondDecimals)); let newRewards = tsDiff.mul(new decimal_js_1.default(rps)).div(rpsDecimal); if (rewardInfo.rewardType == types_1.RewardType.Proportional.discriminator) { // In the `Proportional` case `rps` means // `reward per second for entire farm` } else if (rewardInfo.rewardType == types_1.RewardType.Constant.discriminator) { // In the `Constant` case `rps` means // `reward per second for each lamport staked` const totalStaked = new decimal_js_1.default(farmState.totalStakedAmount.toString()); newRewards = newRewards.mul(totalStaked); } if (!farmState.scopePrices.equals(web3_js_1.PublicKey.default)) { // Oracle adjustment if (scopePrice == null) { throw new Error("Scope price not provided"); } console.log("Adjusting by scope price", scopePrice.toString()); newRewards = newRewards.mul(scopePrice); } // We cap rewards by how much is available in the farm anyway let cappedRewards = decimal_js_1.default.min(newRewards, new decimal_js_1.default(rewardInfo.rewardsAvailable.toString())); return cappedRewards; } function scopePriceForFarm(farmState, scopePrices) { let scopePrice = null; if (!farmState.scopePrices.equals(web3_js_1.PublicKey.default)) { if (scopePrices == null) { throw new Error("Scope prices not provided"); } const price = scopePrices.prices[new decimal_js_1.default(farmState.scopeOraclePriceId.toString()).toNumber()]; const factor = new decimal_js_1.default(10).pow(price.price.exp.toString()); scopePrice = new decimal_js_1.default(price.price.value.toString()).div(factor); } return scopePrice; } //# sourceMappingURL=mathUtils.js.map