From 54a2f69a0c5516f26306037f40deb65cfac14b80 Mon Sep 17 00:00:00 2001 From: hschiau Date: Thu, 10 Oct 2024 14:53:16 +0300 Subject: [PATCH 1/2] SERVICES-2651: add aprIfUncapped and remainingDaysIfUncapped fields --- src/modules/staking/models/staking.model.ts | 4 + .../services/staking.compute.service.ts | 101 ++++++++++++++---- src/modules/staking/staking.resolver.ts | 12 +++ 3 files changed, 99 insertions(+), 18 deletions(-) diff --git a/src/modules/staking/models/staking.model.ts b/src/modules/staking/models/staking.model.ts index 20a08545a..c3626501f 100644 --- a/src/modules/staking/models/staking.model.ts +++ b/src/modules/staking/models/staking.model.ts @@ -34,6 +34,8 @@ export class StakingModel { @Field() apr: string; @Field() + aprIfUncapped: string; + @Field() boostedApr: string; @Field(() => Int) minUnboundEpochs: number; @@ -44,6 +46,8 @@ export class StakingModel { @Field() rewardsRemainingDays: number; @Field() + rewardsRemainingDaysIfUncapped: number; + @Field() divisionSafetyConstant: string; @Field() produceRewardsEnabled: boolean; diff --git a/src/modules/staking/services/staking.compute.service.ts b/src/modules/staking/services/staking.compute.service.ts index 918521353..281e517b3 100644 --- a/src/modules/staking/services/staking.compute.service.ts +++ b/src/modules/staking/services/staking.compute.service.ts @@ -209,17 +209,11 @@ export class StakingComputeService { } async computeStakeFarmAPR(stakeAddress: string): Promise { - const [accumulatedRewards, rewardsCapacity, produceRewardsEnabled] = - await Promise.all([ - this.stakingAbi.accumulatedRewards(stakeAddress), - this.stakingAbi.rewardCapacity(stakeAddress), - this.stakingAbi.produceRewardsEnabled(stakeAddress), - ]); + const rewardsDepletedOrDisabled = await this.rewardsDepletedOrDisabled( + stakeAddress, + ); - if ( - !produceRewardsEnabled || - new BigNumber(accumulatedRewards).isEqualTo(rewardsCapacity) - ) { + if (rewardsDepletedOrDisabled) { return '0'; } @@ -252,6 +246,39 @@ export class StakingComputeService { .toFixed(); } + @ErrorLoggerAsync({ + logArgs: true, + }) + @GetOrSetCache({ + baseKey: 'stake', + remoteTtl: CacheTtlInfo.ContractState.remoteTtl, + localTtl: CacheTtlInfo.ContractState.localTtl, + }) + async stakeFarmUncappedAPR(stakeAddress: string): Promise { + return await this.computeStakeFarmUncappedAPR(stakeAddress); + } + + async computeStakeFarmUncappedAPR(stakeAddress: string): Promise { + const rewardsDepletedOrDisabled = await this.rewardsDepletedOrDisabled( + stakeAddress, + ); + + if (rewardsDepletedOrDisabled) { + return '0'; + } + + const [perBlockRewardAmount, farmTokenSupply] = await Promise.all([ + this.stakingAbi.perBlockRewardsAmount(stakeAddress), + this.stakingAbi.farmTokenSupply(stakeAddress), + ]); + + const rewardsUnboundedBig = new BigNumber( + perBlockRewardAmount, + ).multipliedBy(constantsConfig.BLOCKS_IN_YEAR); + + return rewardsUnboundedBig.dividedBy(farmTokenSupply).toFixed(); + } + @ErrorLoggerAsync({ logArgs: true, }) @@ -322,6 +349,25 @@ export class StakingComputeService { } async computeRewardsRemainingDays(stakeAddress: string): Promise { + const extraRewardsAPRBoundedPerBlock = + await this.computeExtraRewardsAPRBoundedPerBlock(stakeAddress); + + return await this.computeRewardsRemainingDaysBase( + stakeAddress, + extraRewardsAPRBoundedPerBlock, + ); + } + + async computeRewardsRemainingDaysIfUncapped( + stakeAddress: string, + ): Promise { + return await this.computeRewardsRemainingDaysBase(stakeAddress); + } + + async computeRewardsRemainingDaysBase( + stakeAddress: string, + extraRewardsAPRBoundedPerBlock?: BigNumber, + ): Promise { const [perBlockRewardAmount, accumulatedRewards, rewardsCapacity] = await Promise.all([ this.stakingAbi.perBlockRewardsAmount(stakeAddress), @@ -329,17 +375,16 @@ export class StakingComputeService { this.stakingAbi.rewardCapacity(stakeAddress), ]); + const perBlockRewards = extraRewardsAPRBoundedPerBlock + ? BigNumber.min( + extraRewardsAPRBoundedPerBlock, + perBlockRewardAmount, + ) + : new BigNumber(perBlockRewardAmount); + // 10 blocks per minute * 60 minutes per hour * 24 hours per day const blocksInDay = 10 * 60 * 24; - const extraRewardsAPRBoundedPerBlock = - await this.computeExtraRewardsAPRBoundedPerBlock(stakeAddress); - - const perBlockRewards = BigNumber.min( - extraRewardsAPRBoundedPerBlock, - perBlockRewardAmount, - ); - return parseFloat( new BigNumber(rewardsCapacity) .minus(accumulatedRewards) @@ -920,4 +965,24 @@ export class StakingComputeService { ); return deployedAt ?? undefined; } + + private async rewardsDepletedOrDisabled( + stakeAddress: string, + ): Promise { + const [accumulatedRewards, rewardsCapacity, produceRewardsEnabled] = + await Promise.all([ + this.stakingAbi.accumulatedRewards(stakeAddress), + this.stakingAbi.rewardCapacity(stakeAddress), + this.stakingAbi.produceRewardsEnabled(stakeAddress), + ]); + + if ( + !produceRewardsEnabled || + new BigNumber(accumulatedRewards).isEqualTo(rewardsCapacity) + ) { + return true; + } + + return false; + } } diff --git a/src/modules/staking/staking.resolver.ts b/src/modules/staking/staking.resolver.ts index e4907bee6..cac66c91e 100644 --- a/src/modules/staking/staking.resolver.ts +++ b/src/modules/staking/staking.resolver.ts @@ -144,6 +144,11 @@ export class StakingResolver { return this.stakingCompute.stakeFarmAPR(parent.address); } + @ResolveField() + async aprIfUncapped(@Parent() parent: StakingModel) { + return this.stakingCompute.stakeFarmUncappedAPR(parent.address); + } + @ResolveField() async boostedApr(@Parent() parent: StakingModel) { return this.stakingCompute.boostedAPR(parent.address); @@ -169,6 +174,13 @@ export class StakingResolver { return this.stakingCompute.computeRewardsRemainingDays(parent.address); } + @ResolveField() + async rewardsRemainingDaysIfUncapped(@Parent() parent: StakingModel) { + return this.stakingCompute.computeRewardsRemainingDaysIfUncapped( + parent.address, + ); + } + @ResolveField() async divisionSafetyConstant(@Parent() parent: StakingModel) { return this.stakingAbi.divisionSafetyConstant(parent.address); From 56755c6191c80f0fef7de06c0972e4178344b2ce Mon Sep 17 00:00:00 2001 From: hschiau Date: Fri, 11 Oct 2024 14:52:09 +0300 Subject: [PATCH 2/2] SERVICES-2651: rename fields --- src/modules/staking/models/staking.model.ts | 4 ++-- .../services/staking.compute.service.ts | 18 ++++++------------ src/modules/staking/staking.resolver.ts | 6 +++--- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/modules/staking/models/staking.model.ts b/src/modules/staking/models/staking.model.ts index c3626501f..93a34a310 100644 --- a/src/modules/staking/models/staking.model.ts +++ b/src/modules/staking/models/staking.model.ts @@ -34,7 +34,7 @@ export class StakingModel { @Field() apr: string; @Field() - aprIfUncapped: string; + aprUncapped: string; @Field() boostedApr: string; @Field(() => Int) @@ -46,7 +46,7 @@ export class StakingModel { @Field() rewardsRemainingDays: number; @Field() - rewardsRemainingDaysIfUncapped: number; + rewardsRemainingDaysUncapped: number; @Field() divisionSafetyConstant: string; @Field() diff --git a/src/modules/staking/services/staking.compute.service.ts b/src/modules/staking/services/staking.compute.service.ts index 281e517b3..f6046ccc7 100644 --- a/src/modules/staking/services/staking.compute.service.ts +++ b/src/modules/staking/services/staking.compute.service.ts @@ -209,11 +209,9 @@ export class StakingComputeService { } async computeStakeFarmAPR(stakeAddress: string): Promise { - const rewardsDepletedOrDisabled = await this.rewardsDepletedOrDisabled( - stakeAddress, - ); + const isProducingRewards = await this.isProducingRewards(stakeAddress); - if (rewardsDepletedOrDisabled) { + if (isProducingRewards) { return '0'; } @@ -259,11 +257,9 @@ export class StakingComputeService { } async computeStakeFarmUncappedAPR(stakeAddress: string): Promise { - const rewardsDepletedOrDisabled = await this.rewardsDepletedOrDisabled( - stakeAddress, - ); + const isProducingRewards = await this.isProducingRewards(stakeAddress); - if (rewardsDepletedOrDisabled) { + if (isProducingRewards) { return '0'; } @@ -358,7 +354,7 @@ export class StakingComputeService { ); } - async computeRewardsRemainingDaysIfUncapped( + async computeRewardsRemainingDaysUncapped( stakeAddress: string, ): Promise { return await this.computeRewardsRemainingDaysBase(stakeAddress); @@ -966,9 +962,7 @@ export class StakingComputeService { return deployedAt ?? undefined; } - private async rewardsDepletedOrDisabled( - stakeAddress: string, - ): Promise { + private async isProducingRewards(stakeAddress: string): Promise { const [accumulatedRewards, rewardsCapacity, produceRewardsEnabled] = await Promise.all([ this.stakingAbi.accumulatedRewards(stakeAddress), diff --git a/src/modules/staking/staking.resolver.ts b/src/modules/staking/staking.resolver.ts index cac66c91e..22d1f86d0 100644 --- a/src/modules/staking/staking.resolver.ts +++ b/src/modules/staking/staking.resolver.ts @@ -145,7 +145,7 @@ export class StakingResolver { } @ResolveField() - async aprIfUncapped(@Parent() parent: StakingModel) { + async aprUncapped(@Parent() parent: StakingModel) { return this.stakingCompute.stakeFarmUncappedAPR(parent.address); } @@ -175,8 +175,8 @@ export class StakingResolver { } @ResolveField() - async rewardsRemainingDaysIfUncapped(@Parent() parent: StakingModel) { - return this.stakingCompute.computeRewardsRemainingDaysIfUncapped( + async rewardsRemainingDaysUncapped(@Parent() parent: StakingModel) { + return this.stakingCompute.computeRewardsRemainingDaysUncapped( parent.address, ); }