zapo-js 0.1.0 → 0.1.2

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 (366) hide show
  1. package/README.md +12 -7
  2. package/dist/appstate/WaAppStateCrypto.js +18 -25
  3. package/dist/appstate/WaAppStateSyncClient.js +181 -114
  4. package/dist/appstate/WaAppStateSyncResponseParser.js +16 -5
  5. package/dist/appstate/constants.js +4 -3
  6. package/dist/appstate/utils.js +10 -30
  7. package/dist/auth/WaAuthClient.js +48 -55
  8. package/dist/auth/flow/WaAuthCredentialsFlow.js +21 -14
  9. package/dist/auth/index.js +1 -3
  10. package/dist/auth/pairing/WaPairingFlow.js +21 -23
  11. package/dist/auth/pairing/WaQrFlow.js +37 -24
  12. package/dist/client/WaClient.js +103 -276
  13. package/dist/client/WaClientFactory.js +227 -110
  14. package/dist/client/connection/WaConnectionManager.js +292 -0
  15. package/dist/client/connection/WaKeyShareCoordinator.js +63 -0
  16. package/dist/client/connection/WaReceiptQueue.js +51 -0
  17. package/dist/client/coordinators/WaAppStateMutationCoordinator.js +471 -0
  18. package/dist/client/coordinators/WaGroupCoordinator.js +27 -17
  19. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +20 -27
  20. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +231 -686
  21. package/dist/client/coordinators/WaRetryCoordinator.js +70 -37
  22. package/dist/client/dirty.js +35 -29
  23. package/dist/client/events/chat.js +4 -3
  24. package/dist/client/events/group.js +59 -36
  25. package/dist/client/history-sync.js +53 -63
  26. package/dist/client/incoming.js +23 -20
  27. package/dist/client/mailbox.js +8 -8
  28. package/dist/client/messages.js +4 -4
  29. package/dist/client/messaging/fanout.js +189 -0
  30. package/dist/client/messaging/key-protocol.js +130 -0
  31. package/dist/client/messaging/participants.js +191 -0
  32. package/dist/crypto/core/hkdf.js +3 -8
  33. package/dist/crypto/core/index.js +1 -4
  34. package/dist/crypto/core/keys.js +2 -3
  35. package/dist/crypto/core/primitives.js +12 -15
  36. package/dist/crypto/core/random.js +7 -26
  37. package/dist/crypto/curves/Ed25519.js +7 -8
  38. package/dist/crypto/curves/X25519.js +13 -16
  39. package/dist/crypto/index.js +0 -5
  40. package/dist/esm/appstate/WaAppStateCrypto.js +6 -13
  41. package/dist/esm/appstate/WaAppStateSyncClient.js +174 -107
  42. package/dist/esm/appstate/WaAppStateSyncResponseParser.js +17 -6
  43. package/dist/esm/appstate/constants.js +3 -2
  44. package/dist/esm/appstate/utils.js +8 -27
  45. package/dist/esm/auth/WaAuthClient.js +48 -55
  46. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +21 -14
  47. package/dist/esm/auth/index.js +0 -1
  48. package/dist/esm/auth/pairing/WaPairingFlow.js +14 -16
  49. package/dist/esm/auth/pairing/WaQrFlow.js +37 -24
  50. package/dist/esm/client/WaClient.js +103 -276
  51. package/dist/esm/client/WaClientFactory.js +227 -110
  52. package/dist/esm/client/connection/WaConnectionManager.js +288 -0
  53. package/dist/esm/client/connection/WaKeyShareCoordinator.js +59 -0
  54. package/dist/esm/client/connection/WaReceiptQueue.js +47 -0
  55. package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +467 -0
  56. package/dist/esm/client/coordinators/WaGroupCoordinator.js +20 -10
  57. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +20 -27
  58. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +232 -687
  59. package/dist/esm/client/coordinators/WaRetryCoordinator.js +71 -38
  60. package/dist/esm/client/dirty.js +30 -24
  61. package/dist/esm/client/events/chat.js +4 -3
  62. package/dist/esm/client/events/group.js +50 -28
  63. package/dist/esm/client/history-sync.js +50 -60
  64. package/dist/esm/client/incoming.js +23 -20
  65. package/dist/esm/client/mailbox.js +8 -8
  66. package/dist/esm/client/messages.js +1 -1
  67. package/dist/esm/client/messaging/fanout.js +186 -0
  68. package/dist/esm/client/messaging/key-protocol.js +127 -0
  69. package/dist/esm/client/messaging/participants.js +188 -0
  70. package/dist/esm/crypto/core/hkdf.js +3 -8
  71. package/dist/esm/crypto/core/index.js +0 -1
  72. package/dist/esm/crypto/core/keys.js +2 -3
  73. package/dist/esm/crypto/core/primitives.js +12 -15
  74. package/dist/esm/crypto/core/random.js +6 -25
  75. package/dist/esm/crypto/curves/Ed25519.js +4 -5
  76. package/dist/esm/crypto/curves/X25519.js +10 -13
  77. package/dist/esm/crypto/index.js +0 -2
  78. package/dist/esm/infra/log/ConsoleLogger.js +18 -17
  79. package/dist/esm/infra/log/PinoLogger.js +15 -9
  80. package/dist/esm/infra/log/types.js +11 -1
  81. package/dist/esm/infra/perf/BoundedTaskQueue.js +13 -17
  82. package/dist/esm/media/WaMediaCrypto.js +2 -4
  83. package/dist/esm/media/WaMediaTransferClient.js +226 -58
  84. package/dist/esm/media/conn.js +10 -6
  85. package/dist/esm/media/constants.js +4 -1
  86. package/dist/esm/message/WaMessageClient.js +4 -13
  87. package/dist/esm/message/ack.js +6 -6
  88. package/dist/esm/message/addon-crypto.js +59 -0
  89. package/dist/esm/message/incoming.js +106 -111
  90. package/dist/esm/message/index.js +2 -0
  91. package/dist/esm/message/reporting-token.js +438 -0
  92. package/dist/esm/message/use-case-secret.js +49 -0
  93. package/dist/esm/protocol/appstate.js +58 -0
  94. package/dist/esm/protocol/constants.js +2 -1
  95. package/dist/esm/protocol/index.js +2 -10
  96. package/dist/esm/protocol/jid.js +63 -51
  97. package/dist/esm/protocol/media.js +3 -3
  98. package/dist/esm/protocol/nodes.js +2 -0
  99. package/dist/esm/protocol/usync.js +11 -0
  100. package/dist/esm/retry/index.js +1 -0
  101. package/dist/esm/retry/outbound.js +4 -5
  102. package/dist/esm/retry/parse.js +58 -76
  103. package/dist/esm/retry/replay.js +48 -49
  104. package/dist/esm/retry/tracker.js +56 -0
  105. package/dist/esm/signal/api/SignalDeviceSyncApi.js +249 -82
  106. package/dist/esm/signal/api/SignalDigestSyncApi.js +6 -1
  107. package/dist/esm/signal/api/SignalIdentitySyncApi.js +49 -34
  108. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +70 -62
  109. package/dist/esm/signal/api/SignalSessionSyncApi.js +23 -30
  110. package/dist/esm/signal/crypto/WaAdvSignature.js +3 -5
  111. package/dist/esm/signal/group/SenderKeyChain.js +28 -23
  112. package/dist/esm/signal/group/SenderKeyCodec.js +2 -4
  113. package/dist/esm/signal/group/SenderKeyManager.js +26 -16
  114. package/dist/esm/signal/index.js +1 -0
  115. package/dist/esm/signal/session/SignalProtocol.js +49 -14
  116. package/dist/esm/signal/session/SignalRatchet.js +24 -15
  117. package/dist/esm/signal/session/SignalSession.js +14 -9
  118. package/dist/esm/signal/session/resolver.js +186 -0
  119. package/dist/esm/signal/store/sqlite.js +16 -37
  120. package/dist/esm/store/createStore.js +16 -18
  121. package/dist/esm/store/noop.store.js +3 -6
  122. package/dist/esm/store/providers/memory/appstate.store.js +30 -6
  123. package/dist/esm/store/providers/memory/contact.store.js +5 -0
  124. package/dist/esm/store/providers/memory/device-list.store.js +3 -30
  125. package/dist/esm/store/providers/memory/message.store.js +11 -5
  126. package/dist/esm/store/providers/memory/participants.store.js +1 -8
  127. package/dist/esm/store/providers/memory/sender-key.store.js +5 -7
  128. package/dist/esm/store/providers/memory/signal.store.js +13 -1
  129. package/dist/esm/store/providers/memory/thread.store.js +5 -0
  130. package/dist/esm/store/providers/sqlite/appstate.store.js +82 -1
  131. package/dist/esm/store/providers/sqlite/connection.js +18 -13
  132. package/dist/esm/store/providers/sqlite/contact.store.js +31 -18
  133. package/dist/esm/store/providers/sqlite/device-list.store.js +7 -35
  134. package/dist/esm/store/providers/sqlite/message.store.js +45 -32
  135. package/dist/esm/store/providers/sqlite/migrations.js +1 -1
  136. package/dist/esm/store/providers/sqlite/participants.store.js +1 -9
  137. package/dist/esm/store/providers/sqlite/retry.store.js +8 -11
  138. package/dist/esm/store/providers/sqlite/sender-key.store.js +25 -30
  139. package/dist/esm/store/providers/sqlite/signal.store.js +104 -22
  140. package/dist/esm/store/providers/sqlite/table-names.js +107 -0
  141. package/dist/esm/store/providers/sqlite/thread.store.js +35 -22
  142. package/dist/esm/transport/WaComms.js +25 -23
  143. package/dist/esm/transport/WaWebSocket.js +115 -12
  144. package/dist/esm/transport/binary/decoder.js +4 -4
  145. package/dist/esm/transport/binary/encoder.js +12 -4
  146. package/dist/esm/transport/index.js +1 -0
  147. package/dist/esm/transport/keepalive/WaKeepAlive.js +2 -8
  148. package/dist/esm/transport/node/WaNodeOrchestrator.js +2 -4
  149. package/dist/esm/transport/node/WaNodeTransport.js +0 -3
  150. package/dist/esm/transport/node/builders/{accountSync.js → account-sync.js} +16 -36
  151. package/dist/esm/transport/node/builders/index.js +2 -1
  152. package/dist/esm/transport/node/builders/message.js +9 -0
  153. package/dist/esm/transport/node/builders/pairing.js +4 -5
  154. package/dist/esm/transport/node/builders/usync.js +41 -0
  155. package/dist/esm/transport/node/helpers.js +107 -5
  156. package/dist/esm/transport/node/usync.js +35 -0
  157. package/dist/esm/transport/noise/WaFrameCodec.js +48 -33
  158. package/dist/esm/transport/noise/WaNoiseCert.js +3 -6
  159. package/dist/esm/transport/noise/WaNoiseSession.js +17 -10
  160. package/dist/esm/transport/proxy.js +27 -0
  161. package/dist/esm/transport/stream/parse.js +13 -48
  162. package/dist/esm/util/bytes.js +50 -32
  163. package/dist/esm/util/coercion.js +6 -14
  164. package/dist/esm/util/primitives.js +39 -14
  165. package/dist/infra/log/ConsoleLogger.js +18 -17
  166. package/dist/infra/log/PinoLogger.js +15 -9
  167. package/dist/infra/log/types.js +12 -0
  168. package/dist/infra/perf/BoundedTaskQueue.js +13 -17
  169. package/dist/media/WaMediaCrypto.js +1 -3
  170. package/dist/media/WaMediaTransferClient.js +259 -58
  171. package/dist/media/conn.js +10 -6
  172. package/dist/media/constants.js +4 -1
  173. package/dist/message/WaMessageClient.js +5 -14
  174. package/dist/message/ack.js +6 -6
  175. package/dist/message/addon-crypto.js +65 -0
  176. package/dist/message/incoming.js +104 -109
  177. package/dist/message/index.js +2 -0
  178. package/dist/message/reporting-token.js +443 -0
  179. package/dist/message/use-case-secret.js +55 -0
  180. package/dist/protocol/appstate.js +59 -1
  181. package/dist/protocol/constants.js +7 -1
  182. package/dist/protocol/index.js +20 -42
  183. package/dist/protocol/jid.js +64 -51
  184. package/dist/protocol/media.js +3 -3
  185. package/dist/protocol/nodes.js +2 -0
  186. package/dist/protocol/usync.js +14 -0
  187. package/dist/retry/index.js +3 -1
  188. package/dist/retry/outbound.js +6 -7
  189. package/dist/retry/parse.js +57 -75
  190. package/dist/retry/replay.js +46 -47
  191. package/dist/retry/tracker.js +59 -0
  192. package/dist/signal/api/SignalDeviceSyncApi.js +247 -80
  193. package/dist/signal/api/SignalDigestSyncApi.js +6 -1
  194. package/dist/signal/api/SignalIdentitySyncApi.js +49 -34
  195. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +67 -59
  196. package/dist/signal/api/SignalSessionSyncApi.js +23 -30
  197. package/dist/signal/crypto/WaAdvSignature.js +2 -4
  198. package/dist/signal/group/SenderKeyChain.js +27 -22
  199. package/dist/signal/group/SenderKeyCodec.js +1 -3
  200. package/dist/signal/group/SenderKeyManager.js +26 -16
  201. package/dist/signal/index.js +3 -1
  202. package/dist/signal/session/SignalProtocol.js +49 -14
  203. package/dist/signal/session/SignalRatchet.js +24 -15
  204. package/dist/signal/session/SignalSession.js +14 -9
  205. package/dist/signal/session/resolver.js +189 -0
  206. package/dist/signal/store/sqlite.js +16 -37
  207. package/dist/store/createStore.js +16 -18
  208. package/dist/store/noop.store.js +3 -6
  209. package/dist/store/providers/memory/appstate.store.js +28 -4
  210. package/dist/store/providers/memory/contact.store.js +5 -0
  211. package/dist/store/providers/memory/device-list.store.js +3 -30
  212. package/dist/store/providers/memory/message.store.js +11 -5
  213. package/dist/store/providers/memory/participants.store.js +1 -8
  214. package/dist/store/providers/memory/sender-key.store.js +8 -10
  215. package/dist/store/providers/memory/signal.store.js +21 -9
  216. package/dist/store/providers/memory/thread.store.js +5 -0
  217. package/dist/store/providers/sqlite/appstate.store.js +81 -0
  218. package/dist/store/providers/sqlite/connection.js +18 -13
  219. package/dist/store/providers/sqlite/contact.store.js +31 -18
  220. package/dist/store/providers/sqlite/device-list.store.js +7 -35
  221. package/dist/store/providers/sqlite/message.store.js +45 -32
  222. package/dist/store/providers/sqlite/migrations.js +1 -1
  223. package/dist/store/providers/sqlite/participants.store.js +1 -9
  224. package/dist/store/providers/sqlite/retry.store.js +8 -11
  225. package/dist/store/providers/sqlite/sender-key.store.js +24 -29
  226. package/dist/store/providers/sqlite/signal.store.js +105 -23
  227. package/dist/store/providers/sqlite/table-names.js +113 -0
  228. package/dist/store/providers/sqlite/thread.store.js +35 -22
  229. package/dist/transport/WaComms.js +27 -25
  230. package/dist/transport/WaWebSocket.js +148 -12
  231. package/dist/transport/binary/decoder.js +4 -4
  232. package/dist/transport/binary/encoder.js +12 -4
  233. package/dist/transport/index.js +7 -1
  234. package/dist/transport/keepalive/WaKeepAlive.js +1 -7
  235. package/dist/transport/node/WaNodeOrchestrator.js +2 -4
  236. package/dist/transport/node/WaNodeTransport.js +0 -3
  237. package/dist/transport/node/builders/{accountSync.js → account-sync.js} +15 -35
  238. package/dist/transport/node/builders/index.js +12 -9
  239. package/dist/transport/node/builders/message.js +9 -0
  240. package/dist/transport/node/builders/pairing.js +4 -5
  241. package/dist/transport/node/builders/usync.js +45 -0
  242. package/dist/transport/node/helpers.js +112 -4
  243. package/dist/transport/node/usync.js +38 -0
  244. package/dist/transport/noise/WaFrameCodec.js +47 -32
  245. package/dist/transport/noise/WaNoiseCert.js +5 -8
  246. package/dist/transport/noise/WaNoiseSession.js +17 -10
  247. package/dist/transport/proxy.js +34 -0
  248. package/dist/transport/stream/parse.js +17 -53
  249. package/dist/types/appstate/WaAppStateCrypto.d.ts +0 -1
  250. package/dist/types/appstate/WaAppStateSyncClient.d.ts +5 -2
  251. package/dist/types/appstate/constants.d.ts +1 -0
  252. package/dist/types/appstate/store/sqlite.d.ts +4 -18
  253. package/dist/types/appstate/utils.d.ts +0 -1
  254. package/dist/types/auth/WaAuthClient.d.ts +10 -12
  255. package/dist/types/auth/index.d.ts +0 -2
  256. package/dist/types/auth/pairing/WaQrFlow.d.ts +1 -1
  257. package/dist/types/auth/types.d.ts +6 -9
  258. package/dist/types/client/WaClient.d.ts +27 -25
  259. package/dist/types/client/WaClientFactory.d.ts +22 -23
  260. package/dist/types/client/connection/WaConnectionManager.d.ts +64 -0
  261. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +14 -0
  262. package/dist/types/client/connection/WaReceiptQueue.d.ts +13 -0
  263. package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +46 -0
  264. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +0 -1
  265. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +18 -41
  266. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +2 -0
  267. package/dist/types/client/dirty.d.ts +1 -0
  268. package/dist/types/client/events/group.d.ts +2 -1
  269. package/dist/types/client/index.d.ts +1 -1
  270. package/dist/types/client/messaging/fanout.d.ts +14 -0
  271. package/dist/types/client/messaging/key-protocol.d.ts +18 -0
  272. package/dist/types/client/messaging/participants.d.ts +13 -0
  273. package/dist/types/client/types.d.ts +24 -1
  274. package/dist/types/crypto/core/hkdf.d.ts +0 -6
  275. package/dist/types/crypto/core/index.d.ts +0 -1
  276. package/dist/types/crypto/core/random.d.ts +1 -7
  277. package/dist/types/crypto/index.d.ts +0 -2
  278. package/dist/types/index.d.ts +1 -1
  279. package/dist/types/infra/log/ConsoleLogger.d.ts +2 -1
  280. package/dist/types/infra/log/PinoLogger.d.ts +1 -1
  281. package/dist/types/infra/log/types.d.ts +1 -0
  282. package/dist/types/infra/perf/BoundedTaskQueue.d.ts +1 -1
  283. package/dist/types/media/WaMediaTransferClient.d.ts +13 -3
  284. package/dist/types/media/types.d.ts +5 -0
  285. package/dist/types/message/addon-crypto.d.ts +25 -0
  286. package/dist/types/message/index.d.ts +2 -0
  287. package/dist/types/message/reporting-token.d.ts +19 -0
  288. package/dist/types/message/use-case-secret.d.ts +20 -0
  289. package/dist/types/protocol/appstate.d.ts +58 -0
  290. package/dist/types/protocol/constants.d.ts +2 -1
  291. package/dist/types/protocol/index.d.ts +2 -10
  292. package/dist/types/protocol/jid.d.ts +3 -3
  293. package/dist/types/protocol/nodes.d.ts +2 -0
  294. package/dist/types/protocol/usync.d.ts +11 -0
  295. package/dist/types/retry/index.d.ts +1 -0
  296. package/dist/types/retry/replay.d.ts +0 -4
  297. package/dist/types/retry/tracker.d.ts +19 -0
  298. package/dist/types/retry/types.d.ts +4 -3
  299. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +13 -1
  300. package/dist/types/signal/group/SenderKeyCodec.d.ts +4 -6
  301. package/dist/types/signal/index.d.ts +1 -0
  302. package/dist/types/signal/session/SignalProtocol.d.ts +9 -0
  303. package/dist/types/signal/session/resolver.d.ts +17 -0
  304. package/dist/types/store/contracts/appstate.store.d.ts +3 -0
  305. package/dist/types/store/contracts/contact.store.d.ts +1 -0
  306. package/dist/types/store/contracts/device-list.store.d.ts +0 -3
  307. package/dist/types/store/contracts/message.store.d.ts +1 -0
  308. package/dist/types/store/contracts/participants.store.d.ts +0 -1
  309. package/dist/types/store/contracts/sender-key.store.d.ts +0 -1
  310. package/dist/types/store/contracts/signal.store.d.ts +6 -0
  311. package/dist/types/store/contracts/thread.store.d.ts +1 -0
  312. package/dist/types/store/index.d.ts +1 -1
  313. package/dist/types/store/providers/memory/appstate.store.d.ts +2 -0
  314. package/dist/types/store/providers/memory/contact.store.d.ts +1 -0
  315. package/dist/types/store/providers/memory/device-list.store.d.ts +0 -3
  316. package/dist/types/store/providers/memory/message.store.d.ts +1 -0
  317. package/dist/types/store/providers/memory/participants.store.d.ts +0 -1
  318. package/dist/types/store/providers/memory/sender-key.store.d.ts +0 -1
  319. package/dist/types/store/providers/memory/signal.store.d.ts +6 -0
  320. package/dist/types/store/providers/memory/thread.store.d.ts +1 -0
  321. package/dist/types/store/providers/sqlite/appstate.store.d.ts +2 -0
  322. package/dist/types/store/providers/sqlite/contact.store.d.ts +2 -0
  323. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -3
  324. package/dist/types/store/providers/sqlite/message.store.d.ts +2 -0
  325. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -1
  326. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -1
  327. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -1
  328. package/dist/types/store/providers/sqlite/signal.store.d.ts +7 -0
  329. package/dist/types/store/providers/sqlite/table-names.d.ts +5 -0
  330. package/dist/types/store/providers/sqlite/thread.store.d.ts +2 -0
  331. package/dist/types/store/types.d.ts +3 -0
  332. package/dist/types/transport/WaWebSocket.d.ts +3 -0
  333. package/dist/types/transport/index.d.ts +2 -1
  334. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +0 -1
  335. package/dist/types/transport/node/WaNodeTransport.d.ts +0 -9
  336. package/dist/types/transport/node/builders/group.d.ts +4 -6
  337. package/dist/types/transport/node/builders/index.d.ts +2 -1
  338. package/dist/types/transport/node/builders/message.d.ts +14 -25
  339. package/dist/types/transport/node/builders/retry.d.ts +2 -4
  340. package/dist/types/transport/node/builders/usync.d.ts +21 -0
  341. package/dist/types/transport/node/helpers.d.ts +8 -0
  342. package/dist/types/transport/node/usync.d.ts +2 -0
  343. package/dist/types/transport/noise/WaFrameCodec.d.ts +3 -0
  344. package/dist/types/transport/noise/WaNoiseSession.d.ts +1 -0
  345. package/dist/types/transport/proxy.d.ts +6 -0
  346. package/dist/types/transport/stream/parse.d.ts +0 -1
  347. package/dist/types/transport/types.d.ts +18 -1
  348. package/dist/types/util/bytes.d.ts +5 -0
  349. package/dist/types/util/primitives.d.ts +3 -0
  350. package/dist/util/bytes.js +55 -33
  351. package/dist/util/coercion.js +6 -14
  352. package/dist/util/primitives.js +42 -14
  353. package/package.json +27 -9
  354. package/proto/index.d.ts +1090 -1048
  355. package/proto/index.js +1 -1
  356. package/scripts/check-node-version.cjs +0 -1
  357. package/dist/crypto/core/encoding.js +0 -29
  358. package/dist/esm/crypto/core/encoding.js +0 -25
  359. package/dist/esm/util/base64.js +0 -18
  360. package/dist/esm/util/signal-address.js +0 -5
  361. package/dist/types/crypto/core/encoding.d.ts +0 -11
  362. package/dist/types/util/base64.d.ts +0 -4
  363. package/dist/types/util/signal-address.d.ts +0 -2
  364. package/dist/util/base64.js +0 -24
  365. package/dist/util/signal-address.js +0 -8
  366. /package/dist/types/transport/node/builders/{accountSync.d.ts → account-sync.d.ts} +0 -0
@@ -2,13 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WaAppStateSyncClient = exports.WaAppStateMissingKeyError = void 0;
4
4
  const constants_1 = require("./constants");
5
- const utils_1 = require("./utils");
6
5
  const WaAppStateCrypto_1 = require("./WaAppStateCrypto");
7
6
  const WaAppStateSyncResponseParser_1 = require("./WaAppStateSyncResponseParser");
8
7
  const _proto_1 = require("../proto.js");
9
8
  const constants_2 = require("../protocol/constants");
10
- const base64_1 = require("../util/base64");
9
+ const jid_1 = require("../protocol/jid");
10
+ const query_1 = require("../transport/node/query");
11
11
  const bytes_1 = require("../util/bytes");
12
+ const bytes_2 = require("../util/bytes");
12
13
  const primitives_1 = require("../util/primitives");
13
14
  class WaAppStateMissingKeyError extends Error {
14
15
  constructor(message, keyId, collection) {
@@ -24,6 +25,7 @@ class WaAppStateSyncClient {
24
25
  this.logger = options.logger;
25
26
  this.query = options.query;
26
27
  this.store = options.store;
28
+ this.getCurrentMeJid = options.getCurrentMeJid;
27
29
  this.hostDomain = options.hostDomain ?? constants_2.WA_DEFAULTS.HOST_DOMAIN;
28
30
  this.defaultTimeoutMs = options.defaultTimeoutMs ?? constants_2.WA_DEFAULTS.APP_STATE_SYNC_TIMEOUT_MS;
29
31
  this.onMissingKeys = options.onMissingKeys;
@@ -47,14 +49,14 @@ class WaAppStateSyncClient {
47
49
  async importSyncKeyShare(share) {
48
50
  const keys = [];
49
51
  for (const item of share.keys ?? []) {
50
- const keyId = (0, base64_1.decodeProtoBytes)(item.keyId?.keyId, 'appStateSyncKeyShare.keys[].keyId.keyId');
52
+ const keyId = (0, bytes_1.decodeProtoBytes)(item.keyId?.keyId, 'appStateSyncKeyShare.keys[].keyId.keyId');
51
53
  if (!item.keyData?.keyData) {
52
54
  this.logger.debug('app-state sync key share entry missing key data', {
53
- keyId: (0, utils_1.keyIdToHex)(keyId)
55
+ keyId: (0, bytes_2.bytesToHex)(keyId)
54
56
  });
55
57
  continue;
56
58
  }
57
- const keyData = (0, base64_1.decodeProtoBytes)(item.keyData?.keyData, 'appStateSyncKeyShare.keys[].keyData.keyData');
59
+ const keyData = (0, bytes_1.decodeProtoBytes)(item.keyData?.keyData, 'appStateSyncKeyShare.keys[].keyData.keyData');
58
60
  keys.push({
59
61
  keyId,
60
62
  keyData,
@@ -93,6 +95,10 @@ class WaAppStateSyncClient {
93
95
  ...new Set(options.collections ?? constants_1.APP_STATE_DEFAULT_COLLECTIONS)
94
96
  ];
95
97
  try {
98
+ const initialCollectionStates = await this.store.getCollectionStates(collections);
99
+ for (let index = 0; index < collections.length; index += 1) {
100
+ context.collections.set(collections[index], initialCollectionStates[index]);
101
+ }
96
102
  this.logger.info('app-state sync start', {
97
103
  collections: collections.length,
98
104
  pendingMutations: options.pendingMutations?.length ?? 0
@@ -162,36 +168,13 @@ class WaAppStateSyncClient {
162
168
  }
163
169
  }
164
170
  async syncCollectionsRound(collections, pendingByCollection, options) {
165
- const prepared = await this.prepareSyncRoundRequest(collections, pendingByCollection);
166
- const iqNode = this.buildSyncIqNode(prepared.collectionNodes);
167
- const payloadByCollection = await this.fetchSyncPayloadByCollection(iqNode, options.timeoutMs ?? this.defaultTimeoutMs);
168
- const collectionOutcomes = await Promise.all(collections.map((collection) => this.processCollectionRound({
169
- collection,
170
- payloadByCollection,
171
- pendingByCollection,
172
- options,
173
- outgoingContexts: prepared.outgoingContexts,
174
- skippedUploadCollections: prepared.skippedUploadCollections
175
- })));
176
- return {
177
- results: collectionOutcomes.map((entry) => entry.result),
178
- collectionsToRefetch: collectionOutcomes
179
- .filter((entry) => entry.shouldRefetch)
180
- .map((entry) => entry.collection),
181
- stateChanged: collectionOutcomes.some((entry) => entry.stateChanged),
182
- missingKeyIds: this.collectDistinctMissingKeyIds(collectionOutcomes
183
- .map((entry) => entry.missingKeyId)
184
- .filter((value) => value !== null)),
185
- blockedCollections: collectionOutcomes
186
- .filter((entry) => entry.result.state === constants_2.WA_APP_STATE_COLLECTION_STATES.BLOCKED)
187
- .map((entry) => entry.collection)
188
- };
189
- }
190
- async prepareSyncRoundRequest(collections, pendingByCollection) {
191
171
  const requests = await Promise.all(collections.map((collection) => this.buildCollectionSyncRequest(collection, pendingByCollection)));
172
+ const collectionNodes = new Array(requests.length);
192
173
  const outgoingContexts = new Map();
193
174
  const skippedUploadCollections = new Set();
194
- for (const request of requests) {
175
+ for (let index = 0; index < requests.length; index += 1) {
176
+ const request = requests[index];
177
+ collectionNodes[index] = request.node;
195
178
  if (request.outgoingContext) {
196
179
  outgoingContexts.set(request.collection, request.outgoingContext);
197
180
  }
@@ -199,26 +182,57 @@ class WaAppStateSyncClient {
199
182
  skippedUploadCollections.add(request.collection);
200
183
  }
201
184
  }
202
- return {
203
- collectionNodes: requests.map((request) => request.node),
185
+ const iqNode = this.buildSyncIqNode(collectionNodes);
186
+ const payloadByCollection = await this.fetchSyncPayloadByCollection(iqNode, options.timeoutMs ?? this.defaultTimeoutMs);
187
+ const collectionOutcomes = await Promise.all(collections.map((collection) => this.processCollectionRound({
188
+ collection,
189
+ payloadByCollection,
190
+ pendingByCollection,
191
+ options,
204
192
  outgoingContexts,
205
193
  skippedUploadCollections
194
+ })));
195
+ const results = [];
196
+ const collectionsToRefetch = [];
197
+ const blockedCollections = [];
198
+ const missingKeyIds = [];
199
+ const missingKeyIdHexes = new Set();
200
+ let stateChanged = false;
201
+ for (const entry of collectionOutcomes) {
202
+ results.push(entry.result);
203
+ if (entry.shouldRefetch) {
204
+ collectionsToRefetch.push(entry.collection);
205
+ }
206
+ if (entry.stateChanged) {
207
+ stateChanged = true;
208
+ }
209
+ if (entry.result.state === constants_2.WA_APP_STATE_COLLECTION_STATES.BLOCKED) {
210
+ blockedCollections.push(entry.collection);
211
+ }
212
+ if (entry.missingKeyId) {
213
+ const keyHex = (0, bytes_2.bytesToHex)(entry.missingKeyId);
214
+ if (!missingKeyIdHexes.has(keyHex)) {
215
+ missingKeyIdHexes.add(keyHex);
216
+ missingKeyIds.push(entry.missingKeyId);
217
+ }
218
+ }
219
+ }
220
+ return {
221
+ results,
222
+ collectionsToRefetch,
223
+ stateChanged,
224
+ missingKeyIds,
225
+ blockedCollections
206
226
  };
207
227
  }
208
228
  async buildCollectionSyncRequest(collection, pendingByCollection) {
209
229
  const collectionState = await this.getCollectionState(collection);
210
- const hasPersistedState = collectionState.version > 0 ||
211
- collectionState.indexValueMap.size > 0 ||
212
- !(0, bytes_1.uint8Equal)(collectionState.hash, constants_1.APP_STATE_EMPTY_LT_HASH);
230
+ const hasPersistedState = collectionState.initialized;
213
231
  const attrs = {
214
- name: collection
232
+ name: collection,
233
+ version: String(hasPersistedState ? collectionState.version : constants_1.APP_STATE_DEFAULT_COLLECTION_VERSION),
234
+ return_snapshot: hasPersistedState ? 'false' : 'true'
215
235
  };
216
- if (hasPersistedState) {
217
- attrs.version = String(collectionState.version);
218
- }
219
- else {
220
- attrs.return_snapshot = 'true';
221
- }
222
236
  const children = [];
223
237
  const pendingMutations = pendingByCollection.get(collection) ?? [];
224
238
  let outgoingContext;
@@ -275,6 +289,7 @@ class WaAppStateSyncClient {
275
289
  tag: responseNode.tag,
276
290
  type: responseNode.attrs.type
277
291
  });
292
+ (0, query_1.assertIqResult)(responseNode, 'app-state sync');
278
293
  const payloads = (0, WaAppStateSyncResponseParser_1.parseSyncResponse)(responseNode);
279
294
  this.logger.debug('app-state sync payloads parsed', { count: payloads.length });
280
295
  const payloadByCollection = new Map();
@@ -296,20 +311,16 @@ class WaAppStateSyncClient {
296
311
  return this.createCollectionOutcome(collection, payload.state, payload.version);
297
312
  }
298
313
  const pendingMutationsCount = pendingByCollection.get(collection)?.length ?? 0;
299
- if (payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE) {
300
- shouldRefetch = true;
301
- }
302
- else if (payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT &&
303
- pendingMutationsCount > 0) {
304
- shouldRefetch = true;
305
- }
306
- if (payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT) {
307
- return this.createCollectionOutcome(collection, pendingMutationsCount > 0
308
- ? constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT
309
- : constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS, payload.version, shouldRefetch);
310
- }
311
- if (payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE) {
312
- return this.createCollectionOutcome(collection, payload.state, payload.version, shouldRefetch);
314
+ if (payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT ||
315
+ payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE) {
316
+ shouldRefetch =
317
+ payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE ||
318
+ pendingMutationsCount > 0;
319
+ return this.createCollectionOutcome(collection, payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT
320
+ ? pendingMutationsCount > 0
321
+ ? constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT
322
+ : constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS
323
+ : payload.state, payload.version, shouldRefetch);
313
324
  }
314
325
  try {
315
326
  let appliedMutations = [];
@@ -341,13 +352,17 @@ class WaAppStateSyncClient {
341
352
  collectionStateChanged = true;
342
353
  }
343
354
  }
344
- if (payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS_HAS_MORE) {
345
- shouldRefetch = true;
346
- }
347
- if (payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS &&
348
- skippedUploadCollections.has(collection)) {
349
- shouldRefetch = true;
355
+ const currentCollectionState = await this.getCollectionState(collection);
356
+ if (!currentCollectionState.initialized &&
357
+ payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS) {
358
+ this.setCollectionState(collection, payload.version ?? currentCollectionState.version, currentCollectionState.hash, currentCollectionState.indexValueMap);
359
+ collectionStateChanged = true;
350
360
  }
361
+ shouldRefetch =
362
+ shouldRefetch ||
363
+ payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS_HAS_MORE ||
364
+ (payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS &&
365
+ skippedUploadCollections.has(collection));
351
366
  this.logger.debug('app-state collection processed', {
352
367
  collection: payload.collection,
353
368
  state: payload.state,
@@ -386,24 +401,13 @@ class WaAppStateSyncClient {
386
401
  }
387
402
  };
388
403
  }
389
- collectDistinctMissingKeyIds(keyIds) {
390
- const byHex = new Map();
391
- for (const keyId of keyIds) {
392
- const keyHex = (0, utils_1.keyIdToHex)(keyId);
393
- if (byHex.has(keyHex)) {
394
- continue;
395
- }
396
- byHex.set(keyHex, keyId);
397
- }
398
- return [...byHex.values()];
399
- }
400
404
  async notifyMissingKeys(input) {
401
- const keyIds = this.collectDistinctMissingKeyIds(input.keyIds);
402
- const collections = [...new Set(input.collections)];
405
+ const keyIds = input.keyIds;
406
+ const collections = input.collections;
403
407
  if (keyIds.length === 0 || collections.length === 0) {
404
408
  return;
405
409
  }
406
- const keyIdsHex = keyIds.map((keyId) => (0, utils_1.keyIdToHex)(keyId));
410
+ const keyIdsHex = keyIds.map((keyId) => (0, bytes_2.bytesToHex)(keyId));
407
411
  this.logger.info('app-state requesting missing sync keys', {
408
412
  keys: keyIdsHex.length,
409
413
  keyIds: keyIdsHex.join(','),
@@ -493,16 +497,16 @@ class WaAppStateSyncClient {
493
497
  }
494
498
  async applySnapshot(collection, snapshot) {
495
499
  const version = this.normalizeProtoLong(snapshot.version?.version, `snapshot.version.version (${collection})`);
496
- const keyId = (0, base64_1.decodeProtoBytes)(snapshot.keyId?.id, `snapshot.keyId.id (${collection})`);
500
+ const keyId = (0, bytes_1.decodeProtoBytes)(snapshot.keyId?.id, `snapshot.keyId.id (${collection})`);
497
501
  const keyData = await this.getKeyData(keyId);
498
502
  if (!keyData) {
499
- throw new WaAppStateMissingKeyError(`missing snapshot key ${(0, utils_1.keyIdToHex)(keyId)} for ${collection}`, keyId, collection);
503
+ throw new WaAppStateMissingKeyError(`missing snapshot key ${(0, bytes_2.bytesToHex)(keyId)} for ${collection}`, keyId, collection);
500
504
  }
501
505
  const indexValueMap = new Map();
502
506
  const mutations = [];
503
507
  const decryptedRecords = await this.decryptSnapshotRecords(collection, snapshot);
504
508
  for (const { decrypted, recordKeyId } of decryptedRecords) {
505
- const indexMacHex = (0, utils_1.keyIdToHex)(decrypted.indexMac);
509
+ const indexMacHex = (0, bytes_2.bytesToHex)(decrypted.indexMac);
506
510
  indexValueMap.set(indexMacHex, decrypted.valueMac);
507
511
  mutations.push({
508
512
  collection,
@@ -519,7 +523,7 @@ class WaAppStateSyncClient {
519
523
  }
520
524
  const ltHash = await this.crypto.ltHashAdd(constants_1.APP_STATE_EMPTY_LT_HASH, Array.from(indexValueMap.values()));
521
525
  const expectedSnapshotMac = await this.crypto.generateSnapshotMac(keyData, ltHash, version, collection);
522
- if (!(0, bytes_1.uint8Equal)(expectedSnapshotMac, snapshot.mac)) {
526
+ if (!(0, bytes_2.uint8Equal)(expectedSnapshotMac, snapshot.mac)) {
523
527
  throw new Error(`snapshot MAC mismatch for ${collection}`);
524
528
  }
525
529
  this.setCollectionState(collection, version, ltHash, indexValueMap);
@@ -531,32 +535,39 @@ class WaAppStateSyncClient {
531
535
  if (current.version !== patchVersion - 1) {
532
536
  throw new Error(`patch version mismatch for ${collection}: local=${current.version}, incoming=${patchVersion}`);
533
537
  }
534
- const patchKeyId = (0, base64_1.decodeProtoBytes)(patch.keyId?.id, `patch.keyId.id (${collection})`);
538
+ const patchKeyId = (0, bytes_1.decodeProtoBytes)(patch.keyId?.id, `patch.keyId.id (${collection})`);
535
539
  const patchKeyData = await this.getKeyData(patchKeyId);
536
540
  if (!patchKeyData) {
537
- throw new WaAppStateMissingKeyError(`missing patch key ${(0, utils_1.keyIdToHex)(patchKeyId)} for ${collection}`, patchKeyId, collection);
541
+ throw new WaAppStateMissingKeyError(`missing patch key ${(0, bytes_2.bytesToHex)(patchKeyId)} for ${collection}`, patchKeyId, collection);
538
542
  }
539
543
  const decryptedMutations = await this.decryptPatchMutations(collection, patch);
540
- const nextState = await this.computeNextCollectionState(current.hash, current.indexValueMap, decryptedMutations.map((mutation) => ({
541
- operation: mutation.operationCode,
542
- indexMac: mutation.indexMac,
543
- valueMac: mutation.valueMac
544
- })), collection);
545
- await this.assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextState.hash, decryptedMutations);
544
+ const macMutations = new Array(decryptedMutations.length);
545
+ const valueMacs = new Array(decryptedMutations.length);
546
+ for (let index = 0; index < decryptedMutations.length; index += 1) {
547
+ const mutation = decryptedMutations[index];
548
+ valueMacs[index] = mutation.valueMac;
549
+ macMutations[index] = {
550
+ operation: mutation.operationCode,
551
+ indexMac: mutation.indexMac,
552
+ valueMac: mutation.valueMac
553
+ };
554
+ }
555
+ const nextState = await this.computeNextCollectionState(current.hash, current.indexValueMap, macMutations, collection);
556
+ await this.assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextState.hash, valueMacs);
546
557
  this.setCollectionState(collection, patchVersion, nextState.hash, nextState.indexValueMap);
547
- return decryptedMutations.map(({ operationCode, ...mutation }) => {
548
- void operationCode;
549
- return mutation;
550
- });
558
+ return decryptedMutations.slice();
551
559
  }
552
560
  async decryptSnapshotRecords(collection, snapshot) {
553
- return Promise.all((snapshot.records ?? []).map(async (record) => {
554
- const indexMac = (0, base64_1.decodeProtoBytes)(record.index?.blob, `snapshot.record.index.blob (${collection})`);
555
- const valueBlob = (0, base64_1.decodeProtoBytes)(record.value?.blob, `snapshot.record.value.blob (${collection})`);
556
- const recordKeyId = (0, base64_1.decodeProtoBytes)(record.keyId?.id, `snapshot.record.keyId.id (${collection})`);
561
+ const records = (snapshot.records ?? []).map((record) => ({
562
+ indexMac: (0, bytes_1.decodeProtoBytes)(record.index?.blob, `snapshot.record.index.blob (${collection})`),
563
+ valueBlob: (0, bytes_1.decodeProtoBytes)(record.value?.blob, `snapshot.record.value.blob (${collection})`),
564
+ recordKeyId: (0, bytes_1.decodeProtoBytes)(record.keyId?.id, `snapshot.record.keyId.id (${collection})`)
565
+ }));
566
+ await this.preloadKeyData(records.map((record) => record.recordKeyId));
567
+ return Promise.all(records.map(async ({ indexMac, valueBlob, recordKeyId }) => {
557
568
  const recordKeyData = await this.getKeyData(recordKeyId);
558
569
  if (!recordKeyData) {
559
- throw new WaAppStateMissingKeyError(`missing snapshot mutation key ${(0, utils_1.keyIdToHex)(recordKeyId)} for ${collection}`, recordKeyId, collection);
570
+ throw new WaAppStateMissingKeyError(`missing snapshot mutation key ${(0, bytes_2.bytesToHex)(recordKeyId)} for ${collection}`, recordKeyId, collection);
560
571
  }
561
572
  const decrypted = await this.crypto.decryptMutation({
562
573
  operation: _proto_1.proto.SyncdMutation.SyncdOperation.SET,
@@ -572,7 +583,7 @@ class WaAppStateSyncClient {
572
583
  }));
573
584
  }
574
585
  async decryptPatchMutations(collection, patch) {
575
- return Promise.all((patch.mutations ?? []).map(async (mutation) => {
586
+ const parsedMutations = (patch.mutations ?? []).map((mutation) => {
576
587
  const operationCode = mutation.operation;
577
588
  if (operationCode === null || operationCode === undefined) {
578
589
  throw new Error(`patch mutation is missing operation (${collection})`);
@@ -581,12 +592,18 @@ class WaAppStateSyncClient {
581
592
  if (!record) {
582
593
  throw new Error(`patch mutation is missing record (${collection})`);
583
594
  }
584
- const indexMac = (0, base64_1.decodeProtoBytes)(record.index?.blob, `patch.record.index.blob (${collection})`);
585
- const valueBlob = (0, base64_1.decodeProtoBytes)(record.value?.blob, `patch.record.value.blob (${collection})`);
586
- const recordKeyId = (0, base64_1.decodeProtoBytes)(record.keyId?.id, `patch.record.keyId.id (${collection})`);
595
+ return {
596
+ operationCode,
597
+ indexMac: (0, bytes_1.decodeProtoBytes)(record.index?.blob, `patch.record.index.blob (${collection})`),
598
+ valueBlob: (0, bytes_1.decodeProtoBytes)(record.value?.blob, `patch.record.value.blob (${collection})`),
599
+ recordKeyId: (0, bytes_1.decodeProtoBytes)(record.keyId?.id, `patch.record.keyId.id (${collection})`)
600
+ };
601
+ });
602
+ await this.preloadKeyData(parsedMutations.map((mutation) => mutation.recordKeyId));
603
+ return Promise.all(parsedMutations.map(async ({ operationCode, indexMac, valueBlob, recordKeyId }) => {
587
604
  const recordKeyData = await this.getKeyData(recordKeyId);
588
605
  if (!recordKeyData) {
589
- throw new WaAppStateMissingKeyError(`missing mutation key ${(0, utils_1.keyIdToHex)(recordKeyId)} for ${collection}`, recordKeyId, collection);
606
+ throw new WaAppStateMissingKeyError(`missing mutation key ${(0, bytes_2.bytesToHex)(recordKeyId)} for ${collection}`, recordKeyId, collection);
590
607
  }
591
608
  const decrypted = await this.crypto.decryptMutation({
592
609
  operation: operationCode,
@@ -612,15 +629,15 @@ class WaAppStateSyncClient {
612
629
  };
613
630
  }));
614
631
  }
615
- async assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextHash, decryptedMutations) {
616
- const snapshotMac = (0, base64_1.decodeProtoBytes)(patch.snapshotMac, `patch.snapshotMac (${collection})`);
632
+ async assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextHash, valueMacs) {
633
+ const snapshotMac = (0, bytes_1.decodeProtoBytes)(patch.snapshotMac, `patch.snapshotMac (${collection})`);
617
634
  const expectedSnapshotMac = await this.crypto.generateSnapshotMac(patchKeyData, nextHash, patchVersion, collection);
618
- if (!(0, bytes_1.uint8Equal)(expectedSnapshotMac, snapshotMac)) {
635
+ if (!(0, bytes_2.uint8Equal)(expectedSnapshotMac, snapshotMac)) {
619
636
  throw new Error(`patch snapshot MAC mismatch for ${collection}`);
620
637
  }
621
- const patchMac = (0, base64_1.decodeProtoBytes)(patch.patchMac, `patch.patchMac (${collection})`);
622
- const expectedPatchMac = await this.crypto.generatePatchMac(patchKeyData, snapshotMac, decryptedMutations.map((mutation) => mutation.valueMac), patchVersion, collection);
623
- if (!(0, bytes_1.uint8Equal)(expectedPatchMac, patchMac)) {
638
+ const patchMac = (0, bytes_1.decodeProtoBytes)(patch.patchMac, `patch.patchMac (${collection})`);
639
+ const expectedPatchMac = await this.crypto.generatePatchMac(patchKeyData, snapshotMac, valueMacs, patchVersion, collection);
640
+ if (!(0, bytes_2.uint8Equal)(expectedPatchMac, patchMac)) {
624
641
  throw new Error(`patch MAC mismatch for ${collection}`);
625
642
  }
626
643
  }
@@ -661,12 +678,15 @@ class WaAppStateSyncClient {
661
678
  const patchVersion = snapshot.version + 1;
662
679
  const snapshotMac = await this.crypto.generateSnapshotMac(activeKey.keyData, nextState.hash, patchVersion, collection);
663
680
  const patchMac = await this.crypto.generatePatchMac(activeKey.keyData, snapshotMac, macMutations.map((item) => item.valueMac), patchVersion, collection);
681
+ const deviceIndex = this.resolveDeviceIndex();
682
+ const clientDebugData = this.buildPatchClientDebugData();
664
683
  const encodedPatch = _proto_1.proto.SyncdPatch.encode({
665
- version: { version: patchVersion },
666
684
  mutations: encryptedMutations,
667
685
  snapshotMac,
668
686
  patchMac,
669
- keyId: { id: activeKey.keyId }
687
+ keyId: { id: activeKey.keyId },
688
+ ...(deviceIndex === undefined ? {} : { deviceIndex }),
689
+ clientDebugData
670
690
  }).finish();
671
691
  return {
672
692
  encodedPatch,
@@ -678,13 +698,35 @@ class WaAppStateSyncClient {
678
698
  }
679
699
  };
680
700
  }
701
+ resolveDeviceIndex() {
702
+ const meJid = this.getCurrentMeJid?.();
703
+ if (!meJid) {
704
+ return undefined;
705
+ }
706
+ try {
707
+ return (0, jid_1.parseSignalAddressFromJid)(meJid).device;
708
+ }
709
+ catch (error) {
710
+ this.logger.debug('app-state could not parse device index from me jid', {
711
+ meJid
712
+ });
713
+ void error;
714
+ return undefined;
715
+ }
716
+ }
717
+ buildPatchClientDebugData() {
718
+ return _proto_1.proto.PatchDebugData.encode({
719
+ isSenderPrimary: false,
720
+ senderPlatform: _proto_1.proto.PatchDebugData.Platform.WEB
721
+ }).finish();
722
+ }
681
723
  async computeNextCollectionState(baseHash, baseMap, mutations, collection) {
682
724
  const indexValueMap = new Map(baseMap);
683
725
  const addValues = [];
684
726
  const removeValues = [];
685
727
  let missingRemoveCount = 0;
686
728
  for (const mutation of mutations) {
687
- const indexMacHex = (0, utils_1.keyIdToHex)(mutation.indexMac);
729
+ const indexMacHex = (0, bytes_2.bytesToHex)(mutation.indexMac);
688
730
  const existing = indexValueMap.get(indexMacHex);
689
731
  if (mutation.operation === _proto_1.proto.SyncdMutation.SyncdOperation.REMOVE) {
690
732
  if (!existing) {
@@ -749,9 +791,33 @@ class WaAppStateSyncClient {
749
791
  }
750
792
  return compacted;
751
793
  }
794
+ async preloadKeyData(keyIds) {
795
+ if (keyIds.length === 0) {
796
+ return;
797
+ }
798
+ const context = this.requireSyncContext();
799
+ const missingKeyIds = [];
800
+ const missingKeyHexes = new Set();
801
+ for (let index = 0; index < keyIds.length; index += 1) {
802
+ const keyId = keyIds[index];
803
+ const keyHex = (0, bytes_2.bytesToHex)(keyId);
804
+ if (context.keys.has(keyHex) || missingKeyHexes.has(keyHex)) {
805
+ continue;
806
+ }
807
+ missingKeyHexes.add(keyHex);
808
+ missingKeyIds.push(keyId);
809
+ }
810
+ if (missingKeyIds.length === 0) {
811
+ return;
812
+ }
813
+ const loadedKeyData = await this.store.getSyncKeyDataBatch(missingKeyIds);
814
+ for (let index = 0; index < missingKeyIds.length; index += 1) {
815
+ context.keys.set((0, bytes_2.bytesToHex)(missingKeyIds[index]), loadedKeyData[index] ?? null);
816
+ }
817
+ }
752
818
  async getKeyData(keyId) {
753
819
  const context = this.requireSyncContext();
754
- const keyHex = (0, utils_1.keyIdToHex)(keyId);
820
+ const keyHex = (0, bytes_2.bytesToHex)(keyId);
755
821
  if (context.keys.has(keyHex)) {
756
822
  return context.keys.get(keyHex) ?? null;
757
823
  }
@@ -772,6 +838,7 @@ class WaAppStateSyncClient {
772
838
  setCollectionState(collection, version, hash, indexValueMap) {
773
839
  const context = this.requireSyncContext();
774
840
  context.collections.set(collection, {
841
+ initialized: true,
775
842
  version,
776
843
  hash,
777
844
  indexValueMap
@@ -12,6 +12,12 @@ function parseSyncResponse(iqNode) {
12
12
  }
13
13
  const syncNode = (0, helpers_1.findNodeChild)(iqNode, constants_1.WA_NODE_TAGS.SYNC);
14
14
  if (!syncNode) {
15
+ if (iqNode.attrs.type === constants_1.WA_IQ_TYPES.ERROR) {
16
+ const errorNode = (0, helpers_1.findNodeChild)(iqNode, constants_1.WA_NODE_TAGS.ERROR);
17
+ const code = errorNode?.attrs.code ?? 'unknown';
18
+ const text = errorNode?.attrs.text ?? 'unknown';
19
+ throw new Error(`sync iq failed (${code}: ${text})`);
20
+ }
15
21
  throw new Error('sync response is missing <sync> node');
16
22
  }
17
23
  const payloads = [];
@@ -30,11 +36,16 @@ function parseSyncResponse(iqNode) {
30
36
  }
31
37
  version = parsedVersion;
32
38
  }
33
- const patchesNode = (0, helpers_1.findNodeChild)(collectionNode, constants_1.WA_NODE_TAGS.PATCHES);
34
- const patches = patchesNode
35
- ? (0, helpers_1.getNodeChildrenByTag)(patchesNode, constants_1.WA_NODE_TAGS.PATCH).map((node) => _proto_1.proto.SyncdPatch.decode((0, helpers_1.decodeNodeContentBase64OrBytes)(node.content, 'collection.patches.patch')))
36
- : [];
37
- const snapshotNode = (0, helpers_1.findNodeChild)(collectionNode, constants_1.WA_NODE_TAGS.SNAPSHOT);
39
+ const [patchesNode, snapshotNode] = (0, helpers_1.findNodeChildrenByTags)(collectionNode, [
40
+ constants_1.WA_NODE_TAGS.PATCHES,
41
+ constants_1.WA_NODE_TAGS.SNAPSHOT
42
+ ]);
43
+ const patches = [];
44
+ if (patchesNode) {
45
+ for (const patchNode of (0, helpers_1.getNodeChildrenByTag)(patchesNode, constants_1.WA_NODE_TAGS.PATCH)) {
46
+ patches.push(_proto_1.proto.SyncdPatch.decode((0, helpers_1.decodeNodeContentBase64OrBytes)(patchNode.content, 'collection.patches.patch')));
47
+ }
48
+ }
38
49
  const snapshotReference = snapshotNode
39
50
  ? _proto_1.proto.ExternalBlobReference.decode((0, helpers_1.decodeNodeContentBase64OrBytes)(snapshotNode.content, 'collection.snapshot'))
40
51
  : undefined;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.APP_STATE_DEFAULT_COLLECTIONS = exports.APP_STATE_EMPTY_LT_HASH = exports.APP_STATE_POINT_SIZE = exports.APP_STATE_LT_HASH_SIZE = exports.APP_STATE_IV_LENGTH = exports.APP_STATE_MAC_OCTET_LENGTH = exports.APP_STATE_VALUE_MAC_LENGTH = exports.APP_STATE_DERIVED_PATCH_MAC_KEY_END = exports.APP_STATE_DERIVED_SNAPSHOT_MAC_KEY_END = exports.APP_STATE_DERIVED_VALUE_MAC_KEY_END = exports.APP_STATE_DERIVED_VALUE_ENCRYPTION_KEY_END = exports.APP_STATE_DERIVED_INDEX_KEY_END = exports.APP_STATE_DERIVED_KEY_LENGTH = void 0;
3
+ exports.APP_STATE_DEFAULT_COLLECTIONS = exports.APP_STATE_DEFAULT_COLLECTION_VERSION = exports.APP_STATE_EMPTY_LT_HASH = exports.APP_STATE_POINT_SIZE = exports.APP_STATE_LT_HASH_SIZE = exports.APP_STATE_IV_LENGTH = exports.APP_STATE_MAC_OCTET_LENGTH = exports.APP_STATE_VALUE_MAC_LENGTH = exports.APP_STATE_DERIVED_PATCH_MAC_KEY_END = exports.APP_STATE_DERIVED_SNAPSHOT_MAC_KEY_END = exports.APP_STATE_DERIVED_VALUE_MAC_KEY_END = exports.APP_STATE_DERIVED_VALUE_ENCRYPTION_KEY_END = exports.APP_STATE_DERIVED_INDEX_KEY_END = exports.APP_STATE_DERIVED_KEY_LENGTH = void 0;
4
4
  const constants_1 = require("../protocol/constants");
5
5
  exports.APP_STATE_DERIVED_KEY_LENGTH = 160;
6
6
  exports.APP_STATE_DERIVED_INDEX_KEY_END = 32;
@@ -14,10 +14,11 @@ exports.APP_STATE_IV_LENGTH = 16;
14
14
  exports.APP_STATE_LT_HASH_SIZE = 128;
15
15
  exports.APP_STATE_POINT_SIZE = 2;
16
16
  exports.APP_STATE_EMPTY_LT_HASH = new Uint8Array(exports.APP_STATE_LT_HASH_SIZE);
17
- exports.APP_STATE_DEFAULT_COLLECTIONS = [
17
+ exports.APP_STATE_DEFAULT_COLLECTION_VERSION = 0;
18
+ exports.APP_STATE_DEFAULT_COLLECTIONS = Object.freeze([
18
19
  constants_1.WA_APP_STATE_COLLECTIONS.CRITICAL_UNBLOCK_LOW,
19
20
  constants_1.WA_APP_STATE_COLLECTIONS.CRITICAL_BLOCK,
20
21
  constants_1.WA_APP_STATE_COLLECTIONS.REGULAR_LOW,
21
22
  constants_1.WA_APP_STATE_COLLECTIONS.REGULAR,
22
23
  constants_1.WA_APP_STATE_COLLECTIONS.REGULAR_HIGH
23
- ];
24
+ ]);
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.keyIdToHex = keyIdToHex;
4
3
  exports.parseCollectionName = parseCollectionName;
5
4
  exports.keyDeviceId = keyDeviceId;
6
5
  exports.keyEpoch = keyEpoch;
@@ -8,33 +7,18 @@ exports.pickActiveSyncKey = pickActiveSyncKey;
8
7
  exports.toNetworkOrder64 = toNetworkOrder64;
9
8
  exports.downloadExternalBlobReference = downloadExternalBlobReference;
10
9
  const constants_1 = require("../protocol/constants");
11
- const base64_1 = require("../util/base64");
12
10
  const bytes_1 = require("../util/bytes");
13
- function keyIdToHex(keyId) {
14
- return (0, bytes_1.bytesToHex)(keyId);
15
- }
11
+ const APP_STATE_COLLECTION_NAMES = new Set(Object.values(constants_1.WA_APP_STATE_COLLECTIONS));
16
12
  function parseCollectionName(value) {
17
- if (!value) {
18
- return null;
19
- }
20
- for (const collection of Object.values(constants_1.WA_APP_STATE_COLLECTIONS)) {
21
- if (collection === value) {
22
- return collection;
23
- }
24
- }
25
- return null;
13
+ return value && APP_STATE_COLLECTION_NAMES.has(value) ? value : null;
26
14
  }
27
15
  function keyDeviceId(keyId) {
28
- if (keyId.byteLength < 6) {
29
- return null;
30
- }
31
- return (keyId[0] << 8) | keyId[1];
16
+ return keyId.byteLength < 6 ? null : (keyId[0] << 8) | keyId[1];
32
17
  }
33
18
  function keyEpoch(keyId) {
34
- if (keyId.byteLength < 6) {
35
- return -1;
36
- }
37
- return new DataView(keyId.buffer, keyId.byteOffset, keyId.byteLength).getUint32(2, false);
19
+ return keyId.byteLength < 6
20
+ ? -1
21
+ : keyId[2] * 16777216 + keyId[3] * 65536 + keyId[4] * 256 + keyId[5];
38
22
  }
39
23
  function pickActiveSyncKey(keys) {
40
24
  let active = null;
@@ -61,19 +45,15 @@ function pickActiveSyncKey(keys) {
61
45
  return active;
62
46
  }
63
47
  function toNetworkOrder64(value) {
64
- const out = new Uint8Array(8);
65
- const view = new DataView(out.buffer);
66
- view.setUint32(0, Math.floor(value / 4294967296), false);
67
- view.setUint32(4, value >>> 0, false);
68
- return out;
48
+ return (0, bytes_1.intToBytes)(8, value);
69
49
  }
70
50
  async function downloadExternalBlobReference(mediaTransfer, reference) {
71
51
  if (!reference.directPath) {
72
52
  throw new Error('external blob reference is missing directPath');
73
53
  }
74
- const mediaKey = (0, base64_1.decodeProtoBytes)(reference.mediaKey, 'external blob mediaKey');
75
- const fileSha256 = (0, base64_1.decodeProtoBytes)(reference.fileSha256, 'external blob fileSha256');
76
- const fileEncSha256 = (0, base64_1.decodeProtoBytes)(reference.fileEncSha256, 'external blob fileEncSha256');
54
+ const mediaKey = (0, bytes_1.decodeProtoBytes)(reference.mediaKey, 'external blob mediaKey');
55
+ const fileSha256 = (0, bytes_1.decodeProtoBytes)(reference.fileSha256, 'external blob fileSha256');
56
+ const fileEncSha256 = (0, bytes_1.decodeProtoBytes)(reference.fileEncSha256, 'external blob fileEncSha256');
77
57
  return mediaTransfer.downloadAndDecrypt({
78
58
  directPath: reference.directPath,
79
59
  mediaType: constants_1.WA_APP_STATE_KEY_TYPES.MD_APP_STATE,