Skip to content

Commit

Permalink
feat(refactor): Remove pre-paged rewards code (part 1) (#2101)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ross Bulat committed Apr 30, 2024
1 parent 4851436 commit 6fa02f9
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 103 deletions.
106 changes: 27 additions & 79 deletions src/contexts/Payouts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { rmCommas, setStateWithRef } from '@w3ux/utils';
import BigNumber from 'bignumber.js';
import { useNetwork } from 'contexts/Network';
import { useActiveAccounts } from 'contexts/ActiveAccounts';
import { NetworksWithPagedRewards } from 'config/networks';
import { MaxSupportedPayoutEras, defaultPayoutsContext } from './defaults';
import type {
LocalValidatorExposure,
Expand All @@ -35,9 +34,9 @@ export const usePayouts = () => useContext(PayoutsContext);

export const PayoutsProvider = ({ children }: { children: ReactNode }) => {
const { network } = useNetwork();
const { api, consts, activeEra } = useApi();
const { activeAccount } = useActiveAccounts();
const { isNominating, fetchEraStakers } = useStaking();
const { api, consts, activeEra, isPagedRewardsActive } = useApi();
const { maxExposurePageSize } = consts;

// Store active accont's payout state.
Expand Down Expand Up @@ -162,21 +161,6 @@ export const PayoutsProvider = ({ children }: { children: ReactNode }) => {
new BigNumber(b).minus(a).toNumber()
);

// Helper function to check which eras a validator was exposed in.
const validatorExposedEras = (validator: string) => {
const exposedEras: string[] = [];
for (const era of erasToCheck) {
if (
Object.values(
Object.keys(getLocalEraExposure(network, era, activeAccount))
)?.[0] === validator
) {
exposedEras.push(era);
}
}
return exposedEras;
};

// Fetch controllers in order to query ledgers.
const bondedResults =
await api.query.staking.bonded.multi<AnyApi>(uniqueValidators);
Expand All @@ -193,70 +177,34 @@ export const PayoutsProvider = ({ children }: { children: ReactNode }) => {

// Refer to new `ClaimedRewards` storage item and calculate unclaimed rewards from that and
// `exposedPage` stored locally in exposure data.
if (isPagedRewardsActive(activeEra.index)) {
// Accumulate calls to fetch unclaimed rewards for each era for all validators.
const unclaimedRewardsEntries = erasToCheck
.map((era) => uniqueValidators.map((v) => [era, v]))
.flat();

const results = await Promise.all(
unclaimedRewardsEntries.map(([era, v]) =>
api.query.staking.claimedRewards<AnyApi>(era, v)
)
);

for (let i = 0; i < results.length; i++) {
const pages = results[i].toHuman() || [];
const era = unclaimedRewardsEntries[i][0];
const validator = unclaimedRewardsEntries[i][1];
const exposure = getLocalEraExposure(network, era, activeAccount);
const exposedPage =
exposure?.[validator]?.exposedPage !== undefined
? String(exposure[validator].exposedPage)
: undefined;

// Add to `unclaimedRewards` if payout page has not yet been claimed.
if (!pages.includes(exposedPage)) {
if (unclaimedRewards?.[validator]) {
unclaimedRewards[validator].push(era);
} else {
unclaimedRewards[validator] = [era];
}
}
}
} else {
// DEPRECATION: Paged Rewards
//
// Use `staking.ledger` to get unclaimed reward eras. Read `legacyClaimedRewards`
// if paged rewards are active, otherwise use `claimedRewards`.
const ledgerResults = await api.query.staking.ledger.multi<AnyApi>(
Object.values(validatorControllers)
);
// Accumulate calls to fetch unclaimed rewards for each era for all validators.
const unclaimedRewardsEntries = erasToCheck
.map((era) => uniqueValidators.map((v) => [era, v]))
.flat();

const results = await Promise.all(
unclaimedRewardsEntries.map(([era, v]) =>
api.query.staking.claimedRewards<AnyApi>(era, v)
)
);

// Fetch ledgers to determine which eras have not yet been claimed per validator. Only
// includes eras that are in `erasToCheck`.
for (const ledgerResult of ledgerResults) {
const ledger = ledgerResult.unwrapOr(null)?.toHuman();
if (ledger) {
// get claimed eras within `erasToCheck`.
const erasClaimed = ledger[
NetworksWithPagedRewards.includes(network)
? 'legacyClaimedRewards'
: 'claimedRewards'
]
.map((e: string) => rmCommas(e))
.filter(
(e: string) =>
new BigNumber(e).isLessThanOrEqualTo(startEra) &&
new BigNumber(e).isGreaterThanOrEqualTo(endEra)
);

// filter eras yet to be claimed
unclaimedRewards[ledger.stash] = erasToCheck.filter(
(era) =>
validatorExposedEras(ledger.stash).includes(era) &&
!erasClaimed.includes(era)
);
for (let i = 0; i < results.length; i++) {
const pages = results[i].toHuman() || [];
const era = unclaimedRewardsEntries[i][0];
const validator = unclaimedRewardsEntries[i][1];
const exposure = getLocalEraExposure(network, era, activeAccount);
const exposedPage =
exposure?.[validator]?.exposedPage !== undefined
? String(exposure[validator].exposedPage)
: undefined;

// Add to `unclaimedRewards` if payout page has not yet been claimed.
if (!pages.includes(exposedPage)) {
if (unclaimedRewards?.[validator]) {
unclaimedRewards[validator].push(era);
} else {
unclaimedRewards[validator] = [era];
}
}
}
Expand Down
15 changes: 4 additions & 11 deletions src/modals/ClaimPayouts/Forms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const Forms = forwardRef(
ref: ForwardedRef<HTMLDivElement>
) => {
const { t } = useTranslation('modals');
const { api, isPagedRewardsActive } = useApi();
const { api } = useApi();
const {
networkData: { units, unit },
} = useNetwork();
Expand Down Expand Up @@ -68,16 +68,9 @@ export const Forms = forwardRef(
if (!paginatedValidators) {
return [];
}

return paginatedValidators.forEach(([page, v]) => {
if (isPagedRewardsActive(new BigNumber(era))) {
return calls.push(api.tx.staking.payoutStakersByPage(v, era, page));
}
// DEPRECATION: Paged Rewards
//
// Fall back to deprecated `payoutStakers` if not on paged reward era.
return calls.push(api.tx.staking.payoutStakers(v, era));
});
return paginatedValidators.forEach(([page, v]) =>
calls.push(api.tx.staking.payoutStakersByPage(v, era, page))
);
});
return calls;
};
Expand Down
15 changes: 2 additions & 13 deletions src/model/Api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {
} from 'contexts/Api/types';
import { SyncController } from 'controllers/SyncController';
import type { AnyApi, NetworkName } from 'types';
import { NetworkList, NetworksWithPagedRewards } from 'config/networks';
import { NetworkList } from 'config/networks';
import { makeCancelable, rmCommas, stringToBigNumber } from '@w3ux/utils';
import { WellKnownChain } from '@substrate/connect';
import type { BlockNumber } from '@polkadot/types/interfaces';
Expand Down Expand Up @@ -245,20 +245,9 @@ export class Api {
this.api.consts.staking.historyDepth,
this.api.consts.fastUnstake.deposit,
this.api.consts.nominationPools.palletId,
this.api.consts.staking.maxExposurePageSize,
];

// DEPRECATION: Paged Rewards
//
// Fetch `maxExposurePageSize` instead of `maxNominatorRewardedPerValidator` for networks that
// have paged rewards.
if (NetworksWithPagedRewards.includes(this.network)) {
allPromises.push(this.api.consts.staking.maxExposurePageSize);
} else {
allPromises.push(
this.api.consts.staking.maxNominatorRewardedPerValidator
);
}

const consts = await Promise.all(allPromises);

// Fetch the active era. Needed for previous era and for queries below.
Expand Down

0 comments on commit 6fa02f9

Please sign in to comment.