Skip to content

Commit

Permalink
fix: pallets staking progress historicApi (#761)
Browse files Browse the repository at this point in the history
* update pallets staking progress to use historicApi

* lint
  • Loading branch information
TarikGul authored Nov 11, 2021
1 parent 6a8a0c9 commit 9e53d2a
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 47 deletions.
57 changes: 31 additions & 26 deletions src/services/pallets/PalletsStakingProgressService.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { ApiPromise } from '@polkadot/api';
import { ApiDecoration } from '@polkadot/api/types';
import { EraIndex, Hash } from '@polkadot/types/interfaces';
import { InternalServerError } from 'http-errors';

Expand All @@ -16,21 +17,21 @@ import { validators789629Hex } from '../test-helpers/mock/data/validators789629H
import palletsStakingProgress789629SResponse from '../test-helpers/responses/pallets/stakingProgress789629.json';
import { PalletsStakingProgressService } from './PalletsStakingProgressService';

const epochIndexAt = (_hash: Hash) =>
const epochIndexAt = () =>
Promise.resolve().then(() => polkadotRegistry.createType('u64', 330));

const genesisSlotAt = (_hash: Hash) =>
const genesisSlotAt = () =>
Promise.resolve().then(() => polkadotRegistry.createType('u64', 265084563));

const currentSlotAt = (_hash: Hash) =>
const currentSlotAt = () =>
Promise.resolve().then(() => polkadotRegistry.createType('u64', 265876724));

const currentIndexAt = (_hash: Hash) =>
const currentIndexAt = () =>
Promise.resolve().then(() =>
polkadotRegistry.createType('SessionIndex', 330)
);

const eraElectionStatusAt = (_hash: Hash) =>
const eraElectionStatusAt = () =>
Promise.resolve().then(() =>
polkadotRegistry.createType('ElectionStatus', { Close: null })
);
Expand All @@ -40,21 +41,20 @@ const validatorsAt = () =>
polkadotRegistry.createType('Vec<ValidatorId>', validators789629Hex)
);

const forceEraAt = (_hash: Hash) =>
const forceEraAt = () =>
Promise.resolve().then(() =>
polkadotRegistry.createType('Forcing', 'NotForcing')
);

const unappliedSlashesAt = (_hash: Hash, _activeEra: EraIndex) =>
const unappliedSlashesAt = (_activeEra: EraIndex) =>
Promise.resolve().then(() =>
polkadotRegistry.createType('Vec<UnappliedSlash>', [])
);

const validatorCountAt = (_hash: Hash) =>
const validatorCountAt = () =>
Promise.resolve().then(() => polkadotRegistry.createType('u32', 197));

const mockApi = {
...defaultMockApi,
const mockHistoricApi = {
consts: {
babe: {
epochDuration: polkadotRegistry.createType('u64', 2400),
Expand All @@ -66,23 +66,28 @@ const mockApi = {
},
query: {
babe: {
currentSlot: { at: currentSlotAt },
epochIndex: { at: epochIndexAt },
genesisSlot: { at: genesisSlotAt },
currentSlot: currentSlotAt,
epochIndex: epochIndexAt,
genesisSlot: genesisSlotAt,
},
session: {
currentIndex: { at: currentIndexAt },
currentIndex: currentIndexAt,
validators: validatorsAt,
},
staking: {
activeEra: { at: activeEraAt },
eraElectionStatus: { at: eraElectionStatusAt },
erasStartSessionIndex: { at: erasStartSessionIndexAt },
forceEra: { at: forceEraAt },
unappliedSlashes: { at: unappliedSlashesAt },
validatorCount: { at: validatorCountAt },
activeEra: activeEraAt,
eraElectionStatus: eraElectionStatusAt,
erasStartSessionIndex: erasStartSessionIndexAt,
forceEra: forceEraAt,
unappliedSlashes: unappliedSlashesAt,
validatorCount: validatorCountAt,
},
},
} as unknown as ApiDecoration<'promise'>;

const mockApi = {
...defaultMockApi,
at: (_hash: Hash) => mockHistoricApi,
} as unknown as ApiPromise;

/**
Expand All @@ -92,7 +97,7 @@ const palletStakingProgressService = new PalletsStakingProgressService(mockApi);

describe('PalletStakingProgressService', () => {
describe('derivePalletStakingProgress', () => {
(mockApi.query.session.validators as unknown) = { at: validatorsAt };
(mockHistoricApi.query.session.validators as unknown) = validatorsAt;

it('works when ApiPromise works (block 789629)', async () => {
expect(
Expand All @@ -105,7 +110,7 @@ describe('PalletStakingProgressService', () => {
});

it('throws when ErasStartSessionIndex.isNone', async () => {
(mockApi.query.staking.erasStartSessionIndex as any).at = () =>
(mockHistoricApi.query.staking.erasStartSessionIndex as any) = () =>
Promise.resolve().then(() =>
polkadotRegistry.createType('Option<SessionIndex>', null)
);
Expand All @@ -120,12 +125,12 @@ describe('PalletStakingProgressService', () => {
)
);

(mockApi.query.staking.erasStartSessionIndex as any).at =
(mockHistoricApi.query.staking.erasStartSessionIndex as any) =
erasStartSessionIndexAt;
});

it('throws when activeEra.isNone', async () => {
(mockApi.query.staking.activeEra as any).at = () =>
(mockHistoricApi.query.staking.activeEra as any) = () =>
Promise.resolve().then(() =>
polkadotRegistry.createType('Option<ActiveEraInfo>', null)
);
Expand All @@ -138,8 +143,8 @@ describe('PalletStakingProgressService', () => {
new InternalServerError('ActiveEra is None when Some was expected.')
);

(mockApi.query.staking.activeEra as any).at = activeEraAt;
(mockApi.query.session.validators as unknown) = validatorsAt;
(mockHistoricApi.query.staking.activeEra as any) = activeEraAt;
(mockHistoricApi.query.session.validators as unknown) = validatorsAt;
});
});
});
49 changes: 28 additions & 21 deletions src/services/pallets/PalletsStakingProgressService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ApiPromise } from '@polkadot/api';
import { ApiDecoration } from '@polkadot/api/types';
import { BlockHash, EraIndex } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import { InternalServerError } from 'http-errors';
Expand All @@ -16,12 +17,13 @@ export class PalletsStakingProgressService extends AbstractService {
hash: BlockHash
): Promise<IPalletStakingProgress> {
const { api } = this;
const historicApi = await api.at(hash);

const [validatorCount, forceEra, validators, { number }] =
await Promise.all([
api.query.staking.validatorCount.at(hash),
api.query.staking.forceEra.at(hash),
api.query.session.validators.at(hash),
historicApi.query.staking.validatorCount(),
historicApi.query.staking.forceEra(),
historicApi.query.session.validators(),
api.rpc.chain.getHeader(hash),
]);

Expand All @@ -32,8 +34,8 @@ export class PalletsStakingProgressService extends AbstractService {
* runtime less than v0.8.30 it will return a successful result. If it doesn't
* we do nothing and let `eraElectionStatus` stay undefined.
*/
if (api.query.staking.eraElectionStatus) {
eraElectionStatus = await api.query.staking.eraElectionStatus.at(hash);
if (historicApi.query.staking.eraElectionStatus) {
eraElectionStatus = await historicApi.query.staking.eraElectionStatus();
}

const {
Expand All @@ -42,10 +44,10 @@ export class PalletsStakingProgressService extends AbstractService {
sessionLength,
sessionProgress,
activeEra,
} = await this.deriveSessionAndEraProgress(api, hash);
} = await this.deriveSessionAndEraProgress(historicApi);

const unappliedSlashesAtActiveEra =
await api.query.staking.unappliedSlashes.at(hash, activeEra);
await historicApi.query.staking.unappliedSlashes(activeEra);

const currentBlockNumber = number.toBn();

Expand Down Expand Up @@ -78,7 +80,11 @@ export class PalletsStakingProgressService extends AbstractService {
? nextSession // there is a new era every session
: eraLength.sub(eraProgress).add(currentBlockNumber); // the nextActiveEra is at the end of this era

const electionLookAhead = await this.deriveElectionLookAhead(api, hash);
const electionLookAhead = await this.deriveElectionLookAhead(
api,
historicApi,
hash
);

const nextCurrentEra = nextActiveEra
.sub(currentBlockNumber)
Expand Down Expand Up @@ -120,8 +126,7 @@ export class PalletsStakingProgressService extends AbstractService {
* @param hash `BlockHash` to make call at
*/
private async deriveSessionAndEraProgress(
api: ApiPromise,
hash: BlockHash
historicApi: ApiDecoration<'promise'>
): Promise<{
eraLength: BN;
eraProgress: BN;
Expand All @@ -136,11 +141,11 @@ export class PalletsStakingProgressService extends AbstractService {
currentIndex,
activeEraOption,
] = await Promise.all([
api.query.babe.currentSlot.at(hash),
api.query.babe.epochIndex.at(hash),
api.query.babe.genesisSlot.at(hash),
api.query.session.currentIndex.at(hash),
api.query.staking.activeEra.at(hash),
historicApi.query.babe.currentSlot(),
historicApi.query.babe.epochIndex(),
historicApi.query.babe.genesisSlot(),
historicApi.query.session.currentIndex(),
historicApi.query.staking.activeEra(),
]);

if (activeEraOption.isNone) {
Expand All @@ -152,7 +157,7 @@ export class PalletsStakingProgressService extends AbstractService {
const { index: activeEra } = activeEraOption.unwrap();

const activeEraStartSessionIndexOption =
await api.query.staking.erasStartSessionIndex.at(hash, activeEra);
await historicApi.query.staking.erasStartSessionIndex(activeEra);
if (activeEraStartSessionIndexOption.isNone) {
throw new InternalServerError(
'EraStartSessionIndex is None when Some was expected.'
Expand All @@ -161,8 +166,9 @@ export class PalletsStakingProgressService extends AbstractService {
const activeEraStartSessionIndex =
activeEraStartSessionIndexOption.unwrap();

const { epochDuration: sessionLength } = api.consts.babe;
const eraLength = api.consts.staking.sessionsPerEra.mul(sessionLength);
const { epochDuration: sessionLength } = historicApi.consts.babe;
const eraLength =
historicApi.consts.staking.sessionsPerEra.mul(sessionLength);
const epochStartSlot = epochIndex.mul(sessionLength).add(genesisSlot);
const sessionProgress = currentSlot.sub(epochStartSlot);
const eraProgress = currentIndex
Expand Down Expand Up @@ -191,14 +197,15 @@ export class PalletsStakingProgressService extends AbstractService {
*/
private async deriveElectionLookAhead(
api: ApiPromise,
historicApi: ApiDecoration<'promise'>,
hash: BlockHash
): Promise<BN> {
if (api.consts.staking.electionLookahead) {
return api.consts.staking.electionLookahead as unknown as BN;
if (historicApi.consts.staking.electionLookahead) {
return historicApi.consts.staking.electionLookahead as unknown as BN;
}

const { specName } = await api.rpc.state.getRuntimeVersion(hash);
const { epochDuration } = api.consts.babe;
const { epochDuration } = historicApi.consts.babe;

// TODO - create a configurable epochDivisor env for a more generic solution
const epochDurationDivisor =
Expand Down

0 comments on commit 9e53d2a

Please sign in to comment.