zapo-js 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (589) hide show
  1. package/README.md +20 -4
  2. package/dist/appstate/WaAppStateCrypto.js +19 -26
  3. package/dist/appstate/WaAppStateSyncClient.js +293 -181
  4. package/dist/appstate/WaAppStateSyncResponseParser.js +16 -5
  5. package/dist/appstate/constants.js +4 -3
  6. package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
  7. package/dist/appstate/index.js +8 -6
  8. package/dist/appstate/utils.js +9 -34
  9. package/dist/auth/WaAuthClient.js +43 -61
  10. package/dist/auth/flow/WaAuthCredentialsFlow.js +22 -15
  11. package/dist/auth/index.js +1 -8
  12. package/dist/auth/pairing/WaPairingCodeCrypto.js +6 -4
  13. package/dist/auth/pairing/WaPairingFlow.js +34 -26
  14. package/dist/auth/pairing/WaQrFlow.js +37 -24
  15. package/dist/client/WaClient.js +275 -324
  16. package/dist/client/WaClientFactory.js +500 -133
  17. package/dist/client/connection/WaConnectionManager.js +301 -0
  18. package/dist/client/connection/WaKeyShareCoordinator.js +63 -0
  19. package/dist/client/connection/WaReceiptQueue.js +51 -0
  20. package/dist/client/coordinators/WaAppStateMutationCoordinator.js +471 -0
  21. package/dist/client/coordinators/WaBusinessCoordinator.js +241 -0
  22. package/dist/client/coordinators/WaGroupCoordinator.js +30 -16
  23. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
  24. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +439 -701
  25. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  26. package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
  27. package/dist/client/coordinators/WaProfileCoordinator.js +212 -0
  28. package/dist/client/coordinators/WaRetryCoordinator.js +242 -57
  29. package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
  30. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +166 -0
  31. package/dist/client/dirty.js +74 -48
  32. package/dist/client/events/chat.js +4 -3
  33. package/dist/client/events/devices.js +72 -0
  34. package/dist/client/events/group.js +62 -47
  35. package/dist/client/events/identity.js +22 -0
  36. package/dist/client/events/privacy-token.js +39 -0
  37. package/dist/client/history-sync.js +94 -63
  38. package/dist/client/incoming.js +60 -27
  39. package/dist/client/mailbox.js +24 -23
  40. package/dist/client/messages.js +107 -31
  41. package/dist/client/messaging/fanout.js +199 -0
  42. package/dist/client/messaging/key-protocol.js +130 -0
  43. package/dist/client/messaging/participants.js +193 -0
  44. package/dist/client/persistence/WriteBehindPersistence.js +129 -0
  45. package/dist/client/tokens/cs-token.js +50 -0
  46. package/dist/client/tokens/tc-token.js +25 -0
  47. package/dist/crypto/core/hkdf.js +3 -8
  48. package/dist/crypto/core/index.js +2 -5
  49. package/dist/crypto/core/keys.js +6 -7
  50. package/dist/crypto/core/nonce.js +2 -0
  51. package/dist/crypto/core/primitives.js +12 -23
  52. package/dist/crypto/core/random.js +26 -23
  53. package/dist/crypto/curves/Ed25519.js +7 -8
  54. package/dist/crypto/curves/X25519.js +38 -22
  55. package/dist/crypto/index.js +1 -3
  56. package/dist/crypto/math/constants.js +13 -36
  57. package/dist/crypto/math/edwards.js +171 -44
  58. package/dist/crypto/math/fe.js +706 -0
  59. package/dist/crypto/math/mod.js +10 -3
  60. package/dist/esm/appstate/WaAppStateCrypto.js +7 -14
  61. package/dist/esm/appstate/WaAppStateSyncClient.js +284 -172
  62. package/dist/esm/appstate/WaAppStateSyncResponseParser.js +17 -6
  63. package/dist/esm/appstate/constants.js +3 -2
  64. package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
  65. package/dist/esm/appstate/index.js +2 -2
  66. package/dist/esm/appstate/utils.js +8 -30
  67. package/dist/esm/auth/WaAuthClient.js +43 -61
  68. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +22 -15
  69. package/dist/esm/auth/index.js +0 -3
  70. package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +6 -4
  71. package/dist/esm/auth/pairing/WaPairingFlow.js +28 -20
  72. package/dist/esm/auth/pairing/WaQrFlow.js +37 -24
  73. package/dist/esm/client/WaClient.js +275 -324
  74. package/dist/esm/client/WaClientFactory.js +501 -134
  75. package/dist/esm/client/connection/WaConnectionManager.js +297 -0
  76. package/dist/esm/client/connection/WaKeyShareCoordinator.js +59 -0
  77. package/dist/esm/client/connection/WaReceiptQueue.js +47 -0
  78. package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +467 -0
  79. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +238 -0
  80. package/dist/esm/client/coordinators/WaGroupCoordinator.js +23 -9
  81. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
  82. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +443 -705
  83. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  84. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
  85. package/dist/esm/client/coordinators/WaProfileCoordinator.js +209 -0
  86. package/dist/esm/client/coordinators/WaRetryCoordinator.js +244 -59
  87. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
  88. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +162 -0
  89. package/dist/esm/client/dirty.js +69 -43
  90. package/dist/esm/client/events/chat.js +4 -3
  91. package/dist/esm/client/events/devices.js +68 -0
  92. package/dist/esm/client/events/group.js +53 -39
  93. package/dist/esm/client/events/identity.js +19 -0
  94. package/dist/esm/client/events/privacy-token.js +36 -0
  95. package/dist/esm/client/history-sync.js +91 -60
  96. package/dist/esm/client/incoming.js +61 -28
  97. package/dist/esm/client/mailbox.js +24 -23
  98. package/dist/esm/client/messages.js +108 -32
  99. package/dist/esm/client/messaging/fanout.js +196 -0
  100. package/dist/esm/client/messaging/key-protocol.js +127 -0
  101. package/dist/esm/client/messaging/participants.js +190 -0
  102. package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
  103. package/dist/esm/client/tokens/cs-token.js +46 -0
  104. package/dist/esm/client/tokens/tc-token.js +18 -0
  105. package/dist/esm/crypto/core/hkdf.js +3 -8
  106. package/dist/esm/crypto/core/index.js +2 -3
  107. package/dist/esm/crypto/core/keys.js +3 -4
  108. package/dist/esm/crypto/core/nonce.js +2 -0
  109. package/dist/esm/crypto/core/primitives.js +12 -22
  110. package/dist/esm/crypto/core/random.js +25 -23
  111. package/dist/esm/crypto/curves/Ed25519.js +4 -5
  112. package/dist/esm/crypto/curves/X25519.js +35 -19
  113. package/dist/esm/crypto/index.js +0 -1
  114. package/dist/esm/crypto/math/constants.js +12 -35
  115. package/dist/esm/crypto/math/edwards.js +174 -47
  116. package/dist/esm/crypto/math/fe.js +691 -0
  117. package/dist/esm/crypto/math/mod.js +10 -1
  118. package/dist/esm/index.js +1 -1
  119. package/dist/esm/infra/log/ConsoleLogger.js +18 -17
  120. package/dist/esm/infra/log/PinoLogger.js +15 -9
  121. package/dist/esm/infra/log/types.js +11 -1
  122. package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
  123. package/dist/esm/infra/perf/BoundedTaskQueue.js +16 -18
  124. package/dist/esm/infra/perf/PromiseDedup.js +20 -0
  125. package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
  126. package/dist/esm/infra/perf/StoreLock.js +77 -0
  127. package/dist/esm/media/WaMediaCrypto.js +96 -16
  128. package/dist/esm/media/WaMediaTransferClient.js +251 -91
  129. package/dist/esm/media/conn.js +10 -6
  130. package/dist/esm/media/constants.js +6 -2
  131. package/dist/esm/message/WaMessageClient.js +30 -32
  132. package/dist/esm/message/ack.js +6 -6
  133. package/dist/esm/message/addon-crypto.js +59 -0
  134. package/dist/esm/message/content.js +195 -9
  135. package/dist/esm/message/icdc.js +76 -0
  136. package/dist/esm/message/incoming.js +129 -122
  137. package/dist/esm/message/index.js +2 -0
  138. package/dist/esm/message/phash.js +3 -1
  139. package/dist/esm/message/reporting-token.js +425 -0
  140. package/dist/esm/message/use-case-secret.js +49 -0
  141. package/dist/esm/protocol/appstate.js +27 -0
  142. package/dist/esm/protocol/browser.js +10 -18
  143. package/dist/esm/protocol/constants.js +6 -3
  144. package/dist/esm/protocol/defaults.js +6 -0
  145. package/dist/esm/protocol/index.js +2 -11
  146. package/dist/esm/protocol/jid.js +133 -52
  147. package/dist/esm/protocol/media.js +3 -3
  148. package/dist/esm/protocol/message.js +61 -1
  149. package/dist/esm/protocol/nodes.js +4 -0
  150. package/dist/esm/protocol/notification.js +3 -1
  151. package/dist/esm/protocol/privacy-token.js +17 -0
  152. package/dist/esm/protocol/privacy.js +55 -0
  153. package/dist/esm/protocol/stream.js +26 -1
  154. package/dist/esm/protocol/usync.js +11 -0
  155. package/dist/esm/retry/codec.js +216 -0
  156. package/dist/esm/retry/constants.js +1 -1
  157. package/dist/esm/retry/index.js +3 -2
  158. package/dist/esm/retry/parse.js +88 -86
  159. package/dist/esm/retry/replay.js +54 -51
  160. package/dist/esm/retry/tracker.js +94 -0
  161. package/dist/esm/signal/api/SignalDeviceSyncApi.js +276 -92
  162. package/dist/esm/signal/api/SignalDigestSyncApi.js +17 -8
  163. package/dist/esm/signal/api/SignalIdentitySyncApi.js +67 -37
  164. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +86 -67
  165. package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
  166. package/dist/esm/signal/api/SignalSessionSyncApi.js +36 -34
  167. package/dist/esm/signal/api/result-map.js +10 -0
  168. package/dist/esm/signal/constants.js +0 -4
  169. package/dist/esm/signal/crypto/WaAdvSignature.js +13 -9
  170. package/dist/esm/signal/{store/sqlite.js → encoding.js} +93 -60
  171. package/dist/esm/signal/group/SenderKeyChain.js +28 -23
  172. package/dist/esm/signal/group/SenderKeyCodec.js +5 -6
  173. package/dist/esm/signal/group/SenderKeyManager.js +144 -115
  174. package/dist/esm/signal/index.js +2 -0
  175. package/dist/esm/signal/registration/keygen.js +6 -2
  176. package/dist/esm/signal/registration/utils.js +1 -0
  177. package/dist/esm/signal/session/SignalProtocol.js +164 -53
  178. package/dist/esm/signal/session/SignalRatchet.js +24 -15
  179. package/dist/esm/signal/session/SignalSession.js +14 -9
  180. package/dist/esm/signal/session/resolver.js +221 -0
  181. package/dist/esm/store/contracts/privacy-token.store.js +1 -0
  182. package/dist/esm/store/createStore.js +100 -188
  183. package/dist/esm/store/index.js +1 -10
  184. package/dist/esm/store/locks/appstate.lock.js +26 -0
  185. package/dist/esm/store/locks/auth.lock.js +15 -0
  186. package/dist/esm/store/locks/contact.lock.js +20 -0
  187. package/dist/esm/store/locks/device-list.lock.js +20 -0
  188. package/dist/esm/store/locks/message.lock.js +21 -0
  189. package/dist/esm/store/locks/participants.lock.js +20 -0
  190. package/dist/esm/store/locks/privacy-token.lock.js +18 -0
  191. package/dist/esm/store/locks/retry.lock.js +29 -0
  192. package/dist/esm/store/locks/sender-key.lock.js +52 -0
  193. package/dist/esm/store/locks/signal.lock.js +63 -0
  194. package/dist/esm/store/locks/thread.lock.js +21 -0
  195. package/dist/esm/store/noop.store.js +4 -7
  196. package/dist/esm/store/providers/memory/appstate.store.js +38 -16
  197. package/dist/esm/store/providers/memory/contact.store.js +5 -0
  198. package/dist/esm/store/providers/memory/device-list.store.js +12 -34
  199. package/dist/esm/store/providers/memory/message.store.js +11 -5
  200. package/dist/esm/store/providers/memory/participants.store.js +1 -8
  201. package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
  202. package/dist/esm/store/providers/memory/retry.store.js +77 -2
  203. package/dist/esm/store/providers/memory/sender-key.store.js +11 -8
  204. package/dist/esm/store/providers/memory/signal.store.js +47 -18
  205. package/dist/esm/store/providers/memory/thread.store.js +5 -0
  206. package/dist/esm/transport/WaComms.js +28 -24
  207. package/dist/esm/transport/WaWebSocket.js +115 -18
  208. package/dist/esm/transport/binary/constants.js +0 -30
  209. package/dist/esm/transport/binary/decoder.js +8 -8
  210. package/dist/esm/transport/binary/encoder.js +10 -9
  211. package/dist/esm/transport/binary/index.js +0 -1
  212. package/dist/esm/transport/index.js +1 -0
  213. package/dist/esm/transport/keepalive/WaKeepAlive.js +2 -8
  214. package/dist/esm/transport/node/WaNodeOrchestrator.js +25 -21
  215. package/dist/esm/transport/node/WaNodeTransport.js +0 -3
  216. package/dist/esm/transport/node/builders/{accountSync.js → account-sync.js} +16 -36
  217. package/dist/esm/transport/node/builders/business.js +129 -0
  218. package/dist/esm/transport/node/builders/global.js +370 -0
  219. package/dist/esm/transport/node/builders/index.js +7 -3
  220. package/dist/esm/transport/node/builders/message.js +63 -230
  221. package/dist/esm/transport/node/builders/pairing.js +2 -27
  222. package/dist/esm/transport/node/builders/privacy-token.js +41 -0
  223. package/dist/esm/transport/node/builders/privacy.js +48 -0
  224. package/dist/esm/transport/node/builders/profile.js +70 -0
  225. package/dist/esm/transport/node/builders/retry.js +10 -22
  226. package/dist/esm/transport/node/builders/usync.js +45 -0
  227. package/dist/esm/transport/node/helpers.js +125 -5
  228. package/dist/esm/transport/node/usync.js +5 -0
  229. package/dist/esm/transport/node/xml.js +35 -14
  230. package/dist/esm/transport/noise/WaClientPayload.js +10 -10
  231. package/dist/esm/transport/noise/WaFrameCodec.js +48 -33
  232. package/dist/esm/transport/noise/WaNoiseCert.js +4 -7
  233. package/dist/esm/transport/noise/WaNoiseSession.js +77 -29
  234. package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
  235. package/dist/esm/transport/proxy.js +27 -0
  236. package/dist/esm/transport/stream/parse.js +17 -48
  237. package/dist/esm/util/bytes.js +67 -45
  238. package/dist/esm/util/coercion.js +6 -14
  239. package/dist/esm/util/index.js +5 -0
  240. package/dist/esm/util/primitives.js +40 -14
  241. package/dist/index.js +7 -1
  242. package/dist/infra/log/ConsoleLogger.js +18 -17
  243. package/dist/infra/log/PinoLogger.js +15 -9
  244. package/dist/infra/log/types.js +12 -0
  245. package/dist/infra/perf/BackgroundQueue.js +482 -0
  246. package/dist/infra/perf/BoundedTaskQueue.js +16 -18
  247. package/dist/infra/perf/PromiseDedup.js +24 -0
  248. package/dist/infra/perf/SharedExclusiveGate.js +113 -0
  249. package/dist/infra/perf/StoreLock.js +81 -0
  250. package/dist/media/WaMediaCrypto.js +95 -15
  251. package/dist/media/WaMediaTransferClient.js +284 -91
  252. package/dist/media/conn.js +10 -6
  253. package/dist/media/constants.js +6 -2
  254. package/dist/message/WaMessageClient.js +31 -33
  255. package/dist/message/ack.js +6 -6
  256. package/dist/message/addon-crypto.js +65 -0
  257. package/dist/message/content.js +198 -9
  258. package/dist/message/icdc.js +81 -0
  259. package/dist/message/incoming.js +127 -120
  260. package/dist/message/index.js +2 -0
  261. package/dist/message/phash.js +3 -1
  262. package/dist/message/reporting-token.js +429 -0
  263. package/dist/message/use-case-secret.js +55 -0
  264. package/dist/protocol/appstate.js +28 -1
  265. package/dist/protocol/browser.js +10 -18
  266. package/dist/protocol/constants.js +26 -1
  267. package/dist/protocol/defaults.js +6 -0
  268. package/dist/protocol/index.js +23 -42
  269. package/dist/protocol/jid.js +140 -52
  270. package/dist/protocol/media.js +3 -3
  271. package/dist/protocol/message.js +62 -2
  272. package/dist/protocol/nodes.js +4 -0
  273. package/dist/protocol/notification.js +3 -1
  274. package/dist/protocol/privacy-token.js +20 -0
  275. package/dist/protocol/privacy.js +58 -0
  276. package/dist/protocol/stream.js +27 -2
  277. package/dist/protocol/usync.js +14 -0
  278. package/dist/retry/codec.js +220 -0
  279. package/dist/retry/constants.js +1 -1
  280. package/dist/retry/index.js +7 -5
  281. package/dist/retry/parse.js +88 -85
  282. package/dist/retry/replay.js +52 -49
  283. package/dist/retry/tracker.js +97 -0
  284. package/dist/signal/api/SignalDeviceSyncApi.js +273 -89
  285. package/dist/signal/api/SignalDigestSyncApi.js +17 -8
  286. package/dist/signal/api/SignalIdentitySyncApi.js +66 -36
  287. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +82 -63
  288. package/dist/signal/api/SignalRotateKeyApi.js +4 -2
  289. package/dist/signal/api/SignalSessionSyncApi.js +36 -34
  290. package/dist/signal/api/result-map.js +13 -0
  291. package/dist/signal/constants.js +1 -5
  292. package/dist/signal/crypto/WaAdvSignature.js +11 -7
  293. package/dist/signal/{store/sqlite.js → encoding.js} +94 -61
  294. package/dist/signal/group/SenderKeyChain.js +27 -22
  295. package/dist/signal/group/SenderKeyCodec.js +5 -6
  296. package/dist/signal/group/SenderKeyManager.js +144 -115
  297. package/dist/signal/index.js +15 -1
  298. package/dist/signal/registration/keygen.js +6 -2
  299. package/dist/signal/registration/utils.js +1 -0
  300. package/dist/signal/session/SignalProtocol.js +164 -53
  301. package/dist/signal/session/SignalRatchet.js +24 -15
  302. package/dist/signal/session/SignalSession.js +14 -9
  303. package/dist/signal/session/resolver.js +224 -0
  304. package/dist/store/contracts/privacy-token.store.js +2 -0
  305. package/dist/store/createStore.js +100 -188
  306. package/dist/store/index.js +15 -33
  307. package/dist/store/locks/appstate.lock.js +29 -0
  308. package/dist/store/locks/auth.lock.js +18 -0
  309. package/dist/store/locks/contact.lock.js +23 -0
  310. package/dist/store/locks/device-list.lock.js +23 -0
  311. package/dist/store/locks/message.lock.js +24 -0
  312. package/dist/store/locks/participants.lock.js +23 -0
  313. package/dist/store/locks/privacy-token.lock.js +21 -0
  314. package/dist/store/locks/retry.lock.js +32 -0
  315. package/dist/store/locks/sender-key.lock.js +55 -0
  316. package/dist/store/locks/signal.lock.js +66 -0
  317. package/dist/store/locks/thread.lock.js +24 -0
  318. package/dist/store/noop.store.js +4 -7
  319. package/dist/store/providers/memory/appstate.store.js +36 -14
  320. package/dist/store/providers/memory/contact.store.js +5 -0
  321. package/dist/store/providers/memory/device-list.store.js +12 -34
  322. package/dist/store/providers/memory/message.store.js +11 -5
  323. package/dist/store/providers/memory/participants.store.js +1 -8
  324. package/dist/store/providers/memory/privacy-token.store.js +47 -0
  325. package/dist/store/providers/memory/retry.store.js +77 -2
  326. package/dist/store/providers/memory/sender-key.store.js +14 -11
  327. package/dist/store/providers/memory/signal.store.js +54 -25
  328. package/dist/store/providers/memory/thread.store.js +5 -0
  329. package/dist/transport/WaComms.js +30 -26
  330. package/dist/transport/WaWebSocket.js +148 -18
  331. package/dist/transport/binary/constants.js +1 -31
  332. package/dist/transport/binary/decoder.js +8 -8
  333. package/dist/transport/binary/encoder.js +10 -9
  334. package/dist/transport/binary/index.js +0 -4
  335. package/dist/transport/index.js +7 -1
  336. package/dist/transport/keepalive/WaKeepAlive.js +1 -7
  337. package/dist/transport/node/WaNodeOrchestrator.js +25 -21
  338. package/dist/transport/node/WaNodeTransport.js +0 -3
  339. package/dist/transport/node/builders/{accountSync.js → account-sync.js} +15 -35
  340. package/dist/transport/node/builders/business.js +137 -0
  341. package/dist/transport/node/builders/global.js +375 -0
  342. package/dist/transport/node/builders/index.js +29 -17
  343. package/dist/transport/node/builders/message.js +64 -236
  344. package/dist/transport/node/builders/pairing.js +2 -29
  345. package/dist/transport/node/builders/privacy-token.js +46 -0
  346. package/dist/transport/node/builders/privacy.js +55 -0
  347. package/dist/transport/node/builders/profile.js +78 -0
  348. package/dist/transport/node/builders/retry.js +9 -21
  349. package/dist/transport/node/builders/usync.js +49 -0
  350. package/dist/transport/node/helpers.js +131 -4
  351. package/dist/transport/node/usync.js +8 -0
  352. package/dist/transport/node/xml.js +35 -14
  353. package/dist/transport/noise/WaClientPayload.js +13 -13
  354. package/dist/transport/noise/WaFrameCodec.js +47 -32
  355. package/dist/transport/noise/WaNoiseCert.js +5 -8
  356. package/dist/transport/noise/WaNoiseSession.js +77 -29
  357. package/dist/transport/noise/WaNoiseSocket.js +8 -4
  358. package/dist/transport/proxy.js +34 -0
  359. package/dist/transport/stream/parse.js +20 -52
  360. package/dist/types/appstate/WaAppStateCrypto.d.ts +0 -1
  361. package/dist/types/appstate/WaAppStateSyncClient.d.ts +5 -2
  362. package/dist/types/appstate/constants.d.ts +1 -0
  363. package/dist/types/appstate/encoding.d.ts +7 -0
  364. package/dist/types/appstate/index.d.ts +3 -3
  365. package/dist/types/appstate/utils.d.ts +0 -3
  366. package/dist/types/auth/WaAuthClient.d.ts +10 -12
  367. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +1 -1
  368. package/dist/types/auth/index.d.ts +0 -4
  369. package/dist/types/auth/pairing/WaQrFlow.d.ts +1 -1
  370. package/dist/types/auth/types.d.ts +7 -9
  371. package/dist/types/client/WaClient.d.ts +42 -25
  372. package/dist/types/client/WaClientFactory.d.ts +33 -26
  373. package/dist/types/client/connection/WaConnectionManager.d.ts +66 -0
  374. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +14 -0
  375. package/dist/types/client/connection/WaReceiptQueue.d.ts +13 -0
  376. package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +46 -0
  377. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
  378. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +3 -2
  379. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +29 -38
  380. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -0
  381. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
  382. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +36 -0
  383. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +8 -0
  384. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
  385. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +45 -0
  386. package/dist/types/client/dirty.d.ts +1 -0
  387. package/dist/types/client/events/devices.d.ts +20 -0
  388. package/dist/types/client/events/group.d.ts +2 -1
  389. package/dist/types/client/events/identity.d.ts +9 -0
  390. package/dist/types/client/events/privacy-token.d.ts +7 -0
  391. package/dist/types/client/history-sync.d.ts +9 -6
  392. package/dist/types/client/incoming.d.ts +3 -1
  393. package/dist/types/client/index.d.ts +1 -1
  394. package/dist/types/client/mailbox.d.ts +3 -5
  395. package/dist/types/client/messages.d.ts +1 -2
  396. package/dist/types/client/messaging/fanout.d.ts +14 -0
  397. package/dist/types/client/messaging/key-protocol.d.ts +18 -0
  398. package/dist/types/client/messaging/participants.d.ts +13 -0
  399. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
  400. package/dist/types/client/tokens/cs-token.d.ts +10 -0
  401. package/dist/types/client/tokens/tc-token.d.ts +5 -0
  402. package/dist/types/client/types.d.ts +75 -4
  403. package/dist/types/crypto/core/hkdf.d.ts +0 -6
  404. package/dist/types/crypto/core/index.d.ts +2 -3
  405. package/dist/types/crypto/core/nonce.d.ts +2 -0
  406. package/dist/types/crypto/core/primitives.d.ts +0 -1
  407. package/dist/types/crypto/core/random.d.ts +2 -7
  408. package/dist/types/crypto/index.d.ts +0 -1
  409. package/dist/types/crypto/math/constants.d.ts +4 -2
  410. package/dist/types/crypto/math/fe.d.ts +30 -0
  411. package/dist/types/crypto/math/mod.d.ts +0 -2
  412. package/dist/types/crypto/math/types.d.ts +11 -4
  413. package/dist/types/index.d.ts +5 -3
  414. package/dist/types/infra/log/ConsoleLogger.d.ts +2 -1
  415. package/dist/types/infra/log/PinoLogger.d.ts +1 -1
  416. package/dist/types/infra/log/types.d.ts +1 -0
  417. package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
  418. package/dist/types/infra/perf/BoundedTaskQueue.d.ts +1 -1
  419. package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
  420. package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
  421. package/dist/types/infra/perf/StoreLock.d.ts +10 -0
  422. package/dist/types/media/WaMediaCrypto.d.ts +3 -2
  423. package/dist/types/media/WaMediaTransferClient.d.ts +16 -15
  424. package/dist/types/media/constants.d.ts +1 -1
  425. package/dist/types/media/index.d.ts +1 -1
  426. package/dist/types/media/types.d.ts +15 -2
  427. package/dist/types/message/addon-crypto.d.ts +25 -0
  428. package/dist/types/message/content.d.ts +8 -0
  429. package/dist/types/message/icdc.d.ts +13 -0
  430. package/dist/types/message/index.d.ts +2 -0
  431. package/dist/types/message/reporting-token.d.ts +18 -0
  432. package/dist/types/message/types.d.ts +45 -6
  433. package/dist/types/message/use-case-secret.d.ts +20 -0
  434. package/dist/types/protocol/appstate.d.ts +47 -0
  435. package/dist/types/protocol/constants.d.ts +8 -3
  436. package/dist/types/protocol/defaults.d.ts +6 -0
  437. package/dist/types/protocol/index.d.ts +2 -11
  438. package/dist/types/protocol/jid.d.ts +22 -5
  439. package/dist/types/protocol/message.d.ts +60 -0
  440. package/dist/types/protocol/nodes.d.ts +4 -0
  441. package/dist/types/protocol/notification.d.ts +2 -0
  442. package/dist/types/protocol/privacy-token.d.ts +17 -0
  443. package/dist/types/protocol/privacy.d.ts +75 -0
  444. package/dist/types/protocol/stream.d.ts +30 -0
  445. package/dist/types/protocol/usync.d.ts +11 -0
  446. package/dist/types/retry/codec.d.ts +3 -0
  447. package/dist/types/retry/index.d.ts +4 -3
  448. package/dist/types/retry/parse.d.ts +5 -2
  449. package/dist/types/retry/replay.d.ts +0 -4
  450. package/dist/types/retry/tracker.d.ts +20 -0
  451. package/dist/types/retry/types.d.ts +10 -4
  452. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +15 -2
  453. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +6 -0
  454. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +2 -0
  455. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
  456. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
  457. package/dist/types/signal/api/result-map.d.ts +1 -0
  458. package/dist/types/signal/constants.d.ts +0 -3
  459. package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +3 -3
  460. package/dist/types/signal/group/SenderKeyCodec.d.ts +4 -6
  461. package/dist/types/signal/group/SenderKeyManager.d.ts +10 -5
  462. package/dist/types/signal/index.d.ts +3 -0
  463. package/dist/types/signal/session/SignalProtocol.d.ts +19 -4
  464. package/dist/types/signal/session/resolver.d.ts +22 -0
  465. package/dist/types/store/contracts/appstate.store.d.ts +4 -1
  466. package/dist/types/store/contracts/contact.store.d.ts +1 -0
  467. package/dist/types/store/contracts/device-list.store.d.ts +0 -3
  468. package/dist/types/store/contracts/message.store.d.ts +1 -0
  469. package/dist/types/store/contracts/participants.store.d.ts +0 -1
  470. package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
  471. package/dist/types/store/contracts/retry.store.d.ts +7 -0
  472. package/dist/types/store/contracts/sender-key.store.d.ts +0 -1
  473. package/dist/types/store/contracts/signal.store.d.ts +13 -0
  474. package/dist/types/store/contracts/thread.store.d.ts +1 -0
  475. package/dist/types/store/createStore.d.ts +1 -1
  476. package/dist/types/store/index.d.ts +5 -13
  477. package/dist/types/store/locks/appstate.lock.d.ts +3 -0
  478. package/dist/types/store/locks/auth.lock.d.ts +3 -0
  479. package/dist/types/store/locks/contact.lock.d.ts +3 -0
  480. package/dist/types/store/locks/device-list.lock.d.ts +2 -0
  481. package/dist/types/store/locks/message.lock.d.ts +3 -0
  482. package/dist/types/store/locks/participants.lock.d.ts +2 -0
  483. package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
  484. package/dist/types/store/locks/retry.lock.d.ts +2 -0
  485. package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
  486. package/dist/types/store/locks/signal.lock.d.ts +3 -0
  487. package/dist/types/store/locks/thread.lock.d.ts +3 -0
  488. package/dist/types/store/providers/memory/appstate.store.d.ts +3 -1
  489. package/dist/types/store/providers/memory/contact.store.d.ts +1 -0
  490. package/dist/types/store/providers/memory/device-list.store.d.ts +0 -3
  491. package/dist/types/store/providers/memory/message.store.d.ts +1 -0
  492. package/dist/types/store/providers/memory/participants.store.d.ts +0 -1
  493. package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
  494. package/dist/types/store/providers/memory/retry.store.d.ts +8 -0
  495. package/dist/types/store/providers/memory/sender-key.store.d.ts +0 -1
  496. package/dist/types/store/providers/memory/signal.store.d.ts +8 -1
  497. package/dist/types/store/providers/memory/thread.store.d.ts +1 -0
  498. package/dist/types/store/types.d.ts +49 -58
  499. package/dist/types/transport/WaWebSocket.d.ts +3 -1
  500. package/dist/types/transport/binary/constants.d.ts +0 -30
  501. package/dist/types/transport/binary/index.d.ts +0 -1
  502. package/dist/types/transport/index.d.ts +2 -1
  503. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +0 -1
  504. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +3 -4
  505. package/dist/types/transport/node/WaNodeTransport.d.ts +0 -9
  506. package/dist/types/transport/node/builders/business.d.ts +29 -0
  507. package/dist/types/transport/node/builders/global.d.ts +102 -0
  508. package/dist/types/transport/node/builders/group.d.ts +4 -6
  509. package/dist/types/transport/node/builders/index.d.ts +7 -3
  510. package/dist/types/transport/node/builders/message.d.ts +20 -30
  511. package/dist/types/transport/node/builders/pairing.d.ts +0 -2
  512. package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
  513. package/dist/types/transport/node/builders/privacy.d.ts +7 -0
  514. package/dist/types/transport/node/builders/profile.d.ts +8 -0
  515. package/dist/types/transport/node/builders/retry.d.ts +2 -5
  516. package/dist/types/transport/node/builders/usync.d.ts +21 -0
  517. package/dist/types/transport/node/helpers.d.ts +13 -0
  518. package/dist/types/transport/node/usync.d.ts +2 -0
  519. package/dist/types/transport/noise/WaFrameCodec.d.ts +3 -0
  520. package/dist/types/transport/noise/WaNoiseSession.d.ts +4 -2
  521. package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
  522. package/dist/types/transport/proxy.d.ts +6 -0
  523. package/dist/types/transport/stream/parse.d.ts +0 -1
  524. package/dist/types/transport/types.d.ts +18 -1
  525. package/dist/types/util/bytes.d.ts +5 -0
  526. package/dist/types/util/index.d.ts +5 -0
  527. package/dist/types/util/primitives.d.ts +2 -0
  528. package/dist/util/bytes.js +72 -46
  529. package/dist/util/coercion.js +6 -14
  530. package/dist/util/index.js +23 -0
  531. package/dist/util/primitives.js +42 -14
  532. package/package.json +52 -9
  533. package/proto/index.js +1 -1
  534. package/dist/crypto/core/constants.js +0 -4
  535. package/dist/crypto/core/encoding.js +0 -29
  536. package/dist/esm/crypto/core/constants.js +0 -1
  537. package/dist/esm/crypto/core/encoding.js +0 -25
  538. package/dist/esm/retry/outbound.js +0 -83
  539. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
  540. package/dist/esm/store/providers/sqlite/appstate.store.js +0 -169
  541. package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
  542. package/dist/esm/store/providers/sqlite/connection.js +0 -240
  543. package/dist/esm/store/providers/sqlite/contact.store.js +0 -61
  544. package/dist/esm/store/providers/sqlite/device-list.store.js +0 -155
  545. package/dist/esm/store/providers/sqlite/message.store.js +0 -119
  546. package/dist/esm/store/providers/sqlite/migrations.js +0 -347
  547. package/dist/esm/store/providers/sqlite/participants.store.js +0 -85
  548. package/dist/esm/store/providers/sqlite/retry.store.js +0 -144
  549. package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -203
  550. package/dist/esm/store/providers/sqlite/signal.store.js +0 -353
  551. package/dist/esm/store/providers/sqlite/thread.store.js +0 -72
  552. package/dist/esm/util/base64.js +0 -18
  553. package/dist/esm/util/signal-address.js +0 -5
  554. package/dist/retry/outbound.js +0 -88
  555. package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
  556. package/dist/store/providers/sqlite/appstate.store.js +0 -173
  557. package/dist/store/providers/sqlite/auth.store.js +0 -180
  558. package/dist/store/providers/sqlite/connection.js +0 -276
  559. package/dist/store/providers/sqlite/contact.store.js +0 -65
  560. package/dist/store/providers/sqlite/device-list.store.js +0 -159
  561. package/dist/store/providers/sqlite/message.store.js +0 -123
  562. package/dist/store/providers/sqlite/migrations.js +0 -350
  563. package/dist/store/providers/sqlite/participants.store.js +0 -89
  564. package/dist/store/providers/sqlite/retry.store.js +0 -148
  565. package/dist/store/providers/sqlite/sender-key.store.js +0 -207
  566. package/dist/store/providers/sqlite/signal.store.js +0 -357
  567. package/dist/store/providers/sqlite/thread.store.js +0 -76
  568. package/dist/types/appstate/store/sqlite.d.ts +0 -21
  569. package/dist/types/crypto/core/constants.d.ts +0 -1
  570. package/dist/types/crypto/core/encoding.d.ts +0 -11
  571. package/dist/types/retry/outbound.d.ts +0 -4
  572. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
  573. package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -15
  574. package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
  575. package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
  576. package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -10
  577. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -18
  578. package/dist/types/store/providers/sqlite/message.store.d.ts +0 -11
  579. package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
  580. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -13
  581. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -16
  582. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -25
  583. package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -46
  584. package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -11
  585. package/dist/types/util/base64.d.ts +0 -4
  586. package/dist/types/util/signal-address.d.ts +0 -2
  587. package/dist/util/base64.js +0 -24
  588. package/dist/util/signal-address.js +0 -8
  589. /package/dist/types/transport/node/builders/{accountSync.d.ts → account-sync.d.ts} +0 -0
@@ -1,34 +1,48 @@
1
- import { randomInt } from 'node:crypto';
2
- import { WA_DEFAULTS, WA_NODE_TAGS, WA_XMLNS } from '../../protocol/constants.js';
3
- import { parseSignalAddressFromJid, splitJid } from '../../protocol/jid.js';
1
+ import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
2
+ import { WA_DEFAULTS, WA_NODE_TAGS, WA_USYNC_CONTEXTS } from '../../protocol/constants.js';
3
+ import { buildDeviceJid, isHostedDeviceId, splitJid, toUserJid } from '../../protocol/jid.js';
4
+ import { buildUsyncIq } from '../../transport/node/builders/usync.js';
4
5
  import { findNodeChild, getNodeChildrenByTag } from '../../transport/node/helpers.js';
5
- import { assertIqResult, buildIqNode } from '../../transport/node/query.js';
6
+ import { assertIqResult } from '../../transport/node/query.js';
7
+ import { createUsyncSidGenerator } from '../../transport/node/usync.js';
6
8
  export class SignalDeviceSyncApi {
7
9
  constructor(options) {
10
+ this.syncDedup = new PromiseDedup();
8
11
  this.logger = options.logger;
9
12
  this.query = options.query;
10
13
  this.deviceListStore = options.deviceListStore;
11
14
  this.defaultTimeoutMs =
12
15
  options.defaultTimeoutMs ?? WA_DEFAULTS.SIGNAL_FETCH_KEY_BUNDLES_TIMEOUT_MS;
13
16
  this.hostDomain = options.hostDomain ?? WA_DEFAULTS.HOST_DOMAIN;
17
+ this.generateSid = options.generateSid ?? createUsyncSidGenerator();
14
18
  }
15
- async syncDeviceList(userJids, timeoutMs = this.defaultTimeoutMs) {
19
+ syncDeviceList(userJids, timeoutMs = this.defaultTimeoutMs) {
16
20
  const normalizedUsers = this.normalizeUsers(userJids);
17
21
  if (normalizedUsers.length === 0) {
18
- return [];
22
+ return Promise.resolve([]);
19
23
  }
24
+ const dedupKey = normalizedUsers.join(',');
25
+ return this.syncDedup.run(dedupKey, () => this.syncDeviceListInternal(normalizedUsers, timeoutMs));
26
+ }
27
+ async syncDeviceListInternal(normalizedUsers, timeoutMs) {
20
28
  const nowMs = Date.now();
21
29
  const cachedByUser = new Map();
22
30
  const usersToQuery = this.deviceListStore
23
31
  ? await this.collectUsersToQuery(normalizedUsers, nowMs, cachedByUser, this.deviceListStore)
24
32
  : normalizedUsers;
25
33
  if (usersToQuery.length === 0) {
26
- return normalizedUsers.map((jid) => ({
27
- jid,
28
- deviceJids: cachedByUser.get(jid) ?? []
29
- }));
34
+ const fromCache = new Array(normalizedUsers.length);
35
+ for (let index = 0; index < normalizedUsers.length; index += 1) {
36
+ const jid = normalizedUsers[index];
37
+ fromCache[index] = {
38
+ jid,
39
+ deviceJids: cachedByUser.get(jid) ?? []
40
+ };
41
+ }
42
+ return fromCache;
30
43
  }
31
- const request = this.makeDeviceSyncRequest(usersToQuery);
44
+ const sid = await this.generateSid();
45
+ const request = this.makeDeviceSyncRequest(usersToQuery, sid);
32
46
  this.logger.debug('signal device sync request', {
33
47
  users: usersToQuery.length,
34
48
  timeoutMs
@@ -37,72 +51,152 @@ export class SignalDeviceSyncApi {
37
51
  const parsed = this.parseDeviceSyncResponse(response, usersToQuery);
38
52
  if (this.deviceListStore) {
39
53
  const updatedAtMs = Date.now();
40
- await this.deviceListStore.upsertUserDevicesBatch(parsed.map((entry) => ({
41
- userJid: entry.jid,
42
- deviceJids: entry.deviceJids,
43
- updatedAtMs
44
- })));
45
- }
46
- const parsedByUser = new Map(parsed.map((entry) => [entry.jid, entry.deviceJids]));
47
- const merged = normalizedUsers.map((jid) => ({
48
- jid,
49
- deviceJids: parsedByUser.get(jid) ?? cachedByUser.get(jid) ?? []
50
- }));
54
+ const batch = new Array(parsed.length);
55
+ for (let index = 0; index < parsed.length; index += 1) {
56
+ const entry = parsed[index];
57
+ batch[index] = {
58
+ userJid: entry.jid,
59
+ deviceJids: entry.deviceJids,
60
+ updatedAtMs
61
+ };
62
+ }
63
+ await this.deviceListStore.upsertUserDevicesBatch(batch);
64
+ }
65
+ const parsedByUser = new Map();
66
+ for (let index = 0; index < parsed.length; index += 1) {
67
+ const entry = parsed[index];
68
+ parsedByUser.set(entry.jid, entry.deviceJids);
69
+ }
70
+ const merged = new Array(normalizedUsers.length);
71
+ let totalDevices = 0;
72
+ for (let index = 0; index < normalizedUsers.length; index += 1) {
73
+ const jid = normalizedUsers[index];
74
+ const deviceJids = parsedByUser.get(jid) ?? cachedByUser.get(jid) ?? [];
75
+ totalDevices += deviceJids.length;
76
+ merged[index] = {
77
+ jid,
78
+ deviceJids
79
+ };
80
+ }
51
81
  this.logger.debug('signal device sync success', {
52
82
  users: merged.length,
53
- devices: merged.reduce((total, entry) => total + entry.deviceJids.length, 0)
83
+ devices: totalDevices
54
84
  });
55
85
  return merged;
56
86
  }
87
+ async queryLidsByPhoneJids(phoneJids, timeoutMs = this.defaultTimeoutMs) {
88
+ const normalizedPhoneJids = this.normalizeUsers(phoneJids);
89
+ if (normalizedPhoneJids.length === 0) {
90
+ return [];
91
+ }
92
+ const sid = await this.generateSid();
93
+ const request = this.makeLidSyncRequest(normalizedPhoneJids, sid);
94
+ this.logger.debug('signal lid sync request', {
95
+ users: normalizedPhoneJids.length,
96
+ timeoutMs
97
+ });
98
+ const response = await this.query(request, timeoutMs);
99
+ const parsed = this.parseLidSyncResponse(response, normalizedPhoneJids);
100
+ const parsedByPhoneJid = new Map();
101
+ for (let index = 0; index < parsed.length; index += 1) {
102
+ const entry = parsed[index];
103
+ const phoneJid = entry.phoneJid ?? entry.jid;
104
+ parsedByPhoneJid.set(phoneJid, {
105
+ phoneJid,
106
+ lidJid: entry.lidJid,
107
+ exists: entry.exists
108
+ });
109
+ }
110
+ const result = new Array(normalizedPhoneJids.length);
111
+ let found = 0;
112
+ for (let index = 0; index < normalizedPhoneJids.length; index += 1) {
113
+ const phoneJid = normalizedPhoneJids[index];
114
+ const resolved = parsedByPhoneJid.get(phoneJid) ?? {
115
+ phoneJid,
116
+ lidJid: null,
117
+ exists: false
118
+ };
119
+ if (resolved.exists) {
120
+ found += 1;
121
+ }
122
+ result[index] = resolved;
123
+ }
124
+ this.logger.debug('signal lid sync success', {
125
+ users: result.length,
126
+ found
127
+ });
128
+ return result;
129
+ }
57
130
  async collectUsersToQuery(normalizedUsers, nowMs, cachedByUser, store) {
58
131
  const records = await store.getUserDevicesBatch(normalizedUsers, nowMs);
59
- const usersToQuery = [];
132
+ const usersToQuery = new Array(normalizedUsers.length);
133
+ let usersToQueryCount = 0;
60
134
  for (let index = 0; index < normalizedUsers.length; index += 1) {
61
135
  const userJid = normalizedUsers[index];
62
136
  const record = records[index];
63
137
  if (!record) {
64
- usersToQuery.push(userJid);
138
+ usersToQuery[usersToQueryCount] = userJid;
139
+ usersToQueryCount += 1;
65
140
  continue;
66
141
  }
67
142
  cachedByUser.set(userJid, record.deviceJids);
68
143
  }
144
+ usersToQuery.length = usersToQueryCount;
69
145
  return usersToQuery;
70
146
  }
71
- makeDeviceSyncRequest(userJids) {
72
- return buildIqNode('get', this.hostDomain, WA_XMLNS.USYNC, [
73
- {
74
- tag: WA_NODE_TAGS.USYNC,
75
- attrs: {
76
- sid: this.makeSid(),
77
- index: '0',
78
- last: 'true',
79
- mode: WA_NODE_TAGS.QUERY,
80
- context: 'interactive'
81
- },
147
+ makeDeviceSyncRequest(userJids, sid) {
148
+ const users = new Array(userJids.length);
149
+ for (let index = 0; index < userJids.length; index += 1) {
150
+ users[index] = {
151
+ jid: userJids[index]
152
+ };
153
+ }
154
+ return buildUsyncIq({
155
+ sid,
156
+ hostDomain: this.hostDomain,
157
+ context: WA_USYNC_CONTEXTS.INTERACTIVE,
158
+ queryProtocolNodes: [
159
+ {
160
+ tag: WA_NODE_TAGS.DEVICES,
161
+ attrs: {
162
+ version: '2'
163
+ }
164
+ }
165
+ ],
166
+ users
167
+ });
168
+ }
169
+ makeLidSyncRequest(userJids, sid) {
170
+ const users = new Array(userJids.length);
171
+ for (let index = 0; index < userJids.length; index += 1) {
172
+ const jid = userJids[index];
173
+ users[index] = {
174
+ jid,
82
175
  content: [
83
176
  {
84
- tag: WA_NODE_TAGS.QUERY,
177
+ tag: WA_NODE_TAGS.CONTACT,
85
178
  attrs: {},
86
- content: [
87
- {
88
- tag: WA_NODE_TAGS.DEVICES,
89
- attrs: {
90
- version: '2'
91
- }
92
- }
93
- ]
94
- },
95
- {
96
- tag: WA_NODE_TAGS.LIST,
97
- attrs: {},
98
- content: userJids.map((jid) => ({
99
- tag: WA_NODE_TAGS.USER,
100
- attrs: { jid }
101
- }))
179
+ content: splitJid(jid).user
102
180
  }
103
181
  ]
104
- }
105
- ]);
182
+ };
183
+ }
184
+ return buildUsyncIq({
185
+ sid,
186
+ hostDomain: this.hostDomain,
187
+ context: WA_USYNC_CONTEXTS.INTERACTIVE,
188
+ queryProtocolNodes: [
189
+ {
190
+ tag: WA_NODE_TAGS.CONTACT,
191
+ attrs: {}
192
+ },
193
+ {
194
+ tag: WA_NODE_TAGS.LID,
195
+ attrs: {}
196
+ }
197
+ ],
198
+ users
199
+ });
106
200
  }
107
201
  parseDeviceSyncResponse(node, requestedUsers) {
108
202
  assertIqResult(node, 'signal device sync');
@@ -116,24 +210,105 @@ export class SignalDeviceSyncApi {
116
210
  }
117
211
  const requestedSet = new Set(requestedUsers);
118
212
  const userNodes = getNodeChildrenByTag(listNode, WA_NODE_TAGS.USER);
119
- return userNodes.flatMap((userNode) => {
213
+ const parsed = new Array(userNodes.length);
214
+ let parsedCount = 0;
215
+ for (let index = 0; index < userNodes.length; index += 1) {
216
+ const userNode = userNodes[index];
120
217
  const userJid = userNode.attrs.jid;
121
218
  if (!userJid) {
122
- return [];
219
+ continue;
123
220
  }
124
221
  const normalizedUserJid = this.normalizeUserJid(userJid);
125
222
  if (!requestedSet.has(normalizedUserJid)) {
126
- return [];
223
+ continue;
127
224
  }
128
- return [
129
- {
225
+ parsed[parsedCount] = {
226
+ jid: normalizedUserJid,
227
+ deviceJids: this.parseUserDeviceJids(userNode, userJid, normalizedUserJid)
228
+ };
229
+ parsedCount += 1;
230
+ }
231
+ parsed.length = parsedCount;
232
+ return parsed;
233
+ }
234
+ parseLidSyncResponse(node, requestedUsers) {
235
+ assertIqResult(node, 'signal lid sync');
236
+ const usyncNode = findNodeChild(node, WA_NODE_TAGS.USYNC);
237
+ if (!usyncNode) {
238
+ throw new Error('signal lid sync response missing usync node');
239
+ }
240
+ const listNode = findNodeChild(usyncNode, WA_NODE_TAGS.LIST);
241
+ if (!listNode) {
242
+ throw new Error('signal lid sync response missing list node');
243
+ }
244
+ const requestedSet = new Set(requestedUsers);
245
+ const userNodes = getNodeChildrenByTag(listNode, WA_NODE_TAGS.USER);
246
+ const parsed = new Array(userNodes.length);
247
+ let parsedCount = 0;
248
+ for (let index = 0; index < userNodes.length; index += 1) {
249
+ const userNode = userNodes[index];
250
+ const userJid = userNode.attrs.jid;
251
+ if (!userJid) {
252
+ continue;
253
+ }
254
+ const normalizedUserJid = this.normalizeUserJid(userJid);
255
+ const normalizedPhoneJid = userNode.attrs.pn_jid
256
+ ? this.normalizeUserJid(userNode.attrs.pn_jid)
257
+ : null;
258
+ const wasRequested = requestedSet.has(normalizedUserJid) ||
259
+ (normalizedPhoneJid !== null && requestedSet.has(normalizedPhoneJid));
260
+ if (!wasRequested) {
261
+ continue;
262
+ }
263
+ const lidNode = findNodeChild(userNode, WA_NODE_TAGS.LID);
264
+ const contactNode = findNodeChild(userNode, WA_NODE_TAGS.CONTACT);
265
+ if (!lidNode) {
266
+ parsed[parsedCount] = this.buildLidSyncResult(normalizedUserJid, normalizedPhoneJid, contactNode, null);
267
+ parsedCount += 1;
268
+ continue;
269
+ }
270
+ const errorNode = findNodeChild(lidNode, WA_NODE_TAGS.ERROR);
271
+ if (errorNode) {
272
+ this.logger.warn('signal lid sync user error', {
130
273
  jid: normalizedUserJid,
131
- deviceJids: this.parseUserDeviceJids(userNode, normalizedUserJid)
132
- }
133
- ];
134
- });
274
+ code: errorNode.attrs.code,
275
+ text: errorNode.attrs.text
276
+ });
277
+ parsed[parsedCount] = this.buildLidSyncResult(normalizedUserJid, normalizedPhoneJid, contactNode, null);
278
+ parsedCount += 1;
279
+ continue;
280
+ }
281
+ const lidJid = lidNode.attrs.val ? this.normalizeUserJid(lidNode.attrs.val) : null;
282
+ parsed[parsedCount] = this.buildLidSyncResult(normalizedUserJid, normalizedPhoneJid, contactNode, lidJid);
283
+ parsedCount += 1;
284
+ }
285
+ parsed.length = parsedCount;
286
+ return parsed;
135
287
  }
136
- parseUserDeviceJids(userNode, userJid) {
288
+ buildLidSyncResult(jid, phoneJid, contactNode, lidJid) {
289
+ return {
290
+ jid,
291
+ lidJid,
292
+ phoneJid,
293
+ exists: this.parseLidSyncContactExists(contactNode, jid, lidJid !== null)
294
+ };
295
+ }
296
+ parseLidSyncContactExists(contactNode, userJid, defaultExists) {
297
+ if (!contactNode) {
298
+ return defaultExists;
299
+ }
300
+ const errorNode = findNodeChild(contactNode, WA_NODE_TAGS.ERROR);
301
+ if (errorNode) {
302
+ this.logger.warn('signal lid sync contact error', {
303
+ jid: userJid,
304
+ code: errorNode.attrs.code,
305
+ text: errorNode.attrs.text
306
+ });
307
+ return false;
308
+ }
309
+ return contactNode.attrs.type === 'in';
310
+ }
311
+ parseUserDeviceJids(userNode, rawUserJid, normalizedUserJid) {
137
312
  const devicesNode = findNodeChild(userNode, WA_NODE_TAGS.DEVICES);
138
313
  if (!devicesNode) {
139
314
  return [];
@@ -141,7 +316,7 @@ export class SignalDeviceSyncApi {
141
316
  const errorNode = findNodeChild(devicesNode, WA_NODE_TAGS.ERROR);
142
317
  if (errorNode) {
143
318
  this.logger.warn('signal device sync user error', {
144
- jid: userJid,
319
+ jid: normalizedUserJid,
145
320
  code: errorNode.attrs.code,
146
321
  text: errorNode.attrs.text
147
322
  });
@@ -151,35 +326,44 @@ export class SignalDeviceSyncApi {
151
326
  if (!deviceListNode) {
152
327
  return [];
153
328
  }
154
- return [
155
- ...new Set(getNodeChildrenByTag(deviceListNode, 'device')
156
- .map((deviceNode) => {
157
- const parsedId = deviceNode.attrs.id
158
- ? Number.parseInt(deviceNode.attrs.id, 10)
159
- : Number.NaN;
160
- return Number.isSafeInteger(parsedId) && parsedId >= 0
161
- ? this.toDeviceJid(userJid, parsedId)
162
- : null;
163
- })
164
- .filter((jid) => jid !== null))
165
- ];
329
+ const parsedNormalizedUser = splitJid(normalizedUserJid);
330
+ const parsedRawUser = splitJid(rawUserJid);
331
+ const dedup = new Set();
332
+ for (const deviceNode of getNodeChildrenByTag(deviceListNode, 'device')) {
333
+ const parsedId = deviceNode.attrs.id
334
+ ? Number.parseInt(deviceNode.attrs.id, 10)
335
+ : Number.NaN;
336
+ if (!Number.isSafeInteger(parsedId) || parsedId < 0) {
337
+ continue;
338
+ }
339
+ const isHostedDevice = isHostedDeviceId(parsedId) || deviceNode.attrs.is_hosted === 'true';
340
+ dedup.add(buildDeviceJid(parsedNormalizedUser.user, parsedNormalizedUser.server, parsedId, {
341
+ rawServer: parsedRawUser.server,
342
+ isHosted: isHostedDevice
343
+ }));
344
+ }
345
+ return Array.from(dedup);
166
346
  }
167
347
  normalizeUsers(userJids) {
168
- return [...new Set(userJids.map((jid) => this.normalizeUserJid(jid)))];
169
- }
170
- normalizeUserJid(jid) {
171
- const { user } = parseSignalAddressFromJid(jid);
172
- const { server } = splitJid(jid);
173
- return `${user}@${server}`;
174
- }
175
- toDeviceJid(userJid, deviceId) {
176
- const parsed = splitJid(userJid);
177
- if (deviceId === 0) {
178
- return `${parsed.user}@${parsed.server}`;
348
+ const normalized = new Array(userJids.length);
349
+ let normalizedCount = 0;
350
+ const dedup = new Set();
351
+ for (let index = 0; index < userJids.length; index += 1) {
352
+ const normalizedJid = this.normalizeUserJid(userJids[index]);
353
+ if (dedup.has(normalizedJid)) {
354
+ continue;
355
+ }
356
+ dedup.add(normalizedJid);
357
+ normalized[normalizedCount] = normalizedJid;
358
+ normalizedCount += 1;
179
359
  }
180
- return `${parsed.user}:${deviceId}@${parsed.server}`;
360
+ normalized.length = normalizedCount;
361
+ return normalized;
181
362
  }
182
- makeSid() {
183
- return `${Date.now()}.${randomInt(1000000)}`;
363
+ normalizeUserJid(jid) {
364
+ return toUserJid(jid, {
365
+ canonicalizeSignalServer: true,
366
+ hostDomain: this.hostDomain
367
+ });
184
368
  }
185
369
  }
@@ -14,8 +14,10 @@ export class SignalDigestSyncApi {
14
14
  options.defaultTimeoutMs ?? WA_DEFAULTS.SIGNAL_FETCH_KEY_BUNDLES_TIMEOUT_MS;
15
15
  this.hostDomain = options.hostDomain ?? WA_DEFAULTS.HOST_DOMAIN;
16
16
  }
17
- async validateLocalKeyBundle(timeoutMs = this.defaultTimeoutMs) {
18
- this.logger.debug('signal digest query request', { timeoutMs });
17
+ async validateLocalKeyBundle(prefetchedOrTimeout, timeoutMs = this.defaultTimeoutMs) {
18
+ const prefetched = typeof prefetchedOrTimeout === 'number' ? undefined : prefetchedOrTimeout;
19
+ const effectiveTimeoutMs = typeof prefetchedOrTimeout === 'number' ? prefetchedOrTimeout : timeoutMs;
20
+ this.logger.debug('signal digest query request', { timeoutMs: effectiveTimeoutMs });
19
21
  const response = await this.query({
20
22
  tag: WA_NODE_TAGS.IQ,
21
23
  attrs: {
@@ -29,7 +31,7 @@ export class SignalDigestSyncApi {
29
31
  attrs: {}
30
32
  }
31
33
  ]
32
- }, timeoutMs);
34
+ }, effectiveTimeoutMs);
33
35
  if (response.tag !== WA_NODE_TAGS.IQ) {
34
36
  throw new Error(`invalid signal digest response tag: ${response.tag}`);
35
37
  }
@@ -58,10 +60,12 @@ export class SignalDigestSyncApi {
58
60
  preKeyCount: digest.preKeyIds.length
59
61
  };
60
62
  }
61
- const [registrationInfo, signedPreKey] = await Promise.all([
62
- this.signalStore.getRegistrationInfo(),
63
- this.signalStore.getSignedPreKey()
64
- ]);
63
+ const [registrationInfo, signedPreKey] = prefetched
64
+ ? [prefetched.registrationInfo, prefetched.signedPreKey]
65
+ : await Promise.all([
66
+ this.signalStore.getRegistrationInfo(),
67
+ this.signalStore.getSignedPreKey()
68
+ ]);
65
69
  if (!registrationInfo || !signedPreKey) {
66
70
  return {
67
71
  valid: false,
@@ -161,7 +165,12 @@ export class SignalDigestSyncApi {
161
165
  const signedKeyId = parseUint(decodeExactLength(signedKeyIdNode.content, 'signal digest skey.id', SIGNAL_KEY_ID_LENGTH), 'signal digest skey.id');
162
166
  const signedKeyPublicKey = decodeExactLength(signedKeyValueNode.content, 'signal digest skey.value', SIGNAL_KEY_DATA_LENGTH);
163
167
  const signedKeySignature = decodeExactLength(signedKeySignatureNode.content, 'signal digest skey.signature', SIGNAL_SIGNATURE_LENGTH);
164
- const preKeyIds = getNodeChildren(listNode).map((child, index) => parseUint(decodeExactLength(child.content, `signal digest list[${index}]`, SIGNAL_KEY_ID_LENGTH), `signal digest list[${index}]`));
168
+ const listChildren = getNodeChildren(listNode);
169
+ const preKeyIds = new Array(listChildren.length);
170
+ for (let index = 0; index < listChildren.length; index += 1) {
171
+ const child = listChildren[index];
172
+ preKeyIds[index] = parseUint(decodeExactLength(child.content, `signal digest list[${index}]`, SIGNAL_KEY_ID_LENGTH), `signal digest list[${index}]`);
173
+ }
165
174
  const hash = decodeNodeContentBase64OrBytes(hashNode.content, 'signal digest hash');
166
175
  return {
167
176
  registrationId,
@@ -1,11 +1,14 @@
1
1
  import { toSerializedPubKey } from '../../crypto/core/keys.js';
2
+ import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
2
3
  import { WA_DEFAULTS, WA_IQ_TYPES, WA_NODE_TAGS, WA_XMLNS } from '../../protocol/constants.js';
3
- import { normalizeDeviceJid, parseSignalAddressFromJid } from '../../protocol/jid.js';
4
+ import { canonicalizeSignalJid, parseSignalAddressFromJid } from '../../protocol/jid.js';
4
5
  import { decodeExactLength, parseUint } from '../api/codec.js';
5
6
  import { SIGNAL_KEY_BUNDLE_TYPE_LENGTH, SIGNAL_KEY_DATA_LENGTH } from '../api/constants.js';
6
7
  import { findNodeChild, getNodeChildrenByTag } from '../../transport/node/helpers.js';
8
+ import { assertIqResult } from '../../transport/node/query.js';
7
9
  export class SignalIdentitySyncApi {
8
10
  constructor(options) {
11
+ this.syncDedup = new PromiseDedup();
9
12
  this.logger = options.logger;
10
13
  this.query = options.query;
11
14
  this.signalStore = options.signalStore;
@@ -13,11 +16,36 @@ export class SignalIdentitySyncApi {
13
16
  options.defaultTimeoutMs ?? WA_DEFAULTS.SIGNAL_FETCH_KEY_BUNDLES_TIMEOUT_MS;
14
17
  this.hostDomain = options.hostDomain ?? WA_DEFAULTS.HOST_DOMAIN;
15
18
  }
16
- async syncIdentityKeys(targetJids, timeoutMs = this.defaultTimeoutMs) {
17
- const normalizedTargets = [...new Set(targetJids.map((jid) => normalizeDeviceJid(jid)))];
19
+ syncIdentityKeys(targetJids, timeoutMs = this.defaultTimeoutMs) {
20
+ const dedupKey = `${timeoutMs}:${targetJids.join(',')}`;
21
+ return this.syncDedup.run(dedupKey, () => this.syncIdentityKeysInternal(targetJids, timeoutMs));
22
+ }
23
+ async syncIdentityKeysInternal(targetJids, timeoutMs) {
24
+ const normalizedTargets = new Array(targetJids.length);
25
+ let normalizedTargetsCount = 0;
26
+ const dedup = new Set();
27
+ for (let index = 0; index < targetJids.length; index += 1) {
28
+ const normalized = canonicalizeSignalJid(targetJids[index], this.hostDomain);
29
+ if (dedup.has(normalized)) {
30
+ continue;
31
+ }
32
+ dedup.add(normalized);
33
+ normalizedTargets[normalizedTargetsCount] = normalized;
34
+ normalizedTargetsCount += 1;
35
+ }
36
+ normalizedTargets.length = normalizedTargetsCount;
18
37
  if (normalizedTargets.length === 0) {
19
38
  return [];
20
39
  }
40
+ const users = new Array(normalizedTargets.length);
41
+ for (let index = 0; index < normalizedTargets.length; index += 1) {
42
+ users[index] = {
43
+ tag: WA_NODE_TAGS.USER,
44
+ attrs: {
45
+ jid: normalizedTargets[index]
46
+ }
47
+ };
48
+ }
21
49
  this.logger.debug('signal identity sync request', {
22
50
  targets: normalizedTargets.length,
23
51
  timeoutMs
@@ -33,20 +61,22 @@ export class SignalIdentitySyncApi {
33
61
  {
34
62
  tag: WA_NODE_TAGS.IDENTITY,
35
63
  attrs: {},
36
- content: normalizedTargets.map((jid) => ({
37
- tag: WA_NODE_TAGS.USER,
38
- attrs: { jid }
39
- }))
64
+ content: users
40
65
  }
41
66
  ]
42
67
  }, timeoutMs);
43
68
  const entries = this.parseIdentitySyncResponse(response, normalizedTargets);
44
69
  const { signalStore } = this;
45
70
  if (signalStore && entries.length > 0) {
46
- await signalStore.setRemoteIdentities(entries.map((entry) => ({
47
- address: parseSignalAddressFromJid(entry.jid),
48
- identityKey: toSerializedPubKey(entry.identity)
49
- })));
71
+ const identities = new Array(entries.length);
72
+ for (let index = 0; index < entries.length; index += 1) {
73
+ const entry = entries[index];
74
+ identities[index] = {
75
+ address: parseSignalAddressFromJid(entry.jid),
76
+ identityKey: toSerializedPubKey(entry.identity)
77
+ };
78
+ }
79
+ await signalStore.setRemoteIdentities(identities);
50
80
  }
51
81
  this.logger.debug('signal identity sync success', {
52
82
  requested: normalizedTargets.length,
@@ -55,31 +85,22 @@ export class SignalIdentitySyncApi {
55
85
  return entries;
56
86
  }
57
87
  parseIdentitySyncResponse(node, requestedJids) {
58
- if (node.tag !== WA_NODE_TAGS.IQ) {
59
- throw new Error(`invalid identity sync response tag: ${node.tag}`);
60
- }
61
- if (node.attrs.type === WA_IQ_TYPES.ERROR) {
62
- const errorNode = findNodeChild(node, WA_NODE_TAGS.ERROR);
63
- if (!errorNode) {
64
- throw new Error(`identity sync iq error for ${node.attrs.id ?? 'unknown id'}`);
65
- }
66
- const code = errorNode.attrs.code ?? 'unknown';
67
- const text = errorNode.attrs.text ?? errorNode.attrs.type ?? 'unknown';
68
- throw new Error(`identity sync iq error (${code} ${text})`);
69
- }
70
- if (node.attrs.type !== WA_IQ_TYPES.RESULT) {
71
- throw new Error(`invalid identity sync response type: ${node.attrs.type ?? 'unknown'}`);
72
- }
88
+ assertIqResult(node, 'identity sync');
73
89
  const listNode = findNodeChild(node, WA_NODE_TAGS.LIST);
74
90
  if (!listNode) {
75
91
  throw new Error('identity sync response missing list node');
76
92
  }
77
93
  const requested = new Set(requestedJids);
78
94
  const userNodes = getNodeChildrenByTag(listNode, WA_NODE_TAGS.USER);
79
- return userNodes.flatMap((userNode) => {
80
- const jid = userNode.attrs.jid ? normalizeDeviceJid(userNode.attrs.jid) : '';
95
+ const parsed = new Array(userNodes.length);
96
+ let parsedCount = 0;
97
+ for (let index = 0; index < userNodes.length; index += 1) {
98
+ const userNode = userNodes[index];
99
+ const jid = userNode.attrs.jid
100
+ ? canonicalizeSignalJid(userNode.attrs.jid, this.hostDomain)
101
+ : '';
81
102
  if (!jid || !requested.has(jid)) {
82
- return [];
103
+ continue;
83
104
  }
84
105
  const errorNode = findNodeChild(userNode, WA_NODE_TAGS.ERROR);
85
106
  if (errorNode) {
@@ -88,7 +109,7 @@ export class SignalIdentitySyncApi {
88
109
  code: errorNode.attrs.code,
89
110
  text: errorNode.attrs.text
90
111
  });
91
- return [];
112
+ continue;
92
113
  }
93
114
  const identityNode = findNodeChild(userNode, WA_NODE_TAGS.IDENTITY);
94
115
  if (!identityNode) {
@@ -99,13 +120,22 @@ export class SignalIdentitySyncApi {
99
120
  const parsedType = typeNode
100
121
  ? parseUint(decodeExactLength(typeNode.content, 'identity sync type', SIGNAL_KEY_BUNDLE_TYPE_LENGTH), 'identity sync type')
101
122
  : undefined;
102
- return [
103
- {
123
+ if (parsedType === undefined) {
124
+ parsed[parsedCount] = {
104
125
  jid,
105
- identity,
106
- ...(parsedType !== undefined ? { type: parsedType } : {})
107
- }
108
- ];
109
- });
126
+ identity
127
+ };
128
+ parsedCount += 1;
129
+ continue;
130
+ }
131
+ parsed[parsedCount] = {
132
+ jid,
133
+ identity,
134
+ type: parsedType
135
+ };
136
+ parsedCount += 1;
137
+ }
138
+ parsed.length = parsedCount;
139
+ return parsed;
110
140
  }
111
141
  }