@substrate/api-sidecar 17.5.1 → 17.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "17.5.1",
2
+ "version": "17.5.2",
3
3
  "name": "@substrate/api-sidecar",
4
4
  "description": "REST service that makes it easy to interact with blockchain nodes built using Substrate's FRAME framework.",
5
5
  "homepage": "https://github.com/paritytech/substrate-api-sidecar#readme",
@@ -50,29 +50,29 @@
50
50
  "test:test-release": "yarn build:scripts && node scripts/build/runYarnPack.js"
51
51
  },
52
52
  "dependencies": {
53
- "@polkadot/api": "^10.11.2",
54
- "@polkadot/api-contract": "^10.11.2",
53
+ "@polkadot/api": "^10.11.3",
54
+ "@polkadot/api-contract": "^10.11.3",
55
55
  "@polkadot/util-crypto": "^12.6.2",
56
56
  "@substrate/calc": "^0.3.1",
57
57
  "argparse": "^2.0.1",
58
58
  "confmgr": "^1.0.10",
59
- "express": "^4.18.1",
59
+ "express": "^4.18.2",
60
60
  "express-winston": "^4.2.0",
61
61
  "http-errors": "^2.0.0",
62
62
  "lru-cache": "^7.13.1",
63
63
  "prom-client": "^14.2.0",
64
- "rxjs": "^7.5.6",
65
- "winston": "^3.8.1"
64
+ "rxjs": "^7.8.1",
65
+ "winston": "^3.11.0"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@substrate/dev": "^0.7.1",
69
- "@types/argparse": "2.0.10",
70
- "@types/express": "^4.17.17",
71
- "@types/express-serve-static-core": "^4.17.36",
69
+ "@types/argparse": "2.0.14",
70
+ "@types/express": "^4.17.21",
71
+ "@types/express-serve-static-core": "^4.17.43",
72
72
  "@types/http-errors": "1.8.2",
73
73
  "@types/lru-cache": "^7.10.10",
74
- "@types/morgan": "1.9.3",
75
- "@types/triple-beam": "^1.3.2",
74
+ "@types/morgan": "1.9.9",
75
+ "@types/triple-beam": "^1.3.5",
76
76
  "ts-node-dev": "^2.0.0"
77
77
  },
78
78
  "keywords": [
@@ -23,6 +23,7 @@ const bn_js_1 = __importDefault(require("bn.js"));
23
23
  const http_errors_1 = require("http-errors");
24
24
  const middleware_1 = require("../../middleware");
25
25
  const services_1 = require("../../services");
26
+ const kusamaEarlyErasBlockInfo_json_1 = __importDefault(require("../../services/accounts/kusamaEarlyErasBlockInfo.json"));
26
27
  const AbstractController_1 = __importDefault(require("../AbstractController"));
27
28
  /**
28
29
  * GET payout information for a stash account.
@@ -85,11 +86,27 @@ class AccountsStakingPayoutsController extends AbstractController_1.default {
85
86
  * @param res Express Response
86
87
  */
87
88
  this.getStakingPayoutsByAccountId = async ({ params: { address }, query: { depth, era, unclaimedOnly, at } }, res) => {
88
- const hash = await this.getHashFromAt(at);
89
- const apiAt = await this.api.at(hash);
89
+ const earlyErasBlockInfo = kusamaEarlyErasBlockInfo_json_1.default;
90
+ let hash = await this.getHashFromAt(at);
91
+ let apiAt = await this.api.at(hash);
90
92
  const { eraArg, currentEra } = await this.getEraAndHash(apiAt, this.verifyAndCastOr('era', era, undefined));
93
+ if (currentEra <= 519 && depth !== undefined) {
94
+ throw new http_errors_1.InternalServerError('The `depth` query parameter is disabled for eras less than 518.');
95
+ }
96
+ else if (currentEra <= 519 && era !== undefined) {
97
+ throw new http_errors_1.InternalServerError('The `era` query parameter is disabled for eras less than 518.');
98
+ }
99
+ let sanitizedDepth;
100
+ if (depth) {
101
+ sanitizedDepth = Math.min(Number(depth), currentEra - 518).toString();
102
+ }
103
+ if (currentEra < 518) {
104
+ const eraStartBlock = earlyErasBlockInfo[currentEra].start;
105
+ hash = await this.getHashFromAt(eraStartBlock.toString());
106
+ apiAt = await this.api.at(hash);
107
+ }
91
108
  const unclaimedOnlyArg = unclaimedOnly === 'false' ? false : true;
92
- AccountsStakingPayoutsController.sanitizedSend(res, await this.service.fetchAccountStakingPayout(hash, address, this.verifyAndCastOr('depth', depth, 1), eraArg, unclaimedOnlyArg, currentEra, apiAt));
109
+ AccountsStakingPayoutsController.sanitizedSend(res, await this.service.fetchAccountStakingPayout(hash, address, this.verifyAndCastOr('depth', sanitizedDepth, 1), eraArg, unclaimedOnlyArg, currentEra, apiAt));
93
110
  };
94
111
  this.initRoutes();
95
112
  }
@@ -98,15 +115,8 @@ class AccountsStakingPayoutsController extends AbstractController_1.default {
98
115
  this.safeMountAsyncGetHandlers([['', this.getStakingPayoutsByAccountId]]);
99
116
  }
100
117
  async getEraAndHash(apiAt, era) {
101
- const [activeEraOption, currentEraMaybeOption] = await Promise.all([
102
- apiAt.query.staking.activeEra(),
103
- apiAt.query.staking.currentEra(),
104
- ]);
105
- if (activeEraOption.isNone) {
106
- throw new http_errors_1.InternalServerError('ActiveEra is None when Some was expected');
107
- }
108
- const activeEra = activeEraOption.unwrap().index.toNumber();
109
118
  let currentEra;
119
+ const currentEraMaybeOption = (await apiAt.query.staking.currentEra());
110
120
  if (currentEraMaybeOption instanceof types_1.Option) {
111
121
  if (currentEraMaybeOption.isNone) {
112
122
  throw new http_errors_1.InternalServerError('CurrentEra is None when Some was expected');
@@ -120,6 +130,36 @@ class AccountsStakingPayoutsController extends AbstractController_1.default {
120
130
  else {
121
131
  throw new http_errors_1.InternalServerError('Query for current_era returned a non-processable result.');
122
132
  }
133
+ let activeEra;
134
+ if (apiAt.query.staking.activeEra) {
135
+ const activeEraOption = await apiAt.query.staking.activeEra();
136
+ if (activeEraOption.isNone) {
137
+ const historicActiveEra = await apiAt.query.staking.currentEra();
138
+ if (historicActiveEra.isNone) {
139
+ throw new http_errors_1.InternalServerError('ActiveEra is None when Some was expected');
140
+ }
141
+ else {
142
+ activeEra = historicActiveEra.unwrap().toNumber();
143
+ }
144
+ }
145
+ else {
146
+ activeEra = activeEraOption.unwrap().index.toNumber();
147
+ }
148
+ }
149
+ else {
150
+ const sessionIndex = await apiAt.query.session.currentIndex();
151
+ const idx = sessionIndex.toNumber() % 6;
152
+ // https://substrate.stackexchange.com/a/2026/1786
153
+ if (currentEra < 518) {
154
+ activeEra = currentEra;
155
+ }
156
+ else if (idx > 0) {
157
+ activeEra = currentEra;
158
+ }
159
+ else {
160
+ activeEra = currentEra - 1;
161
+ }
162
+ }
123
163
  if (era !== undefined && era > activeEra - 1) {
124
164
  throw new http_errors_1.BadRequest(`The specified era (${era}) is too large. ` + `Largest era payout info is available for is ${activeEra - 1}`);
125
165
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AccountsStakingPayoutsController.js","sourceRoot":"","sources":["../../../../src/controllers/accounts/AccountsStakingPayoutsController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AccountsStakingPayoutsController.js","sourceRoot":"","sources":["../../../../src/controllers/accounts/AccountsStakingPayoutsController.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import type { ApiDecoration } from '@polkadot/api/types';
2
2
  import type { DeriveEraExposure, DeriveEraExposureNominating } from '@polkadot/api-derive/staking/types';
3
- import type { Option } from '@polkadot/types';
4
- import type { BalanceOf, BlockHash, EraIndex, Perbill } from '@polkadot/types/interfaces';
3
+ import { Option } from '@polkadot/types';
4
+ import type { BalanceOf, BlockHash, EraIndex, EraPoints, Perbill } from '@polkadot/types/interfaces';
5
5
  import type { PalletStakingEraRewardPoints, PalletStakingStakingLedger } from '@polkadot/types/lookup';
6
6
  import type { IAccountStakingPayouts, IEraPayouts } from '../../types/responses';
7
7
  import { AbstractService } from '../AbstractService';
@@ -9,7 +9,20 @@ import { AbstractService } from '../AbstractService';
9
9
  * General information about an era, in tuple form because we initially get it
10
10
  * by destructuring a Promise.all(...)
11
11
  */
12
- type IErasGeneral = [DeriveEraExposure, PalletStakingEraRewardPoints, Option<BalanceOf>];
12
+ type IErasGeneral = [IAdjustedDeriveEraExposure, PalletStakingEraRewardPoints | EraPoints, Option<BalanceOf>];
13
+ /**
14
+ * Index of the validator for eras previous to 518
15
+ */
16
+ interface ValidatorIndex {
17
+ [x: string]: number;
18
+ }
19
+ /**
20
+ * Adapted AdjustedDeriveEraExposure interface for compatibility with eras
21
+ * previous to 518
22
+ */
23
+ interface IAdjustedDeriveEraExposure extends DeriveEraExposure {
24
+ validatorIndex?: ValidatorIndex;
25
+ }
13
26
  /**
14
27
  * Commission and staking ledger of a validator
15
28
  */
@@ -21,14 +34,28 @@ interface ICommissionAndLedger {
21
34
  * All the data we need to calculate payouts for an address at a given era.
22
35
  */
23
36
  interface IEraData {
24
- deriveEraExposure: DeriveEraExposure;
25
- eraRewardPoints: PalletStakingEraRewardPoints;
37
+ deriveEraExposure: IAdjustedDeriveEraExposure;
38
+ eraRewardPoints: PalletStakingEraRewardPoints | EraPoints;
26
39
  erasValidatorRewardOption: Option<BalanceOf>;
27
40
  exposuresWithCommission?: (ICommissionAndLedger & {
28
41
  validatorId: string;
29
42
  })[];
30
43
  eraIndex: EraIndex;
31
44
  }
45
+ /**
46
+ * Block information relevant for compatibility with eras previous
47
+ * to 518
48
+ */
49
+ interface IBlockInfo {
50
+ height: string;
51
+ hash: BlockHash;
52
+ }
53
+ export interface IEarlyErasBlockInfo {
54
+ [era: string]: {
55
+ start: number;
56
+ end: number;
57
+ };
58
+ }
32
59
  export declare class AccountsStakingPayoutsService extends AbstractService {
33
60
  /**
34
61
  * Fetch and derive payouts for `address`.
@@ -45,22 +72,22 @@ export declare class AccountsStakingPayoutsService extends AbstractService {
45
72
  /**
46
73
  * Fetch general info about eras in the inclusive range `startEra` .. `era`.
47
74
  *
48
- * @param api `ApiPromise`
49
- * @param hash `BlockHash` to make call at
75
+ * @param historicApi Historic api for querying past blocks
50
76
  * @param startEra first era to get data for
51
77
  * @param era the last era to get data for
78
+ * @param blockNumber block information to ensure compatibility with older eras
52
79
  */
53
- fetchAllErasGeneral(historicApi: ApiDecoration<'promise'>, startEra: number, era: number): Promise<IErasGeneral[]>;
80
+ fetchAllErasGeneral(historicApi: ApiDecoration<'promise'>, startEra: number, era: number, blockNumber: IBlockInfo): Promise<IErasGeneral[]>;
81
+ private fetchHistoricRewardPoints;
54
82
  /**
55
83
  * Fetch the commission & staking ledger for each `validatorId` in `deriveErasExposures`.
56
84
  *
57
- * @param api `ApiPromise`
58
- * @param hash `BlockHash` to make call at
85
+ * @param historicApi Historic api for querying past blocks
59
86
  * @param address address of the _Stash_ account to get the payouts of
60
87
  * @param startEra first era to get data for
61
88
  * @param deriveErasExposures exposures per era for `address`
62
89
  */
63
- fetchAllErasCommissions(historicApi: ApiDecoration<'promise'>, address: string, startEra: number, deriveErasExposures: DeriveEraExposure[]): Promise<ICommissionAndLedger[][]>;
90
+ fetchAllErasCommissions(historicApi: ApiDecoration<'promise'>, address: string, startEra: number, deriveErasExposures: IAdjustedDeriveEraExposure[]): Promise<ICommissionAndLedger[][]>;
64
91
  /**
65
92
  * Derive all the payouts for `address` at `era`.
66
93
  *
@@ -74,10 +101,9 @@ export declare class AccountsStakingPayoutsService extends AbstractService {
74
101
  /**
75
102
  * Fetch the `commission` and `StakingLedger` of `validatorId`.
76
103
  *
77
- * @param api
104
+ * @param historicApi Historic api for querying past blocks
78
105
  * @param validatorId accountId of a validator's _Stash_ account
79
106
  * @param era the era to query
80
- * @param hash `BlockHash` to make call at
81
107
  * @param validatorLedgerCache object mapping validatorId => StakingLedger to limit redundant queries
82
108
  */
83
109
  private fetchCommissionAndLedger;
@@ -88,8 +114,8 @@ export declare class AccountsStakingPayoutsService extends AbstractService {
88
114
  * The original version uses the base ApiDerive implementation which does not include the ApiDecoration implementation.
89
115
  * It is required in this version to query older blocks for their historic data.
90
116
  *
91
- * @param historicApi
92
- * @param eraIndex
117
+ * @param historicApi Historic api for querying past blocks
118
+ * @param eraIndex index of the era to query
93
119
  */
94
120
  private deriveEraExposure;
95
121
  /**
@@ -97,6 +123,8 @@ export declare class AccountsStakingPayoutsService extends AbstractService {
97
123
  *
98
124
  * @param eraRewardPoints
99
125
  * @param validatorId accountId of a validator's _Stash_ account
126
+ * @param validatorIndex index of the validator in relation to the `EraPoints`
127
+ * array
100
128
  * */
101
129
  private extractTotalValidatorRewardPoints;
102
130
  /**
@@ -105,7 +133,7 @@ export declare class AccountsStakingPayoutsService extends AbstractService {
105
133
  *
106
134
  * @param address address of the _Stash_ account to get the exposure of behind `validatorId`
107
135
  * @param validatorId accountId of a validator's _Stash_ account
108
- * @param deriveEraExposure
136
+ * @param deriveEraExposure result of deriveEraExposure
109
137
  */
110
138
  private extractExposure;
111
139
  /**
@@ -115,6 +143,6 @@ export declare class AccountsStakingPayoutsService extends AbstractService {
115
143
  * @param address address of the _Stash_ account to get the payouts of
116
144
  * @param deriveEraExposure result of deriveEraExposure
117
145
  */
118
- deriveNominatedExposures(address: string, deriveEraExposure: DeriveEraExposure): DeriveEraExposureNominating[] | undefined;
146
+ deriveNominatedExposures(address: string, deriveEraExposure: IAdjustedDeriveEraExposure): DeriveEraExposureNominating[] | undefined;
119
147
  }
120
148
  export {};
@@ -14,11 +14,15 @@
14
14
  //
15
15
  // You should have received a copy of the GNU General Public License
16
16
  // along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ var __importDefault = (this && this.__importDefault) || function (mod) {
18
+ return (mod && mod.__esModule) ? mod : { "default": mod };
19
+ };
17
20
  Object.defineProperty(exports, "__esModule", { value: true });
18
21
  exports.AccountsStakingPayoutsService = void 0;
19
22
  const calc_1 = require("@substrate/calc");
20
23
  const http_errors_1 = require("http-errors");
21
24
  const AbstractService_1 = require("../AbstractService");
25
+ const kusamaEarlyErasBlockInfo_json_1 = __importDefault(require("./kusamaEarlyErasBlockInfo.json"));
22
26
  class AccountsStakingPayoutsService extends AbstractService_1.AbstractService {
23
27
  /**
24
28
  * Fetch and derive payouts for `address`.
@@ -34,24 +38,28 @@ class AccountsStakingPayoutsService extends AbstractService_1.AbstractService {
34
38
  async fetchAccountStakingPayout(hash, address, depth, era, unclaimedOnly, currentEra, historicApi) {
35
39
  const { api } = this;
36
40
  const { number } = await api.rpc.chain.getHeader(hash);
41
+ const sanitizedEra = era < 0 ? 0 : era;
37
42
  /**
38
43
  * Given https://github.com/polkadot-js/api/issues/5232,
39
44
  * polkadot-js, and substrate treats historyDepth as a consts. In order
40
45
  * to maintain historical integrity we need to make a check to cover both the
41
46
  * storage query and the consts.
42
47
  */
43
- let historyDepth;
48
+ let historyDepth = api.registry.createType('u32', 84);
44
49
  if (historicApi.consts.staking.historyDepth) {
45
50
  historyDepth = historicApi.consts.staking.historyDepth;
46
51
  }
47
- else {
52
+ else if (historicApi.query.staking.historyDepth) {
48
53
  historyDepth = await historicApi.query.staking.historyDepth();
49
54
  }
55
+ else if (currentEra < 518) {
56
+ historyDepth = api.registry.createType('u32', 0);
57
+ }
50
58
  // Information is kept for eras in `[current_era - history_depth; current_era]`
51
- if (depth > historyDepth.toNumber()) {
59
+ if (historyDepth.toNumber() !== 0 && depth > historyDepth.toNumber()) {
52
60
  throw new http_errors_1.BadRequest('Must specify a depth less than history_depth');
53
61
  }
54
- if (era - (depth - 1) < currentEra - historyDepth.toNumber()) {
62
+ if (era - (depth - 1) < currentEra - historyDepth.toNumber() && historyDepth.toNumber() !== 0) {
55
63
  // In scenarios where depth is not > historyDepth, but the user specifies an era
56
64
  // and historyDepth combo that would lead to querying eras older than history depth
57
65
  throw new http_errors_1.BadRequest('Must specify era and depth such that era - (depth - 1) is less ' +
@@ -62,9 +70,9 @@ class AccountsStakingPayoutsService extends AbstractService_1.AbstractService {
62
70
  hash,
63
71
  };
64
72
  // User friendly - we don't error if the user specified era & depth combo <= 0, instead just start at 0
65
- const startEra = Math.max(0, era - (depth - 1));
73
+ const startEra = Math.max(0, sanitizedEra - (depth - 1));
66
74
  // Fetch general data about the era
67
- const allErasGeneral = await this.fetchAllErasGeneral(historicApi, startEra, era);
75
+ const allErasGeneral = await this.fetchAllErasGeneral(historicApi, startEra, sanitizedEra, at);
68
76
  // With the general data, we can now fetch the commission of each validator `address` nominates
69
77
  const allErasCommissions = await this.fetchAllErasCommissions(historicApi, address, startEra,
70
78
  // Create an array of `DeriveEraExposure`
@@ -99,29 +107,78 @@ class AccountsStakingPayoutsService extends AbstractService_1.AbstractService {
99
107
  /**
100
108
  * Fetch general info about eras in the inclusive range `startEra` .. `era`.
101
109
  *
102
- * @param api `ApiPromise`
103
- * @param hash `BlockHash` to make call at
110
+ * @param historicApi Historic api for querying past blocks
104
111
  * @param startEra first era to get data for
105
112
  * @param era the last era to get data for
113
+ * @param blockNumber block information to ensure compatibility with older eras
106
114
  */
107
- async fetchAllErasGeneral(historicApi, startEra, era) {
115
+ async fetchAllErasGeneral(historicApi, startEra, era, blockNumber) {
108
116
  const allDeriveQuerys = [];
117
+ let nextEraStartBlock = Number(blockNumber.height);
118
+ let eraDurationInBlocks = 0;
119
+ const runtimeInfo = await this.api.rpc.state.getRuntimeVersion(blockNumber.hash);
120
+ const earlyErasBlockInfo = kusamaEarlyErasBlockInfo_json_1.default;
109
121
  for (let e = startEra; e <= era; e += 1) {
110
122
  const eraIndex = historicApi.registry.createType('EraIndex', e);
111
- const eraGeneralTuple = Promise.all([
112
- this.deriveEraExposure(historicApi, eraIndex),
113
- historicApi.query.staking.erasRewardPoints(eraIndex),
114
- historicApi.query.staking.erasValidatorReward(eraIndex),
115
- ]);
116
- allDeriveQuerys.push(eraGeneralTuple);
123
+ if (historicApi.query.staking.erasRewardPoints) {
124
+ const eraGeneralTuple = Promise.all([
125
+ this.deriveEraExposure(historicApi, eraIndex),
126
+ historicApi.query.staking.erasRewardPoints(eraIndex),
127
+ historicApi.query.staking.erasValidatorReward(eraIndex),
128
+ ]);
129
+ allDeriveQuerys.push(eraGeneralTuple);
130
+ }
131
+ else {
132
+ // We check if we are in the Kusama chain since currently we have
133
+ // the block info for the early eras only for Kusama.
134
+ if (runtimeInfo.specName.toString() === 'kusama') {
135
+ // Retrieve the first block of the era following the given era in order
136
+ // to fetch the `Rewards` event at that block.
137
+ nextEraStartBlock = era === 0 ? earlyErasBlockInfo[era + 1].start : earlyErasBlockInfo[era].start;
138
+ }
139
+ else {
140
+ const sessionDuration = historicApi.consts.staking.sessionsPerEra.toNumber();
141
+ const epochDuration = historicApi.consts.babe.epochDuration.toNumber();
142
+ eraDurationInBlocks = sessionDuration * epochDuration;
143
+ }
144
+ const nextEraStartBlockHash = await this.api.rpc.chain.getBlockHash(nextEraStartBlock);
145
+ const currentEraEndBlockHash = era === 0
146
+ ? await this.api.rpc.chain.getBlockHash(earlyErasBlockInfo[0].end)
147
+ : await this.api.rpc.chain.getBlockHash(earlyErasBlockInfo[era - 1].end);
148
+ let reward = historicApi.registry.createType('Option<u128>');
149
+ const blockInfo = await this.api.rpc.chain.getBlock(nextEraStartBlockHash);
150
+ const allRecords = await historicApi.query.system.events();
151
+ blockInfo.block.extrinsics.forEach((index) => {
152
+ allRecords
153
+ .filter(({ phase }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.eq(index))
154
+ .forEach(({ event }) => {
155
+ if (event.method.toString() === 'Reward') {
156
+ const [dispatchInfo] = event.data;
157
+ reward = historicApi.registry.createType('Option<u128>', dispatchInfo.toString());
158
+ }
159
+ });
160
+ });
161
+ const points = this.fetchHistoricRewardPoints(currentEraEndBlockHash);
162
+ const rewardPromise = new Promise((resolve) => {
163
+ resolve(reward);
164
+ });
165
+ if (runtimeInfo.specName.toString() !== 'kusama') {
166
+ nextEraStartBlock = nextEraStartBlock - eraDurationInBlocks;
167
+ }
168
+ const eraGeneralTuple = Promise.all([this.deriveEraExposure(historicApi, eraIndex), points, rewardPromise]);
169
+ allDeriveQuerys.push(eraGeneralTuple);
170
+ }
117
171
  }
118
172
  return Promise.all(allDeriveQuerys);
119
173
  }
174
+ async fetchHistoricRewardPoints(hash) {
175
+ const historicApi = await this.api.at(hash);
176
+ return historicApi.query.staking.currentEraPointsEarned();
177
+ }
120
178
  /**
121
179
  * Fetch the commission & staking ledger for each `validatorId` in `deriveErasExposures`.
122
180
  *
123
- * @param api `ApiPromise`
124
- * @param hash `BlockHash` to make call at
181
+ * @param historicApi Historic api for querying past blocks
125
182
  * @param address address of the _Stash_ account to get the payouts of
126
183
  * @param startEra first era to get data for
127
184
  * @param deriveErasExposures exposures per era for `address`
@@ -153,18 +210,21 @@ class AccountsStakingPayoutsService extends AbstractService_1.AbstractService {
153
210
  message: `${address} has no nominations for the era ${eraIndex.toString()}`,
154
211
  };
155
212
  }
156
- if (erasValidatorRewardOption.isNone) {
213
+ if (erasValidatorRewardOption.isNone && eraIndex.toNumber() !== 0) {
214
+ const event = eraIndex.toNumber() > 517 ? 'ErasValidatorReward' : 'Reward';
157
215
  return {
158
- message: `No ErasValidatorReward for the era ${eraIndex.toString()}`,
216
+ message: `No ${event} for the era ${eraIndex.toString()}`,
159
217
  };
160
218
  }
161
219
  const totalEraRewardPoints = eraRewardPoints.total;
162
- const totalEraPayout = erasValidatorRewardOption.unwrap();
220
+ const totalEraPayout = eraIndex.toNumber() !== 0 ? erasValidatorRewardOption.unwrap() : this.api.registry.createType('BalanceOf', 0);
163
221
  const calcPayout = calc_1.CalcPayout.from_params(totalEraRewardPoints.toNumber(), totalEraPayout.toString(10));
164
222
  // Iterate through validators that this nominator backs and calculate payouts for the era
165
223
  const payouts = [];
166
224
  for (const { validatorId, commission: validatorCommission, validatorLedger } of exposuresWithCommission) {
167
- const totalValidatorRewardPoints = this.extractTotalValidatorRewardPoints(eraRewardPoints, validatorId);
225
+ const totalValidatorRewardPoints = deriveEraExposure.validatorIndex
226
+ ? this.extractTotalValidatorRewardPoints(eraRewardPoints, validatorId, deriveEraExposure.validatorIndex)
227
+ : this.extractTotalValidatorRewardPoints(eraRewardPoints, validatorId);
168
228
  if (!totalValidatorRewardPoints || (totalValidatorRewardPoints === null || totalValidatorRewardPoints === void 0 ? void 0 : totalValidatorRewardPoints.toNumber()) === 0) {
169
229
  // Nothing to do if there are no reward points for the validator
170
230
  continue;
@@ -200,6 +260,9 @@ class AccountsStakingPayoutsService extends AbstractService_1.AbstractService {
200
260
  continue;
201
261
  }
202
262
  }
263
+ else if (eraIndex.toNumber() < 518) {
264
+ indexOfEra = eraIndex.toNumber();
265
+ }
203
266
  else {
204
267
  continue;
205
268
  }
@@ -228,26 +291,39 @@ class AccountsStakingPayoutsService extends AbstractService_1.AbstractService {
228
291
  /**
229
292
  * Fetch the `commission` and `StakingLedger` of `validatorId`.
230
293
  *
231
- * @param api
294
+ * @param historicApi Historic api for querying past blocks
232
295
  * @param validatorId accountId of a validator's _Stash_ account
233
296
  * @param era the era to query
234
- * @param hash `BlockHash` to make call at
235
297
  * @param validatorLedgerCache object mapping validatorId => StakingLedger to limit redundant queries
236
298
  */
237
299
  async fetchCommissionAndLedger(historicApi, validatorId, era, validatorLedgerCache) {
238
300
  let commission;
239
301
  let validatorLedger;
302
+ let commissionPromise;
303
+ const ancient = era < 518;
240
304
  if (validatorId in validatorLedgerCache) {
241
305
  validatorLedger = validatorLedgerCache[validatorId];
242
- const prefs = await historicApi.query.staking.erasValidatorPrefs(era, validatorId);
243
- commission = prefs.commission.unwrap();
306
+ let prefs;
307
+ if (!ancient) {
308
+ prefs = await historicApi.query.staking.erasValidatorPrefs(era, validatorId);
309
+ commission = prefs.commission.unwrap();
310
+ }
311
+ else {
312
+ prefs = (await historicApi.query.staking.validators(validatorId));
313
+ commission = prefs[0].commission.unwrap();
314
+ }
244
315
  }
245
316
  else {
317
+ commissionPromise = ancient
318
+ ? historicApi.query.staking.validators(validatorId)
319
+ : historicApi.query.staking.erasValidatorPrefs(era, validatorId);
246
320
  const [prefs, validatorControllerOption] = await Promise.all([
247
- historicApi.query.staking.erasValidatorPrefs(era, validatorId),
321
+ commissionPromise,
248
322
  historicApi.query.staking.bonded(validatorId),
249
323
  ]);
250
- commission = prefs.commission.unwrap();
324
+ commission = ancient
325
+ ? prefs[0].commission.unwrap()
326
+ : prefs.commission.unwrap();
251
327
  if (validatorControllerOption.isNone) {
252
328
  return {
253
329
  commission,
@@ -271,11 +347,11 @@ class AccountsStakingPayoutsService extends AbstractService_1.AbstractService {
271
347
  * The original version uses the base ApiDerive implementation which does not include the ApiDecoration implementation.
272
348
  * It is required in this version to query older blocks for their historic data.
273
349
  *
274
- * @param historicApi
275
- * @param eraIndex
350
+ * @param historicApi Historic api for querying past blocks
351
+ * @param eraIndex index of the era to query
276
352
  */
277
353
  async deriveEraExposure(historicApi, eraIndex) {
278
- function mapStakers(era, stakers) {
354
+ function mapStakers(era, stakers, validatorIndex) {
279
355
  const nominators = {};
280
356
  const validators = {};
281
357
  stakers.forEach(([key, exposure]) => {
@@ -287,22 +363,58 @@ class AccountsStakingPayoutsService extends AbstractService_1.AbstractService {
287
363
  nominators[nominatorId].push({ validatorId, validatorIndex });
288
364
  });
289
365
  });
290
- return { era, nominators, validators };
366
+ if (Object.keys(validatorIndex).length > 0) {
367
+ return { era, nominators, validators, validatorIndex };
368
+ }
369
+ else {
370
+ return { era, nominators, validators };
371
+ }
372
+ }
373
+ let storageKeys = [];
374
+ const validatorIndex = {};
375
+ if (historicApi.query.staking.erasStakersClipped) {
376
+ storageKeys = await historicApi.query.staking.erasStakersClipped.entries(eraIndex);
291
377
  }
292
- const eraExposure = await historicApi.query.staking.erasStakersClipped.entries(eraIndex);
293
- return mapStakers(eraIndex, eraExposure);
378
+ else {
379
+ const validators = (await historicApi.query.staking.currentElected());
380
+ const validatorId = [];
381
+ validators.map((validator, index) => {
382
+ validatorIndex[validator.toString()] = index;
383
+ validatorId.push(validator);
384
+ });
385
+ let eraExposure = {};
386
+ for (const validator of validatorId) {
387
+ const storageKey = {
388
+ args: [eraIndex, validator],
389
+ };
390
+ eraExposure = (await historicApi.query.staking.stakers(validator));
391
+ storageKeys.push([storageKey, eraExposure]);
392
+ }
393
+ }
394
+ return mapStakers(eraIndex, storageKeys, validatorIndex);
294
395
  }
295
396
  /**
296
397
  * Extract the reward points of `validatorId` from `EraRewardPoints`.
297
398
  *
298
399
  * @param eraRewardPoints
299
400
  * @param validatorId accountId of a validator's _Stash_ account
401
+ * @param validatorIndex index of the validator in relation to the `EraPoints`
402
+ * array
300
403
  * */
301
- extractTotalValidatorRewardPoints(eraRewardPoints, validatorId) {
404
+ extractTotalValidatorRewardPoints(eraRewardPoints, validatorId, validatorIndex) {
302
405
  // Ideally we would just use the map's `get`, but that does not seem to be working here
303
- for (const [id, points] of eraRewardPoints.individual.entries()) {
304
- if (id.toString() === validatorId) {
305
- return points;
406
+ if (validatorIndex === undefined) {
407
+ for (const [id, points] of eraRewardPoints.individual.entries()) {
408
+ if (id.toString() === validatorId) {
409
+ return points;
410
+ }
411
+ }
412
+ }
413
+ else {
414
+ for (const [id, points] of eraRewardPoints.individual.entries()) {
415
+ if (id.toString() === validatorIndex[validatorId.toString()].toString()) {
416
+ return points;
417
+ }
306
418
  }
307
419
  }
308
420
  return;
@@ -313,7 +425,7 @@ class AccountsStakingPayoutsService extends AbstractService_1.AbstractService {
313
425
  *
314
426
  * @param address address of the _Stash_ account to get the exposure of behind `validatorId`
315
427
  * @param validatorId accountId of a validator's _Stash_ account
316
- * @param deriveEraExposure
428
+ * @param deriveEraExposure result of deriveEraExposure
317
429
  */
318
430
  extractExposure(address, validatorId, deriveEraExposure) {
319
431
  var _a;