@bsv/message-box-client 1.1.7 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/cjs/mod.js +20 -0
  2. package/dist/cjs/mod.js.map +1 -0
  3. package/dist/cjs/package.json +69 -0
  4. package/dist/cjs/src/MessageBoxClient.js +1171 -0
  5. package/dist/cjs/src/MessageBoxClient.js.map +1 -0
  6. package/dist/cjs/src/PeerPayClient.js +309 -0
  7. package/dist/cjs/src/PeerPayClient.js.map +1 -0
  8. package/dist/cjs/src/Utils/logger.js +27 -0
  9. package/dist/cjs/src/Utils/logger.js.map +1 -0
  10. package/dist/cjs/src/__tests/MessageBoxClient.test.js +614 -0
  11. package/dist/cjs/src/__tests/MessageBoxClient.test.js.map +1 -0
  12. package/dist/cjs/src/__tests/PeerPayClientUnit.test.js +213 -0
  13. package/dist/cjs/src/__tests/PeerPayClientUnit.test.js.map +1 -0
  14. package/dist/cjs/src/__tests/integration/integrationEncrypted.test.js +84 -0
  15. package/dist/cjs/src/__tests/integration/integrationEncrypted.test.js.map +1 -0
  16. package/dist/cjs/src/__tests/integration/integrationHTTP.test.js +128 -0
  17. package/dist/cjs/src/__tests/integration/integrationHTTP.test.js.map +1 -0
  18. package/dist/cjs/src/__tests/integration/integrationOverlay.test.js +138 -0
  19. package/dist/cjs/src/__tests/integration/integrationOverlay.test.js.map +1 -0
  20. package/dist/cjs/src/__tests/integration/integrationWS.test.js +123 -0
  21. package/dist/cjs/src/__tests/integration/integrationWS.test.js.map +1 -0
  22. package/dist/cjs/src/__tests/integration/testServer.js +65 -0
  23. package/dist/cjs/src/__tests/integration/testServer.js.map +1 -0
  24. package/dist/cjs/src/types.js +3 -0
  25. package/dist/cjs/src/types.js.map +1 -0
  26. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  27. package/dist/esm/mod.js +4 -0
  28. package/dist/esm/mod.js.map +1 -0
  29. package/dist/esm/src/MessageBoxClient.js +1165 -0
  30. package/dist/esm/src/MessageBoxClient.js.map +1 -0
  31. package/dist/esm/src/PeerPayClient.js +307 -0
  32. package/dist/esm/src/PeerPayClient.js.map +1 -0
  33. package/dist/esm/src/Utils/logger.js +23 -0
  34. package/dist/esm/src/Utils/logger.js.map +1 -0
  35. package/dist/esm/src/__tests/MessageBoxClient.test.js +603 -0
  36. package/dist/esm/src/__tests/MessageBoxClient.test.js.map +1 -0
  37. package/dist/esm/src/__tests/PeerPayClientUnit.test.js +211 -0
  38. package/dist/esm/src/__tests/PeerPayClientUnit.test.js.map +1 -0
  39. package/dist/esm/src/__tests/integration/integrationEncrypted.test.js +81 -0
  40. package/dist/esm/src/__tests/integration/integrationEncrypted.test.js.map +1 -0
  41. package/dist/esm/src/__tests/integration/integrationHTTP.test.js +126 -0
  42. package/dist/esm/src/__tests/integration/integrationHTTP.test.js.map +1 -0
  43. package/dist/esm/src/__tests/integration/integrationOverlay.test.js +135 -0
  44. package/dist/esm/src/__tests/integration/integrationOverlay.test.js.map +1 -0
  45. package/dist/esm/src/__tests/integration/integrationWS.test.js +121 -0
  46. package/dist/esm/src/__tests/integration/integrationWS.test.js.map +1 -0
  47. package/dist/esm/src/__tests/integration/testServer.js +61 -0
  48. package/dist/esm/src/__tests/integration/testServer.js.map +1 -0
  49. package/dist/esm/src/types.js +2 -0
  50. package/dist/esm/src/types.js.map +1 -0
  51. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
  52. package/dist/types/mod.d.ts +4 -0
  53. package/dist/types/mod.d.ts.map +1 -0
  54. package/dist/types/src/MessageBoxClient.d.ts +441 -0
  55. package/dist/types/src/MessageBoxClient.d.ts.map +1 -0
  56. package/dist/types/src/PeerPayClient.d.ts +144 -0
  57. package/dist/types/src/PeerPayClient.d.ts.map +1 -0
  58. package/dist/types/src/Utils/logger.d.ts +9 -0
  59. package/dist/types/src/Utils/logger.d.ts.map +1 -0
  60. package/dist/types/src/__tests/MessageBoxClient.test.d.ts +2 -0
  61. package/dist/types/src/__tests/MessageBoxClient.test.d.ts.map +1 -0
  62. package/dist/types/src/__tests/PeerPayClientUnit.test.d.ts +2 -0
  63. package/dist/types/src/__tests/PeerPayClientUnit.test.d.ts.map +1 -0
  64. package/dist/types/src/__tests/integration/integrationEncrypted.test.d.ts +2 -0
  65. package/dist/types/src/__tests/integration/integrationEncrypted.test.d.ts.map +1 -0
  66. package/dist/types/src/__tests/integration/integrationHTTP.test.d.ts +2 -0
  67. package/dist/types/src/__tests/integration/integrationHTTP.test.d.ts.map +1 -0
  68. package/dist/types/src/__tests/integration/integrationOverlay.test.d.ts +2 -0
  69. package/dist/types/src/__tests/integration/integrationOverlay.test.d.ts.map +1 -0
  70. package/dist/types/src/__tests/integration/integrationWS.test.d.ts +2 -0
  71. package/dist/types/src/__tests/integration/integrationWS.test.d.ts.map +1 -0
  72. package/dist/types/src/__tests/integration/testServer.d.ts +9 -0
  73. package/dist/types/src/__tests/integration/testServer.d.ts.map +1 -0
  74. package/dist/types/src/types.d.ts +99 -0
  75. package/dist/types/src/types.d.ts.map +1 -0
  76. package/dist/types/tsconfig.types.tsbuildinfo +1 -0
  77. package/dist/umd/bundle.js +1 -0
  78. package/package.json +5 -5
@@ -0,0 +1,441 @@
1
+ /**
2
+ * @file MessageBoxClient.ts
3
+ * @description
4
+ * Provides the `MessageBoxClient` class — a secure client library for sending and receiving messages
5
+ * via a Message Box Server over HTTP and WebSocket. Messages are authenticated, optionally encrypted,
6
+ * and routed using identity-based addressing based on BRC-2/BRC-42/BRC-43 protocols.
7
+ *
8
+ * Core Features:
9
+ * - Authenticated message transport using identity keys
10
+ * - Deterministic message ID generation via HMAC (BRC-2)
11
+ * - AES-256-GCM encryption using ECDH shared secrets derived via BRC-42/BRC-43
12
+ * - Support for sending messages to self (`counterparty: 'self'`)
13
+ * - Live message streaming using WebSocket rooms
14
+ * - Optional plaintext messaging with `skipEncryption`
15
+ * - Overlay host discovery and advertisement broadcasting via SHIP
16
+ * - MessageBox-based organization and acknowledgment system
17
+ *
18
+ * See BRC-2 for details on the encryption scheme: https://github.com/bitcoin-sv/BRCs/blob/master/wallet/0002.md
19
+ *
20
+ * @module MessageBoxClient
21
+ * @author Project Babbage
22
+ * @license Open BSV License
23
+ */
24
+ import { AuthFetch, BEEF, LockingScript, HexString } from '@bsv/sdk';
25
+ import { AuthSocketClient } from '@bsv/authsocket-client';
26
+ import { AcknowledgeMessageParams, ListMessagesParams, MessageBoxClientOptions, PeerMessage, SendMessageParams, SendMessageResponse } from './types.js';
27
+ interface AdvertisementToken {
28
+ host: string;
29
+ txid: HexString;
30
+ outputIndex: number;
31
+ lockingScript: LockingScript;
32
+ beef: BEEF;
33
+ }
34
+ /**
35
+ * @class MessageBoxClient
36
+ * @description
37
+ * A secure client for sending and receiving authenticated, encrypted messages
38
+ * through a MessageBox server over HTTP and WebSocket.
39
+ *
40
+ * Core Features:
41
+ * - Identity-authenticated message transport (BRC-2)
42
+ * - AES-256-GCM end-to-end encryption with BRC-42/BRC-43 key derivation
43
+ * - HMAC-based message ID generation for deduplication
44
+ * - Live WebSocket messaging with room-based subscription management
45
+ * - Overlay network discovery and host advertisement broadcasting (SHIP protocol)
46
+ * - Fallback to HTTP messaging when WebSocket is unavailable
47
+ *
48
+ * **Important:**
49
+ * The MessageBoxClient automatically calls `await init()` if needed.
50
+ * Manual initialization is optional but still supported.
51
+ *
52
+ * You may call `await init()` manually for explicit control, but you can also use methods
53
+ * like `sendMessage()` or `listenForLiveMessages()` directly — the client will initialize itself
54
+ * automatically if not yet ready.
55
+ *
56
+ * @example
57
+ * const client = new MessageBoxClient({ walletClient, enableLogging: true })
58
+ * await client.init() // <- Required before using the client
59
+ * await client.sendMessage({ recipient, messageBox: 'payment_inbox', body: 'Hello world' })
60
+ */
61
+ export declare class MessageBoxClient {
62
+ private host;
63
+ readonly authFetch: AuthFetch;
64
+ private readonly walletClient;
65
+ private socket?;
66
+ private myIdentityKey?;
67
+ private readonly joinedRooms;
68
+ private readonly lookupResolver;
69
+ private readonly networkPreset;
70
+ private initialized;
71
+ /**
72
+ * @constructor
73
+ * @param {Object} options - Initialization options for the MessageBoxClient.
74
+ * @param {string} [options.host] - The base URL of the MessageBox server. If omitted, defaults to mainnet/testnet hosts.
75
+ * @param {WalletClient} options.walletClient - Wallet instance used for authentication, signing, and encryption.
76
+ * @param {boolean} [options.enableLogging=false] - Whether to enable detailed debug logging to the console.
77
+ * @param {'local' | 'mainnet' | 'testnet'} [options.networkPreset='mainnet'] - Overlay network preset used for routing and advertisement lookup.
78
+ *
79
+ * @description
80
+ * Constructs a new MessageBoxClient.
81
+ *
82
+ * **Note:**
83
+ * Passing a `host` during construction sets the default server.
84
+ * If you do not manually call `await init()`, the client will automatically initialize itself on first use.
85
+ *
86
+ * @example
87
+ * const client = new MessageBoxClient({
88
+ * host: 'https://messagebox.example',
89
+ * walletClient,
90
+ * enableLogging: true,
91
+ * networkPreset: 'testnet'
92
+ * })
93
+ * await client.init()
94
+ */
95
+ constructor(options?: MessageBoxClientOptions);
96
+ /**
97
+ * @method init
98
+ * @async
99
+ * @param {string} [targetHost] - Optional host to set or override the default host.
100
+ * @returns {Promise<void>}
101
+ *
102
+ * @description
103
+ * Initializes the MessageBoxClient by setting or anointing a MessageBox host.
104
+ *
105
+ * - If the client was constructed with a host, it uses that unless a different targetHost is provided.
106
+ * - If no prior advertisement exists for the identity key and host, it automatically broadcasts a new advertisement.
107
+ * - After calling init(), the client becomes ready to send, receive, and acknowledge messages.
108
+ *
109
+ * This method can be called manually for explicit control,
110
+ * but will be automatically invoked if omitted.
111
+ * @throws {Error} If no valid host is provided, or anointing fails.
112
+ *
113
+ * @example
114
+ * const client = new MessageBoxClient({ host: 'https://mybox.example', walletClient })
115
+ * await client.init()
116
+ * await client.sendMessage({ recipient, messageBox: 'inbox', body: 'Hello' })
117
+ */
118
+ init(targetHost?: string): Promise<void>;
119
+ /**
120
+ * @method assertInitialized
121
+ * @private
122
+ * @description
123
+ * Ensures that the MessageBoxClient has completed initialization before performing sensitive operations
124
+ * like sending, receiving, or acknowledging messages.
125
+ *
126
+ * If the client is not yet initialized, it will automatically call `await init()` to complete setup.
127
+ *
128
+ * Used automatically by all public methods that require initialization.
129
+ */
130
+ private assertInitialized;
131
+ /**
132
+ * @method getJoinedRooms
133
+ * @returns {Set<string>} A set of currently joined WebSocket room IDs
134
+ * @description
135
+ * Returns a live list of WebSocket rooms the client is subscribed to.
136
+ * Useful for inspecting state or ensuring no duplicates are joined.
137
+ */
138
+ getJoinedRooms(): Set<string>;
139
+ /**
140
+ * @method getIdentityKey
141
+ * @returns {Promise<string>} The identity public key of the user
142
+ * @description
143
+ * Returns the client's identity key, used for signing, encryption, and addressing.
144
+ * If not already loaded, it will fetch and cache it.
145
+ */
146
+ getIdentityKey(): Promise<string>;
147
+ /**
148
+ * @property testSocket
149
+ * @readonly
150
+ * @returns {AuthSocketClient | undefined} The internal WebSocket client (or undefined if not connected).
151
+ * @description
152
+ * Exposes the underlying Authenticated WebSocket client used for live messaging.
153
+ * This is primarily intended for debugging, test frameworks, or direct inspection.
154
+ *
155
+ * Note: Do not interact with the socket directly unless necessary.
156
+ * Use the provided `sendLiveMessage`, `listenForLiveMessages`, and related methods.
157
+ */
158
+ get testSocket(): ReturnType<typeof AuthSocketClient> | undefined;
159
+ /**
160
+ * @method initializeConnection
161
+ * @async
162
+ * @returns {Promise<void>}
163
+ * @description
164
+ * Establishes an authenticated WebSocket connection to the configured MessageBox server.
165
+ * Enables live message streaming via room-based channels tied to identity keys.
166
+ *
167
+ * This method:
168
+ * 1. Retrieves the user’s identity key if not already set
169
+ * 2. Initializes a secure AuthSocketClient WebSocket connection
170
+ * 3. Authenticates the connection using the identity key
171
+ * 4. Waits up to 5 seconds for authentication confirmation
172
+ *
173
+ * If authentication fails or times out, the connection is rejected.
174
+ *
175
+ * @throws {Error} If the identity key is unavailable or authentication fails
176
+ *
177
+ * @example
178
+ * const mb = new MessageBoxClient({ walletClient })
179
+ * await mb.initializeConnection()
180
+ * // WebSocket is now ready for use
181
+ */
182
+ initializeConnection(): Promise<void>;
183
+ /**
184
+ * @method resolveHostForRecipient
185
+ * @async
186
+ * @param {string} identityKey - The public identity key of the intended recipient.
187
+ * @returns {Promise<string>} - A fully qualified host URL for the recipient's MessageBox server.
188
+ *
189
+ * @description
190
+ * Attempts to resolve the most recently anointed MessageBox host for the given identity key
191
+ * using the BSV overlay network and the `ls_messagebox` LookupResolver.
192
+ *
193
+ * If no advertisements are found, or if resolution fails, the client will fall back
194
+ * to its own configured `host`. This allows seamless operation in both overlay and non-overlay environments.
195
+ *
196
+ * This method guarantees a non-null return value and should be used directly when routing messages.
197
+ *
198
+ * @example
199
+ * const host = await resolveHostForRecipient('028d...') // → returns either overlay host or this.host
200
+ */
201
+ resolveHostForRecipient(identityKey: string): Promise<string>;
202
+ /**
203
+ * Core lookup: ask the LookupResolver (optionally filtered by host),
204
+ * decode every PushDrop output, and collect all the host URLs you find.
205
+ *
206
+ * @param identityKey the recipient’s public key
207
+ * @param host? if passed, only look for adverts anointed at that host
208
+ * @returns 0-length array if nothing valid was found
209
+ */
210
+ queryAdvertisements(identityKey?: string, host?: string): Promise<AdvertisementToken[]>;
211
+ /**
212
+ * @method joinRoom
213
+ * @async
214
+ * @param {string} messageBox - The name of the WebSocket room to join (e.g., "payment_inbox").
215
+ * @returns {Promise<void>}
216
+ *
217
+ * @description
218
+ * Joins a WebSocket room that corresponds to the user’s identity key and the specified message box.
219
+ * This is required to receive real-time messages via WebSocket for a specific type of communication.
220
+ *
221
+ * If the WebSocket connection is not already established, this method will first initialize the connection.
222
+ * It also ensures the room is only joined once, and tracks all joined rooms in an internal set.
223
+ *
224
+ * Room ID format: `${identityKey}-${messageBox}`
225
+ *
226
+ * @example
227
+ * await client.joinRoom('payment_inbox')
228
+ * // Now listening for real-time messages in room '028d...-payment_inbox'
229
+ */
230
+ joinRoom(messageBox: string): Promise<void>;
231
+ /**
232
+ * @method listenForLiveMessages
233
+ * @async
234
+ * @param {Object} params - Configuration for the live message listener.
235
+ * @param {function} params.onMessage - A callback function that will be triggered when a new message arrives.
236
+ * @param {string} params.messageBox - The messageBox name (e.g., `payment_inbox`) to listen for.
237
+ * @returns {Promise<void>}
238
+ *
239
+ * @description
240
+ * Subscribes the client to live messages over WebSocket for a specific messageBox.
241
+ *
242
+ * This method:
243
+ * - Ensures the WebSocket connection is initialized and authenticated.
244
+ * - Joins the correct room formatted as `${identityKey}-${messageBox}`.
245
+ * - Listens for messages broadcast to the room.
246
+ * - Automatically attempts to parse and decrypt message bodies.
247
+ * - Emits the final message (as a `PeerMessage`) to the supplied `onMessage` handler.
248
+ *
249
+ * If the incoming message is encrypted, the client decrypts it using AES-256-GCM via
250
+ * ECDH shared secrets derived from identity keys as defined in [BRC-2](https://github.com/bitcoin-sv/BRCs/blob/master/wallet/0002.md).
251
+ * Messages sent by the client to itself are decrypted using `counterparty = 'self'`.
252
+ *
253
+ * @example
254
+ * await client.listenForLiveMessages({
255
+ * messageBox: 'payment_inbox',
256
+ * onMessage: (msg) => console.log('Received live message:', msg)
257
+ * })
258
+ */
259
+ listenForLiveMessages({ onMessage, messageBox }: {
260
+ onMessage: (message: PeerMessage) => void;
261
+ messageBox: string;
262
+ }): Promise<void>;
263
+ /**
264
+ * @method sendLiveMessage
265
+ * @async
266
+ * @param {SendMessageParams} param0 - The message parameters including recipient, box name, body, and options.
267
+ * @returns {Promise<SendMessageResponse>} A success response with the generated messageId.
268
+ *
269
+ * @description
270
+ * Sends a message in real time using WebSocket with authenticated delivery and overlay fallback.
271
+ *
272
+ * This method:
273
+ * - Ensures the WebSocket connection is open and joins the correct room.
274
+ * - Derives a unique message ID using an HMAC of the message body and counterparty identity key.
275
+ * - 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),
276
+ * unless `skipEncryption` is explicitly set to `true`.
277
+ * - Sends the message to a WebSocket room in the format `${recipient}-${messageBox}`.
278
+ * - Waits for acknowledgment (`sendMessageAck-${roomId}`).
279
+ * - If no acknowledgment is received within 10 seconds, falls back to `sendMessage()` over HTTP.
280
+ *
281
+ * This hybrid delivery strategy ensures reliability in both real-time and offline-capable environments.
282
+ *
283
+ * @throws {Error} If message validation fails, HMAC generation fails, or both WebSocket and HTTP fail to deliver.
284
+ *
285
+ * @example
286
+ * await client.sendLiveMessage({
287
+ * recipient: '028d...',
288
+ * messageBox: 'payment_inbox',
289
+ * body: { amount: 1000 }
290
+ * })
291
+ */
292
+ sendLiveMessage({ recipient, messageBox, body, messageId, skipEncryption }: SendMessageParams): Promise<SendMessageResponse>;
293
+ /**
294
+ * @method leaveRoom
295
+ * @async
296
+ * @param {string} messageBox - The name of the WebSocket room to leave (e.g., `payment_inbox`).
297
+ * @returns {Promise<void>}
298
+ *
299
+ * @description
300
+ * Leaves a previously joined WebSocket room associated with the authenticated identity key.
301
+ * This helps reduce unnecessary message traffic and memory usage.
302
+ *
303
+ * If the WebSocket is not connected or the identity key is missing, the method exits gracefully.
304
+ *
305
+ * @example
306
+ * await client.leaveRoom('payment_inbox')
307
+ */
308
+ leaveRoom(messageBox: string): Promise<void>;
309
+ /**
310
+ * @method disconnectWebSocket
311
+ * @async
312
+ * @returns {Promise<void>} Resolves when the WebSocket connection is successfully closed.
313
+ *
314
+ * @description
315
+ * Gracefully disconnects the WebSocket connection to the MessageBox server.
316
+ * This should be called when the client is shutting down, logging out, or no longer
317
+ * needs real-time communication to conserve system resources.
318
+ *
319
+ * @example
320
+ * await client.disconnectWebSocket()
321
+ */
322
+ disconnectWebSocket(): Promise<void>;
323
+ /**
324
+ * @method sendMessage
325
+ * @async
326
+ * @param {SendMessageParams} message - Contains recipient, messageBox name, message body, optional messageId, and skipEncryption flag.
327
+ * @param {string} [overrideHost] - Optional host to override overlay resolution (useful for testing or private routing).
328
+ * @returns {Promise<SendMessageResponse>} - Resolves with `{ status, messageId }` on success.
329
+ *
330
+ * @description
331
+ * Sends a message over HTTP to a recipient's messageBox. This method:
332
+ *
333
+ * - Derives a deterministic `messageId` using an HMAC of the message body and recipient key.
334
+ * - 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.
335
+ * - Automatically resolves the host via overlay LookupResolver unless an override is provided.
336
+ * - Authenticates the request using the current identity key with `AuthFetch`.
337
+ *
338
+ * This is the fallback mechanism for `sendLiveMessage` when WebSocket delivery fails.
339
+ * It is also used for message types that do not require real-time delivery.
340
+ *
341
+ * @throws {Error} If validation, encryption, HMAC, or network request fails.
342
+ *
343
+ * @example
344
+ * await client.sendMessage({
345
+ * recipient: '03abc...',
346
+ * messageBox: 'notifications',
347
+ * body: { type: 'ping' }
348
+ * })
349
+ */
350
+ sendMessage(message: SendMessageParams, overrideHost?: string): Promise<SendMessageResponse>;
351
+ /**
352
+ * @method anointHost
353
+ * @async
354
+ * @param {string} host - The full URL of the server you want to designate as your MessageBox host (e.g., "https://mybox.com").
355
+ * @returns {Promise<{ txid: string }>} - The transaction ID of the advertisement broadcast to the overlay network.
356
+ *
357
+ * @description
358
+ * Broadcasts a signed overlay advertisement using a PushDrop output under the `tm_messagebox` topic.
359
+ * This advertisement announces that the specified `host` is now authorized to receive and route
360
+ * messages for the sender’s identity key.
361
+ *
362
+ * The broadcasted message includes:
363
+ * - The identity key
364
+ * - The chosen host URL
365
+ *
366
+ * This is essential for enabling overlay-based message delivery via SHIP and LookupResolver.
367
+ * The recipient’s host must advertise itself for message routing to succeed in a decentralized manner.
368
+ *
369
+ * @throws {Error} If the URL is invalid, the PushDrop creation fails, or the overlay broadcast does not succeed.
370
+ *
371
+ * @example
372
+ * const { txid } = await client.anointHost('https://my-messagebox.io')
373
+ */
374
+ anointHost(host: string): Promise<{
375
+ txid: string;
376
+ }>;
377
+ /**
378
+ * @method revokeHostAdvertisement
379
+ * @async
380
+ * @param {AdvertisementToken} advertisementToken - The advertisement token containing the messagebox host to revoke.
381
+ * @returns {Promise<{ txid: string }>} - The transaction ID of the revocation broadcast to the overlay network.
382
+ *
383
+ * @description
384
+ * Broadcasts a signed revocation transaction indicating the advertisement token should be removed
385
+ * and no longer tracked by lookup services.
386
+ *
387
+ * @example
388
+ * const { txid } = await client.revokeHost('https://my-messagebox.io')
389
+ */
390
+ revokeHostAdvertisement(advertisementToken: AdvertisementToken): Promise<{
391
+ txid: string;
392
+ }>;
393
+ /**
394
+ * @method listMessages
395
+ * @async
396
+ * @param {ListMessagesParams} params - Contains the name of the messageBox to read from.
397
+ * @returns {Promise<PeerMessage[]>} - Returns an array of decrypted `PeerMessage` objects.
398
+ *
399
+ * @description
400
+ * Retrieves all messages from the specified `messageBox` assigned to the current identity key.
401
+ * 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.
402
+ *
403
+ * Each message is:
404
+ * - Parsed and, if encrypted, decrypted using AES-256-GCM via BRC-2-compliant ECDH key derivation and symmetric encryption.
405
+ * - Returned as a normalized `PeerMessage` with readable string body content.
406
+ *
407
+ * Decryption automatically derives a shared secret using the sender’s identity key and the receiver’s child private key.
408
+ * If the sender is the same as the recipient, the `counterparty` is set to `'self'`.
409
+ *
410
+ * @throws {Error} If no messageBox is specified, the request fails, or the server returns an error.
411
+ *
412
+ * @example
413
+ * const messages = await client.listMessages({ messageBox: 'inbox' })
414
+ * messages.forEach(msg => console.log(msg.sender, msg.body))
415
+ */
416
+ listMessages({ messageBox, host }: ListMessagesParams): Promise<PeerMessage[]>;
417
+ /**
418
+ * @method acknowledgeMessage
419
+ * @async
420
+ * @param {AcknowledgeMessageParams} params - An object containing an array of message IDs to acknowledge.
421
+ * @returns {Promise<string>} - A string indicating the result, typically `'success'`.
422
+ *
423
+ * @description
424
+ * Notifies the MessageBox server(s) that one or more messages have been
425
+ * successfully received and processed by the client. Once acknowledged, these messages are removed
426
+ * from the recipient's inbox on the server(s).
427
+ *
428
+ * This operation is essential for proper message lifecycle management and prevents duplicate
429
+ * processing or delivery.
430
+ *
431
+ * Acknowledgment supports providing a host override, or will use overlay routing to find the appropriate server the received the given message.
432
+ *
433
+ * @throws {Error} If the message ID array is missing or empty, or if the request to the server fails.
434
+ *
435
+ * @example
436
+ * await client.acknowledgeMessage({ messageIds: ['msg123', 'msg456'] })
437
+ */
438
+ acknowledgeMessage({ messageIds, host }: AcknowledgeMessageParams): Promise<string>;
439
+ }
440
+ export {};
441
+ //# sourceMappingURL=MessageBoxClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageBoxClient.d.ts","sourceRoot":"","sources":["../../../src/MessageBoxClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * PeerPayClient
3
+ *
4
+ * Extends `MessageBoxClient` to enable Bitcoin payments using the MetaNet identity system.
5
+ *
6
+ * This client handles payment token creation, message transmission over HTTP/WebSocket,
7
+ * payment reception (including acceptance and rejection logic), and listing of pending payments.
8
+ *
9
+ * It uses authenticated and encrypted message transmission to ensure secure payment flows
10
+ * between identified peers on the BSV network.
11
+ */
12
+ import { MessageBoxClient } from './MessageBoxClient.js';
13
+ import { WalletClient, AtomicBEEF, Base64String } from '@bsv/sdk';
14
+ export declare const STANDARD_PAYMENT_MESSAGEBOX = "payment_inbox";
15
+ /**
16
+ * Configuration options for initializing PeerPayClient.
17
+ */
18
+ export interface PeerPayClientConfig {
19
+ messageBoxHost?: string;
20
+ walletClient: WalletClient;
21
+ enableLogging?: boolean;
22
+ }
23
+ /**
24
+ * Represents the parameters required to initiate a payment.
25
+ */
26
+ export interface PaymentParams {
27
+ recipient: string;
28
+ amount: number;
29
+ }
30
+ /**
31
+ * Represents a structured payment token.
32
+ */
33
+ export interface PaymentToken {
34
+ customInstructions: {
35
+ derivationPrefix: Base64String;
36
+ derivationSuffix: Base64String;
37
+ };
38
+ transaction: AtomicBEEF;
39
+ amount: number;
40
+ }
41
+ /**
42
+ * Represents an incoming payment received via MessageBox.
43
+ */
44
+ export interface IncomingPayment {
45
+ messageId: string;
46
+ sender: string;
47
+ token: PaymentToken;
48
+ }
49
+ /**
50
+ * PeerPayClient enables peer-to-peer Bitcoin payments using MessageBox.
51
+ */
52
+ export declare class PeerPayClient extends MessageBoxClient {
53
+ private readonly peerPayWalletClient;
54
+ private _authFetchInstance?;
55
+ constructor(config: PeerPayClientConfig);
56
+ private get authFetchInstance();
57
+ /**
58
+ * Generates a valid payment token for a recipient.
59
+ *
60
+ * This function derives a unique public key for the recipient, constructs a P2PKH locking script,
61
+ * and creates a payment action with the specified amount.
62
+ *
63
+ * @param {PaymentParams} payment - The payment details.
64
+ * @param {string} payment.recipient - The recipient's identity key.
65
+ * @param {number} payment.amount - The amount in satoshis to send.
66
+ * @returns {Promise<PaymentToken>} A valid payment token containing transaction details.
67
+ * @throws {Error} If the recipient's public key cannot be derived.
68
+ */
69
+ createPaymentToken(payment: PaymentParams): Promise<PaymentToken>;
70
+ /**
71
+ * Sends Bitcoin to a PeerPay recipient.
72
+ *
73
+ * This function validates the payment details and delegates the transaction
74
+ * to `sendLivePayment` for processing.
75
+ *
76
+ * @param {PaymentParams} payment - The payment details.
77
+ * @param {string} payment.recipient - The recipient's identity key.
78
+ * @param {number} payment.amount - The amount in satoshis to send.
79
+ * @returns {Promise<any>} Resolves with the payment result.
80
+ * @throws {Error} If the recipient is missing or the amount is invalid.
81
+ */
82
+ sendPayment(payment: PaymentParams): Promise<any>;
83
+ /**
84
+ * Sends Bitcoin to a PeerPay recipient over WebSockets.
85
+ *
86
+ * This function generates a payment token and transmits it over WebSockets
87
+ * using `sendLiveMessage`. The recipient’s identity key is explicitly included
88
+ * to ensure proper message routing.
89
+ *
90
+ * @param {PaymentParams} payment - The payment details.
91
+ * @param {string} payment.recipient - The recipient's identity key.
92
+ * @param {number} payment.amount - The amount in satoshis to send.
93
+ * @returns {Promise<void>} Resolves when the payment has been sent.
94
+ * @throws {Error} If payment token generation fails.
95
+ */
96
+ sendLivePayment(payment: PaymentParams): Promise<void>;
97
+ /**
98
+ * Listens for incoming Bitcoin payments over WebSockets.
99
+ *
100
+ * This function listens for messages in the standard payment message box and
101
+ * converts incoming `PeerMessage` objects into `IncomingPayment` objects
102
+ * before invoking the `onPayment` callback.
103
+ *
104
+ * @param {Object} obj - The configuration object.
105
+ * @param {Function} obj.onPayment - Callback function triggered when a payment is received.
106
+ * @returns {Promise<void>} Resolves when the listener is successfully set up.
107
+ */
108
+ listenForLivePayments({ onPayment }: {
109
+ onPayment: (payment: IncomingPayment) => void;
110
+ }): Promise<void>;
111
+ /**
112
+ * Accepts an incoming Bitcoin payment and moves it into the default wallet basket.
113
+ *
114
+ * This function processes a received payment by submitting it for internalization
115
+ * using the wallet client's `internalizeAction` method. The payment details
116
+ * are extracted from the `IncomingPayment` object.
117
+ *
118
+ * @param {IncomingPayment} payment - The payment object containing transaction details.
119
+ * @returns {Promise<any>} Resolves with the payment result if successful.
120
+ * @throws {Error} If payment processing fails.
121
+ */
122
+ acceptPayment(payment: IncomingPayment): Promise<any>;
123
+ /**
124
+ * Rejects an incoming Bitcoin payment by refunding it to the sender, minus a fee.
125
+ *
126
+ * If the payment amount is too small (less than 1000 satoshis after deducting the fee),
127
+ * the payment is simply acknowledged and ignored. Otherwise, the function first accepts
128
+ * the payment, then sends a new transaction refunding the sender.
129
+ *
130
+ * @param {IncomingPayment} payment - The payment object containing transaction details.
131
+ * @returns {Promise<void>} Resolves when the payment is either acknowledged or refunded.
132
+ */
133
+ rejectPayment(payment: IncomingPayment): Promise<void>;
134
+ /**
135
+ * Retrieves a list of incoming Bitcoin payments from the message box.
136
+ *
137
+ * This function queries the message box for new messages and transforms
138
+ * them into `IncomingPayment` objects by extracting relevant fields.
139
+ *
140
+ * @returns {Promise<IncomingPayment[]>} Resolves with an array of pending payments.
141
+ */
142
+ listIncomingPayments(): Promise<IncomingPayment[]>;
143
+ }
144
+ //# sourceMappingURL=PeerPayClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PeerPayClient.d.ts","sourceRoot":"","sources":["../../../src/PeerPayClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,EAAE,YAAY,EAAiC,UAAU,EAAa,YAAY,EAAE,MAAM,UAAU,CAAA;AAc3G,eAAO,MAAM,2BAA2B,kBAAkB,CAAA;AAG1D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,YAAY,CAAA;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,kBAAkB,EAAE;QAClB,gBAAgB,EAAE,YAAY,CAAA;QAC9B,gBAAgB,EAAE,YAAY,CAAA;KAC/B,CAAA;IACD,WAAW,EAAE,UAAU,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,YAAY,CAAA;CACpB;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,gBAAgB;IACjD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAc;IAClD,OAAO,CAAC,kBAAkB,CAAC,CAAW;gBAEzB,MAAM,EAAE,mBAAmB;IASxC,OAAO,KAAK,iBAAiB,GAK5B;IAED;;;;;;;;;;;OAWG;IACG,kBAAkB,CAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAgExE;;;;;;;;;;;OAWG;IACG,WAAW,CAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC;IAexD;;;;;;;;;;;;OAYG;IACG,eAAe,CAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB7D;;;;;;;;;;OAUG;IACG,qBAAqB,CAAE,EAC3B,SAAS,EACV,EAAE;QAAE,SAAS,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBpE;;;;;;;;;;OAUG;IACG,aAAa,CAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC;IA8B5D;;;;;;;;;OASG;IACG,aAAa,CAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAoD7D;;;;;;;OAOG;IACG,oBAAoB,IAAK,OAAO,CAAC,eAAe,EAAE,CAAC;CAa1D"}
@@ -0,0 +1,9 @@
1
+ export declare class Logger {
2
+ private static isEnabled;
3
+ static enable(): void;
4
+ static disable(): void;
5
+ static log(...args: unknown[]): void;
6
+ static warn(...args: unknown[]): void;
7
+ static error(...args: unknown[]): void;
8
+ }
9
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../../src/Utils/logger.ts"],"names":[],"mappings":"AAAA,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAQ;IAEhC,MAAM,CAAC,MAAM,IAAK,IAAI;IAItB,MAAM,CAAC,OAAO,IAAK,IAAI;IAIvB,MAAM,CAAC,GAAG,CAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAMrC,MAAM,CAAC,IAAI,CAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAMtC,MAAM,CAAC,KAAK,CAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAGxC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=MessageBoxClient.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageBoxClient.test.d.ts","sourceRoot":"","sources":["../../../../src/__tests/MessageBoxClient.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=PeerPayClientUnit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PeerPayClientUnit.test.d.ts","sourceRoot":"","sources":["../../../../src/__tests/PeerPayClientUnit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=integrationEncrypted.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrationEncrypted.test.d.ts","sourceRoot":"","sources":["../../../../../src/__tests/integration/integrationEncrypted.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=integrationHTTP.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrationHTTP.test.d.ts","sourceRoot":"","sources":["../../../../../src/__tests/integration/integrationHTTP.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=integrationOverlay.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrationOverlay.test.d.ts","sourceRoot":"","sources":["../../../../../src/__tests/integration/integrationOverlay.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=integrationWS.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrationWS.test.d.ts","sourceRoot":"","sources":["../../../../../src/__tests/integration/integrationWS.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Starts the MessageBoxServer as a separate process if not already running.
3
+ */
4
+ export declare function startTestServer(): Promise<void>;
5
+ /**
6
+ * Stops the MessageBoxServer process after tests.
7
+ */
8
+ export declare function stopTestServer(): Promise<void>;
9
+ //# sourceMappingURL=testServer.d.ts.map