mirror of
https://github.com/pezkuwichain/pezkuwi-api.git
synced 2026-04-22 18:27:57 +00:00
Rebrand: polkadot → pezkuwi, substrate → bizinikiwi, kusama → dicle
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
// Copyright 2017-2025 @pezkuwi/api-derive authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { QueryableStorage } from '@pezkuwi/api-base/types';
|
||||
import type { Compact, Vec } from '@pezkuwi/types';
|
||||
import type { AccountId, BlockNumber, Header } from '@pezkuwi/types/interfaces';
|
||||
import type { PezpalletImOnlineSr25519AppSr25519Public } from '@pezkuwi/types/lookup';
|
||||
import type { Codec, IOption } from '@pezkuwi/types/types';
|
||||
import type { DeriveApi } from '../types.js';
|
||||
|
||||
import { combineLatest, map, mergeMap, of, switchMap } from 'rxjs';
|
||||
|
||||
import { memo, unwrapBlockNumber } from '../util/index.js';
|
||||
|
||||
export type BlockNumberDerive = (instanceId: string, api: DeriveApi) => () => Observable<BlockNumber>;
|
||||
|
||||
type OptionMapping = IOption<{ account: AccountId } & Codec>;
|
||||
type OptionNimbus = IOption<{ nimbus: PezpalletImOnlineSr25519AppSr25519Public } & Codec>;
|
||||
|
||||
export function createBlockNumberDerive <T extends { number: Compact<BlockNumber> | BlockNumber }> (fn: (api: DeriveApi) => Observable<T>): BlockNumberDerive {
|
||||
return (instanceId: string, api: DeriveApi) =>
|
||||
memo(instanceId, () =>
|
||||
fn(api).pipe(
|
||||
map(unwrapBlockNumber)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
function getAuthorDetailsWithAt (header: Header, queryAt: QueryableStorage<'rxjs'>): Observable<[Header, Vec<AccountId> | null, AccountId | null]> {
|
||||
const validators = queryAt.session?.validators
|
||||
? queryAt.session.validators()
|
||||
: of(null);
|
||||
|
||||
// nimbus consensus stores the session key of the block author in header logs
|
||||
const { logs: [log] } = header.digest;
|
||||
const loggedAuthor = (log && (
|
||||
(log.isConsensus && log.asConsensus[0].isNimbus && log.asConsensus[1]) ||
|
||||
(log.isPreRuntime && log.asPreRuntime[0].isNimbus && log.asPreRuntime[1])
|
||||
));
|
||||
|
||||
if (loggedAuthor) {
|
||||
// use the author mapping pallet, if available (ie: moonbeam, moonriver), to map session (nimbus) key to author (collator/validator) key
|
||||
if (queryAt['authorMapping']?.['mappingWithDeposit']) {
|
||||
return combineLatest([
|
||||
of(header),
|
||||
validators,
|
||||
queryAt['authorMapping']['mappingWithDeposit']<OptionMapping>(loggedAuthor).pipe(
|
||||
map((o) =>
|
||||
o.unwrapOr({ account: null }).account
|
||||
)
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
// fall back to session and teyrchain staking pallets, if available (ie: manta, calamari), to map session (nimbus) key to author (collator) key
|
||||
if (queryAt['teyrchainStaking']?.['selectedCandidates'] && queryAt.session?.nextKeys) {
|
||||
const loggedHex = loggedAuthor.toHex();
|
||||
|
||||
return combineLatest([
|
||||
of(header),
|
||||
validators,
|
||||
queryAt['teyrchainStaking']['selectedCandidates']<Vec<AccountId>>().pipe(
|
||||
mergeMap((selectedCandidates) =>
|
||||
combineLatest([
|
||||
of(selectedCandidates),
|
||||
queryAt.session.nextKeys.multi<OptionNimbus>(selectedCandidates).pipe(
|
||||
map((nextKeys) =>
|
||||
nextKeys.findIndex((o) =>
|
||||
o.unwrapOrDefault().nimbus.toHex() === loggedHex
|
||||
)
|
||||
)
|
||||
)
|
||||
])
|
||||
),
|
||||
map(([selectedCandidates, index]) =>
|
||||
index === -1
|
||||
? null
|
||||
: selectedCandidates[index]
|
||||
)
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// normal operation, non-mapping
|
||||
return combineLatest([
|
||||
of(header),
|
||||
validators,
|
||||
of(null)
|
||||
]);
|
||||
}
|
||||
|
||||
export function getAuthorDetails (api: DeriveApi, header: Header, blockHash?: Uint8Array | string): Observable<[Header, Vec<AccountId> | null, AccountId | null]> {
|
||||
// For on-chain state, we need to retrieve it as per the start
|
||||
// of the block being constructed, i.e. session validators would
|
||||
// be at the point of the block construction, not when all operations
|
||||
// has been supplied.
|
||||
//
|
||||
// However for the first block (no parentHash available), we would
|
||||
// just use the as-is
|
||||
return api.queryAt(
|
||||
header.parentHash.isEmpty
|
||||
? blockHash || header.hash
|
||||
: header.parentHash
|
||||
).pipe(
|
||||
switchMap((queryAt) =>
|
||||
getAuthorDetailsWithAt(header, queryAt)
|
||||
)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user