From 2febe1f9db5ce0814dec33daae361023270e37dc Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Date: Fri, 4 Oct 2024 00:24:05 +0800 Subject: [PATCH 01/10] step 1 --- apps/staking/src/api.ts | 2 ++ governance/pyth_staking_sdk/src/types.ts | 1 + governance/pyth_staking_sdk/src/utils/pool.ts | 1 + 3 files changed, 4 insertions(+) diff --git a/apps/staking/src/api.ts b/apps/staking/src/api.ts index 26b012a94..d02f1d3e6 100644 --- a/apps/staking/src/api.ts +++ b/apps/staking/src/api.ts @@ -54,6 +54,7 @@ type Data = { poolUtilizationDelta: bigint; numFeeds: number; qualityRanking: number; + delegationFee: bigint; apyHistory: { date: Date; apy: number }[]; positions?: | { @@ -243,6 +244,7 @@ const loadPublisherData = async ( selfStake: publisher.selfDelegation, selfStakeDelta: publisher.selfDelegationDelta, stakeAccount: publisher.stakeAccount ?? undefined, + delegationFee: publisher.delegationFee, }; }); }; diff --git a/governance/pyth_staking_sdk/src/types.ts b/governance/pyth_staking_sdk/src/types.ts index 92abacd46..c10241533 100644 --- a/governance/pyth_staking_sdk/src/types.ts +++ b/governance/pyth_staking_sdk/src/types.ts @@ -63,6 +63,7 @@ export type PublisherData = { totalDelegationDelta: bigint; selfDelegation: bigint; selfDelegationDelta: bigint; + delegationFee: bigint; apyHistory: { epoch: bigint; apy: number; selfApy: number }[]; }[]; diff --git a/governance/pyth_staking_sdk/src/utils/pool.ts b/governance/pyth_staking_sdk/src/utils/pool.ts index b5f71bb1d..755f37ea2 100644 --- a/governance/pyth_staking_sdk/src/utils/pool.ts +++ b/governance/pyth_staking_sdk/src/utils/pool.ts @@ -24,6 +24,7 @@ export const extractPublisherData = ( (poolData.selfDelState[index]?.deltaDelegation ?? 0n), selfDelegation: poolData.selfDelState[index]?.totalDelegation ?? 0n, selfDelegationDelta: poolData.selfDelState[index]?.deltaDelegation ?? 0n, + delegationFee: poolData.delegationFees[index] ?? 0n, apyHistory: poolData.events .filter((event) => event.epoch > 0n) .map((event) => ({ From a409feb25d7092c9e095919ee1d29550a40c61f3 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Date: Fri, 4 Oct 2024 00:35:44 +0800 Subject: [PATCH 02/10] progress --- .../staking/src/components/OracleIntegrityStaking/index.tsx | 5 +++++ governance/pyth_staking_sdk/src/utils/apy.ts | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/staking/src/components/OracleIntegrityStaking/index.tsx b/apps/staking/src/components/OracleIntegrityStaking/index.tsx index f99a413d8..aa43c737f 100644 --- a/apps/staking/src/components/OracleIntegrityStaking/index.tsx +++ b/apps/staking/src/components/OracleIntegrityStaking/index.tsx @@ -935,6 +935,7 @@ const doSort = ( poolCapacity: a.poolCapacity, poolUtilization: a.poolUtilization + a.poolUtilizationDelta, yieldRate, + delegationFee : a.delegationFee, }) - calculateApy({ isSelf: false, @@ -942,6 +943,7 @@ const doSort = ( poolCapacity: b.poolCapacity, poolUtilization: b.poolUtilization + b.poolUtilizationDelta, yieldRate, + delegationFee : b.delegationFee, }); return sort === SortOption.ApyDescending ? -1 * value : value; } @@ -1063,6 +1065,7 @@ type PublisherProps = { poolUtilizationDelta: bigint; numFeeds: number; qualityRanking: number; + delegationFee: bigint; apyHistory: { date: Date; apy: number }[]; positions?: | { @@ -1124,6 +1127,7 @@ const Publisher = ({ poolUtilization: publisher.poolUtilization + publisher.poolUtilizationDelta, yieldRate, + delegationFee : publisher.delegationFee, }).toFixed(2), [ isSelf, @@ -1548,6 +1552,7 @@ const NewApy = ({ calculateApy({ poolCapacity: publisher.poolCapacity, yieldRate, + delegationFee : publisher.delegationFee, ...(isSelf ? { isSelf: true, diff --git a/governance/pyth_staking_sdk/src/utils/apy.ts b/governance/pyth_staking_sdk/src/utils/apy.ts index 5790c3e24..c206233b4 100644 --- a/governance/pyth_staking_sdk/src/utils/apy.ts +++ b/governance/pyth_staking_sdk/src/utils/apy.ts @@ -9,6 +9,7 @@ export const calculateApy = ( selfStake: bigint; poolCapacity: bigint; yieldRate: bigint; + delegationFee : bigint; } & ({ isSelf: true } | { isSelf: false; poolUtilization: bigint }), ) => { const { selfStake, poolCapacity, yieldRate, isSelf } = options; @@ -24,6 +25,7 @@ export const calculateApy = ( } const { poolUtilization } = options; + const delegatorSplit = 1 - Number(options.delegationFee) / FRACTION_PRECISION; const delegatorPoolUtilization = poolUtilization - selfStake; const delegatorPoolCapacity = poolCapacity - eligibleSelfStake; @@ -33,10 +35,10 @@ export const calculateApy = ( : delegatorPoolUtilization; if (poolUtilization === selfStake) { - return apyPercentage; + return (selfStake >= poolCapacity ? 0 : apyPercentage) * delegatorSplit; } return ( - (apyPercentage * Number(eligibleStake)) / Number(delegatorPoolUtilization) + (apyPercentage * delegatorSplit * Number(eligibleStake)) / Number(delegatorPoolUtilization) ); }; From c9f8e1f30e026cbfb3678756d2a0f8a46cc1bea0 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Date: Fri, 4 Oct 2024 00:41:09 +0800 Subject: [PATCH 03/10] works --- governance/pyth_staking_sdk/src/utils/apy.ts | 12 +++++++++--- governance/pyth_staking_sdk/src/utils/pool.ts | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/governance/pyth_staking_sdk/src/utils/apy.ts b/governance/pyth_staking_sdk/src/utils/apy.ts index c206233b4..632a07d89 100644 --- a/governance/pyth_staking_sdk/src/utils/apy.ts +++ b/governance/pyth_staking_sdk/src/utils/apy.ts @@ -4,6 +4,12 @@ export const convertEpochYieldToApy = (epochYield: bigint) => { return (Number(epochYield) * 52 * 100) / FRACTION_PRECISION; }; +export const computeDelegatorPercentage = ( + delegationFee : bigint, +) => { + return 1 - Number(delegationFee) / FRACTION_PRECISION; +} + export const calculateApy = ( options: { selfStake: bigint; @@ -25,7 +31,7 @@ export const calculateApy = ( } const { poolUtilization } = options; - const delegatorSplit = 1 - Number(options.delegationFee) / FRACTION_PRECISION; + const delegatorPercentage = computeDelegatorPercentage(options.delegationFee); const delegatorPoolUtilization = poolUtilization - selfStake; const delegatorPoolCapacity = poolCapacity - eligibleSelfStake; @@ -35,10 +41,10 @@ export const calculateApy = ( : delegatorPoolUtilization; if (poolUtilization === selfStake) { - return (selfStake >= poolCapacity ? 0 : apyPercentage) * delegatorSplit; + return (selfStake >= poolCapacity ? 0 : apyPercentage) * delegatorPercentage; } return ( - (apyPercentage * delegatorSplit * Number(eligibleStake)) / Number(delegatorPoolUtilization) + (apyPercentage * delegatorPercentage * Number(eligibleStake)) / Number(delegatorPoolUtilization) ); }; diff --git a/governance/pyth_staking_sdk/src/utils/pool.ts b/governance/pyth_staking_sdk/src/utils/pool.ts index 755f37ea2..534e178c9 100644 --- a/governance/pyth_staking_sdk/src/utils/pool.ts +++ b/governance/pyth_staking_sdk/src/utils/pool.ts @@ -1,6 +1,6 @@ import { PublicKey } from "@solana/web3.js"; -import { convertEpochYieldToApy } from "./apy"; +import { computeDelegatorPercentage, convertEpochYieldToApy } from "./apy"; import { FRACTION_PRECISION_N } from "../constants"; import type { PoolDataAccount, PublisherData } from "../types"; @@ -32,7 +32,7 @@ export const extractPublisherData = ( apy: convertEpochYieldToApy( (event.y * (event.eventData[index]?.otherRewardRatio ?? 0n)) / FRACTION_PRECISION_N, - ), + ) * computeDelegatorPercentage(poolData.delegationFees[index] ?? 0n), selfApy: convertEpochYieldToApy( (event.y * (event.eventData[index]?.selfRewardRatio ?? 0n)) / FRACTION_PRECISION_N, From 7f06396424dc2b1bbbfec6e575c6a20f5450647f Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Date: Fri, 4 Oct 2024 00:46:50 +0800 Subject: [PATCH 04/10] add self apy --- apps/staking/src/api.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/staking/src/api.ts b/apps/staking/src/api.ts index d02f1d3e6..257544d76 100644 --- a/apps/staking/src/api.ts +++ b/apps/staking/src/api.ts @@ -55,7 +55,7 @@ type Data = { numFeeds: number; qualityRanking: number; delegationFee: bigint; - apyHistory: { date: Date; apy: number }[]; + apyHistory: { date: Date; apy: number, selfApy: number }[]; positions?: | { warmup?: bigint | undefined; @@ -227,9 +227,10 @@ const loadPublisherData = async ( const publisherRanking = publisherRankings.find( (ranking) => ranking.publisher === publisherPubkeyString, ); - const apyHistory = publisher.apyHistory.map(({ epoch, apy }) => ({ + const apyHistory = publisher.apyHistory.map(({ epoch, apy, selfApy }) => ({ date: epochToDate(epoch + 1n), apy, + selfApy })); return { From 0da8b051a439ee869b27b48a431fc8a202a38437 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Date: Fri, 4 Oct 2024 00:47:45 +0800 Subject: [PATCH 05/10] fixed --- apps/staking/src/api.ts | 4 ++-- .../src/components/OracleIntegrityStaking/index.tsx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/staking/src/api.ts b/apps/staking/src/api.ts index 257544d76..bf38e98eb 100644 --- a/apps/staking/src/api.ts +++ b/apps/staking/src/api.ts @@ -55,7 +55,7 @@ type Data = { numFeeds: number; qualityRanking: number; delegationFee: bigint; - apyHistory: { date: Date; apy: number, selfApy: number }[]; + apyHistory: { date: Date; apy: number; selfApy: number }[]; positions?: | { warmup?: bigint | undefined; @@ -230,7 +230,7 @@ const loadPublisherData = async ( const apyHistory = publisher.apyHistory.map(({ epoch, apy, selfApy }) => ({ date: epochToDate(epoch + 1n), apy, - selfApy + selfApy, })); return { diff --git a/apps/staking/src/components/OracleIntegrityStaking/index.tsx b/apps/staking/src/components/OracleIntegrityStaking/index.tsx index aa43c737f..3e4c34e12 100644 --- a/apps/staking/src/components/OracleIntegrityStaking/index.tsx +++ b/apps/staking/src/components/OracleIntegrityStaking/index.tsx @@ -935,7 +935,7 @@ const doSort = ( poolCapacity: a.poolCapacity, poolUtilization: a.poolUtilization + a.poolUtilizationDelta, yieldRate, - delegationFee : a.delegationFee, + delegationFee: a.delegationFee, }) - calculateApy({ isSelf: false, @@ -943,7 +943,7 @@ const doSort = ( poolCapacity: b.poolCapacity, poolUtilization: b.poolUtilization + b.poolUtilizationDelta, yieldRate, - delegationFee : b.delegationFee, + delegationFee: b.delegationFee, }); return sort === SortOption.ApyDescending ? -1 * value : value; } @@ -1127,7 +1127,7 @@ const Publisher = ({ poolUtilization: publisher.poolUtilization + publisher.poolUtilizationDelta, yieldRate, - delegationFee : publisher.delegationFee, + delegationFee: publisher.delegationFee, }).toFixed(2), [ isSelf, @@ -1552,7 +1552,7 @@ const NewApy = ({ calculateApy({ poolCapacity: publisher.poolCapacity, yieldRate, - delegationFee : publisher.delegationFee, + delegationFee: publisher.delegationFee, ...(isSelf ? { isSelf: true, From dcb554fe30935b1b464d0f92b3756a3a3d3e6866 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Date: Fri, 4 Oct 2024 01:03:03 +0800 Subject: [PATCH 06/10] go --- .../staking/src/components/OracleIntegrityStaking/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/staking/src/components/OracleIntegrityStaking/index.tsx b/apps/staking/src/components/OracleIntegrityStaking/index.tsx index 3e4c34e12..69c109ca8 100644 --- a/apps/staking/src/components/OracleIntegrityStaking/index.tsx +++ b/apps/staking/src/components/OracleIntegrityStaking/index.tsx @@ -1066,7 +1066,7 @@ type PublisherProps = { numFeeds: number; qualityRanking: number; delegationFee: bigint; - apyHistory: { date: Date; apy: number }[]; + apyHistory: { date: Date; apy: number, selfApy: number }[]; positions?: | { warmup?: bigint | undefined; @@ -1266,9 +1266,9 @@ const Publisher = ({
({ + data={publisher.apyHistory.map(({ date, apy, selfApy }) => ({ date, - value: apy, + value: isSelf ? selfApy : apy, }))} />
From 492df8dafbffceab8fa14b6b13dd5ea7488047a6 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Date: Fri, 4 Oct 2024 01:03:33 +0800 Subject: [PATCH 07/10] go --- apps/staking/src/components/OracleIntegrityStaking/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/staking/src/components/OracleIntegrityStaking/index.tsx b/apps/staking/src/components/OracleIntegrityStaking/index.tsx index 69c109ca8..597baa9af 100644 --- a/apps/staking/src/components/OracleIntegrityStaking/index.tsx +++ b/apps/staking/src/components/OracleIntegrityStaking/index.tsx @@ -1066,7 +1066,7 @@ type PublisherProps = { numFeeds: number; qualityRanking: number; delegationFee: bigint; - apyHistory: { date: Date; apy: number, selfApy: number }[]; + apyHistory: { date: Date; apy: number; selfApy: number }[]; positions?: | { warmup?: bigint | undefined; From 6ba4ae369405c2da8bb01447767345eb5ac9172f Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Date: Fri, 4 Oct 2024 01:07:03 +0800 Subject: [PATCH 08/10] rename --- governance/pyth_staking_sdk/src/utils/apy.ts | 4 ++-- governance/pyth_staking_sdk/src/utils/pool.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/pyth_staking_sdk/src/utils/apy.ts b/governance/pyth_staking_sdk/src/utils/apy.ts index 632a07d89..9a122faa4 100644 --- a/governance/pyth_staking_sdk/src/utils/apy.ts +++ b/governance/pyth_staking_sdk/src/utils/apy.ts @@ -4,7 +4,7 @@ export const convertEpochYieldToApy = (epochYield: bigint) => { return (Number(epochYield) * 52 * 100) / FRACTION_PRECISION; }; -export const computeDelegatorPercentage = ( +export const computeDelegatorRewardPercentage = ( delegationFee : bigint, ) => { return 1 - Number(delegationFee) / FRACTION_PRECISION; @@ -31,7 +31,7 @@ export const calculateApy = ( } const { poolUtilization } = options; - const delegatorPercentage = computeDelegatorPercentage(options.delegationFee); + const delegatorPercentage = computeDelegatorRewardPercentage(options.delegationFee); const delegatorPoolUtilization = poolUtilization - selfStake; const delegatorPoolCapacity = poolCapacity - eligibleSelfStake; diff --git a/governance/pyth_staking_sdk/src/utils/pool.ts b/governance/pyth_staking_sdk/src/utils/pool.ts index 534e178c9..f549784e3 100644 --- a/governance/pyth_staking_sdk/src/utils/pool.ts +++ b/governance/pyth_staking_sdk/src/utils/pool.ts @@ -1,6 +1,6 @@ import { PublicKey } from "@solana/web3.js"; -import { computeDelegatorPercentage, convertEpochYieldToApy } from "./apy"; +import { computeDelegatorRewardPercentage, convertEpochYieldToApy } from "./apy"; import { FRACTION_PRECISION_N } from "../constants"; import type { PoolDataAccount, PublisherData } from "../types"; @@ -32,7 +32,7 @@ export const extractPublisherData = ( apy: convertEpochYieldToApy( (event.y * (event.eventData[index]?.otherRewardRatio ?? 0n)) / FRACTION_PRECISION_N, - ) * computeDelegatorPercentage(poolData.delegationFees[index] ?? 0n), + ) * computeDelegatorRewardPercentage(poolData.delegationFees[index] ?? 0n), selfApy: convertEpochYieldToApy( (event.y * (event.eventData[index]?.selfRewardRatio ?? 0n)) / FRACTION_PRECISION_N, From 086c6fdd91ca92662a2fab0228352f8301002b5e Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Date: Fri, 4 Oct 2024 01:15:47 +0800 Subject: [PATCH 09/10] lint --- governance/pyth_staking_sdk/src/utils/apy.ts | 19 +++++++++++-------- governance/pyth_staking_sdk/src/utils/pool.ts | 17 ++++++++++++----- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/governance/pyth_staking_sdk/src/utils/apy.ts b/governance/pyth_staking_sdk/src/utils/apy.ts index 9a122faa4..ec122fb5f 100644 --- a/governance/pyth_staking_sdk/src/utils/apy.ts +++ b/governance/pyth_staking_sdk/src/utils/apy.ts @@ -4,18 +4,16 @@ export const convertEpochYieldToApy = (epochYield: bigint) => { return (Number(epochYield) * 52 * 100) / FRACTION_PRECISION; }; -export const computeDelegatorRewardPercentage = ( - delegationFee : bigint, -) => { +export const computeDelegatorRewardPercentage = (delegationFee: bigint) => { return 1 - Number(delegationFee) / FRACTION_PRECISION; -} +}; export const calculateApy = ( options: { selfStake: bigint; poolCapacity: bigint; yieldRate: bigint; - delegationFee : bigint; + delegationFee: bigint; } & ({ isSelf: true } | { isSelf: false; poolUtilization: bigint }), ) => { const { selfStake, poolCapacity, yieldRate, isSelf } = options; @@ -31,7 +29,9 @@ export const calculateApy = ( } const { poolUtilization } = options; - const delegatorPercentage = computeDelegatorRewardPercentage(options.delegationFee); + const delegatorPercentage = computeDelegatorRewardPercentage( + options.delegationFee, + ); const delegatorPoolUtilization = poolUtilization - selfStake; const delegatorPoolCapacity = poolCapacity - eligibleSelfStake; @@ -41,10 +41,13 @@ export const calculateApy = ( : delegatorPoolUtilization; if (poolUtilization === selfStake) { - return (selfStake >= poolCapacity ? 0 : apyPercentage) * delegatorPercentage; + return ( + (selfStake >= poolCapacity ? 0 : apyPercentage) * delegatorPercentage + ); } return ( - (apyPercentage * delegatorPercentage * Number(eligibleStake)) / Number(delegatorPoolUtilization) + (apyPercentage * delegatorPercentage * Number(eligibleStake)) / + Number(delegatorPoolUtilization) ); }; diff --git a/governance/pyth_staking_sdk/src/utils/pool.ts b/governance/pyth_staking_sdk/src/utils/pool.ts index f549784e3..9bc91b181 100644 --- a/governance/pyth_staking_sdk/src/utils/pool.ts +++ b/governance/pyth_staking_sdk/src/utils/pool.ts @@ -1,6 +1,9 @@ import { PublicKey } from "@solana/web3.js"; -import { computeDelegatorRewardPercentage, convertEpochYieldToApy } from "./apy"; +import { + computeDelegatorRewardPercentage, + convertEpochYieldToApy, +} from "./apy"; import { FRACTION_PRECISION_N } from "../constants"; import type { PoolDataAccount, PublisherData } from "../types"; @@ -29,10 +32,14 @@ export const extractPublisherData = ( .filter((event) => event.epoch > 0n) .map((event) => ({ epoch: event.epoch, - apy: convertEpochYieldToApy( - (event.y * (event.eventData[index]?.otherRewardRatio ?? 0n)) / - FRACTION_PRECISION_N, - ) * computeDelegatorRewardPercentage(poolData.delegationFees[index] ?? 0n), + apy: + convertEpochYieldToApy( + (event.y * (event.eventData[index]?.otherRewardRatio ?? 0n)) / + FRACTION_PRECISION_N, + ) * + computeDelegatorRewardPercentage( + poolData.delegationFees[index] ?? 0n, + ), selfApy: convertEpochYieldToApy( (event.y * (event.eventData[index]?.selfRewardRatio ?? 0n)) / FRACTION_PRECISION_N, From d72c6ef99e2aacdbc0a4c8e9b85faac02d8be630 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Date: Mon, 7 Oct 2024 16:43:15 +0100 Subject: [PATCH 10/10] fix: return 0 apy if pool has 0 capacity --- governance/pyth_staking_sdk/src/utils/apy.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/governance/pyth_staking_sdk/src/utils/apy.ts b/governance/pyth_staking_sdk/src/utils/apy.ts index ec122fb5f..f9e51b7ba 100644 --- a/governance/pyth_staking_sdk/src/utils/apy.ts +++ b/governance/pyth_staking_sdk/src/utils/apy.ts @@ -19,6 +19,10 @@ export const calculateApy = ( const { selfStake, poolCapacity, yieldRate, isSelf } = options; const eligibleSelfStake = selfStake > poolCapacity ? poolCapacity : selfStake; + if (poolCapacity === 0n) { + return 0; + } + const apyPercentage = convertEpochYieldToApy(yieldRate); if (isSelf) {