@bsv/message-box-client 1.1.7
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.
- package/LICENSE.txt +28 -0
- package/README.md +1013 -0
- package/mod.ts +3 -0
- package/package.json +80 -0
- package/src/MessageBoxClient.ts +1341 -0
- package/src/PeerPayClient.ts +386 -0
- package/src/Utils/logger.ts +27 -0
- package/src/__tests/MessageBoxClient.test.ts +763 -0
- package/src/__tests/PeerPayClientUnit.test.ts +245 -0
- package/src/__tests/integration/integrationEncrypted.test.ts +103 -0
- package/src/__tests/integration/integrationHTTP.test.ts +158 -0
- package/src/__tests/integration/integrationOverlay.test.ts +163 -0
- package/src/__tests/integration/integrationWS.test.ts +147 -0
- package/src/__tests/integration/testServer.ts +68 -0
- package/src/types.ts +108 -0
package/README.md
ADDED
|
@@ -0,0 +1,1013 @@
|
|
|
1
|
+
# BSV Peer-to-Peer Messaging & Payment Tools
|
|
2
|
+
|
|
3
|
+
**@bsv/message-box-client** is a toolkit for **peer-to-peer messaging and payments** on the BSV blockchain. It leverages a server-side **store-and-forward** system for message delivery (via `MessageBoxClient`) and also includes a higher-level **peer-to-peer payment** flow (via `PeerPayClient`). Both functionalities build on [BRC-103](https://github.com/bitcoin-sv/BRCs/blob/master/peer-to-peer/0103.md) for mutual authentication and identity key management, allowing secure and authenticated exchanges of data and BSV.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Introduction](#1-introduction)
|
|
8
|
+
2. [Installation](#2-installation)
|
|
9
|
+
- [Running Integration Tests](#21-running-integration-tests)
|
|
10
|
+
3. [Overview](#3-overview)
|
|
11
|
+
- [MessageBoxClient](#31-messageboxclient-overview)
|
|
12
|
+
- [PeerPayClient](#32-peerpayclient-overview)
|
|
13
|
+
4. [Quick Start Examples](#4-quick-start-examples)
|
|
14
|
+
- [Using MessageBoxClient](#41-using-messageboxclient)
|
|
15
|
+
- [Using PeerPayClient](#42-using-peerpayclient)
|
|
16
|
+
5. [API Reference](#5-api-reference)
|
|
17
|
+
- [MessageBoxClient API](#51-messageboxclient-api)
|
|
18
|
+
- [PeerPayClient API](#52-peerpayclient-api)
|
|
19
|
+
6. [Contributing](#6-contributing)
|
|
20
|
+
7. [License](#7-license)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 1. Introduction
|
|
25
|
+
|
|
26
|
+
The **@bsv/message-box-client** library provides two main tools for peer-to-peer interaction:
|
|
27
|
+
|
|
28
|
+
1. **MessageBoxClient** – A store-and-forward messaging system backed by a "message box" server. It supports authenticated sending, listing, and acknowledging (deleting) messages with a mutual-auth approach.
|
|
29
|
+
2. **PeerPayClient** – A higher-level payment client built on top of `MessageBoxClient`, enabling real-time, peer-to-peer Bitcoin payments on the BSV blockchain.
|
|
30
|
+
|
|
31
|
+
Both clients use the [BRC-103](https://github.com/bitcoin-sv/BRCs/blob/master/peer-to-peer/0103.md)-based authentication model. By integrating with a [WalletClient](https://github.com/bitcoin-sv), they can sign and verify messages, ensuring only authorized parties can send and receive.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 2. Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install @bsv/message-box-client
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The package exports both `MessageBoxClient` and `PeerPayClient`. You can import them individually in your JavaScript/TypeScript applications.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### 2.1. Running Integration Tests
|
|
46
|
+
The P2P integration tests verify live communication between the MessageBoxClient and a running instance of the MessageBox Server. To run them, make sure the following are set up:
|
|
47
|
+
|
|
48
|
+
**Prerequisites**
|
|
49
|
+
1. MessageBox Server Running Locally
|
|
50
|
+
You must have a local instance of the [MessageBox Server](https://github.com/bitcoin-sv/messagebox-server.git) running.
|
|
51
|
+
Follow these steps inside the messagebox-server project:
|
|
52
|
+
```bash
|
|
53
|
+
git clone https://github.com/bitcoin-sv/messagebox-server.git
|
|
54
|
+
cd messagebox-server
|
|
55
|
+
cp .env.example .env
|
|
56
|
+
npm install
|
|
57
|
+
npm run start # Starts LARS (overlay service on http://localhost:8080)
|
|
58
|
+
npm run dev # Starts MessageBox Server (HTTP API on http://localhost:5001)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
2. Ensure Environment Configuration
|
|
62
|
+
Your .env file in the MessageBox Server must have:
|
|
63
|
+
```bash
|
|
64
|
+
NODE_ENV=development
|
|
65
|
+
BSV_NETWORK=local
|
|
66
|
+
ENABLE_WEBSOCKETS=true
|
|
67
|
+
```
|
|
68
|
+
and valid values for:
|
|
69
|
+
- SERVER_PRIVATE_KEY
|
|
70
|
+
- WALLET_STORAGE_URL
|
|
71
|
+
- MONGO_URI and MONGO_DB
|
|
72
|
+
- (Optional) If using MySQL locally, ensure KNEX_DB_CONNECTION is properly set.
|
|
73
|
+
|
|
74
|
+
3. Wallet Storage Running (optional)
|
|
75
|
+
If your .env points to a local wallet-storage instance, make sure it is also running.
|
|
76
|
+
|
|
77
|
+
________________________________________
|
|
78
|
+
|
|
79
|
+
**Running the Tests**
|
|
80
|
+
Once the MessageBox Server and overlay service are running:
|
|
81
|
+
```bash
|
|
82
|
+
npm run test:integration
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This will execute all integration tests under src/__tests__/integration/, including HTTP, WebSocket, encryption, and overlay scenarios.
|
|
86
|
+
|
|
87
|
+
________________________________________
|
|
88
|
+
|
|
89
|
+
**Notes**
|
|
90
|
+
- If the server is not running, tests will fail with network or timeout errors.
|
|
91
|
+
- Integration tests use the local network preset (networkPreset: 'local') and assume the default MessageBox API endpoints (e.g., http://localhost:8080).
|
|
92
|
+
- Some tests may require clearing the database manually between runs if data conflicts occur.
|
|
93
|
+
- Unit tests (non-integration) still run by default with npm test. Integration tests are separated.
|
|
94
|
+
|
|
95
|
+
________________________________________
|
|
96
|
+
|
|
97
|
+
**Quick Summary**
|
|
98
|
+
- npm run test → unit tests only
|
|
99
|
+
- npm run test:integration → integration tests against a running MessageBox server
|
|
100
|
+
|
|
101
|
+
________________________________________
|
|
102
|
+
|
|
103
|
+
## 3. Overview
|
|
104
|
+
|
|
105
|
+
### 3.1. MessageBoxClient Overview
|
|
106
|
+
|
|
107
|
+
`MessageBoxClient` uses a **store-and-forward** architecture for Peer-to-Peer messages:
|
|
108
|
+
|
|
109
|
+
- **Store-and-forward:** Messages are posted to a MessageBoxServer under a named "message box" (like an inbox).
|
|
110
|
+
- **Ephemeral storage:** Once the recipient acknowledges the messages, they are removed from the server.
|
|
111
|
+
- **Mutual authentication:** Ensures only authorized peers can read or post messages, using [AuthFetch](https://github.com/bitcoin-sv/authfetch) and [AuthSocketClient](https://github.com/bitcoin-sv/authsocket).
|
|
112
|
+
- **Flexible transport:** Supports both **WebSockets** (for live, push-style delivery) and **HTTP** (for polling or fallback).
|
|
113
|
+
- **Extensible:** Can be the foundation for more advanced workflows (e.g., token-based messaging, invoice/ticket systems, etc.).
|
|
114
|
+
|
|
115
|
+
#### Key Features
|
|
116
|
+
|
|
117
|
+
1. **Secure by default** using Auth libraries for signing/verification.
|
|
118
|
+
2. **Real-time or delayed** delivery with sockets or HTTP.
|
|
119
|
+
3. **Easy integration** with higher-level protocols and services.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
#### Important: Initialization Requirement
|
|
124
|
+
|
|
125
|
+
**Important:**
|
|
126
|
+
Starting with version `@bsv/message-box-client@1.2.0`, `MessageBoxClient` **automatically initializes itself** if needed.
|
|
127
|
+
|
|
128
|
+
- If you provide a host during construction, the client will auto-initialize on first use.
|
|
129
|
+
- If no host is provided, the client will anoint a host from the overlay network automatically during initialization.
|
|
130
|
+
|
|
131
|
+
You may still **manually call** `await init()` if you want to control when initialization happens.
|
|
132
|
+
|
|
133
|
+
Example:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
const client = new MessageBoxClient({ walletClient, host: 'https://messagebox.babbage.systems' })
|
|
137
|
+
|
|
138
|
+
// Manual init (optional but supported)
|
|
139
|
+
await client.init()
|
|
140
|
+
|
|
141
|
+
// Or just start sending — init will auto-run if needed
|
|
142
|
+
await client.sendMessage({ recipient, messageBox: 'inbox', body: 'Hello' })
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Example:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
const client = new MessageBoxClient({ walletClient, host: 'https://messagebox.babbage.systems' })
|
|
149
|
+
await client.init() // Must always call init() before using the client
|
|
150
|
+
await client.sendMessage({ recipient, messageBox: 'inbox', body: 'Hello' })
|
|
151
|
+
```
|
|
152
|
+
The `init()` method will:
|
|
153
|
+
|
|
154
|
+
- Anoint your messagebox host onto the overlay network if necessary.
|
|
155
|
+
|
|
156
|
+
- Initialize the client’s internal identity and network information.
|
|
157
|
+
|
|
158
|
+
- Ensure that your client can receive messages securely from peers.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### 3.2. PeerPayClient Overview
|
|
163
|
+
|
|
164
|
+
`PeerPayClient` builds on `MessageBoxClient` to enable **peer-to-peer Bitcoin payments**:
|
|
165
|
+
|
|
166
|
+
- **Secure Payment Delivery:** Utilizes the same store-and-forward or live WebSocket approach for delivering payment instructions.
|
|
167
|
+
- **Derivation & Signing:** Creates a unique output script for each payment, derived from sender + recipient keys.
|
|
168
|
+
- **Live or Delayed:** Works with web sockets for immediate notifications, or HTTP for an asynchronous flow.
|
|
169
|
+
- **Wallet Integration:** Accept or reject incoming payments. If accepted, the payment is “internalized” into your [BRC-100](https://github.com/bitcoin-sv/BRCs/blob/master/wallet/0100.md) compatible wallet automatically.
|
|
170
|
+
|
|
171
|
+
#### Key Features
|
|
172
|
+
|
|
173
|
+
1. **Deterministic derivation** of payment information using the SPV-compliant [BRC-29](https://github.com/bitcoin-sv/BRCs/blob/master/payments/0029.md) protocol.
|
|
174
|
+
2. **Secure transaction passing** using the `MessageBoxClient` infrastructure.
|
|
175
|
+
3. **Live or offline** support for receiving payments.
|
|
176
|
+
4. **Easy acceptance/refunds** with built-in methods.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 4. Quick Start Examples
|
|
181
|
+
|
|
182
|
+
Below are two condensed examples: one for basic messaging (MessageBoxClient) and another for peer-to-peer payments (PeerPayClient).
|
|
183
|
+
|
|
184
|
+
### 4.1. Using MessageBoxClient
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
const { WalletClient } = require('@bsv/sdk')
|
|
188
|
+
const { MessageBoxClient } = require('@bsv/message-box-client')
|
|
189
|
+
|
|
190
|
+
// Example identity key of the recipient (public key in hex)
|
|
191
|
+
const johnSmithKey = '022600d2ef37d123fdcac7d25d7a464ada7acd3fb65a0daf85412140ee20884311'
|
|
192
|
+
|
|
193
|
+
async function main() {
|
|
194
|
+
// 1) Create your WalletClient (this obtains your identity key)
|
|
195
|
+
const myWallet = new WalletClient()
|
|
196
|
+
|
|
197
|
+
// 2) Create a MessageBoxClient, pointing to a MessageBoxServer
|
|
198
|
+
const msgBoxClient = new MessageBoxClient({
|
|
199
|
+
host: 'https://messagebox.babbage.systems',
|
|
200
|
+
walletClient: myWallet
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
// 3) (Optional) Initialize the client manually
|
|
204
|
+
await msgBoxClient.init()
|
|
205
|
+
|
|
206
|
+
// (Optional) Initialize a WebSocket connection (for real-time listening)
|
|
207
|
+
await msgBoxClient.initializeConnection()
|
|
208
|
+
|
|
209
|
+
// 4) Send a message to John's "demo_inbox"
|
|
210
|
+
await msgBoxClient.sendMessage({
|
|
211
|
+
recipient: johnSmithKey,
|
|
212
|
+
messageBox: 'demo_inbox',
|
|
213
|
+
body: 'Hello John! This is a test message.'
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
// 5) List messages in "demo_inbox"
|
|
217
|
+
const messages = await msgBoxClient.listMessages({ messageBox: 'demo_inbox' })
|
|
218
|
+
console.log(messages[0].body) // --> "Hello John! This is a test message."
|
|
219
|
+
|
|
220
|
+
// 6) Acknowledge (and delete) them from the server
|
|
221
|
+
await msgBoxClient.acknowledgeMessage({
|
|
222
|
+
messageIds: messages.map(msg => msg.messageId.toString())
|
|
223
|
+
})
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
main().catch(console.error)
|
|
227
|
+
```
|
|
228
|
+
Note:
|
|
229
|
+
- If you do not manually call `await init()`, the client will automatically initialize itself when you use it.
|
|
230
|
+
- You can still call `await init()` manually if you want explicit control.
|
|
231
|
+
- `init()` ensures your identity is properly registered and discoverable via overlay advertisement if necessary.
|
|
232
|
+
|
|
233
|
+
**Listening for Live Messages**
|
|
234
|
+
If you want push-style message notifications instead of polling:
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
await msgBoxClient.listenForLiveMessages({
|
|
238
|
+
messageBox: 'demo_inbox',
|
|
239
|
+
onMessage: (msg) => {
|
|
240
|
+
console.log('Received live message in "demo_inbox":', msg.body)
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### 4.2. Using PeerPayClient
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
import { WalletClient } from '@bsv/sdk'
|
|
251
|
+
import { PeerPayClient } from '@bsv/message-box-client'
|
|
252
|
+
|
|
253
|
+
async function paymentDemo() {
|
|
254
|
+
// 1) Create your wallet instance
|
|
255
|
+
const wallet = new WalletClient()
|
|
256
|
+
|
|
257
|
+
// 2) Create a PeerPayClient
|
|
258
|
+
const peerPay = new PeerPayClient({
|
|
259
|
+
walletClient: wallet
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
// 3) (Optional) Listen for incoming payments
|
|
263
|
+
await peerPay.listenForLivePayments({
|
|
264
|
+
onPayment: async (payment) => {
|
|
265
|
+
console.log('Received payment:', payment)
|
|
266
|
+
// Accept it into the wallet
|
|
267
|
+
await peerPay.acceptPayment(payment)
|
|
268
|
+
}
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
// 4) Send a payment of 50,000 sats to the recipient
|
|
272
|
+
await peerPay.sendLivePayment({
|
|
273
|
+
recipient: '0277a2b...e3f4', // recipient's public key
|
|
274
|
+
amount: 50000
|
|
275
|
+
})
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
paymentDemo().catch(console.error)
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Note:** `sendLivePayment` will try WebSocket first and fall back to HTTP if unavailable.
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## 5. API Reference
|
|
286
|
+
|
|
287
|
+
```md
|
|
288
|
+
### 5.1. MessageBoxClient API
|
|
289
|
+
<!--#region ts2md-api-merged-here-->
|
|
290
|
+
|
|
291
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
292
|
+
|
|
293
|
+
##### Interfaces
|
|
294
|
+
|
|
295
|
+
| |
|
|
296
|
+
| --- |
|
|
297
|
+
| [AcknowledgeMessageParams](#interface-acknowledgemessageparams) |
|
|
298
|
+
| [EncryptedMessage](#interface-encryptedmessage) |
|
|
299
|
+
| [ListMessagesParams](#interface-listmessagesparams) |
|
|
300
|
+
| [MessageBoxClientOptions](#interface-messageboxclientoptions) |
|
|
301
|
+
| [PeerMessage](#interface-peermessage) |
|
|
302
|
+
| [SendMessageParams](#interface-sendmessageparams) |
|
|
303
|
+
| [SendMessageResponse](#interface-sendmessageresponse) |
|
|
304
|
+
|
|
305
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
###### Interface: AcknowledgeMessageParams
|
|
310
|
+
|
|
311
|
+
Defines the structure of a request to acknowledge messages.
|
|
312
|
+
|
|
313
|
+
Example
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
{
|
|
317
|
+
messageIds: ["abc123", "def456"]
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
export interface AcknowledgeMessageParams {
|
|
323
|
+
messageIds: string[];
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
###### Interface: EncryptedMessage
|
|
331
|
+
|
|
332
|
+
Encapsulates an AES-256-GCM encrypted message body.
|
|
333
|
+
|
|
334
|
+
Used when transmitting encrypted payloads to the MessageBox server.
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
export interface EncryptedMessage {
|
|
338
|
+
encryptedMessage: Base64String;
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
###### Interface: ListMessagesParams
|
|
346
|
+
|
|
347
|
+
Defines the structure of a request to list messages.
|
|
348
|
+
|
|
349
|
+
Example
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
{
|
|
353
|
+
messageBox: "payment_inbox"
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
```ts
|
|
358
|
+
export interface ListMessagesParams {
|
|
359
|
+
messageBox: string;
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
###### Interface: MessageBoxClientOptions
|
|
367
|
+
|
|
368
|
+
Configuration options for initializing a MessageBoxClient.
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
export interface MessageBoxClientOptions {
|
|
372
|
+
walletClient?: WalletClient;
|
|
373
|
+
host?: string;
|
|
374
|
+
enableLogging?: boolean;
|
|
375
|
+
networkPreset?: "local" | "mainnet" | "testnet";
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
<details>
|
|
380
|
+
|
|
381
|
+
<summary>Interface MessageBoxClientOptions Details</summary>
|
|
382
|
+
|
|
383
|
+
####### Property enableLogging
|
|
384
|
+
|
|
385
|
+
If true, enables detailed logging to the console.
|
|
386
|
+
|
|
387
|
+
```ts
|
|
388
|
+
enableLogging?: boolean
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
####### Property host
|
|
392
|
+
|
|
393
|
+
Base URL of the MessageBox server.
|
|
394
|
+
|
|
395
|
+
```ts
|
|
396
|
+
host?: string
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
####### Property networkPreset
|
|
400
|
+
|
|
401
|
+
Overlay network preset for routing resolution.
|
|
402
|
+
|
|
403
|
+
```ts
|
|
404
|
+
networkPreset?: "local" | "mainnet" | "testnet"
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
####### Property walletClient
|
|
408
|
+
|
|
409
|
+
Wallet instance used for auth, identity, and encryption.
|
|
410
|
+
If not provided, a new WalletClient will be created.
|
|
411
|
+
|
|
412
|
+
```ts
|
|
413
|
+
walletClient?: WalletClient
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
</details>
|
|
417
|
+
|
|
418
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
###### Interface: PeerMessage
|
|
422
|
+
|
|
423
|
+
Represents a decrypted message received from a MessageBox.
|
|
424
|
+
Includes metadata such as sender identity, timestamps, and optional acknowledgment status.
|
|
425
|
+
|
|
426
|
+
Used in both HTTP and WebSocket message retrieval responses.
|
|
427
|
+
|
|
428
|
+
```ts
|
|
429
|
+
export interface PeerMessage {
|
|
430
|
+
messageId: string;
|
|
431
|
+
body: string;
|
|
432
|
+
sender: string;
|
|
433
|
+
created_at: string;
|
|
434
|
+
updated_at: string;
|
|
435
|
+
acknowledged?: boolean;
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
###### Interface: SendMessageParams
|
|
443
|
+
|
|
444
|
+
Parameters required to send a message.
|
|
445
|
+
Message content may be a string or object, and encryption is enabled by default.
|
|
446
|
+
|
|
447
|
+
Example
|
|
448
|
+
|
|
449
|
+
```ts
|
|
450
|
+
{
|
|
451
|
+
recipient: "03abc...",
|
|
452
|
+
messageBox: "payment_inbox",
|
|
453
|
+
body: { type: "ping" },
|
|
454
|
+
skipEncryption: false
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
```ts
|
|
459
|
+
export interface SendMessageParams {
|
|
460
|
+
recipient: string;
|
|
461
|
+
messageBox: string;
|
|
462
|
+
body: string | object;
|
|
463
|
+
messageId?: string;
|
|
464
|
+
skipEncryption?: boolean;
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
###### Interface: SendMessageResponse
|
|
472
|
+
|
|
473
|
+
Server response structure for successful message delivery.
|
|
474
|
+
|
|
475
|
+
Returned by both `sendMessage` and `sendLiveMessage`.
|
|
476
|
+
|
|
477
|
+
```ts
|
|
478
|
+
export interface SendMessageResponse {
|
|
479
|
+
status: string;
|
|
480
|
+
messageId: string;
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
##### Classes
|
|
488
|
+
|
|
489
|
+
| |
|
|
490
|
+
| --- |
|
|
491
|
+
| [Logger](#class-logger) |
|
|
492
|
+
| [MessageBoxClient](#class-messageboxclient) |
|
|
493
|
+
|
|
494
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
###### Class: Logger
|
|
499
|
+
|
|
500
|
+
```ts
|
|
501
|
+
export class Logger {
|
|
502
|
+
static enable(): void
|
|
503
|
+
static disable(): void
|
|
504
|
+
static log(...args: unknown[]): void
|
|
505
|
+
static warn(...args: unknown[]): void
|
|
506
|
+
static error(...args: unknown[]): void
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
###### Class: MessageBoxClient
|
|
514
|
+
|
|
515
|
+
Example
|
|
516
|
+
|
|
517
|
+
```ts
|
|
518
|
+
const client = new MessageBoxClient({ walletClient, enableLogging: true })
|
|
519
|
+
// Manual init is optional — client will auto-initialize if needed
|
|
520
|
+
await client.init()
|
|
521
|
+
await client.sendMessage({ recipient, messageBox: 'payment_inbox', body: 'Hello world' })
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
```ts
|
|
525
|
+
export class MessageBoxClient {
|
|
526
|
+
public readonly authFetch: AuthFetch;
|
|
527
|
+
constructor(options: MessageBoxClientOptions = {})
|
|
528
|
+
async init(targetHost: string = this.host): Promise<void>
|
|
529
|
+
public getJoinedRooms(): Set<string>
|
|
530
|
+
public async getIdentityKey(): Promise<string>
|
|
531
|
+
public get testSocket(): ReturnType<typeof AuthSocketClient> | undefined
|
|
532
|
+
async initializeConnection(): Promise<void>
|
|
533
|
+
async resolveHostForRecipient(identityKey: string): Promise<string>
|
|
534
|
+
async joinRoom(messageBox: string): Promise<void>
|
|
535
|
+
async listenForLiveMessages({ onMessage, messageBox }: {
|
|
536
|
+
onMessage: (message: PeerMessage) => void;
|
|
537
|
+
messageBox: string;
|
|
538
|
+
}): Promise<void>
|
|
539
|
+
async sendLiveMessage({ recipient, messageBox, body, messageId, skipEncryption }: SendMessageParams): Promise<SendMessageResponse>
|
|
540
|
+
async leaveRoom(messageBox: string): Promise<void>
|
|
541
|
+
async disconnectWebSocket(): Promise<void>
|
|
542
|
+
async sendMessage(message: SendMessageParams, overrideHost?: string): Promise<SendMessageResponse>
|
|
543
|
+
async anointHost(host: string): Promise<{
|
|
544
|
+
txid: string;
|
|
545
|
+
}>
|
|
546
|
+
async listMessages({ messageBox }: ListMessagesParams): Promise<PeerMessage[]>
|
|
547
|
+
async acknowledgeMessage({ messageIds }: AcknowledgeMessageParams): Promise<string>
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
See also: [AcknowledgeMessageParams](#interface-acknowledgemessageparams), [ListMessagesParams](#interface-listmessagesparams), [MessageBoxClientOptions](#interface-messageboxclientoptions), [PeerMessage](#interface-peermessage), [SendMessageParams](#interface-sendmessageparams), [SendMessageResponse](#interface-sendmessageresponse)
|
|
552
|
+
|
|
553
|
+
<details>
|
|
554
|
+
|
|
555
|
+
<summary>Class MessageBoxClient Details</summary>
|
|
556
|
+
|
|
557
|
+
####### Constructor
|
|
558
|
+
|
|
559
|
+
```ts
|
|
560
|
+
constructor(options: MessageBoxClientOptions = {})
|
|
561
|
+
```
|
|
562
|
+
See also: [MessageBoxClientOptions](#interface-messageboxclientoptions)
|
|
563
|
+
|
|
564
|
+
Argument Details
|
|
565
|
+
|
|
566
|
+
+ **options**
|
|
567
|
+
+ Initialization options for the MessageBoxClient.
|
|
568
|
+
|
|
569
|
+
Example
|
|
570
|
+
|
|
571
|
+
```ts
|
|
572
|
+
const client = new MessageBoxClient({
|
|
573
|
+
host: 'https://messagebox.example',
|
|
574
|
+
walletClient,
|
|
575
|
+
enableLogging: true,
|
|
576
|
+
networkPreset: 'testnet'
|
|
577
|
+
})
|
|
578
|
+
await client.init()
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
####### Method acknowledgeMessage
|
|
582
|
+
|
|
583
|
+
```ts
|
|
584
|
+
async acknowledgeMessage({ messageIds }: AcknowledgeMessageParams): Promise<string>
|
|
585
|
+
```
|
|
586
|
+
See also: [AcknowledgeMessageParams](#interface-acknowledgemessageparams)
|
|
587
|
+
|
|
588
|
+
Returns
|
|
589
|
+
|
|
590
|
+
- A string indicating the result, typically `'success'`.
|
|
591
|
+
|
|
592
|
+
Argument Details
|
|
593
|
+
|
|
594
|
+
+ **params**
|
|
595
|
+
+ An object containing an array of message IDs to acknowledge.
|
|
596
|
+
|
|
597
|
+
Throws
|
|
598
|
+
|
|
599
|
+
If the message ID array is missing or empty, or if the request to the server fails.
|
|
600
|
+
|
|
601
|
+
Example
|
|
602
|
+
|
|
603
|
+
```ts
|
|
604
|
+
await client.acknowledgeMessage({ messageIds: ['msg123', 'msg456'] })
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
####### Method anointHost
|
|
608
|
+
|
|
609
|
+
```ts
|
|
610
|
+
async anointHost(host: string): Promise<{
|
|
611
|
+
txid: string;
|
|
612
|
+
}>
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
Returns
|
|
616
|
+
|
|
617
|
+
- The transaction ID of the advertisement broadcast to the overlay network.
|
|
618
|
+
|
|
619
|
+
Argument Details
|
|
620
|
+
|
|
621
|
+
+ **host**
|
|
622
|
+
+ The full URL of the server you want to designate as your MessageBox host (e.g., "https://mybox.com").
|
|
623
|
+
|
|
624
|
+
Throws
|
|
625
|
+
|
|
626
|
+
If the URL is invalid, the PushDrop creation fails, or the overlay broadcast does not succeed.
|
|
627
|
+
|
|
628
|
+
Example
|
|
629
|
+
|
|
630
|
+
```ts
|
|
631
|
+
const { txid } = await client.anointHost('https://my-messagebox.io')
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
####### Method disconnectWebSocket
|
|
635
|
+
|
|
636
|
+
```ts
|
|
637
|
+
async disconnectWebSocket(): Promise<void>
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
Returns
|
|
641
|
+
|
|
642
|
+
Resolves when the WebSocket connection is successfully closed.
|
|
643
|
+
|
|
644
|
+
Example
|
|
645
|
+
|
|
646
|
+
```ts
|
|
647
|
+
await client.disconnectWebSocket()
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
####### Method getIdentityKey
|
|
651
|
+
|
|
652
|
+
```ts
|
|
653
|
+
public async getIdentityKey(): Promise<string>
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
Returns
|
|
657
|
+
|
|
658
|
+
The identity public key of the user
|
|
659
|
+
|
|
660
|
+
####### Method getJoinedRooms
|
|
661
|
+
|
|
662
|
+
```ts
|
|
663
|
+
public getJoinedRooms(): Set<string>
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
Returns
|
|
667
|
+
|
|
668
|
+
A set of currently joined WebSocket room IDs
|
|
669
|
+
|
|
670
|
+
####### Method init
|
|
671
|
+
|
|
672
|
+
```ts
|
|
673
|
+
async init(targetHost: string = this.host): Promise<void>
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
Argument Details
|
|
677
|
+
|
|
678
|
+
+ **targetHost**
|
|
679
|
+
+ Optional host to set or override the default host.
|
|
680
|
+
|
|
681
|
+
Throws
|
|
682
|
+
|
|
683
|
+
If no valid host is provided, or anointing fails.
|
|
684
|
+
|
|
685
|
+
Example
|
|
686
|
+
|
|
687
|
+
```ts
|
|
688
|
+
const client = new MessageBoxClient({ host: 'https://mybox.example', walletClient })
|
|
689
|
+
await client.init()
|
|
690
|
+
await client.sendMessage({ recipient, messageBox: 'inbox', body: 'Hello' })
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
####### Method initializeConnection
|
|
694
|
+
|
|
695
|
+
```ts
|
|
696
|
+
async initializeConnection(): Promise<void>
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
Throws
|
|
700
|
+
|
|
701
|
+
If the identity key is unavailable or authentication fails
|
|
702
|
+
|
|
703
|
+
Example
|
|
704
|
+
|
|
705
|
+
```ts
|
|
706
|
+
const mb = new MessageBoxClient({ walletClient })
|
|
707
|
+
await mb.initializeConnection()
|
|
708
|
+
// WebSocket is now ready for use
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
####### Method joinRoom
|
|
712
|
+
|
|
713
|
+
```ts
|
|
714
|
+
async joinRoom(messageBox: string): Promise<void>
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
Argument Details
|
|
718
|
+
|
|
719
|
+
+ **messageBox**
|
|
720
|
+
+ The name of the WebSocket room to join (e.g., "payment_inbox").
|
|
721
|
+
|
|
722
|
+
Example
|
|
723
|
+
|
|
724
|
+
```ts
|
|
725
|
+
await client.joinRoom('payment_inbox')
|
|
726
|
+
// Now listening for real-time messages in room '028d...-payment_inbox'
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
####### Method leaveRoom
|
|
730
|
+
|
|
731
|
+
```ts
|
|
732
|
+
async leaveRoom(messageBox: string): Promise<void>
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
Argument Details
|
|
736
|
+
|
|
737
|
+
+ **messageBox**
|
|
738
|
+
+ The name of the WebSocket room to leave (e.g., `payment_inbox`).
|
|
739
|
+
|
|
740
|
+
Example
|
|
741
|
+
|
|
742
|
+
```ts
|
|
743
|
+
await client.leaveRoom('payment_inbox')
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
####### Method listMessages
|
|
747
|
+
|
|
748
|
+
```ts
|
|
749
|
+
async listMessages({ messageBox }: ListMessagesParams): Promise<PeerMessage[]>
|
|
750
|
+
```
|
|
751
|
+
See also: [ListMessagesParams](#interface-listmessagesparams), [PeerMessage](#interface-peermessage)
|
|
752
|
+
|
|
753
|
+
Returns
|
|
754
|
+
|
|
755
|
+
- Returns an array of decrypted `PeerMessage` objects.
|
|
756
|
+
|
|
757
|
+
Argument Details
|
|
758
|
+
|
|
759
|
+
+ **params**
|
|
760
|
+
+ Contains the name of the messageBox to read from.
|
|
761
|
+
|
|
762
|
+
Throws
|
|
763
|
+
|
|
764
|
+
If no messageBox is specified, the request fails, or the server returns an error.
|
|
765
|
+
|
|
766
|
+
Example
|
|
767
|
+
|
|
768
|
+
```ts
|
|
769
|
+
const messages = await client.listMessages({ messageBox: 'inbox' })
|
|
770
|
+
messages.forEach(msg => console.log(msg.sender, msg.body))
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
####### Method listenForLiveMessages
|
|
774
|
+
|
|
775
|
+
```ts
|
|
776
|
+
async listenForLiveMessages({ onMessage, messageBox }: {
|
|
777
|
+
onMessage: (message: PeerMessage) => void;
|
|
778
|
+
messageBox: string;
|
|
779
|
+
}): Promise<void>
|
|
780
|
+
```
|
|
781
|
+
See also: [PeerMessage](#interface-peermessage)
|
|
782
|
+
|
|
783
|
+
Argument Details
|
|
784
|
+
|
|
785
|
+
+ **params**
|
|
786
|
+
+ Configuration for the live message listener.
|
|
787
|
+
|
|
788
|
+
Example
|
|
789
|
+
|
|
790
|
+
```ts
|
|
791
|
+
await client.listenForLiveMessages({
|
|
792
|
+
messageBox: 'payment_inbox',
|
|
793
|
+
onMessage: (msg) => console.log('Received live message:', msg)
|
|
794
|
+
})
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
####### Method resolveHostForRecipient
|
|
798
|
+
|
|
799
|
+
```ts
|
|
800
|
+
async resolveHostForRecipient(identityKey: string): Promise<string>
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
Returns
|
|
804
|
+
|
|
805
|
+
- A fully qualified host URL for the recipient's MessageBox server.
|
|
806
|
+
|
|
807
|
+
Argument Details
|
|
808
|
+
|
|
809
|
+
+ **identityKey**
|
|
810
|
+
+ The public identity key of the intended recipient.
|
|
811
|
+
|
|
812
|
+
Example
|
|
813
|
+
|
|
814
|
+
```ts
|
|
815
|
+
const host = await resolveHostForRecipient('028d...') // → returns either overlay host or this.host
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
####### Method sendLiveMessage
|
|
819
|
+
|
|
820
|
+
```ts
|
|
821
|
+
async sendLiveMessage({ recipient, messageBox, body, messageId, skipEncryption }: SendMessageParams): Promise<SendMessageResponse>
|
|
822
|
+
```
|
|
823
|
+
See also: [SendMessageParams](#interface-sendmessageparams), [SendMessageResponse](#interface-sendmessageresponse)
|
|
824
|
+
|
|
825
|
+
Returns
|
|
826
|
+
|
|
827
|
+
A success response with the generated messageId.
|
|
828
|
+
|
|
829
|
+
Argument Details
|
|
830
|
+
|
|
831
|
+
+ **param0**
|
|
832
|
+
+ The message parameters including recipient, box name, body, and options.
|
|
833
|
+
|
|
834
|
+
Throws
|
|
835
|
+
|
|
836
|
+
If message validation fails, HMAC generation fails, or both WebSocket and HTTP fail to deliver.
|
|
837
|
+
|
|
838
|
+
Example
|
|
839
|
+
|
|
840
|
+
```ts
|
|
841
|
+
await client.sendLiveMessage({
|
|
842
|
+
recipient: '028d...',
|
|
843
|
+
messageBox: 'payment_inbox',
|
|
844
|
+
body: { amount: 1000 }
|
|
845
|
+
})
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
####### Method sendMessage
|
|
849
|
+
|
|
850
|
+
```ts
|
|
851
|
+
async sendMessage(message: SendMessageParams, overrideHost?: string): Promise<SendMessageResponse>
|
|
852
|
+
```
|
|
853
|
+
See also: [SendMessageParams](#interface-sendmessageparams), [SendMessageResponse](#interface-sendmessageresponse)
|
|
854
|
+
|
|
855
|
+
Returns
|
|
856
|
+
|
|
857
|
+
- Resolves with `{ status, messageId }` on success.
|
|
858
|
+
|
|
859
|
+
Argument Details
|
|
860
|
+
|
|
861
|
+
+ **message**
|
|
862
|
+
+ Contains recipient, messageBox name, message body, optional messageId, and skipEncryption flag.
|
|
863
|
+
+ **overrideHost**
|
|
864
|
+
+ Optional host to override overlay resolution (useful for testing or private routing).
|
|
865
|
+
|
|
866
|
+
Throws
|
|
867
|
+
|
|
868
|
+
If validation, encryption, HMAC, or network request fails.
|
|
869
|
+
|
|
870
|
+
Example
|
|
871
|
+
|
|
872
|
+
```ts
|
|
873
|
+
await client.sendMessage({
|
|
874
|
+
recipient: '03abc...',
|
|
875
|
+
messageBox: 'notifications',
|
|
876
|
+
body: { type: 'ping' }
|
|
877
|
+
})
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
</details>
|
|
881
|
+
|
|
882
|
+
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes)
|
|
883
|
+
|
|
884
|
+
---
|
|
885
|
+
|
|
886
|
+
<!--#endregion ts2md-api-merged-here-->
|
|
887
|
+
---
|
|
888
|
+
|
|
889
|
+
### 5.2. PeerPayClient API
|
|
890
|
+
|
|
891
|
+
```ts
|
|
892
|
+
import { PeerPayClient } from '@bsv/message-box-client'
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
#### Constructor
|
|
896
|
+
|
|
897
|
+
```ts
|
|
898
|
+
new PeerPayClient({
|
|
899
|
+
walletClient: WalletClient,
|
|
900
|
+
messageBoxHost?: string,
|
|
901
|
+
enableLogging?: boolean
|
|
902
|
+
})
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
- **walletClient**: (Required) Your identity/signing wallet.
|
|
906
|
+
- **messageBoxHost**: (Optional) Base URL of the MessageBoxServer. Defaults to `https://messagebox.babbage.systems`.
|
|
907
|
+
- **enableLogging**: (Optional) Enables verbose debug output.
|
|
908
|
+
|
|
909
|
+
---
|
|
910
|
+
|
|
911
|
+
#### `sendPayment({ recipient, amount })`
|
|
912
|
+
|
|
913
|
+
```ts
|
|
914
|
+
await peerPay.sendPayment({
|
|
915
|
+
recipient: '0277a2b...',
|
|
916
|
+
amount: 10000
|
|
917
|
+
})
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
- Sends a payment using HTTP.
|
|
921
|
+
- Internally derives a public key for the recipient and builds a transaction.
|
|
922
|
+
|
|
923
|
+
---
|
|
924
|
+
|
|
925
|
+
#### `sendLivePayment({ recipient, amount })`
|
|
926
|
+
|
|
927
|
+
```ts
|
|
928
|
+
await peerPay.sendLivePayment({
|
|
929
|
+
recipient: '0277a2b...',
|
|
930
|
+
amount: 15000
|
|
931
|
+
})
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
- Sends a payment using WebSockets, falling back to HTTP if needed.
|
|
935
|
+
|
|
936
|
+
---
|
|
937
|
+
|
|
938
|
+
#### `listenForLivePayments({ onPayment })`
|
|
939
|
+
|
|
940
|
+
```ts
|
|
941
|
+
await peerPay.listenForLivePayments({
|
|
942
|
+
onPayment: (payment) => {
|
|
943
|
+
console.log('New live payment:', payment)
|
|
944
|
+
}
|
|
945
|
+
})
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
- Subscribes to live payments in the `payment_inbox`.
|
|
949
|
+
- Invokes `onPayment` callback with an `IncomingPayment` object:
|
|
950
|
+
|
|
951
|
+
```ts
|
|
952
|
+
interface IncomingPayment {
|
|
953
|
+
messageId: number;
|
|
954
|
+
sender: string;
|
|
955
|
+
token: {
|
|
956
|
+
customInstructions: {
|
|
957
|
+
derivationPrefix: string;
|
|
958
|
+
derivationSuffix: string;
|
|
959
|
+
};
|
|
960
|
+
transaction: any; // typically your BSV transaction format
|
|
961
|
+
amount: number;
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
---
|
|
967
|
+
|
|
968
|
+
#### `acceptPayment(payment)`
|
|
969
|
+
|
|
970
|
+
```ts
|
|
971
|
+
await peerPay.acceptPayment(payment)
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
- Accepts (and "internalizes") the payment into your wallet.
|
|
975
|
+
- Acknowledges the message, removing it from the inbox.
|
|
976
|
+
|
|
977
|
+
---
|
|
978
|
+
|
|
979
|
+
#### `rejectPayment(payment)`
|
|
980
|
+
|
|
981
|
+
```ts
|
|
982
|
+
await peerPay.rejectPayment(payment)
|
|
983
|
+
```
|
|
984
|
+
|
|
985
|
+
- Rejects the payment, returning a **refund** to the sender (minus a small fee, e.g. 1000 sats).
|
|
986
|
+
- If the amount is too small to refund, the payment is simply acknowledged and dropped.
|
|
987
|
+
|
|
988
|
+
---
|
|
989
|
+
|
|
990
|
+
#### `listIncomingPayments()`
|
|
991
|
+
|
|
992
|
+
```ts
|
|
993
|
+
const payments = await peerPay.listIncomingPayments()
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
- Lists all incoming payments in the `payment_inbox`.
|
|
997
|
+
- Returns an array of `IncomingPayment` objects.
|
|
998
|
+
|
|
999
|
+
---
|
|
1000
|
+
|
|
1001
|
+
## 6. Contributing
|
|
1002
|
+
|
|
1003
|
+
1. Clone this repository.
|
|
1004
|
+
2. Install dependencies with `npm install`.
|
|
1005
|
+
3. Make your changes, write tests, and open a PR.
|
|
1006
|
+
|
|
1007
|
+
We welcome bug reports, feature requests, and community contributions!
|
|
1008
|
+
|
|
1009
|
+
---
|
|
1010
|
+
|
|
1011
|
+
## 7. License
|
|
1012
|
+
|
|
1013
|
+
This code is licensed under the [Open BSV License](https://www.bsvlicense.org/). See [LICENSE](./LICENSE) for details.
|