mirror of
https://github.com/pezkuwichain/pezkuwi-api.git
synced 2026-11-13 18:07:10 +00:00
- @pezkuwi/dev, dev-test, dev-ts ^0.86.3; disable directives renamed for the new rule names, or removed where the rule no longer reports - rethrown errors carry the original as `cause` (13 sites) - optional chains where a guard expression tested the same value - Init: the registry cache settles with the creator's own promise, dropping the entry in finally(), instead of re-wrapping it - Combinator: a typed call instead of `Function` - checkTypes.manual: synchronous checks run outside Promise.all - sortValues, createTypeUnsafe: initial values that were never read - typegen util: load docs.js for its side effect (it registers the `docs` Handlebars partial) now that its types are re-exported type-only - MockProvider keeps its Header assertion: the package's own build does not load api-augment, so createType returns a plain Codec there - Decorate keeps `delete queue[i]`: the hole marks a fired queue and later indexes must not shift
66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
// Copyright 2017-2026 @pezkuwi/api-derive authors & contributors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
import type { Observable } from 'rxjs';
|
|
import type { Option, u32 } from '@pezkuwi/types';
|
|
import type { AccountId } from '@pezkuwi/types/interfaces';
|
|
import type { Codec } from '@pezkuwi/types/types';
|
|
import type { DeriveApi, DeriveHeartbeats } from '../types.js';
|
|
|
|
import { combineLatest, map, of, switchMap } from 'rxjs';
|
|
|
|
import { BN_ZERO } from '@pezkuwi/util';
|
|
|
|
import { memo } from '../util/index.js';
|
|
|
|
type Result = [DeriveHeartbeats, AccountId[], Option<Codec>[], u32[]];
|
|
|
|
function mapResult ([result, validators, heartbeats, numBlocks]: Result): DeriveHeartbeats {
|
|
validators.forEach((validator, index): void => {
|
|
const validatorId = validator.toString();
|
|
const blockCount = numBlocks[index];
|
|
const hasMessage = !heartbeats[index].isEmpty;
|
|
const prev = result[validatorId];
|
|
|
|
if (prev?.hasMessage !== hasMessage || !prev.blockCount.eq(blockCount)) {
|
|
result[validatorId] = {
|
|
blockCount,
|
|
hasMessage,
|
|
isOnline: hasMessage || blockCount.gt(BN_ZERO)
|
|
};
|
|
}
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @name receivedHeartbeats
|
|
* @description Return a boolean array indicating whether the passed accounts had received heartbeats in the current session.
|
|
* @example
|
|
* ```javascript
|
|
* let unsub = await api.derive.imOnline.receivedHeartbeats((heartbeat) => {
|
|
* console.log(heartbeat);
|
|
* });
|
|
* ```
|
|
*/
|
|
export function receivedHeartbeats (instanceId: string, api: DeriveApi): () => Observable<DeriveHeartbeats> {
|
|
return memo(instanceId, (): Observable<DeriveHeartbeats> =>
|
|
api.query.imOnline?.receivedHeartbeats
|
|
? api.derive.staking.overview().pipe(
|
|
switchMap(({ currentIndex, validators }): Observable<Result> =>
|
|
combineLatest([
|
|
of({}),
|
|
of(validators),
|
|
api.query.imOnline.receivedHeartbeats.multi(
|
|
validators.map((_address, index) => [currentIndex, index])),
|
|
api.query.imOnline.authoredBlocks.multi(
|
|
validators.map((address) => [currentIndex, address]))
|
|
])
|
|
),
|
|
map(mapResult)
|
|
)
|
|
: of({})
|
|
);
|
|
}
|