/**
 * @file MessageBoxClient.ts
 * @description
 * Provides the `MessageBoxClient` class — a secure client library for sending and receiving messages
 * via a Message Box Server over HTTP and WebSocket. Messages are authenticated, optionally encrypted,
 * and routed using identity-based addressing based on BRC-2/BRC-42/BRC-43 protocols.
 *
 * Core Features:
 * - Authenticated message transport using identity keys
 * - Deterministic message ID generation via HMAC (BRC-2)
 * - AES-256-GCM encryption using ECDH shared secrets derived via BRC-42/BRC-43
 * - Support for sending messages to self (`counterparty: 'self'`)
 * - Live message streaming using WebSocket rooms
 * - Optional plaintext messaging with `skipEncryption`
 * - Overlay host discovery and advertisement broadcasting via SHIP
 * - MessageBox-based organization and acknowledgment system
 *
 * See BRC-2 for details on the encryption scheme: https://github.com/bitcoin-sv/BRCs/blob/master/wallet/0002.md
 *
 * @module MessageBoxClient
 * @author Project Babbage
 * @license Open BSV License
 */
import { AuthFetch, BEEF, LockingScript, HexString } from '@bsv/sdk';
import { AuthSocketClient } from '@bsv/authsocket-client';
import { AcknowledgeMessageParams, ListMessagesParams, MessageBoxClientOptions, PeerMessage, SendMessageParams, SendMessageResponse } from './types.js';
interface AdvertisementToken {
    host: string;
    txid: HexString;
    outputIndex: number;
    lockingScript: LockingScript;
    beef: BEEF;
}
/**
 * @class MessageBoxClient
 * @description
 * A secure client for sending and receiving authenticated, encrypted messages
 * through a MessageBox server over HTTP and WebSocket.
 *
 * Core Features:
 * - Identity-authenticated message transport (BRC-2)
 * - AES-256-GCM end-to-end encryption with BRC-42/BRC-43 key derivation
 * - HMAC-based message ID generation for deduplication
 * - Live WebSocket messaging with room-based subscription management
 * - Overlay network discovery and host advertisement broadcasting (SHIP protocol)
 * - Fallback to HTTP messaging when WebSocket is unavailable
 *
 * **Important:**
 * The MessageBoxClient automatically calls `await init()` if needed.
 * Manual initialization is optional but still supported.
 *
 * You may call `await init()` manually for explicit control, but you can also use methods
 * like `sendMessage()` or `listenForLiveMessages()` directly — the client will initialize itself
 * automatically if not yet ready.
 *
 * @example
 * const client = new MessageBoxClient({ walletClient, enableLogging: true })
 * await client.init() // <- Required before using the client
 * await client.sendMessage({ recipient, messageBox: 'payment_inbox', body: 'Hello world' })
 */
export declare class MessageBoxClient {
    private host;
    readonly authFetch: AuthFetch;
    private readonly walletClient;
    private socket?;
    private myIdentityKey?;
    private readonly joinedRooms;
    private readonly lookupResolver;
    private readonly networkPreset;
    private initialized;
    /**
     * @constructor
     * @param {Object} options - Initialization options for the MessageBoxClient.
     * @param {string} [options.host] - The base URL of the MessageBox server. If omitted, defaults to mainnet/testnet hosts.
     * @param {WalletClient} options.walletClient - Wallet instance used for authentication, signing, and encryption.
     * @param {boolean} [options.enableLogging=false] - Whether to enable detailed debug logging to the console.
     * @param {'local' | 'mainnet' | 'testnet'} [options.networkPreset='mainnet'] - Overlay network preset used for routing and advertisement lookup.
     *
     * @description
     * Constructs a new MessageBoxClient.
     *
     * **Note:**
     * Passing a `host` during construction sets the default server.
     * If you do not manually call `await init()`, the client will automatically initialize itself on first use.
     *
     * @example
     * const client = new MessageBoxClient({
     *   host: 'https://messagebox.example',
     *   walletClient,
     *   enableLogging: true,
     *   networkPreset: 'testnet'
     * })
     * await client.init()
     */
    constructor(options?: MessageBoxClientOptions);
    /**
     * @method init
     * @async
     * @param {string} [targetHost] - Optional host to set or override the default host.
     * @returns {Promise<void>}
     *
     * @description
     * Initializes the MessageBoxClient by setting or anointing a MessageBox host.
     *
     * - If the client was constructed with a host, it uses that unless a different targetHost is provided.
     * - If no prior advertisement exists for the identity key and host, it automatically broadcasts a new advertisement.
     * - After calling init(), the client becomes ready to send, receive, and acknowledge messages.
     *
     * This method can be called manually for explicit control,
     * but will be automatically invoked if omitted.
     * @throws {Error} If no valid host is provided, or anointing fails.
     *
     * @example
     * const client = new MessageBoxClient({ host: 'https://mybox.example', walletClient })
     * await client.init()
     * await client.sendMessage({ recipient, messageBox: 'inbox', body: 'Hello' })
     */
    init(targetHost?: string): Promise<void>;
    /**
     * @method assertInitialized
     * @private
     * @description
     * Ensures that the MessageBoxClient has completed initialization before performing sensitive operations
     * like sending, receiving, or acknowledging messages.
     *
     * If the client is not yet initialized, it will automatically call `await init()` to complete setup.
     *
     * Used automatically by all public methods that require initialization.
     */
    private assertInitialized;
    /**
     * @method getJoinedRooms
     * @returns {Set<string>} A set of currently joined WebSocket room IDs
     * @description
     * Returns a live list of WebSocket rooms the client is subscribed to.
     * Useful for inspecting state or ensuring no duplicates are joined.
     */
    getJoinedRooms(): Set<string>;
    /**
   * @method getIdentityKey
   * @returns {Promise<string>} The identity public key of the user
   * @description
   * Returns the client's identity key, used for signing, encryption, and addressing.
   * If not already loaded, it will fetch and cache it.
   */
    getIdentityKey(): Promise<string>;
    /**
     * @property testSocket
     * @readonly
     * @returns {AuthSocketClient | undefined} The internal WebSocket client (or undefined if not connected).
     * @description
     * Exposes the underlying Authenticated WebSocket client used for live messaging.
     * This is primarily intended for debugging, test frameworks, or direct inspection.
     *
     * Note: Do not interact with the socket directly unless necessary.
     * Use the provided `sendLiveMessage`, `listenForLiveMessages`, and related methods.
     */
    get testSocket(): ReturnType<typeof AuthSocketClient> | undefined;
    /**
     * @method initializeConnection
     * @async
     * @returns {Promise<void>}
     * @description
     * Establishes an authenticated WebSocket connection to the configured MessageBox server.
     * Enables live message streaming via room-based channels tied to identity keys.
     *
     * This method:
     * 1. Retrieves the user’s identity key if not already set
     * 2. Initializes a secure AuthSocketClient WebSocket connection
     * 3. Authenticates the connection using the identity key
     * 4. Waits up to 5 seconds for authentication confirmation
     *
     * If authentication fails or times out, the connection is rejected.
     *
     * @throws {Error} If the identity key is unavailable or authentication fails
     *
     * @example
     * const mb = new MessageBoxClient({ walletClient })
     * await mb.initializeConnection()
     * // WebSocket is now ready for use
     */
    initializeConnection(): Promise<void>;
    /**
     * @method resolveHostForRecipient
     * @async
     * @param {string} identityKey - The public identity key of the intended recipient.
     * @returns {Promise<string>} - A fully qualified host URL for the recipient's MessageBox server.
     *
     * @description
     * Attempts to resolve the most recently anointed MessageBox host for the given identity key
     * using the BSV overlay network and the `ls_messagebox` LookupResolver.
     *
     * If no advertisements are found, or if resolution fails, the client will fall back
     * to its own configured `host`. This allows seamless operation in both overlay and non-overlay environments.
     *
     * This method guarantees a non-null return value and should be used directly when routing messages.
     *
     * @example
     * const host = await resolveHostForRecipient('028d...') // → returns either overlay host or this.host
     */
    resolveHostForRecipient(identityKey: string): Promise<string>;
    /**
     * Core lookup: ask the LookupResolver (optionally filtered by host),
     * decode every PushDrop output, and collect all the host URLs you find.
     *
     * @param identityKey  the recipient’s public key
     * @param host?        if passed, only look for adverts anointed at that host
     * @returns            0-length array if nothing valid was found
     */
    queryAdvertisements(identityKey?: string, host?: string): Promise<AdvertisementToken[]>;
    /**
     * @method joinRoom
     * @async
     * @param {string} messageBox - The name of the WebSocket room to join (e.g., "payment_inbox").
     * @returns {Promise<void>}
     *
     * @description
     * Joins a WebSocket room that corresponds to the user’s identity key and the specified message box.
     * This is required to receive real-time messages via WebSocket for a specific type of communication.
     *
     * If the WebSocket connection is not already established, this method will first initialize the connection.
     * It also ensures the room is only joined once, and tracks all joined rooms in an internal set.
     *
     * Room ID format: `${identityKey}-${messageBox}`
     *
     * @example
     * await client.joinRoom('payment_inbox')
     * // Now listening for real-time messages in room '028d...-payment_inbox'
     */
    joinRoom(messageBox: string): Promise<void>;
    /**
     * @method listenForLiveMessages
     * @async
     * @param {Object} params - Configuration for the live message listener.
     * @param {function} params.onMessage - A callback function that will be triggered when a new message arrives.
     * @param {string} params.messageBox - The messageBox name (e.g., `payment_inbox`) to listen for.
     * @returns {Promise<void>}
     *
     * @description
     * Subscribes the client to live messages over WebSocket for a specific messageBox.
     *
     * This method:
     * - Ensures the WebSocket connection is initialized and authenticated.
     * - Joins the correct room formatted as `${identityKey}-${messageBox}`.
     * - Listens for messages broadcast to the room.
     * - Automatically attempts to parse and decrypt message bodies.
     * - Emits the final message (as a `PeerMessage`) to the supplied `onMessage` handler.
     *
     * If the incoming message is encrypted, the client decrypts it using AES-256-GCM via
     * ECDH shared secrets derived from identity keys as defined in [BRC-2](https://github.com/bitcoin-sv/BRCs/blob/master/wallet/0002.md).
     * Messages sent by the client to itself are decrypted using `counterparty = 'self'`.
     *
     * @example
     * await client.listenForLiveMessages({
     *   messageBox: 'payment_inbox',
     *   onMessage: (msg) => console.log('Received live message:', msg)
     * })
     */
    listenForLiveMessages({ onMessage, messageBox }: {
        onMessage: (message: PeerMessage) => void;
        messageBox: string;
    }): Promise<void>;
    /**
     * @method sendLiveMessage
     * @async
     * @param {SendMessageParams} param0 - The message parameters including recipient, box name, body, and options.
     * @returns {Promise<SendMessageResponse>} A success response with the generated messageId.
     *
     * @description
     * Sends a message in real time using WebSocket with authenticated delivery and overlay fallback.
     *
     * This method:
     * - Ensures the WebSocket connection is open and joins the correct room.
     * - Derives a unique message ID using an HMAC of the message body and counterparty identity key.
     * - Encrypts the message body using AES-256-GCM based on the ECDH shared secret between derived keys, per [BRC-2](https://github.com/bitcoin-sv/BRCs/blob/master/wallet/0002.md),
     *   unless `skipEncryption` is explicitly set to `true`.
     * - Sends the message to a WebSocket room in the format `${recipient}-${messageBox}`.
     * - Waits for acknowledgment (`sendMessageAck-${roomId}`).
     * - If no acknowledgment is received within 10 seconds, falls back to `sendMessage()` over HTTP.
     *
     * This hybrid delivery strategy ensures reliability in both real-time and offline-capable environments.
     *
     * @throws {Error} If message validation fails, HMAC generation fails, or both WebSocket and HTTP fail to deliver.
     *
     * @example
     * await client.sendLiveMessage({
     *   recipient: '028d...',
     *   messageBox: 'payment_inbox',
     *   body: { amount: 1000 }
     * })
     */
    sendLiveMessage({ recipient, messageBox, body, messageId, skipEncryption }: SendMessageParams): Promise<SendMessageResponse>;
    /**
     * @method leaveRoom
     * @async
     * @param {string} messageBox - The name of the WebSocket room to leave (e.g., `payment_inbox`).
     * @returns {Promise<void>}
     *
     * @description
     * Leaves a previously joined WebSocket room associated with the authenticated identity key.
     * This helps reduce unnecessary message traffic and memory usage.
     *
     * If the WebSocket is not connected or the identity key is missing, the method exits gracefully.
     *
     * @example
     * await client.leaveRoom('payment_inbox')
     */
    leaveRoom(messageBox: string): Promise<void>;
    /**
     * @method disconnectWebSocket
     * @async
     * @returns {Promise<void>} Resolves when the WebSocket connection is successfully closed.
     *
     * @description
     * Gracefully disconnects the WebSocket connection to the MessageBox server.
     * This should be called when the client is shutting down, logging out, or no longer
     * needs real-time communication to conserve system resources.
     *
     * @example
     * await client.disconnectWebSocket()
     */
    disconnectWebSocket(): Promise<void>;
    /**
     * @method sendMessage
     * @async
     * @param {SendMessageParams} message - Contains recipient, messageBox name, message body, optional messageId, and skipEncryption flag.
     * @param {string} [overrideHost] - Optional host to override overlay resolution (useful for testing or private routing).
     * @returns {Promise<SendMessageResponse>} - Resolves with `{ status, messageId }` on success.
     *
     * @description
     * Sends a message over HTTP to a recipient's messageBox. This method:
     *
     * - Derives a deterministic `messageId` using an HMAC of the message body and recipient key.
     * - Encrypts the message body using AES-256-GCM, derived from a shared secret using BRC-2-compliant key derivation and ECDH, unless `skipEncryption` is set to true.
     * - Automatically resolves the host via overlay LookupResolver unless an override is provided.
     * - Authenticates the request using the current identity key with `AuthFetch`.
     *
     * This is the fallback mechanism for `sendLiveMessage` when WebSocket delivery fails.
     * It is also used for message types that do not require real-time delivery.
     *
     * @throws {Error} If validation, encryption, HMAC, or network request fails.
     *
     * @example
     * await client.sendMessage({
     *   recipient: '03abc...',
     *   messageBox: 'notifications',
     *   body: { type: 'ping' }
     * })
     */
    sendMessage(message: SendMessageParams, overrideHost?: string): Promise<SendMessageResponse>;
    /**
     * @method anointHost
     * @async
     * @param {string} host - The full URL of the server you want to designate as your MessageBox host (e.g., "https://mybox.com").
     * @returns {Promise<{ txid: string }>} - The transaction ID of the advertisement broadcast to the overlay network.
     *
     * @description
     * Broadcasts a signed overlay advertisement using a PushDrop output under the `tm_messagebox` topic.
     * This advertisement announces that the specified `host` is now authorized to receive and route
     * messages for the sender’s identity key.
     *
     * The broadcasted message includes:
     * - The identity key
     * - The chosen host URL
     *
     * This is essential for enabling overlay-based message delivery via SHIP and LookupResolver.
     * The recipient’s host must advertise itself for message routing to succeed in a decentralized manner.
     *
     * @throws {Error} If the URL is invalid, the PushDrop creation fails, or the overlay broadcast does not succeed.
     *
     * @example
     * const { txid } = await client.anointHost('https://my-messagebox.io')
     */
    anointHost(host: string): Promise<{
        txid: string;
    }>;
    /**
     * @method revokeHostAdvertisement
     * @async
     * @param {AdvertisementToken} advertisementToken - The advertisement token containing the messagebox host to revoke.
     * @returns {Promise<{ txid: string }>} - The transaction ID of the revocation broadcast to the overlay network.
     *
     * @description
     * Broadcasts a signed revocation transaction indicating the advertisement token should be removed
     * and no longer tracked by lookup services.
     *
     * @example
     * const { txid } = await client.revokeHost('https://my-messagebox.io')
     */
    revokeHostAdvertisement(advertisementToken: AdvertisementToken): Promise<{
        txid: string;
    }>;
    /**
     * @method listMessages
     * @async
     * @param {ListMessagesParams} params - Contains the name of the messageBox to read from.
     * @returns {Promise<PeerMessage[]>} - Returns an array of decrypted `PeerMessage` objects.
     *
     * @description
     * Retrieves all messages from the specified `messageBox` assigned to the current identity key.
     * Unless a host override is provided, messages are fetched from the resolved overlay host (via LookupResolver) or the default host if no advertisement is found.
     *
     * Each message is:
     * - Parsed and, if encrypted, decrypted using AES-256-GCM via BRC-2-compliant ECDH key derivation and symmetric encryption.
     * - Returned as a normalized `PeerMessage` with readable string body content.
     *
     * Decryption automatically derives a shared secret using the sender’s identity key and the receiver’s child private key.
     * If the sender is the same as the recipient, the `counterparty` is set to `'self'`.
     *
     * @throws {Error} If no messageBox is specified, the request fails, or the server returns an error.
     *
     * @example
     * const messages = await client.listMessages({ messageBox: 'inbox' })
     * messages.forEach(msg => console.log(msg.sender, msg.body))
     */
    listMessages({ messageBox, host }: ListMessagesParams): Promise<PeerMessage[]>;
    /**
     * @method acknowledgeMessage
     * @async
     * @param {AcknowledgeMessageParams} params - An object containing an array of message IDs to acknowledge.
     * @returns {Promise<string>} - A string indicating the result, typically `'success'`.
     *
     * @description
     * Notifies the MessageBox server(s) that one or more messages have been
     * successfully received and processed by the client. Once acknowledged, these messages are removed
     * from the recipient's inbox on the server(s).
     *
     * This operation is essential for proper message lifecycle management and prevents duplicate
     * processing or delivery.
     *
     * Acknowledgment supports providing a host override, or will use overlay routing to find the appropriate server the received the given message.
     *
     * @throws {Error} If the message ID array is missing or empty, or if the request to the server fails.
     *
     * @example
     * await client.acknowledgeMessage({ messageIds: ['msg123', 'msg456'] })
     */
    acknowledgeMessage({ messageIds, host }: AcknowledgeMessageParams): Promise<string>;
}
export {};
//# sourceMappingURL=MessageBoxClient.d.ts.map