zapo-js 0.1.0

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 (585) hide show
  1. package/README.md +235 -0
  2. package/dist/appstate/WaAppStateCrypto.js +202 -0
  3. package/dist/appstate/WaAppStateSyncClient.js +808 -0
  4. package/dist/appstate/WaAppStateSyncResponseParser.js +71 -0
  5. package/dist/appstate/constants.js +23 -0
  6. package/dist/appstate/index.js +28 -0
  7. package/dist/appstate/store/sqlite.js +55 -0
  8. package/dist/appstate/types.js +2 -0
  9. package/dist/appstate/utils.js +84 -0
  10. package/dist/auth/WaAuthClient.js +266 -0
  11. package/dist/auth/flow/WaAuthCredentialsFlow.js +123 -0
  12. package/dist/auth/index.js +27 -0
  13. package/dist/auth/pairing/WaPairingCodeCrypto.js +75 -0
  14. package/dist/auth/pairing/WaPairingFlow.js +328 -0
  15. package/dist/auth/pairing/WaQrFlow.js +86 -0
  16. package/dist/auth/pairing/constants.js +5 -0
  17. package/dist/auth/types.js +2 -0
  18. package/dist/client/WaClient.js +749 -0
  19. package/dist/client/WaClientFactory.js +381 -0
  20. package/dist/client/coordinators/WaGroupCoordinator.js +191 -0
  21. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +315 -0
  22. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +1061 -0
  23. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +200 -0
  24. package/dist/client/coordinators/WaRetryCoordinator.js +494 -0
  25. package/dist/client/coordinators/WaStreamControlCoordinator.js +123 -0
  26. package/dist/client/dirty.js +254 -0
  27. package/dist/client/events/chat.js +226 -0
  28. package/dist/client/events/group.js +410 -0
  29. package/dist/client/history-sync.js +122 -0
  30. package/dist/client/incoming.js +236 -0
  31. package/dist/client/index.js +5 -0
  32. package/dist/client/mailbox.js +49 -0
  33. package/dist/client/messages.js +152 -0
  34. package/dist/client/types.js +2 -0
  35. package/dist/crypto/core/constants.js +4 -0
  36. package/dist/crypto/core/encoding.js +29 -0
  37. package/dist/crypto/core/hkdf.js +26 -0
  38. package/dist/crypto/core/index.js +43 -0
  39. package/dist/crypto/core/keys.js +73 -0
  40. package/dist/crypto/core/nonce.js +18 -0
  41. package/dist/crypto/core/primitives.js +121 -0
  42. package/dist/crypto/core/random.js +32 -0
  43. package/dist/crypto/curves/Ed25519.js +42 -0
  44. package/dist/crypto/curves/X25519.js +64 -0
  45. package/dist/crypto/curves/constants.js +6 -0
  46. package/dist/crypto/curves/types.js +9 -0
  47. package/dist/crypto/index.js +22 -0
  48. package/dist/crypto/math/constants.js +44 -0
  49. package/dist/crypto/math/edwards.js +64 -0
  50. package/dist/crypto/math/le.js +20 -0
  51. package/dist/crypto/math/mod.js +38 -0
  52. package/dist/crypto/math/types.js +2 -0
  53. package/dist/esm/appstate/WaAppStateCrypto.js +198 -0
  54. package/dist/esm/appstate/WaAppStateSyncClient.js +803 -0
  55. package/dist/esm/appstate/WaAppStateSyncResponseParser.js +67 -0
  56. package/dist/esm/appstate/constants.js +20 -0
  57. package/dist/esm/appstate/index.js +6 -0
  58. package/dist/esm/appstate/store/sqlite.js +49 -0
  59. package/dist/esm/appstate/types.js +1 -0
  60. package/dist/esm/appstate/utils.js +75 -0
  61. package/dist/esm/auth/WaAuthClient.js +262 -0
  62. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +118 -0
  63. package/dist/esm/auth/index.js +5 -0
  64. package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +71 -0
  65. package/dist/esm/auth/pairing/WaPairingFlow.js +324 -0
  66. package/dist/esm/auth/pairing/WaQrFlow.js +82 -0
  67. package/dist/esm/auth/pairing/constants.js +2 -0
  68. package/dist/esm/auth/types.js +1 -0
  69. package/dist/esm/client/WaClient.js +745 -0
  70. package/dist/esm/client/WaClientFactory.js +377 -0
  71. package/dist/esm/client/coordinators/WaGroupCoordinator.js +188 -0
  72. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +311 -0
  73. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +1057 -0
  74. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +196 -0
  75. package/dist/esm/client/coordinators/WaRetryCoordinator.js +490 -0
  76. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +120 -0
  77. package/dist/esm/client/dirty.js +250 -0
  78. package/dist/esm/client/events/chat.js +223 -0
  79. package/dist/esm/client/events/group.js +407 -0
  80. package/dist/esm/client/history-sync.js +119 -0
  81. package/dist/esm/client/incoming.js +227 -0
  82. package/dist/esm/client/index.js +1 -0
  83. package/dist/esm/client/mailbox.js +46 -0
  84. package/dist/esm/client/messages.js +148 -0
  85. package/dist/esm/client/types.js +1 -0
  86. package/dist/esm/crypto/core/constants.js +1 -0
  87. package/dist/esm/crypto/core/encoding.js +25 -0
  88. package/dist/esm/crypto/core/hkdf.js +22 -0
  89. package/dist/esm/crypto/core/index.js +11 -0
  90. package/dist/esm/crypto/core/keys.js +66 -0
  91. package/dist/esm/crypto/core/nonce.js +15 -0
  92. package/dist/esm/crypto/core/primitives.js +102 -0
  93. package/dist/esm/crypto/core/random.js +28 -0
  94. package/dist/esm/crypto/curves/Ed25519.js +38 -0
  95. package/dist/esm/crypto/curves/X25519.js +58 -0
  96. package/dist/esm/crypto/curves/constants.js +3 -0
  97. package/dist/esm/crypto/curves/types.js +6 -0
  98. package/dist/esm/crypto/index.js +3 -0
  99. package/dist/esm/crypto/math/constants.js +41 -0
  100. package/dist/esm/crypto/math/edwards.js +60 -0
  101. package/dist/esm/crypto/math/le.js +16 -0
  102. package/dist/esm/crypto/math/mod.js +31 -0
  103. package/dist/esm/crypto/math/types.js +1 -0
  104. package/dist/esm/index.js +6 -0
  105. package/dist/esm/infra/log/ConsoleLogger.js +40 -0
  106. package/dist/esm/infra/log/PinoLogger.js +73 -0
  107. package/dist/esm/infra/log/types.js +1 -0
  108. package/dist/esm/infra/perf/BoundedTaskQueue.js +62 -0
  109. package/dist/esm/media/WaMediaCrypto.js +224 -0
  110. package/dist/esm/media/WaMediaTransferClient.js +361 -0
  111. package/dist/esm/media/conn.js +33 -0
  112. package/dist/esm/media/constants.js +18 -0
  113. package/dist/esm/media/index.js +3 -0
  114. package/dist/esm/media/types.js +1 -0
  115. package/dist/esm/message/WaMessageClient.js +210 -0
  116. package/dist/esm/message/ack.js +46 -0
  117. package/dist/esm/message/content.js +20 -0
  118. package/dist/esm/message/device-sent.js +49 -0
  119. package/dist/esm/message/incoming.js +318 -0
  120. package/dist/esm/message/index.js +2 -0
  121. package/dist/esm/message/padding.js +20 -0
  122. package/dist/esm/message/phash.js +25 -0
  123. package/dist/esm/message/types.js +1 -0
  124. package/dist/esm/package.json +3 -0
  125. package/dist/esm/proto.js +3 -0
  126. package/dist/esm/protocol/appstate.js +34 -0
  127. package/dist/esm/protocol/auth.js +12 -0
  128. package/dist/esm/protocol/browser.js +41 -0
  129. package/dist/esm/protocol/constants.js +11 -0
  130. package/dist/esm/protocol/defaults.js +27 -0
  131. package/dist/esm/protocol/dirty.js +26 -0
  132. package/dist/esm/protocol/group.js +5 -0
  133. package/dist/esm/protocol/index.js +11 -0
  134. package/dist/esm/protocol/jid.js +94 -0
  135. package/dist/esm/protocol/media.js +20 -0
  136. package/dist/esm/protocol/message.js +16 -0
  137. package/dist/esm/protocol/nodes.js +83 -0
  138. package/dist/esm/protocol/notification.js +50 -0
  139. package/dist/esm/protocol/stream.js +60 -0
  140. package/dist/esm/retry/constants.js +20 -0
  141. package/dist/esm/retry/index.js +5 -0
  142. package/dist/esm/retry/outbound.js +83 -0
  143. package/dist/esm/retry/parse.js +130 -0
  144. package/dist/esm/retry/reason.js +50 -0
  145. package/dist/esm/retry/replay.js +177 -0
  146. package/dist/esm/retry/types.js +1 -0
  147. package/dist/esm/signal/api/SignalDeviceSyncApi.js +185 -0
  148. package/dist/esm/signal/api/SignalDigestSyncApi.js +179 -0
  149. package/dist/esm/signal/api/SignalIdentitySyncApi.js +111 -0
  150. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +141 -0
  151. package/dist/esm/signal/api/SignalRotateKeyApi.js +59 -0
  152. package/dist/esm/signal/api/SignalSessionSyncApi.js +187 -0
  153. package/dist/esm/signal/api/codec.js +23 -0
  154. package/dist/esm/signal/api/constants.js +9 -0
  155. package/dist/esm/signal/api/prekeys.js +9 -0
  156. package/dist/esm/signal/constants.js +16 -0
  157. package/dist/esm/signal/crypto/WaAdvSignature.js +60 -0
  158. package/dist/esm/signal/crypto/constants.js +8 -0
  159. package/dist/esm/signal/group/SenderKeyChain.js +97 -0
  160. package/dist/esm/signal/group/SenderKeyCodec.js +46 -0
  161. package/dist/esm/signal/group/SenderKeyManager.js +176 -0
  162. package/dist/esm/signal/index.js +11 -0
  163. package/dist/esm/signal/registration/keygen.js +31 -0
  164. package/dist/esm/signal/registration/utils.js +16 -0
  165. package/dist/esm/signal/session/SignalProtocol.js +122 -0
  166. package/dist/esm/signal/session/SignalRatchet.js +260 -0
  167. package/dist/esm/signal/session/SignalSerializer.js +63 -0
  168. package/dist/esm/signal/session/SignalSession.js +153 -0
  169. package/dist/esm/signal/store/sqlite.js +310 -0
  170. package/dist/esm/signal/types.js +1 -0
  171. package/dist/esm/store/contracts/appstate.store.js +1 -0
  172. package/dist/esm/store/contracts/auth.store.js +1 -0
  173. package/dist/esm/store/contracts/contact.store.js +1 -0
  174. package/dist/esm/store/contracts/device-list.store.js +1 -0
  175. package/dist/esm/store/contracts/message.store.js +1 -0
  176. package/dist/esm/store/contracts/participants.store.js +1 -0
  177. package/dist/esm/store/contracts/retry.store.js +1 -0
  178. package/dist/esm/store/contracts/sender-key.store.js +1 -0
  179. package/dist/esm/store/contracts/signal.store.js +1 -0
  180. package/dist/esm/store/contracts/thread.store.js +1 -0
  181. package/dist/esm/store/createStore.js +278 -0
  182. package/dist/esm/store/index.js +20 -0
  183. package/dist/esm/store/noop.store.js +43 -0
  184. package/dist/esm/store/providers/memory/appstate.store.js +101 -0
  185. package/dist/esm/store/providers/memory/contact.store.js +23 -0
  186. package/dist/esm/store/providers/memory/device-list.store.js +86 -0
  187. package/dist/esm/store/providers/memory/message.store.js +40 -0
  188. package/dist/esm/store/providers/memory/participants.store.js +61 -0
  189. package/dist/esm/store/providers/memory/retry.store.js +71 -0
  190. package/dist/esm/store/providers/memory/sender-key.store.js +88 -0
  191. package/dist/esm/store/providers/memory/signal.store.js +170 -0
  192. package/dist/esm/store/providers/memory/thread.store.js +34 -0
  193. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +37 -0
  194. package/dist/esm/store/providers/sqlite/appstate.store.js +169 -0
  195. package/dist/esm/store/providers/sqlite/auth.store.js +176 -0
  196. package/dist/esm/store/providers/sqlite/connection.js +240 -0
  197. package/dist/esm/store/providers/sqlite/contact.store.js +61 -0
  198. package/dist/esm/store/providers/sqlite/device-list.store.js +155 -0
  199. package/dist/esm/store/providers/sqlite/message.store.js +119 -0
  200. package/dist/esm/store/providers/sqlite/migrations.js +347 -0
  201. package/dist/esm/store/providers/sqlite/participants.store.js +85 -0
  202. package/dist/esm/store/providers/sqlite/retry.store.js +144 -0
  203. package/dist/esm/store/providers/sqlite/sender-key.store.js +203 -0
  204. package/dist/esm/store/providers/sqlite/signal.store.js +353 -0
  205. package/dist/esm/store/providers/sqlite/thread.store.js +72 -0
  206. package/dist/esm/store/types.js +1 -0
  207. package/dist/esm/transport/WaComms.js +527 -0
  208. package/dist/esm/transport/WaWebSocket.js +361 -0
  209. package/dist/esm/transport/binary/constants.js +96 -0
  210. package/dist/esm/transport/binary/decoder.js +275 -0
  211. package/dist/esm/transport/binary/encoder.js +210 -0
  212. package/dist/esm/transport/binary/index.js +4 -0
  213. package/dist/esm/transport/binary/tokens.js +1280 -0
  214. package/dist/esm/transport/index.js +6 -0
  215. package/dist/esm/transport/keepalive/WaKeepAlive.js +141 -0
  216. package/dist/esm/transport/node/WaNodeOrchestrator.js +143 -0
  217. package/dist/esm/transport/node/WaNodeTransport.js +64 -0
  218. package/dist/esm/transport/node/builders/accountSync.js +101 -0
  219. package/dist/esm/transport/node/builders/group.js +47 -0
  220. package/dist/esm/transport/node/builders/index.js +7 -0
  221. package/dist/esm/transport/node/builders/media.js +10 -0
  222. package/dist/esm/transport/node/builders/message.js +317 -0
  223. package/dist/esm/transport/node/builders/pairing.js +130 -0
  224. package/dist/esm/transport/node/builders/prekeys.js +102 -0
  225. package/dist/esm/transport/node/builders/retry.js +116 -0
  226. package/dist/esm/transport/node/helpers.js +37 -0
  227. package/dist/esm/transport/node/query.js +53 -0
  228. package/dist/esm/transport/node/xml.js +39 -0
  229. package/dist/esm/transport/noise/WaClientPayload.js +162 -0
  230. package/dist/esm/transport/noise/WaFrameCodec.js +121 -0
  231. package/dist/esm/transport/noise/WaNoiseCert.js +74 -0
  232. package/dist/esm/transport/noise/WaNoiseHandshake.js +57 -0
  233. package/dist/esm/transport/noise/WaNoiseSession.js +322 -0
  234. package/dist/esm/transport/noise/WaNoiseSocket.js +17 -0
  235. package/dist/esm/transport/noise/constants.js +8 -0
  236. package/dist/esm/transport/noise/types.js +1 -0
  237. package/dist/esm/transport/stream/parse.js +91 -0
  238. package/dist/esm/transport/types.js +1 -0
  239. package/dist/esm/util/async.js +5 -0
  240. package/dist/esm/util/base64.js +18 -0
  241. package/dist/esm/util/bytes.js +275 -0
  242. package/dist/esm/util/coercion.js +56 -0
  243. package/dist/esm/util/collections.js +27 -0
  244. package/dist/esm/util/primitives.js +32 -0
  245. package/dist/esm/util/runtime.js +15 -0
  246. package/dist/esm/util/signal-address.js +5 -0
  247. package/dist/index.js +52 -0
  248. package/dist/infra/log/ConsoleLogger.js +44 -0
  249. package/dist/infra/log/PinoLogger.js +111 -0
  250. package/dist/infra/log/types.js +2 -0
  251. package/dist/infra/perf/BoundedTaskQueue.js +67 -0
  252. package/dist/media/WaMediaCrypto.js +228 -0
  253. package/dist/media/WaMediaTransferClient.js +365 -0
  254. package/dist/media/conn.js +36 -0
  255. package/dist/media/constants.js +21 -0
  256. package/dist/media/index.js +9 -0
  257. package/dist/media/types.js +2 -0
  258. package/dist/message/WaMessageClient.js +214 -0
  259. package/dist/message/ack.js +52 -0
  260. package/dist/message/content.js +24 -0
  261. package/dist/message/device-sent.js +53 -0
  262. package/dist/message/incoming.js +321 -0
  263. package/dist/message/index.js +20 -0
  264. package/dist/message/padding.js +24 -0
  265. package/dist/message/phash.js +28 -0
  266. package/dist/message/types.js +2 -0
  267. package/dist/proto.js +5 -0
  268. package/dist/protocol/appstate.js +37 -0
  269. package/dist/protocol/auth.js +15 -0
  270. package/dist/protocol/browser.js +45 -0
  271. package/dist/protocol/constants.js +46 -0
  272. package/dist/protocol/defaults.js +30 -0
  273. package/dist/protocol/dirty.js +29 -0
  274. package/dist/protocol/group.js +8 -0
  275. package/dist/protocol/index.js +53 -0
  276. package/dist/protocol/jid.js +107 -0
  277. package/dist/protocol/media.js +24 -0
  278. package/dist/protocol/message.js +19 -0
  279. package/dist/protocol/nodes.js +86 -0
  280. package/dist/protocol/notification.js +53 -0
  281. package/dist/protocol/stream.js +63 -0
  282. package/dist/retry/constants.js +23 -0
  283. package/dist/retry/index.js +19 -0
  284. package/dist/retry/outbound.js +88 -0
  285. package/dist/retry/parse.js +133 -0
  286. package/dist/retry/reason.js +53 -0
  287. package/dist/retry/replay.js +181 -0
  288. package/dist/retry/types.js +2 -0
  289. package/dist/signal/api/SignalDeviceSyncApi.js +189 -0
  290. package/dist/signal/api/SignalDigestSyncApi.js +183 -0
  291. package/dist/signal/api/SignalIdentitySyncApi.js +115 -0
  292. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +145 -0
  293. package/dist/signal/api/SignalRotateKeyApi.js +63 -0
  294. package/dist/signal/api/SignalSessionSyncApi.js +191 -0
  295. package/dist/signal/api/codec.js +27 -0
  296. package/dist/signal/api/constants.js +12 -0
  297. package/dist/signal/api/prekeys.js +16 -0
  298. package/dist/signal/constants.js +19 -0
  299. package/dist/signal/crypto/WaAdvSignature.js +72 -0
  300. package/dist/signal/crypto/constants.js +11 -0
  301. package/dist/signal/group/SenderKeyChain.js +101 -0
  302. package/dist/signal/group/SenderKeyCodec.js +50 -0
  303. package/dist/signal/group/SenderKeyManager.js +180 -0
  304. package/dist/signal/index.js +29 -0
  305. package/dist/signal/registration/keygen.js +37 -0
  306. package/dist/signal/registration/utils.js +19 -0
  307. package/dist/signal/session/SignalProtocol.js +126 -0
  308. package/dist/signal/session/SignalRatchet.js +268 -0
  309. package/dist/signal/session/SignalSerializer.js +69 -0
  310. package/dist/signal/session/SignalSession.js +165 -0
  311. package/dist/signal/store/sqlite.js +324 -0
  312. package/dist/signal/types.js +2 -0
  313. package/dist/store/contracts/appstate.store.js +2 -0
  314. package/dist/store/contracts/auth.store.js +2 -0
  315. package/dist/store/contracts/contact.store.js +2 -0
  316. package/dist/store/contracts/device-list.store.js +2 -0
  317. package/dist/store/contracts/message.store.js +2 -0
  318. package/dist/store/contracts/participants.store.js +2 -0
  319. package/dist/store/contracts/retry.store.js +2 -0
  320. package/dist/store/contracts/sender-key.store.js +2 -0
  321. package/dist/store/contracts/signal.store.js +2 -0
  322. package/dist/store/contracts/thread.store.js +2 -0
  323. package/dist/store/createStore.js +281 -0
  324. package/dist/store/index.js +43 -0
  325. package/dist/store/noop.store.js +46 -0
  326. package/dist/store/providers/memory/appstate.store.js +105 -0
  327. package/dist/store/providers/memory/contact.store.js +27 -0
  328. package/dist/store/providers/memory/device-list.store.js +90 -0
  329. package/dist/store/providers/memory/message.store.js +44 -0
  330. package/dist/store/providers/memory/participants.store.js +65 -0
  331. package/dist/store/providers/memory/retry.store.js +75 -0
  332. package/dist/store/providers/memory/sender-key.store.js +92 -0
  333. package/dist/store/providers/memory/signal.store.js +174 -0
  334. package/dist/store/providers/memory/thread.store.js +38 -0
  335. package/dist/store/providers/sqlite/BaseSqliteStore.js +41 -0
  336. package/dist/store/providers/sqlite/appstate.store.js +173 -0
  337. package/dist/store/providers/sqlite/auth.store.js +180 -0
  338. package/dist/store/providers/sqlite/connection.js +276 -0
  339. package/dist/store/providers/sqlite/contact.store.js +65 -0
  340. package/dist/store/providers/sqlite/device-list.store.js +159 -0
  341. package/dist/store/providers/sqlite/message.store.js +123 -0
  342. package/dist/store/providers/sqlite/migrations.js +350 -0
  343. package/dist/store/providers/sqlite/participants.store.js +89 -0
  344. package/dist/store/providers/sqlite/retry.store.js +148 -0
  345. package/dist/store/providers/sqlite/sender-key.store.js +207 -0
  346. package/dist/store/providers/sqlite/signal.store.js +357 -0
  347. package/dist/store/providers/sqlite/thread.store.js +76 -0
  348. package/dist/store/types.js +2 -0
  349. package/dist/transport/WaComms.js +531 -0
  350. package/dist/transport/WaWebSocket.js +365 -0
  351. package/dist/transport/binary/constants.js +99 -0
  352. package/dist/transport/binary/decoder.js +279 -0
  353. package/dist/transport/binary/encoder.js +214 -0
  354. package/dist/transport/binary/index.js +23 -0
  355. package/dist/transport/binary/tokens.js +1283 -0
  356. package/dist/transport/index.js +18 -0
  357. package/dist/transport/keepalive/WaKeepAlive.js +145 -0
  358. package/dist/transport/node/WaNodeOrchestrator.js +147 -0
  359. package/dist/transport/node/WaNodeTransport.js +68 -0
  360. package/dist/transport/node/builders/accountSync.js +110 -0
  361. package/dist/transport/node/builders/group.js +52 -0
  362. package/dist/transport/node/builders/index.js +39 -0
  363. package/dist/transport/node/builders/media.js +13 -0
  364. package/dist/transport/node/builders/message.js +328 -0
  365. package/dist/transport/node/builders/pairing.js +137 -0
  366. package/dist/transport/node/builders/prekeys.js +107 -0
  367. package/dist/transport/node/builders/retry.js +119 -0
  368. package/dist/transport/node/helpers.js +46 -0
  369. package/dist/transport/node/query.js +59 -0
  370. package/dist/transport/node/xml.js +42 -0
  371. package/dist/transport/noise/WaClientPayload.js +166 -0
  372. package/dist/transport/noise/WaFrameCodec.js +125 -0
  373. package/dist/transport/noise/WaNoiseCert.js +77 -0
  374. package/dist/transport/noise/WaNoiseHandshake.js +61 -0
  375. package/dist/transport/noise/WaNoiseSession.js +326 -0
  376. package/dist/transport/noise/WaNoiseSocket.js +21 -0
  377. package/dist/transport/noise/constants.js +11 -0
  378. package/dist/transport/noise/types.js +2 -0
  379. package/dist/transport/stream/parse.js +97 -0
  380. package/dist/transport/types.js +2 -0
  381. package/dist/types/appstate/WaAppStateCrypto.d.ts +59 -0
  382. package/dist/types/appstate/WaAppStateSyncClient.d.ts +63 -0
  383. package/dist/types/appstate/WaAppStateSyncResponseParser.d.ts +12 -0
  384. package/dist/types/appstate/constants.d.ts +14 -0
  385. package/dist/types/appstate/index.d.ts +7 -0
  386. package/dist/types/appstate/store/sqlite.d.ts +21 -0
  387. package/dist/types/appstate/types.d.ts +66 -0
  388. package/dist/types/appstate/utils.d.ts +10 -0
  389. package/dist/types/auth/WaAuthClient.d.ts +61 -0
  390. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +14 -0
  391. package/dist/types/auth/index.d.ts +6 -0
  392. package/dist/types/auth/pairing/WaPairingCodeCrypto.d.ts +17 -0
  393. package/dist/types/auth/pairing/WaPairingFlow.d.ts +48 -0
  394. package/dist/types/auth/pairing/WaQrFlow.d.ts +23 -0
  395. package/dist/types/auth/pairing/constants.d.ts +2 -0
  396. package/dist/types/auth/types.d.ts +48 -0
  397. package/dist/types/client/WaClient.d.ts +97 -0
  398. package/dist/types/client/WaClientFactory.d.ts +83 -0
  399. package/dist/types/client/coordinators/WaGroupCoordinator.d.ts +48 -0
  400. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +60 -0
  401. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +90 -0
  402. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +43 -0
  403. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +61 -0
  404. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +17 -0
  405. package/dist/types/client/dirty.d.ts +17 -0
  406. package/dist/types/client/events/chat.d.ts +3 -0
  407. package/dist/types/client/events/group.d.ts +7 -0
  408. package/dist/types/client/history-sync.d.ts +17 -0
  409. package/dist/types/client/incoming.d.ts +35 -0
  410. package/dist/types/client/index.d.ts +2 -0
  411. package/dist/types/client/mailbox.d.ts +12 -0
  412. package/dist/types/client/messages.d.ts +17 -0
  413. package/dist/types/client/types.d.ts +235 -0
  414. package/dist/types/crypto/core/constants.d.ts +1 -0
  415. package/dist/types/crypto/core/encoding.d.ts +11 -0
  416. package/dist/types/crypto/core/hkdf.d.ts +8 -0
  417. package/dist/types/crypto/core/index.d.ts +11 -0
  418. package/dist/types/crypto/core/keys.d.ts +20 -0
  419. package/dist/types/crypto/core/nonce.d.ts +5 -0
  420. package/dist/types/crypto/core/primitives.d.ts +25 -0
  421. package/dist/types/crypto/core/random.d.ts +8 -0
  422. package/dist/types/crypto/curves/Ed25519.d.ts +7 -0
  423. package/dist/types/crypto/curves/X25519.d.ts +8 -0
  424. package/dist/types/crypto/curves/constants.d.ts +2 -0
  425. package/dist/types/crypto/curves/types.d.ts +10 -0
  426. package/dist/types/crypto/index.d.ts +3 -0
  427. package/dist/types/crypto/math/constants.d.ts +7 -0
  428. package/dist/types/crypto/math/edwards.d.ts +3 -0
  429. package/dist/types/crypto/math/le.d.ts +2 -0
  430. package/dist/types/crypto/math/mod.d.ts +5 -0
  431. package/dist/types/crypto/math/types.d.ts +6 -0
  432. package/dist/types/index.d.ts +10 -0
  433. package/dist/types/infra/log/ConsoleLogger.d.ts +11 -0
  434. package/dist/types/infra/log/PinoLogger.d.ts +30 -0
  435. package/dist/types/infra/log/types.d.ts +9 -0
  436. package/dist/types/infra/perf/BoundedTaskQueue.d.ts +19 -0
  437. package/dist/types/media/WaMediaCrypto.d.ts +12 -0
  438. package/dist/types/media/WaMediaTransferClient.d.ts +81 -0
  439. package/dist/types/media/conn.d.ts +3 -0
  440. package/dist/types/media/constants.d.ts +10 -0
  441. package/dist/types/media/index.d.ts +4 -0
  442. package/dist/types/media/types.d.ts +56 -0
  443. package/dist/types/message/WaMessageClient.d.ts +29 -0
  444. package/dist/types/message/ack.d.ts +5 -0
  445. package/dist/types/message/content.d.ts +4 -0
  446. package/dist/types/message/device-sent.d.ts +3 -0
  447. package/dist/types/message/incoming.d.ts +18 -0
  448. package/dist/types/message/index.d.ts +2 -0
  449. package/dist/types/message/padding.d.ts +2 -0
  450. package/dist/types/message/phash.d.ts +1 -0
  451. package/dist/types/message/types.d.ts +58 -0
  452. package/dist/types/proto.d.ts +2 -0
  453. package/dist/types/protocol/appstate.d.ts +34 -0
  454. package/dist/types/protocol/auth.d.ts +12 -0
  455. package/dist/types/protocol/browser.d.ts +22 -0
  456. package/dist/types/protocol/constants.d.ts +11 -0
  457. package/dist/types/protocol/defaults.d.ts +26 -0
  458. package/dist/types/protocol/dirty.d.ts +15 -0
  459. package/dist/types/protocol/group.d.ts +6 -0
  460. package/dist/types/protocol/index.d.ts +11 -0
  461. package/dist/types/protocol/jid.d.ts +19 -0
  462. package/dist/types/protocol/media.d.ts +15 -0
  463. package/dist/types/protocol/message.d.ts +16 -0
  464. package/dist/types/protocol/nodes.d.ts +83 -0
  465. package/dist/types/protocol/notification.d.ts +50 -0
  466. package/dist/types/protocol/stream.d.ts +60 -0
  467. package/dist/types/retry/constants.d.ts +21 -0
  468. package/dist/types/retry/index.d.ts +7 -0
  469. package/dist/types/retry/outbound.d.ts +4 -0
  470. package/dist/types/retry/parse.d.ts +3 -0
  471. package/dist/types/retry/reason.d.ts +2 -0
  472. package/dist/types/retry/replay.d.ts +30 -0
  473. package/dist/types/retry/types.d.ts +70 -0
  474. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +31 -0
  475. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +27 -0
  476. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +26 -0
  477. package/dist/types/signal/api/SignalMissingPreKeysSyncApi.d.ts +39 -0
  478. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +22 -0
  479. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +38 -0
  480. package/dist/types/signal/api/codec.d.ts +3 -0
  481. package/dist/types/signal/api/constants.d.ts +9 -0
  482. package/dist/types/signal/api/prekeys.d.ts +6 -0
  483. package/dist/types/signal/constants.d.ts +14 -0
  484. package/dist/types/signal/crypto/WaAdvSignature.d.ts +7 -0
  485. package/dist/types/signal/crypto/constants.d.ts +5 -0
  486. package/dist/types/signal/group/SenderKeyChain.d.ts +11 -0
  487. package/dist/types/signal/group/SenderKeyCodec.d.ts +14 -0
  488. package/dist/types/signal/group/SenderKeyManager.d.ts +22 -0
  489. package/dist/types/signal/index.d.ts +12 -0
  490. package/dist/types/signal/registration/keygen.d.ts +5 -0
  491. package/dist/types/signal/registration/utils.d.ts +9 -0
  492. package/dist/types/signal/session/SignalProtocol.d.ts +22 -0
  493. package/dist/types/signal/session/SignalRatchet.d.ts +25 -0
  494. package/dist/types/signal/session/SignalSerializer.d.ts +6 -0
  495. package/dist/types/signal/session/SignalSession.d.ts +43 -0
  496. package/dist/types/signal/store/sqlite.d.ts +72 -0
  497. package/dist/types/signal/types.d.ts +110 -0
  498. package/dist/types/store/contracts/appstate.store.d.ts +22 -0
  499. package/dist/types/store/contracts/auth.store.d.ts +6 -0
  500. package/dist/types/store/contracts/contact.store.d.ts +14 -0
  501. package/dist/types/store/contracts/device-list.store.d.ts +16 -0
  502. package/dist/types/store/contracts/message.store.d.ts +18 -0
  503. package/dist/types/store/contracts/participants.store.d.ts +14 -0
  504. package/dist/types/store/contracts/retry.store.d.ts +11 -0
  505. package/dist/types/store/contracts/sender-key.store.d.ts +16 -0
  506. package/dist/types/store/contracts/signal.store.d.ts +31 -0
  507. package/dist/types/store/contracts/thread.store.d.ts +17 -0
  508. package/dist/types/store/createStore.d.ts +2 -0
  509. package/dist/types/store/index.d.ts +31 -0
  510. package/dist/types/store/noop.store.d.ts +10 -0
  511. package/dist/types/store/providers/memory/appstate.store.d.ts +21 -0
  512. package/dist/types/store/providers/memory/contact.store.d.ts +13 -0
  513. package/dist/types/store/providers/memory/device-list.store.d.ts +20 -0
  514. package/dist/types/store/providers/memory/message.store.d.ts +14 -0
  515. package/dist/types/store/providers/memory/participants.store.d.ts +18 -0
  516. package/dist/types/store/providers/memory/retry.store.d.ts +18 -0
  517. package/dist/types/store/providers/memory/sender-key.store.d.ts +28 -0
  518. package/dist/types/store/providers/memory/signal.store.d.ts +51 -0
  519. package/dist/types/store/providers/memory/thread.store.d.ts +14 -0
  520. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +12 -0
  521. package/dist/types/store/providers/sqlite/appstate.store.d.ts +15 -0
  522. package/dist/types/store/providers/sqlite/auth.store.d.ts +10 -0
  523. package/dist/types/store/providers/sqlite/connection.d.ts +10 -0
  524. package/dist/types/store/providers/sqlite/contact.store.d.ts +10 -0
  525. package/dist/types/store/providers/sqlite/device-list.store.d.ts +18 -0
  526. package/dist/types/store/providers/sqlite/message.store.d.ts +11 -0
  527. package/dist/types/store/providers/sqlite/migrations.d.ts +3 -0
  528. package/dist/types/store/providers/sqlite/participants.store.d.ts +13 -0
  529. package/dist/types/store/providers/sqlite/retry.store.d.ts +16 -0
  530. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +25 -0
  531. package/dist/types/store/providers/sqlite/signal.store.d.ts +46 -0
  532. package/dist/types/store/providers/sqlite/thread.store.d.ts +11 -0
  533. package/dist/types/store/types.d.ts +103 -0
  534. package/dist/types/transport/WaComms.d.ts +61 -0
  535. package/dist/types/transport/WaWebSocket.d.ts +36 -0
  536. package/dist/types/transport/binary/constants.d.ts +49 -0
  537. package/dist/types/transport/binary/decoder.d.ts +3 -0
  538. package/dist/types/transport/binary/encoder.d.ts +3 -0
  539. package/dist/types/transport/binary/index.d.ts +4 -0
  540. package/dist/types/transport/binary/tokens.d.ts +11 -0
  541. package/dist/types/transport/index.d.ts +7 -0
  542. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +39 -0
  543. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +28 -0
  544. package/dist/types/transport/node/WaNodeTransport.d.ts +22 -0
  545. package/dist/types/transport/node/builders/accountSync.d.ts +11 -0
  546. package/dist/types/transport/node/builders/group.d.ts +16 -0
  547. package/dist/types/transport/node/builders/index.d.ts +7 -0
  548. package/dist/types/transport/node/builders/media.d.ts +2 -0
  549. package/dist/types/transport/node/builders/message.d.ts +52 -0
  550. package/dist/types/transport/node/builders/pairing.d.ts +18 -0
  551. package/dist/types/transport/node/builders/prekeys.d.ts +5 -0
  552. package/dist/types/transport/node/builders/retry.d.ts +18 -0
  553. package/dist/types/transport/node/helpers.d.ts +8 -0
  554. package/dist/types/transport/node/query.d.ts +10 -0
  555. package/dist/types/transport/node/xml.d.ts +2 -0
  556. package/dist/types/transport/noise/WaClientPayload.d.ts +3 -0
  557. package/dist/types/transport/noise/WaFrameCodec.d.ts +9 -0
  558. package/dist/types/transport/noise/WaNoiseCert.d.ts +1 -0
  559. package/dist/types/transport/noise/WaNoiseHandshake.d.ts +14 -0
  560. package/dist/types/transport/noise/WaNoiseSession.d.ts +33 -0
  561. package/dist/types/transport/noise/WaNoiseSocket.d.ts +10 -0
  562. package/dist/types/transport/noise/constants.d.ts +7 -0
  563. package/dist/types/transport/noise/types.d.ts +23 -0
  564. package/dist/types/transport/stream/parse.d.ts +23 -0
  565. package/dist/types/transport/types.d.ts +71 -0
  566. package/dist/types/util/async.d.ts +1 -0
  567. package/dist/types/util/base64.d.ts +4 -0
  568. package/dist/types/util/bytes.d.ts +28 -0
  569. package/dist/types/util/coercion.d.ts +8 -0
  570. package/dist/types/util/collections.d.ts +3 -0
  571. package/dist/types/util/primitives.d.ts +7 -0
  572. package/dist/types/util/runtime.d.ts +2 -0
  573. package/dist/types/util/signal-address.d.ts +2 -0
  574. package/dist/util/async.js +8 -0
  575. package/dist/util/base64.js +24 -0
  576. package/dist/util/bytes.js +291 -0
  577. package/dist/util/coercion.js +66 -0
  578. package/dist/util/collections.js +32 -0
  579. package/dist/util/primitives.js +37 -0
  580. package/dist/util/runtime.js +19 -0
  581. package/dist/util/signal-address.js +8 -0
  582. package/package.json +150 -0
  583. package/proto/index.d.ts +10861 -0
  584. package/proto/index.js +1 -0
  585. package/scripts/check-node-version.cjs +55 -0
@@ -0,0 +1,1061 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WaMessageDispatchCoordinator = void 0;
4
+ const keys_1 = require("../../crypto/core/keys");
5
+ const content_1 = require("../../message/content");
6
+ const device_sent_1 = require("../../message/device-sent");
7
+ const padding_1 = require("../../message/padding");
8
+ const phash_1 = require("../../message/phash");
9
+ const _proto_1 = require("../../proto.js");
10
+ const constants_1 = require("../../protocol/constants");
11
+ const jid_1 = require("../../protocol/jid");
12
+ const constants_2 = require("../../retry/constants");
13
+ const outbound_1 = require("../../retry/outbound");
14
+ const binary_1 = require("../../transport/binary");
15
+ const message_1 = require("../../transport/node/builders/message");
16
+ const bytes_1 = require("../../util/bytes");
17
+ const primitives_1 = require("../../util/primitives");
18
+ const signal_address_1 = require("../../util/signal-address");
19
+ class WaMessageDispatchCoordinator {
20
+ constructor(options) {
21
+ this.logger = options.logger;
22
+ this.messageClient = options.messageClient;
23
+ this.retryStore = options.retryStore;
24
+ this.participantsStore = options.participantsStore;
25
+ this.retryTtlMs = this.retryStore.getTtlMs?.() ?? constants_2.RETRY_OUTBOUND_TTL_MS;
26
+ this.buildMessageContent = options.buildMessageContent;
27
+ this.queryGroupParticipantJids = options.queryGroupParticipantJids;
28
+ this.senderKeyManager = options.senderKeyManager;
29
+ this.signalProtocol = options.signalProtocol;
30
+ this.signalStore = options.signalStore;
31
+ this.signalDeviceSync = options.signalDeviceSync;
32
+ this.signalIdentitySync = options.signalIdentitySync;
33
+ this.signalSessionSync = options.signalSessionSync;
34
+ this.getCurrentMeJid = options.getCurrentMeJid;
35
+ this.getCurrentMeLid = options.getCurrentMeLid;
36
+ this.getCurrentSignedIdentity = options.getCurrentSignedIdentity;
37
+ }
38
+ async publishMessageNode(node, options = {}) {
39
+ this.logger.debug('wa client publish message node', {
40
+ tag: node.tag,
41
+ type: node.attrs.type,
42
+ to: node.attrs.to
43
+ });
44
+ const messageType = node.attrs.type ?? 'text';
45
+ const replayPayload = {
46
+ mode: 'opaque_node',
47
+ node: (0, binary_1.encodeBinaryNode)(node)
48
+ };
49
+ return this.publishWithRetryTracking({
50
+ messageIdHint: node.attrs.id,
51
+ toJid: node.attrs.to,
52
+ participantJid: node.attrs.participant,
53
+ recipientJid: node.attrs.recipient,
54
+ messageType,
55
+ replayPayload
56
+ }, async () => this.messageClient.publishNode(node, options));
57
+ }
58
+ async publishEncryptedMessage(input, options = {}) {
59
+ this.logger.debug('wa client publish encrypted message', {
60
+ to: input.to,
61
+ type: input.type,
62
+ encType: input.encType
63
+ });
64
+ const replayPayload = {
65
+ mode: 'encrypted',
66
+ to: input.to,
67
+ type: input.type ?? 'text',
68
+ encType: input.encType,
69
+ ciphertext: input.ciphertext,
70
+ participant: input.participant
71
+ };
72
+ return this.publishWithRetryTracking({
73
+ messageIdHint: input.id,
74
+ toJid: input.to,
75
+ participantJid: input.participant,
76
+ messageType: input.type ?? 'text',
77
+ replayPayload
78
+ }, async () => this.messageClient.publishEncrypted(input, options));
79
+ }
80
+ async publishSignalMessage(input, options = {}) {
81
+ this.requireCurrentMeJid('publishSignalMessage');
82
+ const address = (0, jid_1.parseSignalAddressFromJid)(input.to);
83
+ if (address.server === constants_1.WA_DEFAULTS.GROUP_SERVER) {
84
+ throw new Error('publishSignalMessage currently supports only direct chats; use sender-key flow for groups');
85
+ }
86
+ this.logger.debug('wa client publish signal message', {
87
+ to: input.to,
88
+ type: input.type
89
+ });
90
+ const [paddedPlaintext] = await Promise.all([
91
+ (0, padding_1.writeRandomPadMax16)(input.plaintext),
92
+ this.ensureSignalSession(address, input.to, input.expectedIdentity)
93
+ ]);
94
+ const encrypted = await this.signalProtocol.encryptMessage(address, paddedPlaintext, input.expectedIdentity);
95
+ const messageType = input.type ?? 'text';
96
+ const replayPayload = {
97
+ mode: 'plaintext',
98
+ to: input.to,
99
+ type: messageType,
100
+ plaintext: paddedPlaintext
101
+ };
102
+ return this.publishWithRetryTracking({
103
+ messageIdHint: input.id,
104
+ toJid: input.to,
105
+ participantJid: input.participant,
106
+ messageType,
107
+ replayPayload
108
+ }, async () => this.messageClient.publishEncrypted({
109
+ to: input.to,
110
+ encType: encrypted.type,
111
+ ciphertext: encrypted.ciphertext,
112
+ id: input.id,
113
+ type: input.type,
114
+ category: input.category,
115
+ pushPriority: input.pushPriority,
116
+ participant: input.participant,
117
+ deviceFanout: input.deviceFanout
118
+ }, options));
119
+ }
120
+ async sendMessage(to, content, options = {}) {
121
+ const recipientJid = (0, jid_1.normalizeRecipientJid)(to);
122
+ const message = await this.buildMessageContent(content);
123
+ const plaintext = await (0, padding_1.writeRandomPadMax16)(_proto_1.proto.Message.encode(message).finish());
124
+ const type = (0, content_1.resolveMessageTypeAttr)(message);
125
+ if ((0, jid_1.isGroupJid)(recipientJid)) {
126
+ if (this.shouldUseGroupDirectPath(message)) {
127
+ return this.publishGroupDirectMessage(recipientJid, plaintext, type, options);
128
+ }
129
+ return this.publishGroupSenderKeyMessage(recipientJid, plaintext, type, options);
130
+ }
131
+ const directRecipientJid = (0, jid_1.toUserJid)(recipientJid);
132
+ return this.publishDirectSignalMessageWithFanout(directRecipientJid, message, plaintext, type, options);
133
+ }
134
+ async syncSignalSession(jid, reasonIdentity = false) {
135
+ const address = (0, jid_1.parseSignalAddressFromJid)(jid);
136
+ if (address.server === constants_1.WA_DEFAULTS.GROUP_SERVER) {
137
+ throw new Error('syncSignalSession supports only direct chats');
138
+ }
139
+ await this.ensureSignalSession(address, jid, undefined, reasonIdentity);
140
+ }
141
+ async sendReceipt(input) {
142
+ await this.messageClient.sendReceipt(input);
143
+ }
144
+ async requestAppStateSyncKeys(keyIds) {
145
+ const normalizedKeyIds = this.normalizeKeyIds(keyIds);
146
+ if (normalizedKeyIds.length === 0) {
147
+ return [];
148
+ }
149
+ const peerDeviceJids = await this.resolveOwnPeerDeviceJids();
150
+ if (peerDeviceJids.length === 0) {
151
+ this.logger.warn('app-state sync key request skipped: no peer devices available', {
152
+ keys: normalizedKeyIds.length
153
+ });
154
+ return [];
155
+ }
156
+ const protocolMessage = {
157
+ type: _proto_1.proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_REQUEST,
158
+ appStateSyncKeyRequest: {
159
+ keyIds: normalizedKeyIds.map((keyId) => ({
160
+ keyId
161
+ }))
162
+ }
163
+ };
164
+ await Promise.all(peerDeviceJids.map((deviceJid) => this.publishProtocolMessageToDevice(deviceJid, protocolMessage)));
165
+ this.logger.info('app-state sync key request sent to peer devices', {
166
+ devices: peerDeviceJids.length,
167
+ keys: normalizedKeyIds.length,
168
+ keyIds: normalizedKeyIds.map((keyId) => (0, bytes_1.bytesToHex)(keyId)).join(',')
169
+ });
170
+ return peerDeviceJids;
171
+ }
172
+ async sendAppStateSyncKeyShare(toDeviceJid, keys, missingKeyIds = []) {
173
+ const normalizedTo = (0, jid_1.normalizeDeviceJid)(toDeviceJid);
174
+ const dedupedKeysById = new Map();
175
+ for (const key of keys) {
176
+ dedupedKeysById.set((0, bytes_1.bytesToHex)(key.keyId), key);
177
+ }
178
+ const dedupedKeys = [...dedupedKeysById.values()];
179
+ const dedupedMissingKeyIds = this.normalizeKeyIds(missingKeyIds).filter((keyId) => !dedupedKeysById.has((0, bytes_1.bytesToHex)(keyId)));
180
+ const keyShareEntries = [
181
+ ...dedupedKeys.map((key) => ({
182
+ keyId: { keyId: key.keyId },
183
+ keyData: {
184
+ keyData: key.keyData,
185
+ timestamp: key.timestamp,
186
+ ...(key.fingerprint ? { fingerprint: key.fingerprint } : {})
187
+ }
188
+ })),
189
+ ...dedupedMissingKeyIds.map((keyId) => ({
190
+ keyId: { keyId }
191
+ }))
192
+ ];
193
+ const protocolMessage = {
194
+ type: _proto_1.proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_SHARE,
195
+ appStateSyncKeyShare: {
196
+ keys: keyShareEntries
197
+ }
198
+ };
199
+ await this.publishProtocolMessageToDevice(normalizedTo, protocolMessage);
200
+ this.logger.info('app-state sync key share sent', {
201
+ to: normalizedTo,
202
+ keys: dedupedKeys.length,
203
+ orphanKeys: dedupedMissingKeyIds.length
204
+ });
205
+ }
206
+ async mutateParticipantsCacheFromGroupEvent(event) {
207
+ const groupJid = this.resolveGroupJidForParticipantCacheEvent(event);
208
+ if (!groupJid) {
209
+ return;
210
+ }
211
+ if (event.action === 'delete') {
212
+ await this.participantsStore.deleteGroupParticipants(groupJid);
213
+ return;
214
+ }
215
+ const participantUsers = this.extractParticipantUsersFromGroupEvent(event);
216
+ if (event.action === 'create') {
217
+ if (participantUsers.length === 0) {
218
+ return;
219
+ }
220
+ await this.participantsStore.upsertGroupParticipants({
221
+ groupJid,
222
+ participants: participantUsers,
223
+ updatedAtMs: Date.now()
224
+ });
225
+ return;
226
+ }
227
+ const cached = await this.participantsStore.getGroupParticipants(groupJid);
228
+ if (!cached || cached.participants.length === 0) {
229
+ return;
230
+ }
231
+ const cachedParticipants = this.sanitizeParticipantUsers(cached.participants);
232
+ if (cachedParticipants.length === 0) {
233
+ return;
234
+ }
235
+ if (event.action === 'add' ||
236
+ event.action === 'promote' ||
237
+ event.action === 'demote' ||
238
+ event.action === 'linked_group_promote' ||
239
+ event.action === 'linked_group_demote') {
240
+ await this.mergeParticipantUsersIntoCache(groupJid, cachedParticipants, participantUsers);
241
+ return;
242
+ }
243
+ if (event.action === 'remove') {
244
+ await this.removeParticipantUsersFromCache(groupJid, cachedParticipants, participantUsers);
245
+ return;
246
+ }
247
+ if (event.action === 'modify') {
248
+ const authorUsers = event.authorJid
249
+ ? this.sanitizeParticipantUsers([event.authorJid])
250
+ : [];
251
+ await this.replaceParticipantUsersInCache(groupJid, cachedParticipants, authorUsers, participantUsers);
252
+ }
253
+ }
254
+ async publishProtocolMessageToDevice(deviceJid, protocolMessage) {
255
+ const plaintext = await (0, padding_1.writeRandomPadMax16)(_proto_1.proto.Message.encode({
256
+ protocolMessage
257
+ }).finish());
258
+ await this.publishSignalMessage({
259
+ to: deviceJid,
260
+ plaintext,
261
+ type: 'protocol',
262
+ category: 'peer',
263
+ pushPriority: 'high'
264
+ });
265
+ }
266
+ async resolveOwnPeerDeviceJids() {
267
+ const meJid = this.requireCurrentMeJid('resolveOwnPeerDeviceJids');
268
+ const meUserJid = (0, jid_1.toUserJid)(meJid);
269
+ const meDevices = new Set();
270
+ meDevices.add((0, jid_1.normalizeDeviceJid)(meJid));
271
+ const meLid = this.getCurrentMeLid();
272
+ if (meLid && meLid.includes('@')) {
273
+ try {
274
+ meDevices.add((0, jid_1.normalizeDeviceJid)(meLid));
275
+ }
276
+ catch (error) {
277
+ this.logger.trace('ignoring malformed me lid jid while resolving peer devices', {
278
+ meLid,
279
+ message: (0, primitives_1.toError)(error).message
280
+ });
281
+ }
282
+ }
283
+ try {
284
+ const synced = await this.signalDeviceSync.syncDeviceList([meUserJid]);
285
+ const peerDevices = new Set();
286
+ for (const entry of synced) {
287
+ const sourceDevices = entry.deviceJids.length > 0 ? entry.deviceJids : [entry.jid];
288
+ for (const deviceJid of sourceDevices) {
289
+ try {
290
+ const normalized = (0, jid_1.normalizeDeviceJid)(deviceJid);
291
+ if (meDevices.has(normalized)) {
292
+ continue;
293
+ }
294
+ peerDevices.add(normalized);
295
+ }
296
+ catch (error) {
297
+ this.logger.trace('ignoring malformed peer device jid while resolving app-state peers', {
298
+ deviceJid,
299
+ message: (0, primitives_1.toError)(error).message
300
+ });
301
+ }
302
+ }
303
+ }
304
+ return [...peerDevices];
305
+ }
306
+ catch (error) {
307
+ this.logger.warn('failed to resolve peer devices for app-state key request', {
308
+ message: (0, primitives_1.toError)(error).message
309
+ });
310
+ return [];
311
+ }
312
+ }
313
+ normalizeKeyIds(keyIds) {
314
+ const deduped = new Map();
315
+ for (const keyId of keyIds) {
316
+ if (keyId.byteLength === 0) {
317
+ continue;
318
+ }
319
+ const keyHex = (0, bytes_1.bytesToHex)(keyId);
320
+ if (deduped.has(keyHex)) {
321
+ continue;
322
+ }
323
+ deduped.set(keyHex, keyId);
324
+ }
325
+ return [...deduped.values()];
326
+ }
327
+ async publishWithRetryTracking(args, publish) {
328
+ const nowMs = Date.now();
329
+ const expiresAtMs = nowMs + this.retryTtlMs;
330
+ const hintedMessageId = args.messageIdHint?.trim();
331
+ const resolvedToJid = args.toJid ?? (args.replayPayload.mode === 'opaque_node' ? '' : args.replayPayload.to);
332
+ let hintedPersisted = false;
333
+ if (hintedMessageId) {
334
+ hintedPersisted = await this.safeUpsertRetryOutboundRecord(this.createRetryOutboundRecord({
335
+ messageId: hintedMessageId,
336
+ toJid: resolvedToJid,
337
+ participantJid: args.participantJid,
338
+ recipientJid: args.recipientJid,
339
+ messageType: args.messageType,
340
+ replayPayload: args.replayPayload,
341
+ createdAtMs: nowMs,
342
+ updatedAtMs: nowMs,
343
+ expiresAtMs
344
+ }));
345
+ }
346
+ const result = await publish();
347
+ if (hintedPersisted && hintedMessageId && result.id === hintedMessageId) {
348
+ // Hint and final message id matched; avoid a second equivalent upsert on the hot path.
349
+ return result;
350
+ }
351
+ const persistedNowMs = Date.now();
352
+ await this.safeUpsertRetryOutboundRecord(this.createRetryOutboundRecord({
353
+ messageId: result.id,
354
+ toJid: resolvedToJid,
355
+ participantJid: args.participantJid,
356
+ recipientJid: args.recipientJid,
357
+ messageType: args.messageType,
358
+ replayPayload: args.replayPayload,
359
+ createdAtMs: hintedMessageId ? nowMs : persistedNowMs,
360
+ updatedAtMs: persistedNowMs,
361
+ expiresAtMs: persistedNowMs + this.retryTtlMs
362
+ }));
363
+ return result;
364
+ }
365
+ createRetryOutboundRecord(input) {
366
+ return {
367
+ messageId: input.messageId,
368
+ toJid: input.toJid,
369
+ participantJid: input.participantJid,
370
+ recipientJid: input.recipientJid,
371
+ messageType: input.messageType,
372
+ replayMode: input.replayPayload.mode,
373
+ replayPayload: (0, outbound_1.encodeRetryReplayPayload)(input.replayPayload),
374
+ state: 'pending',
375
+ createdAtMs: input.createdAtMs,
376
+ updatedAtMs: input.updatedAtMs,
377
+ expiresAtMs: input.expiresAtMs
378
+ };
379
+ }
380
+ async safeUpsertRetryOutboundRecord(record) {
381
+ try {
382
+ await this.retryStore.upsertOutboundMessage(record);
383
+ }
384
+ catch (error) {
385
+ this.logger.warn('failed to persist retry outbound message record', {
386
+ messageId: record.messageId,
387
+ to: record.toJid,
388
+ mode: record.replayMode,
389
+ message: (0, primitives_1.toError)(error).message
390
+ });
391
+ return false;
392
+ }
393
+ try {
394
+ await this.retryStore.cleanupExpired(Date.now());
395
+ }
396
+ catch (error) {
397
+ this.logger.warn('failed to cleanup retry records after outbound persist', {
398
+ message: (0, primitives_1.toError)(error).message
399
+ });
400
+ }
401
+ return true;
402
+ }
403
+ shouldUseGroupDirectPath(message) {
404
+ const protocolType = message.protocolMessage?.type;
405
+ if (protocolType === _proto_1.proto.Message.ProtocolMessage.Type.REVOKE ||
406
+ protocolType === _proto_1.proto.Message.ProtocolMessage.Type.MESSAGE_EDIT) {
407
+ return true;
408
+ }
409
+ return message.keepInChatMessage?.keepType === _proto_1.proto.KeepType.UNDO_KEEP_FOR_ALL;
410
+ }
411
+ async publishGroupDirectMessage(groupJid, plaintext, type, options, retryContext = {}) {
412
+ const meJid = this.requireCurrentMeJid('sendMessage');
413
+ const participantUserJids = retryContext.forceRefreshParticipants
414
+ ? await this.refreshGroupParticipantUsers(groupJid)
415
+ : await this.resolveGroupParticipantUsers(groupJid);
416
+ const addressingMode = retryContext.forceAddressingMode ??
417
+ this.resolveGroupAddressingMode(participantUserJids, groupJid);
418
+ const senderForPhash = this.resolveSenderForAddressingMode(addressingMode, meJid);
419
+ const fanoutDeviceJids = await this.resolveGroupParticipantDeviceJids(participantUserJids);
420
+ if (fanoutDeviceJids.length === 0) {
421
+ throw new Error('group direct send resolved no target devices');
422
+ }
423
+ await this.ensureSignalSessionsBatch(fanoutDeviceJids);
424
+ const participants = await Promise.all(fanoutDeviceJids.map(async (targetJid) => {
425
+ const address = (0, jid_1.parseSignalAddressFromJid)(targetJid);
426
+ await this.ensureSignalSession(address, targetJid);
427
+ const encrypted = await this.signalProtocol.encryptMessage(address, plaintext);
428
+ return {
429
+ jid: targetJid,
430
+ encType: encrypted.type,
431
+ ciphertext: encrypted.ciphertext
432
+ };
433
+ }));
434
+ const shouldAttachDeviceIdentity = participants.some((participant) => participant.encType === 'pkmsg');
435
+ const localPhash = await (0, phash_1.computePhashV2)([...fanoutDeviceJids, senderForPhash]);
436
+ const messageNode = (0, message_1.buildGroupDirectMessageNode)({
437
+ to: groupJid,
438
+ type,
439
+ id: options.id,
440
+ phash: localPhash,
441
+ addressingMode,
442
+ participants,
443
+ deviceIdentity: shouldAttachDeviceIdentity
444
+ ? this.getEncodedSignedDeviceIdentity()
445
+ : undefined
446
+ });
447
+ const replayPayload = {
448
+ mode: 'plaintext',
449
+ to: groupJid,
450
+ type,
451
+ plaintext
452
+ };
453
+ const result = await this.publishWithRetryTracking({
454
+ messageIdHint: options.id ?? messageNode.attrs.id,
455
+ toJid: groupJid,
456
+ messageType: type,
457
+ replayPayload
458
+ }, async () => this.messageClient.publishNode(messageNode, options));
459
+ const ackError = result.ack.error;
460
+ const serverPhash = result.ack.phash;
461
+ const serverAddressingMode = result.ack.addressingMode;
462
+ const hasPhashMismatch = !!serverPhash && serverPhash !== localPhash;
463
+ const hasAddressingMismatch = !!serverAddressingMode && serverAddressingMode !== addressingMode;
464
+ const hasAddressingError = ackError === 421;
465
+ if (!retryContext.retried &&
466
+ (hasPhashMismatch || hasAddressingMismatch || hasAddressingError)) {
467
+ this.logger.warn('group direct publish acknowledged with mismatch metadata', {
468
+ id: result.id,
469
+ groupJid,
470
+ localPhash,
471
+ serverPhash,
472
+ localAddressingMode: addressingMode,
473
+ serverAddressingMode,
474
+ ackError
475
+ });
476
+ return this.publishGroupDirectMessage(groupJid, plaintext, type, {
477
+ ...options,
478
+ id: result.id
479
+ }, {
480
+ retried: true,
481
+ forceRefreshParticipants: true,
482
+ forceAddressingMode: serverAddressingMode
483
+ });
484
+ }
485
+ return result;
486
+ }
487
+ async publishGroupSenderKeyMessage(groupJid, plaintext, type, options, retryContext = {}) {
488
+ const meJid = this.requireCurrentMeJid('sendMessage');
489
+ const participantUserJids = retryContext.forceRefreshParticipants
490
+ ? await this.refreshGroupParticipantUsers(groupJid)
491
+ : await this.resolveGroupParticipantUsers(groupJid);
492
+ const addressingMode = retryContext.forceAddressingMode ??
493
+ this.resolveGroupAddressingMode(participantUserJids, groupJid);
494
+ const senderJid = this.resolveSenderForAddressingMode(addressingMode, meJid);
495
+ const sender = (0, jid_1.parseSignalAddressFromJid)(senderJid);
496
+ const senderKeyDistributionMessage = await this.senderKeyManager.createSenderKeyDistributionMessage(groupJid, sender);
497
+ const groupCiphertext = await this.senderKeyManager.encryptGroupMessage(groupJid, sender, plaintext);
498
+ const distributionData = await this.encryptGroupDistributionParticipants(groupJid, sender, senderKeyDistributionMessage, participantUserJids);
499
+ const { fanoutDeviceJids, distributionParticipants } = distributionData;
500
+ const shouldAttachDeviceIdentity = distributionParticipants.some((participant) => participant.encType === 'pkmsg');
501
+ const localPhash = await (0, phash_1.computePhashV2)([...fanoutDeviceJids, senderJid]);
502
+ const messageNode = (0, message_1.buildGroupSenderKeyMessageNode)({
503
+ to: groupJid,
504
+ type,
505
+ id: options.id,
506
+ phash: localPhash,
507
+ addressingMode,
508
+ groupCiphertext: groupCiphertext.ciphertext,
509
+ participants: distributionParticipants,
510
+ deviceIdentity: shouldAttachDeviceIdentity
511
+ ? this.getEncodedSignedDeviceIdentity()
512
+ : undefined
513
+ });
514
+ const replayPayload = {
515
+ mode: 'plaintext',
516
+ to: groupJid,
517
+ type,
518
+ plaintext
519
+ };
520
+ const result = await this.publishWithRetryTracking({
521
+ messageIdHint: options.id ?? messageNode.attrs.id,
522
+ toJid: groupJid,
523
+ messageType: type,
524
+ replayPayload
525
+ }, async () => this.messageClient.publishNode(messageNode, options));
526
+ const distributedAddresses = distributionParticipants.map((participant) => participant.address);
527
+ try {
528
+ await this.senderKeyManager.markSenderKeyDistributed(groupJid, sender, distributedAddresses);
529
+ }
530
+ catch (error) {
531
+ this.logger.warn('failed to mark sender key distribution targets', {
532
+ groupJid,
533
+ participants: distributedAddresses.length,
534
+ message: (0, primitives_1.toError)(error).message
535
+ });
536
+ }
537
+ const ackError = result.ack.error;
538
+ const serverPhash = result.ack.phash;
539
+ const serverAddressingMode = result.ack.addressingMode;
540
+ const hasPhashMismatch = !!serverPhash && serverPhash !== localPhash;
541
+ const hasAddressingMismatch = !!serverAddressingMode && serverAddressingMode !== addressingMode;
542
+ const hasAddressingError = ackError === 421;
543
+ if (!retryContext.retried &&
544
+ (hasPhashMismatch || hasAddressingMismatch || hasAddressingError)) {
545
+ this.logger.warn('group message publish acknowledged with mismatch metadata', {
546
+ id: result.id,
547
+ groupJid,
548
+ localPhash,
549
+ serverPhash,
550
+ localAddressingMode: addressingMode,
551
+ serverAddressingMode,
552
+ ackError
553
+ });
554
+ return this.publishGroupSenderKeyMessage(groupJid, plaintext, type, {
555
+ ...options,
556
+ id: result.id
557
+ }, {
558
+ retried: true,
559
+ forceRefreshParticipants: true,
560
+ forceAddressingMode: serverAddressingMode
561
+ });
562
+ }
563
+ return result;
564
+ }
565
+ async resolveGroupParticipantUsers(groupJid) {
566
+ const cached = await this.participantsStore.getGroupParticipants(groupJid);
567
+ if (cached && cached.participants.length > 0) {
568
+ return this.sanitizeParticipantUsers(cached.participants);
569
+ }
570
+ return this.refreshGroupParticipantUsers(groupJid);
571
+ }
572
+ resolveGroupJidForParticipantCacheEvent(event) {
573
+ if (event.action === 'linked_group_promote' || event.action === 'linked_group_demote') {
574
+ return event.contextGroupJid ?? event.groupJid ?? null;
575
+ }
576
+ return event.groupJid ?? null;
577
+ }
578
+ extractParticipantUsersFromGroupEvent(event) {
579
+ const candidates = [];
580
+ for (const participant of event.participants ?? []) {
581
+ if (participant.jid) {
582
+ candidates.push(participant.jid);
583
+ }
584
+ if (participant.lidJid) {
585
+ candidates.push(participant.lidJid);
586
+ }
587
+ if (participant.phoneJid) {
588
+ candidates.push(participant.phoneJid);
589
+ }
590
+ }
591
+ return this.sanitizeParticipantUsers(candidates);
592
+ }
593
+ async mergeParticipantUsersIntoCache(groupJid, cachedParticipants, participantsToAdd) {
594
+ if (participantsToAdd.length === 0) {
595
+ return;
596
+ }
597
+ const nextParticipants = [...cachedParticipants];
598
+ const existing = new Set(cachedParticipants);
599
+ for (const participant of participantsToAdd) {
600
+ if (existing.has(participant)) {
601
+ continue;
602
+ }
603
+ existing.add(participant);
604
+ nextParticipants.push(participant);
605
+ }
606
+ if (nextParticipants.length === cachedParticipants.length) {
607
+ return;
608
+ }
609
+ await this.participantsStore.upsertGroupParticipants({
610
+ groupJid,
611
+ participants: nextParticipants,
612
+ updatedAtMs: Date.now()
613
+ });
614
+ }
615
+ async removeParticipantUsersFromCache(groupJid, cachedParticipants, participantsToRemove) {
616
+ if (participantsToRemove.length === 0) {
617
+ return;
618
+ }
619
+ const removed = new Set(participantsToRemove);
620
+ const nextParticipants = cachedParticipants.filter((participant) => !removed.has(participant));
621
+ if (nextParticipants.length === cachedParticipants.length) {
622
+ return;
623
+ }
624
+ if (nextParticipants.length === 0) {
625
+ await this.participantsStore.deleteGroupParticipants(groupJid);
626
+ return;
627
+ }
628
+ await this.participantsStore.upsertGroupParticipants({
629
+ groupJid,
630
+ participants: nextParticipants,
631
+ updatedAtMs: Date.now()
632
+ });
633
+ }
634
+ async replaceParticipantUsersInCache(groupJid, cachedParticipants, participantsToReplace, replacementParticipants) {
635
+ const toReplace = new Set(participantsToReplace);
636
+ const nextParticipants = cachedParticipants.filter((participant) => !toReplace.has(participant));
637
+ const existing = new Set(nextParticipants);
638
+ for (const participant of replacementParticipants) {
639
+ if (existing.has(participant)) {
640
+ continue;
641
+ }
642
+ existing.add(participant);
643
+ nextParticipants.push(participant);
644
+ }
645
+ if (this.areParticipantListsEqual(cachedParticipants, nextParticipants)) {
646
+ return;
647
+ }
648
+ if (nextParticipants.length === 0) {
649
+ await this.participantsStore.deleteGroupParticipants(groupJid);
650
+ return;
651
+ }
652
+ await this.participantsStore.upsertGroupParticipants({
653
+ groupJid,
654
+ participants: nextParticipants,
655
+ updatedAtMs: Date.now()
656
+ });
657
+ }
658
+ areParticipantListsEqual(left, right) {
659
+ if (left.length !== right.length) {
660
+ return false;
661
+ }
662
+ for (let index = 0; index < left.length; index += 1) {
663
+ if (left[index] !== right[index]) {
664
+ return false;
665
+ }
666
+ }
667
+ return true;
668
+ }
669
+ async refreshGroupParticipantUsers(groupJid) {
670
+ const queried = await this.queryGroupParticipantJids(groupJid);
671
+ const participants = this.sanitizeParticipantUsers(queried);
672
+ await this.participantsStore.upsertGroupParticipants({
673
+ groupJid,
674
+ participants,
675
+ updatedAtMs: Date.now()
676
+ });
677
+ return participants;
678
+ }
679
+ sanitizeParticipantUsers(participants) {
680
+ const deduped = new Set();
681
+ for (const participant of participants) {
682
+ if (!participant || !participant.includes('@'))
683
+ continue;
684
+ try {
685
+ deduped.add((0, jid_1.toUserJid)(participant));
686
+ }
687
+ catch (error) {
688
+ this.logger.trace('ignoring malformed participant jid', {
689
+ participant,
690
+ message: (0, primitives_1.toError)(error).message
691
+ });
692
+ }
693
+ }
694
+ return [...deduped];
695
+ }
696
+ resolveGroupAddressingMode(participantUserJids, groupJid) {
697
+ for (const participantJid of participantUserJids) {
698
+ try {
699
+ if ((0, jid_1.splitJid)(participantJid).server === 'lid') {
700
+ return 'lid';
701
+ }
702
+ }
703
+ catch (error) {
704
+ this.logger.trace('ignoring malformed participant jid in addressing mode resolution', { participantJid, message: (0, primitives_1.toError)(error).message });
705
+ }
706
+ }
707
+ this.logger.trace('group addressing mode resolved to pn (default)', {
708
+ groupJid,
709
+ participants: participantUserJids.length
710
+ });
711
+ return 'pn';
712
+ }
713
+ resolveSenderForAddressingMode(addressingMode, meJid) {
714
+ if (addressingMode === 'lid') {
715
+ const meLid = this.getCurrentMeLid();
716
+ if (meLid && meLid.includes('@')) {
717
+ try {
718
+ return (0, jid_1.normalizeDeviceJid)(meLid);
719
+ }
720
+ catch (error) {
721
+ this.logger.trace('ignoring malformed me lid jid', {
722
+ meLid,
723
+ message: (0, primitives_1.toError)(error).message
724
+ });
725
+ }
726
+ }
727
+ }
728
+ return (0, jid_1.normalizeDeviceJid)(meJid);
729
+ }
730
+ async encryptGroupDistributionParticipants(groupJid, sender, senderKeyDistributionMessage, participantUserJids) {
731
+ const distributionPayload = await (0, padding_1.writeRandomPadMax16)(_proto_1.proto.Message.encode({
732
+ senderKeyDistributionMessage
733
+ }).finish());
734
+ const fanoutDeviceJids = await this.resolveGroupParticipantDeviceJids(participantUserJids);
735
+ if (fanoutDeviceJids.length === 0) {
736
+ return {
737
+ fanoutDeviceJids,
738
+ distributionParticipants: []
739
+ };
740
+ }
741
+ const fanoutTargets = fanoutDeviceJids.map((jid) => ({
742
+ jid,
743
+ address: (0, jid_1.parseSignalAddressFromJid)(jid)
744
+ }));
745
+ const pendingAddresses = await this.senderKeyManager.filterParticipantsNeedingDistribution(groupJid, sender, fanoutTargets.map((target) => target.address));
746
+ if (pendingAddresses.length === 0) {
747
+ return {
748
+ fanoutDeviceJids,
749
+ distributionParticipants: []
750
+ };
751
+ }
752
+ const pendingAddressKeys = new Set(pendingAddresses.map(signal_address_1.signalAddressKey));
753
+ const pendingTargets = fanoutTargets.filter((target) => pendingAddressKeys.has((0, signal_address_1.signalAddressKey)(target.address)));
754
+ if (pendingTargets.length === 0) {
755
+ return {
756
+ fanoutDeviceJids,
757
+ distributionParticipants: []
758
+ };
759
+ }
760
+ await this.ensureSignalSessionsBatch(pendingTargets.map((target) => target.jid));
761
+ const distributionParticipants = await Promise.all(pendingTargets.map(async (target) => {
762
+ await this.ensureSignalSession(target.address, target.jid);
763
+ const encrypted = await this.signalProtocol.encryptMessage(target.address, distributionPayload);
764
+ return {
765
+ jid: target.jid,
766
+ address: target.address,
767
+ encType: encrypted.type,
768
+ ciphertext: encrypted.ciphertext
769
+ };
770
+ }));
771
+ return {
772
+ fanoutDeviceJids,
773
+ distributionParticipants
774
+ };
775
+ }
776
+ async resolveGroupParticipantDeviceJids(participantUserJids) {
777
+ const meDeviceJids = new Set();
778
+ const meJid = this.getCurrentMeJid();
779
+ if (meJid) {
780
+ try {
781
+ meDeviceJids.add((0, jid_1.normalizeDeviceJid)(meJid));
782
+ }
783
+ catch (error) {
784
+ this.logger.trace('ignoring malformed me jid', {
785
+ meJid,
786
+ message: (0, primitives_1.toError)(error).message
787
+ });
788
+ }
789
+ }
790
+ const meLid = this.getCurrentMeLid();
791
+ if (meLid && meLid.includes('@')) {
792
+ try {
793
+ meDeviceJids.add((0, jid_1.normalizeDeviceJid)(meLid));
794
+ }
795
+ catch (error) {
796
+ this.logger.trace('ignoring malformed me lid jid', {
797
+ meLid,
798
+ message: (0, primitives_1.toError)(error).message
799
+ });
800
+ }
801
+ }
802
+ const candidateUsers = [...new Set(participantUserJids)];
803
+ if (candidateUsers.length === 0) {
804
+ return [];
805
+ }
806
+ try {
807
+ const synced = await this.signalDeviceSync.syncDeviceList(candidateUsers);
808
+ const fanout = new Set();
809
+ for (const entry of synced) {
810
+ if (entry.deviceJids.length === 0) {
811
+ const normalizedEntryJid = (0, jid_1.normalizeDeviceJid)(entry.jid);
812
+ if (meDeviceJids.has(normalizedEntryJid))
813
+ continue;
814
+ fanout.add(normalizedEntryJid);
815
+ continue;
816
+ }
817
+ for (const deviceJid of entry.deviceJids) {
818
+ const normalizedDeviceJid = (0, jid_1.normalizeDeviceJid)(deviceJid);
819
+ if (meDeviceJids.has(normalizedDeviceJid))
820
+ continue;
821
+ fanout.add(normalizedDeviceJid);
822
+ }
823
+ }
824
+ return [...fanout];
825
+ }
826
+ catch (error) {
827
+ this.logger.warn('group participant device sync failed, falling back to participant user jids', {
828
+ participants: candidateUsers.length,
829
+ message: (0, primitives_1.toError)(error).message
830
+ });
831
+ return [...new Set(candidateUsers.map((jid) => (0, jid_1.normalizeDeviceJid)(jid)))].filter((jid) => !meDeviceJids.has(jid));
832
+ }
833
+ }
834
+ async publishDirectSignalMessageWithFanout(recipientJid, message, plaintext, type, options) {
835
+ const meJid = this.requireCurrentMeJid('sendMessage');
836
+ const meLid = this.getCurrentMeLid();
837
+ const selfDeviceJidForRecipient = this.resolveSelfDeviceJidForRecipient(recipientJid, meJid, meLid);
838
+ const deviceJids = await this.resolveDirectFanoutDeviceJids(recipientJid, selfDeviceJidForRecipient);
839
+ const recipientUserJid = (0, jid_1.toUserJid)(recipientJid);
840
+ const meUserJid = (0, jid_1.toUserJid)(selfDeviceJidForRecipient);
841
+ this.logger.debug('wa client publish signal fanout', {
842
+ to: recipientJid,
843
+ devices: deviceJids.length,
844
+ type
845
+ });
846
+ const expectedIdentityByJid = new Map();
847
+ if (options.expectedIdentity) {
848
+ for (let index = 0; index < deviceJids.length; index += 1) {
849
+ const targetJid = deviceJids[index];
850
+ if ((0, jid_1.toUserJid)(targetJid) === recipientUserJid) {
851
+ expectedIdentityByJid.set((0, jid_1.normalizeDeviceJid)(targetJid), options.expectedIdentity);
852
+ }
853
+ }
854
+ }
855
+ await this.ensureSignalSessionsBatch(deviceJids, expectedIdentityByJid);
856
+ const hasSelfDeviceFanout = deviceJids.some((targetJid) => (0, jid_1.toUserJid)(targetJid) === meUserJid);
857
+ const selfDevicePlaintext = hasSelfDeviceFanout
858
+ ? await (0, padding_1.writeRandomPadMax16)(_proto_1.proto.Message.encode((0, device_sent_1.wrapDeviceSentMessage)(message, recipientUserJid)).finish())
859
+ : null;
860
+ const participants = await Promise.all(deviceJids.map(async (targetJid) => {
861
+ const address = (0, jid_1.parseSignalAddressFromJid)(targetJid);
862
+ const targetUserJid = (0, jid_1.toUserJid)(targetJid);
863
+ const expectedIdentity = targetUserJid === recipientUserJid ? options.expectedIdentity : undefined;
864
+ const plaintextForTarget = selfDevicePlaintext && targetUserJid === meUserJid
865
+ ? selfDevicePlaintext
866
+ : plaintext;
867
+ await this.ensureSignalSession(address, targetJid, expectedIdentity);
868
+ const encrypted = await this.signalProtocol.encryptMessage(address, plaintextForTarget, expectedIdentity);
869
+ return {
870
+ jid: targetJid,
871
+ encType: encrypted.type,
872
+ ciphertext: encrypted.ciphertext
873
+ };
874
+ }));
875
+ const shouldAttachDeviceIdentity = participants.some((participant) => participant.encType === 'pkmsg');
876
+ const deviceIdentity = shouldAttachDeviceIdentity
877
+ ? this.getEncodedSignedDeviceIdentity()
878
+ : undefined;
879
+ const messageNode = (0, message_1.buildDirectMessageFanoutNode)({
880
+ to: recipientJid,
881
+ type,
882
+ id: options.id,
883
+ participants,
884
+ deviceIdentity
885
+ });
886
+ const replayPayload = {
887
+ mode: 'plaintext',
888
+ to: recipientJid,
889
+ type,
890
+ plaintext
891
+ };
892
+ return this.publishWithRetryTracking({
893
+ messageIdHint: options.id ?? messageNode.attrs.id,
894
+ toJid: recipientJid,
895
+ messageType: type,
896
+ replayPayload
897
+ }, async () => this.messageClient.publishNode(messageNode, options));
898
+ }
899
+ async ensureSignalSessionsBatch(targetJids, expectedIdentityByJid = new Map()) {
900
+ const normalizedTargetJids = [...new Set(targetJids.map((jid) => (0, jid_1.normalizeDeviceJid)(jid)))];
901
+ if (normalizedTargetJids.length === 0) {
902
+ return;
903
+ }
904
+ const normalizedTargets = normalizedTargetJids.map((jid) => ({
905
+ jid,
906
+ address: (0, jid_1.parseSignalAddressFromJid)(jid)
907
+ }));
908
+ const hasSessions = await this.signalProtocol.hasSessions(normalizedTargets.map((target) => target.address));
909
+ const missingTargets = normalizedTargets.filter((_, index) => !hasSessions[index]);
910
+ if (missingTargets.length === 0) {
911
+ return;
912
+ }
913
+ try {
914
+ const batchResults = await this.signalSessionSync.fetchKeyBundles(missingTargets.map((target) => ({ jid: target.jid })));
915
+ const resultByJid = new Map(batchResults.map((result) => [(0, jid_1.normalizeDeviceJid)(result.jid), result]));
916
+ const fallbackJids = [];
917
+ const establishPromises = [];
918
+ for (let index = 0; index < missingTargets.length; index += 1) {
919
+ const target = missingTargets[index];
920
+ const result = resultByJid.get(target.jid);
921
+ if (!result || !('bundle' in result)) {
922
+ fallbackJids.push(target.jid);
923
+ continue;
924
+ }
925
+ const expectedIdentity = expectedIdentityByJid.get(target.jid);
926
+ const remoteIdentity = (0, keys_1.toSerializedPubKey)(result.bundle.identity);
927
+ if (expectedIdentity &&
928
+ !(0, bytes_1.uint8Equal)(remoteIdentity, (0, keys_1.toSerializedPubKey)(expectedIdentity))) {
929
+ throw new Error('identity mismatch');
930
+ }
931
+ establishPromises.push(this.signalProtocol
932
+ .establishOutgoingSession(target.address, result.bundle)
933
+ .then(() => {
934
+ this.logger.debug('signal session synchronized from batch key fetch', {
935
+ jid: target.jid,
936
+ regId: result.bundle.regId,
937
+ hasOneTimeKey: result.bundle.oneTimeKey !== undefined
938
+ });
939
+ }));
940
+ }
941
+ await Promise.all(establishPromises);
942
+ if (fallbackJids.length === 0) {
943
+ return;
944
+ }
945
+ this.logger.warn('signal batch key fetch returned partial errors, falling back to single requests', {
946
+ requested: missingTargets.length,
947
+ fallbackTargets: fallbackJids.length
948
+ });
949
+ for (let index = 0; index < fallbackJids.length; index += 1) {
950
+ const jid = fallbackJids[index];
951
+ const address = (0, jid_1.parseSignalAddressFromJid)(jid);
952
+ await this.ensureSignalSession(address, jid, expectedIdentityByJid.get(jid));
953
+ }
954
+ }
955
+ catch (error) {
956
+ const normalized = (0, primitives_1.toError)(error);
957
+ if (normalized.message === 'identity mismatch') {
958
+ throw normalized;
959
+ }
960
+ this.logger.warn('signal batch key fetch failed, falling back to single requests', {
961
+ requested: missingTargets.length,
962
+ message: normalized.message
963
+ });
964
+ for (let index = 0; index < missingTargets.length; index += 1) {
965
+ const target = missingTargets[index];
966
+ await this.ensureSignalSession(target.address, target.jid, expectedIdentityByJid.get(target.jid));
967
+ }
968
+ }
969
+ }
970
+ async resolveDirectFanoutDeviceJids(recipientJid, selfDeviceJidForRecipient) {
971
+ const recipientUserJid = (0, jid_1.toUserJid)(recipientJid);
972
+ const meUserJid = (0, jid_1.toUserJid)(selfDeviceJidForRecipient);
973
+ const targets = recipientUserJid === meUserJid ? [recipientUserJid] : [recipientUserJid, meUserJid];
974
+ try {
975
+ const synced = await this.signalDeviceSync.syncDeviceList(targets);
976
+ const byUser = new Map(synced.map((entry) => [(0, jid_1.toUserJid)(entry.jid), entry.deviceJids]));
977
+ const fanout = new Set();
978
+ const recipientDevices = byUser.get(recipientUserJid) ?? [];
979
+ if (recipientDevices.length === 0) {
980
+ fanout.add(recipientUserJid);
981
+ }
982
+ else {
983
+ for (let index = 0; index < recipientDevices.length; index += 1) {
984
+ fanout.add(recipientDevices[index]);
985
+ }
986
+ }
987
+ const meDevices = byUser.get(meUserJid) ?? [];
988
+ const normalizedMeJid = (0, jid_1.normalizeDeviceJid)(selfDeviceJidForRecipient);
989
+ for (let index = 0; index < meDevices.length; index += 1) {
990
+ const deviceJid = meDevices[index];
991
+ if ((0, jid_1.normalizeDeviceJid)(deviceJid) === normalizedMeJid) {
992
+ continue;
993
+ }
994
+ fanout.add(deviceJid);
995
+ }
996
+ return [...fanout];
997
+ }
998
+ catch (error) {
999
+ const message = error instanceof Error ? error.message : String(error);
1000
+ this.logger.warn('signal device fanout sync failed, falling back to direct recipient', {
1001
+ to: recipientJid,
1002
+ message
1003
+ });
1004
+ return [recipientUserJid];
1005
+ }
1006
+ }
1007
+ resolveSelfDeviceJidForRecipient(recipientJid, meJid, meLid) {
1008
+ if ((0, jid_1.splitJid)(recipientJid).server !== 'lid') {
1009
+ return meJid;
1010
+ }
1011
+ if (!meLid || !meLid.includes('@')) {
1012
+ return meJid;
1013
+ }
1014
+ return meLid;
1015
+ }
1016
+ getEncodedSignedDeviceIdentity() {
1017
+ const signedIdentity = this.getCurrentSignedIdentity();
1018
+ if (!signedIdentity) {
1019
+ throw new Error('missing signed identity for pkmsg fanout');
1020
+ }
1021
+ return _proto_1.proto.ADVSignedDeviceIdentity.encode(signedIdentity).finish();
1022
+ }
1023
+ async ensureSignalSession(address, jid, expectedIdentity, reasonIdentity = false) {
1024
+ this.requireCurrentMeJid('ensureSignalSession');
1025
+ if (reasonIdentity) {
1026
+ await this.signalIdentitySync.syncIdentityKeys([jid]);
1027
+ }
1028
+ if (await this.signalProtocol.hasSession(address)) {
1029
+ return;
1030
+ }
1031
+ this.logger.info('signal session missing, fetching remote key bundle', { jid });
1032
+ const fetched = await this.signalSessionSync.fetchKeyBundle({
1033
+ jid,
1034
+ reasonIdentity
1035
+ });
1036
+ const remoteIdentity = (0, keys_1.toSerializedPubKey)(fetched.bundle.identity);
1037
+ if (reasonIdentity) {
1038
+ const storedIdentity = await this.signalStore.getRemoteIdentity(address);
1039
+ if (storedIdentity && !(0, bytes_1.uint8Equal)(remoteIdentity, storedIdentity)) {
1040
+ throw new Error('identity mismatch');
1041
+ }
1042
+ }
1043
+ if (expectedIdentity && !(0, bytes_1.uint8Equal)(remoteIdentity, (0, keys_1.toSerializedPubKey)(expectedIdentity))) {
1044
+ throw new Error('identity mismatch');
1045
+ }
1046
+ await this.signalProtocol.establishOutgoingSession(address, fetched.bundle);
1047
+ this.logger.info('signal session synchronized', {
1048
+ jid,
1049
+ regId: fetched.bundle.regId,
1050
+ hasOneTimeKey: fetched.bundle.oneTimeKey !== undefined
1051
+ });
1052
+ }
1053
+ requireCurrentMeJid(context) {
1054
+ const meJid = this.getCurrentMeJid();
1055
+ if (meJid) {
1056
+ return meJid;
1057
+ }
1058
+ throw new Error(`${context} requires registered meJid`);
1059
+ }
1060
+ }
1061
+ exports.WaMessageDispatchCoordinator = WaMessageDispatchCoordinator;