// Copyright 2017-2025 @pezkuwi/api-derive authors & contributors // SPDX-License-Identifier: Apache-2.0 import type { Observable } from 'rxjs'; import type { Hash, Header } from '@pezkuwi/types/interfaces'; import type { DeriveApi } from '../types.js'; import { from, of, switchMap } from 'rxjs'; import { memo } from '../util/index.js'; /** * Returns a header range from startHash to to (not including) endHash, i.e. lastBlock.parentHash === endHash */ export function _getHeaderRange (instanceId: string, api: DeriveApi): (startHash: Hash, endHash: Hash, prev?: Header[]) => Observable { return memo(instanceId, (startHash: Hash, endHash: Hash, prev: Header[] = []): Observable => api.rpc.chain.getHeader(startHash).pipe( switchMap((header) => header.parentHash.eq(endHash) ? of([header, ...prev]) : api.derive.chain._getHeaderRange(header.parentHash, endHash, [header, ...prev]) ) ) ); } /** * @name subscribeFinalizedHeads * @description An observable of the finalized block headers. Unlike the base * chain.subscribeFinalizedHeads this does not skip any headers. Since finalization * may skip specific blocks (finalization happens in terms of chains), this version * of the derive tracks missing headers (since last retrieved) and provides them * to the caller. * @example * ```javascript * const unsub = await api.derive.chain.subscribeFinalizedHeads((finalizedHead) => { * console.log(`${finalizedHead.hash}`); * }); * ``` */ export function subscribeFinalizedHeads (instanceId: string, api: DeriveApi): () => Observable
{ return memo(instanceId, (): Observable
=> { let prevHash: Hash | null = null; return api.rpc.chain.subscribeFinalizedHeads().pipe( switchMap((header) => { const endHash = prevHash; const startHash = header.parentHash; header.createdAtHash = header.hash as unknown as typeof header.createdAtHash; prevHash = header.hash as unknown as Hash; return endHash === null || startHash.eq(endHash) ? of(header) : api.derive.chain._getHeaderRange(startHash, endHash, [header]).pipe( switchMap((headers) => from(headers) ) ); }) ); }); }