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,11 +1,12 @@
1
- import { APP_STATE_DEFAULT_COLLECTIONS, APP_STATE_EMPTY_LT_HASH } from './constants.js';
2
- import { keyIdToHex } from './utils.js';
1
+ import { APP_STATE_DEFAULT_COLLECTIONS, APP_STATE_DEFAULT_COLLECTION_VERSION, APP_STATE_EMPTY_LT_HASH } from './constants.js';
3
2
  import { WaAppStateCrypto } from './WaAppStateCrypto.js';
4
3
  import { parseSyncResponse } from './WaAppStateSyncResponseParser.js';
5
4
  import { proto } from '../proto.js';
6
5
  import { WA_APP_STATE_COLLECTION_STATES, WA_DEFAULTS, WA_IQ_TYPES, WA_NODE_TAGS, WA_XMLNS } from '../protocol/constants.js';
7
- import { decodeProtoBytes } from '../util/base64.js';
8
- import { uint8Equal } from '../util/bytes.js';
6
+ import { parseSignalAddressFromJid } from '../protocol/jid.js';
7
+ import { assertIqResult } from '../transport/node/query.js';
8
+ import { decodeProtoBytes } from '../util/bytes.js';
9
+ import { bytesToHex, uint8Equal } from '../util/bytes.js';
9
10
  import { longToNumber } from '../util/primitives.js';
10
11
  export class WaAppStateMissingKeyError extends Error {
11
12
  constructor(message, keyId, collection) {
@@ -20,6 +21,7 @@ export class WaAppStateSyncClient {
20
21
  this.logger = options.logger;
21
22
  this.query = options.query;
22
23
  this.store = options.store;
24
+ this.getCurrentMeJid = options.getCurrentMeJid;
23
25
  this.hostDomain = options.hostDomain ?? WA_DEFAULTS.HOST_DOMAIN;
24
26
  this.defaultTimeoutMs = options.defaultTimeoutMs ?? WA_DEFAULTS.APP_STATE_SYNC_TIMEOUT_MS;
25
27
  this.onMissingKeys = options.onMissingKeys;
@@ -46,7 +48,7 @@ export class WaAppStateSyncClient {
46
48
  const keyId = decodeProtoBytes(item.keyId?.keyId, 'appStateSyncKeyShare.keys[].keyId.keyId');
47
49
  if (!item.keyData?.keyData) {
48
50
  this.logger.debug('app-state sync key share entry missing key data', {
49
- keyId: keyIdToHex(keyId)
51
+ keyId: bytesToHex(keyId)
50
52
  });
51
53
  continue;
52
54
  }
@@ -89,6 +91,10 @@ export class WaAppStateSyncClient {
89
91
  ...new Set(options.collections ?? APP_STATE_DEFAULT_COLLECTIONS)
90
92
  ];
91
93
  try {
94
+ const initialCollectionStates = await this.store.getCollectionStates(collections);
95
+ for (let index = 0; index < collections.length; index += 1) {
96
+ context.collections.set(collections[index], initialCollectionStates[index]);
97
+ }
92
98
  this.logger.info('app-state sync start', {
93
99
  collections: collections.length,
94
100
  pendingMutations: options.pendingMutations?.length ?? 0
@@ -158,36 +164,18 @@ export class WaAppStateSyncClient {
158
164
  }
159
165
  }
160
166
  async syncCollectionsRound(collections, pendingByCollection, options) {
161
- const prepared = await this.prepareSyncRoundRequest(collections, pendingByCollection);
162
- const iqNode = this.buildSyncIqNode(prepared.collectionNodes);
163
- const payloadByCollection = await this.fetchSyncPayloadByCollection(iqNode, options.timeoutMs ?? this.defaultTimeoutMs);
164
- const collectionOutcomes = await Promise.all(collections.map((collection) => this.processCollectionRound({
165
- collection,
166
- payloadByCollection,
167
- pendingByCollection,
168
- options,
169
- outgoingContexts: prepared.outgoingContexts,
170
- skippedUploadCollections: prepared.skippedUploadCollections
171
- })));
172
- return {
173
- results: collectionOutcomes.map((entry) => entry.result),
174
- collectionsToRefetch: collectionOutcomes
175
- .filter((entry) => entry.shouldRefetch)
176
- .map((entry) => entry.collection),
177
- stateChanged: collectionOutcomes.some((entry) => entry.stateChanged),
178
- missingKeyIds: this.collectDistinctMissingKeyIds(collectionOutcomes
179
- .map((entry) => entry.missingKeyId)
180
- .filter((value) => value !== null)),
181
- blockedCollections: collectionOutcomes
182
- .filter((entry) => entry.result.state === WA_APP_STATE_COLLECTION_STATES.BLOCKED)
183
- .map((entry) => entry.collection)
184
- };
185
- }
186
- async prepareSyncRoundRequest(collections, pendingByCollection) {
187
- const requests = await Promise.all(collections.map((collection) => this.buildCollectionSyncRequest(collection, pendingByCollection)));
167
+ const activeSyncKey = await this.store.getActiveSyncKey();
168
+ const requestPromises = new Array(collections.length);
169
+ for (let index = 0; index < collections.length; index += 1) {
170
+ requestPromises[index] = this.buildCollectionSyncRequest(collections[index], pendingByCollection, activeSyncKey);
171
+ }
172
+ const requests = await Promise.all(requestPromises);
173
+ const collectionNodes = new Array(requests.length);
188
174
  const outgoingContexts = new Map();
189
175
  const skippedUploadCollections = new Set();
190
- for (const request of requests) {
176
+ for (let index = 0; index < requests.length; index += 1) {
177
+ const request = requests[index];
178
+ collectionNodes[index] = request.node;
191
179
  if (request.outgoingContext) {
192
180
  outgoingContexts.set(request.collection, request.outgoingContext);
193
181
  }
@@ -195,26 +183,62 @@ export class WaAppStateSyncClient {
195
183
  skippedUploadCollections.add(request.collection);
196
184
  }
197
185
  }
186
+ const iqNode = this.buildSyncIqNode(collectionNodes);
187
+ const payloadByCollection = await this.fetchSyncPayloadByCollection(iqNode, options.timeoutMs ?? this.defaultTimeoutMs);
188
+ const collectionOutcomePromises = new Array(collections.length);
189
+ for (let index = 0; index < collections.length; index += 1) {
190
+ collectionOutcomePromises[index] = this.processCollectionRound({
191
+ collection: collections[index],
192
+ payloadByCollection,
193
+ pendingByCollection,
194
+ options,
195
+ outgoingContexts,
196
+ skippedUploadCollections
197
+ });
198
+ }
199
+ const collectionOutcomes = await Promise.all(collectionOutcomePromises);
200
+ const results = [];
201
+ const collectionsToRefetch = [];
202
+ const blockedCollections = [];
203
+ const missingKeyIds = [];
204
+ const missingKeyIdHexes = new Set();
205
+ let stateChanged = false;
206
+ for (let index = 0; index < collectionOutcomes.length; index += 1) {
207
+ const entry = collectionOutcomes[index];
208
+ results.push(entry.result);
209
+ if (entry.shouldRefetch) {
210
+ collectionsToRefetch.push(entry.collection);
211
+ }
212
+ if (entry.stateChanged) {
213
+ stateChanged = true;
214
+ }
215
+ if (entry.result.state === WA_APP_STATE_COLLECTION_STATES.BLOCKED) {
216
+ blockedCollections.push(entry.collection);
217
+ }
218
+ if (entry.missingKeyId) {
219
+ const keyHex = bytesToHex(entry.missingKeyId);
220
+ if (!missingKeyIdHexes.has(keyHex)) {
221
+ missingKeyIdHexes.add(keyHex);
222
+ missingKeyIds.push(entry.missingKeyId);
223
+ }
224
+ }
225
+ }
198
226
  return {
199
- collectionNodes: requests.map((request) => request.node),
200
- outgoingContexts,
201
- skippedUploadCollections
227
+ results,
228
+ collectionsToRefetch,
229
+ stateChanged,
230
+ missingKeyIds,
231
+ blockedCollections
202
232
  };
203
233
  }
204
- async buildCollectionSyncRequest(collection, pendingByCollection) {
234
+ async buildCollectionSyncRequest(collection, pendingByCollection, activeSyncKey) {
205
235
  const collectionState = await this.getCollectionState(collection);
206
- const hasPersistedState = collectionState.version > 0 ||
207
- collectionState.indexValueMap.size > 0 ||
208
- !uint8Equal(collectionState.hash, APP_STATE_EMPTY_LT_HASH);
236
+ const hasPersistedState = collectionState.initialized;
209
237
  const attrs = {
210
- name: collection
238
+ name: collection,
239
+ version: String(hasPersistedState ? collectionState.version : APP_STATE_DEFAULT_COLLECTION_VERSION),
240
+ return_snapshot: hasPersistedState ? 'false' : 'true'
211
241
  };
212
- if (hasPersistedState) {
213
- attrs.version = String(collectionState.version);
214
- }
215
- else {
216
- attrs.return_snapshot = 'true';
217
- }
218
242
  const children = [];
219
243
  const pendingMutations = pendingByCollection.get(collection) ?? [];
220
244
  let outgoingContext;
@@ -228,7 +252,7 @@ export class WaAppStateSyncClient {
228
252
  });
229
253
  }
230
254
  else {
231
- const outgoing = await this.buildOutgoingPatch(collection, collectionState, pendingMutations);
255
+ const outgoing = await this.buildOutgoingPatch(collection, collectionState, pendingMutations, activeSyncKey);
232
256
  outgoingContext = outgoing.context;
233
257
  children.push({
234
258
  tag: WA_NODE_TAGS.PATCH,
@@ -271,6 +295,7 @@ export class WaAppStateSyncClient {
271
295
  tag: responseNode.tag,
272
296
  type: responseNode.attrs.type
273
297
  });
298
+ assertIqResult(responseNode, 'app-state sync');
274
299
  const payloads = parseSyncResponse(responseNode);
275
300
  this.logger.debug('app-state sync payloads parsed', { count: payloads.length });
276
301
  const payloadByCollection = new Map();
@@ -292,20 +317,16 @@ export class WaAppStateSyncClient {
292
317
  return this.createCollectionOutcome(collection, payload.state, payload.version);
293
318
  }
294
319
  const pendingMutationsCount = pendingByCollection.get(collection)?.length ?? 0;
295
- if (payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE) {
296
- shouldRefetch = true;
297
- }
298
- else if (payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT &&
299
- pendingMutationsCount > 0) {
300
- shouldRefetch = true;
301
- }
302
- if (payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT) {
303
- return this.createCollectionOutcome(collection, pendingMutationsCount > 0
304
- ? WA_APP_STATE_COLLECTION_STATES.CONFLICT
305
- : WA_APP_STATE_COLLECTION_STATES.SUCCESS, payload.version, shouldRefetch);
306
- }
307
- if (payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE) {
308
- return this.createCollectionOutcome(collection, payload.state, payload.version, shouldRefetch);
320
+ if (payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT ||
321
+ payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE) {
322
+ shouldRefetch =
323
+ payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE ||
324
+ pendingMutationsCount > 0;
325
+ return this.createCollectionOutcome(collection, payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT
326
+ ? pendingMutationsCount > 0
327
+ ? WA_APP_STATE_COLLECTION_STATES.CONFLICT
328
+ : WA_APP_STATE_COLLECTION_STATES.SUCCESS
329
+ : payload.state, payload.version, shouldRefetch);
309
330
  }
310
331
  try {
311
332
  let appliedMutations = [];
@@ -317,14 +338,14 @@ export class WaAppStateSyncClient {
317
338
  const snapshotBytes = await downloader(payload.collection, 'snapshot', payload.snapshotReference);
318
339
  const snapshot = this.validateSnapshot(payload.collection, proto.SyncdSnapshot.decode(snapshotBytes));
319
340
  const snapshotMutations = await this.applySnapshot(payload.collection, snapshot);
320
- appliedMutations = appliedMutations.concat(snapshotMutations);
341
+ appliedMutations.push(...snapshotMutations);
321
342
  collectionStateChanged = true;
322
343
  }
323
344
  if (payload.patches.length > 0) {
324
345
  const readyPatches = await this.resolveReadyPatches(payload, options);
325
346
  for (const readyPatch of readyPatches) {
326
347
  const patchMutations = await this.applyPatch(payload.collection, readyPatch);
327
- appliedMutations = appliedMutations.concat(patchMutations);
348
+ appliedMutations.push(...patchMutations);
328
349
  collectionStateChanged = true;
329
350
  }
330
351
  }
@@ -337,13 +358,17 @@ export class WaAppStateSyncClient {
337
358
  collectionStateChanged = true;
338
359
  }
339
360
  }
340
- if (payload.state === WA_APP_STATE_COLLECTION_STATES.SUCCESS_HAS_MORE) {
341
- shouldRefetch = true;
342
- }
343
- if (payload.state === WA_APP_STATE_COLLECTION_STATES.SUCCESS &&
344
- skippedUploadCollections.has(collection)) {
345
- shouldRefetch = true;
361
+ const currentCollectionState = await this.getCollectionState(collection);
362
+ if (!currentCollectionState.initialized &&
363
+ payload.state === WA_APP_STATE_COLLECTION_STATES.SUCCESS) {
364
+ this.setCollectionState(collection, payload.version ?? currentCollectionState.version, currentCollectionState.hash, currentCollectionState.indexValueMap);
365
+ collectionStateChanged = true;
346
366
  }
367
+ shouldRefetch =
368
+ shouldRefetch ||
369
+ payload.state === WA_APP_STATE_COLLECTION_STATES.SUCCESS_HAS_MORE ||
370
+ (payload.state === WA_APP_STATE_COLLECTION_STATES.SUCCESS &&
371
+ skippedUploadCollections.has(collection));
347
372
  this.logger.debug('app-state collection processed', {
348
373
  collection: payload.collection,
349
374
  state: payload.state,
@@ -382,24 +407,13 @@ export class WaAppStateSyncClient {
382
407
  }
383
408
  };
384
409
  }
385
- collectDistinctMissingKeyIds(keyIds) {
386
- const byHex = new Map();
387
- for (const keyId of keyIds) {
388
- const keyHex = keyIdToHex(keyId);
389
- if (byHex.has(keyHex)) {
390
- continue;
391
- }
392
- byHex.set(keyHex, keyId);
393
- }
394
- return [...byHex.values()];
395
- }
396
410
  async notifyMissingKeys(input) {
397
- const keyIds = this.collectDistinctMissingKeyIds(input.keyIds);
398
- const collections = [...new Set(input.collections)];
411
+ const keyIds = input.keyIds;
412
+ const collections = input.collections;
399
413
  if (keyIds.length === 0 || collections.length === 0) {
400
414
  return;
401
415
  }
402
- const keyIdsHex = keyIds.map((keyId) => keyIdToHex(keyId));
416
+ const keyIdsHex = keyIds.map((keyId) => bytesToHex(keyId));
403
417
  this.logger.info('app-state requesting missing sync keys', {
404
418
  keys: keyIdsHex.length,
405
419
  keyIds: keyIdsHex.join(','),
@@ -420,13 +434,12 @@ export class WaAppStateSyncClient {
420
434
  }
421
435
  }
422
436
  async resolveReadyPatches(payload, options) {
423
- const sortedPatches = payload.patches
424
- .map((patch) => ({
425
- patch,
426
- sortVersion: this.parseCollectionPatchVersion(payload.collection, patch)
427
- }))
428
- .sort((left, right) => left.sortVersion - right.sortVersion)
429
- .map((entry) => entry.patch);
437
+ const sortedPatches = payload.patches.slice();
438
+ const sortVersions = new Map();
439
+ for (const patch of sortedPatches) {
440
+ sortVersions.set(patch, this.parseCollectionPatchVersion(payload.collection, patch));
441
+ }
442
+ sortedPatches.sort((left, right) => sortVersions.get(left) - sortVersions.get(right));
430
443
  return Promise.all(sortedPatches.map(async (patch) => {
431
444
  let readyPatch = patch;
432
445
  if ((!readyPatch.mutations || readyPatch.mutations.length === 0) &&
@@ -492,13 +505,13 @@ export class WaAppStateSyncClient {
492
505
  const keyId = decodeProtoBytes(snapshot.keyId?.id, `snapshot.keyId.id (${collection})`);
493
506
  const keyData = await this.getKeyData(keyId);
494
507
  if (!keyData) {
495
- throw new WaAppStateMissingKeyError(`missing snapshot key ${keyIdToHex(keyId)} for ${collection}`, keyId, collection);
508
+ throw new WaAppStateMissingKeyError(`missing snapshot key ${bytesToHex(keyId)} for ${collection}`, keyId, collection);
496
509
  }
497
510
  const indexValueMap = new Map();
498
511
  const mutations = [];
499
512
  const decryptedRecords = await this.decryptSnapshotRecords(collection, snapshot);
500
513
  for (const { decrypted, recordKeyId } of decryptedRecords) {
501
- const indexMacHex = keyIdToHex(decrypted.indexMac);
514
+ const indexMacHex = bytesToHex(decrypted.indexMac);
502
515
  indexValueMap.set(indexMacHex, decrypted.valueMac);
503
516
  mutations.push({
504
517
  collection,
@@ -513,7 +526,13 @@ export class WaAppStateSyncClient {
513
526
  timestamp: this.normalizeProtoLong(decrypted.value?.timestamp, `snapshot.record.value.timestamp (${collection})`)
514
527
  });
515
528
  }
516
- const ltHash = await this.crypto.ltHashAdd(APP_STATE_EMPTY_LT_HASH, Array.from(indexValueMap.values()));
529
+ const ltHashInput = new Array(indexValueMap.size);
530
+ let ltHashInputIndex = 0;
531
+ for (const valueMac of indexValueMap.values()) {
532
+ ltHashInput[ltHashInputIndex] = valueMac;
533
+ ltHashInputIndex += 1;
534
+ }
535
+ const ltHash = await this.crypto.ltHashAdd(APP_STATE_EMPTY_LT_HASH, ltHashInput);
517
536
  const expectedSnapshotMac = await this.crypto.generateSnapshotMac(keyData, ltHash, version, collection);
518
537
  if (!uint8Equal(expectedSnapshotMac, snapshot.mac)) {
519
538
  throw new Error(`snapshot MAC mismatch for ${collection}`);
@@ -530,45 +549,69 @@ export class WaAppStateSyncClient {
530
549
  const patchKeyId = decodeProtoBytes(patch.keyId?.id, `patch.keyId.id (${collection})`);
531
550
  const patchKeyData = await this.getKeyData(patchKeyId);
532
551
  if (!patchKeyData) {
533
- throw new WaAppStateMissingKeyError(`missing patch key ${keyIdToHex(patchKeyId)} for ${collection}`, patchKeyId, collection);
552
+ throw new WaAppStateMissingKeyError(`missing patch key ${bytesToHex(patchKeyId)} for ${collection}`, patchKeyId, collection);
534
553
  }
535
554
  const decryptedMutations = await this.decryptPatchMutations(collection, patch);
536
- const nextState = await this.computeNextCollectionState(current.hash, current.indexValueMap, decryptedMutations.map((mutation) => ({
537
- operation: mutation.operationCode,
538
- indexMac: mutation.indexMac,
539
- valueMac: mutation.valueMac
540
- })), collection);
541
- await this.assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextState.hash, decryptedMutations);
555
+ const macMutations = new Array(decryptedMutations.length);
556
+ const valueMacs = new Array(decryptedMutations.length);
557
+ for (let index = 0; index < decryptedMutations.length; index += 1) {
558
+ const mutation = decryptedMutations[index];
559
+ valueMacs[index] = mutation.valueMac;
560
+ macMutations[index] = {
561
+ operation: mutation.operationCode,
562
+ indexMac: mutation.indexMac,
563
+ valueMac: mutation.valueMac
564
+ };
565
+ }
566
+ const nextState = await this.computeNextCollectionState(current.hash, current.indexValueMap, macMutations, collection);
567
+ await this.assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextState.hash, valueMacs);
542
568
  this.setCollectionState(collection, patchVersion, nextState.hash, nextState.indexValueMap);
543
- return decryptedMutations.map(({ operationCode, ...mutation }) => {
544
- void operationCode;
545
- return mutation;
546
- });
569
+ return decryptedMutations;
547
570
  }
548
571
  async decryptSnapshotRecords(collection, snapshot) {
549
- return Promise.all((snapshot.records ?? []).map(async (record) => {
550
- const indexMac = decodeProtoBytes(record.index?.blob, `snapshot.record.index.blob (${collection})`);
551
- const valueBlob = decodeProtoBytes(record.value?.blob, `snapshot.record.value.blob (${collection})`);
572
+ const rawRecords = snapshot.records ?? [];
573
+ const records = new Array(rawRecords.length);
574
+ const recordKeyIds = new Array(rawRecords.length);
575
+ for (let i = 0; i < rawRecords.length; i += 1) {
576
+ const record = rawRecords[i];
552
577
  const recordKeyId = decodeProtoBytes(record.keyId?.id, `snapshot.record.keyId.id (${collection})`);
553
- const recordKeyData = await this.getKeyData(recordKeyId);
554
- if (!recordKeyData) {
555
- throw new WaAppStateMissingKeyError(`missing snapshot mutation key ${keyIdToHex(recordKeyId)} for ${collection}`, recordKeyId, collection);
556
- }
557
- const decrypted = await this.crypto.decryptMutation({
558
- operation: proto.SyncdMutation.SyncdOperation.SET,
559
- keyId: recordKeyId,
560
- keyData: recordKeyData,
561
- indexMac,
562
- valueBlob
563
- });
564
- return {
565
- decrypted,
578
+ records[i] = {
579
+ indexMac: decodeProtoBytes(record.index?.blob, `snapshot.record.index.blob (${collection})`),
580
+ valueBlob: decodeProtoBytes(record.value?.blob, `snapshot.record.value.blob (${collection})`),
566
581
  recordKeyId
567
582
  };
568
- }));
583
+ recordKeyIds[i] = recordKeyId;
584
+ }
585
+ await this.preloadKeyData(recordKeyIds);
586
+ const decryptTasks = new Array(records.length);
587
+ for (let i = 0; i < records.length; i += 1) {
588
+ const { indexMac, valueBlob, recordKeyId } = records[i];
589
+ decryptTasks[i] = (async () => {
590
+ const recordKeyData = await this.getKeyData(recordKeyId);
591
+ if (!recordKeyData) {
592
+ throw new WaAppStateMissingKeyError(`missing snapshot mutation key ${bytesToHex(recordKeyId)} for ${collection}`, recordKeyId, collection);
593
+ }
594
+ const decrypted = await this.crypto.decryptMutation({
595
+ operation: proto.SyncdMutation.SyncdOperation.SET,
596
+ keyId: recordKeyId,
597
+ keyData: recordKeyData,
598
+ indexMac,
599
+ valueBlob
600
+ });
601
+ return {
602
+ decrypted,
603
+ recordKeyId
604
+ };
605
+ })();
606
+ }
607
+ return Promise.all(decryptTasks);
569
608
  }
570
609
  async decryptPatchMutations(collection, patch) {
571
- return Promise.all((patch.mutations ?? []).map(async (mutation) => {
610
+ const rawMutations = patch.mutations ?? [];
611
+ const parsedMutations = new Array(rawMutations.length);
612
+ const mutationKeyIds = new Array(rawMutations.length);
613
+ for (let i = 0; i < rawMutations.length; i += 1) {
614
+ const mutation = rawMutations[i];
572
615
  const operationCode = mutation.operation;
573
616
  if (operationCode === null || operationCode === undefined) {
574
617
  throw new Error(`patch mutation is missing operation (${collection})`);
@@ -577,51 +620,63 @@ export class WaAppStateSyncClient {
577
620
  if (!record) {
578
621
  throw new Error(`patch mutation is missing record (${collection})`);
579
622
  }
580
- const indexMac = decodeProtoBytes(record.index?.blob, `patch.record.index.blob (${collection})`);
581
- const valueBlob = decodeProtoBytes(record.value?.blob, `patch.record.value.blob (${collection})`);
582
623
  const recordKeyId = decodeProtoBytes(record.keyId?.id, `patch.record.keyId.id (${collection})`);
583
- const recordKeyData = await this.getKeyData(recordKeyId);
584
- if (!recordKeyData) {
585
- throw new WaAppStateMissingKeyError(`missing mutation key ${keyIdToHex(recordKeyId)} for ${collection}`, recordKeyId, collection);
586
- }
587
- const decrypted = await this.crypto.decryptMutation({
588
- operation: operationCode,
589
- keyId: recordKeyId,
590
- keyData: recordKeyData,
591
- indexMac,
592
- valueBlob
593
- });
594
- return {
595
- collection,
596
- operation: operationCode === proto.SyncdMutation.SyncdOperation.REMOVE
597
- ? 'remove'
598
- : 'set',
599
- source: 'patch',
624
+ parsedMutations[i] = {
600
625
  operationCode,
601
- index: decrypted.index,
602
- value: decrypted.value,
603
- version: decrypted.version,
604
- indexMac: decrypted.indexMac,
605
- valueMac: decrypted.valueMac,
606
- keyId: recordKeyId,
607
- timestamp: this.normalizeProtoLong(decrypted.value?.timestamp, `patch.record.value.timestamp (${collection})`)
626
+ indexMac: decodeProtoBytes(record.index?.blob, `patch.record.index.blob (${collection})`),
627
+ valueBlob: decodeProtoBytes(record.value?.blob, `patch.record.value.blob (${collection})`),
628
+ recordKeyId
608
629
  };
609
- }));
630
+ mutationKeyIds[i] = recordKeyId;
631
+ }
632
+ await this.preloadKeyData(mutationKeyIds);
633
+ const decryptTasks = new Array(parsedMutations.length);
634
+ for (let i = 0; i < parsedMutations.length; i += 1) {
635
+ const { operationCode, indexMac, valueBlob, recordKeyId } = parsedMutations[i];
636
+ decryptTasks[i] = (async () => {
637
+ const recordKeyData = await this.getKeyData(recordKeyId);
638
+ if (!recordKeyData) {
639
+ throw new WaAppStateMissingKeyError(`missing mutation key ${bytesToHex(recordKeyId)} for ${collection}`, recordKeyId, collection);
640
+ }
641
+ const decrypted = await this.crypto.decryptMutation({
642
+ operation: operationCode,
643
+ keyId: recordKeyId,
644
+ keyData: recordKeyData,
645
+ indexMac,
646
+ valueBlob
647
+ });
648
+ return {
649
+ collection,
650
+ operation: operationCode === proto.SyncdMutation.SyncdOperation.REMOVE
651
+ ? 'remove'
652
+ : 'set',
653
+ source: 'patch',
654
+ operationCode,
655
+ index: decrypted.index,
656
+ value: decrypted.value,
657
+ version: decrypted.version,
658
+ indexMac: decrypted.indexMac,
659
+ valueMac: decrypted.valueMac,
660
+ keyId: recordKeyId,
661
+ timestamp: this.normalizeProtoLong(decrypted.value?.timestamp, `patch.record.value.timestamp (${collection})`)
662
+ };
663
+ })();
664
+ }
665
+ return Promise.all(decryptTasks);
610
666
  }
611
- async assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextHash, decryptedMutations) {
667
+ async assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextHash, valueMacs) {
612
668
  const snapshotMac = decodeProtoBytes(patch.snapshotMac, `patch.snapshotMac (${collection})`);
613
669
  const expectedSnapshotMac = await this.crypto.generateSnapshotMac(patchKeyData, nextHash, patchVersion, collection);
614
670
  if (!uint8Equal(expectedSnapshotMac, snapshotMac)) {
615
671
  throw new Error(`patch snapshot MAC mismatch for ${collection}`);
616
672
  }
617
673
  const patchMac = decodeProtoBytes(patch.patchMac, `patch.patchMac (${collection})`);
618
- const expectedPatchMac = await this.crypto.generatePatchMac(patchKeyData, snapshotMac, decryptedMutations.map((mutation) => mutation.valueMac), patchVersion, collection);
674
+ const expectedPatchMac = await this.crypto.generatePatchMac(patchKeyData, snapshotMac, valueMacs, patchVersion, collection);
619
675
  if (!uint8Equal(expectedPatchMac, patchMac)) {
620
676
  throw new Error(`patch MAC mismatch for ${collection}`);
621
677
  }
622
678
  }
623
- async buildOutgoingPatch(collection, snapshot, pendingMutations) {
624
- const activeKey = await this.store.getActiveSyncKey();
679
+ async buildOutgoingPatch(collection, snapshot, pendingMutations, activeKey) {
625
680
  if (!activeKey) {
626
681
  throw new WaAppStateMissingKeyError(`no sync key available to upload ${collection}`, null, collection);
627
682
  }
@@ -640,29 +695,39 @@ export class WaAppStateSyncClient {
640
695
  });
641
696
  return { operationCode, encrypted };
642
697
  }));
643
- const encryptedMutations = encryptedResults.map(({ operationCode, encrypted }) => ({
644
- operation: operationCode,
645
- record: {
646
- keyId: { id: activeKey.keyId },
647
- index: { blob: encrypted.indexMac },
648
- value: { blob: encrypted.valueBlob }
649
- }
650
- }));
651
- const macMutations = encryptedResults.map(({ operationCode, encrypted }) => ({
652
- operation: operationCode,
653
- indexMac: encrypted.indexMac,
654
- valueMac: encrypted.valueMac
655
- }));
698
+ const encryptedMutations = new Array(encryptedResults.length);
699
+ const macMutations = new Array(encryptedResults.length);
700
+ const valueMacs = new Array(encryptedResults.length);
701
+ for (let i = 0; i < encryptedResults.length; i += 1) {
702
+ const { operationCode, encrypted } = encryptedResults[i];
703
+ encryptedMutations[i] = {
704
+ operation: operationCode,
705
+ record: {
706
+ keyId: { id: activeKey.keyId },
707
+ index: { blob: encrypted.indexMac },
708
+ value: { blob: encrypted.valueBlob }
709
+ }
710
+ };
711
+ macMutations[i] = {
712
+ operation: operationCode,
713
+ indexMac: encrypted.indexMac,
714
+ valueMac: encrypted.valueMac
715
+ };
716
+ valueMacs[i] = encrypted.valueMac;
717
+ }
656
718
  const nextState = await this.computeNextCollectionState(snapshot.hash, snapshot.indexValueMap, macMutations, collection);
657
719
  const patchVersion = snapshot.version + 1;
658
720
  const snapshotMac = await this.crypto.generateSnapshotMac(activeKey.keyData, nextState.hash, patchVersion, collection);
659
- const patchMac = await this.crypto.generatePatchMac(activeKey.keyData, snapshotMac, macMutations.map((item) => item.valueMac), patchVersion, collection);
721
+ const patchMac = await this.crypto.generatePatchMac(activeKey.keyData, snapshotMac, valueMacs, patchVersion, collection);
722
+ const deviceIndex = this.resolveDeviceIndex();
723
+ const clientDebugData = this.buildPatchClientDebugData();
660
724
  const encodedPatch = proto.SyncdPatch.encode({
661
- version: { version: patchVersion },
662
725
  mutations: encryptedMutations,
663
726
  snapshotMac,
664
727
  patchMac,
665
- keyId: { id: activeKey.keyId }
728
+ keyId: { id: activeKey.keyId },
729
+ ...(deviceIndex === undefined ? {} : { deviceIndex }),
730
+ clientDebugData
666
731
  }).finish();
667
732
  return {
668
733
  encodedPatch,
@@ -674,13 +739,35 @@ export class WaAppStateSyncClient {
674
739
  }
675
740
  };
676
741
  }
742
+ resolveDeviceIndex() {
743
+ const meJid = this.getCurrentMeJid?.();
744
+ if (!meJid) {
745
+ return undefined;
746
+ }
747
+ try {
748
+ return parseSignalAddressFromJid(meJid).device;
749
+ }
750
+ catch (error) {
751
+ this.logger.debug('app-state could not parse device index from me jid', {
752
+ meJid
753
+ });
754
+ void error;
755
+ return undefined;
756
+ }
757
+ }
758
+ buildPatchClientDebugData() {
759
+ return proto.PatchDebugData.encode({
760
+ isSenderPrimary: false,
761
+ senderPlatform: proto.PatchDebugData.Platform.WEB
762
+ }).finish();
763
+ }
677
764
  async computeNextCollectionState(baseHash, baseMap, mutations, collection) {
678
765
  const indexValueMap = new Map(baseMap);
679
766
  const addValues = [];
680
767
  const removeValues = [];
681
768
  let missingRemoveCount = 0;
682
769
  for (const mutation of mutations) {
683
- const indexMacHex = keyIdToHex(mutation.indexMac);
770
+ const indexMacHex = bytesToHex(mutation.indexMac);
684
771
  const existing = indexValueMap.get(indexMacHex);
685
772
  if (mutation.operation === proto.SyncdMutation.SyncdOperation.REMOVE) {
686
773
  if (!existing) {
@@ -745,9 +832,33 @@ export class WaAppStateSyncClient {
745
832
  }
746
833
  return compacted;
747
834
  }
835
+ async preloadKeyData(keyIds) {
836
+ if (keyIds.length === 0) {
837
+ return;
838
+ }
839
+ const context = this.requireSyncContext();
840
+ const missingKeyIds = [];
841
+ const missingKeyHexes = new Set();
842
+ for (let index = 0; index < keyIds.length; index += 1) {
843
+ const keyId = keyIds[index];
844
+ const keyHex = bytesToHex(keyId);
845
+ if (context.keys.has(keyHex) || missingKeyHexes.has(keyHex)) {
846
+ continue;
847
+ }
848
+ missingKeyHexes.add(keyHex);
849
+ missingKeyIds.push(keyId);
850
+ }
851
+ if (missingKeyIds.length === 0) {
852
+ return;
853
+ }
854
+ const loadedKeyData = await this.store.getSyncKeyDataBatch(missingKeyIds);
855
+ for (let index = 0; index < missingKeyIds.length; index += 1) {
856
+ context.keys.set(bytesToHex(missingKeyIds[index]), loadedKeyData[index] ?? null);
857
+ }
858
+ }
748
859
  async getKeyData(keyId) {
749
860
  const context = this.requireSyncContext();
750
- const keyHex = keyIdToHex(keyId);
861
+ const keyHex = bytesToHex(keyId);
751
862
  if (context.keys.has(keyHex)) {
752
863
  return context.keys.get(keyHex) ?? null;
753
864
  }
@@ -768,6 +879,7 @@ export class WaAppStateSyncClient {
768
879
  setCollectionState(collection, version, hash, indexValueMap) {
769
880
  const context = this.requireSyncContext();
770
881
  context.collections.set(collection, {
882
+ initialized: true,
771
883
  version,
772
884
  hash,
773
885
  indexValueMap