UNPKG

@bsv/message-box-client

Version:

A client for P2P messaging and payments

743 lines 34.7 kB
/** * @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, PubKeyHex, OriginatorDomainNameStringUnder250Bytes } from '@bsv/sdk'; import { AuthSocketClient } from '@bsv/authsocket-client'; import { AcknowledgeMessageParams, AdvertisementToken, ListMessagesParams, MessageBoxClientOptions, PeerMessage, SendMessageParams, SendMessageResponse, DeviceRegistrationParams, DeviceRegistrationResponse, RegisteredDevice } from './types.js'; import { SetMessageBoxPermissionParams, GetMessageBoxPermissionParams, MessageBoxPermission, MessageBoxQuote, ListPermissionsParams, GetQuoteParams } from './types/permissions.js'; /** * @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; protected originator?: OriginatorDomainNameStringUnder250Bytes; /** * @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 {WalletInterface} 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. * @param {string} [originator] - Optional originator to use with walletClient. * @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 * @param {string} [originator] - Optional originator to use for identity key lookup * @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 * @param {string} [originator] - Optional originator to use for authentication. * @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(overrideHost?: string): Promise<void>; /** * @method resolveHostForRecipient * @async * @param {string} identityKey - The public identity key of the intended recipient. * @param {string} [originator] - The originator to use for the WalletClient. * @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, overrideHost?: 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, overrideHost }: { onMessage: (message: PeerMessage) => void; messageBox: string; overrideHost?: 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, checkPermissions, }: SendMessageParams, overrideHost?: string): 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. * @param {string} [originator] - Optional originator to use with walletClient. * @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. * - Automatically processed for payments: if the message includes recipient fee payments, they are internalized using `walletClient.internalizeAction()`. * - Returned as a normalized `PeerMessage` with readable string body content. * * Payment Processing: * - Detects messages that include payment data (from paid message delivery). * - Automatically internalizes recipient payment outputs, allowing you to receive payments without additional API calls. * - Only recipient payments are stored with messages - delivery fees are already processed by the server. * - Continues processing messages even if payment internalization fails. * * 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)) * // Payments included with messages are automatically received */ listMessages({ messageBox, host, acceptPayments }: ListMessagesParams): Promise<PeerMessage[]>; /** * @method listMessagesLite * @async * @param {ListMessagesParams} params - Contains the `messageBox` to read from and the `host` to query. * @returns {Promise<PeerMessage[]>} - Returns an array of decrypted `PeerMessage` objects with minimal processing. * * @description * A lightweight variant of {@link listMessages} that fetches and decrypts messages * from a specific host without performing: * - Overlay host resolution * - Payment acceptance or internalization * - Cross-host deduplication * * This method: * - Sends a direct POST request to the specified host's `/listMessages` endpoint. * - Parses message bodies as JSON when possible. * - Decrypts messages if they contain an `encryptedMessage` field, using AES-256-GCM via BRC-2-compliant ECDH key derivation. * - Returns messages in the order provided by the host. * * This is intended for cases where you already know the host and need faster, * simpler retrieval without the additional processing overhead of `listMessages`. * * @throws {Error} If the host returns an error status or decryption fails. * * @example * const messages = await client.listMessagesLite({ * messageBox: 'notifications', * host: 'https://messagebox.babbage.systems' * }) * console.log(messages) */ listMessagesLite({ messageBox, host }: ListMessagesParams): Promise<PeerMessage[]>; /** * @method tryParse * @private * @param {string} raw - A raw string value that may contain JSON. * @returns {any} - The parsed JavaScript object if valid JSON, or the original string if parsing fails. * * @description * Attempts to parse a string as JSON. If the string is valid JSON, returns the parsed object; * otherwise returns the original string unchanged. * * This method is used throughout the client to safely handle message bodies that may or may not be * JSON-encoded without throwing parsing errors. * * @example * tryParse('{"hello":"world"}') // → { hello: "world" } * tryParse('plain text') // → "plain text" */ tryParse(raw: string): any; /** * @method acknowledgeNotification * @async * @param {PeerMessage} message - The peer message object to acknowledge. * @returns {Promise<boolean>} - Resolves to `true` if the message included a recipient payment and it was successfully internalized, otherwise `false`. * * @description * Acknowledges receipt of a specific notification message and, if applicable, processes any recipient * payment contained within it. * * This method: * 1. Calls `acknowledgeMessage()` to remove the message from the server's queue. * 2. Checks the message body for embedded payment data. * 3. If a recipient payment exists, attempts to internalize it into the wallet. * * This is a convenience wrapper for acknowledgment and payment handling specifically for messages * representing notifications. * * @example * const success = await client.acknowledgeNotification(message) * console.log(success ? 'Payment received' : 'No payment or failed') */ acknowledgeNotification(message: PeerMessage): Promise<boolean>; /** * @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>; /** * @method setMessageBoxPermission * @async * @param {SetMessageBoxPermissionParams} params - Permission configuration * @param {string} [overrideHost] - Optional host override * @returns {Promise<void>} Permission status after setting * * @description * Sets permission for receiving messages in a specific messageBox. * Can set sender-specific permissions or box-wide defaults. * * @example * // Set box-wide default: allow notifications for 10 sats * await client.setMessageBoxPermission({ messageBox: 'notifications', recipientFee: 10 }) * * // Block specific sender * await client.setMessageBoxPermission({ * messageBox: 'notifications', * sender: '03abc123...', * recipientFee: -1 * }) */ setMessageBoxPermission(params: SetMessageBoxPermissionParams, overrideHost?: string): Promise<void>; /** * @method getMessageBoxPermission * @async * @param {GetMessageBoxPermissionParams} params - Permission query parameters * @param {string} [overrideHost] - Optional host override * @returns {Promise<MessageBoxPermission | null>} Permission data (null if not set) * * @description * Gets current permission data for a sender/messageBox combination. * Returns null if no permission is set. * * @example * const status = await client.getMessageBoxPermission({ * recipient: '03def456...', * messageBox: 'notifications', * sender: '03abc123...' * }) */ getMessageBoxPermission(params: GetMessageBoxPermissionParams, overrideHost?: string): Promise<MessageBoxPermission | null>; /** * @method getMessageBoxQuote * @async * @param {GetQuoteParams} params - Quote request parameters * @returns {Promise<MessageBoxQuote>} Fee quote and permission status * * @description * Gets a fee quote for sending a message, including delivery and recipient fees. * * @example * const quote = await client.getMessageBoxQuote({ * recipient: '03def456...', * messageBox: 'notifications' * }) */ getMessageBoxQuote(params: GetQuoteParams, overrideHost?: string): Promise<MessageBoxQuote>; /** * @method listMessageBoxPermissions * @async * @param {ListPermissionsParams} [params] - Optional filtering and pagination parameters * @returns {Promise<MessageBoxPermission[]>} List of current permissions * * @description * Lists permissions for the authenticated user's messageBoxes with optional pagination. * * @example * // List all permissions * const all = await client.listMessageBoxPermissions() * * // List only notification permissions with pagination * const notifications = await client.listMessageBoxPermissions({ * messageBox: 'notifications', * limit: 50, * offset: 0 * }) */ listMessageBoxPermissions(params?: ListPermissionsParams, overrideHost?: string): Promise<MessageBoxPermission[]>; /** * @method allowNotificationsFromPeer * @async * @param {PubKeyHex} identityKey - Sender's identity key to allow * @param {number} [recipientFee=0] - Fee to charge (0 for always allow) * @param {string} [overrideHost] - Optional host override * @returns {Promise<void>} Permission status after allowing * * @description * Convenience method to allow notifications from a specific peer. * * @example * await client.allowNotificationsFromPeer('03abc123...') // Always allow * await client.allowNotificationsFromPeer('03def456...', 5) // Allow for 5 sats */ allowNotificationsFromPeer(identityKey: PubKeyHex, recipientFee?: number, overrideHost?: string): Promise<void>; /** * @method denyNotificationsFromPeer * @async * @param {PubKeyHex} identityKey - Sender's identity key to block * @returns {Promise<void>} Permission status after denying * * @description * Convenience method to block notifications from a specific peer. * * @example * await client.denyNotificationsFromPeer('03spam123...') */ denyNotificationsFromPeer(identityKey: PubKeyHex, overrideHost?: string): Promise<void>; /** * @method checkPeerNotificationStatus * @async * @param {PubKeyHex} identityKey - Sender's identity key to check * @returns {Promise<MessageBoxPermission>} Current permission status * * @description * Convenience method to check notification permission for a specific peer. * * @example * const status = await client.checkPeerNotificationStatus('03abc123...') * console.log(status.allowed) // true/false */ checkPeerNotificationStatus(identityKey: PubKeyHex, overrideHost?: string): Promise<MessageBoxPermission | null>; /** * @method listPeerNotifications * @async * @returns {Promise<MessageBoxPermission[]>} List of notification permissions * * @description * Convenience method to list all notification permissions. * * @example * const notifications = await client.listPeerNotifications() */ listPeerNotifications(overrideHost?: string): Promise<MessageBoxPermission[]>; /** * @method sendNotification * @async * @param {PubKeyHex} recipient - Recipient's identity key * @param {string | object} body - Notification content * @param {string} [overrideHost] - Optional host override * @returns {Promise<SendMessageResponse>} Send result * * @description * Convenience method to send a notification with automatic quote fetching and payment handling. * Automatically determines the required payment amount and creates the payment if needed. * * @example * // Send notification (auto-determines payment needed) * await client.sendNotification('03def456...', 'Hello!') * * // Send with maximum payment limit for safety * await client.sendNotification('03def456...', { title: 'Alert', body: 'Important update' }, 50) */ sendNotification(recipient: PubKeyHex, body: string | object, overrideHost?: string): Promise<SendMessageResponse>; /** * Register a device for FCM push notifications. * * @async * @param {DeviceRegistrationParams} params - Device registration parameters * @param {string} [overrideHost] - Optional host override * @returns {Promise<DeviceRegistrationResponse>} Registration response * * @description * Registers a device with the message box server to receive FCM push notifications. * The FCM token is obtained from Firebase SDK on the client side. * * @example * const result = await client.registerDevice({ * fcmToken: 'eBo8F...', * platform: 'ios', * deviceId: 'iPhone15Pro' * }) */ registerDevice(params: DeviceRegistrationParams, overrideHost?: string): Promise<DeviceRegistrationResponse>; /** * List all registered devices for push notifications. * * @async * @param {string} [overrideHost] - Optional host override * @returns {Promise<RegisteredDevice[]>} Array of registered devices * * @description * Retrieves all devices registered by the authenticated user for FCM push notifications. * Only shows devices belonging to the current user (authenticated via AuthFetch). * * @example * const devices = await client.listRegisteredDevices() * console.log(`Found ${devices.length} registered devices`) * devices.forEach(device => { * console.log(`Device: ${device.platform} - ${device.fcmToken}`) * }) */ listRegisteredDevices(overrideHost?: string): Promise<RegisteredDevice[]>; private static getStatusFromFee; /** * @method createMessagePayment * @private * @param {string} recipient - Recipient's identity key. * @param {MessageBoxQuote} quote - Quote object containing recipient and delivery fees. * @param {string} [description='MessageBox delivery payment'] - Description for the payment action. * @param {string} [originator] - Optional originator to use for wallet operations. * @returns {Promise<Payment>} - Payment data including the transaction and remittance outputs. * * @description * Constructs and signs a payment transaction covering both delivery and recipient fees for * message delivery, based on a previously obtained quote. * * The transaction includes: * - An optional delivery fee output for the MessageBox server. * - An optional recipient fee output for the message recipient. * * Payment remittance metadata (derivation prefix/suffix, sender identity) is embedded to allow * the payee to derive their private key and spend the output. * * @throws {Error} If no payment is required, key derivation fails, or the action creation fails. * * @example * const payment = await client.createMessagePayment(recipientKey, quote) * await client.sendMessage({ recipient, messageBox, body, payment }) */ private createMessagePayment; } //# sourceMappingURL=MessageBoxClient.d.ts.map