@bopen-io/messagebox-server 1.2.2 → 1.2.3

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 (142) hide show
  1. package/out/knexfile.js +25 -0
  2. package/out/knexfile.js.map +1 -0
  3. package/out/src/__tests/compose.test.js +25 -0
  4. package/out/src/__tests/compose.test.js.map +1 -0
  5. package/out/src/app.js +162 -0
  6. package/out/src/app.js.map +1 -0
  7. package/out/src/compose.js +239 -0
  8. package/out/src/compose.js.map +1 -0
  9. package/out/src/config/firebase.js +150 -0
  10. package/out/src/config/firebase.js.map +1 -0
  11. package/out/src/context.js +23 -0
  12. package/out/src/context.js.map +1 -0
  13. package/out/src/index.js +311 -0
  14. package/out/src/index.js.map +1 -0
  15. package/out/src/migrations/2022-12-28-001-initial-migration.js +28 -0
  16. package/out/src/migrations/2022-12-28-001-initial-migration.js.map +1 -0
  17. package/out/src/migrations/2023-01-17-messages-update.js +11 -0
  18. package/out/src/migrations/2023-01-17-messages-update.js.map +1 -0
  19. package/out/src/migrations/2024-03-05-001-messageID-upgrade.js +21 -0
  20. package/out/src/migrations/2024-03-05-001-messageID-upgrade.js.map +1 -0
  21. package/out/src/migrations/2025-01-31-001-notification-permissions.js +59 -0
  22. package/out/src/migrations/2025-01-31-001-notification-permissions.js.map +1 -0
  23. package/out/src/migrations/2025-01-31-002-device-registrations.js +24 -0
  24. package/out/src/migrations/2025-01-31-002-device-registrations.js.map +1 -0
  25. package/out/src/routes/__tests/acknowledgeMessage.test.js +135 -0
  26. package/out/src/routes/__tests/acknowledgeMessage.test.js.map +1 -0
  27. package/out/src/routes/__tests/listMessages.test.js +217 -0
  28. package/out/src/routes/__tests/listMessages.test.js.map +1 -0
  29. package/out/src/routes/__tests/sendMessage.test.js +313 -0
  30. package/out/src/routes/__tests/sendMessage.test.js.map +1 -0
  31. package/out/src/routes/acknowledgeMessage.js +133 -0
  32. package/out/src/routes/acknowledgeMessage.js.map +1 -0
  33. package/out/src/routes/index.js +17 -0
  34. package/out/src/routes/index.js.map +1 -0
  35. package/out/src/routes/listDevices.js +63 -0
  36. package/out/src/routes/listDevices.js.map +1 -0
  37. package/out/src/routes/listMessages.js +176 -0
  38. package/out/src/routes/listMessages.js.map +1 -0
  39. package/out/src/routes/permissions/getPermission.js +138 -0
  40. package/out/src/routes/permissions/getPermission.js.map +1 -0
  41. package/out/src/routes/permissions/getQuote.js +165 -0
  42. package/out/src/routes/permissions/getQuote.js.map +1 -0
  43. package/out/src/routes/permissions/index.js +12 -0
  44. package/out/src/routes/permissions/index.js.map +1 -0
  45. package/out/src/routes/permissions/listPermissions.js +179 -0
  46. package/out/src/routes/permissions/listPermissions.js.map +1 -0
  47. package/out/src/routes/permissions/setPermission.js +137 -0
  48. package/out/src/routes/permissions/setPermission.js.map +1 -0
  49. package/out/src/routes/registerDevice.js +139 -0
  50. package/out/src/routes/registerDevice.js.map +1 -0
  51. package/out/src/routes/sendMessage.js +438 -0
  52. package/out/src/routes/sendMessage.js.map +1 -0
  53. package/out/src/runtimeDeps.js +15 -0
  54. package/out/src/runtimeDeps.js.map +1 -0
  55. package/out/src/swagger.js +48 -0
  56. package/out/src/swagger.js.map +1 -0
  57. package/out/src/telemetry.js +134 -0
  58. package/out/src/telemetry.js.map +1 -0
  59. package/out/src/types/messagePermissions.js +2 -0
  60. package/out/src/types/messagePermissions.js.map +1 -0
  61. package/out/src/types/notifications.js +2 -0
  62. package/out/src/types/notifications.js.map +1 -0
  63. package/out/src/utils/logger.js +85 -0
  64. package/out/src/utils/logger.js.map +1 -0
  65. package/out/src/utils/messagePermissions.js +115 -0
  66. package/out/src/utils/messagePermissions.js.map +1 -0
  67. package/out/src/utils/sendFCMNotification.js +110 -0
  68. package/out/src/utils/sendFCMNotification.js.map +1 -0
  69. package/out/tsconfig.tsbuildinfo +1 -0
  70. package/out/types/jest.config.d.ts +4 -0
  71. package/out/types/jest.config.d.ts.map +1 -0
  72. package/out/types/jest.config.integration.d.ts +5 -0
  73. package/out/types/jest.config.integration.d.ts.map +1 -0
  74. package/out/types/knexfile.d.ts +6 -0
  75. package/out/types/knexfile.d.ts.map +1 -0
  76. package/out/types/src/__tests/compose.test.d.ts +2 -0
  77. package/out/types/src/__tests/compose.test.d.ts.map +1 -0
  78. package/out/types/src/app.d.ts +63 -0
  79. package/out/types/src/app.d.ts.map +1 -0
  80. package/out/types/src/compose.d.ts +22 -0
  81. package/out/types/src/compose.d.ts.map +1 -0
  82. package/out/types/src/config/firebase.d.ts +34 -0
  83. package/out/types/src/config/firebase.d.ts.map +1 -0
  84. package/out/types/src/context.d.ts +23 -0
  85. package/out/types/src/context.d.ts.map +1 -0
  86. package/out/types/src/index.d.ts +43 -0
  87. package/out/types/src/index.d.ts.map +1 -0
  88. package/out/types/src/migrations/2022-12-28-001-initial-migration.d.ts +4 -0
  89. package/out/types/src/migrations/2022-12-28-001-initial-migration.d.ts.map +1 -0
  90. package/out/types/src/migrations/2023-01-17-messages-update.d.ts +4 -0
  91. package/out/types/src/migrations/2023-01-17-messages-update.d.ts.map +1 -0
  92. package/out/types/src/migrations/2024-03-05-001-messageID-upgrade.d.ts +4 -0
  93. package/out/types/src/migrations/2024-03-05-001-messageID-upgrade.d.ts.map +1 -0
  94. package/out/types/src/migrations/2025-01-31-001-notification-permissions.d.ts +4 -0
  95. package/out/types/src/migrations/2025-01-31-001-notification-permissions.d.ts.map +1 -0
  96. package/out/types/src/migrations/2025-01-31-002-device-registrations.d.ts +4 -0
  97. package/out/types/src/migrations/2025-01-31-002-device-registrations.d.ts.map +1 -0
  98. package/out/types/src/routes/__tests/acknowledgeMessage.test.d.ts +2 -0
  99. package/out/types/src/routes/__tests/acknowledgeMessage.test.d.ts.map +1 -0
  100. package/out/types/src/routes/__tests/listMessages.test.d.ts +2 -0
  101. package/out/types/src/routes/__tests/listMessages.test.d.ts.map +1 -0
  102. package/out/types/src/routes/__tests/sendMessage.test.d.ts +2 -0
  103. package/out/types/src/routes/__tests/sendMessage.test.d.ts.map +1 -0
  104. package/out/types/src/routes/acknowledgeMessage.d.ts +100 -0
  105. package/out/types/src/routes/acknowledgeMessage.d.ts.map +1 -0
  106. package/out/types/src/routes/index.d.ts +11 -0
  107. package/out/types/src/routes/index.d.ts.map +1 -0
  108. package/out/types/src/routes/listDevices.d.ts +19 -0
  109. package/out/types/src/routes/listDevices.d.ts.map +1 -0
  110. package/out/types/src/routes/listMessages.d.ts +124 -0
  111. package/out/types/src/routes/listMessages.d.ts.map +1 -0
  112. package/out/types/src/routes/permissions/getPermission.d.ts +46 -0
  113. package/out/types/src/routes/permissions/getPermission.d.ts.map +1 -0
  114. package/out/types/src/routes/permissions/getQuote.d.ts +50 -0
  115. package/out/types/src/routes/permissions/getQuote.d.ts.map +1 -0
  116. package/out/types/src/routes/permissions/index.d.ts +18 -0
  117. package/out/types/src/routes/permissions/index.d.ts.map +1 -0
  118. package/out/types/src/routes/permissions/listPermissions.d.ts +106 -0
  119. package/out/types/src/routes/permissions/listPermissions.d.ts.map +1 -0
  120. package/out/types/src/routes/permissions/setPermission.d.ts +53 -0
  121. package/out/types/src/routes/permissions/setPermission.d.ts.map +1 -0
  122. package/out/types/src/routes/registerDevice.d.ts +67 -0
  123. package/out/types/src/routes/registerDevice.d.ts.map +1 -0
  124. package/out/types/src/routes/sendMessage.d.ts +140 -0
  125. package/out/types/src/routes/sendMessage.d.ts.map +1 -0
  126. package/out/types/src/runtimeDeps.d.ts +17 -0
  127. package/out/types/src/runtimeDeps.d.ts.map +1 -0
  128. package/out/types/src/swagger.d.ts +3 -0
  129. package/out/types/src/swagger.d.ts.map +1 -0
  130. package/out/types/src/telemetry.d.ts +2 -0
  131. package/out/types/src/telemetry.d.ts.map +1 -0
  132. package/out/types/src/types/messagePermissions.d.ts +15 -0
  133. package/out/types/src/types/messagePermissions.d.ts.map +1 -0
  134. package/out/types/src/types/notifications.d.ts +20 -0
  135. package/out/types/src/types/notifications.d.ts.map +1 -0
  136. package/out/types/src/utils/logger.d.ts +17 -0
  137. package/out/types/src/utils/logger.d.ts.map +1 -0
  138. package/out/types/src/utils/messagePermissions.d.ts +29 -0
  139. package/out/types/src/utils/messagePermissions.d.ts.map +1 -0
  140. package/out/types/src/utils/sendFCMNotification.d.ts +22 -0
  141. package/out/types/src/utils/sendFCMNotification.d.ts.map +1 -0
  142. package/package.json +1 -1
@@ -0,0 +1,438 @@
1
+ /**
2
+ * @file sendMessage.ts
3
+ * @description
4
+ * Route handler to send a message to another identity's messageBox.
5
+ * This route is used for P2P communication in the MessageBox system.
6
+ *
7
+ * It handles:
8
+ * - Validation of message structure
9
+ * - Validation of the recipient public key
10
+ * - MessageBox creation if one doesn't exist
11
+ * - Insertion of the message into the database
12
+ * - Deduplication based on messageId
13
+ *
14
+ */
15
+ import { PublicKey, } from '@bsv/sdk';
16
+ import { Logger, log } from '../utils/logger.js';
17
+ import { sendFCMNotification } from '../utils/sendFCMNotification.js';
18
+ import { getRecipientFee, getServerDeliveryFee, shouldUseFCMDelivery } from '../utils/messagePermissions.js';
19
+ import { runtimeDeps, getWallet } from '../runtimeDeps.js';
20
+ const { SERVER_PRIVATE_KEY } = process.env;
21
+ // Validate critical server-side secret
22
+ if (SERVER_PRIVATE_KEY == null || SERVER_PRIVATE_KEY.trim() === '') {
23
+ throw new Error('SERVER_PRIVATE_KEY is not defined in the environment variables.');
24
+ }
25
+ /**
26
+ * @function calculateMessagePrice
27
+ * @description Determines the price (in satoshis) to send a message, optionally with priority.
28
+ */
29
+ export function calculateMessagePrice(message, priority = false) {
30
+ const basePrice = 2; // Base fee in satoshis
31
+ const sizeFactor = Math.ceil(Buffer.byteLength(message, 'utf8') / 1024) * 3; // Satoshis per KB
32
+ return basePrice + sizeFactor;
33
+ }
34
+ /**
35
+ * @openapi
36
+ * /sendMessage:
37
+ * post:
38
+ * summary: Send a message to a recipient’s message box
39
+ * description: |
40
+ * Inserts a message into the target recipient’s message box on the server.
41
+ * The recipient, message box name, and message ID must be provided.
42
+ * tags:
43
+ * - Message
44
+ * requestBody:
45
+ * required: true
46
+ * content:
47
+ * application/json:
48
+ * schema:
49
+ * type: object
50
+ * properties:
51
+ * message:
52
+ * type: object
53
+ * required:
54
+ * - recipient
55
+ * - messageBox
56
+ * - messageId
57
+ * - body
58
+ * properties:
59
+ * recipient:
60
+ * type: string
61
+ * description: Identity key of the recipient
62
+ * messageBox:
63
+ * type: string
64
+ * description: The name of the recipient's message box
65
+ * messageId:
66
+ * type: string
67
+ * description: Unique identifier for the message (usually an HMAC)
68
+ * body:
69
+ * oneOf:
70
+ * - type: string
71
+ * - type: object
72
+ * description: The message content
73
+ * responses:
74
+ * 200:
75
+ * description: Message stored successfully
76
+ * content:
77
+ * application/json:
78
+ * schema:
79
+ * type: object
80
+ * properties:
81
+ * status:
82
+ * type: string
83
+ * example: success
84
+ * messageId:
85
+ * type: string
86
+ * message:
87
+ * type: string
88
+ * 400:
89
+ * description: Invalid request or duplicate message
90
+ * 500:
91
+ * description: Internal server error
92
+ */
93
+ /**
94
+ * @exports
95
+ * Express-compatible route definition for `/sendMessage`, used to send messages to other users.
96
+ * Contains metadata for auto-generation of route documentation and Swagger/OpenAPI integration.
97
+ */
98
+ export default {
99
+ type: 'post',
100
+ path: '/sendMessage',
101
+ get knex() { return runtimeDeps.knex; },
102
+ summary: "Use this route to send a message to a recipient's message box.",
103
+ parameters: {
104
+ message: {
105
+ recipient: '028d37b941208cd6b8a4c28288eda5f2f16c2b3ab0fcb6d13c18b47fe37b971fc1',
106
+ messageBox: 'payment_inbox',
107
+ messageId: 'xyz123',
108
+ body: '{}'
109
+ }
110
+ },
111
+ exampleResponse: { status: 'success' },
112
+ func: async (req, res) => {
113
+ Logger.log('[DEBUG] Processing /sendMessage request...');
114
+ Logger.log('[DEBUG] Request Headers:', JSON.stringify(req.headers, null, 2));
115
+ const senderKey = req.auth?.identityKey;
116
+ if (senderKey == null) {
117
+ return res.status(401).json({
118
+ status: 'error',
119
+ code: 'ERR_AUTH_REQUIRED',
120
+ description: 'Authentication required'
121
+ });
122
+ }
123
+ try {
124
+ const { message, payment } = req.body;
125
+ log.info({ operation: 'message.send', message_box: message?.messageBox, has_payment: payment != null }, 'Received message send request');
126
+ if (message == null) {
127
+ Logger.error('[ERROR] No message provided in request body!');
128
+ return res.status(400).json({
129
+ status: 'error',
130
+ code: 'ERR_MESSAGE_REQUIRED',
131
+ description: 'Please provide a valid message to send!'
132
+ });
133
+ }
134
+ if (typeof message.messageBox !== 'string' || message.messageBox.trim() === '') {
135
+ return res.status(400).json({ status: 'error', code: 'ERR_INVALID_MESSAGEBOX', description: 'Invalid message box.' });
136
+ }
137
+ if ((typeof message.body !== 'string' && (typeof message.body !== 'object' || message.body === null)) ||
138
+ (typeof message.body === 'string' && message.body.trim() === '')) {
139
+ return res.status(400).json({ status: 'error', code: 'ERR_INVALID_MESSAGE_BODY', description: 'Invalid message body.' });
140
+ }
141
+ // ---------- Back-compat normalization ----------
142
+ // Accept message.recipients (array) or message.recipient (string|array)
143
+ const recipientsRaw = message.recipients ?? message.recipient;
144
+ if (recipientsRaw == null) {
145
+ return res.status(400).json({
146
+ status: 'error',
147
+ code: 'ERR_RECIPIENT_REQUIRED',
148
+ description: 'Missing recipient(s). Provide "recipient" or "recipients".'
149
+ });
150
+ }
151
+ const recipients = Array.isArray(recipientsRaw)
152
+ ? recipientsRaw
153
+ : [recipientsRaw];
154
+ const messageIdRaw = message.messageId;
155
+ if (messageIdRaw == null) {
156
+ return res.status(400).json({
157
+ status: 'error',
158
+ code: 'ERR_MESSAGEID_REQUIRED',
159
+ description: 'Missing messageId.'
160
+ });
161
+ }
162
+ const messageIds = Array.isArray(messageIdRaw)
163
+ ? messageIdRaw
164
+ : [messageIdRaw];
165
+ // If multiple recipients but only one messageId provided, fail clearly (avoid accidental reuse)
166
+ if (recipients.length > 1 && messageIds.length === 1) {
167
+ return res.status(400).json({
168
+ status: 'error',
169
+ code: 'ERR_MESSAGEID_COUNT_MISMATCH',
170
+ description: `Provided 1 messageId for ${recipients.length} recipients. Provide one messageId per recipient (same order).`
171
+ });
172
+ }
173
+ if (messageIds.length !== recipients.length) {
174
+ return res.status(400).json({
175
+ status: 'error',
176
+ code: 'ERR_MESSAGEID_COUNT_MISMATCH',
177
+ description: `Recipients (${recipients.length}) and messageId count (${messageIds.length}) must match.`
178
+ });
179
+ }
180
+ // Validate each messageId
181
+ for (const id of messageIds) {
182
+ if (typeof id !== 'string' || id.trim() === '') {
183
+ return res.status(400).json({ status: 'error', code: 'ERR_INVALID_MESSAGEID', description: 'Each messageId must be a non-empty string.' });
184
+ }
185
+ }
186
+ // Validate recipient keys & build map(recipient -> messageId)
187
+ const recipientsTrimmed = recipients.map(r => String(r).trim());
188
+ const msgIdByRecipient = new Map();
189
+ for (let i = 0; i < recipientsTrimmed.length; i++) {
190
+ const r = recipientsTrimmed[i];
191
+ try {
192
+ PublicKey.fromString(r);
193
+ }
194
+ catch {
195
+ return res.status(400).json({
196
+ status: 'error',
197
+ code: 'ERR_INVALID_RECIPIENT_KEY',
198
+ description: `Invalid recipient key: ${r}`
199
+ });
200
+ }
201
+ msgIdByRecipient.set(r, messageIds[i]);
202
+ }
203
+ // Ensure messageBox exists for each recipient
204
+ const boxType = message.messageBox.trim();
205
+ for (const r of recipientsTrimmed) {
206
+ const existing = await runtimeDeps.knex('messageBox').where({ identityKey: r, type: boxType }).first();
207
+ if (!existing) {
208
+ await runtimeDeps.knex('messageBox').insert({
209
+ identityKey: r, type: boxType, created_at: new Date(), updated_at: new Date()
210
+ });
211
+ }
212
+ }
213
+ // ---------- Fee evaluation ----------
214
+ const deliveryFeeOnce = await getServerDeliveryFee(boxType);
215
+ const feeRows = [];
216
+ for (const r of recipientsTrimmed) {
217
+ const rf = await getRecipientFee(r, senderKey, boxType); // -1 = blocked; 0 = allow; >0 = sats required
218
+ if (rf === -1)
219
+ feeRows.push({ recipient: r, recipientFee: rf, allowed: false, blockedReason: `Messages to ${r} are blocked` });
220
+ else
221
+ feeRows.push({ recipient: r, recipientFee: rf, allowed: true });
222
+ }
223
+ // Blocked recipients short-circuit
224
+ const blocked = feeRows.filter(f => !f.allowed).map(f => f.recipient);
225
+ if (blocked.length) {
226
+ return res.status(403).json({
227
+ status: 'error',
228
+ code: 'ERR_DELIVERY_BLOCKED',
229
+ description: `Blocked recipients: ${blocked.join(', ')}`,
230
+ blockedRecipients: blocked
231
+ });
232
+ }
233
+ const anyRecipientFee = feeRows.some(f => f.recipientFee > 0);
234
+ const requiresPayment = (deliveryFeeOnce > 0) || anyRecipientFee;
235
+ // ---------- Payment internalization (batch) ----------
236
+ const perRecipientOutputs = new Map();
237
+ if (requiresPayment) {
238
+ if (!payment?.tx || !Array.isArray(payment.outputs)) {
239
+ return res.status(400).json({
240
+ status: 'error',
241
+ code: 'ERR_MISSING_PAYMENT_TX',
242
+ description: 'Payment transaction data is required for payable delivery.'
243
+ });
244
+ }
245
+ // Enforce: index 0 is server delivery output (when needed)
246
+ if (deliveryFeeOnce > 0) {
247
+ if (payment.outputs.length === 0) {
248
+ return res.status(400).json({
249
+ status: 'error',
250
+ code: 'ERR_MISSING_DELIVERY_OUTPUT',
251
+ description: 'Delivery fee required but no outputs were provided.'
252
+ });
253
+ }
254
+ const serverDeliveryOutput = payment.outputs[0];
255
+ try {
256
+ const wallet = await getWallet();
257
+ const internalizeResult = await wallet.internalizeAction({
258
+ tx: payment.tx,
259
+ outputs: [serverDeliveryOutput],
260
+ description: payment.description ?? 'MessageBox delivery payment (batch)'
261
+ });
262
+ if (!internalizeResult.accepted) {
263
+ return res.status(400).json({
264
+ status: 'error',
265
+ code: 'ERR_INSUFFICIENT_PAYMENT',
266
+ description: 'Payment was not accepted by the server.'
267
+ });
268
+ }
269
+ Logger.log('[DEBUG] Internalized server delivery output at index 0');
270
+ }
271
+ catch (error) {
272
+ Logger.error('[ERROR] Failed to internalize delivery fee payment:', error);
273
+ return res.status(500).json({
274
+ status: 'error',
275
+ code: 'ERR_INTERNALIZE_FAILED',
276
+ description: `Failed to internalize payment: ${error instanceof Error ? error.message : 'Unknown error'}`
277
+ });
278
+ }
279
+ }
280
+ // ---------- Build per-recipient outputs ----------
281
+ const recipientSideOutputs = payment.outputs.slice(deliveryFeeOnce > 0 ? 1 : 0);
282
+ log.info({ operation: 'message.send', recipient_output_count: recipientSideOutputs.length, total_output_count: payment.outputs.length }, 'Payment outputs');
283
+ const feeRecipients = feeRows.filter(f => f.recipientFee > 0).map(f => f.recipient);
284
+ // Try explicit mapping via customInstructions (in insertionRemittance OR paymentRemittance)
285
+ const outputsByRecipientKey = new Map();
286
+ const usedIndexes = new Set();
287
+ for (const out of recipientSideOutputs) {
288
+ const raw = out?.insertionRemittance?.customInstructions ??
289
+ out?.paymentRemittance?.customInstructions ??
290
+ out?.customInstructions;
291
+ if (!raw)
292
+ continue;
293
+ try {
294
+ const instr = typeof raw === 'string' ? JSON.parse(raw) : raw;
295
+ const key = instr?.recipientIdentityKey;
296
+ if (typeof key === 'string' && key.trim() !== '') {
297
+ if (!outputsByRecipientKey.has(key))
298
+ outputsByRecipientKey.set(key, []);
299
+ outputsByRecipientKey.get(key).push(out);
300
+ if (typeof out?.outputIndex === 'number') {
301
+ usedIndexes.add(out.outputIndex);
302
+ }
303
+ }
304
+ }
305
+ catch {
306
+ // ignore unparsable instructions
307
+ }
308
+ }
309
+ if (outputsByRecipientKey.size === 0) {
310
+ // No explicit tags: fallback to positional mapping for recipients that require a fee
311
+ if (recipientSideOutputs.length < feeRecipients.length) {
312
+ return res.status(400).json({
313
+ status: 'error',
314
+ code: 'ERR_INSUFFICIENT_OUTPUTS',
315
+ description: `Expected at least ${feeRecipients.length} recipient output(s) but received ${recipientSideOutputs.length}`
316
+ });
317
+ }
318
+ feeRecipients.forEach((r, idx) => {
319
+ const out = recipientSideOutputs[idx];
320
+ if (!perRecipientOutputs.has(r))
321
+ perRecipientOutputs.set(r, []);
322
+ perRecipientOutputs.get(r).push(out);
323
+ });
324
+ }
325
+ else {
326
+ // Use tagged outputs where present
327
+ for (const r of feeRecipients) {
328
+ const tagged = outputsByRecipientKey.get(r) ?? [];
329
+ if (tagged.length > 0) {
330
+ perRecipientOutputs.set(r, tagged);
331
+ }
332
+ }
333
+ // For any remaining fee recipients without tags, allocate unused outputs (positional)
334
+ const unmapped = feeRecipients.filter(r => !perRecipientOutputs.has(r));
335
+ if (unmapped.length > 0) {
336
+ const remaining = recipientSideOutputs.filter(o => {
337
+ const idx = o?.outputIndex;
338
+ return typeof idx === 'number' ? !usedIndexes.has(idx) : true;
339
+ });
340
+ if (remaining.length < unmapped.length) {
341
+ return res.status(400).json({
342
+ status: 'error',
343
+ code: 'ERR_INSUFFICIENT_OUTPUTS',
344
+ description: `Expected at least ${unmapped.length} additional recipient output(s) but only ${remaining.length} remain`
345
+ });
346
+ }
347
+ unmapped.forEach((r, i) => {
348
+ const out = remaining[i];
349
+ if (!perRecipientOutputs.has(r))
350
+ perRecipientOutputs.set(r, []);
351
+ perRecipientOutputs.get(r).push(out);
352
+ });
353
+ }
354
+ // Final safety check
355
+ for (const r of feeRecipients) {
356
+ if (!perRecipientOutputs.has(r) || perRecipientOutputs.get(r).length === 0) {
357
+ return res.status(400).json({
358
+ status: 'error',
359
+ code: 'ERR_MISSING_RECIPIENT_OUTPUTS',
360
+ description: `Recipient fee required but no outputs were provided for ${r}`
361
+ });
362
+ }
363
+ }
364
+ }
365
+ }
366
+ // ---------- Store messages (one per recipient) ----------
367
+ const results = [];
368
+ for (const { recipient: r } of feeRows) {
369
+ const mb = await runtimeDeps.knex('messageBox')
370
+ .where({ identityKey: r, type: boxType })
371
+ .select('messageBoxId')
372
+ .first();
373
+ const perRecipientMessageId = msgIdByRecipient.get(r);
374
+ if (!perRecipientMessageId) {
375
+ return res.status(400).json({
376
+ status: 'error',
377
+ code: 'ERR_INVALID_MESSAGEID',
378
+ description: `Missing messageId for recipient ${r}`
379
+ });
380
+ }
381
+ const perRecipientPayment = perRecipientOutputs.has(r) && req.body.payment
382
+ ? { ...req.body.payment, outputs: perRecipientOutputs.get(r) }
383
+ : undefined;
384
+ const storedBody = {
385
+ message: message.body,
386
+ ...(perRecipientPayment && { payment: perRecipientPayment })
387
+ };
388
+ try {
389
+ await runtimeDeps.knex('messages')
390
+ .insert({
391
+ messageId: perRecipientMessageId,
392
+ messageBoxId: mb?.messageBoxId ?? null,
393
+ sender: senderKey,
394
+ recipient: r,
395
+ body: JSON.stringify(storedBody),
396
+ created_at: new Date(),
397
+ updated_at: new Date()
398
+ })
399
+ .onConflict('messageId')
400
+ .ignore();
401
+ results.push({ recipient: r, messageId: perRecipientMessageId });
402
+ }
403
+ catch (error) {
404
+ if (error?.code === 'ER_DUP_ENTRY') {
405
+ return res.status(400).json({
406
+ status: 'error',
407
+ code: 'ERR_DUPLICATE_MESSAGE',
408
+ description: 'Duplicate message.'
409
+ });
410
+ }
411
+ throw error;
412
+ }
413
+ try {
414
+ if (shouldUseFCMDelivery(boxType)) {
415
+ await sendFCMNotification(r, { title: 'New Message', messageId: perRecipientMessageId });
416
+ }
417
+ }
418
+ catch (deliveryError) {
419
+ Logger.error('[ERROR] Error processing FCM delivery:', deliveryError);
420
+ }
421
+ }
422
+ return res.status(200).json({
423
+ status: 'success',
424
+ message: `Your message has been sent to ${results.length} recipient(s).`,
425
+ results
426
+ });
427
+ }
428
+ catch (error) {
429
+ Logger.error('[ERROR] Internal Server Error:', error);
430
+ return res.status(500).json({
431
+ status: 'error',
432
+ code: 'ERR_INTERNAL',
433
+ description: 'An internal error has occurred.'
434
+ });
435
+ }
436
+ }
437
+ };
438
+ //# sourceMappingURL=sendMessage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sendMessage.js","sourceRoot":"","sources":["../../../src/routes/sendMessage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /** Bound before serving; routes read knex/wallet from here. */
2
+ export const runtimeDeps = {
3
+ knex: null
4
+ };
5
+ export function bindMessageBoxRuntime(deps) {
6
+ runtimeDeps.knex = deps.knex;
7
+ runtimeDeps.wallet = deps.wallet;
8
+ }
9
+ export async function getWallet() {
10
+ if (runtimeDeps.wallet == null) {
11
+ throw new Error('Wallet is not initialized');
12
+ }
13
+ return runtimeDeps.wallet;
14
+ }
15
+ //# sourceMappingURL=runtimeDeps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeDeps.js","sourceRoot":"","sources":["../../src/runtimeDeps.ts"],"names":[],"mappings":"AAOA,+DAA+D;AAC/D,MAAM,CAAC,MAAM,WAAW,GAGpB;IACF,IAAI,EAAE,IAAuB;CAC9B,CAAA;AAED,MAAM,UAAU,qBAAqB,CAAE,IAGtC;IACC,WAAW,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;IAC5B,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,WAAW,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;IAC9C,CAAC;IACD,OAAO,WAAW,CAAC,MAAM,CAAA;AAC3B,CAAC"}
@@ -0,0 +1,48 @@
1
+ import swaggerJsdoc from 'swagger-jsdoc';
2
+ import swaggerUi from 'swagger-ui-express';
3
+ export function setupSwagger(app) {
4
+ const options = {
5
+ definition: {
6
+ openapi: '3.0.0',
7
+ info: {
8
+ title: 'MessageBox Server API',
9
+ version: '1.0.0',
10
+ description: 'API documentation for the MessageBox Server, including message delivery, retrieval, acknowledgment, and overlay routing.'
11
+ },
12
+ servers: [
13
+ {
14
+ url: 'http://localhost:5001',
15
+ description: 'Local Development Server'
16
+ },
17
+ {
18
+ url: 'https://messagebox.babbage.systems',
19
+ description: 'Production MessageBox Server'
20
+ }
21
+ ],
22
+ components: {
23
+ securitySchemes: {
24
+ BearerAuth: {
25
+ type: 'http',
26
+ scheme: 'bearer',
27
+ bearerFormat: 'JWT',
28
+ description: 'Provide your signed identity key JWT in the `Authorization` header as: `Bearer <token>`'
29
+ }
30
+ }
31
+ },
32
+ security: [
33
+ {
34
+ BearerAuth: []
35
+ }
36
+ ]
37
+ },
38
+ apis: ['./src/routes/*.ts']
39
+ };
40
+ const swaggerSpec = swaggerJsdoc(options);
41
+ app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
42
+ // Serve raw OpenAPI spec at /openapi.json
43
+ app.get('/openapi.json', (_req, res) => {
44
+ res.setHeader('Content-Type', 'application/json');
45
+ res.send(swaggerSpec);
46
+ });
47
+ }
48
+ //# sourceMappingURL=swagger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swagger.js","sourceRoot":"","sources":["../../src/swagger.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAA;AACxC,OAAO,SAAS,MAAM,oBAAoB,CAAA;AAG1C,MAAM,UAAU,YAAY,CAAE,GAAY;IACxC,MAAM,OAAO,GAAG;QACd,UAAU,EAAE;YACV,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE;gBACJ,KAAK,EAAE,uBAAuB;gBAC9B,OAAO,EAAE,OAAO;gBAChB,WAAW,EAAE,0HAA0H;aACxI;YACD,OAAO,EAAE;gBACP;oBACE,GAAG,EAAE,uBAAuB;oBAC5B,WAAW,EAAE,0BAA0B;iBACxC;gBACD;oBACE,GAAG,EAAE,oCAAoC;oBACzC,WAAW,EAAE,8BAA8B;iBAC5C;aACF;YACD,UAAU,EAAE;gBACV,eAAe,EAAE;oBACf,UAAU,EAAE;wBACV,IAAI,EAAE,MAAM;wBACZ,MAAM,EAAE,QAAQ;wBAChB,YAAY,EAAE,KAAK;wBACnB,WAAW,EAAE,yFAAyF;qBACvG;iBACF;aACF;YACD,QAAQ,EAAE;gBACR;oBACE,UAAU,EAAE,EAAE;iBACf;aACF;SACF;QACD,IAAI,EAAE,CAAC,mBAAmB,CAAC;KAC5B,CAAA;IAED,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,CAIxC;IAAC,GAAW,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAA;IAEzE,0CAA0C;IAC1C,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACrC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;QACjD,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACvB,CAAC,CAAC,CAAA;AACJ,CAAC"}