diff --git a/apps/staking/src/api.ts b/apps/staking/src/api.ts index 96982baa0f..be7da5c508 100644 --- a/apps/staking/src/api.ts +++ b/apps/staking/src/api.ts @@ -289,7 +289,7 @@ const loadPublisherData = async ( ); const apyHistory = publisher.apyHistory.map(({ epoch, apy }) => ({ date: epochToDate(epoch + 1n), - apy: Number(apy), + apy, })); return { diff --git a/governance/pyth_staking_sdk/src/constants.ts b/governance/pyth_staking_sdk/src/constants.ts index 017a4e3fc6..b46cd7f459 100644 --- a/governance/pyth_staking_sdk/src/constants.ts +++ b/governance/pyth_staking_sdk/src/constants.ts @@ -8,6 +8,9 @@ const ONE_WEEK_IN_SECONDS = 7n * ONE_DAY_IN_SECONDS; export const EPOCH_DURATION = ONE_WEEK_IN_SECONDS; +export const FRACTION_PRECISION = 1_000_000; +export const FRACTION_PRECISION_N = 1_000_000n; + export const POSITION_BUFFER_SIZE = 200; export const POSITIONS_ACCOUNT_HEADER_SIZE = DISCRIMINATOR_SIZE + 32; diff --git a/governance/pyth_staking_sdk/src/types.ts b/governance/pyth_staking_sdk/src/types.ts index ddd27972b9..325f7a08b4 100644 --- a/governance/pyth_staking_sdk/src/types.ts +++ b/governance/pyth_staking_sdk/src/types.ts @@ -53,7 +53,7 @@ export type PublisherData = { stakeAccount: PublicKey | null; totalDelegation: bigint; selfDelegation: bigint; - apyHistory: { epoch: bigint; apy: bigint; selfApy: bigint }[]; + apyHistory: { epoch: bigint; apy: number; selfApy: number }[]; }[]; export enum PositionState { diff --git a/governance/pyth_staking_sdk/src/utils/apy.ts b/governance/pyth_staking_sdk/src/utils/apy.ts index b182f698ae..5790c3e24d 100644 --- a/governance/pyth_staking_sdk/src/utils/apy.ts +++ b/governance/pyth_staking_sdk/src/utils/apy.ts @@ -1,3 +1,9 @@ +import { FRACTION_PRECISION } from "../constants"; + +export const convertEpochYieldToApy = (epochYield: bigint) => { + return (Number(epochYield) * 52 * 100) / FRACTION_PRECISION; +}; + export const calculateApy = ( options: { selfStake: bigint; @@ -8,7 +14,7 @@ export const calculateApy = ( const { selfStake, poolCapacity, yieldRate, isSelf } = options; const eligibleSelfStake = selfStake > poolCapacity ? poolCapacity : selfStake; - const apyPercentage = (Number(yieldRate) * 52 * 100) / 1_000_000; + const apyPercentage = convertEpochYieldToApy(yieldRate); if (isSelf) { if (selfStake === 0n) { diff --git a/governance/pyth_staking_sdk/src/utils/pool.ts b/governance/pyth_staking_sdk/src/utils/pool.ts index 9df6672e25..19d0bd10a9 100644 --- a/governance/pyth_staking_sdk/src/utils/pool.ts +++ b/governance/pyth_staking_sdk/src/utils/pool.ts @@ -1,5 +1,7 @@ import { PublicKey } from "@solana/web3.js"; +import { convertEpochYieldToApy } from "./apy"; +import { FRACTION_PRECISION_N } from "../constants"; import type { PoolDataAccount, PublisherData } from "../types"; export const extractPublisherData = ( @@ -22,12 +24,14 @@ export const extractPublisherData = ( .filter((event) => event.epoch > 0n) .map((event) => ({ epoch: event.epoch, - apy: + apy: convertEpochYieldToApy( (event.y * (event.eventData[index]?.otherRewardRatio ?? 0n)) / - 1_000_000n, - selfApy: + FRACTION_PRECISION_N, + ), + selfApy: convertEpochYieldToApy( (event.y * (event.eventData[index]?.selfRewardRatio ?? 0n)) / - 1_000_000n, + FRACTION_PRECISION_N, + ), })) .sort((a, b) => Number(a.epoch) - Number(b.epoch)), }));