Skip to content

Commit

Permalink
fix: add more historic support for staking-payouts (#1397)
Browse files Browse the repository at this point in the history
* fix: add more historic support for staking-payouts

* Update typings

* update nit

* historyDepth guard

* added currentEra

* first commit

* updated deriveEraExposure

* udpated blockinfo interface

* updated payout calc

* removed unused types

* added eras block info

* run linter

* some linting

* udpated points and rewards

* undo

* fixed all type errors

* get era points at current era s end block

* edgecase era 0

* linting

* era 0

* disable depth for eras less than 518

* removed extra blocks in erasBlockInfo json file

* bug fix

* typo

* bug fix

* fix era err msg

* removed commented line

* linting

---------

Co-authored-by: bee344 <alberto.penayo@parity.io>
Co-authored-by: Imod7 <dominique@imodworks.io>
  • Loading branch information
3 people committed Mar 1, 2024
1 parent 0b763f8 commit b1e84be
Show file tree
Hide file tree
Showing 3 changed files with 2,339 additions and 70 deletions.
64 changes: 49 additions & 15 deletions src/controllers/accounts/AccountsStakingPayoutsController.ts
Expand Up @@ -16,13 +16,15 @@

import type { ApiPromise } from '@polkadot/api';
import type { ApiDecoration } from '@polkadot/api/types';
import { Option } from '@polkadot/types';
import { Option, u32 } from '@polkadot/types';
import BN from 'bn.js';
import { RequestHandler } from 'express';
import { BadRequest, InternalServerError } from 'http-errors';

import { validateAddress, validateBoolean } from '../../middleware';
import { AccountsStakingPayoutsService } from '../../services';
import { IEarlyErasBlockInfo } from '../../services/accounts/AccountsStakingPayoutsService';
import kusamaEarlyErasBlockInfo from '../../services/accounts/kusamaEarlyErasBlockInfo.json';
import { IAddressParam } from '../../types/requests';
import AbstractController from '../AbstractController';

Expand Down Expand Up @@ -99,9 +101,24 @@ export default class AccountsStakingPayoutsController extends AbstractController
{ params: { address }, query: { depth, era, unclaimedOnly, at } },
res,
): Promise<void> => {
const hash = await this.getHashFromAt(at);
const apiAt = await this.api.at(hash);
const earlyErasBlockInfo: IEarlyErasBlockInfo = kusamaEarlyErasBlockInfo;
let hash = await this.getHashFromAt(at);
let apiAt = await this.api.at(hash);
const { eraArg, currentEra } = await this.getEraAndHash(apiAt, this.verifyAndCastOr('era', era, undefined));
if (currentEra <= 519 && depth !== undefined) {
throw new InternalServerError('The `depth` query parameter is disabled for eras less than 518.');
} else if (currentEra <= 519 && era !== undefined) {
throw new InternalServerError('The `era` query parameter is disabled for eras less than 518.');
}
let sanitizedDepth: string | undefined;
if (depth) {
sanitizedDepth = Math.min(Number(depth), currentEra - 518).toString();
}
if (currentEra < 518) {
const eraStartBlock: number = earlyErasBlockInfo[currentEra].start;
hash = await this.getHashFromAt(eraStartBlock.toString());
apiAt = await this.api.at(hash);
}

const unclaimedOnlyArg = unclaimedOnly === 'false' ? false : true;

Expand All @@ -110,7 +127,7 @@ export default class AccountsStakingPayoutsController extends AbstractController
await this.service.fetchAccountStakingPayout(
hash,
address,
this.verifyAndCastOr('depth', depth, 1) as number,
this.verifyAndCastOr('depth', sanitizedDepth, 1) as number,
eraArg,
unclaimedOnlyArg,
currentEra,
Expand All @@ -120,17 +137,8 @@ export default class AccountsStakingPayoutsController extends AbstractController
};

private async getEraAndHash(apiAt: ApiDecoration<'promise'>, era?: number) {
const [activeEraOption, currentEraMaybeOption] = await Promise.all([
apiAt.query.staking.activeEra(),
apiAt.query.staking.currentEra(),
]);

if (activeEraOption.isNone) {
throw new InternalServerError('ActiveEra is None when Some was expected');
}
const activeEra = activeEraOption.unwrap().index.toNumber();

let currentEra;
let currentEra: number;
const currentEraMaybeOption = (await apiAt.query.staking.currentEra()) as u32 & Option<u32>;
if (currentEraMaybeOption instanceof Option) {
if (currentEraMaybeOption.isNone) {
throw new InternalServerError('CurrentEra is None when Some was expected');
Expand All @@ -144,6 +152,32 @@ export default class AccountsStakingPayoutsController extends AbstractController
throw new InternalServerError('Query for current_era returned a non-processable result.');
}

let activeEra;
if (apiAt.query.staking.activeEra) {
const activeEraOption = await apiAt.query.staking.activeEra();
if (activeEraOption.isNone) {
const historicActiveEra = await apiAt.query.staking.currentEra();
if (historicActiveEra.isNone) {
throw new InternalServerError('ActiveEra is None when Some was expected');
} else {
activeEra = historicActiveEra.unwrap().toNumber();
}
} else {
activeEra = activeEraOption.unwrap().index.toNumber();
}
} else {
const sessionIndex = await apiAt.query.session.currentIndex();
const idx = sessionIndex.toNumber() % 6;
// https://substrate.stackexchange.com/a/2026/1786
if (currentEra < 518) {
activeEra = currentEra;
} else if (idx > 0) {
activeEra = currentEra;
} else {
activeEra = currentEra - 1;
}
}

if (era !== undefined && era > activeEra - 1) {
throw new BadRequest(
`The specified era (${era}) is too large. ` + `Largest era payout info is available for is ${activeEra - 1}`,
Expand Down

0 comments on commit b1e84be

Please sign in to comment.