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
@@ -0,0 +1,186 @@
1
+ import { toSerializedPubKey } from '../../crypto/core/keys.js';
2
+ import { normalizeDeviceJid, parseSignalAddressFromJid } from '../../protocol/jid.js';
3
+ import { uint8Equal } from '../../util/bytes.js';
4
+ import { toError } from '../../util/primitives.js';
5
+ export function createSignalSessionResolver(options) {
6
+ const { signalProtocol, signalStore, signalIdentitySync, signalSessionSync, logger } = options;
7
+ const ensureSession = async (address, jid, expectedIdentity, reasonIdentity = false) => {
8
+ const expectedSerializedIdentity = expectedIdentity
9
+ ? toSerializedPubKey(expectedIdentity)
10
+ : null;
11
+ if (reasonIdentity) {
12
+ await signalIdentitySync.syncIdentityKeys([jid]);
13
+ }
14
+ if (await signalProtocol.hasSession(address)) {
15
+ if (expectedSerializedIdentity) {
16
+ const storedIdentity = await signalStore.getRemoteIdentity(address);
17
+ if (!storedIdentity || !uint8Equal(storedIdentity, expectedSerializedIdentity)) {
18
+ throw new Error('identity mismatch');
19
+ }
20
+ }
21
+ return;
22
+ }
23
+ logger.info('signal session missing, fetching remote key bundle', { jid });
24
+ const fetched = await signalSessionSync.fetchKeyBundle({
25
+ jid,
26
+ reasonIdentity
27
+ });
28
+ const remoteIdentity = toSerializedPubKey(fetched.bundle.identity);
29
+ if (reasonIdentity) {
30
+ const storedIdentity = await signalStore.getRemoteIdentity(address);
31
+ if (storedIdentity && !uint8Equal(remoteIdentity, storedIdentity)) {
32
+ throw new Error('identity mismatch');
33
+ }
34
+ }
35
+ if (expectedSerializedIdentity && !uint8Equal(remoteIdentity, expectedSerializedIdentity)) {
36
+ throw new Error('identity mismatch');
37
+ }
38
+ await signalProtocol.establishOutgoingSession(address, fetched.bundle);
39
+ logger.info('signal session synchronized', {
40
+ jid,
41
+ regId: fetched.bundle.regId,
42
+ hasOneTimeKey: fetched.bundle.oneTimeKey !== undefined
43
+ });
44
+ };
45
+ const ensureSessionsBatch = async (targetJids, expectedIdentityByJid) => {
46
+ const seenTargetJids = new Set();
47
+ const normalizedTargetJids = [];
48
+ const normalizedTargetAddresses = [];
49
+ for (let index = 0; index < targetJids.length; index += 1) {
50
+ const jid = normalizeDeviceJid(targetJids[index]);
51
+ if (seenTargetJids.has(jid)) {
52
+ continue;
53
+ }
54
+ seenTargetJids.add(jid);
55
+ normalizedTargetJids.push(jid);
56
+ normalizedTargetAddresses.push(parseSignalAddressFromJid(jid));
57
+ }
58
+ if (normalizedTargetJids.length === 0) {
59
+ return;
60
+ }
61
+ const normalizedExpectedIdentityByJid = expectedIdentityByJid && expectedIdentityByJid.size > 0
62
+ ? new Map()
63
+ : undefined;
64
+ if (normalizedExpectedIdentityByJid && expectedIdentityByJid) {
65
+ for (const [jid, identity] of expectedIdentityByJid.entries()) {
66
+ try {
67
+ normalizedExpectedIdentityByJid.set(normalizeDeviceJid(jid), identity);
68
+ }
69
+ catch (error) {
70
+ logger.trace('ignoring malformed expected identity jid during batch normalization', { jid, message: toError(error).message });
71
+ }
72
+ }
73
+ }
74
+ const hasSessions = await signalProtocol.hasSessions(normalizedTargetAddresses);
75
+ if (normalizedExpectedIdentityByJid) {
76
+ const identityAddresses = [];
77
+ const expectedSerializedIdentities = [];
78
+ for (let index = 0; index < normalizedTargetJids.length; index += 1) {
79
+ if (!hasSessions[index]) {
80
+ continue;
81
+ }
82
+ const expectedIdentity = normalizedExpectedIdentityByJid.get(normalizedTargetJids[index]);
83
+ if (!expectedIdentity) {
84
+ continue;
85
+ }
86
+ identityAddresses.push(normalizedTargetAddresses[index]);
87
+ expectedSerializedIdentities.push(toSerializedPubKey(expectedIdentity));
88
+ }
89
+ const storedIdentities = await signalStore.getRemoteIdentities(identityAddresses);
90
+ for (let index = 0; index < storedIdentities.length; index += 1) {
91
+ const storedIdentity = storedIdentities[index];
92
+ if (!storedIdentity ||
93
+ !uint8Equal(storedIdentity, expectedSerializedIdentities[index])) {
94
+ throw new Error('identity mismatch');
95
+ }
96
+ }
97
+ }
98
+ const missingIndices = [];
99
+ for (let index = 0; index < normalizedTargetJids.length; index += 1) {
100
+ if (!hasSessions[index]) {
101
+ missingIndices.push(index);
102
+ }
103
+ }
104
+ if (missingIndices.length === 0) {
105
+ return;
106
+ }
107
+ try {
108
+ const batchRequest = [];
109
+ for (let index = 0; index < missingIndices.length; index += 1) {
110
+ batchRequest.push({ jid: normalizedTargetJids[missingIndices[index]] });
111
+ }
112
+ const batchResults = await signalSessionSync.fetchKeyBundles(batchRequest);
113
+ const fallbackIndices = [];
114
+ const establishedIndices = [];
115
+ const establishPromises = [];
116
+ for (let index = 0; index < missingIndices.length; index += 1) {
117
+ const targetIndex = missingIndices[index];
118
+ const result = batchResults[index];
119
+ if (!result || !('bundle' in result)) {
120
+ fallbackIndices.push(targetIndex);
121
+ continue;
122
+ }
123
+ const targetJid = normalizedTargetJids[targetIndex];
124
+ const expectedIdentity = normalizedExpectedIdentityByJid?.get(targetJid);
125
+ const remoteIdentity = toSerializedPubKey(result.bundle.identity);
126
+ if (expectedIdentity &&
127
+ !uint8Equal(remoteIdentity, toSerializedPubKey(expectedIdentity))) {
128
+ throw new Error('identity mismatch');
129
+ }
130
+ establishedIndices.push(targetIndex);
131
+ establishPromises.push(signalProtocol
132
+ .establishOutgoingSession(normalizedTargetAddresses[targetIndex], result.bundle)
133
+ .then(() => {
134
+ logger.debug('signal session synchronized from batch key fetch', {
135
+ jid: targetJid,
136
+ regId: result.bundle.regId,
137
+ hasOneTimeKey: result.bundle.oneTimeKey !== undefined
138
+ });
139
+ }));
140
+ }
141
+ const establishmentResults = await Promise.allSettled(establishPromises);
142
+ for (let index = 0; index < establishmentResults.length; index += 1) {
143
+ const result = establishmentResults[index];
144
+ if (result.status === 'fulfilled') {
145
+ continue;
146
+ }
147
+ const error = toError(result.reason);
148
+ if (error.message === 'identity mismatch') {
149
+ throw error;
150
+ }
151
+ fallbackIndices.push(establishedIndices[index]);
152
+ }
153
+ if (fallbackIndices.length === 0) {
154
+ return;
155
+ }
156
+ logger.warn('signal batch key fetch returned partial errors, falling back to single requests', {
157
+ requested: missingIndices.length,
158
+ fallbackTargets: fallbackIndices.length
159
+ });
160
+ for (let index = 0; index < fallbackIndices.length; index += 1) {
161
+ const targetIndex = fallbackIndices[index];
162
+ const jid = normalizedTargetJids[targetIndex];
163
+ await ensureSession(normalizedTargetAddresses[targetIndex], jid, normalizedExpectedIdentityByJid?.get(jid));
164
+ }
165
+ }
166
+ catch (error) {
167
+ const normalized = toError(error);
168
+ if (normalized.message === 'identity mismatch') {
169
+ throw normalized;
170
+ }
171
+ logger.warn('signal batch key fetch failed, falling back to single requests', {
172
+ requested: missingIndices.length,
173
+ message: normalized.message
174
+ });
175
+ for (let index = 0; index < missingIndices.length; index += 1) {
176
+ const targetIndex = missingIndices[index];
177
+ const jid = normalizedTargetJids[targetIndex];
178
+ await ensureSession(normalizedTargetAddresses[targetIndex], jid, normalizedExpectedIdentityByJid?.get(jid));
179
+ }
180
+ }
181
+ };
182
+ return {
183
+ ensureSession,
184
+ ensureSessionsBatch
185
+ };
186
+ }
@@ -1,5 +1,6 @@
1
1
  import { proto } from '../../proto.js';
2
2
  import { WA_DEFAULTS } from '../../protocol/constants.js';
3
+ import { assertByteLength } from '../../util/bytes.js';
3
4
  import { asBytes, asNumber, asOptionalBytes, asOptionalNumber, asString, toBoolOrUndef } from '../../util/coercion.js';
4
5
  export function toSignalAddressParts(address) {
5
6
  return {
@@ -94,17 +95,11 @@ function encodeSignalRecvChain(chain) {
94
95
  }
95
96
  function decodeSignalMessageKey(messageKey, field) {
96
97
  const cipherKey = asBytes(messageKey.cipherKey, `${field}.cipherKey`);
97
- if (cipherKey.byteLength !== 32) {
98
- throw new Error(`invalid ${field}.cipherKey length ${cipherKey.byteLength}`);
99
- }
98
+ assertByteLength(cipherKey, 32, `invalid ${field}.cipherKey length ${cipherKey.byteLength}`);
100
99
  const macKey = asBytes(messageKey.macKey, `${field}.macKey`);
101
- if (macKey.byteLength !== 32) {
102
- throw new Error(`invalid ${field}.macKey length ${macKey.byteLength}`);
103
- }
100
+ assertByteLength(macKey, 32, `invalid ${field}.macKey length ${macKey.byteLength}`);
104
101
  const iv = asBytes(messageKey.iv, `${field}.iv`);
105
- if (iv.byteLength !== 16) {
106
- throw new Error(`invalid ${field}.iv length ${iv.byteLength}`);
107
- }
102
+ assertByteLength(iv, 16, `invalid ${field}.iv length ${iv.byteLength}`);
108
103
  return {
109
104
  index: asNumber(messageKey.index, `${field}.index`),
110
105
  cipherKey,
@@ -118,13 +113,9 @@ function decodeSignalRecvChain(chain, field) {
118
113
  throw new Error(`missing ${field}.chainKey`);
119
114
  }
120
115
  const ratchetPubKey = asBytes(chain.senderRatchetKey, `${field}.senderRatchetKey`);
121
- if (ratchetPubKey.byteLength !== 33) {
122
- throw new Error(`invalid ${field}.senderRatchetKey length ${ratchetPubKey.byteLength}`);
123
- }
116
+ assertByteLength(ratchetPubKey, 33, `invalid ${field}.senderRatchetKey length ${ratchetPubKey.byteLength}`);
124
117
  const chainKeyBytes = asBytes(chainKey.key, `${field}.chainKey.key`);
125
- if (chainKeyBytes.byteLength !== 32) {
126
- throw new Error(`invalid ${field}.chainKey.key length ${chainKeyBytes.byteLength}`);
127
- }
118
+ assertByteLength(chainKeyBytes, 32, `invalid ${field}.chainKey.key length ${chainKeyBytes.byteLength}`);
128
119
  return {
129
120
  ratchetPubKey,
130
121
  nextMsgIndex: asNumber(chainKey.index, `${field}.chainKey.index`),
@@ -141,17 +132,11 @@ function decodeSignalSendChain(chain, field) {
141
132
  if (!privateKey) {
142
133
  throw new Error(`missing ${field}.senderRatchetKeyPrivate`);
143
134
  }
144
- if (privateKey.byteLength !== 32) {
145
- throw new Error(`invalid ${field}.senderRatchetKeyPrivate length ${privateKey.byteLength}`);
146
- }
135
+ assertByteLength(privateKey, 32, `invalid ${field}.senderRatchetKeyPrivate length ${privateKey.byteLength}`);
147
136
  const ratchetPubKey = asBytes(chain.senderRatchetKey, `${field}.senderRatchetKey`);
148
- if (ratchetPubKey.byteLength !== 33) {
149
- throw new Error(`invalid ${field}.senderRatchetKey length ${ratchetPubKey.byteLength}`);
150
- }
137
+ assertByteLength(ratchetPubKey, 33, `invalid ${field}.senderRatchetKey length ${ratchetPubKey.byteLength}`);
151
138
  const chainKeyBytes = asBytes(chainKey.key, `${field}.chainKey.key`);
152
- if (chainKeyBytes.byteLength !== 32) {
153
- throw new Error(`invalid ${field}.chainKey.key length ${chainKeyBytes.byteLength}`);
154
- }
139
+ assertByteLength(chainKeyBytes, 32, `invalid ${field}.chainKey.key length ${chainKeyBytes.byteLength}`);
155
140
  return {
156
141
  ratchetKey: {
157
142
  pubKey: ratchetPubKey,
@@ -168,26 +153,20 @@ function decodeSignalSessionSnapshot(session, field) {
168
153
  }
169
154
  const pendingPreKey = session.pendingPreKey;
170
155
  const localPubKey = asBytes(session.localIdentityPublic, `${field}.localIdentityPublic`);
171
- if (localPubKey.byteLength !== 33) {
172
- throw new Error(`invalid ${field}.localIdentityPublic length ${localPubKey.byteLength}`);
173
- }
156
+ assertByteLength(localPubKey, 33, `invalid ${field}.localIdentityPublic length ${localPubKey.byteLength}`);
174
157
  const remotePubKey = asBytes(session.remoteIdentityPublic, `${field}.remoteIdentityPublic`);
175
- if (remotePubKey.byteLength !== 33) {
176
- throw new Error(`invalid ${field}.remoteIdentityPublic length ${remotePubKey.byteLength}`);
177
- }
158
+ assertByteLength(remotePubKey, 33, `invalid ${field}.remoteIdentityPublic length ${remotePubKey.byteLength}`);
178
159
  const rootKey = asBytes(session.rootKey, `${field}.rootKey`);
179
- if (rootKey.byteLength !== 32) {
180
- throw new Error(`invalid ${field}.rootKey length ${rootKey.byteLength}`);
181
- }
160
+ assertByteLength(rootKey, 32, `invalid ${field}.rootKey length ${rootKey.byteLength}`);
182
161
  const localOneTimePubKey = pendingPreKey
183
162
  ? asBytes(pendingPreKey.baseKey, `${field}.pendingPreKey.baseKey`)
184
163
  : null;
185
- if (localOneTimePubKey && localOneTimePubKey.byteLength !== 33) {
186
- throw new Error(`invalid ${field}.pendingPreKey.baseKey length ${localOneTimePubKey.byteLength}`);
164
+ if (localOneTimePubKey) {
165
+ assertByteLength(localOneTimePubKey, 33, `invalid ${field}.pendingPreKey.baseKey length ${localOneTimePubKey.byteLength}`);
187
166
  }
188
167
  const aliceBaseKey = asOptionalBytes(session.aliceBaseKey, `${field}.aliceBaseKey`) ?? null;
189
- if (aliceBaseKey && aliceBaseKey.byteLength !== 33) {
190
- throw new Error(`invalid ${field}.aliceBaseKey length ${aliceBaseKey.byteLength}`);
168
+ if (aliceBaseKey) {
169
+ assertByteLength(aliceBaseKey, 33, `invalid ${field}.aliceBaseKey length ${aliceBaseKey.byteLength}`);
191
170
  }
192
171
  return {
193
172
  local: {
@@ -101,18 +101,17 @@ export function createStore(options) {
101
101
  if (cached) {
102
102
  return cached;
103
103
  }
104
- const custom = options.custom;
105
- const customCache = options.customCache;
106
- const customAuth = resolveStoreValue(normalizedSessionId, custom?.auth, 'custom.auth');
107
- const customSignal = resolveStoreValue(normalizedSessionId, custom?.signal, 'custom.signal');
108
- const customSenderKey = resolveStoreValue(normalizedSessionId, custom?.senderKey, 'custom.senderKey');
109
- const customAppState = resolveStoreValue(normalizedSessionId, custom?.appState, 'custom.appState');
110
- const customRetry = resolveStoreValue(normalizedSessionId, customCache?.retry, 'customCache.retry');
111
- const customParticipants = resolveStoreValue(normalizedSessionId, customCache?.participants, 'customCache.participants');
112
- const customDeviceList = resolveStoreValue(normalizedSessionId, customCache?.deviceList, 'customCache.deviceList');
113
- const customMessages = resolveStoreValue(normalizedSessionId, custom?.messages, 'custom.messages');
114
- const customThreads = resolveStoreValue(normalizedSessionId, custom?.threads, 'custom.threads');
115
- const customContacts = resolveStoreValue(normalizedSessionId, custom?.contacts, 'custom.contacts');
104
+ const resolveCustom = (value, domainPath) => resolveStoreValue(normalizedSessionId, value, domainPath);
105
+ const customAuth = resolveCustom(options.custom?.auth, 'custom.auth');
106
+ const customSignal = resolveCustom(options.custom?.signal, 'custom.signal');
107
+ const customSenderKey = resolveCustom(options.custom?.senderKey, 'custom.senderKey');
108
+ const customAppState = resolveCustom(options.custom?.appState, 'custom.appState');
109
+ const customRetry = resolveCustom(options.customCache?.retry, 'customCache.retry');
110
+ const customParticipants = resolveCustom(options.customCache?.participants, 'customCache.participants');
111
+ const customDeviceList = resolveCustom(options.customCache?.deviceList, 'customCache.deviceList');
112
+ const customMessages = resolveCustom(options.custom?.messages, 'custom.messages');
113
+ const customThreads = resolveCustom(options.custom?.threads, 'custom.threads');
114
+ const customContacts = resolveCustom(options.custom?.contacts, 'custom.contacts');
116
115
  const memoryLimits = options.memory?.limits ?? {};
117
116
  const requiresSqlite = !customAuth ||
118
117
  (!customSignal && providers.signal === 'sqlite') ||
@@ -133,7 +132,8 @@ export function createStore(options) {
133
132
  path: sqlite.path,
134
133
  sessionId: normalizedSessionId,
135
134
  driver: sqlite.driver ?? 'auto',
136
- pragmas: sqlite.pragmas
135
+ pragmas: sqlite.pragmas,
136
+ tableNames: sqlite.tableNames
137
137
  }
138
138
  : null;
139
139
  const authStore = customAuth ?? new WaAuthSqliteStore(sqliteOptions);
@@ -258,8 +258,7 @@ export function createStore(options) {
258
258
  return session;
259
259
  },
260
260
  async destroyCaches() {
261
- const activeSessions = [...sessions.values()];
262
- for (const session of activeSessions) {
261
+ for (const session of sessions.values()) {
263
262
  await session.destroyCaches();
264
263
  }
265
264
  },
@@ -268,9 +267,8 @@ export function createStore(options) {
268
267
  return;
269
268
  }
270
269
  storeDestroyed = true;
271
- const activeSessions = [...sessions.values()];
272
- sessions.clear();
273
- for (const session of activeSessions) {
270
+ for (const [sessionId, session] of sessions) {
271
+ sessions.delete(sessionId);
274
272
  await session.destroy();
275
273
  }
276
274
  }
@@ -1,8 +1,7 @@
1
1
  const EMPTY_STORE_LIST = Object.freeze([]);
2
- const DEFAULT_PARTICIPANTS_CACHE_TTL_MS = 5 * 60 * 1000;
3
- const DEFAULT_DEVICE_LIST_CACHE_TTL_MS = 5 * 60 * 1000;
4
2
  export const NOOP_MESSAGE_STORE = Object.freeze({
5
3
  upsert: async (_record) => { },
4
+ upsertBatch: async (_records) => { },
6
5
  getById: async (_id) => null,
7
6
  listByThread: async (_threadJid, _limit, _beforeTimestampMs) => EMPTY_STORE_LIST,
8
7
  deleteById: async (_id) => 0,
@@ -10,6 +9,7 @@ export const NOOP_MESSAGE_STORE = Object.freeze({
10
9
  });
11
10
  export const NOOP_THREAD_STORE = Object.freeze({
12
11
  upsert: async (_record) => { },
12
+ upsertBatch: async (_records) => { },
13
13
  getByJid: async (_jid) => null,
14
14
  list: async (_limit) => EMPTY_STORE_LIST,
15
15
  deleteByJid: async (_jid) => 0,
@@ -17,12 +17,12 @@ export const NOOP_THREAD_STORE = Object.freeze({
17
17
  });
18
18
  export const NOOP_CONTACT_STORE = Object.freeze({
19
19
  upsert: async (_record) => { },
20
+ upsertBatch: async (_records) => { },
20
21
  getByJid: async (_jid) => null,
21
22
  deleteByJid: async (_jid) => 0,
22
23
  clear: async () => { }
23
24
  });
24
25
  export const NOOP_PARTICIPANTS_STORE = Object.freeze({
25
- getTtlMs: () => DEFAULT_PARTICIPANTS_CACHE_TTL_MS,
26
26
  upsertGroupParticipants: async (_snapshot) => { },
27
27
  getGroupParticipants: async (_groupJid, _nowMs) => null,
28
28
  deleteGroupParticipants: async (_groupJid) => 0,
@@ -31,10 +31,7 @@ export const NOOP_PARTICIPANTS_STORE = Object.freeze({
31
31
  destroy: async () => { }
32
32
  });
33
33
  export const NOOP_DEVICE_LIST_STORE = Object.freeze({
34
- getTtlMs: () => DEFAULT_DEVICE_LIST_CACHE_TTL_MS,
35
- upsertUserDevices: async (_snapshot) => { },
36
34
  upsertUserDevicesBatch: async (_snapshots) => { },
37
- getUserDevices: async (_userJid, _nowMs) => null,
38
35
  getUserDevicesBatch: async (userJids, _nowMs) => userJids.map(() => null),
39
36
  deleteUserDevices: async (_userJid) => 0,
40
37
  cleanupExpired: async (_nowMs) => 0,
@@ -1,6 +1,6 @@
1
1
  import { APP_STATE_EMPTY_LT_HASH } from '../../../appstate/constants.js';
2
- import { keyIdToHex, pickActiveSyncKey } from '../../../appstate/utils.js';
3
- import { uint8Equal } from '../../../util/bytes.js';
2
+ import { pickActiveSyncKey } from '../../../appstate/utils.js';
3
+ import { bytesToHex, uint8Equal } from '../../../util/bytes.js';
4
4
  import { resolvePositive } from '../../../util/coercion.js';
5
5
  import { setBoundedMapEntry } from '../../../util/collections.js';
6
6
  const DEFAULT_APPSTATE_MEMORY_STORE_LIMITS = Object.freeze({
@@ -22,13 +22,14 @@ export class WaAppStateMemoryStore {
22
22
  this.maxCollectionEntries = resolvePositive(options.maxCollectionEntries, DEFAULT_APPSTATE_MEMORY_STORE_LIMITS.collectionEntries, 'WaAppStateMemoryStoreOptions.maxCollectionEntries');
23
23
  if (initial) {
24
24
  for (const key of initial.keys) {
25
- setBoundedMapEntry(this.keys, keyIdToHex(key.keyId), key, this.maxSyncKeys);
25
+ setBoundedMapEntry(this.keys, bytesToHex(key.keyId), key, this.maxSyncKeys);
26
26
  }
27
27
  for (const [collectionName, collection] of Object.entries(initial.collections)) {
28
28
  if (!collection) {
29
29
  continue;
30
30
  }
31
31
  this.collections.set(collectionName, {
32
+ initialized: true,
32
33
  version: collection.version,
33
34
  hash: collection.hash,
34
35
  indexValueMap: toBoundedMap(Object.entries(collection.indexValueMap), this.maxCollectionEntries)
@@ -54,7 +55,7 @@ export class WaAppStateMemoryStore {
54
55
  async upsertSyncKeys(keys) {
55
56
  let inserted = 0;
56
57
  for (const key of keys) {
57
- const keyHex = keyIdToHex(key.keyId);
58
+ const keyHex = bytesToHex(key.keyId);
58
59
  const existing = this.keys.get(keyHex);
59
60
  if (existing && uint8Equal(existing.keyData, key.keyData)) {
60
61
  continue;
@@ -65,10 +66,13 @@ export class WaAppStateMemoryStore {
65
66
  return inserted;
66
67
  }
67
68
  async getSyncKey(keyId) {
68
- return this.keys.get(keyIdToHex(keyId)) ?? null;
69
+ return this.keys.get(bytesToHex(keyId)) ?? null;
69
70
  }
70
71
  async getSyncKeyData(keyId) {
71
- return this.keys.get(keyIdToHex(keyId))?.keyData ?? null;
72
+ return this.keys.get(bytesToHex(keyId))?.keyData ?? null;
73
+ }
74
+ async getSyncKeyDataBatch(keyIds) {
75
+ return keyIds.map((keyId) => this.keys.get(bytesToHex(keyId))?.keyData ?? null);
72
76
  }
73
77
  async getActiveSyncKey() {
74
78
  return pickActiveSyncKey(this.keys.values());
@@ -77,6 +81,7 @@ export class WaAppStateMemoryStore {
77
81
  let state = this.collections.get(collection);
78
82
  if (!state) {
79
83
  state = {
84
+ initialized: false,
80
85
  version: 0,
81
86
  hash: APP_STATE_EMPTY_LT_HASH,
82
87
  indexValueMap: new Map()
@@ -85,9 +90,28 @@ export class WaAppStateMemoryStore {
85
90
  }
86
91
  return state;
87
92
  }
93
+ async getCollectionStates(collections) {
94
+ const result = new Array(collections.length);
95
+ for (let index = 0; index < collections.length; index += 1) {
96
+ const collection = collections[index];
97
+ let state = this.collections.get(collection);
98
+ if (!state) {
99
+ state = {
100
+ initialized: false,
101
+ version: 0,
102
+ hash: APP_STATE_EMPTY_LT_HASH,
103
+ indexValueMap: new Map()
104
+ };
105
+ this.collections.set(collection, state);
106
+ }
107
+ result[index] = state;
108
+ }
109
+ return result;
110
+ }
88
111
  async setCollectionStates(updates) {
89
112
  for (const update of updates) {
90
113
  this.collections.set(update.collection, {
114
+ initialized: true,
91
115
  version: update.version,
92
116
  hash: update.hash,
93
117
  indexValueMap: toBoundedMap(update.indexValueMap.entries(), this.maxCollectionEntries)
@@ -11,6 +11,11 @@ export class WaContactMemoryStore {
11
11
  async upsert(record) {
12
12
  setBoundedMapEntry(this.contacts, record.jid, record, this.maxContacts);
13
13
  }
14
+ async upsertBatch(records) {
15
+ for (const record of records) {
16
+ setBoundedMapEntry(this.contacts, record.jid, record, this.maxContacts);
17
+ }
18
+ }
14
19
  async getByJid(jid) {
15
20
  return this.contacts.get(jid) ?? null;
16
21
  }
@@ -14,38 +14,15 @@ export class WaDeviceListMemoryStore {
14
14
  }, resolveCleanupIntervalMs(ttlMs));
15
15
  this.cleanupTimer.unref();
16
16
  }
17
- getTtlMs() {
18
- return this.ttlMs;
19
- }
20
- async upsertUserDevices(snapshot) {
21
- setBoundedMapEntry(this.records, snapshot.userJid, {
22
- ...snapshot,
23
- expiresAtMs: snapshot.updatedAtMs + this.ttlMs
24
- }, this.maxUsers);
25
- }
26
17
  async upsertUserDevicesBatch(snapshots) {
27
- for (const snapshot of snapshots) {
18
+ for (let index = 0; index < snapshots.length; index += 1) {
19
+ const snapshot = snapshots[index];
28
20
  setBoundedMapEntry(this.records, snapshot.userJid, {
29
21
  ...snapshot,
30
22
  expiresAtMs: snapshot.updatedAtMs + this.ttlMs
31
23
  }, this.maxUsers);
32
24
  }
33
25
  }
34
- async getUserDevices(userJid, nowMs = Date.now()) {
35
- const record = this.records.get(userJid);
36
- if (!record) {
37
- return null;
38
- }
39
- if (record.expiresAtMs <= nowMs) {
40
- this.records.delete(userJid);
41
- return null;
42
- }
43
- return {
44
- userJid: record.userJid,
45
- deviceJids: record.deviceJids,
46
- updatedAtMs: record.updatedAtMs
47
- };
48
- }
49
26
  async getUserDevicesBatch(userJids, nowMs = Date.now()) {
50
27
  return userJids.map((userJid) => {
51
28
  const record = this.records.get(userJid);
@@ -56,11 +33,7 @@ export class WaDeviceListMemoryStore {
56
33
  this.records.delete(userJid);
57
34
  return null;
58
35
  }
59
- return {
60
- userJid: record.userJid,
61
- deviceJids: record.deviceJids,
62
- updatedAtMs: record.updatedAtMs
63
- };
36
+ return record;
64
37
  });
65
38
  }
66
39
  async deleteUserDevices(userJid) {
@@ -1,6 +1,5 @@
1
1
  import { resolvePositive } from '../../../util/coercion.js';
2
- import { normalizeQueryLimit } from '../../../util/collections.js';
3
- import { setBoundedMapEntry } from '../../../util/collections.js';
2
+ import { normalizeQueryLimit, setBoundedMapEntry } from '../../../util/collections.js';
4
3
  const DEFAULT_MESSAGE_MEMORY_STORE_LIMITS = Object.freeze({
5
4
  messages: 50000
6
5
  });
@@ -12,6 +11,11 @@ export class WaMessageMemoryStore {
12
11
  async upsert(record) {
13
12
  setBoundedMapEntry(this.messages, record.id, record, this.maxMessages);
14
13
  }
14
+ async upsertBatch(records) {
15
+ for (const record of records) {
16
+ setBoundedMapEntry(this.messages, record.id, record, this.maxMessages);
17
+ }
18
+ }
15
19
  async getById(id) {
16
20
  return this.messages.get(id) ?? null;
17
21
  }
@@ -19,9 +23,8 @@ export class WaMessageMemoryStore {
19
23
  const normalizedLimit = normalizeQueryLimit(limit, 50);
20
24
  const records = [];
21
25
  for (const record of this.messages.values()) {
22
- if (record.threadJid !== threadJid) {
26
+ if (record.threadJid !== threadJid)
23
27
  continue;
24
- }
25
28
  if (beforeTimestampMs !== undefined &&
26
29
  (record.timestampMs === undefined || record.timestampMs >= beforeTimestampMs)) {
27
30
  continue;
@@ -29,7 +32,10 @@ export class WaMessageMemoryStore {
29
32
  records.push(record);
30
33
  }
31
34
  records.sort((left, right) => (right.timestampMs ?? 0) - (left.timestampMs ?? 0));
32
- return records.length <= normalizedLimit ? records : records.slice(0, normalizedLimit);
35
+ if (records.length > normalizedLimit) {
36
+ records.length = normalizedLimit;
37
+ }
38
+ return records;
33
39
  }
34
40
  async deleteById(id) {
35
41
  return this.messages.delete(id) ? 1 : 0;
@@ -14,9 +14,6 @@ export class WaParticipantsMemoryStore {
14
14
  }, resolveCleanupIntervalMs(ttlMs));
15
15
  this.cleanupTimer.unref();
16
16
  }
17
- getTtlMs() {
18
- return this.ttlMs;
19
- }
20
17
  async upsertGroupParticipants(snapshot) {
21
18
  setBoundedMapEntry(this.records, snapshot.groupJid, {
22
19
  ...snapshot,
@@ -32,11 +29,7 @@ export class WaParticipantsMemoryStore {
32
29
  this.records.delete(groupJid);
33
30
  return null;
34
31
  }
35
- return {
36
- groupJid: record.groupJid,
37
- participants: record.participants,
38
- updatedAtMs: record.updatedAtMs
39
- };
32
+ return record;
40
33
  }
41
34
  async deleteGroupParticipants(groupJid) {
42
35
  return this.records.delete(groupJid) ? 1 : 0;
@@ -1,6 +1,6 @@
1
+ import { signalAddressKey } from '../../../protocol/jid.js';
1
2
  import { resolvePositive } from '../../../util/coercion.js';
2
3
  import { setBoundedMapEntry } from '../../../util/collections.js';
3
- import { signalAddressKey } from '../../../util/signal-address.js';
4
4
  const DEFAULT_SENDER_KEY_STORE_LIMITS = Object.freeze({
5
5
  senderKeys: 8192,
6
6
  senderDistributions: 8192
@@ -45,10 +45,6 @@ export class SenderKeyMemoryStore {
45
45
  const record = this.senderKeys.get(this.makeKey(groupId, sender));
46
46
  return record ?? null;
47
47
  }
48
- async getDeviceSenderKeyDistribution(groupId, sender) {
49
- const record = this.senderDistributions.get(this.makeKey(groupId, sender));
50
- return record ?? null;
51
- }
52
48
  async getDeviceSenderKeyDistributions(groupId, senders) {
53
49
  return senders.map((sender) => this.senderDistributions.get(this.makeKey(groupId, sender)) ?? null);
54
50
  }
@@ -60,8 +56,10 @@ export class SenderKeyMemoryStore {
60
56
  }
61
57
  async markForgetSenderKey(groupId, participants) {
62
58
  let deleted = 0;
63
- for (const participant of participants) {
64
- deleted += await this.deleteDeviceSenderKey(participant, groupId);
59
+ for (let index = 0; index < participants.length; index += 1) {
60
+ const participant = participants[index];
61
+ deleted += this.deleteMatching(this.senderKeys, participant, groupId);
62
+ deleted += this.deleteMatching(this.senderDistributions, participant, groupId);
65
63
  }
66
64
  return deleted;
67
65
  }