import { DebugLogger } from "@nostr-fetch/kernel/debugLogger";
import type { NostrFetcherCommonOptions } from "@nostr-fetch/kernel/fetcherBackend";
import { type NostrEvent } from "@nostr-fetch/kernel/nostr";
import { type FetchFilter, type FetchFilterKeyElem, type FetchFilterKeyName, type FetchStatsListener, type RelayStatus } from "./types";
type AssertionResult = {
    severity: "error" | "warn";
    msg: string;
} | {
    severity: "none";
};
/**
 * assert `req` by `assertions`.
 *
 * If there are some errors, throws `NostrFetchError` which includes all error messages raised from assertions.
 * If there are some warnings, just log them.
 */
export declare const assertReq: <T>(req: T, assertions: ((req: T) => AssertionResult)[], logger: DebugLogger | undefined) => void;
export declare function checkIfTrue<T>(predicate: (req: T) => boolean, severity: "error" | "warn", msg: string): (req: T) => AssertionResult;
export declare function checkIfNonEmpty<T, U>(getArray: (req: T) => U[], severity: "error" | "warn", msg: string): (req: T) => AssertionResult;
export declare function checkIfTimeRangeIsValid<T>(getTimeRange: (req: T) => {
    since?: number;
    until?: number;
}, severity: "error" | "warn"): (req: T) => AssertionResult;
export declare function checkIfTagQueriesAreValid<T>(getFilter: (req: T) => FetchFilter, severity: "error" | "warn"): (req: T) => AssertionResult;
/**
 * The comparator for Nostr events. Pass it into `sort()` to sort Nostr events in "newest to oldest" order.
 *
 * If two events have the same `created_at`, the event with the lexicographically lower `id` should come first.
 */
export declare const compareNostrEvents: (a: NostrEvent, b: NostrEvent) => number;
/**
 * get keys corresponds to `keyName` from the event.
 */
export declare const getKeysOfEvent: <K extends FetchFilterKeyName>(keyName: K, ev: NostrEvent) => FetchFilterKeyElem<K>[];
type EventBucketAddResult = {
    state: "open";
} | {
    state: "fulfilled";
    events: NostrEvent[];
} | {
    state: "dropped";
};
/**
 * Set of event buckets for each `key`, with limit on the number of events.
 */
export declare class EventBuckets<K> {
    #private;
    constructor(keys: K[], limit: number);
    getBucket(key: K): NostrEvent[] | undefined;
    /**
     * Adds an event (`ev`) to the bucket for `key` if there is space.
     *
     * Returns a result with `state: "fulfilled"` and events if the bucket is just fulfilled by the addition, otherwise returns `state: "open"`.
     *
     * If the bucket is already full, drops the event and returns `state: "dropped"`.
     */
    add(key: K, ev: NostrEvent): EventBucketAddResult;
    /**
     * Calculates keys and limit for next request to a relay.
     *
     * * `keys`: (all keys) - (keys correspond to a full bucket)
     * * `limit`: SUM( #(limit per key) - #(events in bucket) )
     */
    calcKeysAndLimitForNextReq(): {
        keys: K[];
        limit: number;
    };
}
/**
 * Map from all combinations of keys per relay URL in `keysPerRelay` to a value of type `V`.
 *
 * This has additional mapping from `key` in `keys` to array of values.
 */
export declare class KeyRelayMatrix<K extends string | number, V> {
    #private;
    constructor(relayToKeys: Map<string, K[]>, initVal: () => V);
    get(key: K, relayUrl: string): V | undefined;
    itemsByKey(key: K): V[] | undefined;
}
/**
 * Takes an `AbortSignal` and makes a new `AbortSignal` and a "breaker" function.
 *
 * The signal returned is aborted when:
 * - the original signal is aborted, or
 * - the "breaker" function is called.
 *
 * The "breaker" function is designed to be called in a `finally` block:
 * ```ts
 * const f = (origSignal: AbortSignal) => {
 *   const [signal, breakSignal] = makeBreakableSignal(origSignal);
 *   try {
 *     // ...
 *   } finally {
 *     breakSignal();
 *   }
 * }
 */
export declare const makeBreakableSignal: (signal?: AbortSignal) => [AbortSignal, () => void];
export interface RelayCapabilityChecker {
    relaySupportsNips(relayUrl: string, requiredNips: number[]): Promise<boolean>;
}
declare class DefaultRelayCapChecker implements RelayCapabilityChecker {
    #private;
    constructor(opts: Required<NostrFetcherCommonOptions>);
    relaySupportsNips(relayUrl: string, requiredNips: number[]): Promise<boolean>;
}
export type RelayCapCheckerInitializer = (opts: Required<NostrFetcherCommonOptions>) => RelayCapabilityChecker;
export declare const initDefaultRelayCapChecker: (opts: Required<NostrFetcherCommonOptions>) => DefaultRelayCapChecker;
type SeenEventsReportResult<SeenOn extends boolean> = {
    hasSeen: boolean;
    seenOn: SeenOn extends true ? string[] : undefined;
};
export interface SeenEvents<SeenOn extends boolean> {
    report(event: NostrEvent, relayUrl: string): SeenEventsReportResult<SeenOn>;
    getSeenOn(eventId: string): string[];
}
export declare const initSeenEvents: <SeenOn extends boolean>(withSeenOn: SeenOn) => SeenEvents<SeenOn>;
export declare class FetchStatsManager {
    #private;
    private constructor();
    static init(cb: FetchStatsListener | undefined, notifIntervalMs: number): FetchStatsManager | undefined;
    setProgressMax(max: number): void;
    addProgress(delta: number): void;
    setCurrentProgress(p: number): void;
    eventFetched(rurl: string): void;
    setNumBufferedEvents(n: number): void;
    subOpened(): void;
    subClosed(): void;
    initRelayStats(allReleys: string[], connectedRelays: string[], initUntil: number): void;
    setRelayStatus(rurl: string, status: RelayStatus): void;
    setRelayFrontier(rurl: string, frontier: number): void;
    stop(): void;
}
export declare class ProgressTracker {
    #private;
    constructor(relayUrls: string[]);
    addProgress(relayUrl: string, delta: number): void;
    setProgress(relayUrl: string, prog: number): void;
    calcTotalProgress(): number;
}
export {};
//# sourceMappingURL=fetcherHelper.d.ts.map