Firm up on derive typings & results (#1489)
* Firm up on derive typings & results * Move assertion (eslint vs ts, round 1, fight!)
This commit is contained in:
@@ -3,37 +3,37 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Balance } from '@polkadot/types/interfaces';
|
||||
import { DerivedFees } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
type Result = [BN, BN, BN, BN, BN];
|
||||
type Result = [Balance, Balance, Balance, Balance, Balance];
|
||||
|
||||
function querySubtrateV2 (api: ApiInterfaceRx): Observable<Result> {
|
||||
function queryV2 (api: ApiInterfaceRx): Observable<Result> {
|
||||
return of([
|
||||
// get values from api.const for substrate versions post spec_version: 101
|
||||
// https://github.com/paritytech/substrate/pull/2883/files#diff-5e5e1c3aec9ddfde0a9054d062ab3db9R131
|
||||
api.consts.balances.creationFee,
|
||||
api.consts.balances.existentialDeposit,
|
||||
api.consts.balances.transactionBaseFee,
|
||||
api.consts.balances.transactionByteFee,
|
||||
api.consts.balances.transferFee
|
||||
]) as any as Observable<Result>;
|
||||
api.consts.balances.creationFee as Balance,
|
||||
api.consts.balances.existentialDeposit as Balance,
|
||||
api.consts.balances.transactionBaseFee as Balance,
|
||||
api.consts.balances.transactionByteFee as Balance,
|
||||
api.consts.balances.transferFee as Balance
|
||||
]);
|
||||
}
|
||||
|
||||
function querySubtrateV1 (api: ApiInterfaceRx): Observable<Result> {
|
||||
return api.queryMulti([
|
||||
function queryV1 (api: ApiInterfaceRx): Observable<Result> {
|
||||
return api.queryMulti<Result>([
|
||||
// Support older versions and get values from storage
|
||||
api.query.balances.creationFee,
|
||||
api.query.balances.existentialDeposit,
|
||||
api.query.balances.transactionBaseFee,
|
||||
api.query.balances.transactionByteFee,
|
||||
api.query.balances.transferFee
|
||||
]) as any as Observable<Result>;
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +44,7 @@ function querySubtrateV1 (api: ApiInterfaceRx): Observable<Result> {
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
* api.derive.balances.fees(([creationFee, transferFee]) => {
|
||||
* api.derive.balances.fees(({ creationFee, transferFee }) => {
|
||||
* console.log(`The fee for creating a new account on this chain is ${creationFee} units. The fee required for making a transfer is ${transferFee} units.`);
|
||||
* });
|
||||
* ```
|
||||
@@ -53,8 +53,8 @@ export function fees (api: ApiInterfaceRx): () => Observable<DerivedFees> {
|
||||
return (): Observable<DerivedFees> => {
|
||||
return (
|
||||
api.consts.balances
|
||||
? querySubtrateV2(api)
|
||||
: querySubtrateV1(api)
|
||||
? queryV2(api)
|
||||
: queryV1(api)
|
||||
).pipe(
|
||||
map(([creationFee, existentialDeposit, transactionBaseFee, transactionByteFee, transferFee]): DerivedFees => ({
|
||||
creationFee,
|
||||
|
||||
@@ -3,17 +3,20 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, BlockNumber, SetIndex, VoteIndex } from '@polkadot/types/interfaces';
|
||||
import { Codec } from '@polkadot/types/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Vec, u32 } from '@polkadot/types';
|
||||
|
||||
import { DerivedElectionsInfo } from '../types';
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
function query (api: ApiInterfaceRx): Observable<[[AccountId, BlockNumber][], AccountId[], BN, BN, SetIndex, BlockNumber, VoteIndex, SetIndex]> {
|
||||
return api.queryMulti([
|
||||
type Result = [Vec<[AccountId, BlockNumber] & Codec>, Vec<AccountId>, u32, u32, SetIndex, BlockNumber, VoteIndex, SetIndex];
|
||||
|
||||
function query (api: ApiInterfaceRx): Observable<Result> {
|
||||
return api.queryMulti<Result>([
|
||||
api.query.elections.members,
|
||||
api.query.elections.candidates,
|
||||
api.query.elections.candidateCount,
|
||||
@@ -22,7 +25,7 @@ function query (api: ApiInterfaceRx): Observable<[[AccountId, BlockNumber][], Ac
|
||||
api.query.elections.termDuration,
|
||||
api.query.elections.voteCount,
|
||||
api.query.elections.voterCount
|
||||
]) as any;
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,7 +36,7 @@ function query (api: ApiInterfaceRx): Observable<[[AccountId, BlockNumber][], Ac
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
* api.derive.elections.info(([members, candidates]) => {
|
||||
* api.derive.elections.info(({ members, candidates }) => {
|
||||
* console.log(`There are currently ${members.length} council members and ${candidates.length} prospective council candidates.`);
|
||||
* });
|
||||
* ```
|
||||
@@ -56,7 +59,7 @@ export function info (api: ApiInterfaceRx): () => Observable<DerivedElectionsInf
|
||||
termDuration,
|
||||
voteCount,
|
||||
voterCount
|
||||
} as unknown as DerivedElectionsInfo)),
|
||||
})),
|
||||
drr()
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,51 +5,51 @@
|
||||
import { BlockNumber, EraIndex, SessionIndex } from '@polkadot/types/interfaces';
|
||||
import { DerivedSessionInfo } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Option, u64 } from '@polkadot/types';
|
||||
import { Option, u64, createType } from '@polkadot/types';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
import { bestNumber } from '../chain';
|
||||
|
||||
type Result0to94 = [BlockNumber, [SessionIndex, Option<BlockNumber>, BN, BN, SessionIndex]];
|
||||
type Result = [[boolean, boolean, u64, SessionIndex], [u64, u64, u64], [SessionIndex, EraIndex]];
|
||||
type Result94Session = [SessionIndex, Option<BlockNumber>, BlockNumber, BlockNumber, SessionIndex];
|
||||
type Result94 = [BlockNumber, Result94Session];
|
||||
|
||||
const ZERO = new BN(0);
|
||||
const ONE = new BN(1);
|
||||
type ResultIndex = [SessionIndex, EraIndex];
|
||||
type ResultSlots = [u64, u64, u64];
|
||||
type ResultType = [boolean, boolean, u64, SessionIndex];
|
||||
type Result = [ResultType, ResultSlots, ResultIndex];
|
||||
|
||||
// internal helper to just split the logic - take all inputs, do the calculations and combine
|
||||
function createDerived0to94 ([bestNumber, [currentIndex, _lastLengthChange, sessionLength, lastEraLengthChange, sessionsPerEra]]: Result0to94): DerivedSessionInfo {
|
||||
const lastLengthChange = _lastLengthChange
|
||||
? _lastLengthChange.unwrapOr(ZERO)
|
||||
: ZERO;
|
||||
function createDerived94 ([bestNumber, [currentIndex, _lastLengthChange, sessionLength, lastEraLengthChange, sessionsPerEra]]: Result94): DerivedSessionInfo {
|
||||
const lastLengthChange = (_lastLengthChange && _lastLengthChange.unwrapOr(null)) || createType('BlockNumber');
|
||||
const sessionProgress = bestNumber
|
||||
.sub(lastLengthChange)
|
||||
.add(sessionLength)
|
||||
.mod(sessionLength);
|
||||
const currentEra = (currentIndex)
|
||||
const currentEra = currentIndex
|
||||
.sub(lastEraLengthChange)
|
||||
.mod(sessionsPerEra);
|
||||
const eraProgress = currentEra
|
||||
.mul(sessionLength)
|
||||
.add(sessionProgress);
|
||||
|
||||
return {
|
||||
currentEra,
|
||||
currentEra: createType('EraIndex', currentEra),
|
||||
currentIndex,
|
||||
eraLength: sessionLength.mul(sessionsPerEra),
|
||||
eraProgress: currentEra
|
||||
.mul(sessionLength)
|
||||
.add(sessionProgress),
|
||||
eraLength: createType('BlockNumber', sessionLength.mul(sessionsPerEra)),
|
||||
eraProgress: createType('BlockNumber', eraProgress),
|
||||
isEpoch: false,
|
||||
lastEraLengthChange,
|
||||
lastLengthChange,
|
||||
sessionLength,
|
||||
sessionsPerEra,
|
||||
sessionProgress
|
||||
} as unknown as DerivedSessionInfo;
|
||||
sessionProgress: createType('BlockNumber', sessionProgress)
|
||||
};
|
||||
}
|
||||
|
||||
function createDerived ([[hasBabe, isGenesisSlot, epochDuration, sessionsPerEra], [currentSlot, epochIndex, epochOrGenesisStartSlot], [currentIndex, currentEra]]: Result): DerivedSessionInfo {
|
||||
function createDerivedLatest ([[hasBabe, isGenesisSlot, epochDuration, sessionsPerEra], [currentSlot, epochIndex, epochOrGenesisStartSlot], [currentIndex, currentEra]]: Result): DerivedSessionInfo {
|
||||
const epochStartSlot = isGenesisSlot
|
||||
? epochIndex
|
||||
.mul(epochDuration)
|
||||
@@ -64,73 +64,74 @@ function createDerived ([[hasBabe, isGenesisSlot, epochDuration, sessionsPerEra]
|
||||
return {
|
||||
currentEra,
|
||||
currentIndex,
|
||||
eraLength: sessionsPerEra.mul(epochDuration),
|
||||
eraProgress,
|
||||
eraLength: createType('BlockNumber', sessionsPerEra.mul(epochDuration)),
|
||||
eraProgress: createType('BlockNumber', eraProgress),
|
||||
isEpoch: hasBabe,
|
||||
lastEraLengthChange: ZERO,
|
||||
lastLengthChange: epochStartSlot,
|
||||
lastEraLengthChange: createType('BlockNumber'),
|
||||
lastLengthChange: createType('BlockNumber', epochStartSlot),
|
||||
sessionLength: epochDuration,
|
||||
sessionsPerEra,
|
||||
sessionProgress: sessionProgress
|
||||
} as unknown as DerivedSessionInfo;
|
||||
sessionProgress: createType('BlockNumber', sessionProgress)
|
||||
};
|
||||
}
|
||||
|
||||
function info94 (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
|
||||
return combineLatest([
|
||||
bestNumber(api)(),
|
||||
api.queryMulti<Result94Session>([
|
||||
api.query.session.currentIndex,
|
||||
api.query.session.lastLengthChange,
|
||||
api.query.session.sessionLength,
|
||||
api.query.staking.lastEraLengthChange,
|
||||
api.query.staking.sessionsPerEra
|
||||
])
|
||||
]).pipe(
|
||||
map(createDerived94),
|
||||
drr()
|
||||
);
|
||||
}
|
||||
|
||||
function infoLatest (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
|
||||
const hasBabe = !!api.consts.babe;
|
||||
|
||||
return combineLatest([
|
||||
of([
|
||||
hasBabe,
|
||||
hasBabe && !!api.query.babe.genesisSlot,
|
||||
hasBabe
|
||||
? api.consts.babe.epochDuration as u64
|
||||
: createType('u64', 1),
|
||||
api.consts.staking.sessionsPerEra as SessionIndex
|
||||
] as ResultType),
|
||||
hasBabe
|
||||
? api.queryMulti<ResultSlots>([
|
||||
api.query.babe.currentSlot,
|
||||
api.query.babe.epochIndex,
|
||||
api.query.babe.genesisSlot
|
||||
? api.query.babe.genesisSlot
|
||||
: api.query.babe.epochStartSlot
|
||||
])
|
||||
: of([createType('u64', 1), createType('u64', 1), createType('u64', 1)] as ResultSlots),
|
||||
api.queryMulti<ResultIndex>([
|
||||
api.query.session.currentIndex,
|
||||
api.query.staking.currentEra
|
||||
])
|
||||
]).pipe(
|
||||
map(createDerivedLatest),
|
||||
drr()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Retrieves all the session and era info and calculates specific values on it as the length of the session and eras
|
||||
*/
|
||||
export function info (api: ApiInterfaceRx): () => Observable<DerivedSessionInfo> {
|
||||
const hasBabe = !!api.consts.babe;
|
||||
|
||||
return (): Observable<DerivedSessionInfo> => {
|
||||
// With substrate `spec_version 94`, the era and session has been explicitly exposed as `parameter_types`.
|
||||
// pre-94 we had more info and needed to calculate (handle old/Alex first)
|
||||
// https://github.com/paritytech/substrate/commit/dbf322620948935d2bbae214504e6c668c3073ed#diff-c29f42d6b931fa93ba038dbbbfec3055
|
||||
return api.query.session.lastLengthChange
|
||||
? (
|
||||
combineLatest([
|
||||
bestNumber(api)(),
|
||||
api.queryMulti([
|
||||
api.query.session.currentIndex,
|
||||
api.query.session.lastLengthChange,
|
||||
api.query.session.sessionLength,
|
||||
api.query.staking.lastEraLengthChange,
|
||||
api.query.staking.sessionsPerEra
|
||||
])
|
||||
]) as any as Observable<Result0to94>
|
||||
).pipe(
|
||||
map(createDerived0to94),
|
||||
drr()
|
||||
)
|
||||
: (
|
||||
combineLatest([
|
||||
// sessionsPerEra:
|
||||
// substrate spec_version >= 94 : get from parameter_types exposed as api.consts
|
||||
// https://github.com/paritytech/substrate/pull/2802/files#diff-5e5e1c3aec9ddfde0a9054d062ab3db9R156
|
||||
of([
|
||||
hasBabe,
|
||||
hasBabe && !!api.query.babe.genesisSlot,
|
||||
hasBabe
|
||||
? api.consts.babe.epochDuration
|
||||
: ONE,
|
||||
api.consts.staking.sessionsPerEra
|
||||
]),
|
||||
hasBabe
|
||||
? api.queryMulti([
|
||||
api.query.babe.currentSlot,
|
||||
api.query.babe.epochIndex,
|
||||
api.query.babe.genesisSlot
|
||||
? api.query.babe.genesisSlot
|
||||
: api.query.babe.epochStartSlot
|
||||
])
|
||||
: of([ONE, ONE, ONE]),
|
||||
api.queryMulti([
|
||||
api.query.session.currentIndex,
|
||||
api.query.staking.currentEra
|
||||
])
|
||||
]) as unknown as Observable<Result>
|
||||
).pipe(
|
||||
map(createDerived),
|
||||
drr()
|
||||
);
|
||||
? info94(api)
|
||||
: infoLatest(api);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, BlockNumber } from '@polkadot/types/interfaces/runtime';
|
||||
import { AccountId, Balance, BlockNumber } from '@polkadot/types/interfaces/runtime';
|
||||
import { Keys } from '@polkadot/types/interfaces/session';
|
||||
import { Exposure, RewardDestination, StakingLedger, UnlockChunk, ValidatorPrefs } from '@polkadot/types/interfaces/staking';
|
||||
import { Codec } from '@polkadot/types/types';
|
||||
@@ -40,15 +40,16 @@ function groupByEra (list: UnlockChunk[]): Record<string, BN> {
|
||||
}
|
||||
|
||||
// calculate the remining blocks in a specific unlock era
|
||||
function remainingBlocks (era: BN, eraLength: BN, bestNumber: BlockNumber): BN {
|
||||
function remainingBlocks (era: BN, eraLength: BN, bestNumber: BlockNumber): BlockNumber {
|
||||
const remaining = eraLength.mul(era).sub(bestNumber);
|
||||
|
||||
return remaining.lten(0)
|
||||
return createType('BlockNumber', remaining.lten(0)
|
||||
? new BN(0)
|
||||
: remaining;
|
||||
: remaining
|
||||
);
|
||||
}
|
||||
|
||||
function calculateUnlocking (stakingLedger: StakingLedger | undefined, eraLength: BN, bestNumber: BlockNumber): DerivedUnlocking | undefined {
|
||||
function calculateUnlocking (stakingLedger: StakingLedger | undefined, eraLength: BN, bestNumber: BlockNumber): DerivedUnlocking[] | undefined {
|
||||
if (isUndefined(stakingLedger)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -63,24 +64,24 @@ function calculateUnlocking (stakingLedger: StakingLedger | undefined, eraLength
|
||||
|
||||
// group the Unlockchunks that have the same era and sum their values
|
||||
const groupedResult = groupByEra(unlockingChunks);
|
||||
const results = Object.entries(groupedResult).map(([eraString, value]): { value: BN; remainingBlocks: BN } => ({
|
||||
value,
|
||||
const results = Object.entries(groupedResult).map(([eraString, value]): DerivedUnlocking => ({
|
||||
value: createType('Balance', value),
|
||||
remainingBlocks: remainingBlocks(createType('BlockNumber', eraString), eraLength, bestNumber)
|
||||
}));
|
||||
|
||||
return results.length ? results : undefined;
|
||||
}
|
||||
|
||||
function redeemableSum (stakingLedger: StakingLedger | undefined, eraLength: BN, bestNumber: BlockNumber): BN {
|
||||
function redeemableSum (stakingLedger: StakingLedger | undefined, eraLength: BN, bestNumber: BlockNumber): Balance {
|
||||
if (isUndefined(stakingLedger)) {
|
||||
return new BN(0);
|
||||
return createType('Balance');
|
||||
}
|
||||
|
||||
return stakingLedger.unlocking.reduce((total, { era, value }): BN => {
|
||||
return createType('Balance', stakingLedger.unlocking.reduce((total, { era, value }): BN => {
|
||||
return remainingBlocks(era.unwrap(), eraLength, bestNumber).eqn(0)
|
||||
? total.add(value.unwrap())
|
||||
: total;
|
||||
}, new BN(0));
|
||||
}, new BN(0)));
|
||||
}
|
||||
|
||||
function unwrapSessionIds (stashId: AccountId, queuedKeys: Option<AccountId> | Vec<[AccountId, Keys] & Codec>, nextKeys: Option<Keys>): { nextSessionIds: AccountId[]; nextSessionId?: AccountId; sessionIds: AccountId[]; sessionId?: AccountId } {
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
// 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, Exposure, Index, RewardDestination, SetIndex, StakingLedger, ValidatorPrefs, Vote, VoteIndex } from '@polkadot/types/interfaces';
|
||||
import { AccountId, Balance, BlockNumber, EraIndex, Exposure, Index, RewardDestination, SessionIndex, SetIndex, StakingLedger, ValidatorPrefs, Vote, VoteIndex } from '@polkadot/types/interfaces';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { u32 } from '@polkadot/types';
|
||||
|
||||
export interface DerivedBalances {
|
||||
accountId: AccountId;
|
||||
@@ -35,8 +36,8 @@ export interface DerivedContractFees {
|
||||
export interface DerivedElectionsInfo {
|
||||
members: Record<string, BlockNumber>;
|
||||
candidates: AccountId[];
|
||||
candidateCount: BN;
|
||||
desiredSeats: BN;
|
||||
candidateCount: u32;
|
||||
desiredSeats: u32;
|
||||
nextVoterSet: SetIndex;
|
||||
termDuration: BlockNumber;
|
||||
voteCount: VoteIndex;
|
||||
@@ -44,11 +45,11 @@ export interface DerivedElectionsInfo {
|
||||
}
|
||||
|
||||
export interface DerivedFees {
|
||||
creationFee: BN;
|
||||
existentialDeposit: BN;
|
||||
transactionBaseFee: BN;
|
||||
transactionByteFee: BN;
|
||||
transferFee: BN;
|
||||
creationFee: Balance;
|
||||
existentialDeposit: Balance;
|
||||
transactionBaseFee: Balance;
|
||||
transactionByteFee: Balance;
|
||||
transferFee: Balance;
|
||||
}
|
||||
|
||||
export interface RecentlyOffline {
|
||||
@@ -65,16 +66,16 @@ export interface DerivedReferendumVote {
|
||||
}
|
||||
|
||||
export interface DerivedSessionInfo {
|
||||
currentEra: BN;
|
||||
currentIndex: BN;
|
||||
eraLength: BN;
|
||||
eraProgress: BN;
|
||||
currentEra: EraIndex;
|
||||
currentIndex: SessionIndex;
|
||||
eraLength: BlockNumber;
|
||||
eraProgress: BlockNumber;
|
||||
isEpoch: boolean;
|
||||
lastEraLengthChange: BN;
|
||||
lastLengthChange: BN;
|
||||
sessionLength: BN;
|
||||
sessionsPerEra: BN;
|
||||
sessionProgress: BN;
|
||||
lastEraLengthChange: BlockNumber;
|
||||
lastLengthChange: BlockNumber;
|
||||
sessionLength: BlockNumber;
|
||||
sessionsPerEra: SessionIndex;
|
||||
sessionProgress: BlockNumber;
|
||||
}
|
||||
|
||||
export type DerivedStakingAccount = [AccountId, DerivedStakingOnlineStatus];
|
||||
@@ -99,7 +100,7 @@ export interface DerivedStaking extends DerivedStakingOnlineStatus {
|
||||
nextSessionId?: AccountId;
|
||||
nextSessionIds: AccountId[];
|
||||
nominators?: AccountId[];
|
||||
redeemable?: BN;
|
||||
redeemable?: Balance;
|
||||
rewardDestination?: RewardDestination;
|
||||
// @deprecated Use sessionIds instead
|
||||
sessionId?: AccountId;
|
||||
@@ -107,11 +108,11 @@ export interface DerivedStaking extends DerivedStakingOnlineStatus {
|
||||
stakers?: Exposure;
|
||||
stakingLedger?: StakingLedger;
|
||||
stashId?: AccountId;
|
||||
unlocking?: DerivedUnlocking;
|
||||
unlocking?: DerivedUnlocking[];
|
||||
validatorPrefs?: ValidatorPrefs;
|
||||
}
|
||||
|
||||
export type DerivedUnlocking = { remainingBlocks: BN; value: BN }[];
|
||||
export type DerivedUnlocking = { remainingBlocks: BlockNumber; value: Balance };
|
||||
|
||||
export interface VoterPosition {
|
||||
globalIndex: BN;
|
||||
|
||||
Reference in New Issue
Block a user