2

I'm trying to figure out how to accurately determine the total amount of token rewards received by a nominator in the network. Specifically, I'm interested in the following:

  1. The Total Rewards in Tokens: I am seeking a method to calculate the total tokens (not reward points) that a nominator has accrued to date for their role in nominating validators. This figure represents the nominator's total payouts from staking activity.
  2. Address-Specific Query: The solution should allow for querying this information based on a specific nominator's address.

Steps I followed to get this data:

  1. Retrieve the eras in which the address has claimed rewards. Below is the code snippet:

    const data = await api.query.staking.ledger(address);
    const ledger = data.unwrap();
    const claimedRewards = ledger.claimedRewards;
    

    enter image description here

  2. Loop through each era to obtain the totalRewardPoints received by the address in that era, as well as the totalRewardPoints for all addresses combined.

  3. Fetch the totalRewardedAmount in tokens for an era:

     const totalRewardedAmount = await api.query.staking.erasValidatorReward(
        rewardedEra
      );
    
  4. I couldn’t find official documentation for the formula to calculate the total rewarded amount for a nominator in a specific era, but I obtained this formula from ChatGPT:

    totalRewardedTokensOfNominatorInAnEra = (nominatorRewardPointsOfTheEra / totalRewardedPointsOfTheEra) * totalRewardedTokensOfTheEra

Below is the full code snippet of the getTotalRewardedAmount function:

const getTotalRewardedAmount = async (address: string) => {
  const api = await getPolkadotApiPromise();

  if (!api) return '';

  try {
    const data = await api.query.staking.ledger(address);
    const ledger = data.unwrapOrDefault();
    const claimedRewards = ledger.claimedRewards;

    const rewardedEras = claimedRewards.map((claimedReward) =>
      claimedReward.toNumber()
    );

    for (const rewardedEra of rewardedEras) {
      const eraReward = await api.query.staking.erasRewardPoints(rewardedEra);
      const individuals = JSON.parse(JSON.stringify(eraReward.individual));
      let individualRewardPoints = individuals[address] || 0;

      individualRewardPoints = Number(individualRewardPoints);
      const totalRewardedPoints = eraReward.total.toNumber();

      const totalRewardedAmount = await api.query.staking.erasValidatorReward(
        rewardedEra
      );
      
      const totalRewardedTokens = Number(totalRewardedAmount.toString());

      const individualRewardTokens =
        (individualRewardPoints / totalRewardedPoints) * totalRewardedTokens;

      console.log(
        `Total Rewarded Tokens for Nominator: ${individualRewardTokens} for Era: ${rewardedEra}`
      );
    }

    return '';
  } catch (e) {
    console.error(e);
    return '';
  }
};

When using this function, I'm not obtaining the correct values. Also, it appears there’s no straightforward solution to calculate the total rewards (in tokens, not points) earned by a nominator. The calculation involves considering factors like validator commission, total rewards given in an era, etc.

I am seeking guidance on the appropriate API queries to perform for this task. Is there a specific module or function that facilitates this kind of query? Thank you in advance for your assistance!

1 Answer 1

0

pallet-staking does not store payout information since this will just inflate the storage. Possible option

  • You can also query Rewarded events which can give you account and reward details (Given you have an archival node to store previous events)

https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/staking/src/pallet/impls.rs#L283

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.