zapo-js 0.1.2 → 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 (468) hide show
  1. package/README.md +12 -4
  2. package/dist/appstate/WaAppStateCrypto.js +1 -1
  3. package/dist/appstate/WaAppStateSyncClient.js +138 -93
  4. package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
  5. package/dist/appstate/index.js +8 -6
  6. package/dist/appstate/utils.js +0 -5
  7. package/dist/auth/WaAuthClient.js +36 -47
  8. package/dist/auth/flow/WaAuthCredentialsFlow.js +7 -7
  9. package/dist/auth/index.js +1 -6
  10. package/dist/auth/pairing/WaPairingCodeCrypto.js +6 -4
  11. package/dist/auth/pairing/WaPairingFlow.js +13 -3
  12. package/dist/client/WaClient.js +225 -101
  13. package/dist/client/WaClientFactory.js +294 -44
  14. package/dist/client/connection/WaConnectionManager.js +19 -10
  15. package/dist/client/coordinators/WaBusinessCoordinator.js +241 -0
  16. package/dist/client/coordinators/WaGroupCoordinator.js +11 -7
  17. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +1 -0
  18. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +292 -99
  19. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  20. package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
  21. package/dist/client/coordinators/WaProfileCoordinator.js +212 -0
  22. package/dist/client/coordinators/WaRetryCoordinator.js +179 -27
  23. package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
  24. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +166 -0
  25. package/dist/client/dirty.js +40 -20
  26. package/dist/client/events/devices.js +72 -0
  27. package/dist/client/events/group.js +3 -11
  28. package/dist/client/events/identity.js +22 -0
  29. package/dist/client/events/privacy-token.js +39 -0
  30. package/dist/client/history-sync.js +50 -9
  31. package/dist/client/incoming.js +37 -7
  32. package/dist/client/mailbox.js +24 -23
  33. package/dist/client/messages.js +107 -31
  34. package/dist/client/messaging/fanout.js +21 -11
  35. package/dist/client/messaging/participants.js +6 -4
  36. package/dist/client/persistence/WriteBehindPersistence.js +129 -0
  37. package/dist/client/tokens/cs-token.js +50 -0
  38. package/dist/client/tokens/tc-token.js +25 -0
  39. package/dist/crypto/core/index.js +2 -2
  40. package/dist/crypto/core/keys.js +4 -4
  41. package/dist/crypto/core/nonce.js +2 -0
  42. package/dist/crypto/core/primitives.js +0 -8
  43. package/dist/crypto/core/random.js +22 -0
  44. package/dist/crypto/curves/X25519.js +25 -6
  45. package/dist/crypto/index.js +3 -0
  46. package/dist/crypto/math/constants.js +13 -36
  47. package/dist/crypto/math/edwards.js +171 -44
  48. package/dist/crypto/math/fe.js +706 -0
  49. package/dist/crypto/math/mod.js +10 -3
  50. package/dist/esm/appstate/WaAppStateCrypto.js +1 -1
  51. package/dist/esm/appstate/WaAppStateSyncClient.js +138 -93
  52. package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
  53. package/dist/esm/appstate/index.js +2 -2
  54. package/dist/esm/appstate/utils.js +2 -5
  55. package/dist/esm/auth/WaAuthClient.js +36 -47
  56. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +7 -7
  57. package/dist/esm/auth/index.js +0 -2
  58. package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +6 -4
  59. package/dist/esm/auth/pairing/WaPairingFlow.js +14 -4
  60. package/dist/esm/client/WaClient.js +225 -101
  61. package/dist/esm/client/WaClientFactory.js +295 -45
  62. package/dist/esm/client/connection/WaConnectionManager.js +19 -10
  63. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +238 -0
  64. package/dist/esm/client/coordinators/WaGroupCoordinator.js +11 -7
  65. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +1 -0
  66. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +295 -102
  67. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  68. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
  69. package/dist/esm/client/coordinators/WaProfileCoordinator.js +209 -0
  70. package/dist/esm/client/coordinators/WaRetryCoordinator.js +181 -29
  71. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
  72. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +162 -0
  73. package/dist/esm/client/dirty.js +40 -20
  74. package/dist/esm/client/events/devices.js +68 -0
  75. package/dist/esm/client/events/group.js +3 -11
  76. package/dist/esm/client/events/identity.js +19 -0
  77. package/dist/esm/client/events/privacy-token.js +36 -0
  78. package/dist/esm/client/history-sync.js +50 -9
  79. package/dist/esm/client/incoming.js +38 -8
  80. package/dist/esm/client/mailbox.js +24 -23
  81. package/dist/esm/client/messages.js +108 -32
  82. package/dist/esm/client/messaging/fanout.js +22 -12
  83. package/dist/esm/client/messaging/participants.js +6 -4
  84. package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
  85. package/dist/esm/client/tokens/cs-token.js +46 -0
  86. package/dist/esm/client/tokens/tc-token.js +18 -0
  87. package/dist/esm/crypto/core/index.js +2 -2
  88. package/dist/esm/crypto/core/keys.js +1 -1
  89. package/dist/esm/crypto/core/nonce.js +2 -0
  90. package/dist/esm/crypto/core/primitives.js +0 -7
  91. package/dist/esm/crypto/core/random.js +22 -1
  92. package/dist/esm/crypto/curves/X25519.js +25 -6
  93. package/dist/esm/crypto/index.js +1 -0
  94. package/dist/esm/crypto/math/constants.js +12 -35
  95. package/dist/esm/crypto/math/edwards.js +174 -47
  96. package/dist/esm/crypto/math/fe.js +691 -0
  97. package/dist/esm/crypto/math/mod.js +10 -1
  98. package/dist/esm/index.js +1 -1
  99. package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
  100. package/dist/esm/infra/perf/BoundedTaskQueue.js +3 -1
  101. package/dist/esm/infra/perf/PromiseDedup.js +20 -0
  102. package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
  103. package/dist/esm/infra/perf/StoreLock.js +77 -0
  104. package/dist/esm/media/WaMediaCrypto.js +95 -13
  105. package/dist/esm/media/WaMediaTransferClient.js +39 -47
  106. package/dist/esm/media/constants.js +2 -1
  107. package/dist/esm/message/WaMessageClient.js +26 -19
  108. package/dist/esm/message/content.js +195 -9
  109. package/dist/esm/message/icdc.js +76 -0
  110. package/dist/esm/message/incoming.js +24 -12
  111. package/dist/esm/message/phash.js +3 -1
  112. package/dist/esm/message/reporting-token.js +14 -27
  113. package/dist/esm/protocol/appstate.js +9 -40
  114. package/dist/esm/protocol/browser.js +10 -18
  115. package/dist/esm/protocol/constants.js +5 -3
  116. package/dist/esm/protocol/defaults.js +6 -0
  117. package/dist/esm/protocol/index.js +1 -2
  118. package/dist/esm/protocol/jid.js +105 -36
  119. package/dist/esm/protocol/message.js +61 -1
  120. package/dist/esm/protocol/nodes.js +2 -0
  121. package/dist/esm/protocol/notification.js +3 -1
  122. package/dist/esm/protocol/privacy-token.js +17 -0
  123. package/dist/esm/protocol/privacy.js +55 -0
  124. package/dist/esm/protocol/stream.js +26 -1
  125. package/dist/esm/retry/codec.js +216 -0
  126. package/dist/esm/retry/constants.js +1 -1
  127. package/dist/esm/retry/index.js +2 -2
  128. package/dist/esm/retry/parse.js +50 -30
  129. package/dist/esm/retry/replay.js +11 -7
  130. package/dist/esm/retry/tracker.js +50 -12
  131. package/dist/esm/signal/api/SignalDeviceSyncApi.js +49 -32
  132. package/dist/esm/signal/api/SignalDigestSyncApi.js +13 -9
  133. package/dist/esm/signal/api/SignalIdentitySyncApi.js +26 -11
  134. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +18 -7
  135. package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
  136. package/dist/esm/signal/api/SignalSessionSyncApi.js +16 -7
  137. package/dist/esm/signal/api/result-map.js +10 -0
  138. package/dist/esm/signal/constants.js +0 -4
  139. package/dist/esm/signal/crypto/WaAdvSignature.js +12 -6
  140. package/dist/esm/signal/{store/sqlite.js → encoding.js} +78 -24
  141. package/dist/esm/signal/group/SenderKeyCodec.js +3 -2
  142. package/dist/esm/signal/group/SenderKeyManager.js +125 -106
  143. package/dist/esm/signal/index.js +1 -0
  144. package/dist/esm/signal/registration/keygen.js +6 -2
  145. package/dist/esm/signal/registration/utils.js +1 -0
  146. package/dist/esm/signal/session/SignalProtocol.js +150 -74
  147. package/dist/esm/signal/session/resolver.js +137 -102
  148. package/dist/esm/store/contracts/privacy-token.store.js +1 -0
  149. package/dist/esm/store/createStore.js +101 -187
  150. package/dist/esm/store/index.js +1 -10
  151. package/dist/esm/store/locks/appstate.lock.js +26 -0
  152. package/dist/esm/store/locks/auth.lock.js +15 -0
  153. package/dist/esm/store/locks/contact.lock.js +20 -0
  154. package/dist/esm/store/locks/device-list.lock.js +20 -0
  155. package/dist/esm/store/locks/message.lock.js +21 -0
  156. package/dist/esm/store/locks/participants.lock.js +20 -0
  157. package/dist/esm/store/locks/privacy-token.lock.js +18 -0
  158. package/dist/esm/store/locks/retry.lock.js +29 -0
  159. package/dist/esm/store/locks/sender-key.lock.js +52 -0
  160. package/dist/esm/store/locks/signal.lock.js +63 -0
  161. package/dist/esm/store/locks/thread.lock.js +21 -0
  162. package/dist/esm/store/noop.store.js +1 -1
  163. package/dist/esm/store/providers/memory/appstate.store.js +22 -24
  164. package/dist/esm/store/providers/memory/device-list.store.js +10 -5
  165. package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
  166. package/dist/esm/store/providers/memory/retry.store.js +77 -2
  167. package/dist/esm/store/providers/memory/sender-key.store.js +6 -1
  168. package/dist/esm/store/providers/memory/signal.store.js +36 -19
  169. package/dist/esm/transport/WaComms.js +3 -1
  170. package/dist/esm/transport/WaWebSocket.js +0 -6
  171. package/dist/esm/transport/binary/constants.js +0 -30
  172. package/dist/esm/transport/binary/decoder.js +4 -4
  173. package/dist/esm/transport/binary/encoder.js +8 -15
  174. package/dist/esm/transport/binary/index.js +0 -1
  175. package/dist/esm/transport/node/WaNodeOrchestrator.js +25 -19
  176. package/dist/esm/transport/node/builders/business.js +129 -0
  177. package/dist/esm/transport/node/builders/global.js +370 -0
  178. package/dist/esm/transport/node/builders/index.js +5 -2
  179. package/dist/esm/transport/node/builders/message.js +63 -239
  180. package/dist/esm/transport/node/builders/pairing.js +0 -24
  181. package/dist/esm/transport/node/builders/privacy-token.js +41 -0
  182. package/dist/esm/transport/node/builders/privacy.js +48 -0
  183. package/dist/esm/transport/node/builders/profile.js +70 -0
  184. package/dist/esm/transport/node/builders/retry.js +10 -22
  185. package/dist/esm/transport/node/builders/usync.js +6 -2
  186. package/dist/esm/transport/node/helpers.js +19 -1
  187. package/dist/esm/transport/node/usync.js +3 -33
  188. package/dist/esm/transport/node/xml.js +35 -14
  189. package/dist/esm/transport/noise/WaClientPayload.js +10 -10
  190. package/dist/esm/transport/noise/WaNoiseCert.js +3 -3
  191. package/dist/esm/transport/noise/WaNoiseSession.js +64 -23
  192. package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
  193. package/dist/esm/transport/stream/parse.js +8 -4
  194. package/dist/esm/util/bytes.js +22 -18
  195. package/dist/esm/util/index.js +5 -0
  196. package/dist/esm/util/primitives.js +3 -2
  197. package/dist/index.js +7 -1
  198. package/dist/infra/perf/BackgroundQueue.js +482 -0
  199. package/dist/infra/perf/BoundedTaskQueue.js +3 -1
  200. package/dist/infra/perf/PromiseDedup.js +24 -0
  201. package/dist/infra/perf/SharedExclusiveGate.js +113 -0
  202. package/dist/infra/perf/StoreLock.js +81 -0
  203. package/dist/media/WaMediaCrypto.js +94 -12
  204. package/dist/media/WaMediaTransferClient.js +39 -47
  205. package/dist/media/constants.js +2 -1
  206. package/dist/message/WaMessageClient.js +26 -19
  207. package/dist/message/content.js +198 -9
  208. package/dist/message/icdc.js +81 -0
  209. package/dist/message/incoming.js +24 -12
  210. package/dist/message/phash.js +3 -1
  211. package/dist/message/reporting-token.js +14 -28
  212. package/dist/protocol/appstate.js +10 -41
  213. package/dist/protocol/browser.js +10 -18
  214. package/dist/protocol/constants.js +21 -2
  215. package/dist/protocol/defaults.js +6 -0
  216. package/dist/protocol/index.js +8 -5
  217. package/dist/protocol/jid.js +111 -36
  218. package/dist/protocol/message.js +62 -2
  219. package/dist/protocol/nodes.js +2 -0
  220. package/dist/protocol/notification.js +3 -1
  221. package/dist/protocol/privacy-token.js +20 -0
  222. package/dist/protocol/privacy.js +58 -0
  223. package/dist/protocol/stream.js +27 -2
  224. package/dist/retry/codec.js +220 -0
  225. package/dist/retry/constants.js +1 -1
  226. package/dist/retry/index.js +5 -5
  227. package/dist/retry/parse.js +51 -30
  228. package/dist/retry/replay.js +10 -6
  229. package/dist/retry/tracker.js +50 -12
  230. package/dist/signal/api/SignalDeviceSyncApi.js +48 -31
  231. package/dist/signal/api/SignalDigestSyncApi.js +13 -9
  232. package/dist/signal/api/SignalIdentitySyncApi.js +25 -10
  233. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +17 -6
  234. package/dist/signal/api/SignalRotateKeyApi.js +4 -2
  235. package/dist/signal/api/SignalSessionSyncApi.js +16 -7
  236. package/dist/signal/api/result-map.js +13 -0
  237. package/dist/signal/constants.js +1 -5
  238. package/dist/signal/crypto/WaAdvSignature.js +11 -5
  239. package/dist/signal/{store/sqlite.js → encoding.js} +79 -25
  240. package/dist/signal/group/SenderKeyCodec.js +4 -3
  241. package/dist/signal/group/SenderKeyManager.js +125 -106
  242. package/dist/signal/index.js +13 -1
  243. package/dist/signal/registration/keygen.js +6 -2
  244. package/dist/signal/registration/utils.js +1 -0
  245. package/dist/signal/session/SignalProtocol.js +150 -74
  246. package/dist/signal/session/resolver.js +135 -100
  247. package/dist/store/contracts/privacy-token.store.js +2 -0
  248. package/dist/store/createStore.js +101 -187
  249. package/dist/store/index.js +15 -33
  250. package/dist/store/locks/appstate.lock.js +29 -0
  251. package/dist/store/locks/auth.lock.js +18 -0
  252. package/dist/store/locks/contact.lock.js +23 -0
  253. package/dist/store/locks/device-list.lock.js +23 -0
  254. package/dist/store/locks/message.lock.js +24 -0
  255. package/dist/store/locks/participants.lock.js +23 -0
  256. package/dist/store/locks/privacy-token.lock.js +21 -0
  257. package/dist/store/locks/retry.lock.js +32 -0
  258. package/dist/store/locks/sender-key.lock.js +55 -0
  259. package/dist/store/locks/signal.lock.js +66 -0
  260. package/dist/store/locks/thread.lock.js +24 -0
  261. package/dist/store/noop.store.js +1 -1
  262. package/dist/store/providers/memory/appstate.store.js +22 -24
  263. package/dist/store/providers/memory/device-list.store.js +10 -5
  264. package/dist/store/providers/memory/privacy-token.store.js +47 -0
  265. package/dist/store/providers/memory/retry.store.js +77 -2
  266. package/dist/store/providers/memory/sender-key.store.js +6 -1
  267. package/dist/store/providers/memory/signal.store.js +36 -19
  268. package/dist/transport/WaComms.js +3 -1
  269. package/dist/transport/WaWebSocket.js +0 -6
  270. package/dist/transport/binary/constants.js +1 -31
  271. package/dist/transport/binary/decoder.js +4 -4
  272. package/dist/transport/binary/encoder.js +8 -15
  273. package/dist/transport/binary/index.js +0 -4
  274. package/dist/transport/node/WaNodeOrchestrator.js +24 -18
  275. package/dist/transport/node/builders/business.js +137 -0
  276. package/dist/transport/node/builders/global.js +375 -0
  277. package/dist/transport/node/builders/index.js +18 -9
  278. package/dist/transport/node/builders/message.js +64 -245
  279. package/dist/transport/node/builders/pairing.js +0 -26
  280. package/dist/transport/node/builders/privacy-token.js +46 -0
  281. package/dist/transport/node/builders/privacy.js +55 -0
  282. package/dist/transport/node/builders/profile.js +78 -0
  283. package/dist/transport/node/builders/retry.js +9 -21
  284. package/dist/transport/node/builders/usync.js +6 -2
  285. package/dist/transport/node/helpers.js +20 -1
  286. package/dist/transport/node/usync.js +2 -32
  287. package/dist/transport/node/xml.js +35 -14
  288. package/dist/transport/noise/WaClientPayload.js +13 -13
  289. package/dist/transport/noise/WaNoiseCert.js +2 -2
  290. package/dist/transport/noise/WaNoiseSession.js +64 -23
  291. package/dist/transport/noise/WaNoiseSocket.js +8 -4
  292. package/dist/transport/stream/parse.js +7 -3
  293. package/dist/types/appstate/encoding.d.ts +7 -0
  294. package/dist/types/appstate/index.d.ts +3 -3
  295. package/dist/types/appstate/utils.d.ts +0 -2
  296. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +1 -1
  297. package/dist/types/auth/index.d.ts +0 -2
  298. package/dist/types/auth/types.d.ts +1 -0
  299. package/dist/types/client/WaClient.d.ts +27 -12
  300. package/dist/types/client/WaClientFactory.d.ts +12 -4
  301. package/dist/types/client/connection/WaConnectionManager.d.ts +2 -0
  302. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
  303. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +3 -1
  304. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +14 -0
  305. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -0
  306. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
  307. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +36 -0
  308. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +6 -0
  309. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
  310. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +45 -0
  311. package/dist/types/client/events/devices.d.ts +20 -0
  312. package/dist/types/client/events/identity.d.ts +9 -0
  313. package/dist/types/client/events/privacy-token.d.ts +7 -0
  314. package/dist/types/client/history-sync.d.ts +9 -6
  315. package/dist/types/client/incoming.d.ts +3 -1
  316. package/dist/types/client/index.d.ts +1 -1
  317. package/dist/types/client/mailbox.d.ts +3 -5
  318. package/dist/types/client/messages.d.ts +1 -2
  319. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
  320. package/dist/types/client/tokens/cs-token.d.ts +10 -0
  321. package/dist/types/client/tokens/tc-token.d.ts +5 -0
  322. package/dist/types/client/types.d.ts +51 -3
  323. package/dist/types/crypto/core/index.d.ts +2 -2
  324. package/dist/types/crypto/core/nonce.d.ts +2 -0
  325. package/dist/types/crypto/core/primitives.d.ts +0 -1
  326. package/dist/types/crypto/core/random.d.ts +1 -0
  327. package/dist/types/crypto/index.d.ts +1 -0
  328. package/dist/types/crypto/math/constants.d.ts +4 -2
  329. package/dist/types/crypto/math/fe.d.ts +30 -0
  330. package/dist/types/crypto/math/mod.d.ts +0 -2
  331. package/dist/types/crypto/math/types.d.ts +11 -4
  332. package/dist/types/index.d.ts +5 -3
  333. package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
  334. package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
  335. package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
  336. package/dist/types/infra/perf/StoreLock.d.ts +10 -0
  337. package/dist/types/media/WaMediaCrypto.d.ts +3 -2
  338. package/dist/types/media/WaMediaTransferClient.d.ts +3 -12
  339. package/dist/types/media/constants.d.ts +1 -1
  340. package/dist/types/media/index.d.ts +1 -1
  341. package/dist/types/media/types.d.ts +10 -2
  342. package/dist/types/message/content.d.ts +8 -0
  343. package/dist/types/message/icdc.d.ts +13 -0
  344. package/dist/types/message/reporting-token.d.ts +0 -1
  345. package/dist/types/message/types.d.ts +45 -6
  346. package/dist/types/protocol/appstate.d.ts +0 -11
  347. package/dist/types/protocol/constants.d.ts +7 -3
  348. package/dist/types/protocol/defaults.d.ts +6 -0
  349. package/dist/types/protocol/index.d.ts +1 -2
  350. package/dist/types/protocol/jid.d.ts +19 -2
  351. package/dist/types/protocol/message.d.ts +60 -0
  352. package/dist/types/protocol/nodes.d.ts +2 -0
  353. package/dist/types/protocol/notification.d.ts +2 -0
  354. package/dist/types/protocol/privacy-token.d.ts +17 -0
  355. package/dist/types/protocol/privacy.d.ts +75 -0
  356. package/dist/types/protocol/stream.d.ts +30 -0
  357. package/dist/types/retry/codec.d.ts +3 -0
  358. package/dist/types/retry/index.d.ts +3 -3
  359. package/dist/types/retry/parse.d.ts +5 -2
  360. package/dist/types/retry/tracker.d.ts +1 -0
  361. package/dist/types/retry/types.d.ts +6 -1
  362. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +2 -1
  363. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +6 -0
  364. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +2 -0
  365. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
  366. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
  367. package/dist/types/signal/api/result-map.d.ts +1 -0
  368. package/dist/types/signal/constants.d.ts +0 -3
  369. package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +3 -3
  370. package/dist/types/signal/group/SenderKeyManager.d.ts +10 -5
  371. package/dist/types/signal/index.d.ts +2 -0
  372. package/dist/types/signal/session/SignalProtocol.d.ts +10 -4
  373. package/dist/types/signal/session/resolver.d.ts +7 -2
  374. package/dist/types/store/contracts/appstate.store.d.ts +1 -1
  375. package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
  376. package/dist/types/store/contracts/retry.store.d.ts +7 -0
  377. package/dist/types/store/contracts/signal.store.d.ts +7 -0
  378. package/dist/types/store/createStore.d.ts +1 -1
  379. package/dist/types/store/index.d.ts +5 -13
  380. package/dist/types/store/locks/appstate.lock.d.ts +3 -0
  381. package/dist/types/store/locks/auth.lock.d.ts +3 -0
  382. package/dist/types/store/locks/contact.lock.d.ts +3 -0
  383. package/dist/types/store/locks/device-list.lock.d.ts +2 -0
  384. package/dist/types/store/locks/message.lock.d.ts +3 -0
  385. package/dist/types/store/locks/participants.lock.d.ts +2 -0
  386. package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
  387. package/dist/types/store/locks/retry.lock.d.ts +2 -0
  388. package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
  389. package/dist/types/store/locks/signal.lock.d.ts +3 -0
  390. package/dist/types/store/locks/thread.lock.d.ts +3 -0
  391. package/dist/types/store/providers/memory/appstate.store.d.ts +1 -1
  392. package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
  393. package/dist/types/store/providers/memory/retry.store.d.ts +8 -0
  394. package/dist/types/store/providers/memory/signal.store.d.ts +2 -1
  395. package/dist/types/store/types.d.ts +49 -61
  396. package/dist/types/transport/WaWebSocket.d.ts +0 -1
  397. package/dist/types/transport/binary/constants.d.ts +0 -30
  398. package/dist/types/transport/binary/index.d.ts +0 -1
  399. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +3 -4
  400. package/dist/types/transport/node/builders/business.d.ts +29 -0
  401. package/dist/types/transport/node/builders/global.d.ts +102 -0
  402. package/dist/types/transport/node/builders/index.d.ts +5 -2
  403. package/dist/types/transport/node/builders/message.d.ts +8 -7
  404. package/dist/types/transport/node/builders/pairing.d.ts +0 -2
  405. package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
  406. package/dist/types/transport/node/builders/privacy.d.ts +7 -0
  407. package/dist/types/transport/node/builders/profile.d.ts +8 -0
  408. package/dist/types/transport/node/builders/retry.d.ts +0 -1
  409. package/dist/types/transport/node/helpers.d.ts +5 -0
  410. package/dist/types/transport/noise/WaNoiseSession.d.ts +3 -2
  411. package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
  412. package/dist/types/util/bytes.d.ts +1 -1
  413. package/dist/types/util/index.d.ts +5 -0
  414. package/dist/types/util/primitives.d.ts +0 -1
  415. package/dist/util/bytes.js +22 -18
  416. package/dist/util/index.js +23 -0
  417. package/dist/util/primitives.js +2 -2
  418. package/package.json +29 -7
  419. package/proto/index.js +1 -1
  420. package/dist/crypto/core/constants.js +0 -4
  421. package/dist/esm/crypto/core/constants.js +0 -1
  422. package/dist/esm/retry/outbound.js +0 -82
  423. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
  424. package/dist/esm/store/providers/sqlite/appstate.store.js +0 -250
  425. package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
  426. package/dist/esm/store/providers/sqlite/connection.js +0 -245
  427. package/dist/esm/store/providers/sqlite/contact.store.js +0 -74
  428. package/dist/esm/store/providers/sqlite/device-list.store.js +0 -127
  429. package/dist/esm/store/providers/sqlite/message.store.js +0 -132
  430. package/dist/esm/store/providers/sqlite/migrations.js +0 -347
  431. package/dist/esm/store/providers/sqlite/participants.store.js +0 -77
  432. package/dist/esm/store/providers/sqlite/retry.store.js +0 -141
  433. package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -198
  434. package/dist/esm/store/providers/sqlite/signal.store.js +0 -435
  435. package/dist/esm/store/providers/sqlite/table-names.js +0 -107
  436. package/dist/esm/store/providers/sqlite/thread.store.js +0 -85
  437. package/dist/retry/outbound.js +0 -87
  438. package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
  439. package/dist/store/providers/sqlite/appstate.store.js +0 -254
  440. package/dist/store/providers/sqlite/auth.store.js +0 -180
  441. package/dist/store/providers/sqlite/connection.js +0 -281
  442. package/dist/store/providers/sqlite/contact.store.js +0 -78
  443. package/dist/store/providers/sqlite/device-list.store.js +0 -131
  444. package/dist/store/providers/sqlite/message.store.js +0 -136
  445. package/dist/store/providers/sqlite/migrations.js +0 -350
  446. package/dist/store/providers/sqlite/participants.store.js +0 -81
  447. package/dist/store/providers/sqlite/retry.store.js +0 -145
  448. package/dist/store/providers/sqlite/sender-key.store.js +0 -202
  449. package/dist/store/providers/sqlite/signal.store.js +0 -439
  450. package/dist/store/providers/sqlite/table-names.js +0 -113
  451. package/dist/store/providers/sqlite/thread.store.js +0 -89
  452. package/dist/types/appstate/store/sqlite.d.ts +0 -7
  453. package/dist/types/crypto/core/constants.d.ts +0 -1
  454. package/dist/types/retry/outbound.d.ts +0 -4
  455. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
  456. package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -17
  457. package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
  458. package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
  459. package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -12
  460. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -15
  461. package/dist/types/store/providers/sqlite/message.store.d.ts +0 -13
  462. package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
  463. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -12
  464. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -15
  465. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -24
  466. package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -53
  467. package/dist/types/store/providers/sqlite/table-names.d.ts +0 -5
  468. package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -13
@@ -45,8 +45,8 @@ export async function completeCompanionFinish(args) {
45
45
  if (primaryEphemeralPub.length === 0) {
46
46
  throw new Error('empty primary ephemeral public key');
47
47
  }
48
- const sharedEphemeral = await X25519.scalarMult(args.companionEphemeralPrivKey, primaryEphemeralPub);
49
- const [bundleSalt, bundleSecret, bundleIv] = await Promise.all([
48
+ const [sharedEphemeral, bundleSalt, bundleSecret, bundleIv] = await Promise.all([
49
+ X25519.scalarMult(args.companionEphemeralPrivKey, primaryEphemeralPub),
50
50
  randomBytesAsync(32),
51
51
  randomBytesAsync(32),
52
52
  randomBytesAsync(12)
@@ -58,9 +58,11 @@ export async function completeCompanionFinish(args) {
58
58
  args.primaryIdentityPub,
59
59
  bundleSecret
60
60
  ]);
61
- const encryptedBundle = await aesGcmEncrypt(bundleEncryptionKey, bundleIv, plaintextBundle);
61
+ const [encryptedBundle, sharedIdentity] = await Promise.all([
62
+ aesGcmEncrypt(bundleEncryptionKey, bundleIv, plaintextBundle),
63
+ X25519.scalarMult(args.registrationIdentityKeyPair.privKey, args.primaryIdentityPub)
64
+ ]);
62
65
  const wrappedKeyBundle = concatBytes([bundleSalt, bundleIv, encryptedBundle]);
63
- const sharedIdentity = await X25519.scalarMult(args.registrationIdentityKeyPair.privKey, args.primaryIdentityPub);
64
66
  const advMaterial = concatBytes([sharedEphemeral, sharedIdentity, bundleSecret]);
65
67
  const advSecret = await hkdf(advMaterial, null, WA_PAIRING_KDF_INFO.ADV_SECRET, 32);
66
68
  return {
@@ -4,7 +4,8 @@ import { proto } from '../../proto.js';
4
4
  import { WA_DEFAULTS, WA_IQ_TYPES, WA_NODE_TAGS, WA_SIGNALING } from '../../protocol/constants.js';
5
5
  import { parsePhoneJid } from '../../protocol/jid.js';
6
6
  import { ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE, computeAdvIdentityHmac, generateDeviceSignature, verifyDeviceIdentityAccountSignature } from '../../signal/crypto/WaAdvSignature.js';
7
- import { buildCompanionFinishRequestNode, buildCompanionHelloRequestNode, buildGetCountryCodeRequestNode, buildIqResultNode, buildNotificationAckNode } from '../../transport/node/builders/pairing.js';
7
+ import { buildAckNode, buildIqResultNode } from '../../transport/node/builders/global.js';
8
+ import { buildCompanionFinishRequestNode, buildCompanionHelloRequestNode, buildGetCountryCodeRequestNode } from '../../transport/node/builders/pairing.js';
8
9
  import { decodeNodeContentUtf8OrBytes, findNodeChildrenByTags, findNodeChild, getFirstNodeChild, getNodeChildrenNonEmptyUtf8ByTag, hasNodeChild } from '../../transport/node/helpers.js';
9
10
  import { decodeProtoBytes } from '../../util/bytes.js';
10
11
  import { concatBytes, uint8Equal } from '../../util/bytes.js';
@@ -118,7 +119,10 @@ export class WaPairingFlow {
118
119
  id: node.attrs.id,
119
120
  stage: linkCodeNode.attrs.stage
120
121
  });
121
- await this.opts.socket.sendNode(buildNotificationAckNode(node));
122
+ await this.opts.socket.sendNode(buildAckNode({
123
+ kind: 'notification',
124
+ node
125
+ }));
122
126
  const stage = linkCodeNode.attrs.stage;
123
127
  if (stage === WA_SIGNALING.LINK_CODE_STAGE_REFRESH_CODE) {
124
128
  const refNode = findNodeChild(linkCodeNode, WA_NODE_TAGS.LINK_CODE_PAIRING_REF);
@@ -146,18 +150,24 @@ export class WaPairingFlow {
146
150
  if (!hasExpectedChild) {
147
151
  return false;
148
152
  }
149
- await this.opts.socket.sendNode(buildNotificationAckNode(node, WA_SIGNALING.COMPANION_REG_REFRESH_NOTIFICATION));
153
+ // Rotate first so we don't ack success before local credential state is durably updated.
150
154
  await this.rotateAdvSecret(this.requireCredentials());
155
+ await this.opts.socket.sendNode(buildAckNode({
156
+ kind: 'notification',
157
+ node,
158
+ typeOverride: WA_SIGNALING.COMPANION_REG_REFRESH_NOTIFICATION
159
+ }));
151
160
  this.opts.logger.info('handled companion_reg_refresh notification');
152
161
  this.opts.qrFlow.refreshCurrentQr();
153
162
  return true;
154
163
  }
155
164
  async handlePairDevice(iqNode, pairDeviceNode) {
156
165
  const refs = getNodeChildrenNonEmptyUtf8ByTag(pairDeviceNode, WA_NODE_TAGS.REF, 'pair-device.ref');
166
+ // Commit adv-secret rotation before sending IQ success to avoid protocol/state divergence.
157
167
  await this.rotateAdvSecret(this.requireCredentials());
168
+ await this.opts.socket.sendNode(buildIqResultNode(iqNode));
158
169
  this.opts.qrFlow.setRefs(refs);
159
170
  this.opts.logger.info('pair-device refs updated', { refsCount: refs.length });
160
- await this.opts.socket.sendNode(buildIqResultNode(iqNode));
161
171
  }
162
172
  async handlePairSuccess(iqNode, pairSuccessNode) {
163
173
  this.opts.logger.info('processing pair-success node');
@@ -3,6 +3,7 @@ import { downloadExternalBlobReference } from '../appstate/utils.js';
3
3
  import { parseChatEventFromAppStateMutation } from './events/chat.js';
4
4
  import { processHistorySyncNotification } from './history-sync.js';
5
5
  import { persistIncomingMailboxEntities } from './mailbox.js';
6
+ import { WriteBehindPersistence } from './persistence/WriteBehindPersistence.js';
6
7
  import { buildWaClientDependencies, resolveWaClientBase } from './WaClientFactory.js';
7
8
  import { ConsoleLogger } from '../infra/log/ConsoleLogger.js';
8
9
  import { proto } from '../proto.js';
@@ -24,6 +25,9 @@ export class WaClient extends EventEmitter {
24
25
  constructor(options, logger = new ConsoleLogger('info')) {
25
26
  super();
26
27
  this.connectPromise = null;
28
+ this.acceptingIncomingEvents = true;
29
+ this.activeIncomingHandlers = 0;
30
+ this.incomingHandlersDrainedWaiters = [];
27
31
  const base = resolveWaClientBase(options, logger);
28
32
  this.options = base.options;
29
33
  this.logger = base.logger;
@@ -31,11 +35,17 @@ export class WaClient extends EventEmitter {
31
35
  this.contactStore = base.sessionStore.contacts;
32
36
  this.messageStore = base.sessionStore.messages;
33
37
  this.participantsStore = base.sessionStore.participants;
38
+ this.privacyTokenStore = base.sessionStore.privacyToken;
34
39
  this.deviceListStore = base.sessionStore.deviceList;
35
40
  this.retryStore = base.sessionStore.retry;
36
41
  this.signalStore = base.sessionStore.signal;
37
42
  this.senderKeyStore = base.sessionStore.senderKey;
38
43
  this.threadStore = base.sessionStore.threads;
44
+ this.writeBehind = new WriteBehindPersistence({
45
+ messageStore: this.messageStore,
46
+ threadStore: this.threadStore,
47
+ contactStore: this.contactStore
48
+ }, this.logger, this.options.writeBehind);
39
49
  const dependencies = buildWaClientDependencies({
40
50
  base,
41
51
  runtime: {
@@ -48,7 +58,10 @@ export class WaClient extends EventEmitter {
48
58
  handleIncomingMessageEvent: this.handleIncomingMessageEvent.bind(this),
49
59
  handleError: this.handleError.bind(this),
50
60
  handleIncomingFrame: this.handleIncomingFrame.bind(this),
51
- clearStoredState: this.clearStoredState.bind(this)
61
+ clearStoredState: this.clearStoredState.bind(this),
62
+ resumeIncomingEvents: () => {
63
+ this.acceptingIncomingEvents = true;
64
+ }
52
65
  }
53
66
  });
54
67
  Object.assign(this, dependencies);
@@ -119,63 +132,65 @@ export class WaClient extends EventEmitter {
119
132
  this.handleError(error);
120
133
  });
121
134
  }
122
- getMailboxPersistenceDeps() {
123
- return {
124
- logger: this.logger,
125
- contactStore: this.contactStore,
126
- messageStore: this.messageStore
127
- };
128
- }
129
135
  async handleIncomingMessageEvent(event) {
130
- this.emit('message', event);
131
- void persistIncomingMailboxEntities({
132
- ...this.getMailboxPersistenceDeps(),
133
- event
134
- });
135
- const protocolMessage = event.message?.protocolMessage;
136
- if (!protocolMessage) {
136
+ if (!this.tryEnterIncomingHandler()) {
137
137
  return;
138
138
  }
139
- const protocolEvent = {
140
- ...event,
141
- protocolMessage
142
- };
143
- this.emit('message_protocol', protocolEvent);
144
- const protocolType = protocolMessage.type;
145
- if (protocolType === null || protocolType === undefined) {
146
- this.logger.debug('incoming protocol message without type', {
147
- id: event.stanzaId,
148
- from: event.chatJid
139
+ try {
140
+ this.emit('message', event);
141
+ void persistIncomingMailboxEntities({
142
+ logger: this.logger,
143
+ writeBehind: this.writeBehind,
144
+ event
149
145
  });
150
- return;
151
- }
152
- if (protocolType === proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_REQUEST) {
153
- await this.handleIncomingAppStateSyncKeyRequest(event, protocolMessage);
154
- return;
155
- }
156
- if (protocolType === proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_SHARE) {
157
- await this.handleIncomingAppStateSyncKeyShare(event, protocolMessage);
158
- return;
159
- }
160
- if (protocolType === proto.Message.ProtocolMessage.Type.HISTORY_SYNC_NOTIFICATION) {
161
- if (this.options.history?.enabled && protocolMessage.historySyncNotification) {
162
- await this.handleHistorySyncNotification(protocolMessage.historySyncNotification);
146
+ const protocolMessage = event.message?.protocolMessage;
147
+ if (!protocolMessage) {
148
+ return;
163
149
  }
164
- return;
165
- }
166
- if (SYNC_RELATED_PROTOCOL_TYPES.has(protocolType)) {
167
- this.logger.info('incoming sync-related protocol message', {
150
+ const protocolEvent = {
151
+ ...event,
152
+ protocolMessage
153
+ };
154
+ this.emit('message_protocol', protocolEvent);
155
+ const protocolType = protocolMessage.type;
156
+ if (protocolType === null || protocolType === undefined) {
157
+ this.logger.debug('incoming protocol message without type', {
158
+ id: event.stanzaId,
159
+ from: event.chatJid
160
+ });
161
+ return;
162
+ }
163
+ if (protocolType === proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_REQUEST) {
164
+ await this.handleIncomingAppStateSyncKeyRequest(event, protocolMessage);
165
+ return;
166
+ }
167
+ if (protocolType === proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_SHARE) {
168
+ await this.handleIncomingAppStateSyncKeyShare(event, protocolMessage);
169
+ return;
170
+ }
171
+ if (protocolType === proto.Message.ProtocolMessage.Type.HISTORY_SYNC_NOTIFICATION) {
172
+ if (this.options.history?.enabled && protocolMessage.historySyncNotification) {
173
+ await this.handleHistorySyncNotification(protocolMessage.historySyncNotification);
174
+ }
175
+ return;
176
+ }
177
+ if (SYNC_RELATED_PROTOCOL_TYPES.has(protocolType)) {
178
+ this.logger.info('incoming sync-related protocol message', {
179
+ id: event.stanzaId,
180
+ from: event.chatJid,
181
+ protocolType
182
+ });
183
+ return;
184
+ }
185
+ this.logger.debug('incoming protocol message received', {
168
186
  id: event.stanzaId,
169
187
  from: event.chatJid,
170
188
  protocolType
171
189
  });
172
- return;
173
190
  }
174
- this.logger.debug('incoming protocol message received', {
175
- id: event.stanzaId,
176
- from: event.chatJid,
177
- protocolType
178
- });
191
+ finally {
192
+ this.leaveIncomingHandler();
193
+ }
179
194
  }
180
195
  async handleIncomingAppStateSyncKeyShare(event, protocolMessage) {
181
196
  const share = protocolMessage.appStateSyncKeyShare;
@@ -264,9 +279,18 @@ export class WaClient extends EventEmitter {
264
279
  });
265
280
  return;
266
281
  }
267
- const requestedKeys = await Promise.all(requestedKeyIds.map((keyId) => this.appStateStore.getSyncKey(keyId)));
268
- const availableKeys = requestedKeys.filter((key) => key !== null);
269
- const missingKeyIds = requestedKeyIds.filter((_, index) => requestedKeys[index] === null);
282
+ const requestedKeys = await this.appStateStore.getSyncKeysBatch(requestedKeyIds);
283
+ const availableKeys = [];
284
+ const missingKeyIds = [];
285
+ for (let i = 0; i < requestedKeys.length; i += 1) {
286
+ const key = requestedKeys[i];
287
+ if (key !== null) {
288
+ availableKeys.push(key);
289
+ }
290
+ else {
291
+ missingKeyIds.push(requestedKeyIds[i]);
292
+ }
293
+ }
270
294
  try {
271
295
  await this.messageDispatch.sendAppStateSyncKeyShare(requesterDeviceJid, availableKeys, missingKeyIds);
272
296
  this.logger.info('responded to app-state key request', {
@@ -313,18 +337,18 @@ export class WaClient extends EventEmitter {
313
337
  return false;
314
338
  }
315
339
  const candidateUser = toUserJid(candidateJid);
316
- const meUsers = [credentials.meJid, credentials.meLid]
317
- .filter((value) => !!value)
318
- .map((jid) => toUserJid(jid));
319
- return meUsers.includes(candidateUser);
340
+ return ((!!credentials.meJid && toUserJid(credentials.meJid) === candidateUser) ||
341
+ (!!credentials.meLid && toUserJid(credentials.meLid) === candidateUser));
320
342
  }
321
343
  async handleHistorySyncNotification(notification) {
322
344
  try {
323
345
  await processHistorySyncNotification({
324
- ...this.getMailboxPersistenceDeps(),
346
+ logger: this.logger,
325
347
  mediaTransfer: this.mediaTransfer,
326
- threadStore: this.threadStore,
327
- emitEvent: this.emit.bind(this)
348
+ writeBehind: this.writeBehind,
349
+ emitEvent: this.emit.bind(this),
350
+ onPrivacyTokens: (conversations) => this.trustedContactToken.hydrateFromHistorySync(conversations),
351
+ onNctSalt: (salt) => this.trustedContactToken.hydrateNctSaltFromHistorySync(salt)
328
352
  }, notification);
329
353
  }
330
354
  catch (error) {
@@ -351,10 +375,17 @@ export class WaClient extends EventEmitter {
351
375
  this.logger.trace('wa client connect already in-flight');
352
376
  return this.connectPromise;
353
377
  }
378
+ this.acceptingIncomingEvents = true;
354
379
  this.connectPromise = this.connectionManager
355
380
  .connect((frame) => this.handleIncomingFrame(frame))
356
381
  .then(() => {
357
- this.emit('connection_open', {});
382
+ this.emit('connection', {
383
+ status: 'open',
384
+ reason: 'connected',
385
+ code: null,
386
+ isLogout: false,
387
+ isNewLogin: this.connectionManager.wasNewLogin()
388
+ });
358
389
  })
359
390
  .finally(() => {
360
391
  this.connectPromise = null;
@@ -362,9 +393,22 @@ export class WaClient extends EventEmitter {
362
393
  return this.connectPromise;
363
394
  }
364
395
  async disconnect() {
396
+ await this.pauseIncomingEventsAndWaitDrain();
397
+ const writeBehindFlush = await this.writeBehind.flush(this.options.writeBehind?.flushTimeoutMs);
398
+ if (writeBehindFlush.remaining > 0) {
399
+ this.logger.warn('disconnect continuing with pending write-behind entries', {
400
+ remaining: writeBehindFlush.remaining
401
+ });
402
+ }
365
403
  this.keyShareCoordinator.notifyDisconnected();
366
404
  await this.connectionManager.disconnect();
367
- this.emit('connection_close', {});
405
+ this.emit('connection', {
406
+ status: 'close',
407
+ reason: 'client_disconnected',
408
+ code: null,
409
+ isLogout: false,
410
+ isNewLogin: false
411
+ });
368
412
  }
369
413
  async requestPairingCode(phoneNumber, shouldShowPushNotification = false) {
370
414
  if (!this.connectionManager.isConnected() || !this.authClient.getCurrentCredentials()) {
@@ -384,7 +428,10 @@ export class WaClient extends EventEmitter {
384
428
  if (!this.connectionManager.isConnected() || !this.authClient.getCurrentCredentials()) {
385
429
  throw new Error('client is not connected');
386
430
  }
387
- const normalizedPhoneJids = phoneNumbers.map(parsePhoneJid);
431
+ const normalizedPhoneJids = new Array(phoneNumbers.length);
432
+ for (let index = 0; index < phoneNumbers.length; index += 1) {
433
+ normalizedPhoneJids[index] = parsePhoneJid(phoneNumbers[index]);
434
+ }
388
435
  this.logger.trace('wa client query lids by phone numbers', {
389
436
  phones: normalizedPhoneJids.length
390
437
  });
@@ -393,41 +440,38 @@ export class WaClient extends EventEmitter {
393
440
  sendMessage(to, content, options = {}) {
394
441
  return this.messageDispatch.sendMessage(to, content, options);
395
442
  }
396
- syncSignalSession(jid, reasonIdentity = false) {
397
- return this.messageDispatch.syncSignalSession(jid, reasonIdentity);
398
- }
399
- sendReceipt(input) {
400
- return this.messageDispatch.sendReceipt(input);
401
- }
402
- setChatMute(chatJid, muted, muteEndTimestampMs) {
403
- return this.appStateMutations.setChatMute(chatJid, muted, muteEndTimestampMs);
404
- }
405
- setChatRead(chatJid, read) {
406
- return this.appStateMutations.setChatRead(chatJid, read);
407
- }
408
- setChatPin(chatJid, pinned) {
409
- return this.appStateMutations.setChatPin(chatJid, pinned);
443
+ async syncSignalSession(jid, reasonIdentity = false) {
444
+ await this.messageDispatch.syncSignalSession(jid, reasonIdentity);
445
+ if (reasonIdentity) {
446
+ this.trustedContactToken.reissueOnIdentityChange(jid).catch((err) => this.logger.warn('tc token reissue on identity change failed', {
447
+ jid,
448
+ message: toError(err).message
449
+ }));
450
+ }
410
451
  }
411
- setChatArchive(chatJid, archived) {
412
- return this.appStateMutations.setChatArchive(chatJid, archived);
452
+ get chat() {
453
+ return this.chatCoordinator;
413
454
  }
414
- clearChat(chatJid, options = {}) {
415
- return this.appStateMutations.clearChat(chatJid, options);
455
+ get group() {
456
+ return this.groupCoordinator;
416
457
  }
417
- deleteChat(chatJid, options = {}) {
418
- return this.appStateMutations.deleteChat(chatJid, options);
458
+ get privacy() {
459
+ return this.privacyCoordinator;
419
460
  }
420
- setChatLock(chatJid, locked) {
421
- return this.appStateMutations.setChatLock(chatJid, locked);
461
+ get profile() {
462
+ return this.profileCoordinator;
422
463
  }
423
- setMessageStar(message, starred) {
424
- return this.appStateMutations.setMessageStar(message, starred);
464
+ get business() {
465
+ return this.businessCoordinator;
425
466
  }
426
- deleteMessageForMe(message, options = {}) {
427
- return this.appStateMutations.deleteMessageForMe(message, options);
467
+ sendReceipt(input) {
468
+ return this.messageDispatch.sendReceipt(input);
428
469
  }
429
470
  flushAppStateMutations() {
430
- return this.appStateMutations.flushMutations();
471
+ return this.chatCoordinator.flushMutations();
472
+ }
473
+ flushWriteBehind(timeoutMs) {
474
+ return this.writeBehind.flush(timeoutMs);
431
475
  }
432
476
  async exportAppState() {
433
477
  return this.appStateSync.exportState();
@@ -504,9 +548,13 @@ export class WaClient extends EventEmitter {
504
548
  });
505
549
  }
506
550
  getBlockedAppStateCollections(syncResult) {
507
- return syncResult.collections
508
- .filter((entry) => entry.state === WA_APP_STATE_COLLECTION_STATES.BLOCKED)
509
- .map((entry) => entry.collection);
551
+ const blocked = [];
552
+ for (const entry of syncResult.collections) {
553
+ if (entry.state === WA_APP_STATE_COLLECTION_STATES.BLOCKED) {
554
+ blocked.push(entry.collection);
555
+ }
556
+ }
557
+ return blocked;
510
558
  }
511
559
  emitChatEventsFromAppStateSyncResult(syncResult) {
512
560
  const shouldEmitSnapshotMutations = this.options.chatEvents?.emitSnapshotMutations === true;
@@ -530,6 +578,7 @@ export class WaClient extends EventEmitter {
530
578
  continue;
531
579
  }
532
580
  try {
581
+ this.handleNctSaltMutation(mutation);
533
582
  const event = parseChatEventFromAppStateMutation(mutation);
534
583
  if (!event) {
535
584
  continue;
@@ -547,23 +596,98 @@ export class WaClient extends EventEmitter {
547
596
  }
548
597
  }
549
598
  }
599
+ handleNctSaltMutation(mutation) {
600
+ const nctAction = mutation.value?.nctSaltSyncAction;
601
+ if (!nctAction) {
602
+ return;
603
+ }
604
+ if (mutation.operation === 'set' && nctAction.salt) {
605
+ this.trustedContactToken.handleNctSaltSync(nctAction.salt).catch((err) => this.logger.warn('nct salt sync set failed', {
606
+ message: toError(err).message
607
+ }));
608
+ }
609
+ else if (mutation.operation === 'remove') {
610
+ this.trustedContactToken.handleNctSaltSync(null).catch((err) => this.logger.warn('nct salt sync remove failed', {
611
+ message: toError(err).message
612
+ }));
613
+ }
614
+ }
550
615
  async clearStoredState() {
616
+ await this.pauseIncomingEventsAndWaitDrain();
617
+ const writeBehindDestroy = await this.writeBehind.destroy(this.options.writeBehind?.flushTimeoutMs);
618
+ if (writeBehindDestroy.remaining > 0) {
619
+ throw new Error(`clear stored state aborted: write-behind did not fully drain (remaining=${writeBehindDestroy.remaining})`);
620
+ }
551
621
  const danglingReceipts = this.receiptQueue.take();
552
622
  if (danglingReceipts.length > 0) {
553
623
  this.logger.debug('cleared dangling receipts while clearing stored state', {
554
624
  count: danglingReceipts.length
555
625
  });
556
626
  }
557
- await this.authClient.clearStoredCredentials();
558
- await this.appStateStore.clear();
559
- await this.contactStore.clear();
560
- await this.messageStore.clear();
561
- await this.participantsStore.clear();
562
- await this.deviceListStore.clear();
563
- await this.retryStore.clear();
564
- await this.signalStore.clear();
565
- await this.senderKeyStore.clear();
566
- await this.threadStore.clear();
627
+ const s = this.options.logoutStoreClear;
628
+ const shouldClear = (key) => s === undefined || s[key] !== false;
629
+ if (shouldClear('auth'))
630
+ await this.authClient.clearStoredCredentials();
631
+ if (shouldClear('appState'))
632
+ await this.appStateStore.clear();
633
+ if (shouldClear('contacts'))
634
+ await this.contactStore.clear();
635
+ if (shouldClear('messages'))
636
+ await this.messageStore.clear();
637
+ if (shouldClear('participants'))
638
+ await this.participantsStore.clear();
639
+ if (shouldClear('deviceList'))
640
+ await this.deviceListStore.clear();
641
+ if (shouldClear('retry'))
642
+ await this.retryStore.clear();
643
+ if (shouldClear('signal'))
644
+ await this.signalStore.clear();
645
+ if (shouldClear('senderKey'))
646
+ await this.senderKeyStore.clear();
647
+ if (shouldClear('threads'))
648
+ await this.threadStore.clear();
649
+ if (shouldClear('privacyToken'))
650
+ await this.privacyTokenStore.clear();
651
+ }
652
+ tryEnterIncomingHandler() {
653
+ if (!this.acceptingIncomingEvents) {
654
+ return false;
655
+ }
656
+ this.activeIncomingHandlers += 1;
657
+ if (this.acceptingIncomingEvents) {
658
+ return true;
659
+ }
660
+ this.leaveIncomingHandler();
661
+ return false;
662
+ }
663
+ leaveIncomingHandler() {
664
+ if (this.activeIncomingHandlers <= 0) {
665
+ return;
666
+ }
667
+ this.activeIncomingHandlers -= 1;
668
+ if (this.activeIncomingHandlers === 0) {
669
+ this.notifyIncomingHandlersDrained();
670
+ }
671
+ }
672
+ async pauseIncomingEventsAndWaitDrain() {
673
+ this.acceptingIncomingEvents = false;
674
+ if (this.activeIncomingHandlers === 0) {
675
+ return;
676
+ }
677
+ await new Promise((resolve) => {
678
+ this.incomingHandlersDrainedWaiters[this.incomingHandlersDrainedWaiters.length] =
679
+ resolve;
680
+ });
681
+ }
682
+ notifyIncomingHandlersDrained() {
683
+ if (this.incomingHandlersDrainedWaiters.length === 0) {
684
+ return;
685
+ }
686
+ const waitersLength = this.incomingHandlersDrainedWaiters.length;
687
+ for (let index = 0; index < waitersLength; index += 1) {
688
+ this.incomingHandlersDrainedWaiters[index]();
689
+ }
690
+ this.incomingHandlersDrainedWaiters.length = 0;
567
691
  }
568
692
  handleError(error) {
569
693
  this.logger.error('wa client error', { message: error.message });