Anybody have the calculation scripts for ICP and SNS projects?
1 Like
I think you are looking for fn distribute_rewards.
I’m looking for a way to calculate the estimated APY when creating a neuron, specifically the Voting rewards calculation on the dashboard:
Hello @dostro
For the ICP Dashboard here is how we fetch the data for the Estimate Rewards
const fetchData = async () => {
try {
// https://ic-api.internetcomputer.org/api/v3/governance-metrics
const response = await queryApi('v3/governance-metrics', ApiType.IC);
const lastRewardRoundTotalAvailableE8s: any = response.data.metrics.find((element: any) => {
return element.name === 'governance_latest_reward_round_total_available_e8s'
});
const lastRewardsRoundTotalAvailableIcp: number =
Number(lastRewardRoundTotalAvailableE8s.subsets[0].value[1]) / 100000000;
setLastRewardsRoundTotalAvailableIcp(lastRewardsRoundTotalAvailableIcp);
const totalVotingPowerE8s: any = response.data.metrics.find((element: any) => {
return element.name === 'governance_voting_power_total'
});
const totalVotingPower: number =
Number(totalVotingPowerE8s.subsets[0].value[1]) / 100000000;
setTotalVotingPower(totalVotingPower);
} catch {
setLastRewardsRoundTotalAvailableIcp(undefined);
setTotalVotingPower(undefined);
}
};
And here is how we do the data calculations
if (lastRewardsRoundTotalAvailableIcp !== undefined
&& totalVotingPower !== undefined
&& totalVotingPower > 0) {
let estimatedRewardsPercentage: number | undefined;
let estimatedNeuronDailyRewards: number | undefined;
if (sliderState.dissolveDelayYears >= 0.5) {
const dissolveDelayBonusSlider: number = 1 + sliderState.dissolveDelayYears / 8;
const dailyRewardsIcpPerVotingPowerUnit: number =
lastRewardsRoundTotalAvailableIcp / totalVotingPower;
let ageBonus: number;
if (neuronInfo !== undefined) {
ageBonus =
1 +
Math.min(neuronInfo.ageSeconds, Constants.governanceMaxNeuronAgeForAgeBonusSeconds) /
Constants.governanceMaxNeuronAgeForAgeBonusSeconds / 4;
const dissolveDelayBonusActual: number =
1 + (NeuronInfo.getDissolveDelayBonusPercentage(neuronInfo) ?? 0) / 100;
estimatedNeuronDailyRewards =
neuronInfo.votingPowerE8s / 100000000 *
dailyRewardsIcpPerVotingPowerUnit *
dissolveDelayBonusSlider / dissolveDelayBonusActual;
} else
ageBonus = 1;
const estimatedRewardsIcpPerVotingPowerUnit: number =
dailyRewardsIcpPerVotingPowerUnit * dissolveDelayBonusSlider * ageBonus;
estimatedRewardsPercentage = estimatedRewardsIcpPerVotingPowerUnit * 365.25 * 100;
} else {
estimatedRewardsPercentage = 0;
estimatedNeuronDailyRewards = neuronInfo !== undefined ? 0 : undefined;
}
setEstimatedRewardsPercentage(estimatedRewardsPercentage);
setEstimatedNeuronDailyRewards(estimatedNeuronDailyRewards);
}
}
4 Likes
Thank you! Will take a look in the coming weeks and let you know how it goes.
2 Likes
hi @ngurian,
could you please take a look?
I have a private method that returns dailyRewards (lastRewardsRoundTotalAvailableIcp / totalVotingPower)
private async getIcpDashboardData(): Promise<
| {
dailyRewardsPerVotingPowerUnit: number
}
| undefined
> {
if (this.icpDashboardData) return this.icpDashboardData
try {
const response = await fetch(
"https://ic-api.internetcomputer.org/api/v3/governance-metrics",
)
const data = await response.json()
const latestRewards =
Number(
data.metrics.find(
(element: any) =>
element.name ===
"governance_latest_reward_round_total_available_e8s",
).subsets[0].value[1],
) /
10 ** this.token.getTokenDecimals()
const votingPower: any =
Number(
data.metrics.find(
(element: any) => element.name === "governance_voting_power_total",
).subsets[0].value[1],
) /
10 ** this.token.getTokenDecimals()
this.icpDashboardData = {
dailyRewardsPerVotingPowerUnit: latestRewards / votingPower,
}
return this.icpDashboardData
} catch (e) {
console.error("ICP Dahsboard Error: ", e)
}
}
Also I have two separate methods for calculating apr and rewards:
- APR:
Here I can’t understand what is 4 (ageBonus last devide action)? Is it a constant value or where it can be taken?
async calculateEstAPR(
lockValueInMonths: number,
lockValue: number,
): Promise<string | undefined> {
const data = await this.getIcpDashboardData()
if (data === undefined) return
const dissolveDelayBonusSlider =
1 + lockValueInMonths / (this.getMaximumLockTimeInMonths() / 12)
const ageBonus =
1 +
Math.min(lockValue, Number(this.params.max_neuron_age_for_age_bonus[0])) /
Number(this.params.max_neuron_age_for_age_bonus[0]) /
4
const estimatedRewardsIcpPerVotingPowerUnit: number =
data.dailyRewardsPerVotingPowerUnit * dissolveDelayBonusSlider * ageBonus
return `${(estimatedRewardsIcpPerVotingPowerUnit * 365.25 * 100).toFixed(
2,
)}%`
}
- Projected Rewards:
I am confused where should I take the votingPowerE8s variable??
async calculateProjectRewards(
amount: string,
lockValueInMonths: number,
): Promise<TokenValue | undefined> {
const data = await this.getIcpDashboardData()
if (data === undefined) return
const { dailyRewardsPerVotingPowerUnit } = data
const dissolveDelayBonusSlider =
1 + lockValueInMonths / 12 / this.getMaximumLockTimeInMonths() / 12
const dissolveDelayBonusActual =
1 +
(Number(this.params.max_dissolve_delay_bonus_percentage[0]) ?? 0) / 100
const votingPowerE8s = 1 // ???
const estimatedNeuronDailyRewards =
((votingPowerE8s / 10 ** this.token.getTokenDecimals()) *
dailyRewardsPerVotingPowerUnit *
dissolveDelayBonusSlider) /
dissolveDelayBonusActual
const value = (estimatedNeuronDailyRewards * lockValueInMonths * 30)
.toFixed(this.token.getTokenDecimals())
.replace(TRIM_ZEROS, "")
return {
getTokenValue: () => `${value} ${this.token.getTokenSymbol()}`,
getUSDValue: () =>
this.token.getTokenRateFormatted(value) || "Not listed",
}
}
1 Like