Aplit derive session.{info, progress} (#2117)
This commit is contained in:
@@ -12,7 +12,7 @@ import { memo } from '../util';
|
||||
|
||||
export function eraProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
|
||||
return memo((): Observable<BlockNumber> =>
|
||||
api.derive.session.info().pipe(
|
||||
api.derive.session.progress().pipe(
|
||||
map((info) => info.eraProgress)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -6,4 +6,5 @@ export * from './eraLength';
|
||||
export * from './eraProgress';
|
||||
export * from './indexes';
|
||||
export * from './info';
|
||||
export * from './progress';
|
||||
export * from './sessionProgress';
|
||||
|
||||
@@ -5,34 +5,26 @@
|
||||
import { SessionIndex } from '@polkadot/types/interfaces';
|
||||
import { DeriveSessionInfo, DeriveSessionIndexes } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Option, u64 } from '@polkadot/types';
|
||||
import { u64 } from '@polkadot/types';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
type ResultSlots = [u64, u64, u64, Option<SessionIndex>];
|
||||
type ResultSlotsFlat = [u64, u64, u64, SessionIndex];
|
||||
type ResultType = [boolean, u64, SessionIndex];
|
||||
type Result = [ResultType, DeriveSessionIndexes, ResultSlotsFlat];
|
||||
|
||||
function createDerive (api: ApiInterfaceRx, [[hasBabe, epochDuration, sessionsPerEra], { activeEra, activeEraStart, currentEra, currentIndex, validatorCount }, [currentSlot, epochIndex, epochOrGenesisStartSlot, activeEraStartSessionIndex]]: Result): DeriveSessionInfo {
|
||||
const epochStartSlot = epochIndex.mul(epochDuration).add(epochOrGenesisStartSlot);
|
||||
const sessionProgress = currentSlot.sub(epochStartSlot);
|
||||
const eraProgress = currentIndex.sub(activeEraStartSessionIndex).mul(epochDuration).add(sessionProgress);
|
||||
type Result = [ResultType, DeriveSessionIndexes];
|
||||
|
||||
function createDerive (api: ApiInterfaceRx, [[hasBabe, epochDuration, sessionsPerEra], { activeEra, activeEraStart, currentEra, currentIndex, validatorCount }]: Result): DeriveSessionInfo {
|
||||
return {
|
||||
activeEra,
|
||||
activeEraStart,
|
||||
currentEra,
|
||||
currentIndex,
|
||||
eraLength: api.registry.createType('BlockNumber', sessionsPerEra.mul(epochDuration)),
|
||||
eraProgress: api.registry.createType('BlockNumber', eraProgress),
|
||||
isEpoch: hasBabe,
|
||||
sessionLength: epochDuration,
|
||||
sessionsPerEra,
|
||||
sessionProgress: api.registry.createType('BlockNumber', sessionProgress),
|
||||
validatorCount
|
||||
};
|
||||
}
|
||||
@@ -46,67 +38,34 @@ function queryAura (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
|
||||
api.registry.createType('u64', 1),
|
||||
api.consts.staking?.sessionsPerEra || api.registry.createType('SessionIndex', 1)
|
||||
],
|
||||
indexes,
|
||||
[
|
||||
api.registry.createType('u64', 1),
|
||||
api.registry.createType('u64', 1),
|
||||
api.registry.createType('u64', 1),
|
||||
api.registry.createType('SessionIndex', 1)
|
||||
]
|
||||
indexes
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function queryBabe (api: ApiInterfaceRx): Observable<[DeriveSessionIndexes, ResultSlotsFlat]> {
|
||||
function queryBabe (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
|
||||
return api.derive.session.indexes().pipe(
|
||||
switchMap((indexes): Observable<[DeriveSessionIndexes, ResultSlots]> =>
|
||||
combineLatest([
|
||||
of(indexes),
|
||||
api.queryMulti<ResultSlots>([
|
||||
api.query.babe.currentSlot,
|
||||
api.query.babe.epochIndex,
|
||||
api.query.babe.genesisSlot,
|
||||
[api.query.staking.erasStartSessionIndex, indexes.activeEra]
|
||||
])
|
||||
map((indexes) =>
|
||||
createDerive(api, [
|
||||
[
|
||||
true,
|
||||
api.consts.babe.epochDuration,
|
||||
api.consts.staking.sessionsPerEra
|
||||
],
|
||||
indexes
|
||||
])
|
||||
),
|
||||
map(([indexes, [currentSlot, epochIndex, genesisSlot, optStartIndex]]): [DeriveSessionIndexes, ResultSlotsFlat] => [
|
||||
indexes, [currentSlot, epochIndex, genesisSlot, optStartIndex.unwrapOr(api.registry.createType('SessionIndex', 1))]
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function queryBabeNoHistory (api: ApiInterfaceRx): Observable<[DeriveSessionIndexes, ResultSlotsFlat]> {
|
||||
return combineLatest([
|
||||
api.derive.session.indexes(),
|
||||
api.queryMulti<ResultSlotsFlat>([
|
||||
api.query.babe.currentSlot,
|
||||
api.query.babe.epochIndex,
|
||||
api.query.babe.genesisSlot,
|
||||
api.query.staking.currentEraStartSessionIndex
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras
|
||||
*/
|
||||
export function info (api: ApiInterfaceRx): () => Observable<DeriveSessionInfo> {
|
||||
return memo((): Observable<DeriveSessionInfo> =>
|
||||
api.consts.babe
|
||||
? (api.query.staking.erasStartSessionIndex
|
||||
? queryBabe(api) // 2.x with Babe
|
||||
: queryBabeNoHistory(api)
|
||||
).pipe(
|
||||
map(([indexes, slots]: [DeriveSessionIndexes, ResultSlotsFlat]): DeriveSessionInfo =>
|
||||
createDerive(api, [
|
||||
[true, api.consts.babe.epochDuration, api.consts.staking.sessionsPerEra],
|
||||
indexes,
|
||||
slots
|
||||
])
|
||||
)
|
||||
)
|
||||
? queryBabe(api)
|
||||
: queryAura(api)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { SessionIndex } from '@polkadot/types/interfaces';
|
||||
import { DeriveSessionInfo, DeriveSessionProgress } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Option, u64 } from '@polkadot/types';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
type ResultSlots = [u64, u64, u64, Option<SessionIndex>];
|
||||
type ResultSlotsFlat = [u64, u64, u64, SessionIndex];
|
||||
|
||||
function createDerive (api: ApiInterfaceRx, info: DeriveSessionInfo, [currentSlot, epochIndex, epochOrGenesisStartSlot, activeEraStartSessionIndex]: ResultSlotsFlat): DeriveSessionProgress {
|
||||
const epochStartSlot = epochIndex.mul(info.sessionLength).add(epochOrGenesisStartSlot);
|
||||
const sessionProgress = currentSlot.sub(epochStartSlot);
|
||||
const eraProgress = info.currentIndex.sub(activeEraStartSessionIndex).mul(info.sessionLength).add(sessionProgress);
|
||||
|
||||
return {
|
||||
...info,
|
||||
eraProgress: api.registry.createType('BlockNumber', eraProgress),
|
||||
sessionProgress: api.registry.createType('BlockNumber', sessionProgress)
|
||||
};
|
||||
}
|
||||
|
||||
function queryAura (api: ApiInterfaceRx): Observable<DeriveSessionProgress> {
|
||||
return api.derive.session.info().pipe(
|
||||
map((info): DeriveSessionProgress =>
|
||||
createDerive(api, info, [
|
||||
api.registry.createType('u64', 1),
|
||||
api.registry.createType('u64', 1),
|
||||
api.registry.createType('u64', 1),
|
||||
api.registry.createType('SessionIndex', 1)
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function queryBabe (api: ApiInterfaceRx): Observable<[DeriveSessionInfo, ResultSlotsFlat]> {
|
||||
return api.derive.session.info().pipe(
|
||||
switchMap((info): Observable<[DeriveSessionInfo, ResultSlots]> =>
|
||||
combineLatest([
|
||||
of(info),
|
||||
api.queryMulti<ResultSlots>([
|
||||
api.query.babe.currentSlot,
|
||||
api.query.babe.epochIndex,
|
||||
api.query.babe.genesisSlot,
|
||||
[api.query.staking.erasStartSessionIndex, info.activeEra]
|
||||
])
|
||||
])
|
||||
),
|
||||
map(([info, [currentSlot, epochIndex, genesisSlot, optStartIndex]]): [DeriveSessionInfo, ResultSlotsFlat] => [
|
||||
info, [currentSlot, epochIndex, genesisSlot, optStartIndex.unwrapOr(api.registry.createType('SessionIndex', 1))]
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
function queryBabeNoHistory (api: ApiInterfaceRx): Observable<[DeriveSessionInfo, ResultSlotsFlat]> {
|
||||
return combineLatest([
|
||||
api.derive.session.info(),
|
||||
api.queryMulti<ResultSlotsFlat>([
|
||||
api.query.babe.currentSlot,
|
||||
api.query.babe.epochIndex,
|
||||
api.query.babe.genesisSlot,
|
||||
api.query.staking.currentEraStartSessionIndex
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras
|
||||
*/
|
||||
export function progress (api: ApiInterfaceRx): () => Observable<DeriveSessionProgress> {
|
||||
return memo((): Observable<DeriveSessionProgress> =>
|
||||
api.consts.babe
|
||||
? (api.query.staking.erasStartSessionIndex
|
||||
? queryBabe(api) // 2.x with Babe
|
||||
: queryBabeNoHistory(api)
|
||||
).pipe(
|
||||
map(([info, slots]: [DeriveSessionInfo, ResultSlotsFlat]): DeriveSessionProgress =>
|
||||
createDerive(api, info, slots)
|
||||
)
|
||||
)
|
||||
: queryAura(api)
|
||||
);
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import { memo } from '../util';
|
||||
|
||||
export function sessionProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
|
||||
return memo((): Observable<BlockNumber> =>
|
||||
api.derive.session.info().pipe(
|
||||
api.derive.session.progress().pipe(
|
||||
map((info) => info.sessionProgress)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -16,9 +16,12 @@ export interface DeriveSessionIndexes {
|
||||
|
||||
export interface DeriveSessionInfo extends DeriveSessionIndexes {
|
||||
eraLength: BlockNumber;
|
||||
eraProgress: BlockNumber;
|
||||
isEpoch: boolean;
|
||||
sessionLength: BlockNumber;
|
||||
sessionsPerEra: SessionIndex;
|
||||
}
|
||||
|
||||
export interface DeriveSessionProgress extends DeriveSessionInfo {
|
||||
eraProgress: BlockNumber;
|
||||
sessionProgress: BlockNumber;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Balance, BlockNumber, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces';
|
||||
import { Balance, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces';
|
||||
import { DeriveSessionInfo, DeriveStakingAccount, DeriveStakingQuery, DeriveUnlocking } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
@@ -27,27 +27,13 @@ function groupByEra (list: UnlockChunk[]): Record<string, BN> {
|
||||
}, {});
|
||||
}
|
||||
|
||||
// calculate the remaining blocks in a specific unlock era
|
||||
function remainingBlocks (api: ApiInterfaceRx, era: BN, sessionInfo: DeriveSessionInfo): BlockNumber {
|
||||
const remaining = era.sub(sessionInfo.currentEra);
|
||||
|
||||
// on the Rust side the current-era >= era-for-unlock (removal done on >)
|
||||
return api.registry.createType('BlockNumber', remaining.gtn(0)
|
||||
? remaining
|
||||
.subn(1)
|
||||
.mul(sessionInfo.eraLength)
|
||||
.add(sessionInfo.eraLength.sub(sessionInfo.eraProgress))
|
||||
: 0
|
||||
);
|
||||
}
|
||||
|
||||
function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DeriveSessionInfo): DeriveUnlocking[] | undefined {
|
||||
if (isUndefined(stakingLedger)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const unlockingChunks = stakingLedger.unlocking.filter(({ era }): boolean =>
|
||||
remainingBlocks(api, era.unwrap(), sessionInfo).gtn(0)
|
||||
era.unwrap().sub(sessionInfo.activeEra).gtn(0)
|
||||
);
|
||||
|
||||
if (!unlockingChunks.length) {
|
||||
@@ -57,8 +43,8 @@ function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger |
|
||||
// group the unlock chunks that have the same era and sum their values
|
||||
const groupedResult = groupByEra(unlockingChunks);
|
||||
const results = Object.entries(groupedResult).map(([eraString, value]): DeriveUnlocking => ({
|
||||
value: api.registry.createType('Balance', value),
|
||||
remainingBlocks: remainingBlocks(api, new BN(eraString), sessionInfo)
|
||||
remainingEras: new BN(eraString).sub(sessionInfo.activeEra),
|
||||
value: api.registry.createType('Balance', value)
|
||||
}));
|
||||
|
||||
return results.length ? results : undefined;
|
||||
@@ -70,7 +56,7 @@ function redeemableSum (api: ApiInterfaceRx, stakingLedger: StakingLedger | unde
|
||||
}
|
||||
|
||||
return api.registry.createType('Balance', stakingLedger.unlocking.reduce((total, { era, value }): BN => {
|
||||
return remainingBlocks(api, era.unwrap(), sessionInfo).eqn(0)
|
||||
return sessionInfo.activeEra.gte(era.unwrap())
|
||||
? total.add(value.unwrap())
|
||||
: total;
|
||||
}, new BN(0)));
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, Balance, BlockNumber, EraIndex, EraRewardPoints, Exposure, Keys, RewardDestination, RewardPoint, StakingLedger, ValidatorPrefs } from '@polkadot/types/interfaces';
|
||||
import { AccountId, Balance, EraIndex, EraRewardPoints, Exposure, Keys, RewardDestination, RewardPoint, StakingLedger, ValidatorPrefs } from '@polkadot/types/interfaces';
|
||||
import { DeriveSessionIndexes } from '../session/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
export type DeriveEraValPoints = Record<string, RewardPoint>;
|
||||
|
||||
export type DeriveEraValPrefs = Record<string, ValidatorPrefs>;
|
||||
@@ -119,6 +121,6 @@ export interface DeriveStakingOverview extends DeriveSessionIndexes {
|
||||
}
|
||||
|
||||
export type DeriveUnlocking = {
|
||||
remainingBlocks: BlockNumber;
|
||||
remainingEras: BN;
|
||||
value: Balance;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user