zapo-js 0.1.1 → 0.2.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 (589) hide show
  1. package/README.md +20 -4
  2. package/dist/appstate/WaAppStateCrypto.js +19 -26
  3. package/dist/appstate/WaAppStateSyncClient.js +293 -181
  4. package/dist/appstate/WaAppStateSyncResponseParser.js +16 -5
  5. package/dist/appstate/constants.js +4 -3
  6. package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
  7. package/dist/appstate/index.js +8 -6
  8. package/dist/appstate/utils.js +9 -34
  9. package/dist/auth/WaAuthClient.js +43 -61
  10. package/dist/auth/flow/WaAuthCredentialsFlow.js +22 -15
  11. package/dist/auth/index.js +1 -8
  12. package/dist/auth/pairing/WaPairingCodeCrypto.js +6 -4
  13. package/dist/auth/pairing/WaPairingFlow.js +34 -26
  14. package/dist/auth/pairing/WaQrFlow.js +37 -24
  15. package/dist/client/WaClient.js +275 -324
  16. package/dist/client/WaClientFactory.js +500 -133
  17. package/dist/client/connection/WaConnectionManager.js +301 -0
  18. package/dist/client/connection/WaKeyShareCoordinator.js +63 -0
  19. package/dist/client/connection/WaReceiptQueue.js +51 -0
  20. package/dist/client/coordinators/WaAppStateMutationCoordinator.js +471 -0
  21. package/dist/client/coordinators/WaBusinessCoordinator.js +241 -0
  22. package/dist/client/coordinators/WaGroupCoordinator.js +30 -16
  23. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
  24. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +439 -701
  25. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  26. package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
  27. package/dist/client/coordinators/WaProfileCoordinator.js +212 -0
  28. package/dist/client/coordinators/WaRetryCoordinator.js +242 -57
  29. package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
  30. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +166 -0
  31. package/dist/client/dirty.js +74 -48
  32. package/dist/client/events/chat.js +4 -3
  33. package/dist/client/events/devices.js +72 -0
  34. package/dist/client/events/group.js +62 -47
  35. package/dist/client/events/identity.js +22 -0
  36. package/dist/client/events/privacy-token.js +39 -0
  37. package/dist/client/history-sync.js +94 -63
  38. package/dist/client/incoming.js +60 -27
  39. package/dist/client/mailbox.js +24 -23
  40. package/dist/client/messages.js +107 -31
  41. package/dist/client/messaging/fanout.js +199 -0
  42. package/dist/client/messaging/key-protocol.js +130 -0
  43. package/dist/client/messaging/participants.js +193 -0
  44. package/dist/client/persistence/WriteBehindPersistence.js +129 -0
  45. package/dist/client/tokens/cs-token.js +50 -0
  46. package/dist/client/tokens/tc-token.js +25 -0
  47. package/dist/crypto/core/hkdf.js +3 -8
  48. package/dist/crypto/core/index.js +2 -5
  49. package/dist/crypto/core/keys.js +6 -7
  50. package/dist/crypto/core/nonce.js +2 -0
  51. package/dist/crypto/core/primitives.js +12 -23
  52. package/dist/crypto/core/random.js +26 -23
  53. package/dist/crypto/curves/Ed25519.js +7 -8
  54. package/dist/crypto/curves/X25519.js +38 -22
  55. package/dist/crypto/index.js +1 -3
  56. package/dist/crypto/math/constants.js +13 -36
  57. package/dist/crypto/math/edwards.js +171 -44
  58. package/dist/crypto/math/fe.js +706 -0
  59. package/dist/crypto/math/mod.js +10 -3
  60. package/dist/esm/appstate/WaAppStateCrypto.js +7 -14
  61. package/dist/esm/appstate/WaAppStateSyncClient.js +284 -172
  62. package/dist/esm/appstate/WaAppStateSyncResponseParser.js +17 -6
  63. package/dist/esm/appstate/constants.js +3 -2
  64. package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
  65. package/dist/esm/appstate/index.js +2 -2
  66. package/dist/esm/appstate/utils.js +8 -30
  67. package/dist/esm/auth/WaAuthClient.js +43 -61
  68. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +22 -15
  69. package/dist/esm/auth/index.js +0 -3
  70. package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +6 -4
  71. package/dist/esm/auth/pairing/WaPairingFlow.js +28 -20
  72. package/dist/esm/auth/pairing/WaQrFlow.js +37 -24
  73. package/dist/esm/client/WaClient.js +275 -324
  74. package/dist/esm/client/WaClientFactory.js +501 -134
  75. package/dist/esm/client/connection/WaConnectionManager.js +297 -0
  76. package/dist/esm/client/connection/WaKeyShareCoordinator.js +59 -0
  77. package/dist/esm/client/connection/WaReceiptQueue.js +47 -0
  78. package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +467 -0
  79. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +238 -0
  80. package/dist/esm/client/coordinators/WaGroupCoordinator.js +23 -9
  81. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
  82. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +443 -705
  83. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  84. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
  85. package/dist/esm/client/coordinators/WaProfileCoordinator.js +209 -0
  86. package/dist/esm/client/coordinators/WaRetryCoordinator.js +244 -59
  87. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
  88. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +162 -0
  89. package/dist/esm/client/dirty.js +69 -43
  90. package/dist/esm/client/events/chat.js +4 -3
  91. package/dist/esm/client/events/devices.js +68 -0
  92. package/dist/esm/client/events/group.js +53 -39
  93. package/dist/esm/client/events/identity.js +19 -0
  94. package/dist/esm/client/events/privacy-token.js +36 -0
  95. package/dist/esm/client/history-sync.js +91 -60
  96. package/dist/esm/client/incoming.js +61 -28
  97. package/dist/esm/client/mailbox.js +24 -23
  98. package/dist/esm/client/messages.js +108 -32
  99. package/dist/esm/client/messaging/fanout.js +196 -0
  100. package/dist/esm/client/messaging/key-protocol.js +127 -0
  101. package/dist/esm/client/messaging/participants.js +190 -0
  102. package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
  103. package/dist/esm/client/tokens/cs-token.js +46 -0
  104. package/dist/esm/client/tokens/tc-token.js +18 -0
  105. package/dist/esm/crypto/core/hkdf.js +3 -8
  106. package/dist/esm/crypto/core/index.js +2 -3
  107. package/dist/esm/crypto/core/keys.js +3 -4
  108. package/dist/esm/crypto/core/nonce.js +2 -0
  109. package/dist/esm/crypto/core/primitives.js +12 -22
  110. package/dist/esm/crypto/core/random.js +25 -23
  111. package/dist/esm/crypto/curves/Ed25519.js +4 -5
  112. package/dist/esm/crypto/curves/X25519.js +35 -19
  113. package/dist/esm/crypto/index.js +0 -1
  114. package/dist/esm/crypto/math/constants.js +12 -35
  115. package/dist/esm/crypto/math/edwards.js +174 -47
  116. package/dist/esm/crypto/math/fe.js +691 -0
  117. package/dist/esm/crypto/math/mod.js +10 -1
  118. package/dist/esm/index.js +1 -1
  119. package/dist/esm/infra/log/ConsoleLogger.js +18 -17
  120. package/dist/esm/infra/log/PinoLogger.js +15 -9
  121. package/dist/esm/infra/log/types.js +11 -1
  122. package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
  123. package/dist/esm/infra/perf/BoundedTaskQueue.js +16 -18
  124. package/dist/esm/infra/perf/PromiseDedup.js +20 -0
  125. package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
  126. package/dist/esm/infra/perf/StoreLock.js +77 -0
  127. package/dist/esm/media/WaMediaCrypto.js +96 -16
  128. package/dist/esm/media/WaMediaTransferClient.js +251 -91
  129. package/dist/esm/media/conn.js +10 -6
  130. package/dist/esm/media/constants.js +6 -2
  131. package/dist/esm/message/WaMessageClient.js +30 -32
  132. package/dist/esm/message/ack.js +6 -6
  133. package/dist/esm/message/addon-crypto.js +59 -0
  134. package/dist/esm/message/content.js +195 -9
  135. package/dist/esm/message/icdc.js +76 -0
  136. package/dist/esm/message/incoming.js +129 -122
  137. package/dist/esm/message/index.js +2 -0
  138. package/dist/esm/message/phash.js +3 -1
  139. package/dist/esm/message/reporting-token.js +425 -0
  140. package/dist/esm/message/use-case-secret.js +49 -0
  141. package/dist/esm/protocol/appstate.js +27 -0
  142. package/dist/esm/protocol/browser.js +10 -18
  143. package/dist/esm/protocol/constants.js +6 -3
  144. package/dist/esm/protocol/defaults.js +6 -0
  145. package/dist/esm/protocol/index.js +2 -11
  146. package/dist/esm/protocol/jid.js +133 -52
  147. package/dist/esm/protocol/media.js +3 -3
  148. package/dist/esm/protocol/message.js +61 -1
  149. package/dist/esm/protocol/nodes.js +4 -0
  150. package/dist/esm/protocol/notification.js +3 -1
  151. package/dist/esm/protocol/privacy-token.js +17 -0
  152. package/dist/esm/protocol/privacy.js +55 -0
  153. package/dist/esm/protocol/stream.js +26 -1
  154. package/dist/esm/protocol/usync.js +11 -0
  155. package/dist/esm/retry/codec.js +216 -0
  156. package/dist/esm/retry/constants.js +1 -1
  157. package/dist/esm/retry/index.js +3 -2
  158. package/dist/esm/retry/parse.js +88 -86
  159. package/dist/esm/retry/replay.js +54 -51
  160. package/dist/esm/retry/tracker.js +94 -0
  161. package/dist/esm/signal/api/SignalDeviceSyncApi.js +276 -92
  162. package/dist/esm/signal/api/SignalDigestSyncApi.js +17 -8
  163. package/dist/esm/signal/api/SignalIdentitySyncApi.js +67 -37
  164. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +86 -67
  165. package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
  166. package/dist/esm/signal/api/SignalSessionSyncApi.js +36 -34
  167. package/dist/esm/signal/api/result-map.js +10 -0
  168. package/dist/esm/signal/constants.js +0 -4
  169. package/dist/esm/signal/crypto/WaAdvSignature.js +13 -9
  170. package/dist/esm/signal/{store/sqlite.js → encoding.js} +93 -60
  171. package/dist/esm/signal/group/SenderKeyChain.js +28 -23
  172. package/dist/esm/signal/group/SenderKeyCodec.js +5 -6
  173. package/dist/esm/signal/group/SenderKeyManager.js +144 -115
  174. package/dist/esm/signal/index.js +2 -0
  175. package/dist/esm/signal/registration/keygen.js +6 -2
  176. package/dist/esm/signal/registration/utils.js +1 -0
  177. package/dist/esm/signal/session/SignalProtocol.js +164 -53
  178. package/dist/esm/signal/session/SignalRatchet.js +24 -15
  179. package/dist/esm/signal/session/SignalSession.js +14 -9
  180. package/dist/esm/signal/session/resolver.js +221 -0
  181. package/dist/esm/store/contracts/privacy-token.store.js +1 -0
  182. package/dist/esm/store/createStore.js +100 -188
  183. package/dist/esm/store/index.js +1 -10
  184. package/dist/esm/store/locks/appstate.lock.js +26 -0
  185. package/dist/esm/store/locks/auth.lock.js +15 -0
  186. package/dist/esm/store/locks/contact.lock.js +20 -0
  187. package/dist/esm/store/locks/device-list.lock.js +20 -0
  188. package/dist/esm/store/locks/message.lock.js +21 -0
  189. package/dist/esm/store/locks/participants.lock.js +20 -0
  190. package/dist/esm/store/locks/privacy-token.lock.js +18 -0
  191. package/dist/esm/store/locks/retry.lock.js +29 -0
  192. package/dist/esm/store/locks/sender-key.lock.js +52 -0
  193. package/dist/esm/store/locks/signal.lock.js +63 -0
  194. package/dist/esm/store/locks/thread.lock.js +21 -0
  195. package/dist/esm/store/noop.store.js +4 -7
  196. package/dist/esm/store/providers/memory/appstate.store.js +38 -16
  197. package/dist/esm/store/providers/memory/contact.store.js +5 -0
  198. package/dist/esm/store/providers/memory/device-list.store.js +12 -34
  199. package/dist/esm/store/providers/memory/message.store.js +11 -5
  200. package/dist/esm/store/providers/memory/participants.store.js +1 -8
  201. package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
  202. package/dist/esm/store/providers/memory/retry.store.js +77 -2
  203. package/dist/esm/store/providers/memory/sender-key.store.js +11 -8
  204. package/dist/esm/store/providers/memory/signal.store.js +47 -18
  205. package/dist/esm/store/providers/memory/thread.store.js +5 -0
  206. package/dist/esm/transport/WaComms.js +28 -24
  207. package/dist/esm/transport/WaWebSocket.js +115 -18
  208. package/dist/esm/transport/binary/constants.js +0 -30
  209. package/dist/esm/transport/binary/decoder.js +8 -8
  210. package/dist/esm/transport/binary/encoder.js +10 -9
  211. package/dist/esm/transport/binary/index.js +0 -1
  212. package/dist/esm/transport/index.js +1 -0
  213. package/dist/esm/transport/keepalive/WaKeepAlive.js +2 -8
  214. package/dist/esm/transport/node/WaNodeOrchestrator.js +25 -21
  215. package/dist/esm/transport/node/WaNodeTransport.js +0 -3
  216. package/dist/esm/transport/node/builders/{accountSync.js → account-sync.js} +16 -36
  217. package/dist/esm/transport/node/builders/business.js +129 -0
  218. package/dist/esm/transport/node/builders/global.js +370 -0
  219. package/dist/esm/transport/node/builders/index.js +7 -3
  220. package/dist/esm/transport/node/builders/message.js +63 -230
  221. package/dist/esm/transport/node/builders/pairing.js +2 -27
  222. package/dist/esm/transport/node/builders/privacy-token.js +41 -0
  223. package/dist/esm/transport/node/builders/privacy.js +48 -0
  224. package/dist/esm/transport/node/builders/profile.js +70 -0
  225. package/dist/esm/transport/node/builders/retry.js +10 -22
  226. package/dist/esm/transport/node/builders/usync.js +45 -0
  227. package/dist/esm/transport/node/helpers.js +125 -5
  228. package/dist/esm/transport/node/usync.js +5 -0
  229. package/dist/esm/transport/node/xml.js +35 -14
  230. package/dist/esm/transport/noise/WaClientPayload.js +10 -10
  231. package/dist/esm/transport/noise/WaFrameCodec.js +48 -33
  232. package/dist/esm/transport/noise/WaNoiseCert.js +4 -7
  233. package/dist/esm/transport/noise/WaNoiseSession.js +77 -29
  234. package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
  235. package/dist/esm/transport/proxy.js +27 -0
  236. package/dist/esm/transport/stream/parse.js +17 -48
  237. package/dist/esm/util/bytes.js +67 -45
  238. package/dist/esm/util/coercion.js +6 -14
  239. package/dist/esm/util/index.js +5 -0
  240. package/dist/esm/util/primitives.js +40 -14
  241. package/dist/index.js +7 -1
  242. package/dist/infra/log/ConsoleLogger.js +18 -17
  243. package/dist/infra/log/PinoLogger.js +15 -9
  244. package/dist/infra/log/types.js +12 -0
  245. package/dist/infra/perf/BackgroundQueue.js +482 -0
  246. package/dist/infra/perf/BoundedTaskQueue.js +16 -18
  247. package/dist/infra/perf/PromiseDedup.js +24 -0
  248. package/dist/infra/perf/SharedExclusiveGate.js +113 -0
  249. package/dist/infra/perf/StoreLock.js +81 -0
  250. package/dist/media/WaMediaCrypto.js +95 -15
  251. package/dist/media/WaMediaTransferClient.js +284 -91
  252. package/dist/media/conn.js +10 -6
  253. package/dist/media/constants.js +6 -2
  254. package/dist/message/WaMessageClient.js +31 -33
  255. package/dist/message/ack.js +6 -6
  256. package/dist/message/addon-crypto.js +65 -0
  257. package/dist/message/content.js +198 -9
  258. package/dist/message/icdc.js +81 -0
  259. package/dist/message/incoming.js +127 -120
  260. package/dist/message/index.js +2 -0
  261. package/dist/message/phash.js +3 -1
  262. package/dist/message/reporting-token.js +429 -0
  263. package/dist/message/use-case-secret.js +55 -0
  264. package/dist/protocol/appstate.js +28 -1
  265. package/dist/protocol/browser.js +10 -18
  266. package/dist/protocol/constants.js +26 -1
  267. package/dist/protocol/defaults.js +6 -0
  268. package/dist/protocol/index.js +23 -42
  269. package/dist/protocol/jid.js +140 -52
  270. package/dist/protocol/media.js +3 -3
  271. package/dist/protocol/message.js +62 -2
  272. package/dist/protocol/nodes.js +4 -0
  273. package/dist/protocol/notification.js +3 -1
  274. package/dist/protocol/privacy-token.js +20 -0
  275. package/dist/protocol/privacy.js +58 -0
  276. package/dist/protocol/stream.js +27 -2
  277. package/dist/protocol/usync.js +14 -0
  278. package/dist/retry/codec.js +220 -0
  279. package/dist/retry/constants.js +1 -1
  280. package/dist/retry/index.js +7 -5
  281. package/dist/retry/parse.js +88 -85
  282. package/dist/retry/replay.js +52 -49
  283. package/dist/retry/tracker.js +97 -0
  284. package/dist/signal/api/SignalDeviceSyncApi.js +273 -89
  285. package/dist/signal/api/SignalDigestSyncApi.js +17 -8
  286. package/dist/signal/api/SignalIdentitySyncApi.js +66 -36
  287. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +82 -63
  288. package/dist/signal/api/SignalRotateKeyApi.js +4 -2
  289. package/dist/signal/api/SignalSessionSyncApi.js +36 -34
  290. package/dist/signal/api/result-map.js +13 -0
  291. package/dist/signal/constants.js +1 -5
  292. package/dist/signal/crypto/WaAdvSignature.js +11 -7
  293. package/dist/signal/{store/sqlite.js → encoding.js} +94 -61
  294. package/dist/signal/group/SenderKeyChain.js +27 -22
  295. package/dist/signal/group/SenderKeyCodec.js +5 -6
  296. package/dist/signal/group/SenderKeyManager.js +144 -115
  297. package/dist/signal/index.js +15 -1
  298. package/dist/signal/registration/keygen.js +6 -2
  299. package/dist/signal/registration/utils.js +1 -0
  300. package/dist/signal/session/SignalProtocol.js +164 -53
  301. package/dist/signal/session/SignalRatchet.js +24 -15
  302. package/dist/signal/session/SignalSession.js +14 -9
  303. package/dist/signal/session/resolver.js +224 -0
  304. package/dist/store/contracts/privacy-token.store.js +2 -0
  305. package/dist/store/createStore.js +100 -188
  306. package/dist/store/index.js +15 -33
  307. package/dist/store/locks/appstate.lock.js +29 -0
  308. package/dist/store/locks/auth.lock.js +18 -0
  309. package/dist/store/locks/contact.lock.js +23 -0
  310. package/dist/store/locks/device-list.lock.js +23 -0
  311. package/dist/store/locks/message.lock.js +24 -0
  312. package/dist/store/locks/participants.lock.js +23 -0
  313. package/dist/store/locks/privacy-token.lock.js +21 -0
  314. package/dist/store/locks/retry.lock.js +32 -0
  315. package/dist/store/locks/sender-key.lock.js +55 -0
  316. package/dist/store/locks/signal.lock.js +66 -0
  317. package/dist/store/locks/thread.lock.js +24 -0
  318. package/dist/store/noop.store.js +4 -7
  319. package/dist/store/providers/memory/appstate.store.js +36 -14
  320. package/dist/store/providers/memory/contact.store.js +5 -0
  321. package/dist/store/providers/memory/device-list.store.js +12 -34
  322. package/dist/store/providers/memory/message.store.js +11 -5
  323. package/dist/store/providers/memory/participants.store.js +1 -8
  324. package/dist/store/providers/memory/privacy-token.store.js +47 -0
  325. package/dist/store/providers/memory/retry.store.js +77 -2
  326. package/dist/store/providers/memory/sender-key.store.js +14 -11
  327. package/dist/store/providers/memory/signal.store.js +54 -25
  328. package/dist/store/providers/memory/thread.store.js +5 -0
  329. package/dist/transport/WaComms.js +30 -26
  330. package/dist/transport/WaWebSocket.js +148 -18
  331. package/dist/transport/binary/constants.js +1 -31
  332. package/dist/transport/binary/decoder.js +8 -8
  333. package/dist/transport/binary/encoder.js +10 -9
  334. package/dist/transport/binary/index.js +0 -4
  335. package/dist/transport/index.js +7 -1
  336. package/dist/transport/keepalive/WaKeepAlive.js +1 -7
  337. package/dist/transport/node/WaNodeOrchestrator.js +25 -21
  338. package/dist/transport/node/WaNodeTransport.js +0 -3
  339. package/dist/transport/node/builders/{accountSync.js → account-sync.js} +15 -35
  340. package/dist/transport/node/builders/business.js +137 -0
  341. package/dist/transport/node/builders/global.js +375 -0
  342. package/dist/transport/node/builders/index.js +29 -17
  343. package/dist/transport/node/builders/message.js +64 -236
  344. package/dist/transport/node/builders/pairing.js +2 -29
  345. package/dist/transport/node/builders/privacy-token.js +46 -0
  346. package/dist/transport/node/builders/privacy.js +55 -0
  347. package/dist/transport/node/builders/profile.js +78 -0
  348. package/dist/transport/node/builders/retry.js +9 -21
  349. package/dist/transport/node/builders/usync.js +49 -0
  350. package/dist/transport/node/helpers.js +131 -4
  351. package/dist/transport/node/usync.js +8 -0
  352. package/dist/transport/node/xml.js +35 -14
  353. package/dist/transport/noise/WaClientPayload.js +13 -13
  354. package/dist/transport/noise/WaFrameCodec.js +47 -32
  355. package/dist/transport/noise/WaNoiseCert.js +5 -8
  356. package/dist/transport/noise/WaNoiseSession.js +77 -29
  357. package/dist/transport/noise/WaNoiseSocket.js +8 -4
  358. package/dist/transport/proxy.js +34 -0
  359. package/dist/transport/stream/parse.js +20 -52
  360. package/dist/types/appstate/WaAppStateCrypto.d.ts +0 -1
  361. package/dist/types/appstate/WaAppStateSyncClient.d.ts +5 -2
  362. package/dist/types/appstate/constants.d.ts +1 -0
  363. package/dist/types/appstate/encoding.d.ts +7 -0
  364. package/dist/types/appstate/index.d.ts +3 -3
  365. package/dist/types/appstate/utils.d.ts +0 -3
  366. package/dist/types/auth/WaAuthClient.d.ts +10 -12
  367. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +1 -1
  368. package/dist/types/auth/index.d.ts +0 -4
  369. package/dist/types/auth/pairing/WaQrFlow.d.ts +1 -1
  370. package/dist/types/auth/types.d.ts +7 -9
  371. package/dist/types/client/WaClient.d.ts +42 -25
  372. package/dist/types/client/WaClientFactory.d.ts +33 -26
  373. package/dist/types/client/connection/WaConnectionManager.d.ts +66 -0
  374. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +14 -0
  375. package/dist/types/client/connection/WaReceiptQueue.d.ts +13 -0
  376. package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +46 -0
  377. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
  378. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +3 -2
  379. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +29 -38
  380. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -0
  381. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
  382. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +36 -0
  383. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +8 -0
  384. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
  385. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +45 -0
  386. package/dist/types/client/dirty.d.ts +1 -0
  387. package/dist/types/client/events/devices.d.ts +20 -0
  388. package/dist/types/client/events/group.d.ts +2 -1
  389. package/dist/types/client/events/identity.d.ts +9 -0
  390. package/dist/types/client/events/privacy-token.d.ts +7 -0
  391. package/dist/types/client/history-sync.d.ts +9 -6
  392. package/dist/types/client/incoming.d.ts +3 -1
  393. package/dist/types/client/index.d.ts +1 -1
  394. package/dist/types/client/mailbox.d.ts +3 -5
  395. package/dist/types/client/messages.d.ts +1 -2
  396. package/dist/types/client/messaging/fanout.d.ts +14 -0
  397. package/dist/types/client/messaging/key-protocol.d.ts +18 -0
  398. package/dist/types/client/messaging/participants.d.ts +13 -0
  399. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
  400. package/dist/types/client/tokens/cs-token.d.ts +10 -0
  401. package/dist/types/client/tokens/tc-token.d.ts +5 -0
  402. package/dist/types/client/types.d.ts +75 -4
  403. package/dist/types/crypto/core/hkdf.d.ts +0 -6
  404. package/dist/types/crypto/core/index.d.ts +2 -3
  405. package/dist/types/crypto/core/nonce.d.ts +2 -0
  406. package/dist/types/crypto/core/primitives.d.ts +0 -1
  407. package/dist/types/crypto/core/random.d.ts +2 -7
  408. package/dist/types/crypto/index.d.ts +0 -1
  409. package/dist/types/crypto/math/constants.d.ts +4 -2
  410. package/dist/types/crypto/math/fe.d.ts +30 -0
  411. package/dist/types/crypto/math/mod.d.ts +0 -2
  412. package/dist/types/crypto/math/types.d.ts +11 -4
  413. package/dist/types/index.d.ts +5 -3
  414. package/dist/types/infra/log/ConsoleLogger.d.ts +2 -1
  415. package/dist/types/infra/log/PinoLogger.d.ts +1 -1
  416. package/dist/types/infra/log/types.d.ts +1 -0
  417. package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
  418. package/dist/types/infra/perf/BoundedTaskQueue.d.ts +1 -1
  419. package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
  420. package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
  421. package/dist/types/infra/perf/StoreLock.d.ts +10 -0
  422. package/dist/types/media/WaMediaCrypto.d.ts +3 -2
  423. package/dist/types/media/WaMediaTransferClient.d.ts +16 -15
  424. package/dist/types/media/constants.d.ts +1 -1
  425. package/dist/types/media/index.d.ts +1 -1
  426. package/dist/types/media/types.d.ts +15 -2
  427. package/dist/types/message/addon-crypto.d.ts +25 -0
  428. package/dist/types/message/content.d.ts +8 -0
  429. package/dist/types/message/icdc.d.ts +13 -0
  430. package/dist/types/message/index.d.ts +2 -0
  431. package/dist/types/message/reporting-token.d.ts +18 -0
  432. package/dist/types/message/types.d.ts +45 -6
  433. package/dist/types/message/use-case-secret.d.ts +20 -0
  434. package/dist/types/protocol/appstate.d.ts +47 -0
  435. package/dist/types/protocol/constants.d.ts +8 -3
  436. package/dist/types/protocol/defaults.d.ts +6 -0
  437. package/dist/types/protocol/index.d.ts +2 -11
  438. package/dist/types/protocol/jid.d.ts +22 -5
  439. package/dist/types/protocol/message.d.ts +60 -0
  440. package/dist/types/protocol/nodes.d.ts +4 -0
  441. package/dist/types/protocol/notification.d.ts +2 -0
  442. package/dist/types/protocol/privacy-token.d.ts +17 -0
  443. package/dist/types/protocol/privacy.d.ts +75 -0
  444. package/dist/types/protocol/stream.d.ts +30 -0
  445. package/dist/types/protocol/usync.d.ts +11 -0
  446. package/dist/types/retry/codec.d.ts +3 -0
  447. package/dist/types/retry/index.d.ts +4 -3
  448. package/dist/types/retry/parse.d.ts +5 -2
  449. package/dist/types/retry/replay.d.ts +0 -4
  450. package/dist/types/retry/tracker.d.ts +20 -0
  451. package/dist/types/retry/types.d.ts +10 -4
  452. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +15 -2
  453. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +6 -0
  454. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +2 -0
  455. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
  456. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
  457. package/dist/types/signal/api/result-map.d.ts +1 -0
  458. package/dist/types/signal/constants.d.ts +0 -3
  459. package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +3 -3
  460. package/dist/types/signal/group/SenderKeyCodec.d.ts +4 -6
  461. package/dist/types/signal/group/SenderKeyManager.d.ts +10 -5
  462. package/dist/types/signal/index.d.ts +3 -0
  463. package/dist/types/signal/session/SignalProtocol.d.ts +19 -4
  464. package/dist/types/signal/session/resolver.d.ts +22 -0
  465. package/dist/types/store/contracts/appstate.store.d.ts +4 -1
  466. package/dist/types/store/contracts/contact.store.d.ts +1 -0
  467. package/dist/types/store/contracts/device-list.store.d.ts +0 -3
  468. package/dist/types/store/contracts/message.store.d.ts +1 -0
  469. package/dist/types/store/contracts/participants.store.d.ts +0 -1
  470. package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
  471. package/dist/types/store/contracts/retry.store.d.ts +7 -0
  472. package/dist/types/store/contracts/sender-key.store.d.ts +0 -1
  473. package/dist/types/store/contracts/signal.store.d.ts +13 -0
  474. package/dist/types/store/contracts/thread.store.d.ts +1 -0
  475. package/dist/types/store/createStore.d.ts +1 -1
  476. package/dist/types/store/index.d.ts +5 -13
  477. package/dist/types/store/locks/appstate.lock.d.ts +3 -0
  478. package/dist/types/store/locks/auth.lock.d.ts +3 -0
  479. package/dist/types/store/locks/contact.lock.d.ts +3 -0
  480. package/dist/types/store/locks/device-list.lock.d.ts +2 -0
  481. package/dist/types/store/locks/message.lock.d.ts +3 -0
  482. package/dist/types/store/locks/participants.lock.d.ts +2 -0
  483. package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
  484. package/dist/types/store/locks/retry.lock.d.ts +2 -0
  485. package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
  486. package/dist/types/store/locks/signal.lock.d.ts +3 -0
  487. package/dist/types/store/locks/thread.lock.d.ts +3 -0
  488. package/dist/types/store/providers/memory/appstate.store.d.ts +3 -1
  489. package/dist/types/store/providers/memory/contact.store.d.ts +1 -0
  490. package/dist/types/store/providers/memory/device-list.store.d.ts +0 -3
  491. package/dist/types/store/providers/memory/message.store.d.ts +1 -0
  492. package/dist/types/store/providers/memory/participants.store.d.ts +0 -1
  493. package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
  494. package/dist/types/store/providers/memory/retry.store.d.ts +8 -0
  495. package/dist/types/store/providers/memory/sender-key.store.d.ts +0 -1
  496. package/dist/types/store/providers/memory/signal.store.d.ts +8 -1
  497. package/dist/types/store/providers/memory/thread.store.d.ts +1 -0
  498. package/dist/types/store/types.d.ts +49 -58
  499. package/dist/types/transport/WaWebSocket.d.ts +3 -1
  500. package/dist/types/transport/binary/constants.d.ts +0 -30
  501. package/dist/types/transport/binary/index.d.ts +0 -1
  502. package/dist/types/transport/index.d.ts +2 -1
  503. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +0 -1
  504. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +3 -4
  505. package/dist/types/transport/node/WaNodeTransport.d.ts +0 -9
  506. package/dist/types/transport/node/builders/business.d.ts +29 -0
  507. package/dist/types/transport/node/builders/global.d.ts +102 -0
  508. package/dist/types/transport/node/builders/group.d.ts +4 -6
  509. package/dist/types/transport/node/builders/index.d.ts +7 -3
  510. package/dist/types/transport/node/builders/message.d.ts +20 -30
  511. package/dist/types/transport/node/builders/pairing.d.ts +0 -2
  512. package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
  513. package/dist/types/transport/node/builders/privacy.d.ts +7 -0
  514. package/dist/types/transport/node/builders/profile.d.ts +8 -0
  515. package/dist/types/transport/node/builders/retry.d.ts +2 -5
  516. package/dist/types/transport/node/builders/usync.d.ts +21 -0
  517. package/dist/types/transport/node/helpers.d.ts +13 -0
  518. package/dist/types/transport/node/usync.d.ts +2 -0
  519. package/dist/types/transport/noise/WaFrameCodec.d.ts +3 -0
  520. package/dist/types/transport/noise/WaNoiseSession.d.ts +4 -2
  521. package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
  522. package/dist/types/transport/proxy.d.ts +6 -0
  523. package/dist/types/transport/stream/parse.d.ts +0 -1
  524. package/dist/types/transport/types.d.ts +18 -1
  525. package/dist/types/util/bytes.d.ts +5 -0
  526. package/dist/types/util/index.d.ts +5 -0
  527. package/dist/types/util/primitives.d.ts +2 -0
  528. package/dist/util/bytes.js +72 -46
  529. package/dist/util/coercion.js +6 -14
  530. package/dist/util/index.js +23 -0
  531. package/dist/util/primitives.js +42 -14
  532. package/package.json +52 -9
  533. package/proto/index.js +1 -1
  534. package/dist/crypto/core/constants.js +0 -4
  535. package/dist/crypto/core/encoding.js +0 -29
  536. package/dist/esm/crypto/core/constants.js +0 -1
  537. package/dist/esm/crypto/core/encoding.js +0 -25
  538. package/dist/esm/retry/outbound.js +0 -83
  539. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
  540. package/dist/esm/store/providers/sqlite/appstate.store.js +0 -169
  541. package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
  542. package/dist/esm/store/providers/sqlite/connection.js +0 -240
  543. package/dist/esm/store/providers/sqlite/contact.store.js +0 -61
  544. package/dist/esm/store/providers/sqlite/device-list.store.js +0 -155
  545. package/dist/esm/store/providers/sqlite/message.store.js +0 -119
  546. package/dist/esm/store/providers/sqlite/migrations.js +0 -347
  547. package/dist/esm/store/providers/sqlite/participants.store.js +0 -85
  548. package/dist/esm/store/providers/sqlite/retry.store.js +0 -144
  549. package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -203
  550. package/dist/esm/store/providers/sqlite/signal.store.js +0 -353
  551. package/dist/esm/store/providers/sqlite/thread.store.js +0 -72
  552. package/dist/esm/util/base64.js +0 -18
  553. package/dist/esm/util/signal-address.js +0 -5
  554. package/dist/retry/outbound.js +0 -88
  555. package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
  556. package/dist/store/providers/sqlite/appstate.store.js +0 -173
  557. package/dist/store/providers/sqlite/auth.store.js +0 -180
  558. package/dist/store/providers/sqlite/connection.js +0 -276
  559. package/dist/store/providers/sqlite/contact.store.js +0 -65
  560. package/dist/store/providers/sqlite/device-list.store.js +0 -159
  561. package/dist/store/providers/sqlite/message.store.js +0 -123
  562. package/dist/store/providers/sqlite/migrations.js +0 -350
  563. package/dist/store/providers/sqlite/participants.store.js +0 -89
  564. package/dist/store/providers/sqlite/retry.store.js +0 -148
  565. package/dist/store/providers/sqlite/sender-key.store.js +0 -207
  566. package/dist/store/providers/sqlite/signal.store.js +0 -357
  567. package/dist/store/providers/sqlite/thread.store.js +0 -76
  568. package/dist/types/appstate/store/sqlite.d.ts +0 -21
  569. package/dist/types/crypto/core/constants.d.ts +0 -1
  570. package/dist/types/crypto/core/encoding.d.ts +0 -11
  571. package/dist/types/retry/outbound.d.ts +0 -4
  572. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
  573. package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -15
  574. package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
  575. package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
  576. package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -10
  577. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -18
  578. package/dist/types/store/providers/sqlite/message.store.d.ts +0 -11
  579. package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
  580. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -13
  581. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -16
  582. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -25
  583. package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -46
  584. package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -11
  585. package/dist/types/util/base64.d.ts +0 -4
  586. package/dist/types/util/signal-address.d.ts +0 -2
  587. package/dist/util/base64.js +0 -24
  588. package/dist/util/signal-address.js +0 -8
  589. /package/dist/types/transport/node/builders/{accountSync.d.ts → account-sync.d.ts} +0 -0
@@ -0,0 +1,162 @@
1
+ import { CsTokenGenerator } from '../tokens/cs-token.js';
2
+ import { isTokenExpired, shouldSendNewToken, clampDuration } from '../tokens/tc-token.js';
3
+ import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
4
+ import { WA_PRIVACY_TOKEN_TYPES, WA_TC_TOKEN_DEFAULTS } from '../../protocol/privacy-token.js';
5
+ import { buildPrivacyTokenIqNode, buildTcTokenMessageNode, buildCsTokenMessageNode } from '../../transport/node/builders/privacy-token.js';
6
+ import { toError } from '../../util/primitives.js';
7
+ const NCT_SALT_SENTINEL_JID = '__nct_salt__';
8
+ export class WaTrustedContactTokenCoordinator {
9
+ constructor(options) {
10
+ this.logger = options.logger;
11
+ this.store = options.store;
12
+ this.runtime = options.runtime;
13
+ const maxDurationS = options.maxDurationS ?? WA_TC_TOKEN_DEFAULTS.MAX_DURATION_S;
14
+ this.config = {
15
+ durationS: clampDuration(options.durationS ?? WA_TC_TOKEN_DEFAULTS.DURATION_S, maxDurationS),
16
+ numBuckets: options.numBuckets ?? WA_TC_TOKEN_DEFAULTS.NUM_BUCKETS,
17
+ senderDurationS: clampDuration(options.senderDurationS ?? WA_TC_TOKEN_DEFAULTS.SENDER_DURATION_S, maxDurationS),
18
+ senderNumBuckets: options.senderNumBuckets ?? WA_TC_TOKEN_DEFAULTS.SENDER_NUM_BUCKETS,
19
+ maxDurationS
20
+ };
21
+ this.csTokenGenerator = new CsTokenGenerator();
22
+ this.senderTokenDedup = new PromiseDedup();
23
+ this.cachedNctSalt = null;
24
+ this.nctSaltHydrated = false;
25
+ }
26
+ async resolveTokenForMessage(recipientJid) {
27
+ const record = await this.store.getByJid(recipientJid);
28
+ const nowS = Math.floor(Date.now() / 1000);
29
+ if (record?.tcToken &&
30
+ record.tcTokenTimestamp !== undefined &&
31
+ !isTokenExpired(record.tcTokenTimestamp, nowS, this.config.durationS, this.config.numBuckets)) {
32
+ return buildTcTokenMessageNode(record.tcToken);
33
+ }
34
+ const nctSalt = await this.getNctSalt();
35
+ if (!nctSalt) {
36
+ return null;
37
+ }
38
+ const meLid = this.runtime.getCurrentMeLid();
39
+ if (!meLid) {
40
+ return null;
41
+ }
42
+ const hash = await this.csTokenGenerator.generate(nctSalt, meLid);
43
+ return buildCsTokenMessageNode(hash);
44
+ }
45
+ async handleIncomingToken(fromJid, tokens) {
46
+ const nowMs = Date.now();
47
+ for (let i = 0; i < tokens.length; i += 1) {
48
+ const token = tokens[i];
49
+ if (token.type !== WA_PRIVACY_TOKEN_TYPES.TRUSTED_CONTACT) {
50
+ this.logger.warn('ignoring unknown privacy token type', { type: token.type });
51
+ continue;
52
+ }
53
+ await this.store.upsert({
54
+ jid: fromJid,
55
+ tcToken: token.tokenBytes,
56
+ tcTokenTimestamp: token.timestampS,
57
+ updatedAtMs: nowMs
58
+ });
59
+ this.runtime.emitEvent('privacy_token_update', {
60
+ jid: fromJid,
61
+ timestampS: token.timestampS,
62
+ type: token.type,
63
+ source: 'notification'
64
+ });
65
+ }
66
+ }
67
+ async maybeIssueSenderToken(recipientJid) {
68
+ return this.senderTokenDedup.run(recipientJid, async () => {
69
+ const nowS = Math.floor(Date.now() / 1000);
70
+ const record = await this.store.getByJid(recipientJid);
71
+ const senderTimestampS = record?.tcTokenSenderTimestamp;
72
+ if (senderTimestampS !== undefined && senderTimestampS > 0) {
73
+ if (!shouldSendNewToken(senderTimestampS, nowS, this.config.senderDurationS)) {
74
+ return;
75
+ }
76
+ }
77
+ await this.issuePrivacyToken(recipientJid, nowS);
78
+ await this.store.upsert({
79
+ jid: recipientJid,
80
+ tcTokenSenderTimestamp: nowS,
81
+ updatedAtMs: Date.now()
82
+ });
83
+ });
84
+ }
85
+ async reissueOnIdentityChange(jid) {
86
+ const record = await this.store.getByJid(jid);
87
+ if (!record?.tcTokenSenderTimestamp) {
88
+ return;
89
+ }
90
+ const nowS = Math.floor(Date.now() / 1000);
91
+ if (isTokenExpired(record.tcTokenSenderTimestamp, nowS, this.config.senderDurationS, this.config.senderNumBuckets)) {
92
+ return;
93
+ }
94
+ try {
95
+ await this.issuePrivacyToken(jid, record.tcTokenSenderTimestamp);
96
+ }
97
+ catch (error) {
98
+ this.logger.warn('send-tc-token-device-identity-change-failed', {
99
+ jid,
100
+ message: toError(error).message
101
+ });
102
+ }
103
+ }
104
+ async hydrateFromHistorySync(conversations) {
105
+ const nowMs = Date.now();
106
+ const records = [];
107
+ for (let i = 0; i < conversations.length; i += 1) {
108
+ const conv = conversations[i];
109
+ if (!conv.tcToken && !conv.tcTokenTimestamp && !conv.tcTokenSenderTimestamp) {
110
+ continue;
111
+ }
112
+ records[records.length] = {
113
+ jid: conv.jid,
114
+ tcToken: conv.tcToken ?? undefined,
115
+ tcTokenTimestamp: conv.tcTokenTimestamp ?? undefined,
116
+ tcTokenSenderTimestamp: conv.tcTokenSenderTimestamp ?? undefined,
117
+ updatedAtMs: nowMs
118
+ };
119
+ }
120
+ if (records.length > 0) {
121
+ await this.store.upsertBatch(records);
122
+ }
123
+ }
124
+ async handleNctSaltSync(salt) {
125
+ if (salt) {
126
+ await this.store.upsert({
127
+ jid: NCT_SALT_SENTINEL_JID,
128
+ nctSalt: salt,
129
+ updatedAtMs: Date.now()
130
+ });
131
+ this.cachedNctSalt = salt;
132
+ }
133
+ else {
134
+ await this.store.deleteByJid(NCT_SALT_SENTINEL_JID);
135
+ this.cachedNctSalt = null;
136
+ }
137
+ this.nctSaltHydrated = true;
138
+ this.csTokenGenerator.invalidate();
139
+ }
140
+ async hydrateNctSaltFromHistorySync(salt) {
141
+ await this.store.upsert({
142
+ jid: NCT_SALT_SENTINEL_JID,
143
+ nctSalt: salt,
144
+ updatedAtMs: Date.now()
145
+ });
146
+ this.cachedNctSalt = salt;
147
+ this.nctSaltHydrated = true;
148
+ }
149
+ async getNctSalt() {
150
+ if (this.nctSaltHydrated) {
151
+ return this.cachedNctSalt;
152
+ }
153
+ const record = await this.store.getByJid(NCT_SALT_SENTINEL_JID);
154
+ this.cachedNctSalt = record?.nctSalt ?? null;
155
+ this.nctSaltHydrated = true;
156
+ return this.cachedNctSalt;
157
+ }
158
+ async issuePrivacyToken(jid, timestampS) {
159
+ const node = buildPrivacyTokenIqNode({ jid, timestampS });
160
+ await this.runtime.queryWithContext('issue-privacy-token', node);
161
+ }
162
+ }
@@ -1,10 +1,8 @@
1
- import { randomBytesAsync } from '../crypto/index.js';
2
1
  import { WA_ACCOUNT_SYNC_PROTOCOLS, WA_DEFAULTS, WA_DIRTY_PROTOCOLS, WA_DIRTY_TYPES, WA_IQ_TYPES, WA_SUPPORTED_DIRTY_TYPES } from '../protocol/constants.js';
3
2
  import { toUserJid } from '../protocol/jid.js';
4
- import { buildAccountBlocklistSyncIq, buildAccountDevicesSyncIq, buildAccountPictureSyncIq, buildAccountPrivacySyncIq, buildClearDirtyBitsIq, buildGroupsDirtySyncIq, buildNewsletterMetadataSyncIq } from '../transport/node/builders/accountSync.js';
5
- import { getNodeChildren } from '../transport/node/helpers.js';
3
+ import { buildAccountBlocklistSyncIq, buildAccountDevicesSyncIq, buildAccountPictureSyncIq, buildAccountPrivacySyncIq, buildClearDirtyBitsIq, buildGroupsDirtySyncIq, buildNewsletterMetadataSyncIq } from '../transport/node/builders/account-sync.js';
4
+ import { getNodeChildrenTags } from '../transport/node/helpers.js';
6
5
  import { assertIqResult, parseIqError } from '../transport/node/query.js';
7
- import { bytesToHex } from '../util/bytes.js';
8
6
  import { toError } from '../util/primitives.js';
9
7
  const SUPPORTED_DIRTY_TYPES = new Set(WA_SUPPORTED_DIRTY_TYPES);
10
8
  const ACCOUNT_SYNC_PROTOCOL_SET = new Set(WA_ACCOUNT_SYNC_PROTOCOLS);
@@ -18,30 +16,36 @@ function parseDirtyBitNode(node, logger) {
18
16
  });
19
17
  return null;
20
18
  }
21
- const protocols = getNodeChildren(node).map((child) => child.tag);
19
+ const protocols = getNodeChildrenTags(node);
22
20
  return {
23
21
  type,
24
22
  timestamp,
25
23
  protocols
26
24
  };
27
25
  }
28
- function splitDirtyBitsBySupport(dirtyBits) {
29
- return {
30
- supported: dirtyBits.filter((dirtyBit) => SUPPORTED_DIRTY_TYPES.has(dirtyBit.type)),
31
- unsupported: dirtyBits.filter((dirtyBit) => !SUPPORTED_DIRTY_TYPES.has(dirtyBit.type))
32
- };
33
- }
34
26
  function resolveAccountSyncProtocols(protocols) {
35
- const selected = protocols.filter((protocol) => ACCOUNT_SYNC_PROTOCOL_SET.has(protocol));
27
+ const selected = [];
28
+ for (let index = 0; index < protocols.length; index += 1) {
29
+ const protocol = protocols[index];
30
+ if (ACCOUNT_SYNC_PROTOCOL_SET.has(protocol)) {
31
+ selected.push(protocol);
32
+ }
33
+ }
36
34
  if (selected.length > 0) {
37
35
  return selected;
38
36
  }
39
37
  return WA_ACCOUNT_SYNC_PROTOCOLS;
40
38
  }
41
39
  export function parseDirtyBits(nodes, logger) {
42
- return nodes
43
- .map((node) => parseDirtyBitNode(node, logger))
44
- .filter((dirtyBit) => dirtyBit !== null);
40
+ const parsed = [];
41
+ for (const node of nodes) {
42
+ const dirtyBit = parseDirtyBitNode(node, logger);
43
+ if (!dirtyBit) {
44
+ continue;
45
+ }
46
+ parsed.push(dirtyBit);
47
+ }
48
+ return parsed;
45
49
  }
46
50
  export async function handleDirtyBits(runtime, dirtyBits) {
47
51
  const meJid = runtime.getCurrentCredentials()?.meJid ?? null;
@@ -49,22 +53,45 @@ export async function handleDirtyBits(runtime, dirtyBits) {
49
53
  runtime.logger.trace('dirty bits skipped: session is not registered');
50
54
  return;
51
55
  }
52
- const { supported, unsupported } = splitDirtyBitsBySupport(dirtyBits);
56
+ const supported = [];
57
+ const unsupported = [];
58
+ for (const dirtyBit of dirtyBits) {
59
+ if (SUPPORTED_DIRTY_TYPES.has(dirtyBit.type)) {
60
+ supported.push(dirtyBit);
61
+ continue;
62
+ }
63
+ unsupported.push(dirtyBit);
64
+ }
65
+ const supportedTypes = new Array(supported.length);
66
+ for (let index = 0; index < supported.length; index += 1) {
67
+ supportedTypes[index] = supported[index].type;
68
+ }
69
+ const unsupportedTypes = new Array(unsupported.length);
70
+ for (let index = 0; index < unsupported.length; index += 1) {
71
+ unsupportedTypes[index] = unsupported[index].type;
72
+ }
53
73
  runtime.logger.info('handling dirty bits from info bulletin', {
54
- supported: supported.map((entry) => entry.type).join(','),
55
- unsupported: unsupported.map((entry) => entry.type).join(',')
74
+ supported: supportedTypes.join(','),
75
+ unsupported: unsupportedTypes.join(',')
56
76
  });
57
- const handledSupported = (await Promise.allSettled(supported.map(async (dirtyBit) => handleDirtyBit(runtime, dirtyBit)))).flatMap((result, index) => {
77
+ const clearableDirtyBits = [...unsupported];
78
+ const supportedPromises = new Array(supported.length);
79
+ for (let index = 0; index < supported.length; index += 1) {
80
+ supportedPromises[index] = handleDirtyBit(runtime, supported[index]);
81
+ }
82
+ const settledSupported = await Promise.allSettled(supportedPromises);
83
+ for (let index = 0; index < settledSupported.length; index += 1) {
84
+ const result = settledSupported[index];
58
85
  if (result.status === 'fulfilled') {
59
- return [supported[index]];
86
+ clearableDirtyBits.push(supported[index]);
87
+ continue;
60
88
  }
61
89
  runtime.logger.warn('failed handling dirty bit', {
62
90
  type: supported[index].type,
63
91
  message: toError(result.reason).message
64
92
  });
65
- return [];
66
- });
67
- await clearDirtyBits(runtime, unsupported.concat(handledSupported));
93
+ }
94
+ await clearDirtyBits(runtime, clearableDirtyBits);
68
95
  }
69
96
  async function handleDirtyBit(runtime, dirtyBit) {
70
97
  switch (dirtyBit.type) {
@@ -92,18 +119,23 @@ async function handleAccountSyncDirtyBit(runtime, protocols) {
92
119
  protocols: selectedProtocols.join(',')
93
120
  });
94
121
  const failures = [];
95
- await Promise.all(selectedProtocols.map(async (protocol) => {
96
- try {
97
- await runAccountSyncProtocol(runtime, protocol);
98
- }
99
- catch (error) {
100
- failures.push(protocol);
101
- runtime.logger.warn('account_sync protocol failed', {
102
- protocol,
103
- message: toError(error).message
104
- });
105
- }
106
- }));
122
+ const protocolPromises = new Array(selectedProtocols.length);
123
+ for (let index = 0; index < selectedProtocols.length; index += 1) {
124
+ const protocol = selectedProtocols[index];
125
+ protocolPromises[index] = (async () => {
126
+ try {
127
+ await runAccountSyncProtocol(runtime, protocol);
128
+ }
129
+ catch (error) {
130
+ failures.push(protocol);
131
+ runtime.logger.warn('account_sync protocol failed', {
132
+ protocol,
133
+ message: toError(error).message
134
+ });
135
+ }
136
+ })();
137
+ }
138
+ await Promise.all(protocolPromises);
107
139
  if (failures.length > 0) {
108
140
  throw new Error(`account_sync protocols failed: ${failures.join(',')}`);
109
141
  }
@@ -123,7 +155,7 @@ async function runAccountSyncProtocol(runtime, protocol) {
123
155
  await syncAccountBlocklistDirtyBit(runtime);
124
156
  return;
125
157
  case WA_DIRTY_PROTOCOLS.NOTICE:
126
- await syncAccountNoticeDirtyBit(runtime);
158
+ runtime.logger.info('account_sync notice protocol received (no GraphQL/MEX job configured)');
127
159
  return;
128
160
  default:
129
161
  runtime.logger.debug('unsupported account_sync protocol', {
@@ -149,7 +181,7 @@ async function syncAccountDevicesDirtyBit(runtime) {
149
181
  }
150
182
  await runSyncQuery(runtime, {
151
183
  queryContext: 'account_sync.devices',
152
- node: buildAccountDevicesSyncIq(userJids, await generateUsyncSid()),
184
+ node: buildAccountDevicesSyncIq(userJids, await runtime.generateUsyncSid()),
153
185
  logMessage: 'account_sync devices synchronized',
154
186
  contextData: { meJid, targets: userJids.join(',') }
155
187
  });
@@ -198,9 +230,6 @@ async function syncAccountBlocklistDirtyBit(runtime) {
198
230
  logMessage: 'account_sync blocklist synchronized'
199
231
  });
200
232
  }
201
- async function syncAccountNoticeDirtyBit(runtime) {
202
- runtime.logger.info('account_sync notice protocol received (no GraphQL/MEX job configured)');
203
- }
204
233
  async function syncGroupsDirtyBit(runtime) {
205
234
  await runSyncQuery(runtime, {
206
235
  queryContext: 'dirty.groups',
@@ -213,9 +242,6 @@ async function syncNewsletterMetadataDirtyBit(runtime) {
213
242
  runtime.logger.info('newsletter_metadata dirty bit received (GraphQL/MEX sync intentionally disabled)');
214
243
  await runtime.queryWithContext('dirty.newsletter_metadata', buildNewsletterMetadataSyncIq(), WA_DEFAULTS.IQ_TIMEOUT_MS);
215
244
  }
216
- async function generateUsyncSid() {
217
- return bytesToHex(await randomBytesAsync(8));
218
- }
219
245
  function resolveAccountSyncDeviceTargets(credentials) {
220
246
  if (!credentials?.meJid) {
221
247
  return [];
@@ -75,8 +75,7 @@ export function parseChatEventFromAppStateMutation(mutation) {
75
75
  ...pickOptionalPrimitive('deviceAgentId', value.chatAssignment.deviceAgentID, 'string')
76
76
  };
77
77
  }
78
- const fallbackAction = normalizeIndexAction(parsedIndex?.action) ??
79
- normalizeValueActionKey(syncActionValueKey);
78
+ const fallbackAction = normalizeIndexAction(parsedIndex?.action) ?? normalizeValueActionKey(syncActionValueKey);
80
79
  if (!fallbackAction) {
81
80
  return null;
82
81
  }
@@ -201,10 +200,12 @@ function extractChatJid(parts) {
201
200
  return undefined;
202
201
  }
203
202
  function findPresentSyncActionValueKey(value) {
204
- for (const [key, keyValue] of Object.entries(value)) {
203
+ const valueRecord = value;
204
+ for (const key in valueRecord) {
205
205
  if (key === 'timestamp') {
206
206
  continue;
207
207
  }
208
+ const keyValue = valueRecord[key];
208
209
  if (keyValue === null || keyValue === undefined) {
209
210
  continue;
210
211
  }
@@ -0,0 +1,68 @@
1
+ import { parseSignalAddressFromJid } from '../../protocol/jid.js';
2
+ import { findNodeChild, getNodeChildrenByTag } from '../../transport/node/helpers.js';
3
+ export const DEVICE_NOTIFICATION_ACTIONS = Object.freeze({
4
+ ADD: 'add',
5
+ REMOVE: 'remove',
6
+ UPDATE: 'update'
7
+ });
8
+ export function parseDeviceNotification(node) {
9
+ const stanzaId = node.attrs.id;
10
+ const fromJid = node.attrs.from;
11
+ if (!stanzaId || !fromJid) {
12
+ return null;
13
+ }
14
+ let action;
15
+ let actionNode;
16
+ if (findNodeChild(node, DEVICE_NOTIFICATION_ACTIONS.REMOVE)) {
17
+ action = DEVICE_NOTIFICATION_ACTIONS.REMOVE;
18
+ actionNode = findNodeChild(node, DEVICE_NOTIFICATION_ACTIONS.REMOVE);
19
+ }
20
+ else if (findNodeChild(node, DEVICE_NOTIFICATION_ACTIONS.ADD)) {
21
+ action = DEVICE_NOTIFICATION_ACTIONS.ADD;
22
+ actionNode = findNodeChild(node, DEVICE_NOTIFICATION_ACTIONS.ADD);
23
+ }
24
+ else if (findNodeChild(node, DEVICE_NOTIFICATION_ACTIONS.UPDATE)) {
25
+ action = DEVICE_NOTIFICATION_ACTIONS.UPDATE;
26
+ actionNode = findNodeChild(node, DEVICE_NOTIFICATION_ACTIONS.UPDATE);
27
+ }
28
+ else {
29
+ return null;
30
+ }
31
+ const devices = [];
32
+ if (action !== DEVICE_NOTIFICATION_ACTIONS.UPDATE && actionNode) {
33
+ const deviceNodes = getNodeChildrenByTag(actionNode, 'device');
34
+ for (let index = 0; index < deviceNodes.length; index += 1) {
35
+ const deviceNode = deviceNodes[index];
36
+ const jidAttr = deviceNode.attrs.jid;
37
+ if (!jidAttr) {
38
+ continue;
39
+ }
40
+ let deviceId;
41
+ try {
42
+ deviceId = parseSignalAddressFromJid(jidAttr).device;
43
+ }
44
+ catch {
45
+ continue;
46
+ }
47
+ const keyIndexAttr = deviceNode.attrs['key-index'];
48
+ const parsedKeyIndex = keyIndexAttr === undefined ? null : Number.parseInt(keyIndexAttr, 10);
49
+ const keyIndex = parsedKeyIndex !== null &&
50
+ Number.isSafeInteger(parsedKeyIndex) &&
51
+ parsedKeyIndex >= 0
52
+ ? parsedKeyIndex
53
+ : null;
54
+ devices[devices.length] = {
55
+ deviceId,
56
+ keyIndex
57
+ };
58
+ }
59
+ }
60
+ return {
61
+ action,
62
+ stanzaId,
63
+ fromJid,
64
+ lid: node.attrs.lid,
65
+ hash: action === DEVICE_NOTIFICATION_ACTIONS.UPDATE ? actionNode?.attrs.hash : undefined,
66
+ devices
67
+ };
68
+ }
@@ -1,8 +1,9 @@
1
+ import { createUnhandledIncomingNodeEvent } from '../incoming.js';
1
2
  import { WA_GROUP_NOTIFICATION_TAGS, WA_NOTIFICATION_TYPES } from '../../protocol/constants.js';
2
3
  import { WA_NODE_TAGS } from '../../protocol/nodes.js';
3
4
  import { findNodeChild, getNodeChildren, getNodeChildrenByTag } from '../../transport/node/helpers.js';
4
- import { parseOptionalInt } from '../../transport/stream/parse.js';
5
5
  import { TEXT_DECODER } from '../../util/bytes.js';
6
+ import { parseOptionalInt } from '../../util/primitives.js';
6
7
  function readNodeTextContent(node) {
7
8
  if (!node) {
8
9
  return undefined;
@@ -15,31 +16,43 @@ function readNodeTextContent(node) {
15
16
  }
16
17
  return undefined;
17
18
  }
18
- function parseParticipants(node) {
19
- return getNodeChildrenByTag(node, WA_NODE_TAGS.PARTICIPANT).map((participantNode) => ({
20
- jid: participantNode.attrs.jid,
21
- role: participantNode.attrs.type,
22
- lidJid: participantNode.attrs.lid,
23
- phoneJid: participantNode.attrs.phone_number,
24
- displayName: participantNode.attrs.display_name,
25
- username: participantNode.attrs.username,
26
- expirationSeconds: parseOptionalInt(participantNode.attrs.expiration)
27
- }));
19
+ export function parseParticipants(node) {
20
+ const participants = [];
21
+ for (const participantNode of getNodeChildrenByTag(node, WA_NODE_TAGS.PARTICIPANT)) {
22
+ participants.push({
23
+ jid: participantNode.attrs.jid,
24
+ role: participantNode.attrs.type,
25
+ lidJid: participantNode.attrs.lid,
26
+ phoneJid: participantNode.attrs.phone_number,
27
+ displayName: participantNode.attrs.display_name,
28
+ username: participantNode.attrs.username,
29
+ expirationSeconds: parseOptionalInt(participantNode.attrs.expiration)
30
+ });
31
+ }
32
+ return participants;
28
33
  }
29
34
  function parseLinkedGroups(node) {
30
- return getNodeChildrenByTag(node, WA_NODE_TAGS.GROUP).map((groupNode) => ({
31
- jid: groupNode.attrs.jid,
32
- subject: groupNode.attrs.subject,
33
- subjectTimestampSeconds: parseOptionalInt(groupNode.attrs.s_t),
34
- hiddenSubgroup: findNodeChild(groupNode, 'hidden_group') !== undefined
35
- }));
35
+ const groups = [];
36
+ for (const groupNode of getNodeChildrenByTag(node, WA_NODE_TAGS.GROUP)) {
37
+ groups.push({
38
+ jid: groupNode.attrs.jid,
39
+ subject: groupNode.attrs.subject,
40
+ subjectTimestampSeconds: parseOptionalInt(groupNode.attrs.s_t),
41
+ hiddenSubgroup: findNodeChild(groupNode, 'hidden_group') !== undefined
42
+ });
43
+ }
44
+ return groups;
36
45
  }
37
46
  function parseMembershipRequests(node) {
38
- return getNodeChildrenByTag(node, 'requested_user').map((requestNode) => ({
39
- jid: requestNode.attrs.jid,
40
- username: requestNode.attrs.username,
41
- phoneJid: requestNode.attrs.phone_number
42
- }));
47
+ const requests = [];
48
+ for (const requestNode of getNodeChildrenByTag(node, 'requested_user')) {
49
+ requests.push({
50
+ jid: requestNode.attrs.jid,
51
+ username: requestNode.attrs.username,
52
+ phoneJid: requestNode.attrs.phone_number
53
+ });
54
+ }
55
+ return requests;
43
56
  }
44
57
  function parseSubgroupSuggestion(node) {
45
58
  const subjectNode = findNodeChild(node, WA_NODE_TAGS.SUBJECT);
@@ -65,9 +78,15 @@ function parseSubgroupSuggestion(node) {
65
78
  };
66
79
  }
67
80
  function parseSubgroupSuggestions(node) {
68
- return getNodeChildrenByTag(node, 'sub_group_suggestion')
69
- .map(parseSubgroupSuggestion)
70
- .filter((suggestion) => suggestion !== null);
81
+ const suggestions = [];
82
+ for (const suggestionNode of getNodeChildrenByTag(node, 'sub_group_suggestion')) {
83
+ const suggestion = parseSubgroupSuggestion(suggestionNode);
84
+ if (!suggestion) {
85
+ continue;
86
+ }
87
+ suggestions.push(suggestion);
88
+ }
89
+ return suggestions;
71
90
  }
72
91
  function createBaseGroupEvent(notificationNode, actionNode) {
73
92
  return {
@@ -81,15 +100,6 @@ function createBaseGroupEvent(notificationNode, actionNode) {
81
100
  timestampSeconds: parseOptionalInt(notificationNode.attrs.t)
82
101
  };
83
102
  }
84
- function createUnhandledStanzaEvent(notificationNode, reason) {
85
- return {
86
- rawNode: notificationNode,
87
- stanzaId: notificationNode.attrs.id,
88
- chatJid: notificationNode.attrs.from,
89
- stanzaType: notificationNode.attrs.type,
90
- reason
91
- };
92
- }
93
103
  function parseCreateGroupAction(notificationNode, actionNode) {
94
104
  const groupNode = findNodeChild(actionNode, WA_NODE_TAGS.GROUP);
95
105
  if (!groupNode) {
@@ -136,8 +146,7 @@ function parseCreateGroupAction(notificationNode, actionNode) {
136
146
  ephemeralDuration: parseOptionalInt(findNodeChild(groupNode, WA_NODE_TAGS.EPHEMERAL)?.attrs.expiration),
137
147
  disappearingTrigger: findNodeChild(groupNode, WA_NODE_TAGS.EPHEMERAL)?.attrs.trigger,
138
148
  membershipApprovalEnabled: groupJoinNode?.attrs.state === 'on',
139
- allowNonAdminSubGroupCreation: findNodeChild(groupNode, WA_GROUP_NOTIFICATION_TAGS.ALLOW_NON_ADMIN_SUB_GROUP_CREATION) !==
140
- undefined,
149
+ allowNonAdminSubGroupCreation: findNodeChild(groupNode, WA_GROUP_NOTIFICATION_TAGS.ALLOW_NON_ADMIN_SUB_GROUP_CREATION) !== undefined,
141
150
  linkedParentGroupJid: findNodeChild(groupNode, 'linked_parent')?.attrs.jid ??
142
151
  findNodeChild(groupNode, 'parent')?.attrs.jid
143
152
  }
@@ -224,7 +233,12 @@ function parseGroupActionNode(notificationNode, actionNode) {
224
233
  };
225
234
  }
226
235
  case WA_GROUP_NOTIFICATION_TAGS.LOCKED:
227
- return { ...baseEvent, action: 'restrict', enabled: true, mode: actionNode.attrs.threshold };
236
+ return {
237
+ ...baseEvent,
238
+ action: 'restrict',
239
+ enabled: true,
240
+ mode: actionNode.attrs.threshold
241
+ };
228
242
  case WA_GROUP_NOTIFICATION_TAGS.UNLOCKED:
229
243
  return { ...baseEvent, action: 'restrict', enabled: false };
230
244
  case WA_GROUP_NOTIFICATION_TAGS.ANNOUNCEMENT:
@@ -391,13 +405,13 @@ export function parseGroupNotificationEvents(notificationNode) {
391
405
  try {
392
406
  const parsedEvent = parseGroupActionNode(notificationNode, actionNode);
393
407
  if (!parsedEvent) {
394
- unhandled.push(createUnhandledStanzaEvent(notificationNode, `notification.${WA_NOTIFICATION_TYPES.GROUP}.${actionNode.tag}.not_supported`));
408
+ unhandled.push(createUnhandledIncomingNodeEvent(notificationNode, `notification.${WA_NOTIFICATION_TYPES.GROUP}.${actionNode.tag}.not_supported`));
395
409
  continue;
396
410
  }
397
411
  events.push(parsedEvent);
398
412
  }
399
413
  catch {
400
- unhandled.push(createUnhandledStanzaEvent(notificationNode, `notification.${WA_NOTIFICATION_TYPES.GROUP}.${actionNode.tag}.parse_failed`));
414
+ unhandled.push(createUnhandledIncomingNodeEvent(notificationNode, `notification.${WA_NOTIFICATION_TYPES.GROUP}.${actionNode.tag}.parse_failed`));
401
415
  }
402
416
  }
403
417
  return {
@@ -0,0 +1,19 @@
1
+ import { getFirstNodeChild } from '../../transport/node/helpers.js';
2
+ export function parseIdentityChangeNotification(node) {
3
+ const child = getFirstNodeChild(node);
4
+ if (!child || child.tag !== 'identity') {
5
+ return null;
6
+ }
7
+ const fromJid = node.attrs.from;
8
+ const stanzaId = node.attrs.id;
9
+ if (!fromJid || !stanzaId) {
10
+ return null;
11
+ }
12
+ return {
13
+ fromJid,
14
+ stanzaId,
15
+ displayName: node.attrs.display_name,
16
+ lid: node.attrs.lid,
17
+ offline: node.attrs.offline
18
+ };
19
+ }
@@ -0,0 +1,36 @@
1
+ import { WA_PRIVACY_TOKEN_TAGS } from '../../protocol/privacy-token.js';
2
+ import { findNodeChild, getNodeChildren } from '../../transport/node/helpers.js';
3
+ import { toBytesView } from '../../util/bytes.js';
4
+ import { asNumber } from '../../util/coercion.js';
5
+ export function parsePrivacyTokenNotification(node) {
6
+ const tokensNode = findNodeChild(node, WA_PRIVACY_TOKEN_TAGS.TOKENS);
7
+ if (!tokensNode) {
8
+ return [];
9
+ }
10
+ const children = getNodeChildren(tokensNode);
11
+ const result = [];
12
+ for (let i = 0; i < children.length; i += 1) {
13
+ const child = children[i];
14
+ if (child.tag !== WA_PRIVACY_TOKEN_TAGS.TOKEN) {
15
+ continue;
16
+ }
17
+ const type = child.attrs.type;
18
+ if (!type) {
19
+ continue;
20
+ }
21
+ const rawTimestamp = child.attrs.t;
22
+ if (!rawTimestamp) {
23
+ continue;
24
+ }
25
+ const content = child.content;
26
+ if (!(content instanceof Uint8Array)) {
27
+ continue;
28
+ }
29
+ result[result.length] = {
30
+ type,
31
+ tokenBytes: toBytesView(content),
32
+ timestampS: asNumber(Number(rawTimestamp), 'privacy_token.t')
33
+ };
34
+ }
35
+ return result;
36
+ }