// Copyright 2017-2026 @pezkuwi/react-hooks authors & contributors // SPDX-License-Identifier: Apache-2.0 import type { ApiPromise } from '@pezkuwi/api'; import type { EventRecord } from '@pezkuwi/types/interfaces'; import type { Codec } from '@pezkuwi/types/types'; import type { BN } from '@pezkuwi/util'; import type { EventCheck } from './useEventTrigger.js'; import { useEffect, useState } from 'react'; import { isFunction } from '@pezkuwi/util'; import { useApi } from './useApi.js'; import { useEventTrigger } from './useEventTrigger.js'; import { useMemoValue } from './useMemoValue.js'; export interface Changes { added?: T[]; removed?: T[]; } function interleave (existing: T[] = [], { added = [], removed = [] }: Changes): T[] { if (!added.length && !removed.length) { return existing; } const map: Record = {}; [existing, added].forEach((m) => m.forEach((v): void => { map[v.toHex()] = v; }) ); removed.forEach((v): void => { delete map[v.toHex()]; }); const adjusted = Object .entries(map) .sort((a, b) => // for BN-like objects, we use the built-in compare for sorting isFunction((a[1] as unknown as BN).cmp) ? (a[1] as unknown as BN).cmp(b[1] as unknown as BN) : a[0].localeCompare(b[0]) ) .map(([, v]) => v); return adjusted.length !== existing.length || adjusted.find((e, i) => !e.eq(existing[i])) ? adjusted : existing; } export function useEventChanges (checks: EventCheck[], filter: (records: EventRecord[], api: ApiPromise, additional?: A) => Changes, startValue?: T[], additional?: A): T[] | undefined { const { api } = useApi(); const [state, setState] = useState(); const memoChecks = useMemoValue(checks); const { blockHash, events } = useEventTrigger(memoChecks); // when startValue changes, we do a full refresh useEffect((): void => { startValue && setState((prev) => interleave(prev, { added: startValue })); }, [startValue]); // add/remove any additional items detected (only when actual events occur) useEffect((): void => { blockHash && setState((prev) => interleave(prev, filter(events, api, additional))); }, [additional, api, blockHash, events, filter]); return state; }