diff --git a/packages/api-derive/src/balances/fees.ts b/packages/api-derive/src/balances/fees.ts index 352b56c065..50ffc7d4d2 100644 --- a/packages/api-derive/src/balances/fees.ts +++ b/packages/api-derive/src/balances/fees.ts @@ -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 { +function queryV2 (api: ApiInterfaceRx): Observable { 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; + 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 { - return api.queryMulti([ +function queryV1 (api: ApiInterfaceRx): Observable { + return api.queryMulti([ // 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; + ]); } /** @@ -44,7 +44,7 @@ function querySubtrateV1 (api: ApiInterfaceRx): Observable { *
* * ```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 { return (): Observable => { return ( api.consts.balances - ? querySubtrateV2(api) - : querySubtrateV1(api) + ? queryV2(api) + : queryV1(api) ).pipe( map(([creationFee, existentialDeposit, transactionBaseFee, transactionByteFee, transferFee]): DerivedFees => ({ creationFee, diff --git a/packages/api-derive/src/elections/info.ts b/packages/api-derive/src/elections/info.ts index 3c49f98070..48714b07e4 100644 --- a/packages/api-derive/src/elections/info.ts +++ b/packages/api-derive/src/elections/info.ts @@ -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, u32, u32, SetIndex, BlockNumber, VoteIndex, SetIndex]; + +function query (api: ApiInterfaceRx): Observable { + return api.queryMulti([ 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 *
* * ```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, BN, BN, SessionIndex]]; -type Result = [[boolean, boolean, u64, SessionIndex], [u64, u64, u64], [SessionIndex, EraIndex]]; +type Result94Session = [SessionIndex, Option, 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 { + return 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 + ]) + ]).pipe( + map(createDerived94), + drr() + ); +} + +function infoLatest (api: ApiInterfaceRx): Observable { + 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([ + 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([ + 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 { - const hasBabe = !!api.consts.babe; - return (): Observable => { // 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 - ).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 - ).pipe( - map(createDerived), - drr() - ); + ? info94(api) + : infoLatest(api); }; } diff --git a/packages/api-derive/src/staking/info.ts b/packages/api-derive/src/staking/info.ts index 84079a56ad..838dc5a239 100644 --- a/packages/api-derive/src/staking/info.ts +++ b/packages/api-derive/src/staking/info.ts @@ -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 { } // 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 | Vec<[AccountId, Keys] & Codec>, nextKeys: Option): { nextSessionIds: AccountId[]; nextSessionId?: AccountId; sessionIds: AccountId[]; sessionId?: AccountId } { diff --git a/packages/api-derive/src/types.ts b/packages/api-derive/src/types.ts index 43af9cb09b..2712d9a5ba 100644 --- a/packages/api-derive/src/types.ts +++ b/packages/api-derive/src/types.ts @@ -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; 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;