zapo-js 0.2.0 → 1.0.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 (863) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +103 -179
  3. package/dist/appstate/{WaAppStateCrypto.js → crypto/WaAppStateCrypto.js} +79 -62
  4. package/dist/appstate/index.js +8 -7
  5. package/dist/appstate/{encoding.js → parsers/encoding.js} +11 -4
  6. package/dist/appstate/{WaAppStateSyncResponseParser.js → parsers/response-parser.js} +20 -8
  7. package/dist/appstate/{WaAppStateSyncClient.js → sync/WaAppStateSyncClient.js} +246 -88
  8. package/dist/appstate/utils.js +16 -0
  9. package/dist/appstate-spec.js +89 -0
  10. package/dist/auth/WaAuthClient.js +117 -13
  11. package/dist/auth/credentials-flow.js +207 -0
  12. package/dist/auth/pairing/WaPairingFlow.js +53 -47
  13. package/dist/auth/pairing/pairing-code-crypto.js +91 -0
  14. package/dist/client/WaClient.js +369 -460
  15. package/dist/client/WaClientFactory.js +377 -93
  16. package/dist/client/connection/WaConnectionManager.js +31 -11
  17. package/dist/client/coordinators/WaAbPropsCoordinator.js +140 -0
  18. package/dist/client/coordinators/WaAppStateMutationCoordinator.js +663 -143
  19. package/dist/client/coordinators/WaBotCoordinator.js +345 -0
  20. package/dist/client/coordinators/WaBroadcastListCoordinator.js +20 -0
  21. package/dist/client/coordinators/WaBusinessCoordinator.js +81 -180
  22. package/dist/client/coordinators/WaEmailCoordinator.js +64 -0
  23. package/dist/client/coordinators/WaGroupCoordinator.js +529 -52
  24. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +130 -20
  25. package/dist/client/coordinators/WaLowLevelCoordinator.js +41 -0
  26. package/dist/client/coordinators/WaMessageCoordinator.js +365 -0
  27. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +724 -216
  28. package/dist/client/coordinators/WaNewsletterCoordinator.js +18 -0
  29. package/dist/client/coordinators/WaOfflineResumeCoordinator.js +114 -0
  30. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +53 -22
  31. package/dist/client/coordinators/WaPresenceCoordinator.js +21 -0
  32. package/dist/client/coordinators/WaPrivacyCoordinator.js +7 -5
  33. package/dist/client/coordinators/WaProfileCoordinator.js +223 -50
  34. package/dist/client/coordinators/WaRetryCoordinator.js +256 -123
  35. package/dist/client/coordinators/WaStatusCoordinator.js +49 -0
  36. package/dist/client/coordinators/WaStreamControlCoordinator.js +6 -6
  37. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +29 -10
  38. package/dist/client/events/abprops.js +43 -0
  39. package/dist/client/events/appstate-mutation.js +133 -0
  40. package/dist/client/events/business.js +375 -0
  41. package/dist/client/events/call.js +58 -0
  42. package/dist/client/events/chatstate.js +23 -0
  43. package/dist/client/events/devices.js +15 -16
  44. package/dist/client/{dirty.js → events/dirty.js} +34 -20
  45. package/dist/client/events/group.js +13 -24
  46. package/dist/client/events/identity.js +2 -1
  47. package/dist/client/events/incoming.js +502 -0
  48. package/dist/client/events/mex-notification.js +181 -0
  49. package/dist/client/events/picture.js +33 -0
  50. package/dist/client/events/presence.js +44 -0
  51. package/dist/client/events/privacy-token.js +1 -2
  52. package/dist/client/events/receipt.js +26 -0
  53. package/dist/client/events/registration.js +42 -0
  54. package/dist/client/media.js +400 -0
  55. package/dist/client/messaging/fanout.js +9 -10
  56. package/dist/client/messaging/{participants.js → group-metadata.js} +73 -35
  57. package/dist/client/messaging/ignore-key.js +132 -0
  58. package/dist/client/messaging/key-protocol.js +3 -17
  59. package/dist/client/messaging/link-preview.js +159 -0
  60. package/dist/client/messaging/messages.js +671 -0
  61. package/dist/client/newsletter/admin.js +165 -0
  62. package/dist/client/newsletter/content.js +253 -0
  63. package/dist/client/newsletter/discovery.js +115 -0
  64. package/dist/client/newsletter/messaging.js +197 -0
  65. package/dist/client/newsletter/mex.js +41 -0
  66. package/dist/client/newsletter/parse.js +217 -0
  67. package/dist/client/persistence/WriteBehindPersistence.js +31 -4
  68. package/dist/client/{history-sync.js → persistence/history-sync.js} +125 -18
  69. package/dist/client/persistence/mailbox.js +104 -0
  70. package/dist/client/tokens/cs-token.js +11 -17
  71. package/dist/crypto/core/hkdf.js +12 -12
  72. package/dist/crypto/core/index.js +9 -8
  73. package/dist/crypto/core/keys.js +1 -8
  74. package/dist/crypto/core/nonce.js +12 -12
  75. package/dist/crypto/core/primitives.js +123 -93
  76. package/dist/crypto/core/random.js +9 -9
  77. package/dist/crypto/core/xeddsa.js +59 -0
  78. package/dist/crypto/curves/Ed25519.js +32 -21
  79. package/dist/crypto/curves/X25519.js +71 -17
  80. package/dist/crypto/curves/constants.js +3 -1
  81. package/dist/crypto/math/constants.js +1 -2
  82. package/dist/crypto/math/mod.js +0 -33
  83. package/dist/esm/appstate/{WaAppStateCrypto.js → crypto/WaAppStateCrypto.js} +72 -55
  84. package/dist/esm/appstate/index.js +5 -5
  85. package/dist/esm/appstate/{encoding.js → parsers/encoding.js} +11 -4
  86. package/dist/esm/appstate/{WaAppStateSyncResponseParser.js → parsers/response-parser.js} +20 -8
  87. package/dist/esm/appstate/{WaAppStateSyncClient.js → sync/WaAppStateSyncClient.js} +235 -76
  88. package/dist/esm/appstate/utils.js +16 -0
  89. package/dist/esm/appstate-spec.js +79 -0
  90. package/dist/esm/auth/WaAuthClient.js +114 -10
  91. package/dist/esm/auth/credentials-flow.js +202 -0
  92. package/dist/esm/auth/pairing/WaPairingFlow.js +52 -46
  93. package/dist/esm/auth/pairing/pairing-code-crypto.js +85 -0
  94. package/dist/esm/client/WaClient.js +372 -463
  95. package/dist/esm/client/WaClientFactory.js +380 -96
  96. package/dist/esm/client/connection/WaConnectionManager.js +31 -11
  97. package/dist/esm/client/coordinators/WaAbPropsCoordinator.js +136 -0
  98. package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +665 -145
  99. package/dist/esm/client/coordinators/WaBotCoordinator.js +342 -0
  100. package/dist/esm/client/coordinators/WaBroadcastListCoordinator.js +17 -0
  101. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +78 -177
  102. package/dist/esm/client/coordinators/WaEmailCoordinator.js +61 -0
  103. package/dist/esm/client/coordinators/WaGroupCoordinator.js +532 -55
  104. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +132 -22
  105. package/dist/esm/client/coordinators/WaLowLevelCoordinator.js +38 -0
  106. package/dist/esm/client/coordinators/WaMessageCoordinator.js +361 -0
  107. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +719 -211
  108. package/dist/esm/client/coordinators/WaNewsletterCoordinator.js +13 -0
  109. package/dist/esm/client/coordinators/WaOfflineResumeCoordinator.js +110 -0
  110. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +54 -23
  111. package/dist/esm/client/coordinators/WaPresenceCoordinator.js +18 -0
  112. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +7 -5
  113. package/dist/esm/client/coordinators/WaProfileCoordinator.js +226 -53
  114. package/dist/esm/client/coordinators/WaRetryCoordinator.js +258 -125
  115. package/dist/esm/client/coordinators/WaStatusCoordinator.js +46 -0
  116. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +6 -6
  117. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +31 -12
  118. package/dist/esm/client/events/abprops.js +40 -0
  119. package/dist/esm/client/events/appstate-mutation.js +130 -0
  120. package/dist/esm/client/events/business.js +370 -0
  121. package/dist/esm/client/events/call.js +55 -0
  122. package/dist/esm/client/events/chatstate.js +20 -0
  123. package/dist/esm/client/events/devices.js +15 -16
  124. package/dist/esm/client/{dirty.js → events/dirty.js} +34 -20
  125. package/dist/esm/client/events/group.js +14 -25
  126. package/dist/esm/client/events/identity.js +2 -1
  127. package/dist/esm/client/events/incoming.js +487 -0
  128. package/dist/esm/client/events/mex-notification.js +178 -0
  129. package/dist/esm/client/events/picture.js +30 -0
  130. package/dist/esm/client/events/presence.js +41 -0
  131. package/dist/esm/client/events/privacy-token.js +1 -2
  132. package/dist/esm/client/events/receipt.js +23 -0
  133. package/dist/esm/client/events/registration.js +39 -0
  134. package/dist/esm/client/media.js +384 -0
  135. package/dist/esm/client/messaging/fanout.js +10 -11
  136. package/dist/esm/client/messaging/{participants.js → group-metadata.js} +72 -34
  137. package/dist/esm/client/messaging/ignore-key.js +126 -0
  138. package/dist/esm/client/messaging/key-protocol.js +3 -17
  139. package/dist/esm/client/messaging/link-preview.js +156 -0
  140. package/dist/esm/client/messaging/messages.js +667 -0
  141. package/dist/esm/client/newsletter/admin.js +162 -0
  142. package/dist/esm/client/newsletter/content.js +249 -0
  143. package/dist/esm/client/newsletter/discovery.js +112 -0
  144. package/dist/esm/client/newsletter/messaging.js +194 -0
  145. package/dist/esm/client/newsletter/mex.js +37 -0
  146. package/dist/esm/client/newsletter/parse.js +200 -0
  147. package/dist/esm/client/persistence/WriteBehindPersistence.js +31 -4
  148. package/dist/esm/client/{history-sync.js → persistence/history-sync.js} +124 -18
  149. package/dist/esm/client/persistence/mailbox.js +101 -0
  150. package/dist/esm/client/tokens/cs-token.js +12 -18
  151. package/dist/esm/crypto/core/hkdf.js +14 -14
  152. package/dist/esm/crypto/core/index.js +3 -2
  153. package/dist/esm/crypto/core/keys.js +1 -7
  154. package/dist/esm/crypto/core/nonce.js +11 -11
  155. package/dist/esm/crypto/core/primitives.js +121 -88
  156. package/dist/esm/crypto/core/random.js +8 -7
  157. package/dist/esm/crypto/core/xeddsa.js +55 -0
  158. package/dist/esm/crypto/curves/Ed25519.js +35 -24
  159. package/dist/esm/crypto/curves/X25519.js +74 -20
  160. package/dist/esm/crypto/curves/constants.js +2 -0
  161. package/dist/esm/crypto/math/constants.js +1 -2
  162. package/dist/esm/crypto/math/mod.js +0 -32
  163. package/dist/esm/index.js +7 -2
  164. package/dist/esm/infra/log/ConsoleLogger.js +30 -6
  165. package/dist/esm/infra/log/PinoLogger.js +64 -0
  166. package/dist/esm/infra/log/types.js +4 -2
  167. package/dist/esm/infra/perf/BackgroundQueue.js +55 -13
  168. package/dist/esm/infra/perf/StoreLock.js +7 -4
  169. package/dist/esm/media/constants.js +35 -2
  170. package/dist/esm/media/crypto/WaMediaCrypto.js +374 -0
  171. package/dist/esm/media/index.js +4 -3
  172. package/dist/esm/media/processor.js +1 -0
  173. package/dist/esm/media/sticker/sticker-pack.js +133 -0
  174. package/dist/esm/media/{WaMediaTransferClient.js → transfer/WaMediaTransferClient.js} +84 -196
  175. package/dist/esm/media/{conn.js → transfer/conn.js} +10 -5
  176. package/dist/esm/message/WaMessageClient.js +46 -15
  177. package/dist/esm/message/addons/link-preview/builder.js +36 -0
  178. package/dist/esm/message/addons/link-preview/detect.js +55 -0
  179. package/dist/esm/message/addons/link-preview/fetcher.js +391 -0
  180. package/dist/esm/message/addons/link-preview/types.js +1 -0
  181. package/dist/esm/message/context-info.js +123 -0
  182. package/dist/esm/message/crypto/addon-crypto.js +244 -0
  183. package/dist/esm/message/{icdc.js → crypto/icdc.js} +11 -13
  184. package/dist/esm/message/crypto/phash.js +133 -0
  185. package/dist/esm/message/{reporting-token.js → crypto/reporting-token.js} +7 -7
  186. package/dist/esm/message/{use-case-secret.js → crypto/use-case-secret.js} +21 -4
  187. package/dist/esm/message/{content.js → encode/content.js} +183 -8
  188. package/dist/esm/message/encode/media-payload.js +42 -0
  189. package/dist/esm/message/{padding.js → encode/padding.js} +9 -3
  190. package/dist/esm/message/index.js +2 -2
  191. package/dist/esm/message/kinds/bot.js +111 -0
  192. package/dist/esm/message/kinds/newsletter.js +244 -0
  193. package/dist/esm/message/kinds/sticker-pack.js +29 -0
  194. package/dist/esm/message/{ack.js → primitives/ack.js} +8 -1
  195. package/dist/esm/message/primitives/incoming.js +511 -0
  196. package/dist/esm/message/primitives/peer-data-operation.js +93 -0
  197. package/dist/esm/mex.js +1 -0
  198. package/dist/esm/protocol/abprops.js +169 -0
  199. package/dist/esm/protocol/appstate.js +6 -30
  200. package/dist/esm/protocol/auth.js +3 -2
  201. package/dist/esm/protocol/bot.js +77 -0
  202. package/dist/esm/protocol/browser.js +22 -0
  203. package/dist/esm/protocol/business.js +19 -0
  204. package/dist/esm/protocol/call.js +48 -0
  205. package/dist/esm/protocol/constants.js +10 -2
  206. package/dist/esm/protocol/defaults.js +3 -0
  207. package/dist/esm/protocol/email.js +30 -0
  208. package/dist/esm/protocol/index.js +1 -1
  209. package/dist/esm/protocol/jid.js +142 -11
  210. package/dist/esm/protocol/media.js +25 -12
  211. package/dist/esm/protocol/message.js +4 -1
  212. package/dist/esm/protocol/newsletter.js +61 -0
  213. package/dist/esm/protocol/nodes.js +26 -2
  214. package/dist/esm/protocol/notification.js +24 -2
  215. package/dist/esm/protocol/presence.js +13 -0
  216. package/dist/esm/protocol/status.js +6 -0
  217. package/dist/esm/retry/codec.js +5 -0
  218. package/dist/esm/retry/parse.js +20 -38
  219. package/dist/esm/retry/reason.js +6 -1
  220. package/dist/esm/retry/replay.js +131 -37
  221. package/dist/esm/retry/tracker.js +4 -8
  222. package/dist/esm/signal/api/SignalDeviceSyncApi.js +71 -21
  223. package/dist/esm/signal/api/SignalDigestSyncApi.js +15 -8
  224. package/dist/esm/signal/api/SignalIdentitySyncApi.js +13 -4
  225. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +24 -63
  226. package/dist/esm/signal/api/SignalRotateKeyApi.js +10 -0
  227. package/dist/esm/signal/api/SignalSessionSyncApi.js +23 -51
  228. package/dist/esm/signal/api/codec.js +52 -1
  229. package/dist/esm/signal/api/prekeys.js +4 -0
  230. package/dist/esm/signal/attestation/WaAdvSignature.js +17 -0
  231. package/dist/esm/signal/{crypto → attestation}/constants.js +0 -4
  232. package/dist/esm/signal/constants.js +3 -0
  233. package/dist/esm/signal/encoding.js +6 -332
  234. package/dist/esm/signal/group/SenderKeyChain.js +20 -35
  235. package/dist/esm/signal/group/SenderKeyCodec.js +5 -6
  236. package/dist/esm/signal/group/SenderKeyManager.js +37 -17
  237. package/dist/esm/signal/group/encoding.js +96 -0
  238. package/dist/esm/signal/index.js +4 -1
  239. package/dist/esm/signal/registration/encoding.js +34 -0
  240. package/dist/esm/signal/registration/keygen.js +12 -3
  241. package/dist/esm/signal/registration/utils.js +8 -2
  242. package/dist/esm/signal/session/SignalProtocol.js +129 -26
  243. package/dist/esm/signal/session/SignalRatchet.js +46 -64
  244. package/dist/esm/signal/session/SignalSerializer.js +5 -6
  245. package/dist/esm/signal/session/SignalSession.js +14 -19
  246. package/dist/esm/signal/session/encoding.js +173 -0
  247. package/dist/esm/signal/session/resolver.js +144 -35
  248. package/dist/esm/store/cache/identity.cache.js +75 -0
  249. package/dist/esm/store/cache/privacy-token.cache.js +57 -0
  250. package/dist/esm/store/cache/sender-key.cache.js +101 -0
  251. package/dist/esm/store/cache/session.cache.js +92 -0
  252. package/dist/esm/store/contracts/group-metadata.store.js +1 -0
  253. package/dist/esm/store/contracts/identity.store.js +1 -0
  254. package/dist/esm/store/contracts/message-secret.store.js +1 -0
  255. package/dist/esm/store/contracts/pre-key.store.js +1 -0
  256. package/dist/esm/store/contracts/session.store.js +1 -0
  257. package/dist/esm/store/createStore.js +129 -39
  258. package/dist/esm/store/index.js +15 -10
  259. package/dist/esm/store/locks/contact.lock.js +1 -0
  260. package/dist/esm/store/locks/device-list.lock.js +1 -0
  261. package/dist/esm/store/locks/group-metadata.lock.js +20 -0
  262. package/dist/esm/store/locks/identity.lock.js +16 -0
  263. package/dist/esm/store/locks/message-secret.lock.js +17 -0
  264. package/dist/esm/store/locks/pre-key.lock.js +27 -0
  265. package/dist/esm/store/locks/session.lock.js +19 -0
  266. package/dist/esm/store/locks/signal.lock.js +0 -24
  267. package/dist/esm/store/{providers/memory → memory}/appstate.store.js +5 -5
  268. package/dist/esm/store/memory/auth.store.js +24 -0
  269. package/dist/esm/store/memory/contact.store.js +79 -0
  270. package/dist/esm/store/memory/device-list.store.js +103 -0
  271. package/dist/esm/store/{providers/memory/participants.store.js → memory/group-metadata.store.js} +24 -12
  272. package/dist/esm/store/memory/identity.store.js +31 -0
  273. package/dist/esm/store/memory/message-secret.store.js +90 -0
  274. package/dist/esm/store/{providers/memory → memory}/message.store.js +2 -2
  275. package/dist/esm/store/memory/pre-key.store.js +97 -0
  276. package/dist/esm/store/{providers/memory → memory}/privacy-token.store.js +1 -1
  277. package/dist/esm/store/{providers/memory → memory}/retry.store.js +49 -14
  278. package/dist/esm/store/{providers/memory → memory}/sender-key.store.js +3 -3
  279. package/dist/esm/store/memory/session.store.js +45 -0
  280. package/dist/esm/store/memory/signal.store.js +36 -0
  281. package/dist/esm/store/{providers/memory → memory}/thread.store.js +2 -2
  282. package/dist/esm/store/noop.store.js +26 -4
  283. package/dist/esm/transport/WaComms.js +18 -8
  284. package/dist/esm/transport/WaWebSocket.js +41 -9
  285. package/dist/esm/transport/binary/constants.js +10 -4
  286. package/dist/esm/transport/binary/decoder.js +21 -15
  287. package/dist/esm/transport/binary/encoder.js +96 -21
  288. package/dist/esm/transport/binary/tokens.js +12 -12
  289. package/dist/esm/transport/index.js +7 -0
  290. package/dist/esm/transport/keepalive/WaKeepAlive.js +35 -12
  291. package/dist/esm/transport/node/WaMobileTcpSocket.js +120 -0
  292. package/dist/esm/transport/node/WaNodeOrchestrator.js +26 -13
  293. package/dist/esm/transport/node/WaNodeTransport.js +13 -0
  294. package/dist/esm/transport/node/builders/abprops.js +20 -0
  295. package/dist/esm/transport/node/builders/account-sync.js +7 -15
  296. package/dist/esm/transport/node/builders/bot.js +38 -0
  297. package/dist/esm/transport/node/builders/business.js +30 -30
  298. package/dist/esm/transport/node/builders/chatstate.js +28 -0
  299. package/dist/esm/transport/node/builders/community.js +53 -0
  300. package/dist/esm/transport/node/builders/device.js +11 -0
  301. package/dist/esm/transport/node/builders/email.js +66 -0
  302. package/dist/esm/transport/node/builders/global.js +1 -1
  303. package/dist/esm/transport/node/builders/group.js +114 -4
  304. package/dist/esm/transport/node/builders/media.js +2 -2
  305. package/dist/esm/transport/node/builders/message.js +83 -49
  306. package/dist/esm/transport/node/builders/newsletter.js +176 -0
  307. package/dist/esm/transport/node/builders/offline.js +14 -0
  308. package/dist/esm/transport/node/builders/passive.js +7 -0
  309. package/dist/esm/transport/node/builders/prekeys.js +40 -43
  310. package/dist/esm/transport/node/builders/presence.js +39 -0
  311. package/dist/esm/transport/node/builders/privacy-token.js +19 -23
  312. package/dist/esm/transport/node/builders/privacy.js +6 -6
  313. package/dist/esm/transport/node/builders/profile.js +28 -8
  314. package/dist/esm/transport/node/builders/retry.js +1 -1
  315. package/dist/esm/transport/node/builders/tos.js +58 -0
  316. package/dist/esm/transport/node/builders/usync.js +51 -2
  317. package/dist/esm/transport/node/helpers.js +27 -1
  318. package/dist/esm/transport/node/mex/argo-decoder.js +152 -0
  319. package/dist/esm/transport/node/mex/client.js +105 -0
  320. package/dist/esm/transport/node/query.js +17 -0
  321. package/dist/esm/transport/node/usync.js +12 -0
  322. package/dist/esm/transport/noise/WaClientPayload.js +23 -18
  323. package/dist/esm/transport/noise/WaFrameCodec.js +2 -2
  324. package/dist/esm/transport/noise/WaMobileClientPayload.js +58 -0
  325. package/dist/esm/transport/noise/WaNoiseCert.js +14 -27
  326. package/dist/esm/transport/noise/WaNoiseHandshake.js +27 -25
  327. package/dist/esm/transport/noise/WaNoiseSession.js +48 -67
  328. package/dist/esm/transport/noise/WaNoiseSocket.js +19 -13
  329. package/dist/esm/transport/noise/constants.js +0 -1
  330. package/dist/esm/transport/proxy.js +5 -0
  331. package/dist/esm/transport/stream/parse.js +3 -7
  332. package/dist/esm/transport/wa-web-version-fetcher.js +91 -0
  333. package/dist/esm/util/async.js +4 -0
  334. package/dist/esm/util/bytes.js +37 -2
  335. package/dist/esm/util/clock.js +15 -0
  336. package/dist/esm/util/coercion.js +45 -3
  337. package/dist/esm/util/collections.js +11 -0
  338. package/dist/esm/util/index.js +2 -2
  339. package/dist/esm/util/primitives.js +19 -0
  340. package/dist/esm/util/runtime.js +5 -0
  341. package/dist/esm/version-spec.js +1 -0
  342. package/dist/index.js +31 -1
  343. package/dist/infra/log/ConsoleLogger.js +30 -6
  344. package/dist/infra/log/PinoLogger.js +64 -0
  345. package/dist/infra/log/types.js +4 -2
  346. package/dist/infra/perf/BackgroundQueue.js +55 -13
  347. package/dist/infra/perf/StoreLock.js +7 -4
  348. package/dist/media/constants.js +36 -3
  349. package/dist/media/crypto/WaMediaCrypto.js +378 -0
  350. package/dist/media/index.js +9 -4
  351. package/dist/media/processor.js +2 -0
  352. package/dist/media/sticker/sticker-pack.js +136 -0
  353. package/dist/media/{WaMediaTransferClient.js → transfer/WaMediaTransferClient.js} +87 -229
  354. package/dist/media/{conn.js → transfer/conn.js} +10 -5
  355. package/dist/message/WaMessageClient.js +46 -15
  356. package/dist/message/addons/link-preview/builder.js +39 -0
  357. package/dist/message/addons/link-preview/detect.js +58 -0
  358. package/dist/message/addons/link-preview/fetcher.js +394 -0
  359. package/dist/message/addons/link-preview/types.js +2 -0
  360. package/dist/message/context-info.js +129 -0
  361. package/dist/message/crypto/addon-crypto.js +254 -0
  362. package/dist/message/{icdc.js → crypto/icdc.js} +11 -13
  363. package/dist/message/crypto/phash.js +136 -0
  364. package/dist/message/{reporting-token.js → crypto/reporting-token.js} +7 -7
  365. package/dist/message/{use-case-secret.js → crypto/use-case-secret.js} +21 -4
  366. package/dist/message/{content.js → encode/content.js} +200 -7
  367. package/dist/message/encode/media-payload.js +45 -0
  368. package/dist/message/{padding.js → encode/padding.js} +9 -3
  369. package/dist/message/index.js +2 -2
  370. package/dist/message/kinds/bot.js +120 -0
  371. package/dist/message/kinds/newsletter.js +248 -0
  372. package/dist/message/kinds/sticker-pack.js +34 -0
  373. package/dist/message/{ack.js → primitives/ack.js} +8 -1
  374. package/dist/message/{incoming.js → primitives/incoming.js} +225 -38
  375. package/dist/message/primitives/peer-data-operation.js +96 -0
  376. package/dist/mex.js +6 -0
  377. package/dist/proto.js +1 -1
  378. package/dist/protocol/abprops.js +173 -0
  379. package/dist/protocol/appstate.js +7 -31
  380. package/dist/protocol/auth.js +3 -2
  381. package/dist/protocol/bot.js +81 -0
  382. package/dist/protocol/browser.js +23 -0
  383. package/dist/protocol/business.js +22 -0
  384. package/dist/protocol/call.js +51 -0
  385. package/dist/protocol/constants.js +51 -3
  386. package/dist/protocol/defaults.js +3 -0
  387. package/dist/protocol/email.js +33 -0
  388. package/dist/protocol/index.js +12 -3
  389. package/dist/protocol/jid.js +148 -11
  390. package/dist/protocol/media.js +25 -12
  391. package/dist/protocol/message.js +4 -1
  392. package/dist/protocol/newsletter.js +64 -0
  393. package/dist/protocol/nodes.js +26 -2
  394. package/dist/protocol/notification.js +25 -3
  395. package/dist/protocol/presence.js +16 -0
  396. package/dist/protocol/status.js +9 -0
  397. package/dist/retry/codec.js +5 -0
  398. package/dist/retry/parse.js +16 -34
  399. package/dist/retry/reason.js +6 -1
  400. package/dist/retry/replay.js +129 -35
  401. package/dist/retry/tracker.js +3 -7
  402. package/dist/signal/api/SignalDeviceSyncApi.js +69 -19
  403. package/dist/signal/api/SignalDigestSyncApi.js +14 -7
  404. package/dist/signal/api/SignalIdentitySyncApi.js +13 -4
  405. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +21 -60
  406. package/dist/signal/api/SignalRotateKeyApi.js +10 -0
  407. package/dist/signal/api/SignalSessionSyncApi.js +20 -48
  408. package/dist/signal/api/codec.js +52 -0
  409. package/dist/signal/api/prekeys.js +4 -0
  410. package/dist/signal/attestation/WaAdvSignature.js +26 -0
  411. package/dist/signal/{crypto → attestation}/constants.js +1 -5
  412. package/dist/signal/constants.js +4 -1
  413. package/dist/signal/encoding.js +5 -341
  414. package/dist/signal/group/SenderKeyChain.js +19 -34
  415. package/dist/signal/group/SenderKeyCodec.js +4 -5
  416. package/dist/signal/group/SenderKeyManager.js +36 -16
  417. package/dist/signal/group/encoding.js +101 -0
  418. package/dist/signal/index.js +13 -10
  419. package/dist/signal/registration/encoding.js +39 -0
  420. package/dist/signal/registration/keygen.js +11 -2
  421. package/dist/signal/registration/utils.js +8 -2
  422. package/dist/signal/session/SignalProtocol.js +128 -25
  423. package/dist/signal/session/SignalRatchet.js +41 -60
  424. package/dist/signal/session/SignalSerializer.js +5 -6
  425. package/dist/signal/session/SignalSession.js +13 -19
  426. package/dist/signal/session/encoding.js +183 -0
  427. package/dist/signal/session/resolver.js +144 -35
  428. package/dist/store/cache/identity.cache.js +78 -0
  429. package/dist/store/cache/privacy-token.cache.js +60 -0
  430. package/dist/store/cache/sender-key.cache.js +104 -0
  431. package/dist/store/cache/session.cache.js +95 -0
  432. package/dist/store/contracts/group-metadata.store.js +2 -0
  433. package/dist/store/contracts/identity.store.js +2 -0
  434. package/dist/store/contracts/message-secret.store.js +2 -0
  435. package/dist/store/contracts/pre-key.store.js +2 -0
  436. package/dist/store/contracts/session.store.js +2 -0
  437. package/dist/store/createStore.js +128 -38
  438. package/dist/store/index.js +22 -12
  439. package/dist/store/locks/contact.lock.js +1 -0
  440. package/dist/store/locks/device-list.lock.js +1 -0
  441. package/dist/store/locks/group-metadata.lock.js +23 -0
  442. package/dist/store/locks/identity.lock.js +19 -0
  443. package/dist/store/locks/message-secret.lock.js +20 -0
  444. package/dist/store/locks/pre-key.lock.js +30 -0
  445. package/dist/store/locks/session.lock.js +22 -0
  446. package/dist/store/locks/signal.lock.js +0 -24
  447. package/dist/store/{providers/memory → memory}/appstate.store.js +5 -5
  448. package/dist/store/memory/auth.store.js +28 -0
  449. package/dist/store/memory/contact.store.js +83 -0
  450. package/dist/store/memory/device-list.store.js +107 -0
  451. package/dist/store/{providers/memory/participants.store.js → memory/group-metadata.store.js} +26 -14
  452. package/dist/store/memory/identity.store.js +35 -0
  453. package/dist/store/memory/message-secret.store.js +94 -0
  454. package/dist/store/{providers/memory → memory}/message.store.js +2 -2
  455. package/dist/store/memory/pre-key.store.js +101 -0
  456. package/dist/store/{providers/memory → memory}/privacy-token.store.js +1 -1
  457. package/dist/store/{providers/memory → memory}/retry.store.js +49 -14
  458. package/dist/store/{providers/memory → memory}/sender-key.store.js +3 -3
  459. package/dist/store/memory/session.store.js +49 -0
  460. package/dist/store/memory/signal.store.js +40 -0
  461. package/dist/store/{providers/memory → memory}/thread.store.js +2 -2
  462. package/dist/store/noop.store.js +27 -5
  463. package/dist/transport/WaComms.js +18 -8
  464. package/dist/transport/WaWebSocket.js +41 -9
  465. package/dist/transport/binary/constants.js +11 -5
  466. package/dist/transport/binary/decoder.js +24 -18
  467. package/dist/transport/binary/encoder.js +109 -34
  468. package/dist/transport/binary/tokens.js +12 -12
  469. package/dist/transport/index.js +19 -1
  470. package/dist/transport/keepalive/WaKeepAlive.js +35 -12
  471. package/dist/transport/node/WaMobileTcpSocket.js +124 -0
  472. package/dist/transport/node/WaNodeOrchestrator.js +25 -12
  473. package/dist/transport/node/WaNodeTransport.js +13 -0
  474. package/dist/transport/node/builders/abprops.js +23 -0
  475. package/dist/transport/node/builders/account-sync.js +7 -16
  476. package/dist/transport/node/builders/bot.js +43 -0
  477. package/dist/transport/node/builders/business.js +31 -31
  478. package/dist/transport/node/builders/chatstate.js +31 -0
  479. package/dist/transport/node/builders/community.js +59 -0
  480. package/dist/transport/node/builders/device.js +14 -0
  481. package/dist/transport/node/builders/email.js +73 -0
  482. package/dist/transport/node/builders/global.js +1 -1
  483. package/dist/transport/node/builders/group.js +121 -3
  484. package/dist/transport/node/builders/media.js +1 -1
  485. package/dist/transport/node/builders/message.js +84 -49
  486. package/dist/transport/node/builders/newsletter.js +183 -0
  487. package/dist/transport/node/builders/offline.js +17 -0
  488. package/dist/transport/node/builders/passive.js +10 -0
  489. package/dist/transport/node/builders/prekeys.js +38 -41
  490. package/dist/transport/node/builders/presence.js +43 -0
  491. package/dist/transport/node/builders/privacy-token.js +18 -22
  492. package/dist/transport/node/builders/privacy.js +5 -5
  493. package/dist/transport/node/builders/profile.js +30 -7
  494. package/dist/transport/node/builders/retry.js +1 -1
  495. package/dist/transport/node/builders/tos.js +63 -0
  496. package/dist/transport/node/builders/usync.js +52 -1
  497. package/dist/transport/node/helpers.js +28 -1
  498. package/dist/transport/node/mex/argo-decoder.js +189 -0
  499. package/dist/transport/node/mex/client.js +109 -0
  500. package/dist/transport/node/query.js +17 -0
  501. package/dist/transport/node/usync.js +13 -0
  502. package/dist/transport/noise/WaClientPayload.js +22 -17
  503. package/dist/transport/noise/WaFrameCodec.js +1 -1
  504. package/dist/transport/noise/WaMobileClientPayload.js +61 -0
  505. package/dist/transport/noise/WaNoiseCert.js +13 -26
  506. package/dist/transport/noise/WaNoiseHandshake.js +25 -23
  507. package/dist/transport/noise/WaNoiseSession.js +47 -66
  508. package/dist/transport/noise/WaNoiseSocket.js +18 -12
  509. package/dist/transport/noise/constants.js +1 -2
  510. package/dist/transport/proxy.js +5 -0
  511. package/dist/transport/stream/parse.js +3 -7
  512. package/dist/transport/wa-web-version-fetcher.js +94 -0
  513. package/dist/types/appstate/constants.d.ts +1 -1
  514. package/dist/types/appstate/{WaAppStateCrypto.d.ts → crypto/WaAppStateCrypto.d.ts} +29 -9
  515. package/dist/types/appstate/index.d.ts +5 -5
  516. package/dist/types/appstate/{encoding.d.ts → parsers/encoding.d.ts} +8 -1
  517. package/dist/types/appstate/{WaAppStateSyncResponseParser.d.ts → parsers/response-parser.d.ts} +13 -3
  518. package/dist/types/appstate/sync/WaAppStateSyncClient.d.ts +105 -0
  519. package/dist/types/appstate/types.d.ts +1 -1
  520. package/dist/types/appstate/utils.d.ts +17 -1
  521. package/dist/types/appstate-spec.d.ts +24 -0
  522. package/dist/types/auth/WaAuthClient.d.ts +95 -3
  523. package/dist/types/auth/credentials-flow.d.ts +21 -0
  524. package/dist/types/auth/pairing/WaPairingFlow.d.ts +3 -2
  525. package/dist/types/auth/pairing/{WaPairingCodeCrypto.d.ts → pairing-code-crypto.d.ts} +5 -1
  526. package/dist/types/auth/types.d.ts +88 -1
  527. package/dist/types/client/WaClient.d.ts +183 -65
  528. package/dist/types/client/WaClientFactory.d.ts +40 -9
  529. package/dist/types/client/connection/WaConnectionManager.d.ts +4 -2
  530. package/dist/types/client/connection/WaReceiptQueue.d.ts +1 -1
  531. package/dist/types/client/coordinators/WaAbPropsCoordinator.d.ts +26 -0
  532. package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +215 -5
  533. package/dist/types/client/coordinators/WaBotCoordinator.d.ts +117 -0
  534. package/dist/types/client/coordinators/WaBroadcastListCoordinator.d.ts +39 -0
  535. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +45 -44
  536. package/dist/types/client/coordinators/WaEmailCoordinator.d.ts +40 -0
  537. package/dist/types/client/coordinators/WaGroupCoordinator.d.ts +311 -9
  538. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +16 -4
  539. package/dist/types/client/coordinators/WaLowLevelCoordinator.d.ts +47 -0
  540. package/dist/types/client/coordinators/WaMessageCoordinator.d.ts +232 -0
  541. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +65 -29
  542. package/dist/types/client/coordinators/WaNewsletterCoordinator.d.ts +13 -0
  543. package/dist/types/client/coordinators/WaOfflineResumeCoordinator.d.ts +31 -0
  544. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +15 -3
  545. package/dist/types/client/coordinators/WaPresenceCoordinator.d.ts +27 -0
  546. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +28 -1
  547. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +117 -2
  548. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +23 -15
  549. package/dist/types/client/coordinators/WaStatusCoordinator.d.ts +42 -0
  550. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +16 -2
  551. package/dist/types/client/events/abprops.d.ts +15 -0
  552. package/dist/types/client/events/appstate-mutation.d.ts +3 -0
  553. package/dist/types/client/events/business.d.ts +10 -0
  554. package/dist/types/client/events/call.d.ts +31 -0
  555. package/dist/types/client/events/chatstate.d.ts +9 -0
  556. package/dist/types/client/events/devices.d.ts +5 -4
  557. package/dist/types/client/{dirty.d.ts → events/dirty.d.ts} +7 -4
  558. package/dist/types/client/events/group.d.ts +2 -1
  559. package/dist/types/client/events/identity.d.ts +2 -1
  560. package/dist/types/client/events/incoming.d.ts +65 -0
  561. package/dist/types/client/events/mex-notification.d.ts +6 -0
  562. package/dist/types/client/events/picture.d.ts +8 -0
  563. package/dist/types/client/events/presence.d.ts +28 -0
  564. package/dist/types/client/events/receipt.d.ts +14 -0
  565. package/dist/types/client/events/registration.d.ts +18 -0
  566. package/dist/types/client/index.d.ts +1 -1
  567. package/dist/types/client/media.d.ts +65 -0
  568. package/dist/types/client/messaging/fanout.d.ts +2 -2
  569. package/dist/types/client/messaging/group-metadata.d.ts +19 -0
  570. package/dist/types/client/messaging/ignore-key.d.ts +11 -0
  571. package/dist/types/client/messaging/key-protocol.d.ts +9 -7
  572. package/dist/types/client/messaging/link-preview.d.ts +19 -0
  573. package/dist/types/client/messaging/messages.d.ts +28 -0
  574. package/dist/types/client/newsletter/admin.d.ts +71 -0
  575. package/dist/types/client/newsletter/content.d.ts +42 -0
  576. package/dist/types/client/newsletter/discovery.d.ts +33 -0
  577. package/dist/types/client/newsletter/messaging.d.ts +66 -0
  578. package/dist/types/client/newsletter/mex.d.ts +14 -0
  579. package/dist/types/client/newsletter/parse.d.ts +19 -0
  580. package/dist/types/client/newsletter/types.d.ts +190 -0
  581. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +13 -2
  582. package/dist/types/client/persistence/history-sync.d.ts +29 -0
  583. package/dist/types/client/persistence/mailbox.d.ts +12 -0
  584. package/dist/types/client/tokens/cs-token.d.ts +1 -3
  585. package/dist/types/client/types.d.ts +926 -55
  586. package/dist/types/crypto/core/hkdf.d.ts +10 -2
  587. package/dist/types/crypto/core/index.d.ts +3 -2
  588. package/dist/types/crypto/core/keys.d.ts +0 -4
  589. package/dist/types/crypto/core/nonce.d.ts +4 -5
  590. package/dist/types/crypto/core/primitives.d.ts +31 -20
  591. package/dist/types/crypto/core/random.d.ts +7 -1
  592. package/dist/types/crypto/core/xeddsa.d.ts +11 -0
  593. package/dist/types/crypto/curves/Ed25519.d.ts +7 -1
  594. package/dist/types/crypto/curves/X25519.d.ts +20 -1
  595. package/dist/types/crypto/curves/constants.d.ts +4 -2
  596. package/dist/types/crypto/curves/types.d.ts +0 -5
  597. package/dist/types/crypto/index.d.ts +1 -0
  598. package/dist/types/crypto/math/constants.d.ts +0 -1
  599. package/dist/types/crypto/math/mod.d.ts +0 -1
  600. package/dist/types/index.d.ts +32 -5
  601. package/dist/types/infra/log/ConsoleLogger.d.ts +19 -2
  602. package/dist/types/infra/log/PinoLogger.d.ts +56 -2
  603. package/dist/types/infra/log/types.d.ts +6 -0
  604. package/dist/types/infra/perf/BackgroundQueue.d.ts +19 -0
  605. package/dist/types/infra/perf/StoreLock.d.ts +1 -0
  606. package/dist/types/media/constants.d.ts +9 -2
  607. package/dist/types/media/crypto/WaMediaCrypto.d.ts +59 -0
  608. package/dist/types/media/index.d.ts +7 -4
  609. package/dist/types/media/processor.d.ts +50 -0
  610. package/dist/types/media/sticker/sticker-pack.d.ts +6 -0
  611. package/dist/types/media/{WaMediaTransferClient.d.ts → transfer/WaMediaTransferClient.d.ts} +33 -12
  612. package/dist/types/media/transfer/conn.d.ts +7 -0
  613. package/dist/types/media/types.d.ts +10 -5
  614. package/dist/types/message/WaMessageClient.d.ts +14 -0
  615. package/dist/types/message/addons/link-preview/builder.d.ts +13 -0
  616. package/dist/types/message/addons/link-preview/detect.d.ts +5 -0
  617. package/dist/types/message/addons/link-preview/fetcher.d.ts +13 -0
  618. package/dist/types/message/addons/link-preview/types.d.ts +51 -0
  619. package/dist/types/message/context-info.d.ts +66 -0
  620. package/dist/types/message/crypto/addon-crypto.d.ts +78 -0
  621. package/dist/types/message/{icdc.d.ts → crypto/icdc.d.ts} +6 -6
  622. package/dist/types/message/{phash.d.ts → crypto/phash.d.ts} +1 -1
  623. package/dist/types/message/{reporting-token.d.ts → crypto/reporting-token.d.ts} +2 -2
  624. package/dist/types/message/{use-case-secret.d.ts → crypto/use-case-secret.d.ts} +17 -1
  625. package/dist/types/message/encode/content.d.ts +43 -0
  626. package/dist/types/message/{device-sent.d.ts → encode/device-sent.d.ts} +1 -1
  627. package/dist/types/message/encode/media-payload.d.ts +12 -0
  628. package/dist/types/message/index.d.ts +2 -2
  629. package/dist/types/message/kinds/bot.d.ts +31 -0
  630. package/dist/types/message/kinds/newsletter.d.ts +12 -0
  631. package/dist/types/message/kinds/sticker-pack.d.ts +6 -0
  632. package/dist/types/message/{ack.d.ts → primitives/ack.d.ts} +1 -1
  633. package/dist/types/message/primitives/incoming.d.ts +21 -0
  634. package/dist/types/message/primitives/peer-data-operation.d.ts +23 -0
  635. package/dist/types/message/types.d.ts +218 -28
  636. package/dist/types/mex.d.ts +2 -0
  637. package/dist/types/proto.d.ts +2 -2
  638. package/dist/types/protocol/abprops.d.ts +151 -0
  639. package/dist/types/protocol/appstate.d.ts +4 -49
  640. package/dist/types/protocol/auth.d.ts +2 -2
  641. package/dist/types/protocol/bot.d.ts +45 -0
  642. package/dist/types/protocol/browser.d.ts +9 -0
  643. package/dist/types/protocol/business.d.ts +21 -0
  644. package/dist/types/protocol/call.d.ts +44 -0
  645. package/dist/types/protocol/constants.d.ts +20 -3
  646. package/dist/types/protocol/defaults.d.ts +3 -0
  647. package/dist/types/protocol/email.d.ts +32 -0
  648. package/dist/types/protocol/group.d.ts +1 -1
  649. package/dist/types/protocol/index.d.ts +2 -1
  650. package/dist/types/protocol/jid.d.ts +79 -0
  651. package/dist/types/protocol/media.d.ts +21 -13
  652. package/dist/types/protocol/message.d.ts +4 -0
  653. package/dist/types/protocol/newsletter.d.ts +65 -0
  654. package/dist/types/protocol/nodes.d.ts +24 -0
  655. package/dist/types/protocol/notification.d.ts +22 -0
  656. package/dist/types/protocol/presence.d.ts +16 -0
  657. package/dist/types/protocol/status.d.ts +7 -0
  658. package/dist/types/protocol/stream.d.ts +1 -0
  659. package/dist/types/retry/codec.d.ts +5 -0
  660. package/dist/types/retry/index.d.ts +1 -1
  661. package/dist/types/retry/parse.d.ts +9 -0
  662. package/dist/types/retry/reason.d.ts +6 -1
  663. package/dist/types/retry/replay.d.ts +19 -5
  664. package/dist/types/retry/tracker.d.ts +10 -3
  665. package/dist/types/retry/types.d.ts +3 -8
  666. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +20 -0
  667. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +13 -0
  668. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +12 -3
  669. package/dist/types/signal/api/SignalMissingPreKeysSyncApi.d.ts +8 -0
  670. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +10 -0
  671. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +13 -0
  672. package/dist/types/signal/api/codec.d.ts +20 -0
  673. package/dist/types/signal/api/constants.d.ts +1 -1
  674. package/dist/types/signal/api/prekeys.d.ts +4 -0
  675. package/dist/types/signal/{crypto → attestation}/WaAdvSignature.d.ts +2 -4
  676. package/dist/types/signal/attestation/constants.d.ts +4 -0
  677. package/dist/types/signal/constants.d.ts +7 -4
  678. package/dist/types/signal/encoding.d.ts +6 -62
  679. package/dist/types/signal/group/SenderKeyChain.d.ts +2 -2
  680. package/dist/types/signal/group/SenderKeyManager.d.ts +24 -2
  681. package/dist/types/signal/group/encoding.d.ts +25 -0
  682. package/dist/types/signal/index.d.ts +4 -1
  683. package/dist/types/signal/registration/encoding.d.ts +30 -0
  684. package/dist/types/signal/registration/keygen.d.ts +10 -0
  685. package/dist/types/signal/registration/utils.d.ts +7 -1
  686. package/dist/types/signal/session/SignalProtocol.d.ts +66 -2
  687. package/dist/types/signal/session/SignalRatchet.d.ts +2 -3
  688. package/dist/types/signal/session/SignalSerializer.d.ts +2 -1
  689. package/dist/types/signal/session/SignalSession.d.ts +0 -1
  690. package/dist/types/signal/session/encoding.d.ts +28 -0
  691. package/dist/types/signal/session/resolver.d.ts +18 -2
  692. package/dist/types/signal/types.d.ts +16 -4
  693. package/dist/types/store/cache/identity.cache.d.ts +15 -0
  694. package/dist/types/store/cache/privacy-token.cache.d.ts +15 -0
  695. package/dist/types/store/cache/sender-key.cache.d.ts +18 -0
  696. package/dist/types/store/cache/session.cache.d.ts +23 -0
  697. package/dist/types/store/contracts/contact.store.d.ts +14 -0
  698. package/dist/types/store/contracts/device-list.store.d.ts +13 -0
  699. package/dist/types/store/contracts/group-metadata.store.d.ts +14 -0
  700. package/dist/types/store/contracts/identity.store.d.ts +11 -0
  701. package/dist/types/store/contracts/message-secret.store.d.ts +16 -0
  702. package/dist/types/store/contracts/message.store.d.ts +0 -2
  703. package/dist/types/store/contracts/pre-key.store.d.ts +13 -0
  704. package/dist/types/store/contracts/session.store.d.ts +14 -0
  705. package/dist/types/store/contracts/signal.store.d.ts +1 -34
  706. package/dist/types/store/createStore.d.ts +54 -2
  707. package/dist/types/store/index.d.ts +22 -13
  708. package/dist/types/store/locks/group-metadata.lock.d.ts +2 -0
  709. package/dist/types/store/locks/identity.lock.d.ts +3 -0
  710. package/dist/types/store/locks/message-secret.lock.d.ts +3 -0
  711. package/dist/types/store/locks/pre-key.lock.d.ts +3 -0
  712. package/dist/types/store/locks/session.lock.d.ts +3 -0
  713. package/dist/types/store/{providers/memory → memory}/appstate.store.d.ts +2 -2
  714. package/dist/types/store/memory/auth.store.d.ts +18 -0
  715. package/dist/types/store/{providers/memory → memory}/contact.store.d.ts +6 -1
  716. package/dist/types/store/{providers/memory → memory}/device-list.store.d.ts +15 -2
  717. package/dist/types/store/memory/group-metadata.store.d.ts +27 -0
  718. package/dist/types/store/memory/identity.store.d.ts +18 -0
  719. package/dist/types/store/memory/message-secret.store.d.ts +31 -0
  720. package/dist/types/store/{providers/memory → memory}/message.store.d.ts +1 -1
  721. package/dist/types/store/memory/pre-key.store.d.ts +23 -0
  722. package/dist/types/store/{providers/memory → memory}/privacy-token.store.d.ts +1 -1
  723. package/dist/types/store/{providers/memory → memory}/retry.store.d.ts +23 -4
  724. package/dist/types/store/{providers/memory → memory}/sender-key.store.d.ts +2 -2
  725. package/dist/types/store/memory/session.store.d.ts +21 -0
  726. package/dist/types/store/memory/signal.store.d.ts +16 -0
  727. package/dist/types/store/{providers/memory → memory}/thread.store.d.ts +1 -1
  728. package/dist/types/store/noop.store.d.ts +6 -2
  729. package/dist/types/store/types.d.ts +271 -7
  730. package/dist/types/transport/WaComms.d.ts +5 -0
  731. package/dist/types/transport/WaWebSocket.d.ts +6 -0
  732. package/dist/types/transport/binary/constants.d.ts +8 -2
  733. package/dist/types/transport/binary/decoder.d.ts +5 -0
  734. package/dist/types/transport/binary/encoder.d.ts +5 -0
  735. package/dist/types/transport/binary/tokens.d.ts +6 -6
  736. package/dist/types/transport/index.d.ts +9 -0
  737. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +11 -1
  738. package/dist/types/transport/node/WaMobileTcpSocket.d.ts +24 -0
  739. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +11 -2
  740. package/dist/types/transport/node/WaNodeTransport.d.ts +13 -0
  741. package/dist/types/transport/node/builders/abprops.d.ts +5 -0
  742. package/dist/types/transport/node/builders/account-sync.d.ts +1 -2
  743. package/dist/types/transport/node/builders/bot.d.ts +4 -0
  744. package/dist/types/transport/node/builders/business.d.ts +21 -4
  745. package/dist/types/transport/node/builders/chatstate.d.ts +11 -0
  746. package/dist/types/transport/node/builders/community.d.ts +17 -0
  747. package/dist/types/transport/node/builders/device.d.ts +2 -0
  748. package/dist/types/transport/node/builders/email.d.ts +11 -0
  749. package/dist/types/transport/node/builders/group.d.ts +44 -2
  750. package/dist/types/transport/node/builders/message.d.ts +11 -6
  751. package/dist/types/transport/node/builders/newsletter.d.ts +73 -0
  752. package/dist/types/transport/node/builders/offline.d.ts +2 -0
  753. package/dist/types/transport/node/builders/passive.d.ts +3 -0
  754. package/dist/types/transport/node/builders/prekeys.d.ts +4 -3
  755. package/dist/types/transport/node/builders/presence.d.ts +13 -0
  756. package/dist/types/transport/node/builders/profile.d.ts +3 -0
  757. package/dist/types/transport/node/builders/tos.d.ts +12 -0
  758. package/dist/types/transport/node/builders/usync.d.ts +16 -0
  759. package/dist/types/transport/node/helpers.d.ts +3 -1
  760. package/dist/types/transport/node/mex/argo-decoder.d.ts +11 -0
  761. package/dist/types/transport/node/mex/client.d.ts +29 -0
  762. package/dist/types/transport/node/query.d.ts +19 -1
  763. package/dist/types/transport/node/usync.d.ts +3 -0
  764. package/dist/types/transport/noise/WaMobileClientPayload.d.ts +34 -0
  765. package/dist/types/transport/noise/WaNoiseCert.d.ts +12 -1
  766. package/dist/types/transport/noise/WaNoiseHandshake.d.ts +12 -6
  767. package/dist/types/transport/noise/WaNoiseSession.d.ts +1 -1
  768. package/dist/types/transport/noise/WaNoiseSocket.d.ts +12 -6
  769. package/dist/types/transport/noise/constants.d.ts +4 -5
  770. package/dist/types/transport/proxy.d.ts +5 -0
  771. package/dist/types/transport/types.d.ts +15 -0
  772. package/dist/types/transport/wa-web-version-fetcher.d.ts +44 -0
  773. package/dist/types/util/async.d.ts +4 -0
  774. package/dist/types/util/bytes.d.ts +36 -1
  775. package/dist/types/util/clock.d.ts +6 -0
  776. package/dist/types/util/coercion.d.ts +25 -0
  777. package/dist/types/util/collections.d.ts +8 -0
  778. package/dist/types/util/index.d.ts +2 -2
  779. package/dist/types/util/primitives.d.ts +11 -0
  780. package/dist/types/util/runtime.d.ts +5 -0
  781. package/dist/types/version-spec.d.ts +1 -0
  782. package/dist/util/async.js +4 -0
  783. package/dist/util/bytes.js +37 -2
  784. package/dist/util/clock.js +18 -0
  785. package/dist/util/coercion.js +48 -3
  786. package/dist/util/collections.js +12 -0
  787. package/dist/util/index.js +7 -1
  788. package/dist/util/primitives.js +20 -0
  789. package/dist/util/runtime.js +5 -0
  790. package/dist/version-spec.js +5 -0
  791. package/package.json +37 -11
  792. package/spec/appstate/index.d.ts +188 -0
  793. package/spec/appstate/index.js +850 -0
  794. package/spec/mex/index.d.ts +4172 -0
  795. package/spec/mex/index.js +261 -0
  796. package/spec/proto/index.d.ts +16305 -0
  797. package/spec/proto/index.js +1 -0
  798. package/spec/version/index.d.ts +4 -0
  799. package/spec/version/index.js +9 -0
  800. package/spec/version/version.json +3 -0
  801. package/dist/auth/flow/WaAuthCredentialsFlow.js +0 -130
  802. package/dist/auth/pairing/WaPairingCodeCrypto.js +0 -77
  803. package/dist/auth/pairing/constants.js +0 -5
  804. package/dist/client/connection/WaKeyShareCoordinator.js +0 -63
  805. package/dist/client/events/chat.js +0 -227
  806. package/dist/client/incoming.js +0 -269
  807. package/dist/client/mailbox.js +0 -50
  808. package/dist/client/messages.js +0 -228
  809. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +0 -125
  810. package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +0 -73
  811. package/dist/esm/auth/pairing/constants.js +0 -2
  812. package/dist/esm/client/connection/WaKeyShareCoordinator.js +0 -59
  813. package/dist/esm/client/events/chat.js +0 -224
  814. package/dist/esm/client/incoming.js +0 -260
  815. package/dist/esm/client/mailbox.js +0 -47
  816. package/dist/esm/client/messages.js +0 -224
  817. package/dist/esm/media/WaMediaCrypto.js +0 -304
  818. package/dist/esm/message/addon-crypto.js +0 -59
  819. package/dist/esm/message/incoming.js +0 -325
  820. package/dist/esm/message/phash.js +0 -27
  821. package/dist/esm/signal/crypto/WaAdvSignature.js +0 -64
  822. package/dist/esm/store/locks/participants.lock.js +0 -20
  823. package/dist/esm/store/providers/memory/contact.store.js +0 -28
  824. package/dist/esm/store/providers/memory/device-list.store.js +0 -64
  825. package/dist/esm/store/providers/memory/signal.store.js +0 -199
  826. package/dist/esm/transport/node/builders/index.js +0 -11
  827. package/dist/media/WaMediaCrypto.js +0 -308
  828. package/dist/message/addon-crypto.js +0 -65
  829. package/dist/message/phash.js +0 -30
  830. package/dist/signal/crypto/WaAdvSignature.js +0 -76
  831. package/dist/store/locks/participants.lock.js +0 -23
  832. package/dist/store/providers/memory/contact.store.js +0 -32
  833. package/dist/store/providers/memory/device-list.store.js +0 -68
  834. package/dist/store/providers/memory/signal.store.js +0 -203
  835. package/dist/transport/node/builders/index.js +0 -51
  836. package/dist/types/appstate/WaAppStateSyncClient.d.ts +0 -66
  837. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +0 -14
  838. package/dist/types/auth/pairing/constants.d.ts +0 -2
  839. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +0 -14
  840. package/dist/types/client/events/chat.d.ts +0 -3
  841. package/dist/types/client/history-sync.d.ts +0 -20
  842. package/dist/types/client/incoming.d.ts +0 -37
  843. package/dist/types/client/mailbox.d.ts +0 -10
  844. package/dist/types/client/messages.d.ts +0 -16
  845. package/dist/types/client/messaging/participants.d.ts +0 -13
  846. package/dist/types/media/WaMediaCrypto.d.ts +0 -13
  847. package/dist/types/media/conn.d.ts +0 -3
  848. package/dist/types/message/addon-crypto.d.ts +0 -25
  849. package/dist/types/message/content.d.ts +0 -12
  850. package/dist/types/message/incoming.d.ts +0 -18
  851. package/dist/types/signal/crypto/constants.d.ts +0 -5
  852. package/dist/types/store/contracts/participants.store.d.ts +0 -13
  853. package/dist/types/store/locks/participants.lock.d.ts +0 -2
  854. package/dist/types/store/providers/memory/participants.store.d.ts +0 -17
  855. package/dist/types/store/providers/memory/signal.store.d.ts +0 -58
  856. package/dist/types/transport/node/builders/index.d.ts +0 -11
  857. package/proto/index.d.ts +0 -10903
  858. package/proto/index.js +0 -1
  859. /package/dist/{store/contracts/participants.store.js → client/newsletter/types.js} +0 -0
  860. /package/dist/esm/{store/contracts/participants.store.js → client/newsletter/types.js} +0 -0
  861. /package/dist/esm/message/{device-sent.js → encode/device-sent.js} +0 -0
  862. /package/dist/message/{device-sent.js → encode/device-sent.js} +0 -0
  863. /package/dist/types/message/{padding.d.ts → encode/padding.d.ts} +0 -0
@@ -1,17 +1,18 @@
1
1
  import { EventEmitter } from 'node:events';
2
- import { downloadExternalBlobReference } from '../appstate/utils.js';
3
- import { parseChatEventFromAppStateMutation } from './events/chat.js';
4
- import { processHistorySyncNotification } from './history-sync.js';
5
- import { persistIncomingMailboxEntities } from './mailbox.js';
2
+ import { createIgnoreKeyFilter, validateIgnoreKey } from './messaging/ignore-key.js';
3
+ import { runHistorySyncNotification } from './persistence/history-sync.js';
4
+ import { persistIncomingMailboxEntities } from './persistence/mailbox.js';
6
5
  import { WriteBehindPersistence } from './persistence/WriteBehindPersistence.js';
7
6
  import { buildWaClientDependencies, resolveWaClientBase } from './WaClientFactory.js';
8
7
  import { ConsoleLogger } from '../infra/log/ConsoleLogger.js';
9
8
  import { proto } from '../proto.js';
10
- import { WA_APP_STATE_COLLECTION_STATES, WA_DEFAULTS } from '../protocol/constants.js';
11
- import { normalizeDeviceJid, parsePhoneJid, toUserJid } from '../protocol/jid.js';
12
- import { queryWithContext as queryNodeWithContext } from '../transport/node/query.js';
13
- import { decodeProtoBytes } from '../util/bytes.js';
14
- import { bytesToHex } from '../util/bytes.js';
9
+ import { WA_DEFAULTS, WA_MESSAGE_TYPES } from '../protocol/constants.js';
10
+ import { normalizeDeviceJid } from '../protocol/jid.js';
11
+ import { WA_DISCONNECT_REASONS, WA_LOGOUT_REASONS } from '../protocol/stream.js';
12
+ import { NOOP_MESSAGE_SECRET_STORE } from '../store/noop.store.js';
13
+ import { buildRemoveCompanionDeviceIq } from '../transport/node/builders/device.js';
14
+ import { assertIqResult, queryWithContext as queryNodeWithContext } from '../transport/node/query.js';
15
+ import { fetchLatestWaWebVersion } from '../transport/wa-web-version-fetcher.js';
15
16
  import { toError } from '../util/primitives.js';
16
17
  const SYNC_RELATED_PROTOCOL_TYPES = new Set([
17
18
  proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_REQUEST,
@@ -19,9 +20,59 @@ const SYNC_RELATED_PROTOCOL_TYPES = new Set([
19
20
  proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE,
20
21
  proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_RESPONSE_MESSAGE
21
22
  ]);
22
- const WA_APP_STATE_KEY_SHARE_WAIT_TIMEOUT_MS = 15000;
23
- const WA_APP_STATE_KEY_SHARE_MAX_RETRIES = 2;
23
+ /**
24
+ * Top-level WhatsApp client. Owns the transport, auth, signal, and per-feature
25
+ * coordinators (accessible via getters such as {@link message}, {@link group},
26
+ * {@link newsletter}, etc.) and re-emits every {@link WaClientEventMap} event.
27
+ *
28
+ * Lifecycle: construct with {@link WaClientOptions}, call {@link connect} to
29
+ * open the socket, react to `connection`/`auth_qr`/`auth_pairing_code` events,
30
+ * then use the coordinator getters to drive the session. Call {@link disconnect}
31
+ * to shut down cleanly or {@link logout} to remove the companion device.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * import { createPinoLogger, createStore, WaClient } from '../index.js'
36
+ * import { createSqliteStore } from '@zapo-js/store-sqlite'
37
+ *
38
+ * const store = createStore({
39
+ * backends: { sqlite: createSqliteStore({ path: '.auth/state.sqlite' }) },
40
+ * providers: {
41
+ * auth: 'sqlite',
42
+ * signal: 'sqlite',
43
+ * preKey: 'sqlite',
44
+ * session: 'sqlite',
45
+ * identity: 'sqlite',
46
+ * senderKey: 'sqlite',
47
+ * appState: 'sqlite',
48
+ * privacyToken: 'sqlite',
49
+ * messages: 'sqlite',
50
+ * threads: 'sqlite',
51
+ * contacts: 'sqlite'
52
+ * }
53
+ * })
54
+ *
55
+ * const client = new WaClient(
56
+ * { store, sessionId: 'default' },
57
+ * await createPinoLogger({ level: 'info', pretty: true })
58
+ * )
59
+ *
60
+ * client.on('auth_qr', ({ qr, ttlMs }) => console.log('scan:', qr, ttlMs))
61
+ * client.on('connection', (event) => console.log('connection', event))
62
+ * client.on('message', async (event) => {
63
+ * if (event.message?.conversation === 'ping') {
64
+ * await client.message.send(event.chatJid!, 'pong')
65
+ * }
66
+ * })
67
+ *
68
+ * await client.connect()
69
+ * ```
70
+ */
24
71
  export class WaClient extends EventEmitter {
72
+ /**
73
+ * @param options Client configuration (store, transport, addons, history...).
74
+ * @param logger Optional structured logger. Defaults to a `ConsoleLogger('info')`.
75
+ */
25
76
  constructor(options, logger = new ConsoleLogger('info')) {
26
77
  super();
27
78
  this.connectPromise = null;
@@ -31,29 +82,26 @@ export class WaClient extends EventEmitter {
31
82
  const base = resolveWaClientBase(options, logger);
32
83
  this.options = base.options;
33
84
  this.logger = base.logger;
34
- this.appStateStore = base.sessionStore.appState;
35
- this.contactStore = base.sessionStore.contacts;
36
- this.messageStore = base.sessionStore.messages;
37
- this.participantsStore = base.sessionStore.participants;
38
- this.privacyTokenStore = base.sessionStore.privacyToken;
39
- this.deviceListStore = base.sessionStore.deviceList;
40
- this.retryStore = base.sessionStore.retry;
41
- this.signalStore = base.sessionStore.signal;
42
- this.senderKeyStore = base.sessionStore.senderKey;
43
- this.threadStore = base.sessionStore.threads;
85
+ this.stores = base.sessionStore;
44
86
  this.writeBehind = new WriteBehindPersistence({
45
- messageStore: this.messageStore,
46
- threadStore: this.threadStore,
47
- contactStore: this.contactStore
87
+ messageStore: this.stores.messages,
88
+ threadStore: this.stores.threads,
89
+ contactStore: this.stores.contacts
48
90
  }, this.logger, this.options.writeBehind);
91
+ if (this.options.addons?.autoDecrypt !== false &&
92
+ this.stores.messageSecret === NOOP_MESSAGE_SECRET_STORE) {
93
+ this.logger.warn('addons.autoDecrypt is on (default) but messageSecret cache is noop – ' +
94
+ 'addon decryption will only work if secrets are in the message store. ' +
95
+ 'Set addons.autoDecrypt: false to silence this warning.');
96
+ }
49
97
  const dependencies = buildWaClientDependencies({
50
98
  base,
51
99
  runtime: {
52
- sendNode: (node) => this.sendNode(node),
53
- query: (node, timeoutMs) => this.query(node, timeoutMs),
100
+ sendNode: (node) => this.deps.lowLevelCoordinator.sendNode(node),
101
+ query: (node, timeoutMs, options) => this.deps.lowLevelCoordinator.query(node, timeoutMs, options),
54
102
  queryWithContext: this.queryWithContext.bind(this),
55
- syncAppState: () => this.syncAppState().then(() => { }),
56
- syncAppStateWithOptions: (syncOptions) => this.syncAppState(syncOptions),
103
+ syncAppState: () => this.deps.chatCoordinator.sync().then(() => { }),
104
+ syncAppStateWithOptions: (syncOptions) => this.deps.chatCoordinator.sync(syncOptions),
57
105
  emitEvent: this.emit.bind(this),
58
106
  handleIncomingMessageEvent: this.handleIncomingMessageEvent.bind(this),
59
107
  handleError: this.handleError.bind(this),
@@ -61,11 +109,50 @@ export class WaClient extends EventEmitter {
61
109
  clearStoredState: this.clearStoredState.bind(this),
62
110
  resumeIncomingEvents: () => {
63
111
  this.acceptingIncomingEvents = true;
64
- }
112
+ },
113
+ subscribeProtocolMessage: (handler) => {
114
+ this.on('message_protocol', handler);
115
+ return () => {
116
+ this.off('message_protocol', handler);
117
+ };
118
+ },
119
+ persistContact: (record) => this.writeBehind.persistContact(record)
65
120
  }
66
121
  });
67
- Object.assign(this, dependencies);
122
+ this.deps = dependencies;
123
+ this.appStateSync = dependencies.appStateSync;
124
+ this.mediaTransfer = dependencies.mediaTransfer;
68
125
  this.bindNodeTransportEvents();
126
+ this.on('connection', (event) => {
127
+ if (event.status !== 'close')
128
+ return;
129
+ if (!this.options.recoverFromClientTooOld)
130
+ return;
131
+ if (event.reason !== WA_DISCONNECT_REASONS.FAILURE_CLIENT_TOO_OLD)
132
+ return;
133
+ this.logger.warn('wa rejected the connect with client_too_old: the zapo default WA Web version is outdated. ' +
134
+ 'Auto-recovering by fetching the current version from web.whatsapp.com – ' +
135
+ 'please upgrade zapo so the shipped default catches up.');
136
+ void this.runClientTooOldRecover();
137
+ });
138
+ }
139
+ async runClientTooOldRecover() {
140
+ try {
141
+ if (this.connectPromise) {
142
+ await this.connectPromise.catch(() => undefined);
143
+ }
144
+ const latest = await fetchLatestWaWebVersion();
145
+ this.logger.info('client_too_old auto-recover: reconnecting', {
146
+ version: latest.version
147
+ });
148
+ this.deps.authClient.setNextConnectVersion(latest.version);
149
+ await this.connect();
150
+ }
151
+ catch (error) {
152
+ this.logger.warn('client_too_old auto-recover failed', {
153
+ message: toError(error).message
154
+ });
155
+ }
69
156
  }
70
157
  on(event, listener) {
71
158
  return super.on(event, listener);
@@ -79,56 +166,36 @@ export class WaClient extends EventEmitter {
79
166
  emit(event, ...args) {
80
167
  return super.emit(event, ...args);
81
168
  }
169
+ /**
170
+ * Returns the current auth state snapshot (credentials, registration,
171
+ * connection flag) – useful for resuming or inspecting the client.
172
+ */
82
173
  getState() {
83
- const connected = this.connectionManager.isConnected();
174
+ const connected = this.deps.connectionManager.isConnected();
84
175
  this.logger.trace('wa client state requested', { connected });
85
- return this.authClient.getState(connected);
176
+ return this.deps.authClient.getState(connected);
86
177
  }
178
+ /**
179
+ * Returns the credentials persisted for the current session, or `null` if
180
+ * the client has not been paired yet.
181
+ */
87
182
  getCredentials() {
88
- return this.authClient.getCurrentCredentials();
183
+ return this.deps.authClient.getCurrentCredentials();
89
184
  }
185
+ /**
186
+ * Returns the measured skew between the local clock and the server, in
187
+ * milliseconds, or `null` if no handshake has completed yet.
188
+ */
90
189
  getClockSkewMs() {
91
- return this.connectionManager.getClockSkewMs();
92
- }
93
- async sendNode(node) {
94
- try {
95
- await this.nodeOrchestrator.sendNode(node);
96
- }
97
- catch (error) {
98
- const normalized = toError(error);
99
- if (this.receiptQueue.shouldQueue(node, normalized)) {
100
- this.receiptQueue.enqueue(node);
101
- this.logger.warn('queued dangling receipt after send failure', {
102
- id: node.attrs.id,
103
- to: node.attrs.to,
104
- message: normalized.message,
105
- queueSize: this.receiptQueue.size()
106
- });
107
- return;
108
- }
109
- throw normalized;
110
- }
111
- }
112
- async query(node, timeoutMs = this.options.iqTimeoutMs ?? WA_DEFAULTS.IQ_TIMEOUT_MS) {
113
- if (!this.connectionManager.isConnected()) {
114
- throw new Error('client is not connected');
115
- }
116
- this.logger.debug('wa client query', { tag: node.tag, id: node.attrs.id, timeoutMs });
117
- return this.nodeOrchestrator.query(node, timeoutMs);
118
- }
119
- registerIncomingHandler(registration) {
120
- return this.incomingNode.registerIncomingHandler(registration);
121
- }
122
- unregisterIncomingHandler(registration) {
123
- return this.incomingNode.unregisterIncomingHandler(registration);
190
+ return this.deps.connectionManager.getClockSkewMs();
124
191
  }
125
192
  bindNodeTransportEvents() {
126
- this.nodeTransport.on('frame_in', (frame) => this.emit('transport_frame_in', { frame }));
127
- this.nodeTransport.on('frame_out', (frame) => this.emit('transport_frame_out', { frame }));
128
- this.nodeTransport.on('node_in', (node, frame) => this.emit('transport_node_in', { node, frame }));
129
- this.nodeTransport.on('node_out', (node, frame) => this.emit('transport_node_out', { node, frame }));
130
- this.nodeTransport.on('decode_error', (error, frame) => {
131
- this.emit('transport_decode_error', { error, frame });
193
+ this.deps.nodeTransport.on('frame_in', (frame) => this.emit('debug_transport_frame_in', { frame }));
194
+ this.deps.nodeTransport.on('frame_out', (frame) => this.emit('debug_transport_frame_out', { frame }));
195
+ this.deps.nodeTransport.on('node_in', (node, frame) => this.emit('debug_transport_node_in', { node, frame }));
196
+ this.deps.nodeTransport.on('node_out', (node, frame) => this.emit('debug_transport_node_out', { node, frame }));
197
+ this.deps.nodeTransport.on('decode_error', (error, frame) => {
198
+ this.emit('debug_transport_decode_error', { error, frame });
132
199
  this.handleError(error);
133
200
  });
134
201
  }
@@ -141,8 +208,27 @@ export class WaClient extends EventEmitter {
141
208
  void persistIncomingMailboxEntities({
142
209
  logger: this.logger,
143
210
  writeBehind: this.writeBehind,
211
+ messageSecretStore: this.stores.messageSecret,
144
212
  event
145
213
  });
214
+ if (this.options.addons?.autoDecrypt !== false && event.message) {
215
+ void this.deps.messageCoordinator.tryDecryptAddon(event).catch((err) => {
216
+ this.logger.warn('addon auto-decrypt failed', {
217
+ id: event.key.id,
218
+ message: toError(err).message
219
+ });
220
+ });
221
+ }
222
+ // Decode unconditionally – chunks whose parent prompt we never sent
223
+ // are skipped by the secret-store lookup downstream.
224
+ if (event.message) {
225
+ void this.deps.botCoordinator.tryDecryptChunk(event).catch((err) => {
226
+ this.logger.warn('bot chunk auto-decrypt failed', {
227
+ id: event.key.id,
228
+ message: toError(err).message
229
+ });
230
+ });
231
+ }
146
232
  const protocolMessage = event.message?.protocolMessage;
147
233
  if (!protocolMessage) {
148
234
  return;
@@ -155,36 +241,62 @@ export class WaClient extends EventEmitter {
155
241
  const protocolType = protocolMessage.type;
156
242
  if (protocolType === null || protocolType === undefined) {
157
243
  this.logger.debug('incoming protocol message without type', {
158
- id: event.stanzaId,
159
- from: event.chatJid
244
+ id: event.key.id,
245
+ from: event.key.remoteJid
160
246
  });
161
247
  return;
162
248
  }
163
249
  if (protocolType === proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_REQUEST) {
164
- await this.handleIncomingAppStateSyncKeyRequest(event, protocolMessage);
250
+ await this.appStateSync.handleIncomingKeyRequest(event.key, protocolMessage);
165
251
  return;
166
252
  }
167
253
  if (protocolType === proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_SHARE) {
168
- await this.handleIncomingAppStateSyncKeyShare(event, protocolMessage);
254
+ await this.appStateSync.handleIncomingKeyShare(event.key, protocolMessage);
169
255
  return;
170
256
  }
171
257
  if (protocolType === proto.Message.ProtocolMessage.Type.HISTORY_SYNC_NOTIFICATION) {
172
- if (this.options.history?.enabled && protocolMessage.historySyncNotification) {
173
- await this.handleHistorySyncNotification(protocolMessage.historySyncNotification);
258
+ if (this.options.history?.enabled !== false &&
259
+ protocolMessage.historySyncNotification) {
260
+ const peerRemoteJid = event.key.remoteJid;
261
+ const peerStanzaId = event.key.id;
262
+ await runHistorySyncNotification({
263
+ logger: this.logger,
264
+ mediaTransfer: this.mediaTransfer,
265
+ writeBehind: this.writeBehind,
266
+ emitEvent: this.emit.bind(this),
267
+ onPrivacyTokens: (conversations) => this.deps.trustedContactToken.hydrateFromHistorySync(conversations),
268
+ onNctSalt: (salt) => this.deps.trustedContactToken.hydrateNctSaltFromHistorySync(salt),
269
+ onProcessed: peerRemoteJid && peerStanzaId
270
+ ? async () => {
271
+ try {
272
+ await this.message.sendReceipt(peerRemoteJid, peerStanzaId, {
273
+ type: WA_MESSAGE_TYPES.RECEIPT_TYPE_HISTORY_SYNC
274
+ });
275
+ }
276
+ catch (err) {
277
+ this.logger.warn('failed to send hist_sync receipt', {
278
+ id: peerStanzaId,
279
+ to: peerRemoteJid,
280
+ message: toError(err).message
281
+ });
282
+ }
283
+ }
284
+ : undefined
285
+ }, protocolMessage.historySyncNotification);
174
286
  }
175
287
  return;
176
288
  }
177
289
  if (SYNC_RELATED_PROTOCOL_TYPES.has(protocolType)) {
178
290
  this.logger.info('incoming sync-related protocol message', {
179
- id: event.stanzaId,
180
- from: event.chatJid,
291
+ id: event.key.id,
292
+ from: event.key.remoteJid,
181
293
  protocolType
182
294
  });
183
295
  return;
184
296
  }
185
297
  this.logger.debug('incoming protocol message received', {
186
- id: event.stanzaId,
187
- from: event.chatJid,
298
+ id: event.key.id,
299
+ from: event.key.remoteJid,
188
300
  protocolType
189
301
  });
190
302
  }
@@ -192,199 +304,60 @@ export class WaClient extends EventEmitter {
192
304
  this.leaveIncomingHandler();
193
305
  }
194
306
  }
195
- async handleIncomingAppStateSyncKeyShare(event, protocolMessage) {
196
- const share = protocolMessage.appStateSyncKeyShare;
197
- if (!share) {
198
- this.logger.warn('incoming app-state key share protocol message without payload', {
199
- id: event.stanzaId,
200
- from: event.chatJid
201
- });
202
- return;
203
- }
204
- try {
205
- const imported = await this.appStateSync.importSyncKeyShare(share);
206
- this.logger.info('imported app-state sync key share from protocol message', {
207
- id: event.stanzaId,
208
- from: event.chatJid,
209
- imported
210
- });
211
- if (imported > 0) {
212
- const hadWaiters = this.keyShareCoordinator.hasWaiters();
213
- this.keyShareCoordinator.notifyReceived();
214
- if (hadWaiters) {
215
- this.logger.debug('app-state key share imported and waiters released', {
216
- id: event.stanzaId,
217
- from: event.chatJid,
218
- imported
219
- });
220
- return;
221
- }
222
- void this.syncAppState().catch((error) => {
223
- this.logger.warn('failed to sync app-state after key share import', {
224
- id: event.stanzaId,
225
- from: event.chatJid,
226
- message: toError(error).message
227
- });
228
- });
229
- }
230
- }
231
- catch (error) {
232
- this.logger.warn('failed to import app-state sync key share from protocol message', {
233
- id: event.stanzaId,
234
- from: event.chatJid,
235
- message: toError(error).message
236
- });
237
- }
238
- }
239
- async handleIncomingAppStateSyncKeyRequest(event, protocolMessage) {
240
- const request = protocolMessage.appStateSyncKeyRequest;
241
- if (!request) {
242
- this.logger.warn('incoming app-state key request protocol message without payload', {
243
- id: event.stanzaId,
244
- from: event.chatJid
245
- });
246
- return;
247
- }
248
- const requesterRaw = event.senderJid ?? event.chatJid;
249
- if (!requesterRaw) {
250
- this.logger.warn('incoming app-state key request missing sender jid', {
251
- id: event.stanzaId
252
- });
253
- return;
254
- }
255
- let requesterDeviceJid;
256
- try {
257
- requesterDeviceJid = normalizeDeviceJid(requesterRaw);
258
- }
259
- catch (error) {
260
- this.logger.warn('incoming app-state key request has malformed sender jid', {
261
- id: event.stanzaId,
262
- from: requesterRaw,
263
- message: toError(error).message
264
- });
265
- return;
266
- }
267
- if (!this.isOwnAccountDeviceJid(requesterDeviceJid)) {
268
- this.logger.warn('incoming app-state key request ignored: sender is not own account', {
269
- id: event.stanzaId,
270
- from: requesterDeviceJid
271
- });
272
- return;
273
- }
274
- const requestedKeyIds = this.extractAppStateSyncKeyRequestIds(request);
275
- if (requestedKeyIds.length === 0) {
276
- this.logger.warn('incoming app-state key request has no valid key ids', {
277
- id: event.stanzaId,
278
- from: requesterDeviceJid
279
- });
280
- return;
281
- }
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
- }
294
- try {
295
- await this.messageDispatch.sendAppStateSyncKeyShare(requesterDeviceJid, availableKeys, missingKeyIds);
296
- this.logger.info('responded to app-state key request', {
297
- id: event.stanzaId,
298
- to: requesterDeviceJid,
299
- requested: requestedKeyIds.length,
300
- shared: availableKeys.length,
301
- missing: missingKeyIds.length
302
- });
303
- }
304
- catch (error) {
305
- this.logger.warn('failed to respond to app-state key request', {
306
- id: event.stanzaId,
307
- to: requesterDeviceJid,
308
- requested: requestedKeyIds.length,
309
- shared: availableKeys.length,
310
- missing: missingKeyIds.length,
311
- message: toError(error).message
312
- });
313
- }
314
- }
315
- extractAppStateSyncKeyRequestIds(request) {
316
- const deduped = new Map();
317
- for (const key of request.keyIds ?? []) {
318
- try {
319
- const keyId = decodeProtoBytes(key.keyId, 'appStateSyncKeyRequest.keyIds[].keyId');
320
- const keyHex = bytesToHex(keyId);
321
- if (deduped.has(keyHex)) {
322
- continue;
323
- }
324
- deduped.set(keyHex, keyId);
325
- }
326
- catch (error) {
327
- this.logger.trace('ignoring malformed app-state key id request entry', {
328
- message: toError(error).message
329
- });
330
- }
331
- }
332
- return [...deduped.values()];
333
- }
334
- isOwnAccountDeviceJid(candidateJid) {
335
- const credentials = this.authClient.getCurrentCredentials();
336
- if (!credentials) {
337
- return false;
338
- }
339
- const candidateUser = toUserJid(candidateJid);
340
- return ((!!credentials.meJid && toUserJid(credentials.meJid) === candidateUser) ||
341
- (!!credentials.meLid && toUserJid(credentials.meLid) === candidateUser));
342
- }
343
- async handleHistorySyncNotification(notification) {
344
- try {
345
- await processHistorySyncNotification({
346
- logger: this.logger,
347
- mediaTransfer: this.mediaTransfer,
348
- writeBehind: this.writeBehind,
349
- emitEvent: this.emit.bind(this),
350
- onPrivacyTokens: (conversations) => this.trustedContactToken.hydrateFromHistorySync(conversations),
351
- onNctSalt: (salt) => this.trustedContactToken.hydrateNctSaltFromHistorySync(salt)
352
- }, notification);
353
- }
354
- catch (error) {
355
- this.logger.warn('failed to process history sync notification', {
356
- syncType: notification.syncType,
357
- chunkOrder: notification.chunkOrder,
358
- message: toError(error).message
359
- });
360
- }
361
- }
362
- async queryWithContext(context, node, timeoutMs = this.options.iqTimeoutMs ?? WA_DEFAULTS.IQ_TIMEOUT_MS, contextData = {}) {
363
- return queryNodeWithContext(async (queryNode, queryTimeoutMs) => this.query(queryNode, queryTimeoutMs), this.logger, context, node, timeoutMs, contextData);
307
+ async queryWithContext(context, node, timeoutMs = this.options.iqTimeoutMs ?? WA_DEFAULTS.IQ_TIMEOUT_MS, contextData = {}, options = {}) {
308
+ return queryNodeWithContext(async (queryNode, queryTimeoutMs) => this.deps.lowLevelCoordinator.query(queryNode, queryTimeoutMs, options), this.logger, context, node, timeoutMs, contextData);
364
309
  }
365
310
  async handleIncomingFrame(frame) {
366
311
  try {
367
- await this.nodeTransport.dispatchIncomingFrame(frame, async (node) => this.incomingNode.handleIncomingNode(node));
312
+ await this.deps.nodeTransport.dispatchIncomingFrame(frame, async (node) => this.deps.incomingNode.handleIncomingNode(node));
368
313
  }
369
314
  catch (error) {
370
315
  this.handleError(toError(error));
371
316
  }
372
317
  }
318
+ /**
319
+ * Opens the transport and runs the noise/auth handshake. If a connection
320
+ * is already in flight, the in-flight promise is reused. Resolves once the
321
+ * client is fully ready; pairing prompts are surfaced via the `auth_qr`
322
+ * and `auth_pairing_code` events while this awaits.
323
+ *
324
+ * **First-time pairing:** the promise stays pending until the user scans a
325
+ * QR or types the pairing code. Subscribe to `auth_qr` / `auth_pairing_code`
326
+ * *before* awaiting – they fire while `connect()` is still running.
327
+ *
328
+ * @example
329
+ * ```ts
330
+ * // QR pairing (default – works headless)
331
+ * client.on('auth_qr', ({ qr }) => console.log('scan:', qr))
332
+ * client.on('auth_paired', ({ credentials }) => console.log('paired:', credentials.meJid))
333
+ * await client.connect()
334
+ *
335
+ * // Link-code pairing – call requestPairingCode while connect() is running
336
+ * void client.connect()
337
+ * await new Promise((r) => client.once('auth_pairing_required', r))
338
+ * const code = await client.auth.requestPairingCode('5511999999999')
339
+ * console.log('enter code on phone:', code)
340
+ * ```
341
+ */
373
342
  async connect() {
374
343
  if (this.connectPromise) {
375
344
  this.logger.trace('wa client connect already in-flight');
376
345
  return this.connectPromise;
377
346
  }
347
+ this.writeBehind.restart();
378
348
  this.acceptingIncomingEvents = true;
379
- this.connectPromise = this.connectionManager
349
+ this.connectPromise = this.deps.connectionManager
380
350
  .connect((frame) => this.handleIncomingFrame(frame))
381
351
  .then(() => {
352
+ if (!this.deps.authClient.getCurrentCredentials()?.meJid) {
353
+ return;
354
+ }
382
355
  this.emit('connection', {
383
356
  status: 'open',
384
357
  reason: 'connected',
385
358
  code: null,
386
359
  isLogout: false,
387
- isNewLogin: this.connectionManager.wasNewLogin()
360
+ isNewLogin: false
388
361
  });
389
362
  })
390
363
  .finally(() => {
@@ -392,6 +365,14 @@ export class WaClient extends EventEmitter {
392
365
  });
393
366
  return this.connectPromise;
394
367
  }
368
+ /**
369
+ * Closes the transport gracefully: pauses incoming events, flushes the
370
+ * write-behind persistence queue, and emits a `connection` close event
371
+ * with reason `client_disconnected`. Does not clear stored credentials -
372
+ * call {@link connect} again to resume the same session. There is no
373
+ * built-in auto-reconnect; subscribe to `connection: { status: 'close' }`
374
+ * and decide your own backoff.
375
+ */
395
376
  async disconnect() {
396
377
  await this.pauseIncomingEventsAndWaitDrain();
397
378
  const writeBehindFlush = await this.writeBehind.flush(this.options.writeBehind?.flushTimeoutMs);
@@ -400,8 +381,7 @@ export class WaClient extends EventEmitter {
400
381
  remaining: writeBehindFlush.remaining
401
382
  });
402
383
  }
403
- this.keyShareCoordinator.notifyDisconnected();
404
- await this.connectionManager.disconnect();
384
+ await this.deps.connectionManager.disconnect();
405
385
  this.emit('connection', {
406
386
  status: 'close',
407
387
  reason: 'client_disconnected',
@@ -410,207 +390,122 @@ export class WaClient extends EventEmitter {
410
390
  isNewLogin: false
411
391
  });
412
392
  }
413
- async requestPairingCode(phoneNumber, shouldShowPushNotification = false) {
414
- if (!this.connectionManager.isConnected() || !this.authClient.getCurrentCredentials()) {
415
- throw new Error('client is not connected');
416
- }
417
- this.logger.debug('wa client request pairing code');
418
- return this.authClient.requestPairingCode(phoneNumber, shouldShowPushNotification);
393
+ /**
394
+ * Drops matching inbound stanzas before any handler runs. Server still
395
+ * gets the ack so it stops re-delivering. Returns an `unregister` function.
396
+ *
397
+ * Accepts either a declarative descriptor or a predicate. The descriptor
398
+ * matches by `remoteJid`/`fromMe`/`id`/`participant` (PN ↔ LID alt-attrs
399
+ * resolved automatically) and throws when no match field is given or
400
+ * arrays are empty. The predicate receives a parsed
401
+ * {@link WaIgnoreKeyContext} and returns `true` to drop the stanza.
402
+ *
403
+ * @example
404
+ * ```ts
405
+ * client.ignoreKey({ remoteJid: spammerJid })
406
+ * client.ignoreKey({ fromMe: true, only: ['message'] })
407
+ * client.ignoreKey((m) => m.kind === 'message' && isGroupJid(m.remoteJid ?? ''))
408
+ * ```
409
+ */
410
+ ignoreKey(input) {
411
+ if (typeof input !== 'function') {
412
+ validateIgnoreKey(input);
413
+ }
414
+ const filter = createIgnoreKeyFilter(input, () => this.deps.authClient.getCurrentCredentials()?.meJid);
415
+ return this.deps.incomingNode.registerIncomingStanzaFilter(filter);
416
+ }
417
+ /** Auth client: pairing, credentials, registration state. */
418
+ get auth() {
419
+ return this.deps.authClient;
420
+ }
421
+ /** Message coordinator: send/receive, receipts, addons, media download. */
422
+ get message() {
423
+ return this.deps.messageCoordinator;
424
+ }
425
+ /** Presence coordinator: own/peer presence subscriptions. */
426
+ get presence() {
427
+ return this.deps.presenceCoordinator;
428
+ }
429
+ /** Low-level coordinator: raw node send/query escape hatch. */
430
+ get lowlevel() {
431
+ return this.deps.lowLevelCoordinator;
432
+ }
433
+ /** App-state mutation coordinator: chat-side settings (mute, pin, etc.). */
434
+ get chat() {
435
+ return this.deps.chatCoordinator;
419
436
  }
420
- async fetchPairingCountryCodeIso() {
421
- if (!this.connectionManager.isConnected() || !this.authClient.getCurrentCredentials()) {
422
- throw new Error('client is not connected');
423
- }
424
- this.logger.trace('wa client fetch pairing country code iso');
425
- return this.authClient.fetchPairingCountryCodeIso();
437
+ /** Group coordinator: create/query/manage WhatsApp groups and communities. */
438
+ get group() {
439
+ return this.deps.groupCoordinator;
426
440
  }
427
- async getLidsByPhoneNumbers(phoneNumbers) {
428
- if (!this.connectionManager.isConnected() || !this.authClient.getCurrentCredentials()) {
429
- throw new Error('client is not connected');
430
- }
431
- const normalizedPhoneJids = new Array(phoneNumbers.length);
432
- for (let index = 0; index < phoneNumbers.length; index += 1) {
433
- normalizedPhoneJids[index] = parsePhoneJid(phoneNumbers[index]);
434
- }
435
- this.logger.trace('wa client query lids by phone numbers', {
436
- phones: normalizedPhoneJids.length
437
- });
438
- return this.signalDeviceSync.queryLidsByPhoneJids(normalizedPhoneJids);
439
- }
440
- sendMessage(to, content, options = {}) {
441
- return this.messageDispatch.sendMessage(to, content, options);
442
- }
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
- }
441
+ /** Status coordinator: status broadcast send and reactions. */
442
+ get status() {
443
+ return this.deps.statusCoordinator;
451
444
  }
452
- get chat() {
453
- return this.chatCoordinator;
445
+ /**
446
+ * Broadcast-list coordinator: list management and broadcast sends.
447
+ * **Business-only** - the underlying app-state schema rejects regular
448
+ * accounts. See {@link WaBroadcastListCoordinator}.
449
+ */
450
+ get broadcastList() {
451
+ return this.deps.broadcastListCoordinator;
454
452
  }
455
- get group() {
456
- return this.groupCoordinator;
453
+ /** Newsletter coordinator: create/query/follow/admin/send for channels. */
454
+ get newsletter() {
455
+ return this.deps.newsletterCoordinator;
457
456
  }
457
+ /** Privacy coordinator: privacy categories, blocklist, disallowed list. */
458
458
  get privacy() {
459
- return this.privacyCoordinator;
459
+ return this.deps.privacyCoordinator;
460
460
  }
461
+ /** Profile coordinator: own/peer profile fields (picture, status, username). */
461
462
  get profile() {
462
- return this.profileCoordinator;
463
- }
463
+ return this.deps.profileCoordinator;
464
+ }
465
+ /**
466
+ * Business coordinator: business profile, verified-name lookups. Reads
467
+ * work from any account; **writes (`editBusinessProfile`,
468
+ * `updateCoverPhoto`, `deleteCoverPhoto`) are business-only** and throw
469
+ * on regular accounts. See {@link WaBusinessCoordinator}.
470
+ */
464
471
  get business() {
465
- return this.businessCoordinator;
466
- }
467
- sendReceipt(input) {
468
- return this.messageDispatch.sendReceipt(input);
469
- }
470
- flushAppStateMutations() {
471
- return this.chatCoordinator.flushMutations();
472
- }
473
- flushWriteBehind(timeoutMs) {
474
- return this.writeBehind.flush(timeoutMs);
475
- }
476
- async exportAppState() {
477
- return this.appStateSync.exportState();
478
- }
479
- async syncAppState(options = {}) {
480
- if (!this.connectionManager.isConnected()) {
481
- throw new Error('client is not connected');
482
- }
483
- const shouldWaitForKeyShare = (await this.appStateStore.getActiveSyncKey()) === null;
484
- if (shouldWaitForKeyShare && !this.keyShareCoordinator.isBootstrapDone()) {
485
- this.keyShareCoordinator.markBootstrapDone();
486
- this.logger.info('app-state bootstrap pre-sync waiting for key share', {
487
- timeoutMs: WA_APP_STATE_KEY_SHARE_WAIT_TIMEOUT_MS
488
- });
489
- const received = await this.keyShareCoordinator.waitForShare(WA_APP_STATE_KEY_SHARE_WAIT_TIMEOUT_MS);
490
- if (received) {
491
- this.logger.info('app-state bootstrap pre-sync received key share, continuing sync');
492
- }
493
- else {
494
- this.logger.warn('app-state bootstrap pre-sync key share wait timed out, continuing sync', {
495
- timeoutMs: WA_APP_STATE_KEY_SHARE_WAIT_TIMEOUT_MS
496
- });
497
- }
498
- }
499
- let syncResult = await this.executeAppStateSync(options);
500
- let blockedCollections = this.getBlockedAppStateCollections(syncResult);
501
- if (!shouldWaitForKeyShare || blockedCollections.length === 0) {
502
- this.emitChatEventsFromAppStateSyncResult(syncResult);
503
- return syncResult;
504
- }
505
- let retryCount = 0;
506
- let observedKeyShareVersion = this.keyShareCoordinator.getVersion();
507
- while (blockedCollections.length > 0 && retryCount < WA_APP_STATE_KEY_SHARE_MAX_RETRIES) {
508
- const hasFreshShare = this.keyShareCoordinator.getVersion() !== observedKeyShareVersion;
509
- if (!hasFreshShare) {
510
- this.logger.info('app-state bootstrap waiting for key share', {
511
- blockedCollections: blockedCollections.join(','),
512
- timeoutMs: WA_APP_STATE_KEY_SHARE_WAIT_TIMEOUT_MS,
513
- retryCount: retryCount + 1
514
- });
515
- const received = await this.keyShareCoordinator.waitForShare(WA_APP_STATE_KEY_SHARE_WAIT_TIMEOUT_MS);
516
- if (!received) {
517
- this.logger.warn('app-state bootstrap key share wait timed out', {
518
- blockedCollections: blockedCollections.join(','),
519
- timeoutMs: WA_APP_STATE_KEY_SHARE_WAIT_TIMEOUT_MS
520
- });
521
- break;
522
- }
523
- }
524
- observedKeyShareVersion = this.keyShareCoordinator.getVersion();
525
- retryCount += 1;
526
- this.logger.info('app-state bootstrap retrying sync after key share', {
527
- retryCount,
528
- blockedCollections: blockedCollections.join(',')
529
- });
530
- syncResult = await this.executeAppStateSync(options);
531
- blockedCollections = this.getBlockedAppStateCollections(syncResult);
532
- }
533
- if (blockedCollections.length > 0) {
534
- this.logger.warn('app-state bootstrap still blocked after waiting for key share', {
535
- blockedCollections: blockedCollections.join(','),
536
- retries: retryCount
537
- });
538
- }
539
- this.emitChatEventsFromAppStateSyncResult(syncResult);
540
- return syncResult;
541
- }
542
- async executeAppStateSync(options) {
543
- return options.downloadExternalBlob
544
- ? this.appStateSync.sync(options)
545
- : this.appStateSync.sync({
546
- ...options,
547
- downloadExternalBlob: async (_collection, _kind, reference) => downloadExternalBlobReference(this.mediaTransfer, reference)
548
- });
549
- }
550
- getBlockedAppStateCollections(syncResult) {
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;
558
- }
559
- emitChatEventsFromAppStateSyncResult(syncResult) {
560
- const shouldEmitSnapshotMutations = this.options.chatEvents?.emitSnapshotMutations === true;
561
- for (const collectionResult of syncResult.collections) {
562
- const mutations = collectionResult.mutations ?? [];
563
- const lastMutationIndexByKey = new Map();
564
- for (let mutationIndex = 0; mutationIndex < mutations.length; mutationIndex += 1) {
565
- const mutation = mutations[mutationIndex];
566
- if (!shouldEmitSnapshotMutations && mutation.source === 'snapshot') {
567
- continue;
568
- }
569
- lastMutationIndexByKey.set(`${mutation.collection}\u0001${mutation.index}`, mutationIndex);
570
- }
571
- for (let mutationIndex = 0; mutationIndex < mutations.length; mutationIndex += 1) {
572
- const mutation = mutations[mutationIndex];
573
- if (!shouldEmitSnapshotMutations && mutation.source === 'snapshot') {
574
- continue;
575
- }
576
- const coalesceKey = `${mutation.collection}\u0001${mutation.index}`;
577
- if (lastMutationIndexByKey.get(coalesceKey) !== mutationIndex) {
578
- continue;
579
- }
580
- try {
581
- this.handleNctSaltMutation(mutation);
582
- const event = parseChatEventFromAppStateMutation(mutation);
583
- if (!event) {
584
- continue;
585
- }
586
- this.emit('chat_event', event);
587
- }
588
- catch (error) {
589
- this.logger.debug('failed to parse chat event from app-state mutation', {
590
- collection: mutation.collection,
591
- source: mutation.source,
592
- index: mutation.index,
593
- message: toError(error).message
594
- });
595
- }
596
- }
597
- }
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
- }
472
+ return this.deps.businessCoordinator;
473
+ }
474
+ /** Bot coordinator: Meta-AI bot profiles, prompt/chunk decryption. */
475
+ get bot() {
476
+ return this.deps.botCoordinator;
477
+ }
478
+ /**
479
+ * Email coordinator: bind/unbind/verify email on the account.
480
+ * **Mobile-only** - every method throws unless the client is connected
481
+ * via `options.mobileTransport`. See {@link WaEmailCoordinator}.
482
+ */
483
+ get email() {
484
+ return this.deps.emailCoordinator;
485
+ }
486
+ /**
487
+ * Unpairs this companion device by removing it server-side. Requires an
488
+ * authenticated session; throws when no `meJid` is present.
489
+ *
490
+ * **Does not** disconnect the socket or clear local stores by itself -
491
+ * the server initiates the close after accepting the IQ, which surfaces
492
+ * via a `connection` event with `isLogout: true`. That close handler is
493
+ * what wipes the persisted state, honoring `options.logoutStoreClear`.
494
+ * The {@link WaClient} instance is single-shot after logout: create a
495
+ * fresh one (with a fresh `sessionId` or pre-cleared store) to re-pair.
496
+ */
497
+ async logout(reason = WA_LOGOUT_REASONS.USER_INITIATED) {
498
+ const meJid = this.deps.authClient.getCurrentCredentials()?.meJid;
499
+ if (!meJid) {
500
+ throw new Error('cannot logout: client is not authenticated');
501
+ }
502
+ const deviceJid = normalizeDeviceJid(meJid);
503
+ const node = buildRemoveCompanionDeviceIq(deviceJid, reason);
504
+ const result = await this.queryWithContext('client.logout', node, undefined, {
505
+ jid: deviceJid,
506
+ reason
507
+ });
508
+ assertIqResult(result, 'client.logout');
614
509
  }
615
510
  async clearStoredState() {
616
511
  await this.pauseIncomingEventsAndWaitDrain();
@@ -618,36 +513,50 @@ export class WaClient extends EventEmitter {
618
513
  if (writeBehindDestroy.remaining > 0) {
619
514
  throw new Error(`clear stored state aborted: write-behind did not fully drain (remaining=${writeBehindDestroy.remaining})`);
620
515
  }
621
- const danglingReceipts = this.receiptQueue.take();
516
+ const danglingReceipts = this.deps.receiptQueue.take();
622
517
  if (danglingReceipts.length > 0) {
623
518
  this.logger.debug('cleared dangling receipts while clearing stored state', {
624
519
  count: danglingReceipts.length
625
520
  });
626
521
  }
627
522
  const s = this.options.logoutStoreClear;
628
- const shouldClear = (key) => s === undefined || s[key] !== false;
523
+ const isMailbox = (key) => key === 'messages' || key === 'threads' || key === 'contacts';
524
+ const shouldClear = (key) => {
525
+ const explicit = s?.[key];
526
+ if (explicit !== undefined)
527
+ return explicit;
528
+ return !isMailbox(key);
529
+ };
629
530
  if (shouldClear('auth'))
630
- await this.authClient.clearStoredCredentials();
531
+ await this.deps.authClient.clearStoredCredentials();
631
532
  if (shouldClear('appState'))
632
- await this.appStateStore.clear();
533
+ await this.stores.appState.clear();
633
534
  if (shouldClear('contacts'))
634
- await this.contactStore.clear();
535
+ await this.stores.contacts.clear();
635
536
  if (shouldClear('messages'))
636
- await this.messageStore.clear();
637
- if (shouldClear('participants'))
638
- await this.participantsStore.clear();
537
+ await this.stores.messages.clear();
538
+ if (shouldClear('messageSecret'))
539
+ await this.stores.messageSecret.clear();
540
+ if (shouldClear('groupMetadata'))
541
+ await this.stores.groupMetadata.clear();
639
542
  if (shouldClear('deviceList'))
640
- await this.deviceListStore.clear();
543
+ await this.stores.deviceList.clear();
641
544
  if (shouldClear('retry'))
642
- await this.retryStore.clear();
545
+ await this.stores.retry.clear();
643
546
  if (shouldClear('signal'))
644
- await this.signalStore.clear();
547
+ await this.stores.signal.clear();
548
+ if (shouldClear('preKey'))
549
+ await this.stores.preKey.clear();
550
+ if (shouldClear('session'))
551
+ await this.stores.session.clear();
552
+ if (shouldClear('identity'))
553
+ await this.stores.identity.clear();
645
554
  if (shouldClear('senderKey'))
646
- await this.senderKeyStore.clear();
555
+ await this.stores.senderKey.clear();
647
556
  if (shouldClear('threads'))
648
- await this.threadStore.clear();
557
+ await this.stores.threads.clear();
649
558
  if (shouldClear('privacyToken'))
650
- await this.privacyTokenStore.clear();
559
+ await this.stores.privacyToken.clear();
651
560
  }
652
561
  tryEnterIncomingHandler() {
653
562
  if (!this.acceptingIncomingEvents) {
@@ -691,6 +600,6 @@ export class WaClient extends EventEmitter {
691
600
  }
692
601
  handleError(error) {
693
602
  this.logger.error('wa client error', { message: error.message });
694
- this.emit('client_error', { error });
603
+ this.emit('debug_client_error', { error });
695
604
  }
696
605
  }