zapo-js 0.1.2 → 0.3.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 (630) hide show
  1. package/README.md +16 -4
  2. package/dist/appstate/WaAppStateCrypto.js +50 -42
  3. package/dist/appstate/WaAppStateSyncClient.js +215 -133
  4. package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
  5. package/dist/appstate/index.js +9 -7
  6. package/dist/appstate/utils.js +0 -5
  7. package/dist/auth/WaAuthClient.js +55 -57
  8. package/dist/auth/credentials-flow.js +195 -0
  9. package/dist/auth/index.js +1 -6
  10. package/dist/auth/pairing/WaPairingFlow.js +39 -32
  11. package/dist/auth/pairing/{WaPairingCodeCrypto.js → pairing-code-crypto.js} +35 -17
  12. package/dist/client/WaClient.js +338 -174
  13. package/dist/client/WaClientFactory.js +399 -66
  14. package/dist/client/connection/WaConnectionManager.js +23 -11
  15. package/dist/client/coordinators/WaAbPropsCoordinator.js +141 -0
  16. package/dist/client/coordinators/WaBusinessCoordinator.js +232 -0
  17. package/dist/client/coordinators/WaEmailCoordinator.js +63 -0
  18. package/dist/client/coordinators/WaGroupCoordinator.js +11 -7
  19. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +34 -8
  20. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +341 -118
  21. package/dist/client/coordinators/WaOfflineResumeCoordinator.js +114 -0
  22. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +97 -36
  23. package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
  24. package/dist/client/coordinators/WaProfileCoordinator.js +214 -0
  25. package/dist/client/coordinators/WaRetryCoordinator.js +184 -30
  26. package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
  27. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +184 -0
  28. package/dist/client/dirty.js +41 -21
  29. package/dist/client/events/abprops.js +43 -0
  30. package/dist/client/events/devices.js +72 -0
  31. package/dist/client/events/group.js +3 -11
  32. package/dist/client/events/identity.js +22 -0
  33. package/dist/client/events/privacy-token.js +38 -0
  34. package/dist/client/events/registration.js +42 -0
  35. package/dist/client/history-sync.js +50 -9
  36. package/dist/client/incoming.js +74 -7
  37. package/dist/client/mailbox.js +40 -23
  38. package/dist/client/media.js +243 -0
  39. package/dist/client/messages.js +245 -92
  40. package/dist/client/messaging/fanout.js +21 -11
  41. package/dist/client/messaging/participants.js +6 -4
  42. package/dist/client/persistence/WriteBehindPersistence.js +129 -0
  43. package/dist/client/tokens/cs-token.js +50 -0
  44. package/dist/client/tokens/tc-token.js +25 -0
  45. package/dist/crypto/core/index.js +5 -2
  46. package/dist/crypto/core/keys.js +4 -4
  47. package/dist/crypto/core/nonce.js +2 -0
  48. package/dist/crypto/core/primitives.js +0 -8
  49. package/dist/crypto/core/random.js +24 -8
  50. package/dist/crypto/core/xeddsa.js +57 -0
  51. package/dist/crypto/curves/X25519.js +43 -6
  52. package/dist/crypto/curves/constants.js +2 -1
  53. package/dist/crypto/index.js +3 -0
  54. package/dist/crypto/math/constants.js +13 -36
  55. package/dist/crypto/math/edwards.js +171 -44
  56. package/dist/crypto/math/fe.js +706 -0
  57. package/dist/crypto/math/mod.js +10 -3
  58. package/dist/esm/appstate/WaAppStateCrypto.js +40 -32
  59. package/dist/esm/appstate/WaAppStateSyncClient.js +206 -124
  60. package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
  61. package/dist/esm/appstate/index.js +2 -2
  62. package/dist/esm/appstate/{WaAppStateSyncResponseParser.js → response-parser.js} +1 -1
  63. package/dist/esm/appstate/utils.js +2 -5
  64. package/dist/esm/auth/WaAuthClient.js +52 -54
  65. package/dist/esm/auth/credentials-flow.js +190 -0
  66. package/dist/esm/auth/index.js +0 -2
  67. package/dist/esm/auth/pairing/WaPairingFlow.js +39 -32
  68. package/dist/esm/auth/pairing/{WaPairingCodeCrypto.js → pairing-code-crypto.js} +26 -10
  69. package/dist/esm/client/WaClient.js +339 -175
  70. package/dist/esm/client/WaClientFactory.js +401 -68
  71. package/dist/esm/client/connection/WaConnectionManager.js +23 -11
  72. package/dist/esm/client/coordinators/WaAbPropsCoordinator.js +137 -0
  73. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +229 -0
  74. package/dist/esm/client/coordinators/WaEmailCoordinator.js +60 -0
  75. package/dist/esm/client/coordinators/WaGroupCoordinator.js +11 -7
  76. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +36 -10
  77. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +337 -114
  78. package/dist/esm/client/coordinators/WaOfflineResumeCoordinator.js +110 -0
  79. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +97 -36
  80. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
  81. package/dist/esm/client/coordinators/WaProfileCoordinator.js +211 -0
  82. package/dist/esm/client/coordinators/WaRetryCoordinator.js +186 -32
  83. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
  84. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +180 -0
  85. package/dist/esm/client/dirty.js +41 -21
  86. package/dist/esm/client/events/abprops.js +40 -0
  87. package/dist/esm/client/events/devices.js +68 -0
  88. package/dist/esm/client/events/group.js +3 -11
  89. package/dist/esm/client/events/identity.js +19 -0
  90. package/dist/esm/client/events/privacy-token.js +35 -0
  91. package/dist/esm/client/events/registration.js +39 -0
  92. package/dist/esm/client/history-sync.js +50 -9
  93. package/dist/esm/client/incoming.js +74 -8
  94. package/dist/esm/client/mailbox.js +40 -23
  95. package/dist/esm/client/media.js +234 -0
  96. package/dist/esm/client/messages.js +244 -91
  97. package/dist/esm/client/messaging/fanout.js +22 -12
  98. package/dist/esm/client/messaging/participants.js +6 -4
  99. package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
  100. package/dist/esm/client/tokens/cs-token.js +46 -0
  101. package/dist/esm/client/tokens/tc-token.js +18 -0
  102. package/dist/esm/crypto/core/index.js +3 -2
  103. package/dist/esm/crypto/core/keys.js +1 -1
  104. package/dist/esm/crypto/core/nonce.js +2 -0
  105. package/dist/esm/crypto/core/primitives.js +0 -7
  106. package/dist/esm/crypto/core/random.js +23 -7
  107. package/dist/esm/crypto/core/xeddsa.js +53 -0
  108. package/dist/esm/crypto/curves/X25519.js +45 -8
  109. package/dist/esm/crypto/curves/constants.js +1 -0
  110. package/dist/esm/crypto/index.js +1 -0
  111. package/dist/esm/crypto/math/constants.js +12 -35
  112. package/dist/esm/crypto/math/edwards.js +174 -47
  113. package/dist/esm/crypto/math/fe.js +691 -0
  114. package/dist/esm/crypto/math/mod.js +10 -1
  115. package/dist/esm/index.js +1 -1
  116. package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
  117. package/dist/esm/infra/perf/BoundedTaskQueue.js +3 -1
  118. package/dist/esm/infra/perf/PromiseDedup.js +20 -0
  119. package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
  120. package/dist/esm/infra/perf/StoreLock.js +80 -0
  121. package/dist/esm/media/WaMediaCrypto.js +332 -55
  122. package/dist/esm/media/WaMediaTransferClient.js +69 -220
  123. package/dist/esm/media/constants.js +4 -1
  124. package/dist/esm/media/processor.js +1 -0
  125. package/dist/esm/message/WaMessageClient.js +26 -19
  126. package/dist/esm/message/addon-crypto.js +130 -3
  127. package/dist/esm/message/content.js +206 -14
  128. package/dist/esm/message/icdc.js +76 -0
  129. package/dist/esm/message/incoming.js +38 -24
  130. package/dist/esm/message/phash.js +35 -13
  131. package/dist/esm/message/reporting-token.js +17 -30
  132. package/dist/esm/message/use-case-secret.js +1 -1
  133. package/dist/esm/protocol/abprops.js +159 -0
  134. package/dist/esm/protocol/appstate.js +9 -40
  135. package/dist/esm/protocol/browser.js +24 -18
  136. package/dist/esm/protocol/constants.js +8 -4
  137. package/dist/esm/protocol/defaults.js +6 -0
  138. package/dist/esm/protocol/email.js +30 -0
  139. package/dist/esm/protocol/index.js +1 -2
  140. package/dist/esm/protocol/jid.js +142 -39
  141. package/dist/esm/protocol/message.js +61 -1
  142. package/dist/esm/protocol/nodes.js +8 -2
  143. package/dist/esm/protocol/notification.js +9 -1
  144. package/dist/esm/protocol/privacy-token.js +17 -0
  145. package/dist/esm/protocol/privacy.js +55 -0
  146. package/dist/esm/protocol/stream.js +26 -1
  147. package/dist/esm/retry/codec.js +216 -0
  148. package/dist/esm/retry/constants.js +1 -1
  149. package/dist/esm/retry/index.js +2 -2
  150. package/dist/esm/retry/parse.js +50 -30
  151. package/dist/esm/retry/reason.js +1 -1
  152. package/dist/esm/retry/replay.js +11 -7
  153. package/dist/esm/retry/tracker.js +50 -12
  154. package/dist/esm/signal/api/SignalDeviceSyncApi.js +52 -32
  155. package/dist/esm/signal/api/SignalDigestSyncApi.js +21 -15
  156. package/dist/esm/signal/api/SignalIdentitySyncApi.js +30 -15
  157. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +19 -8
  158. package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
  159. package/dist/esm/signal/api/SignalSessionSyncApi.js +17 -8
  160. package/dist/esm/signal/api/result-map.js +10 -0
  161. package/dist/esm/signal/constants.js +0 -4
  162. package/dist/esm/signal/crypto/WaAdvSignature.js +5 -45
  163. package/dist/esm/signal/crypto/constants.js +0 -4
  164. package/dist/esm/signal/{store/sqlite.js → encoding.js} +40 -29
  165. package/dist/esm/signal/group/SenderKeyChain.js +3 -3
  166. package/dist/esm/signal/group/SenderKeyCodec.js +8 -8
  167. package/dist/esm/signal/group/SenderKeyManager.js +131 -109
  168. package/dist/esm/signal/index.js +1 -0
  169. package/dist/esm/signal/registration/keygen.js +8 -5
  170. package/dist/esm/signal/registration/utils.js +3 -2
  171. package/dist/esm/signal/session/SignalProtocol.js +158 -81
  172. package/dist/esm/signal/session/SignalRatchet.js +21 -10
  173. package/dist/esm/signal/session/SignalSerializer.js +5 -6
  174. package/dist/esm/signal/session/SignalSession.js +11 -9
  175. package/dist/esm/signal/session/resolver.js +140 -105
  176. package/dist/esm/store/contracts/identity.store.js +1 -0
  177. package/dist/esm/store/contracts/message-secret.store.js +1 -0
  178. package/dist/esm/store/contracts/pre-key.store.js +1 -0
  179. package/dist/esm/store/contracts/privacy-token.store.js +1 -0
  180. package/dist/esm/store/contracts/session.store.js +1 -0
  181. package/dist/esm/store/createStore.js +143 -193
  182. package/dist/esm/store/index.js +5 -10
  183. package/dist/esm/store/locks/appstate.lock.js +26 -0
  184. package/dist/esm/store/locks/auth.lock.js +15 -0
  185. package/dist/esm/store/locks/contact.lock.js +20 -0
  186. package/dist/esm/store/locks/device-list.lock.js +20 -0
  187. package/dist/esm/store/locks/identity.lock.js +16 -0
  188. package/dist/esm/store/locks/message-secret.lock.js +17 -0
  189. package/dist/esm/store/locks/message.lock.js +21 -0
  190. package/dist/esm/store/locks/participants.lock.js +20 -0
  191. package/dist/esm/store/locks/pre-key.lock.js +27 -0
  192. package/dist/esm/store/locks/privacy-token.lock.js +18 -0
  193. package/dist/esm/store/locks/retry.lock.js +29 -0
  194. package/dist/esm/store/locks/sender-key.lock.js +52 -0
  195. package/dist/esm/store/locks/session.lock.js +19 -0
  196. package/dist/esm/store/locks/signal.lock.js +39 -0
  197. package/dist/esm/store/locks/thread.lock.js +21 -0
  198. package/dist/esm/store/noop.store.js +21 -1
  199. package/dist/esm/store/providers/memory/appstate.store.js +22 -24
  200. package/dist/esm/store/providers/memory/device-list.store.js +13 -5
  201. package/dist/esm/store/providers/memory/identity.store.js +31 -0
  202. package/dist/esm/store/providers/memory/message-secret.store.js +81 -0
  203. package/dist/esm/store/providers/memory/participants.store.js +3 -0
  204. package/dist/esm/store/providers/memory/pre-key.store.js +97 -0
  205. package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
  206. package/dist/esm/store/providers/memory/retry.store.js +99 -10
  207. package/dist/esm/store/providers/memory/sender-key.store.js +6 -1
  208. package/dist/esm/store/providers/memory/session.store.js +45 -0
  209. package/dist/esm/store/providers/memory/signal.store.js +1 -147
  210. package/dist/esm/transport/WaComms.js +7 -4
  211. package/dist/esm/transport/WaWebSocket.js +9 -7
  212. package/dist/esm/transport/binary/constants.js +0 -30
  213. package/dist/esm/transport/binary/decoder.js +4 -4
  214. package/dist/esm/transport/binary/encoder.js +8 -15
  215. package/dist/esm/transport/binary/index.js +0 -1
  216. package/dist/esm/transport/index.js +6 -0
  217. package/dist/esm/transport/keepalive/WaKeepAlive.js +17 -8
  218. package/dist/esm/transport/node/WaMobileTcpSocket.js +114 -0
  219. package/dist/esm/transport/node/WaNodeOrchestrator.js +37 -22
  220. package/dist/esm/transport/node/builders/abprops.js +20 -0
  221. package/dist/esm/transport/node/builders/business.js +129 -0
  222. package/dist/esm/transport/node/builders/device.js +11 -0
  223. package/dist/esm/transport/node/builders/email.js +65 -0
  224. package/dist/esm/transport/node/builders/global.js +370 -0
  225. package/dist/esm/transport/node/builders/message.js +63 -239
  226. package/dist/esm/transport/node/builders/offline.js +14 -0
  227. package/dist/esm/transport/node/builders/pairing.js +0 -24
  228. package/dist/esm/transport/node/builders/prekeys.js +37 -40
  229. package/dist/esm/transport/node/builders/presence.js +13 -0
  230. package/dist/esm/transport/node/builders/privacy-token.js +37 -0
  231. package/dist/esm/transport/node/builders/privacy.js +48 -0
  232. package/dist/esm/transport/node/builders/profile.js +70 -0
  233. package/dist/esm/transport/node/builders/retry.js +11 -23
  234. package/dist/esm/transport/node/builders/usync.js +6 -2
  235. package/dist/esm/transport/node/helpers.js +43 -1
  236. package/dist/esm/transport/node/mex/argo-decoder.js +152 -0
  237. package/dist/esm/transport/node/mex/client.js +83 -0
  238. package/dist/esm/transport/node/mex/persist-ids.js +10 -0
  239. package/dist/esm/transport/node/usync.js +3 -33
  240. package/dist/esm/transport/node/xml.js +35 -14
  241. package/dist/esm/transport/noise/WaClientPayload.js +24 -19
  242. package/dist/esm/transport/noise/WaFrameCodec.js +2 -2
  243. package/dist/esm/transport/noise/WaMobileClientPayload.js +53 -0
  244. package/dist/esm/transport/noise/WaNoiseCert.js +9 -27
  245. package/dist/esm/transport/noise/WaNoiseSession.js +76 -34
  246. package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
  247. package/dist/esm/transport/stream/parse.js +8 -4
  248. package/dist/esm/util/bytes.js +22 -18
  249. package/dist/esm/util/index.js +5 -0
  250. package/dist/esm/util/primitives.js +3 -2
  251. package/dist/index.js +7 -1
  252. package/dist/infra/perf/BackgroundQueue.js +482 -0
  253. package/dist/infra/perf/BoundedTaskQueue.js +3 -1
  254. package/dist/infra/perf/PromiseDedup.js +24 -0
  255. package/dist/infra/perf/SharedExclusiveGate.js +113 -0
  256. package/dist/infra/perf/StoreLock.js +84 -0
  257. package/dist/media/WaMediaCrypto.js +328 -51
  258. package/dist/media/WaMediaTransferClient.js +72 -253
  259. package/dist/media/constants.js +5 -2
  260. package/dist/media/processor.js +2 -0
  261. package/dist/message/WaMessageClient.js +26 -19
  262. package/dist/message/addon-crypto.js +131 -0
  263. package/dist/message/content.js +211 -14
  264. package/dist/message/icdc.js +81 -0
  265. package/dist/message/incoming.js +38 -24
  266. package/dist/message/phash.js +35 -13
  267. package/dist/message/reporting-token.js +16 -30
  268. package/dist/message/use-case-secret.js +1 -1
  269. package/dist/protocol/abprops.js +163 -0
  270. package/dist/protocol/appstate.js +10 -41
  271. package/dist/protocol/browser.js +25 -18
  272. package/dist/protocol/constants.js +33 -2
  273. package/dist/protocol/defaults.js +6 -0
  274. package/dist/protocol/email.js +33 -0
  275. package/dist/protocol/index.js +8 -5
  276. package/dist/protocol/jid.js +149 -39
  277. package/dist/protocol/message.js +62 -2
  278. package/dist/protocol/nodes.js +8 -2
  279. package/dist/protocol/notification.js +10 -2
  280. package/dist/protocol/privacy-token.js +20 -0
  281. package/dist/protocol/privacy.js +58 -0
  282. package/dist/protocol/stream.js +27 -2
  283. package/dist/retry/codec.js +220 -0
  284. package/dist/retry/constants.js +1 -1
  285. package/dist/retry/index.js +5 -5
  286. package/dist/retry/parse.js +51 -30
  287. package/dist/retry/reason.js +1 -1
  288. package/dist/retry/replay.js +10 -6
  289. package/dist/retry/tracker.js +50 -12
  290. package/dist/signal/api/SignalDeviceSyncApi.js +51 -31
  291. package/dist/signal/api/SignalDigestSyncApi.js +21 -15
  292. package/dist/signal/api/SignalIdentitySyncApi.js +29 -14
  293. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +17 -6
  294. package/dist/signal/api/SignalRotateKeyApi.js +4 -2
  295. package/dist/signal/api/SignalSessionSyncApi.js +16 -7
  296. package/dist/signal/api/result-map.js +13 -0
  297. package/dist/signal/constants.js +1 -5
  298. package/dist/signal/crypto/WaAdvSignature.js +2 -44
  299. package/dist/signal/crypto/constants.js +1 -5
  300. package/dist/signal/{store/sqlite.js → encoding.js} +41 -25
  301. package/dist/signal/group/SenderKeyChain.js +2 -2
  302. package/dist/signal/group/SenderKeyCodec.js +8 -8
  303. package/dist/signal/group/SenderKeyManager.js +130 -108
  304. package/dist/signal/index.js +13 -1
  305. package/dist/signal/registration/keygen.js +7 -4
  306. package/dist/signal/registration/utils.js +3 -2
  307. package/dist/signal/session/SignalProtocol.js +158 -81
  308. package/dist/signal/session/SignalRatchet.js +19 -8
  309. package/dist/signal/session/SignalSerializer.js +5 -6
  310. package/dist/signal/session/SignalSession.js +11 -9
  311. package/dist/signal/session/resolver.js +138 -103
  312. package/dist/store/contracts/identity.store.js +2 -0
  313. package/dist/store/contracts/message-secret.store.js +2 -0
  314. package/dist/store/contracts/pre-key.store.js +2 -0
  315. package/dist/store/contracts/privacy-token.store.js +2 -0
  316. package/dist/store/contracts/session.store.js +2 -0
  317. package/dist/store/createStore.js +142 -192
  318. package/dist/store/index.js +23 -33
  319. package/dist/store/locks/appstate.lock.js +29 -0
  320. package/dist/store/locks/auth.lock.js +18 -0
  321. package/dist/store/locks/contact.lock.js +23 -0
  322. package/dist/store/locks/device-list.lock.js +23 -0
  323. package/dist/store/locks/identity.lock.js +19 -0
  324. package/dist/store/locks/message-secret.lock.js +20 -0
  325. package/dist/store/locks/message.lock.js +24 -0
  326. package/dist/store/locks/participants.lock.js +23 -0
  327. package/dist/store/locks/pre-key.lock.js +30 -0
  328. package/dist/store/locks/privacy-token.lock.js +21 -0
  329. package/dist/store/locks/retry.lock.js +32 -0
  330. package/dist/store/locks/sender-key.lock.js +55 -0
  331. package/dist/store/locks/session.lock.js +22 -0
  332. package/dist/store/locks/signal.lock.js +42 -0
  333. package/dist/store/locks/thread.lock.js +24 -0
  334. package/dist/store/noop.store.js +22 -2
  335. package/dist/store/providers/memory/appstate.store.js +22 -24
  336. package/dist/store/providers/memory/device-list.store.js +13 -5
  337. package/dist/store/providers/memory/identity.store.js +35 -0
  338. package/dist/store/providers/memory/message-secret.store.js +85 -0
  339. package/dist/store/providers/memory/participants.store.js +3 -0
  340. package/dist/store/providers/memory/pre-key.store.js +101 -0
  341. package/dist/store/providers/memory/privacy-token.store.js +47 -0
  342. package/dist/store/providers/memory/retry.store.js +98 -9
  343. package/dist/store/providers/memory/sender-key.store.js +6 -1
  344. package/dist/store/providers/memory/session.store.js +49 -0
  345. package/dist/store/providers/memory/signal.store.js +1 -147
  346. package/dist/transport/WaComms.js +7 -4
  347. package/dist/transport/WaWebSocket.js +9 -7
  348. package/dist/transport/binary/constants.js +1 -31
  349. package/dist/transport/binary/decoder.js +4 -4
  350. package/dist/transport/binary/encoder.js +8 -15
  351. package/dist/transport/binary/index.js +0 -4
  352. package/dist/transport/index.js +17 -1
  353. package/dist/transport/keepalive/WaKeepAlive.js +17 -8
  354. package/dist/transport/node/WaMobileTcpSocket.js +118 -0
  355. package/dist/transport/node/WaNodeOrchestrator.js +36 -21
  356. package/dist/transport/node/builders/abprops.js +23 -0
  357. package/dist/transport/node/builders/business.js +137 -0
  358. package/dist/transport/node/builders/device.js +14 -0
  359. package/dist/transport/node/builders/email.js +72 -0
  360. package/dist/transport/node/builders/global.js +375 -0
  361. package/dist/transport/node/builders/message.js +64 -245
  362. package/dist/transport/node/builders/offline.js +17 -0
  363. package/dist/transport/node/builders/pairing.js +0 -26
  364. package/dist/transport/node/builders/prekeys.js +36 -39
  365. package/dist/transport/node/builders/presence.js +16 -0
  366. package/dist/transport/node/builders/privacy-token.js +42 -0
  367. package/dist/transport/node/builders/privacy.js +55 -0
  368. package/dist/transport/node/builders/profile.js +78 -0
  369. package/dist/transport/node/builders/retry.js +10 -22
  370. package/dist/transport/node/builders/usync.js +6 -2
  371. package/dist/transport/node/helpers.js +46 -1
  372. package/dist/transport/node/mex/argo-decoder.js +189 -0
  373. package/dist/transport/node/mex/client.js +86 -0
  374. package/dist/transport/node/mex/persist-ids.js +13 -0
  375. package/dist/transport/node/usync.js +2 -32
  376. package/dist/transport/node/xml.js +35 -14
  377. package/dist/transport/noise/WaClientPayload.js +26 -21
  378. package/dist/transport/noise/WaFrameCodec.js +1 -1
  379. package/dist/transport/noise/WaMobileClientPayload.js +56 -0
  380. package/dist/transport/noise/WaNoiseCert.js +8 -26
  381. package/dist/transport/noise/WaNoiseSession.js +75 -33
  382. package/dist/transport/noise/WaNoiseSocket.js +8 -4
  383. package/dist/transport/stream/parse.js +7 -3
  384. package/dist/types/appstate/WaAppStateCrypto.d.ts +11 -8
  385. package/dist/types/appstate/WaAppStateSyncClient.d.ts +6 -2
  386. package/dist/types/appstate/encoding.d.ts +7 -0
  387. package/dist/types/appstate/index.d.ts +3 -3
  388. package/dist/types/appstate/{WaAppStateSyncResponseParser.d.ts → response-parser.d.ts} +1 -1
  389. package/dist/types/appstate/types.d.ts +1 -1
  390. package/dist/types/appstate/utils.d.ts +0 -2
  391. package/dist/types/auth/WaAuthClient.d.ts +9 -3
  392. package/dist/types/auth/credentials-flow.d.ts +20 -0
  393. package/dist/types/auth/index.d.ts +0 -2
  394. package/dist/types/auth/pairing/WaPairingFlow.d.ts +3 -2
  395. package/dist/types/auth/pairing/{WaPairingCodeCrypto.d.ts → pairing-code-crypto.d.ts} +6 -1
  396. package/dist/types/auth/types.d.ts +41 -0
  397. package/dist/types/client/WaClient.d.ts +44 -18
  398. package/dist/types/client/WaClientFactory.d.ts +22 -8
  399. package/dist/types/client/connection/WaConnectionManager.d.ts +2 -0
  400. package/dist/types/client/coordinators/WaAbPropsCoordinator.d.ts +26 -0
  401. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
  402. package/dist/types/client/coordinators/WaEmailCoordinator.d.ts +24 -0
  403. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +9 -2
  404. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +29 -2
  405. package/dist/types/client/coordinators/WaOfflineResumeCoordinator.d.ts +31 -0
  406. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +16 -1
  407. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
  408. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +38 -0
  409. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +12 -0
  410. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
  411. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +55 -0
  412. package/dist/types/client/dirty.d.ts +3 -1
  413. package/dist/types/client/events/abprops.d.ts +14 -0
  414. package/dist/types/client/events/devices.d.ts +20 -0
  415. package/dist/types/client/events/identity.d.ts +9 -0
  416. package/dist/types/client/events/privacy-token.d.ts +7 -0
  417. package/dist/types/client/events/registration.d.ts +17 -0
  418. package/dist/types/client/history-sync.d.ts +9 -6
  419. package/dist/types/client/incoming.d.ts +9 -2
  420. package/dist/types/client/index.d.ts +1 -1
  421. package/dist/types/client/mailbox.d.ts +5 -5
  422. package/dist/types/client/media.d.ts +31 -0
  423. package/dist/types/client/messages.d.ts +3 -2
  424. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
  425. package/dist/types/client/tokens/cs-token.d.ts +10 -0
  426. package/dist/types/client/tokens/tc-token.d.ts +5 -0
  427. package/dist/types/client/types.d.ts +151 -4
  428. package/dist/types/crypto/core/index.d.ts +3 -2
  429. package/dist/types/crypto/core/nonce.d.ts +2 -0
  430. package/dist/types/crypto/core/primitives.d.ts +1 -2
  431. package/dist/types/crypto/core/random.d.ts +2 -1
  432. package/dist/types/crypto/core/xeddsa.d.ts +2 -0
  433. package/dist/types/crypto/curves/constants.d.ts +1 -0
  434. package/dist/types/crypto/index.d.ts +2 -0
  435. package/dist/types/crypto/math/constants.d.ts +4 -2
  436. package/dist/types/crypto/math/fe.d.ts +30 -0
  437. package/dist/types/crypto/math/mod.d.ts +0 -2
  438. package/dist/types/crypto/math/types.d.ts +11 -4
  439. package/dist/types/index.d.ts +6 -3
  440. package/dist/types/infra/log/ConsoleLogger.d.ts +1 -1
  441. package/dist/types/infra/log/PinoLogger.d.ts +1 -1
  442. package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
  443. package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
  444. package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
  445. package/dist/types/infra/perf/StoreLock.d.ts +11 -0
  446. package/dist/types/media/WaMediaCrypto.d.ts +16 -6
  447. package/dist/types/media/WaMediaTransferClient.d.ts +6 -23
  448. package/dist/types/media/constants.d.ts +3 -1
  449. package/dist/types/media/index.d.ts +2 -1
  450. package/dist/types/media/processor.d.ts +28 -0
  451. package/dist/types/media/types.d.ts +19 -5
  452. package/dist/types/message/addon-crypto.d.ts +34 -3
  453. package/dist/types/message/content.d.ts +11 -1
  454. package/dist/types/message/icdc.d.ts +13 -0
  455. package/dist/types/message/reporting-token.d.ts +0 -1
  456. package/dist/types/message/types.d.ts +42 -11
  457. package/dist/types/protocol/abprops.d.ts +142 -0
  458. package/dist/types/protocol/appstate.d.ts +0 -11
  459. package/dist/types/protocol/browser.d.ts +1 -0
  460. package/dist/types/protocol/constants.d.ts +12 -4
  461. package/dist/types/protocol/defaults.d.ts +6 -0
  462. package/dist/types/protocol/email.d.ts +32 -0
  463. package/dist/types/protocol/index.d.ts +1 -2
  464. package/dist/types/protocol/jid.d.ts +20 -2
  465. package/dist/types/protocol/message.d.ts +60 -0
  466. package/dist/types/protocol/nodes.d.ts +6 -0
  467. package/dist/types/protocol/notification.d.ts +8 -0
  468. package/dist/types/protocol/privacy-token.d.ts +17 -0
  469. package/dist/types/protocol/privacy.d.ts +75 -0
  470. package/dist/types/protocol/stream.d.ts +31 -0
  471. package/dist/types/retry/codec.d.ts +3 -0
  472. package/dist/types/retry/index.d.ts +3 -3
  473. package/dist/types/retry/parse.d.ts +5 -2
  474. package/dist/types/retry/reason.d.ts +1 -1
  475. package/dist/types/retry/tracker.d.ts +1 -0
  476. package/dist/types/retry/types.d.ts +6 -1
  477. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +2 -1
  478. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +9 -0
  479. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +5 -3
  480. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
  481. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
  482. package/dist/types/signal/api/result-map.d.ts +1 -0
  483. package/dist/types/signal/constants.d.ts +0 -3
  484. package/dist/types/signal/crypto/WaAdvSignature.d.ts +0 -2
  485. package/dist/types/signal/crypto/constants.d.ts +0 -1
  486. package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +9 -3
  487. package/dist/types/signal/group/SenderKeyChain.d.ts +1 -1
  488. package/dist/types/signal/group/SenderKeyManager.d.ts +17 -7
  489. package/dist/types/signal/index.d.ts +2 -0
  490. package/dist/types/signal/registration/utils.d.ts +2 -1
  491. package/dist/types/signal/session/SignalProtocol.d.ts +21 -6
  492. package/dist/types/signal/session/SignalSerializer.d.ts +2 -1
  493. package/dist/types/signal/session/resolver.d.ts +11 -4
  494. package/dist/types/signal/types.d.ts +16 -4
  495. package/dist/types/store/contracts/appstate.store.d.ts +1 -1
  496. package/dist/types/store/contracts/identity.store.d.ts +11 -0
  497. package/dist/types/store/contracts/message-secret.store.d.ts +16 -0
  498. package/dist/types/store/contracts/pre-key.store.d.ts +13 -0
  499. package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
  500. package/dist/types/store/contracts/retry.store.d.ts +7 -0
  501. package/dist/types/store/contracts/session.store.d.ts +14 -0
  502. package/dist/types/store/contracts/signal.store.d.ts +1 -27
  503. package/dist/types/store/createStore.d.ts +1 -1
  504. package/dist/types/store/index.d.ts +12 -12
  505. package/dist/types/store/locks/appstate.lock.d.ts +3 -0
  506. package/dist/types/store/locks/auth.lock.d.ts +3 -0
  507. package/dist/types/store/locks/contact.lock.d.ts +3 -0
  508. package/dist/types/store/locks/device-list.lock.d.ts +2 -0
  509. package/dist/types/store/locks/identity.lock.d.ts +3 -0
  510. package/dist/types/store/locks/message-secret.lock.d.ts +3 -0
  511. package/dist/types/store/locks/message.lock.d.ts +3 -0
  512. package/dist/types/store/locks/participants.lock.d.ts +2 -0
  513. package/dist/types/store/locks/pre-key.lock.d.ts +3 -0
  514. package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
  515. package/dist/types/store/locks/retry.lock.d.ts +2 -0
  516. package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
  517. package/dist/types/store/locks/session.lock.d.ts +3 -0
  518. package/dist/types/store/locks/signal.lock.d.ts +3 -0
  519. package/dist/types/store/locks/thread.lock.d.ts +3 -0
  520. package/dist/types/store/noop.store.d.ts +4 -0
  521. package/dist/types/store/providers/memory/appstate.store.d.ts +1 -1
  522. package/dist/types/store/providers/memory/identity.store.d.ts +18 -0
  523. package/dist/types/store/providers/memory/message-secret.store.d.ts +21 -0
  524. package/dist/types/store/providers/memory/pre-key.store.d.ts +23 -0
  525. package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
  526. package/dist/types/store/providers/memory/retry.store.d.ts +15 -1
  527. package/dist/types/store/providers/memory/session.store.d.ts +21 -0
  528. package/dist/types/store/providers/memory/signal.store.d.ts +2 -43
  529. package/dist/types/store/providers/memory/thread.store.d.ts +1 -1
  530. package/dist/types/store/types.d.ts +69 -61
  531. package/dist/types/transport/WaWebSocket.d.ts +1 -1
  532. package/dist/types/transport/binary/constants.d.ts +0 -30
  533. package/dist/types/transport/binary/index.d.ts +0 -1
  534. package/dist/types/transport/index.d.ts +8 -1
  535. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +4 -1
  536. package/dist/types/transport/node/WaMobileTcpSocket.d.ts +18 -0
  537. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +9 -6
  538. package/dist/types/transport/node/builders/abprops.d.ts +5 -0
  539. package/dist/types/transport/node/builders/business.d.ts +29 -0
  540. package/dist/types/transport/node/builders/device.d.ts +2 -0
  541. package/dist/types/transport/node/builders/email.d.ts +11 -0
  542. package/dist/types/transport/node/builders/global.d.ts +102 -0
  543. package/dist/types/transport/node/builders/message.d.ts +8 -7
  544. package/dist/types/transport/node/builders/offline.d.ts +2 -0
  545. package/dist/types/transport/node/builders/pairing.d.ts +0 -2
  546. package/dist/types/transport/node/builders/prekeys.d.ts +4 -3
  547. package/dist/types/transport/node/builders/presence.d.ts +6 -0
  548. package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
  549. package/dist/types/transport/node/builders/privacy.d.ts +7 -0
  550. package/dist/types/transport/node/builders/profile.d.ts +8 -0
  551. package/dist/types/transport/node/builders/retry.d.ts +0 -1
  552. package/dist/types/transport/node/helpers.d.ts +8 -0
  553. package/dist/types/transport/node/mex/argo-decoder.d.ts +11 -0
  554. package/dist/types/transport/node/mex/client.d.ts +18 -0
  555. package/dist/types/transport/node/mex/persist-ids.d.ts +14 -0
  556. package/dist/types/transport/noise/WaMobileClientPayload.d.ts +29 -0
  557. package/dist/types/transport/noise/WaNoiseCert.d.ts +7 -1
  558. package/dist/types/transport/noise/WaNoiseSession.d.ts +4 -2
  559. package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
  560. package/dist/types/transport/types.d.ts +8 -0
  561. package/dist/types/util/bytes.d.ts +1 -1
  562. package/dist/types/util/index.d.ts +5 -0
  563. package/dist/types/util/primitives.d.ts +0 -1
  564. package/dist/util/bytes.js +22 -18
  565. package/dist/util/index.js +23 -0
  566. package/dist/util/primitives.js +2 -2
  567. package/package.json +34 -10
  568. package/proto/index.js +1 -1
  569. package/dist/auth/flow/WaAuthCredentialsFlow.js +0 -130
  570. package/dist/auth/pairing/constants.js +0 -5
  571. package/dist/client/connection/WaKeyShareCoordinator.js +0 -63
  572. package/dist/crypto/core/constants.js +0 -4
  573. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +0 -125
  574. package/dist/esm/auth/pairing/constants.js +0 -2
  575. package/dist/esm/client/connection/WaKeyShareCoordinator.js +0 -59
  576. package/dist/esm/crypto/core/constants.js +0 -1
  577. package/dist/esm/retry/outbound.js +0 -82
  578. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
  579. package/dist/esm/store/providers/sqlite/appstate.store.js +0 -250
  580. package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
  581. package/dist/esm/store/providers/sqlite/connection.js +0 -245
  582. package/dist/esm/store/providers/sqlite/contact.store.js +0 -74
  583. package/dist/esm/store/providers/sqlite/device-list.store.js +0 -127
  584. package/dist/esm/store/providers/sqlite/message.store.js +0 -132
  585. package/dist/esm/store/providers/sqlite/migrations.js +0 -347
  586. package/dist/esm/store/providers/sqlite/participants.store.js +0 -77
  587. package/dist/esm/store/providers/sqlite/retry.store.js +0 -141
  588. package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -198
  589. package/dist/esm/store/providers/sqlite/signal.store.js +0 -435
  590. package/dist/esm/store/providers/sqlite/table-names.js +0 -107
  591. package/dist/esm/store/providers/sqlite/thread.store.js +0 -85
  592. package/dist/esm/transport/node/builders/index.js +0 -8
  593. package/dist/retry/outbound.js +0 -87
  594. package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
  595. package/dist/store/providers/sqlite/appstate.store.js +0 -254
  596. package/dist/store/providers/sqlite/auth.store.js +0 -180
  597. package/dist/store/providers/sqlite/connection.js +0 -281
  598. package/dist/store/providers/sqlite/contact.store.js +0 -78
  599. package/dist/store/providers/sqlite/device-list.store.js +0 -131
  600. package/dist/store/providers/sqlite/message.store.js +0 -136
  601. package/dist/store/providers/sqlite/migrations.js +0 -350
  602. package/dist/store/providers/sqlite/participants.store.js +0 -81
  603. package/dist/store/providers/sqlite/retry.store.js +0 -145
  604. package/dist/store/providers/sqlite/sender-key.store.js +0 -202
  605. package/dist/store/providers/sqlite/signal.store.js +0 -439
  606. package/dist/store/providers/sqlite/table-names.js +0 -113
  607. package/dist/store/providers/sqlite/thread.store.js +0 -89
  608. package/dist/transport/node/builders/index.js +0 -42
  609. package/dist/types/appstate/store/sqlite.d.ts +0 -7
  610. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +0 -14
  611. package/dist/types/auth/pairing/constants.d.ts +0 -2
  612. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +0 -14
  613. package/dist/types/crypto/core/constants.d.ts +0 -1
  614. package/dist/types/retry/outbound.d.ts +0 -4
  615. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
  616. package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -17
  617. package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
  618. package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
  619. package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -12
  620. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -15
  621. package/dist/types/store/providers/sqlite/message.store.d.ts +0 -13
  622. package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
  623. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -12
  624. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -15
  625. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -24
  626. package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -53
  627. package/dist/types/store/providers/sqlite/table-names.d.ts +0 -5
  628. package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -13
  629. package/dist/types/transport/node/builders/index.d.ts +0 -8
  630. /package/dist/appstate/{WaAppStateSyncResponseParser.js → response-parser.js} +0 -0
@@ -1,20 +1,25 @@
1
1
  import { randomBytesAsync, sha256 } from '../../crypto/index.js';
2
+ import { md5Bytes } from '../../crypto/core/primitives.js';
3
+ import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
2
4
  import { ensureMessageSecret } from '../../message/index.js';
3
- import { resolveMessageTypeAttr } from '../../message/content.js';
5
+ import { needsSecretPersistence, resolveEditAttr, resolveEncMediaType, resolveMessageTypeAttr, resolveMetaAttrs } from '../../message/content.js';
4
6
  import { wrapDeviceSentMessage } from '../../message/device-sent.js';
7
+ import { injectDeviceListMetadata, resolveIcdcMeta } from '../../message/icdc.js';
5
8
  import { writeRandomPadMax16 } from '../../message/padding.js';
6
9
  import { computePhashV2 } from '../../message/phash.js';
7
10
  import { buildReportingTokenArtifacts } from '../../message/reporting-token.js';
8
11
  import { proto } from '../../proto.js';
9
12
  import { WA_DEFAULTS } from '../../protocol/constants.js';
10
- import { isGroupJid, normalizeDeviceJid, normalizeRecipientJid, parseSignalAddressFromJid, splitJid, toUserJid } from '../../protocol/jid.js';
11
- import { signalAddressKey } from '../../protocol/jid.js';
13
+ import { isGroupJid, isLidJid, normalizeDeviceJid, normalizeRecipientJid, parseJidFull, parseSignalAddressFromJid, signalAddressKey, toUserJid } from '../../protocol/jid.js';
12
14
  import { encodeBinaryNode } from '../../transport/binary/index.js';
13
- import { buildDirectMessageFanoutNode, buildGroupDirectMessageNode, buildGroupSenderKeyMessageNode } from '../../transport/node/builders/message.js';
15
+ import { buildDirectMessageFanoutNode, buildGroupSenderKeyMessageNode, buildMetaNode } from '../../transport/node/builders/message.js';
14
16
  import { bytesToHex, concatBytes, TEXT_ENCODER } from '../../util/bytes.js';
15
17
  import { toError } from '../../util/primitives.js';
16
18
  export class WaMessageDispatchCoordinator {
17
19
  constructor(options) {
20
+ this.icdcDedup = new PromiseDedup();
21
+ this.privacyTokenDedup = new PromiseDedup();
22
+ this.distributionDedup = new PromiseDedup();
18
23
  this.logger = options.logger;
19
24
  this.messageClient = options.messageClient;
20
25
  this.retryTracker = options.retryTracker;
@@ -25,9 +30,18 @@ export class WaMessageDispatchCoordinator {
25
30
  this.buildMessageContent = options.buildMessageContent;
26
31
  this.senderKeyManager = options.senderKeyManager;
27
32
  this.signalProtocol = options.signalProtocol;
33
+ this.signalStore = options.signalStore;
34
+ this.sessionStore = options.sessionStore;
35
+ this.identityStore = options.identityStore;
36
+ this.deviceListStore = options.deviceListStore;
37
+ this.messageSecretStore = options.messageSecretStore;
28
38
  this.getCurrentMeJid = options.getCurrentMeJid;
29
39
  this.getCurrentMeLid = options.getCurrentMeLid;
30
40
  this.getCurrentSignedIdentity = options.getCurrentSignedIdentity;
41
+ this.resolvePrivacyTokenNode = options.resolvePrivacyTokenNode;
42
+ this.onDirectMessageSent = options.onDirectMessageSent;
43
+ this.getIcdcHashLength = options.getIcdcHashLength;
44
+ this.mobileMessageIdFormat = options.mobileMessageIdFormat ?? false;
31
45
  }
32
46
  async publishMessageNode(node, options = {}) {
33
47
  this.logger.debug('wa client publish message node', {
@@ -68,7 +82,8 @@ export class WaMessageDispatchCoordinator {
68
82
  toJid: input.to,
69
83
  type: input.type ?? 'text',
70
84
  replayPayload,
71
- participantJid: input.participant
85
+ participantJid: input.participant,
86
+ eligibleRequesterDeviceJids: [input.to]
72
87
  }, async () => this.messageClient.publishEncrypted(input, options));
73
88
  }
74
89
  async publishSignalMessage(input, options = {}) {
@@ -98,7 +113,8 @@ export class WaMessageDispatchCoordinator {
98
113
  toJid: input.to,
99
114
  type: messageType,
100
115
  replayPayload,
101
- participantJid: input.participant
116
+ participantJid: input.participant,
117
+ eligibleRequesterDeviceJids: [input.to]
102
118
  }, async () => this.messageClient.publishEncrypted({
103
119
  to: input.to,
104
120
  encType: encrypted.type,
@@ -118,16 +134,47 @@ export class WaMessageDispatchCoordinator {
118
134
  this.withResolvedMessageId(options)
119
135
  ]);
120
136
  const messageWithSecret = await ensureMessageSecret(message);
121
- const plaintext = await writeRandomPadMax16(proto.Message.encode(messageWithSecret).finish());
122
- const type = resolveMessageTypeAttr(messageWithSecret);
123
- if (isGroupJid(recipientJid)) {
124
- if (this.shouldUseGroupDirectPath(messageWithSecret)) {
125
- return this.publishGroupDirectMessage(recipientJid, messageWithSecret, plaintext, type, sendOptions);
137
+ const rawSecret = messageWithSecret.messageContextInfo?.messageSecret;
138
+ if (rawSecret &&
139
+ rawSecret.length > 0 &&
140
+ sendOptions.id &&
141
+ needsSecretPersistence(messageWithSecret)) {
142
+ const meJid = this.getCurrentMeJid() ?? '';
143
+ void this.messageSecretStore
144
+ .set(sendOptions.id, { secret: rawSecret, senderJid: meJid })
145
+ .catch((error) => {
146
+ this.logger.warn('failed to persist outgoing message secret', {
147
+ id: sendOptions.id,
148
+ message: toError(error).message
149
+ });
150
+ });
151
+ }
152
+ const meJid = this.getCurrentMeJid();
153
+ const regInfo = meJid ? await this.signalStore.getRegistrationInfo() : null;
154
+ const localPubKey = regInfo?.identityKeyPair.pubKey;
155
+ const meParsed = meJid ? parseJidFull(meJid) : undefined;
156
+ const meUserJid = meParsed?.userJid;
157
+ const localIdentity = meParsed && localPubKey ? { address: meParsed.address, pubKey: localPubKey } : undefined;
158
+ const isGroup = isGroupJid(recipientJid);
159
+ const [senderIcdc, recipientIcdc] = await Promise.all([
160
+ meUserJid ? this.resolveUserIcdc(meUserJid, localIdentity) : null,
161
+ !isGroup ? this.resolveUserIcdc(toUserJid(recipientJid)) : null
162
+ ]);
163
+ const messageWithIcdc = injectDeviceListMetadata(messageWithSecret, senderIcdc, recipientIcdc);
164
+ const plaintext = await writeRandomPadMax16(proto.Message.encode(messageWithIcdc).finish());
165
+ const type = resolveMessageTypeAttr(messageWithIcdc);
166
+ const edit = resolveEditAttr(messageWithIcdc, sendOptions.subtype) ?? undefined;
167
+ const mediatype = resolveEncMediaType(messageWithIcdc) ?? undefined;
168
+ const metaAttrs = resolveMetaAttrs(messageWithIcdc);
169
+ const metaNode = metaAttrs ? buildMetaNode(metaAttrs) : undefined;
170
+ if (isGroup) {
171
+ if (this.shouldUseGroupDirectPath(messageWithIcdc)) {
172
+ return this.publishGroupDirectMessage(recipientJid, messageWithIcdc, plaintext, type, sendOptions, {}, edit, mediatype, metaNode);
126
173
  }
127
- return this.publishGroupSenderKeyMessage(recipientJid, messageWithSecret, plaintext, type, sendOptions);
174
+ return this.publishGroupSenderKeyMessage(recipientJid, messageWithIcdc, plaintext, type, sendOptions, {}, edit, mediatype, metaNode);
128
175
  }
129
176
  const directRecipientJid = toUserJid(recipientJid);
130
- return this.publishDirectSignalMessageWithFanout(directRecipientJid, messageWithSecret, plaintext, type, sendOptions);
177
+ return this.publishDirectSignalMessageWithFanout(directRecipientJid, messageWithIcdc, plaintext, type, sendOptions, edit, mediatype, metaNode);
131
178
  }
132
179
  async syncSignalSession(jid, reasonIdentity = false) {
133
180
  const address = parseSignalAddressFromJid(jid);
@@ -156,7 +203,7 @@ export class WaMessageDispatchCoordinator {
156
203
  }
157
204
  return message.keepInChatMessage?.keepType === proto.KeepType.UNDO_KEEP_FOR_ALL;
158
205
  }
159
- async publishGroupDirectMessage(groupJid, message, plaintext, type, options, retryContext = {}) {
206
+ async publishGroupDirectMessage(groupJid, message, plaintext, type, options, retryContext = {}, edit, mediatype, metaNode) {
160
207
  const sendOptions = await this.withResolvedMessageId(options);
161
208
  const meJid = this.requireCurrentMeJid('sendMessage');
162
209
  const participantUserJids = retryContext.forceRefreshParticipants
@@ -169,37 +216,68 @@ export class WaMessageDispatchCoordinator {
169
216
  if (fanoutDeviceJids.length === 0) {
170
217
  throw new Error('group direct send resolved no target devices');
171
218
  }
172
- await this.sessionResolver.ensureSessionsBatch(fanoutDeviceJids);
173
- const participantAddresses = fanoutDeviceJids.map((targetJid) => parseSignalAddressFromJid(targetJid));
174
- const encryptedParticipants = await this.signalProtocol.encryptMessagesBatch(participantAddresses.map((address) => ({
175
- address,
176
- plaintext
177
- })));
178
- const participants = fanoutDeviceJids.map((targetJid, index) => ({
179
- jid: targetJid,
180
- encType: encryptedParticipants[index].type,
181
- ciphertext: encryptedParticipants[index].ciphertext
182
- }));
183
- const shouldAttachDeviceIdentity = participants.some((participant) => participant.encType === 'pkmsg');
184
- const localPhash = await computePhashV2([...fanoutDeviceJids, senderForPhash]);
185
- const reportingArtifacts = await this.tryBuildReportingTokenArtifacts({
186
- message,
187
- stanzaId: sendOptions.id,
188
- senderUserJid: toUserJid(senderForPhash),
189
- remoteJid: groupJid,
190
- context: 'group_direct'
191
- });
192
- const messageNode = buildGroupDirectMessageNode({
219
+ const resolvedFanoutTargets = await this.sessionResolver.ensureSessionsBatch(fanoutDeviceJids);
220
+ const uniqueNormalizedFanoutJids = new Set();
221
+ for (let index = 0; index < fanoutDeviceJids.length; index += 1) {
222
+ uniqueNormalizedFanoutJids.add(normalizeDeviceJid(fanoutDeviceJids[index]));
223
+ }
224
+ if (resolvedFanoutTargets.length !== uniqueNormalizedFanoutJids.size) {
225
+ throw new Error('group direct send resolved incomplete signal sessions');
226
+ }
227
+ const participantEncryptRequests = new Array(resolvedFanoutTargets.length);
228
+ for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
229
+ const target = resolvedFanoutTargets[index];
230
+ participantEncryptRequests[index] = {
231
+ address: target.address,
232
+ plaintext
233
+ };
234
+ }
235
+ const encryptedParticipants = await this.signalProtocol.encryptMessagesBatch(participantEncryptRequests, resolvedFanoutTargets);
236
+ const participants = new Array(resolvedFanoutTargets.length);
237
+ for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
238
+ const target = resolvedFanoutTargets[index];
239
+ participants[index] = {
240
+ jid: target.jid,
241
+ encType: encryptedParticipants[index].type,
242
+ ciphertext: encryptedParticipants[index].ciphertext
243
+ };
244
+ }
245
+ let shouldAttachDeviceIdentity = false;
246
+ for (let index = 0; index < participants.length; index += 1) {
247
+ if (participants[index].encType === 'pkmsg') {
248
+ shouldAttachDeviceIdentity = true;
249
+ break;
250
+ }
251
+ }
252
+ const phashTargets = new Array(resolvedFanoutTargets.length + 1);
253
+ for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
254
+ phashTargets[index] = resolvedFanoutTargets[index].jid;
255
+ }
256
+ phashTargets[resolvedFanoutTargets.length] = senderForPhash;
257
+ const [localPhash, reportingArtifacts] = await Promise.all([
258
+ computePhashV2(phashTargets),
259
+ this.tryBuildReportingTokenArtifacts({
260
+ message,
261
+ stanzaId: sendOptions.id,
262
+ senderUserJid: toUserJid(senderForPhash),
263
+ remoteJid: groupJid,
264
+ context: 'group_direct'
265
+ })
266
+ ]);
267
+ const messageNode = buildDirectMessageFanoutNode({
193
268
  to: groupJid,
194
269
  type,
195
270
  id: sendOptions.id,
271
+ edit,
196
272
  phash: localPhash,
197
273
  addressingMode,
198
274
  participants,
199
275
  deviceIdentity: shouldAttachDeviceIdentity
200
276
  ? this.getEncodedSignedDeviceIdentity()
201
277
  : undefined,
202
- reportingNode: reportingArtifacts?.node ?? undefined
278
+ reportingNode: reportingArtifacts?.node ?? undefined,
279
+ metaNode,
280
+ mediatype
203
281
  });
204
282
  const replayPayload = {
205
283
  mode: 'plaintext',
@@ -211,7 +289,8 @@ export class WaMessageDispatchCoordinator {
211
289
  messageIdHint: sendOptions.id ?? messageNode.attrs.id,
212
290
  toJid: groupJid,
213
291
  type,
214
- replayPayload
292
+ replayPayload,
293
+ eligibleRequesterDeviceJids: undefined
215
294
  }, async () => this.messageClient.publishNode(messageNode, sendOptions));
216
295
  const ackError = result.ack.error;
217
296
  const serverPhash = result.ack.phash;
@@ -237,11 +316,11 @@ export class WaMessageDispatchCoordinator {
237
316
  retried: true,
238
317
  forceRefreshParticipants: true,
239
318
  forceAddressingMode: serverAddressingMode
240
- });
319
+ }, edit, mediatype, metaNode);
241
320
  }
242
321
  return result;
243
322
  }
244
- async publishGroupSenderKeyMessage(groupJid, message, plaintext, type, options, retryContext = {}) {
323
+ async publishGroupSenderKeyMessage(groupJid, message, plaintext, type, options, retryContext = {}, edit, mediatype, metaNode) {
245
324
  const sendOptions = await this.withResolvedMessageId(options);
246
325
  const meJid = this.requireCurrentMeJid('sendMessage');
247
326
  const participantUserJids = retryContext.forceRefreshParticipants
@@ -251,23 +330,36 @@ export class WaMessageDispatchCoordinator {
251
330
  this.resolveGroupAddressingMode(participantUserJids, groupJid);
252
331
  const senderJid = this.resolveSenderForAddressingMode(addressingMode, meJid);
253
332
  const sender = parseSignalAddressFromJid(senderJid);
254
- const senderKeyDistributionMessage = await this.senderKeyManager.createSenderKeyDistributionMessage(groupJid, sender);
255
- const groupCiphertext = await this.senderKeyManager.encryptGroupMessage(groupJid, sender, plaintext);
256
- const distributionData = await this.encryptGroupDistributionParticipants(groupJid, sender, senderKeyDistributionMessage, participantUserJids);
333
+ const { distributionMessage: senderKeyDistributionMessage, ciphertext: groupCiphertext, keyId: senderKeyId } = await this.senderKeyManager.prepareGroupEncryption(groupJid, sender, plaintext);
334
+ const distributionData = await this.distributionDedup.run(`dist:${groupJid}:${senderKeyId}`, () => this.encryptGroupDistributionParticipants(groupJid, senderKeyId, senderKeyDistributionMessage, participantUserJids));
257
335
  const { fanoutDeviceJids, distributionParticipants } = distributionData;
258
- const shouldAttachDeviceIdentity = distributionParticipants.some((participant) => participant.encType === 'pkmsg');
259
- const localPhash = await computePhashV2([...fanoutDeviceJids, senderJid]);
260
- const reportingArtifacts = await this.tryBuildReportingTokenArtifacts({
261
- message,
262
- stanzaId: sendOptions.id,
263
- senderUserJid: toUserJid(senderJid),
264
- remoteJid: groupJid,
265
- context: 'group_sender_key'
266
- });
336
+ let shouldAttachDeviceIdentity = false;
337
+ for (let index = 0; index < distributionParticipants.length; index += 1) {
338
+ if (distributionParticipants[index].encType === 'pkmsg') {
339
+ shouldAttachDeviceIdentity = true;
340
+ break;
341
+ }
342
+ }
343
+ const phashTargets = new Array(fanoutDeviceJids.length + 1);
344
+ for (let index = 0; index < fanoutDeviceJids.length; index += 1) {
345
+ phashTargets[index] = fanoutDeviceJids[index];
346
+ }
347
+ phashTargets[fanoutDeviceJids.length] = senderJid;
348
+ const [localPhash, reportingArtifacts] = await Promise.all([
349
+ computePhashV2(phashTargets),
350
+ this.tryBuildReportingTokenArtifacts({
351
+ message,
352
+ stanzaId: sendOptions.id,
353
+ senderUserJid: toUserJid(senderJid),
354
+ remoteJid: groupJid,
355
+ context: 'group_sender_key'
356
+ })
357
+ ]);
267
358
  const messageNode = buildGroupSenderKeyMessageNode({
268
359
  to: groupJid,
269
360
  type,
270
361
  id: sendOptions.id,
362
+ edit,
271
363
  phash: localPhash,
272
364
  addressingMode,
273
365
  groupCiphertext: groupCiphertext.ciphertext,
@@ -275,7 +367,9 @@ export class WaMessageDispatchCoordinator {
275
367
  deviceIdentity: shouldAttachDeviceIdentity
276
368
  ? this.getEncodedSignedDeviceIdentity()
277
369
  : undefined,
278
- reportingNode: reportingArtifacts?.node ?? undefined
370
+ reportingNode: reportingArtifacts?.node ?? undefined,
371
+ metaNode,
372
+ mediatype
279
373
  });
280
374
  const replayPayload = {
281
375
  mode: 'plaintext',
@@ -287,11 +381,15 @@ export class WaMessageDispatchCoordinator {
287
381
  messageIdHint: sendOptions.id ?? messageNode.attrs.id,
288
382
  toJid: groupJid,
289
383
  type,
290
- replayPayload
384
+ replayPayload,
385
+ eligibleRequesterDeviceJids: undefined
291
386
  }, async () => this.messageClient.publishNode(messageNode, sendOptions));
292
- const distributedAddresses = distributionParticipants.map((participant) => participant.address);
387
+ const distributedAddresses = new Array(distributionParticipants.length);
388
+ for (let index = 0; index < distributionParticipants.length; index += 1) {
389
+ distributedAddresses[index] = distributionParticipants[index].address;
390
+ }
293
391
  try {
294
- await this.senderKeyManager.markSenderKeyDistributed(groupJid, sender, distributedAddresses);
392
+ await this.senderKeyManager.markSenderKeyDistributed(groupJid, senderKeyId, distributedAddresses);
295
393
  }
296
394
  catch (error) {
297
395
  this.logger.warn('failed to mark sender key distribution targets', {
@@ -324,19 +422,14 @@ export class WaMessageDispatchCoordinator {
324
422
  retried: true,
325
423
  forceRefreshParticipants: true,
326
424
  forceAddressingMode: serverAddressingMode
327
- });
425
+ }, edit, mediatype, metaNode);
328
426
  }
329
427
  return result;
330
428
  }
331
429
  resolveGroupAddressingMode(participantUserJids, groupJid) {
332
- for (const participantJid of participantUserJids) {
333
- try {
334
- if (splitJid(participantJid).server === 'lid') {
335
- return 'lid';
336
- }
337
- }
338
- catch (error) {
339
- this.logger.trace('ignoring malformed participant jid in addressing mode resolution', { participantJid, message: toError(error).message });
430
+ for (let index = 0; index < participantUserJids.length; index += 1) {
431
+ if (isLidJid(participantUserJids[index])) {
432
+ return 'lid';
340
433
  }
341
434
  }
342
435
  this.logger.trace('group addressing mode resolved to pn (default)', {
@@ -362,7 +455,7 @@ export class WaMessageDispatchCoordinator {
362
455
  }
363
456
  return normalizeDeviceJid(meJid);
364
457
  }
365
- async encryptGroupDistributionParticipants(groupJid, sender, senderKeyDistributionMessage, participantUserJids) {
458
+ async encryptGroupDistributionParticipants(groupJid, senderKeyId, senderKeyDistributionMessage, participantUserJids) {
366
459
  const distributionPayload = await writeRandomPadMax16(proto.Message.encode({
367
460
  senderKeyDistributionMessage
368
461
  }).finish());
@@ -381,7 +474,7 @@ export class WaMessageDispatchCoordinator {
381
474
  fanoutAddresses[index] = address;
382
475
  fanoutTargetsByAddressKey.set(signalAddressKey(address), { jid, address });
383
476
  }
384
- const pendingAddresses = await this.senderKeyManager.filterParticipantsNeedingDistribution(groupJid, sender, fanoutAddresses);
477
+ const pendingAddresses = await this.senderKeyManager.filterParticipantsNeedingDistribution(groupJid, senderKeyId, fanoutAddresses);
385
478
  if (pendingAddresses.length === 0) {
386
479
  return {
387
480
  fanoutDeviceJids,
@@ -411,50 +504,82 @@ export class WaMessageDispatchCoordinator {
411
504
  for (let index = 0; index < pendingTargets.length; index += 1) {
412
505
  pendingTargetJids[index] = pendingTargets[index].jid;
413
506
  }
507
+ let availableTargets = [];
508
+ let prefetchedAvailableTargets;
414
509
  try {
415
- await this.sessionResolver.ensureSessionsBatch(pendingTargetJids);
510
+ const resolvedTargets = await this.sessionResolver.ensureSessionsBatch(pendingTargetJids);
511
+ availableTargets = resolvedTargets;
512
+ prefetchedAvailableTargets = resolvedTargets;
416
513
  }
417
514
  catch (error) {
515
+ const normalized = toError(error);
516
+ if (normalized.message === 'identity mismatch') {
517
+ throw normalized;
518
+ }
418
519
  this.logger.warn('group sender-key distribution session sync failed, continuing with available sessions', {
419
520
  groupJid,
420
521
  requested: pendingTargetJids.length,
421
- message: toError(error).message
522
+ message: normalized.message
422
523
  });
524
+ const pendingTargetAddresses = new Array(pendingTargets.length);
525
+ for (let index = 0; index < pendingTargets.length; index += 1) {
526
+ pendingTargetAddresses[index] = pendingTargets[index].address;
527
+ }
528
+ const hasPendingSessions = await this.sessionStore.hasSessions(pendingTargetAddresses);
529
+ const nextAvailableTargets = [];
530
+ for (let index = 0; index < pendingTargets.length; index += 1) {
531
+ if (hasPendingSessions[index]) {
532
+ nextAvailableTargets.push(pendingTargets[index]);
533
+ }
534
+ }
535
+ availableTargets = nextAvailableTargets;
423
536
  }
424
- const hasPendingSessions = await this.signalProtocol.hasSessions(pendingTargets.map((target) => target.address));
425
- const availableTargets = pendingTargets.filter((_target, index) => hasPendingSessions[index]);
426
537
  if (availableTargets.length === 0) {
427
538
  return {
428
539
  fanoutDeviceJids,
429
540
  distributionParticipants: []
430
541
  };
431
542
  }
432
- const encryptedDistributionParticipants = await this.signalProtocol.encryptMessagesBatch(availableTargets.map((target) => ({
433
- address: target.address,
434
- plaintext: distributionPayload
435
- })));
436
- const distributionParticipants = availableTargets.map((target, index) => ({
437
- jid: target.jid,
438
- address: target.address,
439
- encType: encryptedDistributionParticipants[index].type,
440
- ciphertext: encryptedDistributionParticipants[index].ciphertext
441
- }));
543
+ const distributionEncryptRequests = new Array(availableTargets.length);
544
+ for (let index = 0; index < availableTargets.length; index += 1) {
545
+ const target = availableTargets[index];
546
+ distributionEncryptRequests[index] = {
547
+ address: target.address,
548
+ plaintext: distributionPayload
549
+ };
550
+ }
551
+ const encryptedDistributionParticipants = await this.signalProtocol.encryptMessagesBatch(distributionEncryptRequests, prefetchedAvailableTargets);
552
+ const distributionParticipants = new Array(availableTargets.length);
553
+ for (let index = 0; index < availableTargets.length; index += 1) {
554
+ const target = availableTargets[index];
555
+ distributionParticipants[index] = {
556
+ jid: target.jid,
557
+ address: target.address,
558
+ encType: encryptedDistributionParticipants[index].type,
559
+ ciphertext: encryptedDistributionParticipants[index].ciphertext
560
+ };
561
+ }
442
562
  return {
443
563
  fanoutDeviceJids,
444
564
  distributionParticipants
445
565
  };
446
566
  }
447
- async publishDirectSignalMessageWithFanout(recipientJid, message, plaintext, type, options) {
567
+ async publishDirectSignalMessageWithFanout(recipientJid, message, plaintext, type, options, edit, mediatype, metaNode) {
448
568
  const sendOptions = await this.withResolvedMessageId(options);
449
569
  const meJid = this.requireCurrentMeJid('sendMessage');
450
570
  const meLid = this.getCurrentMeLid();
451
571
  const selfDeviceJidForRecipient = this.fanoutResolver.resolveSelfDeviceJidForRecipient(recipientJid, meJid, meLid);
452
572
  const deviceJids = await this.fanoutResolver.resolveDirectFanoutDeviceJids(recipientJid, selfDeviceJidForRecipient);
453
- const targets = deviceJids.map((jid) => ({
454
- jid,
455
- normalizedJid: normalizeDeviceJid(jid),
456
- userJid: toUserJid(jid)
457
- }));
573
+ const targets = new Array(deviceJids.length);
574
+ for (let index = 0; index < deviceJids.length; index += 1) {
575
+ const jid = deviceJids[index];
576
+ const parsed = parseJidFull(jid);
577
+ targets[index] = {
578
+ jid,
579
+ normalizedJid: parsed.normalizedJid,
580
+ userJid: parsed.userJid
581
+ };
582
+ }
458
583
  const recipientUserJid = toUserJid(recipientJid);
459
584
  const meUserJid = toUserJid(selfDeviceJidForRecipient);
460
585
  this.logger.debug('wa client publish signal fanout', {
@@ -471,30 +596,75 @@ export class WaMessageDispatchCoordinator {
471
596
  }
472
597
  }
473
598
  }
474
- await this.sessionResolver.ensureSessionsBatch(deviceJids, expectedIdentityByJid);
475
- const hasSelfDeviceFanout = targets.some((target) => target.userJid === meUserJid);
599
+ const resolvedFanoutTargets = await this.sessionResolver.ensureSessionsBatch(deviceJids, expectedIdentityByJid);
600
+ const resolvedFanoutTargetsByJid = new Map();
601
+ for (let index = 0; index < resolvedFanoutTargets.length; index += 1) {
602
+ const target = resolvedFanoutTargets[index];
603
+ resolvedFanoutTargetsByJid.set(normalizeDeviceJid(target.jid), target);
604
+ }
605
+ for (let index = 0; index < targets.length; index += 1) {
606
+ if (!resolvedFanoutTargetsByJid.has(targets[index].normalizedJid)) {
607
+ throw new Error('direct fanout missing signal sessions for one or more targets');
608
+ }
609
+ }
610
+ let hasSelfDeviceFanout = false;
611
+ for (let index = 0; index < targets.length; index += 1) {
612
+ if (targets[index].userJid === meUserJid) {
613
+ hasSelfDeviceFanout = true;
614
+ break;
615
+ }
616
+ }
476
617
  const selfDevicePlaintext = hasSelfDeviceFanout
477
618
  ? await writeRandomPadMax16(proto.Message.encode(wrapDeviceSentMessage(message, recipientUserJid)).finish())
478
619
  : null;
479
- const participantRequests = targets.map((target) => ({
480
- target,
481
- address: parseSignalAddressFromJid(target.jid),
482
- expectedIdentity: target.userJid === recipientUserJid ? sendOptions.expectedIdentity : undefined,
483
- plaintext: selfDevicePlaintext && target.userJid === meUserJid
484
- ? selfDevicePlaintext
485
- : plaintext
486
- }));
487
- const encryptedParticipants = await this.signalProtocol.encryptMessagesBatch(participantRequests.map((request) => ({
488
- address: request.address,
489
- plaintext: request.plaintext,
490
- expectedIdentity: request.expectedIdentity
491
- })));
492
- const participants = participantRequests.map((request, index) => ({
493
- jid: request.target.jid,
494
- encType: encryptedParticipants[index].type,
495
- ciphertext: encryptedParticipants[index].ciphertext
496
- }));
497
- const shouldAttachDeviceIdentity = participants.some((participant) => participant.encType === 'pkmsg');
620
+ const participantRequests = new Array(targets.length);
621
+ for (let index = 0; index < targets.length; index += 1) {
622
+ const target = targets[index];
623
+ const resolvedTarget = resolvedFanoutTargetsByJid.get(target.normalizedJid);
624
+ if (!resolvedTarget) {
625
+ throw new Error('direct fanout missing signal session for target');
626
+ }
627
+ participantRequests[index] = {
628
+ target,
629
+ address: resolvedTarget.address,
630
+ session: resolvedTarget.session,
631
+ expectedIdentity: target.userJid === recipientUserJid ? sendOptions.expectedIdentity : undefined,
632
+ plaintext: selfDevicePlaintext && target.userJid === meUserJid
633
+ ? selfDevicePlaintext
634
+ : plaintext
635
+ };
636
+ }
637
+ const encryptRequests = new Array(participantRequests.length);
638
+ const prefetchedSessions = new Array(participantRequests.length);
639
+ for (let index = 0; index < participantRequests.length; index += 1) {
640
+ const request = participantRequests[index];
641
+ encryptRequests[index] = {
642
+ address: request.address,
643
+ plaintext: request.plaintext,
644
+ expectedIdentity: request.expectedIdentity
645
+ };
646
+ prefetchedSessions[index] = {
647
+ address: request.address,
648
+ session: request.session
649
+ };
650
+ }
651
+ const encryptedParticipants = await this.signalProtocol.encryptMessagesBatch(encryptRequests, prefetchedSessions);
652
+ const participants = new Array(participantRequests.length);
653
+ for (let index = 0; index < participantRequests.length; index += 1) {
654
+ const request = participantRequests[index];
655
+ participants[index] = {
656
+ jid: request.target.jid,
657
+ encType: encryptedParticipants[index].type,
658
+ ciphertext: encryptedParticipants[index].ciphertext
659
+ };
660
+ }
661
+ let shouldAttachDeviceIdentity = false;
662
+ for (let index = 0; index < participants.length; index += 1) {
663
+ if (participants[index].encType === 'pkmsg') {
664
+ shouldAttachDeviceIdentity = true;
665
+ break;
666
+ }
667
+ }
498
668
  const deviceIdentity = shouldAttachDeviceIdentity
499
669
  ? this.getEncodedSignedDeviceIdentity()
500
670
  : undefined;
@@ -505,13 +675,28 @@ export class WaMessageDispatchCoordinator {
505
675
  remoteJid: recipientUserJid,
506
676
  context: 'direct_fanout'
507
677
  });
678
+ let privacyTokenNode;
679
+ try {
680
+ privacyTokenNode =
681
+ (await this.privacyTokenDedup.run(`pt:${recipientUserJid}`, () => this.resolvePrivacyTokenNode(recipientUserJid))) ?? undefined;
682
+ }
683
+ catch (error) {
684
+ this.logger.warn('privacy token resolution failed', {
685
+ to: recipientUserJid,
686
+ message: toError(error).message
687
+ });
688
+ }
508
689
  const messageNode = buildDirectMessageFanoutNode({
509
690
  to: recipientJid,
510
691
  type,
511
692
  id: sendOptions.id,
693
+ edit,
512
694
  participants,
513
695
  deviceIdentity,
514
- reportingNode: reportingArtifacts?.node ?? undefined
696
+ reportingNode: reportingArtifacts?.node ?? undefined,
697
+ privacyTokenNode,
698
+ metaNode,
699
+ mediatype
515
700
  });
516
701
  const replayPayload = {
517
702
  mode: 'plaintext',
@@ -519,12 +704,15 @@ export class WaMessageDispatchCoordinator {
519
704
  type,
520
705
  plaintext
521
706
  };
522
- return this.retryTracker.track({
707
+ const result = await this.retryTracker.track({
523
708
  messageIdHint: sendOptions.id ?? messageNode.attrs.id,
524
709
  toJid: recipientJid,
525
710
  type,
526
- replayPayload
711
+ replayPayload,
712
+ eligibleRequesterDeviceJids: deviceJids
527
713
  }, async () => this.messageClient.publishNode(messageNode, sendOptions));
714
+ this.onDirectMessageSent(recipientUserJid);
715
+ return result;
528
716
  }
529
717
  async withResolvedMessageId(options) {
530
718
  const normalizedId = options.id?.trim();
@@ -545,9 +733,20 @@ export class WaMessageDispatchCoordinator {
545
733
  async generateOutgoingMessageId() {
546
734
  try {
547
735
  const meUserJid = toUserJid(this.requireCurrentMeJid('sendMessage'));
548
- const timestampSeconds = Math.floor(Date.now() / 1000);
549
736
  const timestampBytes = new Uint8Array(8);
550
- new DataView(timestampBytes.buffer, timestampBytes.byteOffset, timestampBytes.byteLength).setBigUint64(0, BigInt(timestampSeconds), false);
737
+ const dv = new DataView(timestampBytes.buffer, timestampBytes.byteOffset, timestampBytes.byteLength);
738
+ if (this.mobileMessageIdFormat) {
739
+ dv.setBigUint64(0, BigInt(Date.now()), false);
740
+ const entropy = concatBytes([
741
+ timestampBytes,
742
+ TEXT_ENCODER.encode(meUserJid),
743
+ await randomBytesAsync(16)
744
+ ]);
745
+ const digest = md5Bytes(entropy);
746
+ digest[0] = 0xac;
747
+ return bytesToHex(digest).toUpperCase();
748
+ }
749
+ dv.setBigUint64(0, BigInt(Math.floor(Date.now() / 1000)), false);
551
750
  const entropy = concatBytes([
552
751
  timestampBytes,
553
752
  TEXT_ENCODER.encode(meUserJid),
@@ -557,9 +756,14 @@ export class WaMessageDispatchCoordinator {
557
756
  return `3EB0${bytesToHex(digest.subarray(0, 9)).toUpperCase()}`;
558
757
  }
559
758
  catch (error) {
560
- this.logger.warn('failed to generate sha256 message id, falling back to random id', {
759
+ this.logger.warn('failed to generate message id, falling back to random', {
561
760
  message: toError(error).message
562
761
  });
762
+ if (this.mobileMessageIdFormat) {
763
+ const bytes = await randomBytesAsync(16);
764
+ bytes[0] = 0xac;
765
+ return bytesToHex(bytes).toUpperCase();
766
+ }
563
767
  return `3EB0${bytesToHex(await randomBytesAsync(8)).toUpperCase()}`;
564
768
  }
565
769
  }
@@ -588,10 +792,29 @@ export class WaMessageDispatchCoordinator {
588
792
  getEncodedSignedDeviceIdentity() {
589
793
  const signedIdentity = this.getCurrentSignedIdentity();
590
794
  if (!signedIdentity) {
591
- throw new Error('missing signed identity for pkmsg fanout');
795
+ return undefined;
592
796
  }
593
797
  return proto.ADVSignedDeviceIdentity.encode(signedIdentity).finish();
594
798
  }
799
+ resolveUserIcdc(userJid, localIdentity) {
800
+ return this.icdcDedup.run(`icdc:${userJid}:${localIdentity ? '1' : '0'}`, async () => {
801
+ try {
802
+ const snapshots = await this.deviceListStore.getUserDevicesBatch([userJid]);
803
+ const snapshot = snapshots[0];
804
+ if (!snapshot || snapshot.deviceJids.length === 0) {
805
+ return null;
806
+ }
807
+ return resolveIcdcMeta(snapshot.deviceJids, this.identityStore, snapshot.updatedAtMs, localIdentity, this.getIcdcHashLength?.());
808
+ }
809
+ catch (error) {
810
+ this.logger.trace('icdc resolution failed', {
811
+ userJid,
812
+ message: toError(error).message
813
+ });
814
+ return null;
815
+ }
816
+ });
817
+ }
595
818
  requireCurrentMeJid(context) {
596
819
  const meJid = this.getCurrentMeJid();
597
820
  if (meJid) {