From f7e44e021a0b466451e362e9661b92c3ac8c55ef Mon Sep 17 00:00:00 2001 From: Petar Todorovic Date: Tue, 18 Nov 2025 15:45:32 +0100 Subject: [PATCH] fix: computed reward rate --- .changeset/loud-mugs-see.md | 5 +++++ packages/widget/src/domain/types/yields.ts | 18 +++++++++++++++++- .../get-yield-opportunity.ts | 2 ++ packages/widget/src/hooks/use-summary.tsx | 4 ++-- .../earn-page/state/earn-page-context.tsx | 4 ++-- 5 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 .changeset/loud-mugs-see.md diff --git a/.changeset/loud-mugs-see.md b/.changeset/loud-mugs-see.md new file mode 100644 index 00000000..a4ffc484 --- /dev/null +++ b/.changeset/loud-mugs-see.md @@ -0,0 +1,5 @@ +--- +"@stakekit/widget": patch +--- + +fix: computed reward rate diff --git a/packages/widget/src/domain/types/yields.ts b/packages/widget/src/domain/types/yields.ts index 2d95e7b0..96f0b0b1 100644 --- a/packages/widget/src/domain/types/yields.ts +++ b/packages/widget/src/domain/types/yields.ts @@ -2,7 +2,7 @@ import type { YieldDto, YieldType } from "@stakekit/api-hooks"; import { EvmNetworks } from "@stakekit/common"; import BigNumber from "bignumber.js"; import type { TFunction } from "i18next"; -import { Maybe } from "purify-ts"; +import { List, Maybe } from "purify-ts"; import type { SupportedSKChains } from "./chains"; export type ExtendedYieldType = YieldType | "native_staking" | "pooled_staking"; @@ -178,3 +178,19 @@ export const isEthenaUsdeStaking = (yieldId: string) => export const isBittensorStaking = (yieldId: string) => yieldId === "bittensor-native-staking"; + +export const getComputedRewardRate = (yieldDto: YieldDto) => { + const liveFeeConfigurations = yieldDto.feeConfigurations.filter( + (fc) => fc.status === "LIVE" + ); + + const firstLiveFeeConfiguration = List.head( + liveFeeConfigurations + ).extractNullable(); + + if (liveFeeConfigurations.length === 1 && firstLiveFeeConfiguration) { + return firstLiveFeeConfiguration.computedRewardRate; + } + + return yieldDto.rewardRate; +}; diff --git a/packages/widget/src/hooks/api/use-yield-opportunity/get-yield-opportunity.ts b/packages/widget/src/hooks/api/use-yield-opportunity/get-yield-opportunity.ts index 133b7e12..0c248f47 100644 --- a/packages/widget/src/hooks/api/use-yield-opportunity/get-yield-opportunity.ts +++ b/packages/widget/src/hooks/api/use-yield-opportunity/get-yield-opportunity.ts @@ -4,6 +4,7 @@ import { EitherAsync } from "purify-ts"; import { yieldYieldOpportunity } from "../../../common/private-api"; import { filterMapValidators, + getComputedRewardRate, isBittensorStaking, isEthenaUsdeStaking, type ValidatorsConfig, @@ -67,6 +68,7 @@ const fn = ({ isEthenaUsdeStaking(y.id) ? ({ ...y, + rewardRate: getComputedRewardRate(y), metadata: { ...y.metadata, name: y.metadata.name.replace(/staking/i, ""), diff --git a/packages/widget/src/hooks/use-summary.tsx b/packages/widget/src/hooks/use-summary.tsx index a8f54cc5..50f30cc1 100644 --- a/packages/widget/src/hooks/use-summary.tsx +++ b/packages/widget/src/hooks/use-summary.tsx @@ -294,10 +294,10 @@ export const SummaryProvider = ({ prices, }); - if (yieldDto.apy > 0 && usdAmount.gt(0)) { + if (yieldDto.rewardRate > 0 && usdAmount.gt(0)) { return { totalWeightedApy: acc.totalWeightedApy.plus( - usdAmount.times(yieldDto.apy * 100) + usdAmount.times(yieldDto.rewardRate * 100) ), totalValue: acc.totalValue.plus(usdAmount), }; diff --git a/packages/widget/src/pages/details/earn-page/state/earn-page-context.tsx b/packages/widget/src/pages/details/earn-page/state/earn-page-context.tsx index c1a44e32..bc90d6ee 100644 --- a/packages/widget/src/pages/details/earn-page/state/earn-page-context.tsx +++ b/packages/widget/src/pages/details/earn-page/state/earn-page-context.tsx @@ -235,8 +235,8 @@ export const EarnPageContextProvider = ({ children }: PropsWithChildren) => { const selectedStakeData = useMemo>( () => Maybe.of(multiYields) - .map((val) => [...val].sort((a, b) => b.apy - a.apy)) - .map((val) => val.filter((v) => v.apy > 0)) + .map((val) => [...val].sort((a, b) => b.rewardRate - a.rewardRate)) + .map((val) => val.filter((v) => v.rewardRate > 0)) .chain((yieldDtos) => Maybe.of(deferredStakeSearch) .chain((val) =>