import { EventEmitter as EventEmitter$1 } from 'node:events';
import { EventEmitter } from 'tseep';
import * as nostr_tools_lib_types_nip19_js from 'nostr-tools/lib/types/nip19.js';
import debug$1 from 'debug';
import { LRUCache } from 'typescript-lru-cache';

declare enum NDKKind {
    Metadata = 0,
    Text = 1,
    RecommendRelay = 2,
    Contacts = 3,
    EncryptedDirectMessage = 4,
    EventDeletion = 5,
    Repost = 6,
    Reaction = 7,
    BadgeAward = 8,
    GroupChat = 9,
    GroupNote = 11,
    GroupReply = 12,
    GiftWrapSeal = 13,
    PrivateDirectMessage = 14,
    Image = 20,
    Video = 21,
    ShortVideo = 22,
    Story = 23,
    Vanish = 62,
    CashuWalletBackup = 375,
    GiftWrap = 1059,
    GenericRepost = 16,
    ChannelCreation = 40,
    ChannelMetadata = 41,
    ChannelMessage = 42,
    ChannelHideMessage = 43,
    ChannelMuteUser = 44,
    WikiMergeRequest = 818,
    GenericReply = 1111,
    Media = 1063,
    DraftCheckpoint = 1234,
    Task = 1934,
    Report = 1984,
    Label = 1985,
    DVMReqTextExtraction = 5000,
    DVMReqTextSummarization = 5001,
    DVMReqTextTranslation = 5002,
    DVMReqTextGeneration = 5050,
    DVMReqImageGeneration = 5100,
    DVMReqTextToSpeech = 5250,
    DVMReqDiscoveryNostrContent = 5300,
    DVMReqDiscoveryNostrPeople = 5301,
    DVMReqTimestamping = 5900,
    DVMEventSchedule = 5905,
    DVMJobFeedback = 7000,
    Subscribe = 7001,
    Unsubscribe = 7002,
    SubscriptionReceipt = 7003,
    CashuReserve = 7373,
    CashuQuote = 7374,
    CashuToken = 7375,
    CashuWalletTx = 7376,
    GroupAdminAddUser = 9000,
    GroupAdminRemoveUser = 9001,
    GroupAdminEditMetadata = 9002,
    GroupAdminEditStatus = 9006,
    GroupAdminCreateGroup = 9007,
    GroupAdminRequestJoin = 9021,
    MuteList = 10000,
    PinList = 10001,
    RelayList = 10002,
    BookmarkList = 10003,
    CommunityList = 10004,
    PublicChatList = 10005,
    BlockRelayList = 10006,
    SearchRelayList = 10007,
    SimpleGroupList = 10009,
    InterestList = 10015,
    CashuMintList = 10019,
    EmojiList = 10030,
    DirectMessageReceiveRelayList = 10050,
    BlossomList = 10063,
    NostrWaletConnectInfo = 13194,
    TierList = 17000,
    CashuWallet = 17375,
    FollowSet = 30000,
    CategorizedPeopleList = 30000,// Deprecated but left for backwards compatibility
    CategorizedBookmarkList = 30001,// Deprecated but left for backwards compatibility
    RelaySet = 30002,
    CategorizedRelayList = 30002,// Deprecated but left for backwards compatibility
    BookmarkSet = 30003,
    /**
     * @deprecated Use ArticleCurationSet instead
     */
    CurationSet = 30004,// Deprecated but left for backwards compatibility
    ArticleCurationSet = 30004,
    VideoCurationSet = 30005,
    ImageCurationSet = 30006,
    InterestSet = 30015,
    InterestsList = 30015,// Deprecated but left for backwards compatibility
    ProjectTemplate = 30717,
    EmojiSet = 30030,
    ModularArticle = 30040,
    ModularArticleItem = 30041,
    Wiki = 30818,
    Draft = 31234,
    Project = 31933,
    SubscriptionTier = 37001,
    EcashMintRecommendation = 38000,
    HighlightSet = 39802,
    CategorizedHighlightList = 39802,// Deprecated but left for backwards compatibility
    Nutzap = 9321,
    ZapRequest = 9734,
    Zap = 9735,
    Highlight = 9802,
    ClientAuth = 22242,
    NostrWalletConnectReq = 23194,
    NostrWalletConnectRes = 23195,
    NostrConnect = 24133,
    BlossomUpload = 24242,
    HttpAuth = 27235,
    ProfileBadge = 30008,
    BadgeDefinition = 30009,
    MarketStall = 30017,
    MarketProduct = 30018,
    Article = 30023,
    AppSpecificData = 30078,
    Classified = 30402,
    HorizontalVideo = 34235,
    VerticalVideo = 34236,
    LegacyCashuWallet = 37375,
    GroupMetadata = 39000,// NIP-29
    GroupAdmins = 39001,// NIP-29
    GroupMembers = 39002,// NIP-29
    FollowPack = 39089,
    MediaFollowPack = 39092,
    AppRecommendation = 31989,
    AppHandler = 31990
}

type NDKEncryptionScheme = "nip04" | "nip44";

declare enum NdkNutzapStatus {
    INITIAL = "initial",
    PROCESSING = "processing",
    REDEEMED = "redeemed",
    SPENT = "spent",
    MISSING_PRIVKEY = "missing_privkey",
    TEMPORARY_ERROR = "temporary_error",
    PERMANENT_ERROR = "permanent_error",
    INVALID_NUTZAP = "invalid_nutzap"
}
interface NDKNutzapState {
    nutzap?: NDKNutzap;
    status: NdkNutzapStatus;
    redeemedById?: NDKEventId;
    errorMessage?: string;
    redeemedAmount?: number;
}

type NDKPoolStats = {
    total: number;
    connected: number;
    disconnected: number;
    connecting: number;
};
/**
 * Handles connections to all relays. A single pool should be used per NDK instance.
 *
 * @emit connecting - Emitted when a relay in the pool is connecting.
 * @emit connect - Emitted when all relays in the pool are connected, or when the specified timeout has elapsed, and some relays are connected.
 * @emit notice - Emitted when a relay in the pool sends a notice.
 * @emit flapping - Emitted when a relay in the pool is flapping.
 * @emit relay:connect - Emitted when a relay in the pool connects.
 * @emit relay:ready - Emitted when a relay in the pool is ready to serve requests.
 * @emit relay:disconnect - Emitted when a relay in the pool disconnects.
 */
declare class NDKPool extends EventEmitter<{
    notice: (relay: NDKRelay, notice: string) => void;
    flapping: (relay: NDKRelay) => void;
    connect: () => void;
    "relay:connecting": (relay: NDKRelay) => void;
    /**
     * Emitted when a relay in the pool connects.
     * @param relay - The relay that connected.
     */
    "relay:connect": (relay: NDKRelay) => void;
    "relay:ready": (relay: NDKRelay) => void;
    "relay:disconnect": (relay: NDKRelay) => void;
    "relay:auth": (relay: NDKRelay, challenge: string) => void;
    "relay:authed": (relay: NDKRelay) => void;
}> {
    private _relays;
    private status;
    autoConnectRelays: Set<string>;
    poolBlacklistRelayUrls: Set<string>;
    private debug;
    private temporaryRelayTimers;
    private flappingRelays;
    private backoffTimes;
    private ndk;
    get blacklistRelayUrls(): Set<string>;
    /**
     * @param relayUrls - The URLs of the relays to connect to.
     * @param blacklistedRelayUrls - URLs to blacklist for this pool IN ADDITION to those blacklisted at the ndk-level
     * @param ndk - The NDK instance.
     * @param opts - Options for the pool.
     */
    constructor(relayUrls: WebSocket["url"][], blacklistedRelayUrls: WebSocket["url"][], ndk: NDK, { debug, name, }?: {
        debug?: debug$1.Debugger;
        name?: string;
    });
    get relays(): Map<string, NDKRelay>;
    set relayUrls(urls: WebSocket["url"][]);
    private _name;
    get name(): string;
    set name(name: string);
    /**
     * Adds a relay to the pool, and sets a timer to remove it if it is not used within the specified time.
     * @param relay - The relay to add to the pool.
     * @param removeIfUnusedAfter - The time in milliseconds to wait before removing the relay from the pool after it is no longer used.
     */
    useTemporaryRelay(relay: NDKRelay, removeIfUnusedAfter?: number, filters?: NDKFilter[] | string): void;
    /**
     * Adds a relay to the pool.
     *
     * @param relay - The relay to add to the pool.
     * @param connect - Whether or not to connect to the relay.
     */
    addRelay(relay: NDKRelay, connect?: boolean): void;
    /**
     * Removes a relay from the pool.
     * @param relayUrl - The URL of the relay to remove.
     * @returns {boolean} True if the relay was removed, false if it was not found.
     */
    removeRelay(relayUrl: string): boolean;
    /**
     * Checks whether a relay is already connected in the pool.
     */
    isRelayConnected(url: WebSocket["url"]): boolean;
    /**
     * Fetches a relay from the pool, or creates a new one if it does not exist.
     *
     * New relays will be attempted to be connected.
     */
    getRelay(url: WebSocket["url"], connect?: boolean, temporary?: boolean, filters?: NDKFilter[]): NDKRelay;
    private handleRelayConnect;
    private handleRelayReady;
    /**
     * Attempts to establish a connection to each relay in the pool.
     *
     * @async
     * @param {number} [timeoutMs] - Optional timeout in milliseconds for each connection attempt.
     * @returns {Promise<void>} A promise that resolves when all connection attempts have completed.
     * @throws {Error} If any of the connection attempts result in an error or timeout.
     */
    connect(timeoutMs?: number): Promise<void>;
    private checkOnFlappingRelays;
    private handleFlapping;
    size(): number;
    /**
     * Returns the status of each relay in the pool.
     * @returns {NDKPoolStats} An object containing the number of relays in each status.
     */
    stats(): NDKPoolStats;
    connectedRelays(): NDKRelay[];
    permanentAndConnectedRelays(): NDKRelay[];
    /**
     * Get a list of all relay urls in the pool.
     */
    urls(): string[];
}

/**
 * NDKUserProfile represents a user's kind 0 profile metadata
 */
interface NDKUserProfile {
    [key: string]: string | number | undefined;
    created_at?: number;
    name?: string;
    displayName?: string;
    /**
     * @deprecated Use picture instead
     */
    image?: string;
    picture?: string;
    banner?: string;
    bio?: string;
    nip05?: string;
    lud06?: string;
    lud16?: string;
    about?: string;
    website?: string;
    profileEvent?: string;
}

type NDKPaymentConfirmationLN = {
    preimage: string;
};
type LNPaymentRequest = string;
type LnPaymentInfo = {
    pr: LNPaymentRequest;
};
type NDKLUD18ServicePayerData = Partial<{
    name: {
        mandatory: boolean;
    };
    pubkey: {
        mandatory: boolean;
    };
    identifier: {
        mandatory: boolean;
    };
    email: {
        mandatory: boolean;
    };
    auth: {
        mandatory: boolean;
        k1: string;
    };
}> & Record<string, unknown>;
type NDKLnUrlData = {
    tag: string;
    callback: string;
    minSendable: number;
    maxSendable: number;
    metadata: string;
    payerData?: NDKLUD18ServicePayerData;
    commentAllowed?: number;
    /**
     * Pubkey of the zapper that should publish zap receipts for this user
     */
    nostrPubkey?: Hexpubkey;
    allowsNostr?: boolean;
};

type NDKCacheEntry<T> = T & {
    cachedAt?: number;
};
interface NDKCacheAdapter {
    /**
     * Whether this cache adapter is expected to be fast.
     * If this is true, the cache will be queried before the relays.
     * When this is false, the cache will be queried in addition to the relays.
     */
    locking: boolean;
    /**
     * Weather the cache is ready.
     */
    ready?: boolean;
    initializeAsync?(ndk: NDK): Promise<void>;
    initialize?(ndk: NDK): void;
    /**
     * Either synchronously or asynchronously queries the cache.
     *
     * Cache adapters that return values synchronously should return an array of events.
     * Asynchronous cache adapters should call the subscription.eventReceived method for each event.
     */
    query(subscription: NDKSubscription): NDKEvent[] | Promise<NDKEvent[]>;
    setEvent(event: NDKEvent, filters: NDKFilter[], relay?: NDKRelay): Promise<void>;
    /**
     * Called when an event is deleted by the client.
     * Cache adapters should remove the event from their cache.
     * @param eventIds - The ids of the events that were deleted.
     */
    deleteEventIds?(eventIds: NDKEventId[]): Promise<void>;
    /**
     * Fetches a profile from the cache synchronously.
     * @param pubkey - The pubkey of the profile to fetch.
     * @returns The profile, or null if it is not in the cache.
     */
    fetchProfileSync?(pubkey: Hexpubkey): NDKCacheEntry<NDKUserProfile> | null;
    /**
     * Retrieve all profiles from the cache synchronously.
     * @returns A map of pubkeys to profiles.
     */
    getAllProfilesSync?(): Map<Hexpubkey, NDKCacheEntry<NDKUserProfile>>;
    /**
     * Special purpose
     */
    fetchProfile?(pubkey: Hexpubkey): Promise<NDKCacheEntry<NDKUserProfile> | null>;
    saveProfile?(pubkey: Hexpubkey, profile: NDKUserProfile): void;
    /**
     * Fetches profiles that match the given filter.
     * @param filter
     * @returns NDKUserProfiles that match the filter.
     * @example
     * const searchFunc = (pubkey, profile) => profile.name.toLowerCase().includes("alice");
     * const allAliceProfiles = await cache.getProfiles(searchFunc);
     */
    getProfiles?: (filter: (pubkey: Hexpubkey, profile: NDKUserProfile) => boolean) => Promise<Map<Hexpubkey, NDKUserProfile> | undefined>;
    loadNip05?(nip05: string, maxAgeForMissing?: number): Promise<ProfilePointer | null | "missing">;
    saveNip05?(nip05: string, profile: ProfilePointer | null): void;
    /**
     * Fetches a user's LNURL data from the cache.
     * @param pubkey The pubkey of the user to fetch the LNURL data for.
     * @param maxAgeInSecs The maximum age of the data in seconds.
     * @param maxAgeForMissing The maximum age of the data in seconds if it is missing before it returns that it should be refetched.
     * @returns The LNURL data, null if it is not in the cache and under the maxAgeForMissing, or "missing" if it should be refetched.
     */
    loadUsersLNURLDoc?(pubkey: Hexpubkey, maxAgeInSecs?: number, maxAgeForMissing?: number): Promise<NDKLnUrlData | null | "missing">;
    saveUsersLNURLDoc?(pubkey: Hexpubkey, doc: NDKLnUrlData | null): void;
    /**
     * Updates information about the relay.
     */
    updateRelayStatus?(relayUrl: WebSocket["url"], info: NDKCacheRelayInfo): void;
    /**
     * Fetches information about the relay.
     */
    getRelayStatus?(relayUrl: WebSocket["url"]): NDKCacheRelayInfo | undefined;
    /**
     * Tracks a publishing event.
     * @param event
     * @param relayUrls List of relays that the event will be published to.
     */
    addUnpublishedEvent?(event: NDKEvent, relayUrls: WebSocket["url"][]): void;
    /**
     * Fetches all unpublished events.
     */
    getUnpublishedEvents?(): Promise<{
        event: NDKEvent;
        relays?: WebSocket["url"][];
        lastTryAt?: number;
    }[]>;
    /**
     * Removes an unpublished event.
     */
    discardUnpublishedEvent?(eventId: NDKEventId): void;
    /**
     * Called when the cache is ready.
     */
    onReady?(callback: () => void): void;
    /**
     * Get a decrypted event from the cache by ID.
     * @param eventId - The ID of the decrypted event to get.
     * @returns The decrypted event, or null if it doesn't exist.
     */
    getDecryptedEvent?(eventId: NDKEventId): NDKEvent | null;
    /**
     * Store a decrypted event in the cache.
     * @param event - The decrypted event to store.
     */
    addDecryptedEvent?(event: NDKEvent): void;
    /**
     * Cleans up the cache. This is called when the user logs out.
     */
    clear?(): Promise<void>;
    /**
     * Gets all nutzap states from the cache.
     * @returns A map of event IDs to nutzap states.
     */
    getAllNutzapStates?(): Promise<Map<NDKEventId, NDKNutzapState>>;
    /**
     * Sets the state of a nutzap in the cache.
     * @param id The ID of the nutzap event.
     * @param stateChange The partial state change to apply.
     */
    setNutzapState?(id: NDKEventId, stateChange: Partial<NDKNutzapState>): Promise<void>;
}
type NDKCacheRelayInfo = {
    lastConnectedAt?: number;
    dontConnectBefore?: number;
};

type ContentTag = {
    tags: NDKTag[];
    content: string;
};

interface NDKSigner {
    /**
     * Synchronously get the public key of the signer.
     * @throws {Error} "Not ready" when the signer is not ready to provide a pubkey synchronously (e.g., NIP-07 or NIP-46 signers)
     * @returns The public key in hex format
     */
    get pubkey(): string;
    /**
     * Blocks until the signer is ready and returns the associated NDKUser.
     * @returns A promise that resolves to the NDKUser instance.
     */
    blockUntilReady(): Promise<NDKUser>;
    /**
     * Getter for the user property.
     * @returns A promise that resolves to the NDKUser instance.
     */
    user(): Promise<NDKUser>;
    get userSync(): NDKUser;
    /**
     * Signs the given Nostr event.
     * @param event - The Nostr event to be signed.
     * @returns A promise that resolves to the signature of the signed event.
     */
    sign(event: NostrEvent): Promise<string>;
    /**
     * Getter for the preferred relays.
     * @returns A promise containing a simple map of preferred relays and their read/write policies.
     */
    relays?(ndk?: NDK): Promise<NDKRelay[]>;
    /**
     * Determine the types of encryption (by nip) that this signer can perform.
     * Implementing classes SHOULD return a value even for legacy (only nip04) third party signers.
     * @nip Optionally returns an array with single supported nip or empty, to check for truthy or falsy.
     * @return A promised list of any (or none) of these strings  ['nip04', 'nip44']
     */
    encryptionEnabled?(scheme?: NDKEncryptionScheme): Promise<NDKEncryptionScheme[]>;
    /**
     * Encrypts the given Nostr event for the given recipient.
     * Implementing classes SHOULD equate legacy (only nip04) to nip == `nip04` || undefined
     * @param recipient - The recipient (pubkey or conversationKey) of the encrypted value.
     * @param value - The value to be encrypted.
     * @param nip - which NIP is being implemented ('nip04', 'nip44')
     */
    encrypt(recipient: NDKUser, value: string, scheme?: NDKEncryptionScheme): Promise<string>;
    /**
     * Decrypts the given value.
     * Implementing classes SHOULD equate legacy (only nip04) to nip == `nip04` || undefined
     * @param sender - The sender (pubkey or conversationKey) of the encrypted value
     * @param value - The value to be decrypted
     * @param scheme - which NIP is being implemented ('nip04', 'nip44', 'nip49')
     */
    decrypt(sender: NDKUser, value: string, scheme?: NDKEncryptionScheme): Promise<string>;
    /**
     * Serializes the signer's essential data into a storable format.
     * @returns A JSON string containing the type and payload.
     */
    toPayload(): string;
}

type Proof$1 = {
    /**
     * Keyset id, used to link proofs to a mint an its MintKeys.
     */
    id: string;
    /**
     * Amount denominated in Satoshis. Has to match the amount of the mints signing key.
     */
    amount: number;
    /**
     * The initial secret that was (randomly) chosen for the creation of this proof.
     */
    secret: string;
    /**
     * The unblinded signature for this secret, signed by the mints private key.
     */
    C: string;
};

/**
 * Represents a NIP-61 nutzap
 */
declare class NDKNutzap extends NDKEvent {
    private debug;
    private _proofs;
    static kind: NDKKind;
    static kinds: NDKKind[];
    constructor(ndk?: NDK, event?: NostrEvent | NDKEvent);
    static from(event: NDKEvent): NDKNutzap | undefined;
    set comment(comment: string | undefined);
    get comment(): string;
    set proofs(proofs: Proof$1[]);
    get proofs(): Proof$1[];
    get rawP2pk(): string | undefined;
    /**
     * Gets the p2pk pubkey that is embedded in the first proof.
     *
     * Note that this returns a nostr pubkey, not a cashu pubkey (no "02" prefix)
     */
    get p2pk(): string | undefined;
    /**
     * Get the mint where this nutzap proofs exist
     */
    get mint(): string;
    set mint(value: string);
    get unit(): string;
    set unit(value: string | undefined);
    get amount(): number;
    sender: NDKUser;
    /**
     * Set the target of the nutzap
     * @param target The target of the nutzap (a user or an event)
     */
    set target(target: NDKEvent | NDKUser);
    set recipientPubkey(pubkey: Hexpubkey);
    get recipientPubkey(): Hexpubkey;
    get recipient(): NDKUser;
    toNostrEvent(): Promise<NostrEvent>;
    /**
     * Validates that the nutzap conforms to NIP-61
     */
    get isValid(): boolean;
}

/**
 * A signer that uses an in-memory private key (nsec).
 *
 * @example
 * ```ts
 * const signer = NDKPrivateKeySigner.generate();
 * console.log('your nsec is', signer.nsec);
 * console.log('your pubkey is', signer.pubkey);
 * console.log('your npub is', signer.npub);
 * ```
 *
 * @example
 * ```ts
 * const signer = new NDKPrivateKeySigner(nsec);
 * ```
 */
declare class NDKPrivateKeySigner implements NDKSigner {
    private _user;
    private _privateKey;
    private _pubkey?;
    /**
     * Create a new signer from a private key.
     * @param privateKey - The private key to use in hex form or nsec.
     * @param ndk - The NDK instance to use.
     */
    constructor(privateKeyOrNsec: Uint8Array | string, ndk?: NDK);
    /**
     * Get the private key in hex form.
     */
    get privateKey(): string;
    /**
     * Get the public key in hex form.
     */
    get pubkey(): string;
    /**
     * Get the private key in nsec form.
     */
    get nsec(): string;
    /**
     * Get the public key in npub form.
     */
    get npub(): string;
    /**
     * Generate a new private key.
     */
    static generate(): NDKPrivateKeySigner;
    /**
     * Noop in NDKPrivateKeySigner.
     */
    blockUntilReady(): Promise<NDKUser>;
    /**
     * Get the user.
     */
    user(): Promise<NDKUser>;
    /**
     * Get the user.
     */
    get userSync(): NDKUser;
    sign(event: NostrEvent): Promise<string>;
    encryptionEnabled(scheme?: NDKEncryptionScheme): Promise<NDKEncryptionScheme[]>;
    encrypt(recipient: NDKUser, value: string, scheme?: NDKEncryptionScheme): Promise<string>;
    decrypt(sender: NDKUser, value: string, scheme?: NDKEncryptionScheme): Promise<string>;
    /**
     * Serializes the signer's private key into a storable format.
     * @returns A JSON string containing the type and the hex private key.
     */
    toPayload(): string;
    /**
     * Deserializes the signer from a payload string.
     * @param payloadString The JSON string obtained from toPayload().
     * @param ndk Optional NDK instance.
     * @returns An instance of NDKPrivateKeySigner.
     */
    static fromPayload(payloadString: string, ndk?: NDK): Promise<NDKPrivateKeySigner>;
}

/**
 * NDKAuthPolicies are functions that are called when a relay requests authentication
 * so that you can define a behavior for your application.
 *
 * @param relay The relay that requested authentication.
 * @param challenge The challenge that the relay sent.
 */
type NDKAuthPolicy = (relay: NDKRelay, challenge: string) => Promise<boolean | undefined | NDKEvent>;

type Nip07RelayMap = {
    [key: string]: {
        read: boolean;
        write: boolean;
    };
};
type Nip44 = {
    encrypt: (recipient: Hexpubkey, value: string) => Promise<string>;
    decrypt: (sender: Hexpubkey, value: string) => Promise<string>;
};
declare global {
    interface Window {
        nostr?: {
            getPublicKey(): Promise<string>;
            signEvent(event: NostrEvent): Promise<{
                sig: string;
            }>;
            getRelays?: () => Promise<Nip07RelayMap>;
            nip04?: {
                encrypt(recipientHexPubKey: string, value: string): Promise<string>;
                decrypt(senderHexPubKey: string, value: string): Promise<string>;
            };
            nip44?: Nip44;
        };
    }
}

type NDKFilterFingerprint = string;

type NDKEventSerialized = string;

/**
 * Provides information that should be used to send a NIP-61 nutzap.
 * mints: URLs of the mints that can be used.
 * relays: URLs of the relays where nutzap must be published
 * p2pk: Optional pubkey to use for P2PK lock
 */
type CashuPaymentInfo = {
    /**
     * Mints that must be used for the payment
     */
    mints?: string[];
    /**
     * Relays where nutzap must be published
     */
    relays?: string[];
    /**
     * Optional pubkey to use for P2PK lock
     */
    p2pk?: string;
    /**
     * Intramint fallback allowed:
     *
     * When set to true, if cross-mint payments fail, we will
     * fallback to sending an intra-mint payment.
     */
    allowIntramintFallback?: boolean;
};
/**
 * This is what a wallet implementing Cashu payments should provide back
 * when a payment has been requested.
 */
type NDKPaymentConfirmationCashu = {
    /**
     * Proof of the payment
     */
    proofs: Proof$1[];
    /**
     * Mint
     */
    mint: string;
};

type NDKZapDetails<T> = T & {
    /**
     * Target of the zap
     */
    target: NDKEvent | NDKUser;
    /**
     * Comment for the zap
     */
    comment?: string;
    /**
     * Tags to add to the zap
     */
    tags?: NDKTag[];
    /**
     * Pubkey of the user to zap to
     */
    recipientPubkey: string;
    /**
     * Amount of the payment
     */
    amount: number;
    /**
     * Unit of the payment (e.g. msat)
     */
    unit: string;
    /**
     * Description of the payment for the sender's record
     */
    paymentDescription?: string;
    /**
     * If this payment is for a nip57 zap, this will contain the zap request.
     */
    nip57ZapRequest?: NDKEvent;
    /**
     * When set to true, when a pubkey is not zappable, we will
     * automatically fallback to using NIP-61.
     *
     * Every pubkey must be able to receive money.
     *
     * @default false
     */
    nutzapAsFallback?: boolean;
};
type NDKPaymentConfirmation = NDKPaymentConfirmationLN | NDKNutzap;
type NDKZapSplit = {
    pubkey: string;
    amount: number;
};
type NDKZapMethod = "nip57" | "nip61";
type NDKLnLudData = {
    lud06?: string;
    lud16?: string;
};
type NDKZapMethodInfo = NDKLnLudData | CashuPaymentInfo;
type LnPayCb = (payment: NDKZapDetails<LnPaymentInfo>) => Promise<NDKPaymentConfirmationLN | undefined>;
type CashuPayCb = (payment: NDKZapDetails<CashuPaymentInfo>, onLnInvoice?: (pr: string) => void) => Promise<NDKPaymentConfirmationCashu | undefined>;

type Hexpubkey = string;
type Npub = string;
type ProfilePointer = {
    pubkey: string;
    relays?: string[];
    nip46?: string[];
};
interface NDKUserParams {
    npub?: Npub;
    hexpubkey?: Hexpubkey;
    pubkey?: Hexpubkey;
    nip05?: string;
    relayUrls?: string[];
    nip46Urls?: string[];
    nprofile?: string;
}
/**
 * Represents a pubkey.
 */
declare class NDKUser {
    ndk: NDK | undefined;
    profile?: NDKUserProfile;
    profileEvent?: NDKEvent;
    private _npub?;
    private _pubkey?;
    relayUrls: string[];
    readonly nip46Urls: string[];
    constructor(opts: NDKUserParams);
    get npub(): string;
    get nprofile(): string;
    set npub(npub: Npub);
    /**
     * Get the user's pubkey
     * @returns {string} The user's pubkey
     */
    get pubkey(): string;
    /**
     * Set the user's pubkey
     * @param pubkey {string} The user's pubkey
     */
    set pubkey(pubkey: string);
    /**
     * Equivalent to NDKEvent.filters().
     * @returns {NDKFilter}
     */
    filter(): NDKFilter;
    /**
     * Gets NIP-57 and NIP-61 information that this user has signaled
     *
     * @param getAll {boolean} Whether to get all zap info or just the first one
     */
    getZapInfo(timeoutMs?: number): Promise<Map<NDKZapMethod, NDKZapMethodInfo>>;
    /**
     * Instantiate an NDKUser from a NIP-05 string
     * @param nip05Id {string} The user's NIP-05
     * @param ndk {NDK} An NDK instance
     * @param skipCache {boolean} Whether to skip the cache or not
     * @returns {NDKUser | undefined} An NDKUser if one is found for the given NIP-05, undefined otherwise.
     */
    static fromNip05(nip05Id: string, ndk: NDK, skipCache?: boolean): Promise<NDKUser | undefined>;
    /**
     * Fetch a user's profile
     * @param opts {NDKSubscriptionOptions} A set of NDKSubscriptionOptions
     * @param storeProfileEvent {boolean} Whether to store the profile event or not
     * @returns User Profile
     */
    fetchProfile(opts?: NDKSubscriptionOptions, storeProfileEvent?: boolean): Promise<NDKUserProfile | null>;
    /**
     * Returns a set of users that this user follows.
     *
     * @deprecated Use followSet instead
     */
    follows: (opts?: NDKSubscriptionOptions | undefined, outbox?: boolean | undefined, kind?: number | undefined) => Promise<Set<NDKUser>>;
    /**
     * Returns a set of pubkeys that this user follows.
     *
     * @param opts - NDKSubscriptionOptions
     * @param outbox - boolean
     * @param kind - number
     */
    followSet(opts?: NDKSubscriptionOptions, outbox?: boolean, kind?: number): Promise<Set<Hexpubkey>>;
    /** @deprecated Use referenceTags instead. */
    /**
     * Get the tag that can be used to reference this user in an event
     * @returns {NDKTag} an NDKTag
     */
    tagReference(): NDKTag;
    /**
     * Get the tags that can be used to reference this user in an event
     * @returns {NDKTag[]} an array of NDKTag
     */
    referenceTags(marker?: string): NDKTag[];
    /**
     * Publishes the current profile.
     */
    publish(): Promise<void>;
    /**
     * Add a follow to this user's contact list
     *
     * @param newFollow {NDKUser} The user to follow
     * @param currentFollowList {Set<NDKUser>} The current follow list
     * @param kind {NDKKind} The kind to use for this contact list (defaults to `3`)
     * @returns {Promise<boolean>} True if the follow was added, false if the follow already exists
     */
    follow(newFollow: NDKUser, currentFollowList?: Set<NDKUser>, kind?: NDKKind): Promise<boolean>;
    /**
     * Remove a follow from this user's contact list
     *
     * @param user {NDKUser} The user to unfollow
     * @param currentFollowList {Set<NDKUser>} The current follow list
     * @param kind {NDKKind} The kind to use for this contact list (defaults to `3`)
     * @returns The relays were the follow list was published or false if the user wasn't found
     */
    unfollow(user: NDKUser, currentFollowList?: Set<NDKUser>, kind?: NDKKind): Promise<Set<NDKRelay> | boolean>;
    /**
     * Validate a user's NIP-05 identifier (usually fetched from their kind:0 profile data)
     *
     * @param nip05Id The NIP-05 string to validate
     * @returns {Promise<boolean | null>} True if the NIP-05 is found and matches this user's pubkey,
     * False if the NIP-05 is found but doesn't match this user's pubkey,
     * null if the NIP-05 isn't found on the domain or we're unable to verify (because of network issues, etc.)
     */
    validateNip05(nip05Id: string): Promise<boolean | null>;
}

type NDKSubscriptionId = string;
/**
 * This class monitors active subscriptions.
 */
declare class NDKSubscriptionManager {
    subscriptions: Map<NDKSubscriptionId, NDKSubscription>;
    seenEvents: Map<string, NDKRelay[]>;
    constructor();
    add(sub: NDKSubscription): void;
    seenEvent(eventId: NDKEventId, relay: NDKRelay): void;
    /**
     * Whenever an event comes in, this function is called.
     * This function matches the received event against all the
     * known (i.e. active) NDKSubscriptions, and if it matches,
     * it sends the event to the subscription.
     *
     * This is the single place in the codebase that matches
     * incoming events with parties interested in the event.
     *
     * This is also what allows for reactivity in NDK apps, such that
     * whenever an active subscription receives an event that some
     * other active subscription would want to receive, both receive it.
     *
     * TODO This also allows for subscriptions that overlap in meaning
     * to be collapsed into one.
     *
     * I.e. if a subscription with filter: kinds: [1], authors: [alice]
     * is created and EOSEs, and then a subsequent subscription with
     * kinds: [1], authors: [alice] is created, once the second subscription
     * EOSEs we can safely close it, increment its refCount and close it,
     * and when the first subscription receives a new event from Alice this
     * code will make the second subscription receive the event even though
     * it has no active subscription on a relay.
     * @param event Raw event received from a relay
     * @param relay Relay that sent the event
     * @param optimisticPublish Whether the event is coming from an optimistic publish
     */
    dispatchEvent(event: NostrEvent, relay?: NDKRelay, optimisticPublish?: boolean): void;
}

type Item = {
    subscription: NDKSubscription;
    filters: NDKFilter[];
};
declare enum NDKRelaySubscriptionStatus {
    INITIAL = 0,
    /**
     * The subscription is pending execution.
     */
    PENDING = 1,
    /**
     * The subscription is waiting for the relay to be ready.
     */
    WAITING = 2,
    /**
     * The subscription is currently running.
     */
    RUNNING = 3,
    CLOSED = 4
}
/**
 * Groups together a number of NDKSubscriptions (as created by the user),
 * filters (as computed internally), executed, or to be executed, within
 * a single specific relay.
 */
declare class NDKRelaySubscription {
    fingerprint: NDKFilterFingerprint;
    items: Map<NDKSubscriptionInternalId, Item>;
    topSubManager: NDKSubscriptionManager;
    debug: debug.Debugger;
    /**
     * Tracks the status of this REQ.
     */
    status: NDKRelaySubscriptionStatus;
    onClose?: (sub: NDKRelaySubscription) => void;
    private relay;
    /**
     * Whether this subscription has reached EOSE.
     */
    private eosed;
    /**
     * Timeout at which this subscription will
     * start executing.
     */
    private executionTimer?;
    /**
     * Track the time at which this subscription will fire.
     */
    private fireTime?;
    /**
     * The delay type that the current fireTime was calculated with.
     */
    private delayType?;
    /**
     * The filters that have been executed.
     */
    executeFilters?: NDKFilter[];
    readonly id: string;
    /**
     *
     * @param fingerprint The fingerprint of this subscription.
     */
    constructor(relay: NDKRelay, fingerprint: NDKFilterFingerprint | null, topSubManager: NDKSubscriptionManager);
    private _subId?;
    get subId(): string;
    private subIdParts;
    private addSubIdPart;
    addItem(subscription: NDKSubscription, filters: NDKFilter[]): void;
    /**
     * A subscription has been closed, remove it from the list of items.
     * @param subscription
     */
    removeItem(subscription: NDKSubscription): void;
    private close;
    cleanup(): void;
    private evaluateExecutionPlan;
    private schedule;
    private executeOnRelayReady;
    private finalizeSubId;
    private reExecuteAfterAuth;
    private execute;
    onstart(): void;
    onevent(event: NostrEvent): void;
    oneose(subId: string): void;
    onclose(_reason?: string): void;
    onclosed(reason?: string): void;
    /**
     * Grabs the filters from all the subscriptions
     * and merges them into a single filter.
     */
    private compileFilters;
}

declare class NDKRelayConnectivity {
    private ndkRelay;
    private ws?;
    private _status;
    private timeoutMs?;
    private connectedAt?;
    private _connectionStats;
    private debug;
    netDebug?: NDKNetDebug;
    private connectTimeout;
    private reconnectTimeout;
    private ndk?;
    openSubs: Map<string, NDKRelaySubscription>;
    private openCountRequests;
    private openEventPublishes;
    private serial;
    baseEoseTimeout: number;
    constructor(ndkRelay: NDKRelay, ndk?: NDK);
    /**
     * Connects to the NDK relay and handles the connection lifecycle.
     *
     * This method attempts to establish a WebSocket connection to the NDK relay specified in the `ndkRelay` object.
     * If the connection is successful, it updates the connection statistics, sets the connection status to `CONNECTED`,
     * and emits `connect` and `ready` events on the `ndkRelay` object.
     *
     * If the connection attempt fails, it handles the error by either initiating a reconnection attempt or emitting a
     * `delayed-connect` event on the `ndkRelay` object, depending on the `reconnect` parameter.
     *
     * @param timeoutMs - The timeout in milliseconds for the connection attempt. If not provided, the default timeout from the `ndkRelay` object is used.
     * @param reconnect - Indicates whether a reconnection should be attempted if the connection fails. Defaults to `true`.
     * @returns A Promise that resolves when the connection is established, or rejects if the connection fails.
     */
    connect(timeoutMs?: number, reconnect?: boolean): Promise<void>;
    /**
     * Disconnects the WebSocket connection to the NDK relay.
     * This method sets the connection status to `NDKRelayStatus.DISCONNECTING`,
     * attempts to close the WebSocket connection, and sets the status to
     * `NDKRelayStatus.DISCONNECTED` if the disconnect operation fails.
     */
    disconnect(): void;
    /**
     * Handles the error that occurred when attempting to connect to the NDK relay.
     * If `reconnect` is `true`, this method will initiate a reconnection attempt.
     * Otherwise, it will emit a `delayed-connect` event on the `ndkRelay` object,
     * indicating that a reconnection should be attempted after a delay.
     *
     * @param reconnect - Indicates whether a reconnection should be attempted.
     */
    onConnectionError(reconnect: boolean): void;
    /**
     * Handles the connection event when the WebSocket connection is established.
     * This method is called when the WebSocket connection is successfully opened.
     * It clears any existing connection and reconnection timeouts, updates the connection statistics,
     * sets the connection status to `CONNECTED`, and emits `connect` and `ready` events on the `ndkRelay` object.
     */
    private onConnect;
    /**
     * Handles the disconnection event when the WebSocket connection is closed.
     * This method is called when the WebSocket connection is successfully closed.
     * It updates the connection statistics, sets the connection status to `DISCONNECTED`,
     * initiates a reconnection attempt if we didn't disconnect ourselves,
     * and emits a `disconnect` event on the `ndkRelay` object.
     */
    private onDisconnect;
    /**
     * Handles incoming messages from the NDK relay WebSocket connection.
     * This method is called whenever a message is received from the relay.
     * It parses the message data and dispatches the appropriate handling logic based on the message type.
     *
     * @param event - The MessageEvent containing the received message data.
     */
    private onMessage;
    /**
     * Handles an authentication request from the NDK relay.
     *
     * If an authentication policy is configured, it will be used to authenticate the connection.
     * Otherwise, the `auth` event will be emitted to allow the application to handle the authentication.
     *
     * @param challenge - The authentication challenge provided by the NDK relay.
     */
    private onAuthRequested;
    /**
     * Handles errors that occur on the WebSocket connection to the relay.
     * @param error - The error or event that occurred.
     */
    private onError;
    /**
     * Gets the current status of the NDK relay connection.
     * @returns {NDKRelayStatus} The current status of the NDK relay connection.
     */
    get status(): NDKRelayStatus;
    /**
     * Checks if the NDK relay connection is currently available.
     * @returns {boolean} `true` if the relay connection is in the `CONNECTED` status, `false` otherwise.
     */
    isAvailable(): boolean;
    /**
     * Checks if the NDK relay connection is flapping, which means the connection is rapidly
     * disconnecting and reconnecting. This is determined by analyzing the durations of the
     * last three connection attempts. If the standard deviation of the durations is less
     * than 1000 milliseconds, the connection is considered to be flapping.
     *
     * @returns {boolean} `true` if the connection is flapping, `false` otherwise.
     */
    private isFlapping;
    /**
     * Handles a notice received from the NDK relay.
     * If the notice indicates the relay is complaining (e.g. "too many" or "maximum"),
     * the method disconnects from the relay and attempts to reconnect after a 2-second delay.
     * A debug message is logged with the relay URL and the notice text.
     * The "notice" event is emitted on the ndkRelay instance with the notice text.
     *
     * @param notice - The notice text received from the NDK relay.
     */
    private onNotice;
    /**
     * Attempts to reconnect to the NDK relay after a connection is lost.
     * This function is called recursively to handle multiple reconnection attempts.
     * It checks if the relay is flapping and emits a "flapping" event if so.
     * It then calculates a delay before the next reconnection attempt based on the number of previous attempts.
     * The function sets a timeout to execute the next reconnection attempt after the calculated delay.
     * If the maximum number of reconnection attempts is reached, a debug message is logged.
     *
     * @param attempt - The current attempt number (default is 0).
     */
    private handleReconnection;
    /**
     * Sends a message to the NDK relay if the connection is in the CONNECTED state and the WebSocket is open.
     * If the connection is not in the CONNECTED state or the WebSocket is not open, logs a debug message and throws an error.
     *
     * @param message - The message to send to the NDK relay.
     * @throws {Error} If attempting to send on a closed relay connection.
     */
    send(message: string): Promise<void>;
    /**
     * Authenticates the NDK event by sending it to the NDK relay and returning a promise that resolves with the result.
     *
     * @param event - The NDK event to authenticate.
     * @returns A promise that resolves with the authentication result.
     */
    private auth;
    /**
     * Publishes an NDK event to the relay and returns a promise that resolves with the result.
     *
     * @param event - The NDK event to publish.
     * @returns A promise that resolves with the result of the event publication.
     * @throws {Error} If attempting to publish on a closed relay connection.
     */
    publish(event: NostrEvent): Promise<string>;
    /**
     * Counts the number of events that match the provided filters.
     *
     * @param filters - The filters to apply to the count request.
     * @param params - An optional object containing a custom id for the count request.
     * @returns A promise that resolves with the number of matching events.
     * @throws {Error} If attempting to send the count request on a closed relay connection.
     */
    count(filters: NDKFilter[], params: {
        id?: string | null;
    }): Promise<number>;
    close(subId: string, reason?: string): void;
    /**
     * Subscribes to the NDK relay with the provided filters and parameters.
     *
     * @param filters - The filters to apply to the subscription.
     * @param params - The subscription parameters, including an optional custom id.
     * @returns A new NDKRelaySubscription instance.
     */
    req(relaySub: NDKRelaySubscription): void;
    /**
     * Utility functions to update the connection stats.
     */
    private updateConnectionStats;
    /** Returns the connection stats. */
    get connectionStats(): NDKRelayConnectionStats;
    /** Returns the relay URL */
    get url(): WebSocket["url"];
    get connected(): boolean;
}

type NDKRelayScore = number;

/**
 * The subscription manager of an NDKRelay is in charge of orchestrating the subscriptions
 * that are created and closed in a given relay.
 *
 * The manager is responsible for:
 * * restarting subscriptions when they are unexpectedly closed
 * * scheduling subscriptions that are received before the relay is connected
 * * grouping similar subscriptions to be compiled into individual REQs
 */
declare class NDKRelaySubscriptionManager {
    private relay;
    subscriptions: Map<NDKFilterFingerprint, NDKRelaySubscription[]>;
    private generalSubManager;
    /**
     * @param relay - The relay instance.
     * @param generalSubManager - The subscription manager instance.
     */
    constructor(relay: NDKRelay, generalSubManager: NDKSubscriptionManager);
    /**
     * Adds a subscription to the manager.
     */
    addSubscription(sub: NDKSubscription, filters: NDKFilter[]): void;
    createSubscription(_sub: NDKSubscription, _filters: NDKFilter[], fingerprint?: NDKFilterFingerprint): NDKRelaySubscription;
    private onRelaySubscriptionClose;
}

declare enum NDKRelayStatus {
    DISCONNECTING = 0,// 0
    DISCONNECTED = 1,// 1
    RECONNECTING = 2,// 2
    FLAPPING = 3,// 3
    CONNECTING = 4,// 4
    CONNECTED = 5,// 5
    AUTH_REQUESTED = 6,// 6
    AUTHENTICATING = 7,// 7
    AUTHENTICATED = 8
}
interface NDKRelayConnectionStats {
    /**
     * The number of times a connection has been attempted.
     */
    attempts: number;
    /**
     * The number of times a connection has been successfully established.
     */
    success: number;
    /**
     * The durations of the last 100 connections in milliseconds.
     */
    durations: number[];
    /**
     * The time the current connection was established in milliseconds.
     */
    connectedAt?: number;
    /**
     * Timestamp of the next reconnection attempt.
     */
    nextReconnectAt?: number;
    /**
     * Signature validation ratio for this relay.
     * @see NDKRelayOptions.validationRatio
     */
    validationRatio?: number;
}
/**
 * The NDKRelay class represents a connection to a relay.
 *
 * @emits NDKRelay#connect
 * @emits NDKRelay#ready
 * @emits NDKRelay#disconnect
 * @emits NDKRelay#notice
 * @emits NDKRelay#event
 * @emits NDKRelay#published when an event is published to the relay
 * @emits NDKRelay#publish:failed when an event fails to publish to the relay
 * @emits NDKRelay#eose when the relay has reached the end of stored events
 * @emits NDKRelay#auth when the relay requires authentication
 * @emits NDKRelay#authed when the relay has authenticated
 * @emits NDKRelay#delayed-connect when the relay will wait before reconnecting
 */
declare class NDKRelay extends EventEmitter<{
    connect: () => void;
    ready: () => void;
    /**
     * Emitted when the relay has reached the end of stored events.
     */
    disconnect: () => void;
    flapping: (stats: NDKRelayConnectionStats) => void;
    notice: (notice: string) => void;
    auth: (challenge: string) => void;
    authed: () => void;
    "auth:failed": (error: Error) => void;
    published: (event: NDKEvent) => void;
    "publish:failed": (event: NDKEvent, error: Error) => void;
    "delayed-connect": (delayInMs: number) => void;
}> {
    readonly url: WebSocket["url"];
    readonly scores: Map<NDKUser, NDKRelayScore>;
    connectivity: NDKRelayConnectivity;
    subs: NDKRelaySubscriptionManager;
    private publisher;
    authPolicy?: NDKAuthPolicy;
    /**
     * The lowest validation ratio this relay can reach.
     */
    lowestValidationRatio?: number;
    /**
     * Current validation ratio this relay is targeting.
     */
    targetValidationRatio?: number;
    validationRatioFn?: (relay: NDKRelay, validatedCount: number, nonValidatedCount: number) => number;
    /**
     * This tracks events that have been seen by this relay
     * with a valid signature.
     */
    validatedEventCount: number;
    /**
     * This tracks events that have been seen by this relay
     * but have not been validated.
     */
    nonValidatedEventCount: number;
    /**
     * Whether this relay is trusted.
     *
     * Trusted relay's events do not get their signature verified.
     */
    trusted: boolean;
    complaining: boolean;
    readonly debug: debug$1.Debugger;
    static defaultValidationRatioUpdateFn: (relay: NDKRelay, validatedCount: number, _nonValidatedCount: number) => number;
    constructor(url: WebSocket["url"], authPolicy: NDKAuthPolicy | undefined, ndk: NDK);
    private updateValidationRatio;
    get status(): NDKRelayStatus;
    get connectionStats(): NDKRelayConnectionStats;
    /**
     * Connects to the relay.
     */
    connect(timeoutMs?: number, reconnect?: boolean): Promise<void>;
    /**
     * Disconnects from the relay.
     */
    disconnect(): void;
    /**
     * Queues or executes the subscription of a specific set of filters
     * within this relay.
     *
     * @param subscription NDKSubscription this filters belong to.
     * @param filters Filters to execute
     */
    subscribe(subscription: NDKSubscription, filters: NDKFilter[]): void;
    /**
     * Publishes an event to the relay with an optional timeout.
     *
     * If the relay is not connected, the event will be published when the relay connects,
     * unless the timeout is reached before the relay connects.
     *
     * @param event The event to publish
     * @param timeoutMs The timeout for the publish operation in milliseconds
     * @returns A promise that resolves when the event has been published or rejects if the operation times out
     */
    publish(event: NDKEvent, timeoutMs?: number): Promise<boolean>;
    referenceTags(): NDKTag[];
    addValidatedEvent(): void;
    addNonValidatedEvent(): void;
    /**
     * The current validation ratio this relay has achieved.
     */
    get validationRatio(): number;
    shouldValidateEvent(): boolean;
    get connected(): boolean;
    req: (relaySub: NDKRelaySubscription) => void;
    close: (subId: string) => void;
}

declare class NDKPublishError extends Error {
    errors: Map<NDKRelay, Error>;
    publishedToRelays: Set<NDKRelay>;
    /**
     * Intended relay set where the publishing was intended to happen.
     */
    intendedRelaySet?: NDKRelaySet;
    constructor(message: string, errors: Map<NDKRelay, Error>, publishedToRelays: Set<NDKRelay>, intendedRelaySet?: NDKRelaySet);
    get relayErrors(): string;
}
/**
 * A relay set is a group of relays. This grouping can be short-living, for a single
 * REQ or can be long-lasting, for example for the explicit relay list the user
 * has specified.
 *
 * Requests to relays should be sent through this interface.
 */
declare class NDKRelaySet {
    readonly relays: Set<NDKRelay>;
    private debug;
    private ndk;
    private pool;
    constructor(relays: Set<NDKRelay>, ndk: NDK, pool?: NDKPool);
    /**
     * Adds a relay to this set.
     */
    addRelay(relay: NDKRelay): void;
    get relayUrls(): WebSocket["url"][];
    /**
     * Creates a relay set from a list of relay URLs.
     *
     * If no connection to the relay is found in the pool it will temporarily
     * connect to it.
     *
     * @param relayUrls - list of relay URLs to include in this set
     * @param ndk
     * @param connect - whether to connect to the relay immediately if it was already in the pool but not connected
     * @returns NDKRelaySet
     */
    static fromRelayUrls(relayUrls: readonly string[], ndk: NDK, connect?: boolean, pool?: NDKPool): NDKRelaySet;
    /**
     * Publish an event to all relays in this relay set.
     *
     * This method implements a robust mechanism for publishing events to multiple relays with
     * built-in handling for race conditions, timeouts, and partial failures. The implementation
     * uses a dual-tracking mechanism to ensure accurate reporting of which relays successfully
     * received an event.
     *
     * Key aspects of this implementation:
     *
     * 1. DUAL-TRACKING MECHANISM:
     *    - Promise-based tracking: Records successes/failures from the promises returned by relay.publish()
     *    - Event-based tracking: Listens for 'relay:published' events that indicate successful publishing
     *    This approach ensures we don't miss successful publishes even if there are subsequent errors in
     *    the promise chain.
     *
     * 2. RACE CONDITION HANDLING:
     *    - If a relay emits a success event but later fails in the promise chain, we still count it as a success
     *    - If a relay times out after successfully publishing, we still count it as a success
     *    - All relay operations happen in parallel, with proper tracking regardless of completion order
     *
     * 3. TIMEOUT MANAGEMENT:
     *    - Individual timeouts for each relay operation
     *    - Proper cleanup of timeouts to prevent memory leaks
     *    - Clear timeout error reporting
     *
     * 4. ERROR HANDLING:
     *    - Detailed tracking of specific errors for each failed relay
     *    - Special handling for ephemeral events (which don't expect acknowledgement)
     *    - RequiredRelayCount parameter to control the minimum success threshold
     *
     * @param event Event to publish
     * @param timeoutMs Timeout in milliseconds for each relay publish operation
     * @param requiredRelayCount The minimum number of relays we expect the event to be published to
     * @returns A set of relays the event was published to
     * @throws {NDKPublishError} If the event could not be published to at least `requiredRelayCount` relays
     * @example
     * ```typescript
     * const relaySet = new NDKRelaySet(new Set([relay1, relay2]), ndk);
     * const publishedToRelays = await relaySet.publish(event);
     * // publishedToRelays can contain relay1, relay2, both, or none
     * // depending on which relays the event was successfully published to
     * if (publishedToRelays.size > 0) {
     *   console.log("Event published to at least one relay");
     * }
     * ```
     */
    publish(event: NDKEvent, timeoutMs?: number, requiredRelayCount?: number): Promise<Set<NDKRelay>>;
    get size(): number;
}

/**
 * Options on how to handle when a relay hint doesn't respond
 * with the requested event.
 *
 * When a tag includes a relay hint, and the relay hint doesn't come back
 * with the event, the fallback options are used to try to fetch the event
 * from somewhere else.
 */
type NDKFetchFallbackOptions = {
    /**
     * Relay set to use as a fallback when the hint relay doesn't respond.
     * If not provided, the normal NDK calculation is used (whether explicit relays or outbox calculation)
     * Default is `undefined`.
     */
    relaySet?: NDKRelaySet;
    /**
     * Type of fallback to use when the hint relay doesn't respond.
     * - "timeout" will wait for a timeout before falling back
     * - "eose" will wait for the EOSE before falling back
     * - "none" will not fall back
     * Default is "timeout".
     */
    type: "timeout" | "eose" | "none";
    /**
     * Timeout in milliseconds for the fallback relay.
     * Default is 1500ms.
     */
    timeout?: number;
};

type OutboxItemType = "user" | "kind";
/**
 * Tracks outbox scoring of an item. An item can be any of:
 *
 *  -  A user
 *  -  A tag
 */
declare class OutboxItem {
    /**
     * Type of item
     */
    type: OutboxItemType;
    /**
     * The relay URLs that are of interest to this item
     */
    relayUrlScores: Map<WebSocket["url"], number>;
    readRelays: Set<WebSocket["url"]>;
    writeRelays: Set<WebSocket["url"]>;
    constructor(type: OutboxItemType);
}
/**
 * The responsibility of this class is to track relay:outbox-item associations
 * so that we can intelligently choose which relays to query for which items.
 *
 * A single instance of this class should be shared across all subscriptions within
 * an NDK instance.
 *
 * TODO: The state of this tracker needs to be added to cache adapters so that we
 * can rehydrate-it when a cache is present.
 */
declare class OutboxTracker extends EventEmitter {
    data: LRUCache<Hexpubkey, OutboxItem>;
    private ndk;
    private debug;
    constructor(ndk: NDK);
    /**
     * Adds a list of users to the tracker.
     * @param items
     * @param skipCache
     */
    trackUsers(items: NDKUser[] | Hexpubkey[], skipCache?: boolean): Promise<void[]>;
    /**
     *
     * @param key
     * @param score
     */
    track(item: NDKUser | Hexpubkey, type?: OutboxItemType, _skipCache?: boolean): OutboxItem;
}

type QueueItem<T> = {
    /**
     * Deterministic id of the item
     */
    id: string;
    /**
     * A function to process the item
     * @returns
     */
    func: () => Promise<T>;
};
declare class Queue<T> {
    private queue;
    private maxConcurrency;
    private processing;
    private promises;
    constructor(_name: string, maxConcurrency: number);
    add(item: QueueItem<T>): Promise<T>;
    private process;
    clear(): void;
    clearProcessing(): void;
    clearAll(): void;
    length(): number;
}

type NDKValidationRatioFn = (relay: NDKRelay, validatedCount: number, nonValidatedCount: number) => number;
type NDKNetDebug = (msg: string, relay: NDKRelay, direction?: "send" | "recv") => void;
/**
 * An interface compatible with ndk-wallet that allows setting multiple handlers and callbacks.
 */
interface NDKWalletInterface {
    lnPay?: LnPayCb;
    cashuPay?: CashuPayCb;
    onPaymentComplete?: (results: Map<NDKZapSplit, NDKPaymentConfirmation | Error | undefined>) => void;
}
interface NDKConstructorParams {
    /**
     * Relays we should explicitly connect to
     */
    explicitRelayUrls?: string[];
    /**
     * Relays we should never connect to
     */
    blacklistRelayUrls?: string[];
    /**
     * When this is set, we always write only to this relays.
     */
    devWriteRelayUrls?: string[];
    /**
     * Outbox relay URLs.
     */
    outboxRelayUrls?: string[];
    /**
     * Enable outbox model (defaults to false)
     */
    enableOutboxModel?: boolean;
    /**
     * Auto-connect to main user's relays. The "main" user is determined
     * by the presence of a signer. Upon connection to the explicit relays,
     * the user's relays will be fetched and connected to if this is set to true.
     * @default true
     */
    autoConnectUserRelays?: boolean;
    /**
     * Automatically fetch user's mutelist
     * @default true
     */
    autoFetchUserMutelist?: boolean;
    /**
     * Signer to use for signing events by default
     */
    signer?: NDKSigner;
    /**
     * Cache adapter to use for caching events
     */
    cacheAdapter?: NDKCacheAdapter;
    /**
     * Debug instance to use
     */
    debug?: debug$1.Debugger;
    /**
     * Provide a caller function to receive all networking traffic from relays
     */
    netDebug?: NDKNetDebug;
    /**
     * Muted pubkeys and eventIds
     */
    mutedIds?: Map<Hexpubkey | NDKEventId, string>;
    /**
     * Client name to add to events' tag
     */
    clientName?: string;
    /**
     * Client nip89 to add to events' tag
     */
    clientNip89?: string;
    /**
     * Default relay-auth policy
     */
    relayAuthDefaultPolicy?: NDKAuthPolicy;
    /**
     * Set a Web Worker for signature verification.
     *
     * @default undefined
     *
     * When provided, signature verification will be processed in a web worker.
     * You should listen for the `event:invalid-sig` event to handle invalid signatures.
     *
     * @example
     * ```typescript
     * const worker = new Worker("path/to/signature-verification.js");
     * ndk.signatureVerificationWorker = worker;
     * ndk.on("event:invalid-sig", (event) => {
     *    console.error("Invalid signature", event);
     * });
     * ```
     */
    signatureVerificationWorker?: Worker | undefined;
    /**
     * The signature verification validation ratio for new relays.
     */
    initialValidationRatio?: number;
    /**
     * The lowest validation ratio any single relay can have.
     * Relays will have a sample of events verified based on this ratio.
     * When using this, you MUST listen for event:invalid-sig events
     * to handle invalid signatures and disconnect from evil relays.
     *
     * @default 0.1
     */
    lowestValidationRatio?: number;
    /**
     * A function that is invoked to calculate the validation ratio for a relay.
     */
    validationRatioFn?: NDKValidationRatioFn;
    /**
     * A custom function to verify event signatures.
     * When provided, this function will be used instead of the default verification logic.
     * This is particularly useful for platforms like React Native where Web Workers are not available.
     *
     * @example
     * ```typescript
     * import { verifySignatureAsync } from "@nostr-dev-kit/ndk-mobile";
     *
     * const ndk = new NDK({
     *   signatureVerificationFunction: verifySignatureAsync
     * });
     * ```
     */
    signatureVerificationFunction?: (event: NDKEvent) => Promise<boolean>;
    /**
     * Whether to automatically blacklist relays that provide invalid signatures.
     *
     * @default true
     */
    autoBlacklistInvalidRelays?: boolean;
}
interface GetUserParams extends NDKUserParams {
    npub?: string;
    pubkey?: string;
    /**
     * @deprecated Use `pubkey` instead
     */
    hexpubkey?: string;
}
/**
 * Defines handlers that can be passed to `ndk.subscribe` via the `autoStart` parameter
 * to react to subscription lifecycle events.
 */
interface NDKSubscriptionEventHandlers {
    /**
     * Called for each individual event received from relays *after* the initial cache load (if `onEvents` is provided),
     * or for *all* events (including cached ones) if `onEvents` is not provided.
     * @param event The received NDKEvent.
     * @param relay The relay the event was received from (undefined if from cache).
     */
    onEvent?: (event: NDKEvent, relay?: NDKRelay) => void;
    /**
     * Called *once* with an array of all events found synchronously in the cache when the subscription starts.
     * If this handler is provided, `onEvent` will *not* be called for this initial batch of cached events.
     * This is useful for bulk processing or batching UI updates based on the initial cached state.
     * @param events An array of NDKEvents loaded synchronously from the cache.
     */
    onEvents?: (events: NDKEvent[]) => void;
    /**
     * Called when the subscription receives an EOSE (End of Stored Events) marker
     * from all connected relays involved in this subscription request.
     * @param sub The NDKSubscription instance that reached EOSE.
     */
    onEose?: (sub: NDKSubscription) => void;
}
/**
 * The NDK class is the main entry point to the library.
 *
 * @emits signer:ready when a signer is ready
 * @emits invalid-signature when an event with an invalid signature is received
 */
declare class NDK extends EventEmitter<{
    "signer:ready": (signer: NDKSigner) => void;
    "signer:required": () => void;
    /**
     * Emitted when an event with an invalid signature is received.
     * Includes the relay that provided the invalid signature.
     */
    "event:invalid-sig": (event: NDKEvent, relay?: NDKRelay) => void;
    /**
     * Emitted when an event fails to publish.
     * @param event The event that failed to publish
     * @param error The error that caused the event to fail to publish
     * @param relays The relays that the event was attempted to be published to
     */
    "event:publish-failed": (event: NDKEvent, error: NDKPublishError, relays: WebSocket["url"][]) => void;
}> {
    private _explicitRelayUrls?;
    blacklistRelayUrls?: WebSocket["url"][];
    pool: NDKPool;
    outboxPool?: NDKPool;
    private _signer?;
    private _activeUser?;
    cacheAdapter?: NDKCacheAdapter;
    debug: debug$1.Debugger;
    devWriteRelaySet?: NDKRelaySet;
    outboxTracker?: OutboxTracker;
    mutedIds: Map<Hexpubkey | NDKEventId, string>;
    clientName?: string;
    clientNip89?: string;
    queuesZapConfig: Queue<NDKLnUrlData | undefined>;
    queuesNip05: Queue<ProfilePointer | null>;
    asyncSigVerification: boolean;
    initialValidationRatio: number;
    lowestValidationRatio: number;
    validationRatioFn?: NDKValidationRatioFn;
    autoBlacklistInvalidRelays: boolean;
    subManager: NDKSubscriptionManager;
    /**
     * Private storage for the signature verification function
     */
    private _signatureVerificationFunction?;
    /**
     * Private storage for the signature verification worker
     */
    private _signatureVerificationWorker?;
    /**
     * Rolling total of time spent (in ms) performing signature verifications.
     * Users can read this to monitor or display aggregate verification cost.
     */
    signatureVerificationTimeMs: number;
    publishingFailureHandled: boolean;
    pools: NDKPool[];
    /**
     * Default relay-auth policy that will be used when a relay requests authentication,
     * if no other policy is specified for that relay.
     *
     * @example Disconnect from relays that request authentication:
     * ```typescript
     * ndk.relayAuthDefaultPolicy = NDKAuthPolicies.disconnect(ndk.pool);
     * ```
     *
     * @example Sign in to relays that request authentication:
     * ```typescript
     * ndk.relayAuthDefaultPolicy = NDKAuthPolicies.signIn({ndk})
     * ```
     *
     * @example Sign in to relays that request authentication, asking the user for confirmation:
     * ```typescript
     * ndk.relayAuthDefaultPolicy = (relay: NDKRelay) => {
     *     const signIn = NDKAuthPolicies.signIn({ndk});
     *     if (confirm(`Relay ${relay.url} is requesting authentication, do you want to sign in?`)) {
     *        signIn(relay);
     *     }
     * }
     * ```
     */
    relayAuthDefaultPolicy?: NDKAuthPolicy;
    /**
     * Fetch function to use for HTTP requests.
     *
     * @example
     * ```typescript
     * import fetch from "node-fetch";
     *
     * ndk.httpFetch = fetch;
     * ```
     */
    httpFetch: typeof fetch | undefined;
    /**
     * Provide a caller function to receive all networking traffic from relays
     */
    readonly netDebug?: NDKNetDebug;
    autoConnectUserRelays: boolean;
    autoFetchUserMutelist: boolean;
    walletConfig?: NDKWalletInterface;
    constructor(opts?: NDKConstructorParams);
    set explicitRelayUrls(urls: WebSocket["url"][]);
    get explicitRelayUrls(): WebSocket["url"][];
    /**
     * Set a Web Worker for signature verification.
     *
     * This method initializes the worker and sets the asyncSigVerification flag.
     * The actual verification is handled by the verifySignatureAsync function in signature.ts,
     * which will use the worker if available.
     */
    set signatureVerificationWorker(worker: Worker | undefined);
    /**
     * Set a custom signature verification function.
     *
     * This method is particularly useful for platforms that don't support Web Workers,
     * such as React Native.
     *
     * When a function is provided, it will be used for signature verification
     * instead of the default worker-based verification. This enables signature
     * verification on platforms where Web Workers are not available.
     *
     * @example
     * ```typescript
     * import { verifySignatureAsync } from "@nostr-dev-kit/ndk-mobile";
     *
     * ndk.signatureVerificationFunction = verifySignatureAsync;
     * ```
     */
    set signatureVerificationFunction(fn: ((event: NDKEvent) => Promise<boolean>) | undefined);
    /**
     * Get the custom signature verification function
     */
    get signatureVerificationFunction(): ((event: NDKEvent) => Promise<boolean>) | undefined;
    /**
     * Adds an explicit relay to the pool.
     * @param url
     * @param relayAuthPolicy Authentication policy to use if different from the default
     * @param connect Whether to connect to the relay automatically
     * @returns
     */
    addExplicitRelay(urlOrRelay: string | NDKRelay, relayAuthPolicy?: NDKAuthPolicy, connect?: boolean): NDKRelay;
    toJSON(): string;
    get activeUser(): NDKUser | undefined;
    /**
     * Sets the active user for this NDK instance, typically this will be
     * called when assigning a signer to the NDK instance.
     *
     * This function will automatically connect to the user's relays if
     * `autoConnectUserRelays` is set to true.
     *
     * It will also fetch the user's mutelist if `autoFetchUserMutelist` is set to true.
     */
    set activeUser(user: NDKUser | undefined);
    get signer(): NDKSigner | undefined;
    set signer(newSigner: NDKSigner | undefined);
    /**
     * Connect to relays with optional timeout.
     * If the timeout is reached, the connection will be continued to be established in the background.
     */
    connect(timeoutMs?: number): Promise<void>;
    /**
     * Centralized method to report an invalid signature, identifying the relay that provided it.
     * A single invalid signature means the relay is considered malicious.
     * All invalid signature detections (synchronous or asynchronous) should delegate to this method.
     *
     * @param event The event with an invalid signature
     * @param relay The relay that provided the invalid signature
     */
    reportInvalidSignature(event: NDKEvent, relay?: NDKRelay): void;
    /**
     * Add a relay URL to the blacklist as it has been identified as malicious
     */
    blacklistRelay(url: string): void;
    /**
     * Default function to calculate validation ratio based on historical validation results.
     * The more events validated successfully, the lower the ratio goes (down to the minimum).
     */
    private defaultValidationRatioFn;
    /**
     * Get a NDKUser object
     *
     * @param opts
     * @returns
     */
    getUser(opts: GetUserParams): NDKUser;
    /**
     * Get a NDKUser from a NIP05
     * @param nip05 NIP-05 ID
     * @param skipCache Skip cache
     * @returns
     */
    getUserFromNip05(nip05: string, skipCache?: boolean): Promise<NDKUser | undefined>;
    /**
     * Creates and starts a new subscription.
     *
     * Subscriptions automatically start unless `autoStart` is set to `false`.
     * You can control automatic closing on EOSE via `opts.closeOnEose`.
     *
     * @param filters - A single NDKFilter object or an array of filters.
     * @param opts - Optional NDKSubscriptionOptions to customize behavior (e.g., caching, grouping).
     * @param handlers - Optional handlers for subscription events. Passing handlers is the preferred method of using ndk.subscribe.
     *   - `onEvent`: Called for each event received.
     *  - `onEvents`: Called once with an array of events when the subscription starts (from the cache).
     *  - `onEose`: Called when the subscription receives EOSE.
     *  For backwards compatibility, this third parameter also accepts a relaySet, the relaySet should be passed via `opts.relaySet`.
     *
     * @param _autoStart - For backwards compatibility, this can be a boolean indicating whether to start the subscription immediately.
     *  This parameter is deprecated and will be removed in a future version.
     *   - `false`: Creates the subscription but does not start it (call `subscription.start()` manually).
     * @returns The created NDKSubscription instance.
     *
     * @example Basic subscription
     * ```typescript
     * const sub = ndk.subscribe({ kinds: [1], authors: [pubkey] });
     * sub.on("event", (event) => console.log("Kind 1 event:", event.content));
     * ```
     *
     * @example Subscription with options and direct handlers
     * ```typescript
     * const sub = ndk.subscribe(
     *   { kinds: [0], authors: [pubkey] },
     *   { closeOnEose: true, cacheUsage: NDKSubscriptionCacheUsage.PARALLEL },
     *   undefined, // Use default relay set calculation
     *   {
     *     onEvents: (events) => { // Renamed parameter
     *       if (events.length > 0) {
     *         console.log(`Got ${events.length} profile events from cache:`, events[0].content);
     *       }
     *     },
     *     onEvent: (event) => { // Renamed parameter
     *       console.log("Got profile update from relay:", event.content); // Clarified source
     *     },
     *     onEose: () => console.log("Profile subscription finished.")
     *   }
     * );
     * ```
     *
     * @since 2.13.0 `relaySet` parameter removed; pass `relaySet` or `relayUrls` via `opts`.
     */
    subscribe(filters: NDKFilter | NDKFilter[], opts?: NDKSubscriptionOptions, autoStartOrRelaySet?: NDKRelaySet | boolean | NDKSubscriptionEventHandlers, _autoStart?: boolean): NDKSubscription;
    /**
     * Attempts to fetch an event from a tag, following relay hints and
     * other best practices.
     * @param tag Tag to fetch the event from
     * @param originalEvent Event where the tag came from
     * @param subOpts Subscription options to use when fetching the event
     * @param fallback Fallback options to use when the hint relay doesn't respond
     * @returns
     */
    fetchEventFromTag: (tag: NDKTag, originalEvent: NDKEvent, subOpts?: NDKSubscriptionOptions | undefined, fallback?: NDKFetchFallbackOptions | undefined) => Promise<NDKEvent | null>;
    /**
     * Fetch an event from the cache synchronously.
     * @param idOrFilter event id in bech32 format or filter
     * @returns events from the cache or null if the cache is empty
     */
    fetchEventSync(idOrFilter: string | NDKFilter[]): NDKEvent[] | null;
    /**
     * Fetch a single event.
     *
     * @param idOrFilter event id in bech32 format or filter
     * @param opts subscription options
     * @param relaySetOrRelay explicit relay set to use
     */
    fetchEvent(idOrFilter: string | NDKFilter | NDKFilter[], opts?: NDKSubscriptionOptions, relaySetOrRelay?: NDKRelaySet | NDKRelay): Promise<NDKEvent | null>;
    /**
     * Fetch events
     */
    fetchEvents(filters: NDKFilter | NDKFilter[], opts?: NDKSubscriptionOptions, relaySet?: NDKRelaySet): Promise<Set<NDKEvent>>;
    /**
     * Ensures that a signer is available to sign an event.
     */
    assertSigner(): void;
    getEntity: (entity: string) => NDKUser | {
        type: "nrelay";
        data: string;
    } | {
        type: "nevent";
        data: nostr_tools_lib_types_nip19_js.EventPointer;
    } | {
        type: "naddr";
        data: nostr_tools_lib_types_nip19_js.AddressPointer;
    } | {
        type: "nsec";
        data: Uint8Array<ArrayBufferLike>;
    } | {
        type: "note";
        data: string;
    } | null;
    set wallet(wallet: NDKWalletInterface | undefined);
}

type NDKSubscriptionInternalId = string;
type NDKSubscriptionDelayedType = "at-least" | "at-most";
type NDKFilter<K extends number = NDKKind> = {
    ids?: string[];
    kinds?: K[];
    authors?: string[];
    since?: number;
    until?: number;
    limit?: number;
    search?: string;
    [key: `#${string}`]: string[] | undefined;
};
declare enum NDKSubscriptionCacheUsage {
    ONLY_CACHE = "ONLY_CACHE",
    CACHE_FIRST = "CACHE_FIRST",
    PARALLEL = "PARALLEL",
    ONLY_RELAY = "ONLY_RELAY"
}
interface NDKSubscriptionOptions {
    /**
     * Whether to close the subscription when all relays have reached the end of the event stream.
     * @default false
     */
    closeOnEose?: boolean;
    cacheUsage?: NDKSubscriptionCacheUsage;
    /**
     * Whether to skip caching events coming from this subscription
     **/
    dontSaveToCache?: boolean;
    /**
     * Groupable subscriptions are created with a slight time
     * delayed to allow similar filters to be grouped together.
     */
    groupable?: boolean;
    /**
     * The delay to use when grouping subscriptions, specified in milliseconds.
     * @default 100
     * @example
     * const sub1 = ndk.subscribe({ kinds: [1], authors: ["alice"] }, { groupableDelay: 100 });
     * const sub2 = ndk.subscribe({ kinds: [0], authors: ["alice"] }, { groupableDelay: 1000 });
     * // sub1 and sub2 will be grouped together and executed 100ms after sub1 was created
     */
    groupableDelay?: number;
    /**
     * Specifies how this delay should be interpreted.
     * "at-least" means "wait at least this long before sending the subscription"
     * "at-most" means "wait at most this long before sending the subscription"
     * @default "at-most"
     * @example
     * const sub1 = ndk.subscribe({ kinds: [1], authors: ["alice"] }, { groupableDelay: 100, groupableDelayType: "at-least" }); // 3 args
     * const sub2 = ndk.subscribe({ kinds: [0], authors: ["alice"] }, { groupableDelay: 1000, groupableDelayType: "at-most" }); // 3 args
     * // sub1 and sub2 will be grouped together and executed 1000ms after sub1 was created
     */
    groupableDelayType?: NDKSubscriptionDelayedType;
    /**
     * The subscription ID to use for the subscription.
     */
    subId?: string;
    /**
     * Pool to use
     */
    pool?: NDKPool;
    /**
     * Skip signature verification
     * @default false
     */
    skipVerification?: boolean;
    /**
     * Skip event validation. Event validation, checks whether received
     * kinds conform to what the expected schema of that kind should look like.rtwle
     * @default false
     */
    skipValidation?: boolean;
    /**
     * Skip emitting on events before they are received from a relay. (skip optimistic publish)
     * @default false
     */
    skipOptimisticPublishEvent?: boolean;
    /**
     * Remove filter constraints when querying the cache.
     *
     * This allows setting more aggressive filters that will be removed when hitting the cache.
     *
     * Useful uses of this include removing `since` or `until` constraints or `limit` filters.
     *
     * @example
     * ndk.subscribe({ kinds: [1], since: 1710000000, limit: 10 }, { cacheUnconstrainFilter: ['since', 'limit'] }); // 3 args
     *
     * This will hit relays with the since and limit constraints, while loading from the cache without them.
     */
    cacheUnconstrainFilter?: (keyof NDKFilter)[];
    /**
     * Whether to wrap events in kind-specific classes when possible.
     * @default false
     */
    wrap?: boolean;
    /**
     * Explicit relay set to use for this subscription instead of calculating it.
     * If `relayUrls` is also provided in the options, this `relaySet` takes precedence.
     * @since 2.13.0 Moved from `ndk.subscribe` parameter to options.
     */
    relaySet?: NDKRelaySet;
    /**
     * Explicit relay URLs to use for this subscription instead of calculating the relay set.
     * An `NDKRelaySet` will be created internally from these URLs.
     * If `relaySet` is also provided in the options, the explicit `relaySet` takes precedence over these URLs.
     * @since 2.13.0
     */
    relayUrls?: string[];
    /**
     * When set, the cache will be queried first, and, when hitting relays,
     * a `since` filter will be added to the subscription that is one second
     * after the last event received from the cache.
     *
     * This option implies cacheUsage: CACHE_FIRST.
     */
    addSinceFromCache?: boolean;
}
/**
 * Represents a subscription to an NDK event stream.
 *
 * @emits event
 * Emitted when an event is received by the subscription.
 * * ({NDKEvent} event - The event received by the subscription,
 * * {NDKRelay} relay - The relay that received the event,
 * * {NDKSubscription} subscription - The subscription that received the event.)
 *
 * @emits event:dup
 * Emitted when a duplicate event is received by the subscription.
 * * {NDKEvent} event - The duplicate event received by the subscription.
 * * {NDKRelay} relay - The relay that received the event.
 * * {number} timeSinceFirstSeen - The time elapsed since the first time the event was seen.
 * * {NDKSubscription} subscription - The subscription that received the event.
 *
 * @emits cacheEose - Emitted when the cache adapter has reached the end of the events it had.
 *
 * @emits eose - Emitted when all relays have reached the end of the event stream.
 * * {NDKSubscription} subscription - The subscription that received EOSE.
 *
 * @emits close - Emitted when the subscription is closed.
 * * {NDKSubscription} subscription - The subscription that was closed.
 *
 * @example
 * const sub = ndk.subscribe({ kinds: [1] }); // Get all kind:1s
 * sub.on("event", (event) => console.log(event.content); // Show the content
 * sub.on("eose", () => console.log("All relays have reached the end of the event stream"));
 * sub.on("close", () => console.log("Subscription closed"));
 * setTimeout(() => sub.stop(), 10000); // Stop the subscription after 10 seconds
 *
 * @description
 * Subscriptions are created using {@link NDK.subscribe}.
 *
 * # Event validation
 * By defaults, subscriptions will validate events to comply with the minimal requirement
 * of each known NIP.
 * This can be disabled by setting the `skipValidation` option to `true`.
 *
 * @example
 * const sub = ndk.subscribe({ kinds: [1] }, { skipValidation: false });
 * sub.on("event", (event) => console.log(event.content); // Only valid events will be received
 */
declare class NDKSubscription extends EventEmitter<{
    cacheEose: () => void;
    eose: (sub: NDKSubscription) => void;
    close: (sub: NDKSubscription) => void;
    /**
     * Emitted when a duplicate event is received by the subscription.
     * @param event - The duplicate event received by the subscription.
     * @param relay - The relay that received the event.
     * @param timeSinceFirstSeen - The time elapsed since the first time the event was seen.
     * @param sub - The subscription that received the event.
     */
    "event:dup": (event: NDKEvent | NostrEvent, relay: NDKRelay | undefined, timeSinceFirstSeen: number, sub: NDKSubscription, fromCache: boolean, optimisticPublish: boolean) => void;
    /**
     * Emitted when an event is received by the subscription.
     * @param event - The event received by the subscription.
     * @param relay - The relay that received the event.
     * @param sub - The subscription that received the event.
     * @param fromCache - Whether the event was received from the cache.
     * @param optimisticPublish - Whether the event was received from an optimistic publish.
     */
    event: (event: NDKSignedEvent, relay: NDKRelay | undefined, sub: NDKSubscription, fromCache: boolean, optimisticPublish: boolean) => void;
    /**
     * Emitted when a relay unilaterally closes the subscription.
     * @param relay
     * @param reason
     * @returns
     */
    closed: (relay: NDKRelay, reason: string) => void;
}> {
    readonly subId?: string;
    readonly filters: NDKFilter[];
    readonly opts: NDKSubscriptionOptions;
    readonly pool: NDKPool;
    readonly skipVerification: boolean;
    readonly skipValidation: boolean;
    /**
     * Tracks the filters as they are executed on each relay
     */
    relayFilters?: Map<WebSocket["url"], NDKFilter[]>;
    relaySet?: NDKRelaySet;
    ndk: NDK;
    debug: debug.Debugger;
    /**
     * Events that have been seen by the subscription, with the time they were first seen.
     */
    eventFirstSeen: Map<string, number>;
    /**
     * Relays that have sent an EOSE.
     */
    eosesSeen: Set<NDKRelay>;
    /**
     * The time the last event was received by the subscription.
     * This is used to calculate when EOSE should be emitted.
     */
    private lastEventReceivedAt;
    /**
     * The most recent event timestamp from cache results.
     * This is used for addSinceFromCache functionality.
     */
    private mostRecentCacheEventTimestamp?;
    internalId: NDKSubscriptionInternalId;
    /**
     * Whether the subscription should close when all relays have reached the end of the event stream.
     */
    closeOnEose: boolean;
    /**
     * Pool monitor callback
     */
    private poolMonitor;
    skipOptimisticPublishEvent: boolean;
    /**
     * Filters to remove when querying the cache.
     */
    cacheUnconstrainFilter?: Array<keyof NDKFilter>;
    constructor(ndk: NDK, filters: NDKFilter | NDKFilter[], opts?: NDKSubscriptionOptions, subId?: string);
    /**
     * Returns the relays that have not yet sent an EOSE.
     */
    relaysMissingEose(): WebSocket["url"][];
    /**
     * Provides access to the first filter of the subscription for
     * backwards compatibility.
     */
    get filter(): NDKFilter;
    get groupableDelay(): number | undefined;
    get groupableDelayType(): NDKSubscriptionDelayedType;
    isGroupable(): boolean;
    private shouldQueryCache;
    private shouldQueryRelays;
    private shouldWaitForCache;
    /**
     * Start the subscription. This is the main method that should be called
     * after creating a subscription.
     *
     * @param emitCachedEvents - Whether to emit events coming from a synchronous cache
     *
     * When using a synchronous cache, the events will be returned immediately
     * by this function. If you will use those returned events, you should
     * set emitCachedEvents to false to prevent seeing them as duplicate events.
     */
    start(emitCachedEvents?: boolean): NDKEvent[] | null;
    /**
     * We want to monitor for new relays that are coming online, in case
     * they should be part of this subscription.
     */
    private startPoolMonitor;
    onStopped?: () => void;
    stop(): void;
    /**
     * @returns Whether the subscription has an authors filter.
     */
    hasAuthorsFilter(): boolean;
    private startWithCache;
    /**
     * Find available relays that should be part of this subscription and execute in them.
     *
     * Note that this is executed in addition to using the pool monitor, so even if the relay set
     * that is computed (i.e. we don't have any relays available), when relays come online, we will
     * check if we need to execute in them.
     */
    private startWithRelays;
    /**
     * Called when an event is received from a relay or the cache
     * @param event
     * @param relay
     * @param fromCache Whether the event was received from the cache
     * @param optimisticPublish Whether this event is coming from an optimistic publish
     */
    eventReceived(event: NDKEvent | NostrEvent, relay: NDKRelay | undefined, fromCache?: boolean, optimisticPublish?: boolean): void;
    /**
     * Optionally wraps, sync or async, and emits the event (if one comes back from the wrapper)
     */
    private emitEvent;
    closedReceived(relay: NDKRelay, reason: string): void;
    private eoseTimeout;
    private eosed;
    eoseReceived(relay: NDKRelay): void;
}

/**
 * NIP-73 entity types
 */
type NIP73EntityType = "url" | "hashtag" | "geohash" | "isbn" | "podcast:guid" | "podcast:item:guid" | "podcast:publisher:guid" | "isan" | "doi";

type NDKEventId = string;
type NDKTag = string[];
type NostrEvent = {
    created_at: number;
    content: string;
    tags: NDKTag[];
    kind?: NDKKind | number;
    pubkey: string;
    id?: string;
    sig?: string;
};
/**
 * A finalized event
 */
type NDKRawEvent = {
    created_at: number;
    content: string;
    tags: NDKTag[];
    kind: NDKKind | number;
    pubkey: string;
    id: string;
    sig: string;
};
/**
 * NDKEvent is the basic building block of NDK; most things
 * you do with NDK will revolve around writing or consuming NDKEvents.
 */
declare class NDKEvent extends EventEmitter {
    ndk?: NDK;
    created_at?: number;
    content: string;
    tags: NDKTag[];
    kind: NDKKind | number;
    id: string;
    sig?: string;
    pubkey: string;
    signatureVerified?: boolean;
    private _author;
    /**
     * The relay that this event was first received from.
     */
    relay: NDKRelay | undefined;
    /**
     * The relays that this event was received from and/or successfully published to.
     */
    get onRelays(): NDKRelay[];
    /**
     * The status of the publish operation.
     */
    publishStatus?: "pending" | "success" | "error";
    publishError?: Error;
    constructor(ndk?: NDK, event?: Partial<NDKRawEvent> | NDKEvent);
    /**
     * Deserialize an NDKEvent from a serialized payload.
     * @param ndk
     * @param event
     * @returns
     */
    static deserialize(ndk: NDK | undefined, event: NDKEventSerialized): NDKEvent;
    /**
     * Returns the event as is.
     */
    rawEvent(): NDKRawEvent;
    set author(user: NDKUser);
    /**
     * Returns an NDKUser for the author of the event.
     */
    get author(): NDKUser;
    /**
     * NIP-73 tagging of external entities
     * @param entity to be tagged
     * @param type of the entity
     * @param markerUrl to be used as the marker URL
     *
     * @example
     * ```typescript
     * event.tagExternal("https://example.com/article/123#nostr", "url");
     * event.tags => [["i", "https://example.com/123"], ["k", "https://example.com"]]
     * ```
     *
     * @example tag a podcast:item:guid
     * ```typescript
     * event.tagExternal("e32b4890-b9ea-4aef-a0bf-54b787833dc5", "podcast:item:guid");
     * event.tags => [["i", "podcast:item:guid:e32b4890-b9ea-4aef-a0bf-54b787833dc5"], ["k", "podcast:item:guid"]]
     * ```
     *
     * @see https://github.com/nostr-protocol/nips/blob/master/73.md
     */
    tagExternal(entity: string, type: NIP73EntityType, markerUrl?: string): void;
    /**
     * Tag a user with an optional marker.
     * @param target What is to be tagged. Can be an NDKUser, NDKEvent, or an NDKTag.
     * @param marker The marker to use in the tag.
     * @param skipAuthorTag Whether to explicitly skip adding the author tag of the event.
     * @param forceTag Force a specific tag to be used instead of the default "e" or "a" tag.
     * @example
     * ```typescript
     * reply.tag(opEvent, "reply");
     * // reply.tags => [["e", <id>, <relay>, "reply"]]
     * ```
     */
    tag(target: NDKTag | NDKUser | NDKEvent, marker?: string, skipAuthorTag?: boolean, forceTag?: string): void;
    /**
     * Return a NostrEvent object, trying to fill in missing fields
     * when possible, adding tags when necessary.
     * @param pubkey {string} The pubkey of the user who the event belongs to.
     * @returns {Promise<NostrEvent>} A promise that resolves to a NostrEvent.
     */
    toNostrEvent(pubkey?: string): Promise<NostrEvent>;
    serialize: (includeSig?: boolean | undefined, includeId?: boolean | undefined) => string;
    getEventHash: () => string;
    validate: () => boolean;
    verifySignature: (persist: boolean) => boolean | undefined;
    /**
     * Is this event replaceable (whether parameterized or not)?
     *
     * This will return true for kind 0, 3, 10k-20k and 30k-40k
     */
    isReplaceable: () => boolean;
    isEphemeral: () => boolean;
    isDvm: () => boolean | 0;
    /**
     * Is this event parameterized replaceable?
     *
     * This will return true for kind 30k-40k
     */
    isParamReplaceable: () => boolean;
    /**
     * Encodes a bech32 id.
     *
     * @param relays {string[]} The relays to encode in the id
     * @returns {string} - Encoded naddr, note or nevent.
     */
    encode: (maxRelayCount?: number | undefined) => string;
    encrypt: (recipient?: NDKUser | undefined, signer?: NDKSigner | undefined, scheme?: NDKEncryptionScheme | undefined) => Promise<void>;
    decrypt: (sender?: NDKUser | undefined, signer?: NDKSigner | undefined, scheme?: NDKEncryptionScheme | undefined) => Promise<void>;
    /**
     * Get all tags with the given name
     * @param tagName {string} The name of the tag to search for
     * @returns {NDKTag[]} An array of the matching tags
     */
    getMatchingTags(tagName: string, marker?: string): NDKTag[];
    /**
     * Check if the event has a tag with the given name
     * @param tagName
     * @param marker
     * @returns
     */
    hasTag(tagName: string, marker?: string): boolean;
    /**
     * Get the first tag with the given name
     * @param tagName Tag name to search for
     * @returns The value of the first tag with the given name, or undefined if no such tag exists
     */
    tagValue(tagName: string, marker?: string): string | undefined;
    /**
     * Gets the NIP-31 "alt" tag of the event.
     */
    get alt(): string | undefined;
    /**
     * Sets the NIP-31 "alt" tag of the event. Use this to set an alt tag so
     * clients that don't handle a particular event kind can display something
     * useful for users.
     */
    set alt(alt: string | undefined);
    /**
     * Gets the NIP-33 "d" tag of the event.
     */
    get dTag(): string | undefined;
    /**
     * Sets the NIP-33 "d" tag of the event.
     */
    set dTag(value: string | undefined);
    /**
     * Remove all tags with the given name (e.g. "d", "a", "p")
     * @param tagName Tag name(s) to search for and remove
     * @param marker Optional marker to check for too
     *
     * @example
     * Remove a tags with a "defer" marker
     * ```typescript
     * event.tags = [
     *   ["a", "....", "defer"],
     *   ["a", "....", "no-defer"],
     * ]
     *
     * event.removeTag("a", "defer");
     *
     * // event.tags => [["a", "....", "no-defer"]]
     *
     * @returns {void}
     */
    removeTag(tagName: string | string[], marker?: string): void;
    /**
     * Replace a tag with a new value. If not found, it will be added.
     * @param tag The tag to replace.
     * @param value The new value for the tag.
     */
    replaceTag(tag: NDKTag): void;
    /**
     * Sign the event if a signer is present.
     *
     * It will generate tags.
     * Repleacable events will have their created_at field set to the current time.
     * @param signer {NDKSigner} The NDKSigner to use to sign the event
     * @returns {Promise<string>} A Promise that resolves to the signature of the signed event.
     */
    sign(signer?: NDKSigner): Promise<string>;
    /**
     *
     * @param relaySet
     * @param timeoutMs
     * @param requiredRelayCount
     * @returns
     */
    publishReplaceable(relaySet?: NDKRelaySet, timeoutMs?: number, requiredRelayCount?: number): Promise<Set<NDKRelay>>;
    /**
     * Attempt to sign and then publish an NDKEvent to a given relaySet.
     * If no relaySet is provided, the relaySet will be calculated by NDK.
     * @param relaySet {NDKRelaySet} The relaySet to publish the even to.
     * @param timeoutM {number} The timeout for the publish operation in milliseconds.
     * @param requiredRelayCount The number of relays that must receive the event for the publish to be considered successful.
     * @returns A promise that resolves to the relays the event was published to.
     */
    publish(relaySet?: NDKRelaySet, timeoutMs?: number, requiredRelayCount?: number): Promise<Set<NDKRelay>>;
    /**
     * Generates tags for users, notes, and other events tagged in content.
     * Will also generate random "d" tag for parameterized replaceable events where needed.
     * @returns {ContentTag} The tags and content of the event.
     */
    generateTags(): Promise<ContentTag>;
    get shouldAddClientTag(): boolean;
    get shouldStripClientTag(): boolean;
    muted(): string | null;
    /**
     * Returns the "d" tag of a parameterized replaceable event or throws an error if the event isn't
     * a parameterized replaceable event.
     * @returns {string} the "d" tag of the event.
     *
     * @deprecated Use `dTag` instead.
     */
    replaceableDTag(): string;
    /**
     * Provides a deduplication key for the event.
     *
     * For kinds 0, 3, 10k-20k this will be the event <kind>:<pubkey>
     * For kinds 30k-40k this will be the event <kind>:<pubkey>:<d-tag>
     * For all other kinds this will be the event id
     */
    deduplicationKey(): string;
    /**
     * Returns the id of the event or, if it's a parameterized event, the generated id of the event using "d" tag, pubkey, and kind.
     * @returns {string} The id
     */
    tagId(): string;
    /**
     * Returns a stable reference value for a replaceable event.
     *
     * Param replaceable events are returned in the expected format of `<kind>:<pubkey>:<d-tag>`.
     * Kind-replaceable events are returned in the format of `<kind>:<pubkey>:`.
     *
     * @returns {string} A stable reference value for replaceable events
     */
    tagAddress(): string;
    /**
     * Determines the type of tag that can be used to reference this event from another event.
     * @returns {string} The tag type
     * @example
     * event = new NDKEvent(ndk, { kind: 30000, pubkey: 'pubkey', tags: [ ["d", "d-code"] ] });
     * event.tagType(); // "a"
     */
    tagType(): "e" | "a";
    /**
     * Get the tag that can be used to reference this event from another event.
     *
     * Consider using referenceTags() instead (unless you have a good reason to use this)
     *
     * @example
     *     event = new NDKEvent(ndk, { kind: 30000, pubkey: 'pubkey', tags: [ ["d", "d-code"] ] });
     *     event.tagReference(); // ["a", "30000:pubkey:d-code"]
     *
     *     event = new NDKEvent(ndk, { kind: 1, pubkey: 'pubkey', id: "eventid" });
     *     event.tagReference(); // ["e", "eventid"]
     * @returns {NDKTag} The NDKTag object referencing this event
     */
    tagReference(marker?: string): NDKTag;
    /**
     * Get the tags that can be used to reference this event from another event
     * @param marker The marker to use in the tag
     * @param skipAuthorTag Whether to explicitly skip adding the author tag of the event
     * @param forceTag Force a specific tag to be used instead of the default "e" or "a" tag
     * @example
     *     event = new NDKEvent(ndk, { kind: 30000, pubkey: 'pubkey', tags: [ ["d", "d-code"] ] });
     *     event.referenceTags(); // [["a", "30000:pubkey:d-code"], ["e", "parent-id"]]
     *
     *     event = new NDKEvent(ndk, { kind: 1, pubkey: 'pubkey', id: "eventid" });
     *     event.referenceTags(); // [["e", "parent-id"]]
     * @returns {NDKTag} The NDKTag object referencing this event
     */
    referenceTags(marker?: string, skipAuthorTag?: boolean, forceTag?: string): NDKTag[];
    /**
     * Provides the filter that will return matching events for this event.
     *
     * @example
     *    event = new NDKEvent(ndk, { kind: 30000, pubkey: 'pubkey', tags: [ ["d", "d-code"] ] });
     *    event.filter(); // { "#a": ["30000:pubkey:d-code"] }
     * @example
     *    event = new NDKEvent(ndk, { kind: 1, pubkey: 'pubkey', id: "eventid" });
     *    event.filter(); // { "#e": ["eventid"] }
     *
     * @returns The filter that will return matching events for this event
     */
    filter(): NDKFilter;
    nip22Filter(): NDKFilter;
    /**
     * Generates a deletion event of the current event
     *
     * @param reason The reason for the deletion
     * @param publish Whether to publish the deletion event automatically
     * @returns The deletion event
     */
    delete(reason?: string, publish?: boolean): Promise<NDKEvent>;
    /**
     * Establishes whether this is a NIP-70-protectede event.
     * @@satisfies NIP-70
     */
    set isProtected(val: boolean);
    /**
     * Whether this is a NIP-70-protected event.
     * @@satisfies NIP-70
     */
    get isProtected(): boolean;
    /**
     * Fetch an event tagged with the given tag following relay hints if provided.
     * @param tag The tag to search for
     * @param marker The marker to use in the tag (e.g. "root")
     * @returns The fetched event or null if no event was found, undefined if no matching tag was found in the event
     * * @example
     * const replyEvent = await ndk.fetchEvent("nevent1qqs8x8vnycyha73grv380gmvlury4wtmx0nr9a5ds2dngqwgu87wn6gpzemhxue69uhhyetvv9ujuurjd9kkzmpwdejhgq3ql2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqz4cwjd")
     * const originalEvent = await replyEvent.fetchTaggedEvent("e", "reply");
     * console.log(replyEvent.encode() + " is a reply to event " + originalEvent?.encode());
     */
    fetchTaggedEvent: (tag: string, marker?: string | undefined) => Promise<NDKEvent | null | undefined>;
    /**
     * Fetch the root event of the current event.
     * @returns The fetched root event or null if no event was found
     * @example
     * const replyEvent = await ndk.fetchEvent("nevent1qqs8x8vnycyha73grv380gmvlury4wtmx0nr9a5ds2dngqwgu87wn6gpzemhxue69uhhyetvv9ujuurjd9kkzmpwdejhgq3ql2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqz4cwjd")
     * const rootEvent = await replyEvent.fetchRootEvent();
     * console.log(replyEvent.encode() + " is a reply in the thread " + rootEvent?.encode());
     */
    fetchRootEvent: (subOpts?: NDKSubscriptionOptions | undefined) => Promise<NDKEvent | null | undefined>;
    /**
     * Fetch the event the current event is replying to.
     * @returns The fetched reply event or null if no event was found
     */
    fetchReplyEvent: (subOpts?: NDKSubscriptionOptions | undefined) => Promise<NDKEvent | null | undefined>;
    /**
     * NIP-18 reposting event.
     *
     * @param publish Whether to publish the reposted event automatically @default true
     * @param signer The signer to use for signing the reposted event
     * @returns The reposted event
     *
     * @function
     */
    repost: (publish?: boolean | undefined, signer?: NDKSigner | undefined) => Promise<NDKEvent>;
    /**
     * React to an existing event
     *
     * @param content The content of the reaction
     */
    react(content: string, publish?: boolean): Promise<NDKEvent>;
    /**
     * Checks whether the event is valid per underlying NIPs.
     *
     * This method is meant to be overridden by subclasses that implement specific NIPs
     * to allow the enforcement of NIP-specific validation rules.
     *
     * Otherwise, it will only check for basic event properties.
     *
     */
    get isValid(): boolean;
    get inspect(): string;
    /**
     * Dump the event to console for debugging purposes.
     * Prints a JSON stringified version of rawEvent() with indentation
     * and also lists all relay URLs for onRelays.
     */
    dump(): void;
    /**
     * Creates a reply event for the current event.
     *
     * This function will use NIP-22 when appropriate (i.e. replies to non-kind:1 events).
     * This function does not have side-effects; it will just return an event with the appropriate tags
     * to generate the reply event; the caller is responsible for publishing the event.
     *
     * @param forceNip22 - Optional flag to force NIP-22 style replies (kind 1111) regardless of the original event's kind
     */
    reply(forceNip22?: boolean): NDKEvent;
}
/**
 * Discriminated union types for signed and unsigned events
 */
/**
 * An NDKEvent that has been signed and has all required fields for relay transmission
 */
type NDKSignedEvent = NDKEvent & {
    readonly signed: true;
    id: string;
    sig: string;
    created_at: number;
};

interface RelayMockOptions {
    simulateDisconnect?: boolean;
    disconnectAfter?: number;
    connectionDelay?: number;
    autoConnect?: boolean;
    failNextPublish?: boolean;
}
/**
 * Mock implementation of NDK Relay for testing purposes
 */
declare class RelayMock extends EventEmitter$1 {
    url: string;
    private _status;
    messageLog: Array<{
        direction: "in" | "out";
        message: string;
    }>;
    private activeSubscriptions;
    validatedEvents: number;
    nonValidatedEvents: number;
    options: Required<RelayMockOptions>;
    constructor(url?: string, options?: RelayMockOptions);
    connect(): Promise<void>;
    disconnect(): Promise<void>;
    get status(): NDKRelayStatus;
    send(message: string): void;
    publish(event: NDKEvent): Promise<boolean>;
    subscribe(subscription: NDKSubscription, filters: NDKFilter[]): void;
    shouldValidateEvent(): boolean;
    /**
     * Track the number of validated events (used in tests)
     */
    addValidatedEvent(): void;
    /**
     * Track the number of non-validated events (used in tests)
     */
    addNonValidatedEvent(): void;
    /**
     * Simulate receiving a raw message
     */
    simulateReceiveMessage(message: string): void;
    /**
     * Simulate receiving an event
     */
    simulateEvent(event: NDKEvent, subId?: string): Promise<void>;
    /**
     * Simulate end of stored events
     */
    simulateEOSE(subId: string): void;
    /**
     * Simulate a NOTICE message from the relay
     */
    simulateNotice(message: string): void;
    reset(): void;
}

declare class RelayPoolMock {
    mockRelays: Map<string, RelayMock>;
    relays: Set<RelayMock>;
    private eventListeners;
    private onceListeners;
    addMockRelay(url: string, options?: {}): RelayMock;
    getMockRelay(url: string): RelayMock | undefined;
    addRelay(relay: RelayMock): void;
    removeRelay(relay: RelayMock): void;
    simulateEventOnAll(event: NDKEvent): void;
    simulateEventOn(relayUrls: string[], event: NDKEvent): void;
    simulateEOSEOnAll(subscriptionId: string): void;
    disconnectAll(): void;
    resetAll(): void;
    permanentAndConnectedRelays(): RelayMock[];
    connectedRelays(): RelayMock[];
    getRelay(url: string, connect?: boolean, createIfNotExists?: boolean, _filters?: NDKFilter[]): RelayMock;
    on(eventName: string, callback: Function): void;
    once(eventName: string, callback: Function): void;
    off(eventName: string, callback: Function): void;
    emit(eventName: string, ...args: any[]): void;
}

/**
 * EventGenerator for testing purposes
 *
 * This utility helps generate test events for the NDK testing infrastructure.
 * It handles private key generation and event creation with proper signing.
 */
declare class EventGenerator {
    private static privateKeys;
    private static ndk;
    static setNDK(ndk: any): void;
    static getPrivateKeyForPubkey(pubkey: string): string;
    static createEvent(kind?: number, // text note
    content?: string, pubkey?: string): NDKEvent;
    static createSignedTextNote(content: string, pubkey?: string): Promise<NDKEvent>;
    static createEncryptedDirectMessage(content: string, from: string, to: string): Promise<NDKEvent>;
    static createRepost(originalEvent: NDKEvent, pubkey?: string): Promise<NDKEvent>;
    static createParameterizedReplaceable(kind: number, content: string, pubkey?: string, dTag?: string): Promise<NDKEvent>;
}

type Proof = {
    id: string;
    amount: number;
    secret: string;
    C: string;
};
/**
 * Creates a nutzap for a given amount, optionally locking to a p2pk.
 * @param mint
 * @param amount
 * @param ndk
 * @param opts
 * @param opts.senderPk - The private key of the sender
 * @param opts.recipientPubkey - The nostr pubkey of the recipient
 * @param opts.content - The content of the nutzap
 */
declare function mockNutzap(mint: string, amount: number, ndk: any, { senderPk, recipientPubkey, content, }?: {
    senderPk?: any;
    recipientPubkey?: string;
    content?: string;
}): Promise<NDKNutzap>;
/**
 * Creates a proof for a given amount, optionally locking to a p2pk.
 * @param C
 * @param amount
 * @param p2pk
 * @returns
 */
declare function mockProof(C: string, amount: number, p2pk?: string): Proof;

type Names = "alice" | "bob" | "carol" | "dave" | "eve";
/**
 * Class for generating deterministic test users
 */
declare class UserGenerator {
    static privateKeys: Record<string, string>;
    /**
     * Get a user with a deterministic private key
     * @param name The name of the user (alice, bob, carol, dave, eve)
     * @param ndk The NDK instance to use for the user
     * @returns The NDK user
     */
    static getUser(name: Names, ndk?: NDK): Promise<NDKUser>;
    /**
     * Get the private key for a specific test user
     * @param name The name of the user (alice, bob, carol, dave, eve)
     * @returns The private key hex string
     */
    static getPrivateKey(name: Names): string;
    /**
     * Get a user with a random private key
     * @param ndk The NDK instance to use for the user
     * @returns The NDK user
     */
    static getRandomUser(ndk?: NDK): Promise<NDKUser>;
}
/**
 * Class for generating deterministic test signers
 */
declare class SignerGenerator {
    /**
     * Get a signer for a specific test user
     * @param name The name of the user (alice, bob, carol, dave, eve)
     * @returns The NDK signer
     */
    static getSigner(name: Names): NDKPrivateKeySigner;
    static sign(event: NDKEvent, user: Names): Promise<NDKEvent>;
    /**
     * Generate a random signer
     * @returns The NDK signer
     */
    static getRandomSigner(): NDKPrivateKeySigner;
}
/**
 * Enhanced event generation utilities that build on EventGenerator
 */
declare class TestEventFactory {
    private ndk;
    constructor(ndk: NDK);
    /**
     * Create a signed text note from a specific user
     * @param content The content of the note
     * @param user The user that authored the note, or name of predefined test user
     * @param kind The kind of the event (defaults to 1)
     * @returns The signed event
     */
    createSignedTextNote(content: string, user: NDKUser | Names | undefined, kind?: number): Promise<any>;
    /**
     * Create a direct message from one user to another
     * @param content The content of the message
     * @param fromUser The sender (author)
     * @param toUser The recipient
     * @returns The created event (not necessarily signed)
     */
    createDirectMessage(content: string, fromUser: NDKUser | Names, toUser: NDKUser | Names): Promise<any>;
    /**
     * Create a reply to an event
     * @param originalEvent The event being replied to
     * @param content The content of the reply
     * @param fromUser The author of the reply
     * @param kind The kind of the reply (defaults to same as original for kind 1, or 1111 for other kinds)
     * @returns The created reply event (not necessarily signed)
     */
    createReply(originalEvent: any, content: string, fromUser: NDKUser | Names, kind?: number): Promise<any>;
    /**
     * Creates a chain of events (e.g., a thread)
     * @param initialContent Content of the first message
     * @param replies Array of {content, author} objects for each reply
     * @returns Array of events in the chain
     */
    createEventChain(initialContent: string, initialAuthor: NDKUser | Names, replies: Array<{
        content: string;
        author: NDKUser | Names;
    }>): Promise<any[]>;
}
/**
 * Complete test fixture environment
 */
declare class TestFixture {
    ndk: NDK;
    eventFactory: TestEventFactory;
    constructor();
    /**
     * Get a predefined test user
     * @param name The name of the user (alice, bob, carol, dave, eve)
     * @returns The NDK user
     */
    getUser(name: Names): Promise<NDKUser>;
    /**
     * Get a signer for a predefined test user
     * @param name The name of the user
     * @returns The NDK signer
     */
    getSigner(name: Names): NDKPrivateKeySigner;
    /**
     * Set up the NDK instance with a specific signer
     * @param name The name of the predefined user to use as signer
     */
    setupSigner(name: Names): void;
}

/**
 * Utility class for controlling time in tests
 */
declare class TimeController {
    private static viObject;
    /**
     * Set the Vitest object to use for time control
     */
    static setViObject(vi: any): void;
    /**
     * Advance timers by a specified number of milliseconds
     */
    static advanceTime(ms: number): void;
    /**
     * Advance timers asynchronously by a specified number of milliseconds
     */
    static tickAsync(ms?: number): Promise<void>;
    /**
     * Clear all timers
     */
    static reset(): void;
    /**
     * Wait for the next tick of the event loop
     */
    static waitForNextTick(): Promise<void>;
}
/**
 * Higher-order function for using time control in tests
 */
declare function withTimeControl(viObject: any): (fn: (timeController: typeof TimeController) => Promise<void>) => (() => Promise<void>);

export { EventGenerator, type Proof, RelayMock, RelayPoolMock, SignerGenerator, TestEventFactory, TestFixture, TimeController, UserGenerator, mockNutzap, mockProof, withTimeControl };
