-
Notifications
You must be signed in to change notification settings - Fork 162
fix: added staking.claimed() in replacement of staking.ledger().legacyClaimedRewards
#1436
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
marshacb
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
| const startEra = Math.max(0, sanitizedEra - (depth - 1)); | ||
| const runtimeInfo = await this.api.rpc.state.getRuntimeVersion(at.hash); | ||
| const isKusama = runtimeInfo.specName.toString().toLowerCase() === 'kusama'; | ||
| const stakingVersion = await historicApi.query.staking.palletVersion<u16>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an awesome call. Has this been around for a bit? Is it safe to use historically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it has been around since v13. Before that it was api.query.staking.storageVersion() and it returned a type Releases first and then PalletStakingReleases, that went from V0 to V12_0_0
| return { | ||
| commission, | ||
| }; | ||
| } else if (stakingVersion < 14) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have serious doubts about using staking.palletVersion.
By adding this check here for older eras even if legacyClaimedRewards has values it is skipping and checking the claimedRewards which does not have any values for that era. So then it does not return payouts.
Example
For account 1123RekaPHgWaPL5v9qfsikRemeZdYC4tvKXYuLXwhfT3NKy and era 1366 it should give payouts but it does not.
http://127.0.0.1:8080/accounts/1123RekaPHgWaPL5v9qfsikRemeZdYC4tvKXYuLXwhfT3NKy/staking-payouts?unclaimedOnly=false&era=1366
Payouts shown in Subscan
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made some changes and reduced the use of the stakingVersion. The bug you mention was a few lines below, but I changed it so that if the stakingVersion is below 14, it goes with the old logic, but if it's not, instead of replacing validatorLedger.legacyClaimedRewards with claimedRewards, the value of the era gets added to the array.
| if (validatorLedger.legacyClaimedRewards) { | ||
| if (validatorLedger.legacyClaimedRewards && stakingVersion < 14) { | ||
| indexOfEra = validatorLedger.legacyClaimedRewards.indexOf(eraIndex); | ||
| } else if (stakingVersion >= 14) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we add this check here, whenever the staking pallet version is >= 14, variable claimed will result to true correct ? That does not seem right but maybe I am missing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome catch! That's right, I changed it and should not happen now
| } else if (stakingVersion < 14) { | ||
| validatorLedger = validatorLedgerOption.unwrap(); | ||
| } else { | ||
| validatorLedger = validatorLedgerOption.unwrap(); | ||
| const claimed = await historicApi.query.staking.claimedRewards(era, validatorControllerOption.unwrap()); | ||
| if (claimed.length > 0) { | ||
| validatorLedger.legacyClaimedRewards.push(era as unknown as u32); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| } else if (stakingVersion < 14) { | |
| validatorLedger = validatorLedgerOption.unwrap(); | |
| } else { | |
| validatorLedger = validatorLedgerOption.unwrap(); | |
| const claimed = await historicApi.query.staking.claimedRewards(era, validatorControllerOption.unwrap()); | |
| if (claimed.length > 0) { | |
| validatorLedger.legacyClaimedRewards.push(era as unknown as u32); | |
| } | |
| } | |
| validatorLedger = validatorLedgerOption.unwrap(); | |
| if (historicApi.query.staking.claimedRewards) { | |
| const claimed = await historicApi.query.staking.claimedRewards(era, validatorControllerOption.unwrap()); | |
| if (claimed.length > 0) { | |
| const eraVal: u32 = historicApi.registry.createType('u32', era); | |
| validatorLedger.legacyClaimedRewards.push(eraVal); | |
| } |
-
Since in both cases we
unwrap, we can put it outside theifs and that way we call it once. -
We could avoid checking
stakingVersionif we just check ifclaimedRewardsexists. That way we don't need an extra call or to passstakingVersionthrough the methods. -
I changed how you push the
erabecause if we pushera as unknown as u32, it messes up with the types of theVec.- If you check in debug mode
validatorLedger.legacyClaimedRewardsyou will see before the push it is Type(8) [u32, u32, u32, u32, u32, u32, u32, u32- and after adding the additional era, it becomes
Type(8) [u32, u32, u32, u32, u32, u32, u32, u32, 6585 - and then calls like
validatorLedger.legacyClaimedRewards.toHuman()also break
Note: the use of
createTypeis discouraged but in this case, I only found this way to make it work. - If you check in debug mode
-
Since we do not use the variable
claimedwe do not have to store the call. We could just doif ((await historicApi.query.staking.claimedRewards(era, validatorControllerOption.unwrap())).length > 0) {- but this is up to you! By storing, the code is also more clear also so yeah.
-
Question: Why when it retrieves the
claimedRewardsfor the era the result is0? is it something to be fixed in pjs-api ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Done.
- Done.
- Nice one, done.
- Done.
claimedRewardsreturns the index of thereward pagesthat were claimed. So if only the first page was claimed, it returns0, if pages 1 and 2,0,1, and so on.
Imod7
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is another thing to take into account either in this PR or I will add an issue to make the change in the future.
legacyClaimed... will be removed (related PR) so when this happens, this line
validatorLedger.legacyClaimedRewards.push(eraVal);
will break. For now we can add a check if it exists
if (validatorLedger.legacyClaimedRewards) {
...
}
Imod7
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to the complexity and the number of changes, I checked out a new branch from your branch of this PR so you can review & test. All changes are mentioned here
|
Closing this PR in favor of #1579 |
Description
After the staking pallet was upgraded to v14 in Polkadot,

legacyClaimedRewardsis no longer used, so any for any eras after 1418, the era is no longer stored there but instaking.claimed(Era, Account), so querying the former would make it look like the rewards weren't claimed when in turn they were, as you can see here:With this PR it checks the staking pallet version, and if it's less than 14, it sticks to the old logic, otherwise
staking.claimedtakes the place oflegacyClaimedRewards, as seen here.With this fix, it returns the correct status:

NOTE
staking.claimed()returns the page of the claimed reward, whilelegacyClaimedRewardsinstead contains the list of eras claimed. So we assume that ifstaking.claimed()returns anything other than an empty array, the era was claimed.Edit: added image of response after fix
Edit 2: wrong era