ICP/SNS staking rewards calculation?

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);
    } 
  }
3 Likes

Thank you! Will take a look in the coming weeks and let you know how it goes.

2 Likes