@bsv/message-box-client 2.0.6 → 2.0.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.
Files changed (32) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/PeerPayClient.js +405 -5
  3. package/dist/cjs/src/PeerPayClient.js.map +1 -1
  4. package/dist/cjs/src/__tests/PeerPayClientRequestIntegration.test.js +317 -0
  5. package/dist/cjs/src/__tests/PeerPayClientRequestIntegration.test.js.map +1 -0
  6. package/dist/cjs/src/__tests/PeerPayClientUnit.test.js +505 -1
  7. package/dist/cjs/src/__tests/PeerPayClientUnit.test.js.map +1 -1
  8. package/dist/cjs/src/types.js +5 -0
  9. package/dist/cjs/src/types.js.map +1 -1
  10. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  11. package/dist/esm/src/PeerPayClient.js +401 -5
  12. package/dist/esm/src/PeerPayClient.js.map +1 -1
  13. package/dist/esm/src/__tests/PeerPayClientRequestIntegration.test.js +312 -0
  14. package/dist/esm/src/__tests/PeerPayClientRequestIntegration.test.js.map +1 -0
  15. package/dist/esm/src/__tests/PeerPayClientUnit.test.js +505 -1
  16. package/dist/esm/src/__tests/PeerPayClientUnit.test.js.map +1 -1
  17. package/dist/esm/src/types.js +4 -1
  18. package/dist/esm/src/types.js.map +1 -1
  19. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  20. package/dist/types/src/PeerPayClient.d.ts +159 -0
  21. package/dist/types/src/PeerPayClient.d.ts.map +1 -1
  22. package/dist/types/src/__tests/PeerPayClientRequestIntegration.test.d.ts +10 -0
  23. package/dist/types/src/__tests/PeerPayClientRequestIntegration.test.d.ts.map +1 -0
  24. package/dist/types/src/types.d.ts +88 -0
  25. package/dist/types/src/types.d.ts.map +1 -1
  26. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  27. package/dist/umd/bundle.js +1 -1
  28. package/package.json +1 -1
  29. package/src/PeerPayClient.ts +460 -9
  30. package/src/__tests/PeerPayClientRequestIntegration.test.ts +364 -0
  31. package/src/__tests/PeerPayClientUnit.test.ts +594 -1
  32. package/src/types.ts +95 -0
@@ -0,0 +1,312 @@
1
+ /* eslint-env jest */
2
+ /**
3
+ * Integration tests for the PeerPayClient payment request flow.
4
+ *
5
+ * Uses a MockMessageBus to simulate the MessageBox server in memory,
6
+ * wiring the PeerPayClient methods (sendMessage, listMessages, acknowledgeMessage,
7
+ * getIdentityKey) to the mock bus so that full round-trip flows can be tested
8
+ * without hitting a real server.
9
+ */
10
+ import { PeerPayClient, PAYMENT_REQUESTS_MESSAGEBOX, PAYMENT_REQUEST_RESPONSES_MESSAGEBOX, STANDARD_PAYMENT_MESSAGEBOX } from '../PeerPayClient.js';
11
+ import { PrivateKey, WalletClient } from '@bsv/sdk';
12
+ import { jest } from '@jest/globals';
13
+ // ---------------------------------------------------------------------------
14
+ // Mock @bsv/sdk the same way as PeerPayClientUnit.test.ts
15
+ // ---------------------------------------------------------------------------
16
+ jest.mock('@bsv/sdk', () => {
17
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
18
+ const actualSDK = jest.requireActual('@bsv/sdk');
19
+ return {
20
+ ...actualSDK,
21
+ WalletClient: jest.fn().mockImplementation(() => ({
22
+ getPublicKey: jest.fn(),
23
+ createAction: jest.fn(),
24
+ internalizeAction: jest.fn(),
25
+ createHmac: jest.fn().mockResolvedValue({
26
+ hmac: [1, 2, 3, 4, 5]
27
+ }),
28
+ verifyHmac: jest.fn().mockResolvedValue({ valid: true })
29
+ }))
30
+ };
31
+ });
32
+ // ---------------------------------------------------------------------------
33
+ // MockMessageBus
34
+ // ---------------------------------------------------------------------------
35
+ /**
36
+ * Stores messages per (recipient, messageBox) pair in memory.
37
+ * Provides send / list / ack helpers that the wired client delegates to.
38
+ */
39
+ class MockMessageBus {
40
+ counter = 0;
41
+ // key: `${recipient}::${messageBox}`
42
+ store = new Map();
43
+ key(recipient, messageBox) {
44
+ return `${recipient}::${messageBox}`;
45
+ }
46
+ send(params) {
47
+ const { recipient, messageBox, body, sender } = params;
48
+ const k = this.key(recipient, messageBox);
49
+ const messageId = `msg-${++this.counter}`;
50
+ const now = new Date().toISOString();
51
+ const msg = { messageId, sender, body, created_at: now, updated_at: now };
52
+ const existing = this.store.get(k);
53
+ if (existing != null) {
54
+ existing.push(msg);
55
+ }
56
+ else {
57
+ this.store.set(k, [msg]);
58
+ }
59
+ return { status: 'success', messageId };
60
+ }
61
+ list(recipient, messageBox) {
62
+ return this.store.get(this.key(recipient, messageBox)) ?? [];
63
+ }
64
+ ack(recipient, messageBox, messageIds) {
65
+ const k = this.key(recipient, messageBox);
66
+ const msgs = this.store.get(k);
67
+ if (msgs == null)
68
+ return;
69
+ const remaining = msgs.filter(m => !messageIds.includes(m.messageId));
70
+ this.store.set(k, remaining);
71
+ }
72
+ /** Convenience: clear everything */
73
+ reset() {
74
+ this.store.clear();
75
+ this.counter = 0;
76
+ }
77
+ }
78
+ // ---------------------------------------------------------------------------
79
+ // createWiredClient
80
+ // ---------------------------------------------------------------------------
81
+ /**
82
+ * Creates a PeerPayClient whose sendMessage, listMessages, acknowledgeMessage,
83
+ * and getIdentityKey are wired to the provided MockMessageBus instance.
84
+ *
85
+ * The identityKey is the "address" used as recipient/sender for messages
86
+ * sent through the bus.
87
+ *
88
+ * sendPayment is mocked to be a no-op so tests that call fulfillPaymentRequest
89
+ * don't need a real wallet.
90
+ */
91
+ function createWiredClient(params) {
92
+ const { bus, identityKey, walletClient } = params;
93
+ const client = new PeerPayClient({
94
+ messageBoxHost: 'https://messagebox.babbage.systems',
95
+ walletClient
96
+ });
97
+ // Wire getIdentityKey
98
+ jest.spyOn(client, 'getIdentityKey').mockResolvedValue(identityKey);
99
+ // Wire sendMessage: route to the bus using the current client identity as sender
100
+ jest.spyOn(client, 'sendMessage').mockImplementation(async (sendParams) => {
101
+ const body = typeof sendParams.body === 'string' ? sendParams.body : JSON.stringify(sendParams.body);
102
+ return bus.send({
103
+ recipient: sendParams.recipient,
104
+ messageBox: sendParams.messageBox,
105
+ body,
106
+ sender: identityKey
107
+ });
108
+ });
109
+ // Wire listMessages: retrieve from bus for this identity as recipient
110
+ jest.spyOn(client, 'listMessages').mockImplementation(async (listParams) => {
111
+ return bus.list(identityKey, listParams.messageBox);
112
+ });
113
+ // Wire acknowledgeMessage: remove messages from bus
114
+ // We need to know which messageBox to remove from — scan all boxes for this recipient
115
+ jest.spyOn(client, 'acknowledgeMessage').mockImplementation(async (ackParams) => {
116
+ const { messageIds } = ackParams;
117
+ // Attempt to ack from all known messageBoxes
118
+ for (const mb of [PAYMENT_REQUESTS_MESSAGEBOX, PAYMENT_REQUEST_RESPONSES_MESSAGEBOX, STANDARD_PAYMENT_MESSAGEBOX]) {
119
+ bus.ack(identityKey, mb, messageIds);
120
+ }
121
+ return 'acknowledged';
122
+ });
123
+ // Mock sendPayment to be a no-op (avoids needing real wallet for tx creation)
124
+ jest.spyOn(client, 'sendPayment').mockResolvedValue(undefined);
125
+ return client;
126
+ }
127
+ // ---------------------------------------------------------------------------
128
+ // Tests
129
+ // ---------------------------------------------------------------------------
130
+ describe('PeerPayClient — Integration: payment request flow', () => {
131
+ let bus;
132
+ let mockWalletRequester;
133
+ let mockWalletPayer;
134
+ const REQUESTER_KEY = PrivateKey.fromRandom().toPublicKey().toString();
135
+ const PAYER_KEY = PrivateKey.fromRandom().toPublicKey().toString();
136
+ beforeEach(() => {
137
+ jest.clearAllMocks();
138
+ bus = new MockMessageBus();
139
+ mockWalletRequester = new WalletClient();
140
+ mockWalletRequester.getPublicKey.mockResolvedValue({ publicKey: REQUESTER_KEY });
141
+ mockWalletPayer = new WalletClient();
142
+ mockWalletPayer.getPublicKey.mockResolvedValue({ publicKey: PAYER_KEY });
143
+ });
144
+ // -------------------------------------------------------------------------
145
+ // Test 1: Full round-trip — request → fulfill → requester sees paid response
146
+ // -------------------------------------------------------------------------
147
+ it('Test 1: full round-trip: request → fulfill → requester sees paid response', async () => {
148
+ const requester = createWiredClient({ bus, identityKey: REQUESTER_KEY, walletClient: mockWalletRequester });
149
+ const payer = createWiredClient({ bus, identityKey: PAYER_KEY, walletClient: mockWalletPayer });
150
+ // Requester sends a payment request to payer
151
+ const { requestId } = await requester.requestPayment({
152
+ recipient: PAYER_KEY,
153
+ amount: 5000,
154
+ description: 'Invoice #1',
155
+ expiresAt: Date.now() + 60000
156
+ });
157
+ expect(requestId).toBeTruthy();
158
+ // Payer lists incoming requests
159
+ const incoming = await payer.listIncomingPaymentRequests();
160
+ expect(incoming).toHaveLength(1);
161
+ expect(incoming[0].requestId).toBe(requestId);
162
+ expect(incoming[0].amount).toBe(5000);
163
+ // Payer fulfills the request
164
+ await payer.fulfillPaymentRequest({ request: incoming[0] });
165
+ // Requester checks for responses
166
+ const responses = await requester.listPaymentRequestResponses();
167
+ expect(responses).toHaveLength(1);
168
+ expect(responses[0]).toMatchObject({ requestId, status: 'paid', amountPaid: 5000 });
169
+ });
170
+ // -------------------------------------------------------------------------
171
+ // Test 2: Full round-trip — request → decline → requester sees declined
172
+ // -------------------------------------------------------------------------
173
+ it('Test 2: full round-trip: request → decline → requester sees declined response', async () => {
174
+ const requester = createWiredClient({ bus, identityKey: REQUESTER_KEY, walletClient: mockWalletRequester });
175
+ const payer = createWiredClient({ bus, identityKey: PAYER_KEY, walletClient: mockWalletPayer });
176
+ const { requestId } = await requester.requestPayment({
177
+ recipient: PAYER_KEY,
178
+ amount: 3000,
179
+ description: 'Invoice #2',
180
+ expiresAt: Date.now() + 60000
181
+ });
182
+ const incoming = await payer.listIncomingPaymentRequests();
183
+ expect(incoming).toHaveLength(1);
184
+ await payer.declinePaymentRequest({ request: incoming[0], note: 'No funds' });
185
+ const responses = await requester.listPaymentRequestResponses();
186
+ expect(responses).toHaveLength(1);
187
+ expect(responses[0]).toMatchObject({ requestId, status: 'declined', note: 'No funds' });
188
+ });
189
+ // -------------------------------------------------------------------------
190
+ // Test 3: Request → cancel → payer no longer sees the request
191
+ // -------------------------------------------------------------------------
192
+ it('Test 3: request → cancel → payer no longer sees the request', async () => {
193
+ const requester = createWiredClient({ bus, identityKey: REQUESTER_KEY, walletClient: mockWalletRequester });
194
+ const payer = createWiredClient({ bus, identityKey: PAYER_KEY, walletClient: mockWalletPayer });
195
+ const { requestId, requestProof } = await requester.requestPayment({
196
+ recipient: PAYER_KEY,
197
+ amount: 2000,
198
+ description: 'Cancellable request',
199
+ expiresAt: Date.now() + 60000
200
+ });
201
+ // Confirm payer can see it before cancellation
202
+ const beforeCancel = await payer.listIncomingPaymentRequests();
203
+ expect(beforeCancel).toHaveLength(1);
204
+ // Requester cancels the request
205
+ await requester.cancelPaymentRequest({ recipient: PAYER_KEY, requestId, requestProof });
206
+ // Payer should now see zero active requests (the cancel message causes filtering)
207
+ const afterCancel = await payer.listIncomingPaymentRequests();
208
+ expect(afterCancel).toHaveLength(0);
209
+ });
210
+ // -------------------------------------------------------------------------
211
+ // Test 4: Expired request is filtered out automatically
212
+ // -------------------------------------------------------------------------
213
+ it('Test 4: expired request is filtered out automatically', async () => {
214
+ const payer = createWiredClient({ bus, identityKey: PAYER_KEY, walletClient: mockWalletPayer });
215
+ // Inject an already-expired request directly onto the bus (expiresAt in the past)
216
+ const expiredBody = JSON.stringify({
217
+ requestId: 'expired-req-1',
218
+ amount: 4000,
219
+ description: 'Already expired',
220
+ expiresAt: Date.now() - 10000, // in the past
221
+ senderIdentityKey: REQUESTER_KEY,
222
+ requestProof: 'mock-proof'
223
+ });
224
+ bus.send({ recipient: PAYER_KEY, messageBox: PAYMENT_REQUESTS_MESSAGEBOX, body: expiredBody, sender: REQUESTER_KEY });
225
+ // Also inject a valid request so the filter has something to keep
226
+ const validBody = JSON.stringify({
227
+ requestId: 'valid-req-1',
228
+ amount: 4000,
229
+ description: 'Still valid',
230
+ expiresAt: Date.now() + 60000,
231
+ senderIdentityKey: REQUESTER_KEY,
232
+ requestProof: 'mock-proof'
233
+ });
234
+ bus.send({ recipient: PAYER_KEY, messageBox: PAYMENT_REQUESTS_MESSAGEBOX, body: validBody, sender: REQUESTER_KEY });
235
+ const requests = await payer.listIncomingPaymentRequests();
236
+ expect(requests).toHaveLength(1);
237
+ expect(requests[0].requestId).toBe('valid-req-1');
238
+ });
239
+ // -------------------------------------------------------------------------
240
+ // Test 5: Requests below minAmount are auto-acknowledged and excluded
241
+ // -------------------------------------------------------------------------
242
+ it('Test 5: requests below minAmount are auto-acknowledged and excluded', async () => {
243
+ const payer = createWiredClient({ bus, identityKey: PAYER_KEY, walletClient: mockWalletPayer });
244
+ // Inject a request below the minAmount threshold
245
+ const smallBody = JSON.stringify({
246
+ requestId: 'req-small',
247
+ amount: 100, // below minAmount of 1000
248
+ description: 'Too small',
249
+ expiresAt: Date.now() + 60000,
250
+ senderIdentityKey: REQUESTER_KEY,
251
+ requestProof: 'mock-proof'
252
+ });
253
+ bus.send({ recipient: PAYER_KEY, messageBox: PAYMENT_REQUESTS_MESSAGEBOX, body: smallBody, sender: REQUESTER_KEY });
254
+ // Inject a valid request that passes the filter
255
+ const okBody = JSON.stringify({
256
+ requestId: 'req-ok',
257
+ amount: 5000,
258
+ description: 'Just right',
259
+ expiresAt: Date.now() + 60000,
260
+ senderIdentityKey: REQUESTER_KEY,
261
+ requestProof: 'mock-proof'
262
+ });
263
+ bus.send({ recipient: PAYER_KEY, messageBox: PAYMENT_REQUESTS_MESSAGEBOX, body: okBody, sender: REQUESTER_KEY });
264
+ const requests = await payer.listIncomingPaymentRequests(undefined, { minAmount: 1000, maxAmount: 10000 });
265
+ expect(requests).toHaveLength(1);
266
+ expect(requests[0].requestId).toBe('req-ok');
267
+ // The small request should have been auto-acknowledged (removed from bus)
268
+ const remaining = bus.list(PAYER_KEY, PAYMENT_REQUESTS_MESSAGEBOX);
269
+ const remainingIds = remaining.map(m => {
270
+ const b = JSON.parse(m.body);
271
+ return b.requestId;
272
+ });
273
+ expect(remainingIds).not.toContain('req-small');
274
+ });
275
+ // -------------------------------------------------------------------------
276
+ // Test 6: Requests above maxAmount are auto-acknowledged and excluded
277
+ // -------------------------------------------------------------------------
278
+ it('Test 6: requests above maxAmount are auto-acknowledged and excluded', async () => {
279
+ const payer = createWiredClient({ bus, identityKey: PAYER_KEY, walletClient: mockWalletPayer });
280
+ // Inject a request above the maxAmount threshold
281
+ const largeBody = JSON.stringify({
282
+ requestId: 'req-large',
283
+ amount: 99999, // above maxAmount of 10000
284
+ description: 'Too large',
285
+ expiresAt: Date.now() + 60000,
286
+ senderIdentityKey: REQUESTER_KEY,
287
+ requestProof: 'mock-proof'
288
+ });
289
+ bus.send({ recipient: PAYER_KEY, messageBox: PAYMENT_REQUESTS_MESSAGEBOX, body: largeBody, sender: REQUESTER_KEY });
290
+ // Inject a valid request that passes the filter
291
+ const okBody = JSON.stringify({
292
+ requestId: 'req-ok-2',
293
+ amount: 5000,
294
+ description: 'Just right',
295
+ expiresAt: Date.now() + 60000,
296
+ senderIdentityKey: REQUESTER_KEY,
297
+ requestProof: 'mock-proof'
298
+ });
299
+ bus.send({ recipient: PAYER_KEY, messageBox: PAYMENT_REQUESTS_MESSAGEBOX, body: okBody, sender: REQUESTER_KEY });
300
+ const requests = await payer.listIncomingPaymentRequests(undefined, { minAmount: 1000, maxAmount: 10000 });
301
+ expect(requests).toHaveLength(1);
302
+ expect(requests[0].requestId).toBe('req-ok-2');
303
+ // The large request should have been auto-acknowledged (removed from bus)
304
+ const remaining = bus.list(PAYER_KEY, PAYMENT_REQUESTS_MESSAGEBOX);
305
+ const remainingIds = remaining.map(m => {
306
+ const b = JSON.parse(m.body);
307
+ return b.requestId;
308
+ });
309
+ expect(remainingIds).not.toContain('req-large');
310
+ });
311
+ });
312
+ //# sourceMappingURL=PeerPayClientRequestIntegration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PeerPayClientRequestIntegration.test.js","sourceRoot":"","sources":["../../../../src/__tests/PeerPayClientRequestIntegration.test.ts"],"names":[],"mappings":"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"}