@substrate/api-sidecar
Version:
REST service that makes it easy to interact with blockchain nodes built using Substrate's FRAME framework.
109 lines • 4.76 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PalletsStakingValidatorsService = void 0;
const badStakingBlocks_1 = require("../../util/badStakingBlocks");
const AbstractService_1 = require("../AbstractService");
class PalletsStakingValidatorsService extends AbstractService_1.AbstractService {
/**
* Fetch all validators addresses and their status at a given block.
* The status of the validator can be either:
* - `active` (validator is part of the active set) or
* - `waiting` (validator did not get into the active set this era)
*
* @param hash `BlockHash` to make call at
*/
async derivePalletStakingValidators(hash) {
const { api } = this;
const historicApi = await api.at(hash);
if (!historicApi.query.staking) {
throw new Error('Staking pallet not found for queried runtime');
}
const [{ number }, validatorsEntries] = await Promise.all([
api.rpc.chain.getHeader(hash),
historicApi.query.staking.validators.entries(),
]);
const at = {
hash,
height: number.unwrap().toString(10),
};
if ((0, badStakingBlocks_1.isBadStakingBlock)(this.specName, number.unwrap().toNumber())) {
let chainName = this.specName;
switch (this.specName) {
case 'westmint':
chainName = 'Westend Asset Hub';
break;
}
throw new Error(`Post migration, there were some interruptions to staking on ${chainName}, Block ${number.unwrap().toString(10)} is in the list of known bad staking blocks in ${chainName}`);
}
// Populating the returned array with the Validator address and its
// status. If the address is found in the `validatorsActiveSet` then
// status is `active` otherwise is set to `waiting`
const validators = [];
// Active validators that wont be part of the next active validator set
// for the incoming era.
const validatorsToBeChilled = [];
const validatorsActiveSet = await this.getActiveValidators(historicApi);
validatorsEntries.map(([key, prefs]) => {
const address = key.args.map((k) => k.toString())[0];
let status;
if (validatorsActiveSet.has(address)) {
status = 'active';
validatorsActiveSet.delete(address);
}
else {
status = 'waiting';
}
validators.push({
address,
status,
commission: prefs.commission ? prefs.commission.unwrap().toString() : undefined,
blocked: prefs.blocked ? prefs.blocked.isTrue : false,
});
});
// Any validators remaining in validatorsActiveSet are active in the current session
// but don't have entries in staking.validators, which means they're being chilled
if (validatorsActiveSet.size > 0) {
validatorsActiveSet.forEach((address) => {
validators.push({ address, status: 'active' });
validatorsToBeChilled.push({ address, status: 'active' });
});
}
return {
at,
validators,
validatorsToBeChilled,
};
}
/**
* Get the active validators given an era.
*
* @param historicApi
*/
async getActiveValidators(historicApi) {
const validatorsActiveSet = new Set();
if (historicApi.query.staking.erasStakersOverview) {
let activeEra;
const activeEraOption = await historicApi.query.staking.activeEra();
if (activeEraOption.isNone) {
const currentEraOption = await historicApi.query.staking.currentEra();
if (currentEraOption.isNone)
throw new Error('No active or current era was found');
activeEra = currentEraOption.unwrap();
}
else {
activeEra = activeEraOption.unwrap().index;
}
const vals = await historicApi.query.staking.erasStakersOverview.keys(activeEra);
vals.forEach(({ args }) => validatorsActiveSet.add(args[1].toString()));
}
else {
const validatorSession = await historicApi.query.session.validators();
for (const address of validatorSession) {
validatorsActiveSet.add(address.toString());
}
}
return validatorsActiveSet;
}
}
exports.PalletsStakingValidatorsService = PalletsStakingValidatorsService;
//# sourceMappingURL=PalletsStakingValidatorsService.js.map