Retrieve heartbeats for all validators (#1527)

* Retrieve heartbeats for all validators

* Tested, confirmed working
This commit is contained in:
Jaco Greeff
2019-10-29 12:21:49 +01:00
committed by GitHub
parent d2e2d3be76
commit fed9e8f7de
5 changed files with 32 additions and 24 deletions
@@ -27,12 +27,11 @@ import { drr } from '../util/drr';
*/
export function idToIndex (api: ApiInterfaceRx): (accountId: AccountId | string) => Observable<AccountIndex | undefined> {
return (accountId: AccountId | string): Observable<AccountIndex | undefined> =>
indexes(api)()
.pipe(
startWith({}),
map((indexes: AccountIndexes): AccountIndex | undefined =>
(indexes || {})[accountId.toString()]
),
drr()
);
indexes(api)().pipe(
startWith({}),
map((indexes: AccountIndexes): AccountIndex | undefined =>
(indexes || {})[accountId.toString()]
),
drr()
);
}
@@ -32,7 +32,8 @@ export function indexToId (api: ApiInterfaceRx): (accountIndex: AccountIndex | s
? _accountIndex
: createType('AccountIndex', _accountIndex);
return (querySection.enumSet<Vec<AccountId>>(accountIndex.div(ENUMSET_SIZE)))
return querySection
.enumSet<Vec<AccountId>>(accountIndex.div(ENUMSET_SIZE))
.pipe(
startWith([]),
map((accounts): AccountId | undefined =>
+2 -1
View File
@@ -33,7 +33,8 @@ const enumsetSize = ENUMSET_SIZE.toNumber();
*/
export function indexes (api: ApiInterfaceRx): () => Observable<AccountIndexes> {
return (): Observable<AccountIndexes> => {
return (api.query.indices.nextEnumSet<AccountIndex>())
return api.query.indices
.nextEnumSet<AccountIndex>()
.pipe(
// use the nextEnumSet (which is a counter of the number of sets) to construct
// a range of values to query [0, 1, 2, ...]. Retrieve the full enum set for the
@@ -3,8 +3,9 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, SessionIndex } from '@polkadot/types/interfaces';
import { DerivedHeartbeats } from '../types';
import { of, Observable } from 'rxjs';
import { of, Observable, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Bytes, Vec } from '@polkadot/types';
@@ -14,25 +15,29 @@ import { drr } from '../util/drr';
/**
* @description Return a boolean array indicating whether the passed accounts had received heartbeats in the current session
*/
export function receivedHeartbeats (api: ApiInterfaceRx): (addresses: (AccountId | string)[]) => Observable<boolean[]> {
return (addresses: (AccountId | string)[]): Observable<boolean[]> => {
export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<DerivedHeartbeats> {
return (): Observable<DerivedHeartbeats> => {
return api.query.imOnline && api.query.imOnline.receivedHeartbeats
? api.queryMulti<[SessionIndex, Vec<AccountId>]>([
api.query.session.currentIndex,
api.query.imOnline.keys
? api.queryMulti<[Vec<AccountId>, SessionIndex]>([
api.query.imOnline.keys,
api.query.session.currentIndex
]).pipe(
switchMap(([currentIndex, keys]): Observable<Bytes[]> =>
api.query.imOnline.receivedHeartbeats.multi(
addresses.map((address): [SessionIndex, number] =>
[currentIndex, keys.indexOf(address)]
switchMap(([keys, currentIndex]): Observable<[AccountId[], Bytes[]]> =>
combineLatest([
of(keys),
api.query.imOnline.receivedHeartbeats.multi<Bytes>(
keys.map((_address, index): [SessionIndex, number] => [currentIndex, index])
)
)
])
),
map((heartbeats): boolean[] =>
heartbeats.map((heartbeat): boolean => !heartbeat.isEmpty)
map(([keys, heartbeats]): DerivedHeartbeats =>
keys.reduce((result: DerivedHeartbeats, key, index): DerivedHeartbeats => ({
...result,
[key.toString()]: !!heartbeats[index] && !heartbeats[index].isEmpty
}), {})
),
drr()
)
: of([...new Array(addresses.length).keys()].map((): boolean => false));
: of({});
};
}
+2
View File
@@ -56,6 +56,8 @@ export interface DerivedFees {
transferFee: Balance;
}
export type DerivedHeartbeats = Record<string, boolean>;
export interface RecentlyOffline {
blockNumber: BlockNumber;
count: BN;