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
@@ -4,7 +4,6 @@ exports.processHistorySyncNotification = processHistorySyncNotification;
4
4
  const node_util_1 = require("node:util");
5
5
  const node_zlib_1 = require("node:zlib");
6
6
  const _proto_1 = require("../proto.js");
7
- const base64_1 = require("../util/base64");
8
7
  const bytes_1 = require("../util/bytes");
9
8
  const primitives_1 = require("../util/primitives");
10
9
  const unzipAsync = (0, node_util_1.promisify)(node_zlib_1.unzip);
@@ -31,15 +30,58 @@ async function processHistorySyncNotification(deps, notification) {
31
30
  pushnames: historySync.pushnames.length
32
31
  });
33
32
  const nowMs = Date.now();
33
+ const contacts = [];
34
+ for (const pn of historySync.pushnames) {
35
+ if (!pn.id) {
36
+ continue;
37
+ }
38
+ contacts.push({
39
+ jid: pn.id,
40
+ pushName: pn.pushname ?? undefined,
41
+ lastUpdatedMs: nowMs
42
+ });
43
+ }
44
+ const threads = [];
45
+ const messages = [];
34
46
  let messagesCount = 0;
35
- const conversationPromises = [];
36
47
  for (const conversation of historySync.conversations) {
37
- conversationPromises.push(persistConversation(deps, conversation, nowMs).then((count) => {
38
- messagesCount += count;
39
- }));
48
+ const threadJid = conversation.id;
49
+ if (!threadJid) {
50
+ deps.logger.debug('skipping history sync conversation without thread jid');
51
+ continue;
52
+ }
53
+ threads.push({
54
+ jid: threadJid,
55
+ name: conversation.name ?? undefined,
56
+ unreadCount: conversation.unreadCount ?? undefined,
57
+ archived: conversation.archived ?? undefined,
58
+ pinned: conversation.pinned ?? undefined,
59
+ muteEndMs: (0, primitives_1.longToNumber)(conversation.muteEndTime) || undefined,
60
+ markedAsUnread: conversation.markedAsUnread ?? undefined,
61
+ ephemeralExpiration: conversation.ephemeralExpiration ?? undefined
62
+ });
63
+ for (const histMsg of conversation.messages ?? []) {
64
+ const webMsg = histMsg.message;
65
+ if (!webMsg?.key?.id) {
66
+ continue;
67
+ }
68
+ const timestampMs = (0, primitives_1.longToNumber)(webMsg.messageTimestamp) * 1000;
69
+ messages.push({
70
+ id: webMsg.key.id,
71
+ threadJid,
72
+ senderJid: webMsg.key.participant ?? undefined,
73
+ fromMe: webMsg.key.fromMe === true,
74
+ timestampMs: timestampMs || undefined,
75
+ messageBytes: webMsg.message
76
+ ? _proto_1.proto.Message.encode(webMsg.message).finish()
77
+ : undefined
78
+ });
79
+ messagesCount += 1;
80
+ }
40
81
  }
41
- const pushnamePromise = persistPushnames(deps, historySync.pushnames, nowMs);
42
- await Promise.all([...conversationPromises, pushnamePromise]);
82
+ await deps.contactStore.upsertBatch(contacts);
83
+ await deps.threadStore.upsertBatch(threads);
84
+ await deps.messageStore.upsertBatch(messages);
43
85
  const event = {
44
86
  syncType,
45
87
  messagesCount,
@@ -52,14 +94,14 @@ async function processHistorySyncNotification(deps, notification) {
52
94
  }
53
95
  async function downloadHistorySyncBlob(deps, notification) {
54
96
  if (notification.initialHistBootstrapInlinePayload) {
55
- return (0, base64_1.decodeProtoBytes)(notification.initialHistBootstrapInlinePayload, 'initialHistBootstrapInlinePayload');
97
+ return (0, bytes_1.decodeProtoBytes)(notification.initialHistBootstrapInlinePayload, 'initialHistBootstrapInlinePayload');
56
98
  }
57
99
  if (!notification.directPath) {
58
100
  throw new Error('history sync notification missing directPath');
59
101
  }
60
- const mediaKey = (0, base64_1.decodeProtoBytes)(notification.mediaKey, 'history sync mediaKey');
61
- const fileSha256 = (0, base64_1.decodeProtoBytes)(notification.fileSha256, 'history sync fileSha256');
62
- const fileEncSha256 = (0, base64_1.decodeProtoBytes)(notification.fileEncSha256, 'history sync fileEncSha256');
102
+ const mediaKey = (0, bytes_1.decodeProtoBytes)(notification.mediaKey, 'history sync mediaKey');
103
+ const fileSha256 = (0, bytes_1.decodeProtoBytes)(notification.fileSha256, 'history sync fileSha256');
104
+ const fileEncSha256 = (0, bytes_1.decodeProtoBytes)(notification.fileEncSha256, 'history sync fileEncSha256');
63
105
  return deps.mediaTransfer.downloadAndDecrypt({
64
106
  directPath: notification.directPath,
65
107
  mediaType: 'history',
@@ -68,55 +110,3 @@ async function downloadHistorySyncBlob(deps, notification) {
68
110
  fileEncSha256
69
111
  });
70
112
  }
71
- async function persistConversation(deps, conversation, _nowMs) {
72
- const threadJid = conversation.id;
73
- if (!threadJid) {
74
- deps.logger.debug('skipping history sync conversation without thread jid');
75
- return 0;
76
- }
77
- const messages = conversation.messages ?? [];
78
- const messageRecords = [];
79
- for (const histMsg of messages) {
80
- const webMsg = histMsg.message;
81
- if (!webMsg?.key?.id) {
82
- continue;
83
- }
84
- const timestampMs = (0, primitives_1.longToNumber)(webMsg.messageTimestamp) * 1000;
85
- const messageBytes = webMsg.message
86
- ? _proto_1.proto.Message.encode(webMsg.message).finish()
87
- : undefined;
88
- messageRecords.push({
89
- id: webMsg.key.id,
90
- threadJid,
91
- senderJid: webMsg.key.participant ?? undefined,
92
- fromMe: webMsg.key.fromMe === true,
93
- timestampMs: timestampMs || undefined,
94
- messageBytes
95
- });
96
- }
97
- const threadPromise = deps.threadStore.upsert({
98
- jid: threadJid,
99
- name: conversation.name ?? undefined,
100
- unreadCount: conversation.unreadCount ?? undefined,
101
- archived: conversation.archived ?? undefined,
102
- pinned: conversation.pinned ?? undefined,
103
- muteEndMs: (0, primitives_1.longToNumber)(conversation.muteEndTime) || undefined,
104
- markedAsUnread: conversation.markedAsUnread ?? undefined,
105
- ephemeralExpiration: conversation.ephemeralExpiration ?? undefined
106
- });
107
- const messagePromises = messageRecords.map((record) => deps.messageStore.upsert(record));
108
- await Promise.all([threadPromise, ...messagePromises]);
109
- return messageRecords.length;
110
- }
111
- async function persistPushnames(deps, pushnames, nowMs) {
112
- if (pushnames.length === 0) {
113
- return;
114
- }
115
- await Promise.all(pushnames
116
- .filter((pn) => !!pn.id)
117
- .map((pn) => deps.contactStore.upsert({
118
- jid: pn.id,
119
- pushName: pn.pushname ?? undefined,
120
- lastUpdatedMs: nowMs
121
- })));
122
- }
@@ -12,7 +12,6 @@ const constants_1 = require("../protocol/constants");
12
12
  const message_1 = require("../transport/node/builders/message");
13
13
  const pairing_1 = require("../transport/node/builders/pairing");
14
14
  const helpers_1 = require("../transport/node/helpers");
15
- const parse_1 = require("../transport/stream/parse");
16
15
  const primitives_1 = require("../util/primitives");
17
16
  const LOGOUT_FAILURE_REASONS = new Set([401, 403, 406]);
18
17
  const DISCONNECT_FAILURE_REASONS = new Set([405, 409, 503]);
@@ -128,8 +127,8 @@ function createIncomingReceiptHandler(options) {
128
127
  }
129
128
  function createIncomingFailureHandler(options) {
130
129
  return async (node) => {
131
- const reason = (0, parse_1.parseOptionalInt)(node.attrs.reason);
132
- const code = (0, parse_1.parseOptionalInt)(node.attrs.code);
130
+ const reason = (0, primitives_1.parseOptionalInt)(node.attrs.reason);
131
+ const code = (0, primitives_1.parseOptionalInt)(node.attrs.code);
133
132
  options.emitIncomingFailure({
134
133
  ...createIncomingBaseEvent(node),
135
134
  failureReason: reason,
@@ -150,47 +149,50 @@ function createIncomingNotificationHandler(options) {
150
149
  const notificationType = node.attrs.type ?? '';
151
150
  const classification = classifyNotificationType(notificationType);
152
151
  const firstChildTag = (0, helpers_1.getFirstNodeChild)(node)?.tag;
152
+ const baseEvent = createIncomingBaseEvent(node);
153
153
  const serverSyncCollections = notificationType === 'server_sync'
154
- ? (0, helpers_1.getNodeChildrenByTag)(node, constants_1.WA_NODE_TAGS.COLLECTION)
155
- .map((collectionNode) => collectionNode.attrs.name)
156
- .filter((name) => typeof name === 'string' && name.length > 0)
154
+ ? (0, helpers_1.getNodeChildrenNonEmptyAttrValuesByTag)(node, constants_1.WA_NODE_TAGS.COLLECTION, 'name')
157
155
  : [];
156
+ let details;
157
+ if (firstChildTag || serverSyncCollections.length > 0) {
158
+ details = {};
159
+ if (firstChildTag) {
160
+ details.firstChildTag = firstChildTag;
161
+ }
162
+ if (serverSyncCollections.length > 0) {
163
+ details.collections = serverSyncCollections;
164
+ }
165
+ }
158
166
  options.emitIncomingNotification({
159
- ...createIncomingBaseEvent(node),
167
+ ...baseEvent,
160
168
  notificationType,
161
169
  classification,
162
- details: firstChildTag || serverSyncCollections.length > 0
163
- ? {
164
- ...(firstChildTag ? { firstChildTag } : {}),
165
- ...(serverSyncCollections.length > 0
166
- ? { collections: serverSyncCollections }
167
- : {})
168
- }
169
- : undefined
170
+ details
170
171
  });
171
172
  if (classification === 'out_of_scope') {
172
173
  options.emitUnhandledStanza({
173
- ...createIncomingBaseEvent(node),
174
+ ...baseEvent,
174
175
  reason: `notification.${notificationType}.out_of_scope`
175
176
  });
176
177
  }
177
178
  else if (classification === 'unknown') {
178
179
  options.emitUnhandledStanza({
179
- ...createIncomingBaseEvent(node),
180
+ ...baseEvent,
180
181
  reason: `notification.${notificationType || 'unknown'}.not_supported`
181
182
  });
182
183
  }
183
184
  await sendSafeAck(options.logger, options.sendNode, (0, pairing_1.buildNotificationAckNode)(node));
184
185
  if (notificationType === 'server_sync' && serverSyncCollections.length > 0) {
186
+ const collectionsCsv = serverSyncCollections.join(',');
185
187
  if (!options.syncAppState) {
186
188
  options.logger.warn('received server_sync notification without app-state sync runtime', {
187
- collections: serverSyncCollections.join(',')
189
+ collections: collectionsCsv
188
190
  });
189
191
  return true;
190
192
  }
191
193
  void options.syncAppState().catch((error) => {
192
194
  options.logger.warn('failed to sync app-state after server_sync notification', {
193
- collections: serverSyncCollections.join(','),
195
+ collections: collectionsCsv,
194
196
  message: (0, primitives_1.toError)(error).message
195
197
  });
196
198
  });
@@ -203,6 +205,7 @@ function createIncomingGroupNotificationHandler(options) {
203
205
  if (node.attrs.type !== constants_1.WA_NOTIFICATION_TYPES.GROUP) {
204
206
  return false;
205
207
  }
208
+ const baseEvent = createIncomingBaseEvent(node);
206
209
  const parsed = (0, group_1.parseGroupNotificationEvents)(node);
207
210
  for (const event of parsed.events) {
208
211
  options.emitGroupEvent(event);
@@ -212,7 +215,7 @@ function createIncomingGroupNotificationHandler(options) {
212
215
  }
213
216
  if (parsed.events.length === 0 && parsed.unhandled.length === 0) {
214
217
  options.emitUnhandledStanza({
215
- ...createIncomingBaseEvent(node),
218
+ ...baseEvent,
216
219
  reason: `notification.${constants_1.WA_NOTIFICATION_TYPES.GROUP}.empty`
217
220
  });
218
221
  }
@@ -4,14 +4,12 @@ exports.persistIncomingMailboxEntities = persistIncomingMailboxEntities;
4
4
  const _proto_1 = require("../proto.js");
5
5
  const primitives_1 = require("../util/primitives");
6
6
  async function persistContacts(contactStore, event, nowMs) {
7
- const candidateJids = new Set();
8
- if (event.senderJid) {
9
- candidateJids.add(event.senderJid);
10
- }
11
- if (event.rawNode.attrs.participant) {
12
- candidateJids.add(event.rawNode.attrs.participant);
7
+ const candidateJids = [event.senderJid, event.rawNode.attrs.participant].filter((jid) => !!jid);
8
+ if (candidateJids.length === 0) {
9
+ return;
13
10
  }
14
- await Promise.all(Array.from(candidateJids, (jid) => contactStore.upsert({ jid, lastUpdatedMs: nowMs })));
11
+ const contacts = [...new Set(candidateJids)].map((jid) => ({ jid, lastUpdatedMs: nowMs }));
12
+ await contactStore.upsertBatch(contacts);
15
13
  }
16
14
  async function persistIncomingMailboxEntities(options) {
17
15
  const { logger, contactStore, messageStore, event } = options;
@@ -31,7 +29,9 @@ async function persistIncomingMailboxEntities(options) {
31
29
  senderJid: event.senderJid,
32
30
  participantJid: event.rawNode.attrs.participant,
33
31
  fromMe: false,
34
- timestampMs: event.timestampSeconds === undefined ? undefined : event.timestampSeconds * 1000,
32
+ timestampMs: event.timestampSeconds === undefined
33
+ ? undefined
34
+ : event.timestampSeconds * 1000,
35
35
  encType: event.encryptionType,
36
36
  plaintext: event.plaintext,
37
37
  messageBytes
@@ -8,8 +8,8 @@ const WaMediaCrypto_1 = require("../media/WaMediaCrypto");
8
8
  const content_1 = require("../message/content");
9
9
  const constants_2 = require("../protocol/constants");
10
10
  const media_1 = require("../transport/node/builders/media");
11
- const base64_1 = require("../util/base64");
12
11
  const bytes_1 = require("../util/bytes");
12
+ const bytes_2 = require("../util/bytes");
13
13
  const primitives_1 = require("../util/primitives");
14
14
  async function buildMediaMessageContent(options, content) {
15
15
  if (typeof content === 'string') {
@@ -36,7 +36,7 @@ async function getMediaConn(options, forceRefresh = false) {
36
36
  return mediaConn;
37
37
  }
38
38
  async function buildMediaMessage(options, content) {
39
- const mediaBytes = (0, bytes_1.toBytesView)(content.media);
39
+ const mediaBytes = (0, bytes_2.toBytesView)(content.media);
40
40
  const uploaded = await uploadMedia(options, content, mediaBytes);
41
41
  const mediaKeyTimestamp = Math.floor(Date.now() / 1000);
42
42
  const common = {
@@ -113,7 +113,7 @@ async function uploadMedia(options, content, mediaBytes) {
113
113
  ]);
114
114
  const selectedHost = mediaConn.hosts.find((host) => !host.isFallback)?.hostname ?? mediaConn.hosts[0].hostname;
115
115
  const uploadPath = constants_1.MEDIA_UPLOAD_PATHS[uploadType];
116
- const hashToken = (0, base64_1.bytesToBase64UrlSafe)(encrypted.fileEncSha256);
116
+ const hashToken = (0, bytes_1.bytesToBase64UrlSafe)(encrypted.fileEncSha256);
117
117
  const uploadUrl = `https://${selectedHost}${uploadPath}/${hashToken}?auth=${encodeURIComponent(mediaConn.auth)}&token=${encodeURIComponent(hashToken)}`;
118
118
  options.logger.debug('sending media upload request', {
119
119
  mediaType: content.type,
@@ -133,7 +133,7 @@ async function uploadMedia(options, content, mediaBytes) {
133
133
  }
134
134
  let parsedBody;
135
135
  try {
136
- parsedBody = JSON.parse(bytes_1.TEXT_DECODER.decode(uploadBody));
136
+ parsedBody = JSON.parse(bytes_2.TEXT_DECODER.decode(uploadBody));
137
137
  }
138
138
  catch (error) {
139
139
  throw new Error(`media upload returned invalid json: ${(0, primitives_1.toError)(error).message}`);
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDeviceFanoutResolver = createDeviceFanoutResolver;
4
+ const jid_1 = require("../../protocol/jid");
5
+ const primitives_1 = require("../../util/primitives");
6
+ function createDeviceFanoutResolver(options) {
7
+ const { signalDeviceSync, getCurrentMeJid, getCurrentMeLid, logger } = options;
8
+ const requireCurrentMeJid = (context) => {
9
+ const meJid = getCurrentMeJid();
10
+ if (meJid) {
11
+ return meJid;
12
+ }
13
+ throw new Error(`${context} requires registered meJid`);
14
+ };
15
+ const resolveDirectFanoutDeviceJids = async (recipientJid, selfDeviceJidForRecipient) => {
16
+ const recipientUserJid = (0, jid_1.toUserJid)(recipientJid);
17
+ const meUserJid = (0, jid_1.toUserJid)(selfDeviceJidForRecipient);
18
+ const targets = recipientUserJid === meUserJid ? [recipientUserJid] : [recipientUserJid, meUserJid];
19
+ try {
20
+ const synced = await signalDeviceSync.syncDeviceList(targets);
21
+ const byUser = new Map(synced.map((entry) => [(0, jid_1.toUserJid)(entry.jid), entry.deviceJids]));
22
+ const fanout = new Set();
23
+ const recipientDevices = byUser.get(recipientUserJid) ?? [];
24
+ if (recipientDevices.length === 0) {
25
+ fanout.add(recipientUserJid);
26
+ }
27
+ else {
28
+ for (let index = 0; index < recipientDevices.length; index += 1) {
29
+ fanout.add(recipientDevices[index]);
30
+ }
31
+ }
32
+ const meDevices = byUser.get(meUserJid) ?? [];
33
+ const normalizedMeJid = (0, jid_1.normalizeDeviceJid)(selfDeviceJidForRecipient);
34
+ for (let index = 0; index < meDevices.length; index += 1) {
35
+ const deviceJid = meDevices[index];
36
+ if ((0, jid_1.normalizeDeviceJid)(deviceJid) === normalizedMeJid) {
37
+ continue;
38
+ }
39
+ fanout.add(deviceJid);
40
+ }
41
+ return [...fanout];
42
+ }
43
+ catch (error) {
44
+ logger.warn('signal device fanout sync failed, falling back to direct recipient', {
45
+ to: recipientJid,
46
+ message: (0, primitives_1.toError)(error).message
47
+ });
48
+ return [recipientUserJid];
49
+ }
50
+ };
51
+ const resolveGroupParticipantDeviceJids = async (participantUserJids) => {
52
+ const meDeviceJids = new Set();
53
+ const meJid = getCurrentMeJid();
54
+ if (meJid) {
55
+ try {
56
+ meDeviceJids.add((0, jid_1.normalizeDeviceJid)(meJid));
57
+ }
58
+ catch (error) {
59
+ logger.trace('ignoring malformed me jid', {
60
+ meJid,
61
+ message: (0, primitives_1.toError)(error).message
62
+ });
63
+ }
64
+ }
65
+ const meLid = getCurrentMeLid();
66
+ if (meLid && meLid.includes('@')) {
67
+ try {
68
+ meDeviceJids.add((0, jid_1.normalizeDeviceJid)(meLid));
69
+ }
70
+ catch (error) {
71
+ logger.trace('ignoring malformed me lid jid', {
72
+ meLid,
73
+ message: (0, primitives_1.toError)(error).message
74
+ });
75
+ }
76
+ }
77
+ const candidateUsers = [...new Set(participantUserJids)];
78
+ if (candidateUsers.length === 0) {
79
+ return [];
80
+ }
81
+ try {
82
+ const synced = await signalDeviceSync.syncDeviceList(candidateUsers);
83
+ const fanout = new Set();
84
+ for (const entry of synced) {
85
+ if (entry.deviceJids.length === 0) {
86
+ const normalizedEntryJid = (0, jid_1.normalizeDeviceJid)(entry.jid);
87
+ if (meDeviceJids.has(normalizedEntryJid)) {
88
+ continue;
89
+ }
90
+ fanout.add(normalizedEntryJid);
91
+ continue;
92
+ }
93
+ for (const deviceJid of entry.deviceJids) {
94
+ const normalizedDeviceJid = (0, jid_1.normalizeDeviceJid)(deviceJid);
95
+ if (meDeviceJids.has(normalizedDeviceJid)) {
96
+ continue;
97
+ }
98
+ fanout.add(normalizedDeviceJid);
99
+ }
100
+ }
101
+ return [...fanout];
102
+ }
103
+ catch (error) {
104
+ logger.warn('group participant device sync failed, falling back to participant user jids', {
105
+ participants: candidateUsers.length,
106
+ message: (0, primitives_1.toError)(error).message
107
+ });
108
+ const fallbackJids = new Set();
109
+ for (const candidateJid of candidateUsers) {
110
+ try {
111
+ const normalizedCandidateJid = (0, jid_1.normalizeDeviceJid)(candidateJid);
112
+ if (meDeviceJids.has(normalizedCandidateJid)) {
113
+ continue;
114
+ }
115
+ fallbackJids.add(normalizedCandidateJid);
116
+ }
117
+ catch (fallbackError) {
118
+ logger.trace('ignoring malformed participant jid in fallback fanout resolution', {
119
+ participantJid: candidateJid,
120
+ message: (0, primitives_1.toError)(fallbackError).message
121
+ });
122
+ }
123
+ }
124
+ return [...fallbackJids];
125
+ }
126
+ };
127
+ const resolveOwnPeerDeviceJids = async () => {
128
+ const meJid = requireCurrentMeJid('resolveOwnPeerDeviceJids');
129
+ const meUserJid = (0, jid_1.toUserJid)(meJid);
130
+ const meDevices = new Set();
131
+ meDevices.add((0, jid_1.normalizeDeviceJid)(meJid));
132
+ const meLid = getCurrentMeLid();
133
+ if (meLid && meLid.includes('@')) {
134
+ try {
135
+ meDevices.add((0, jid_1.normalizeDeviceJid)(meLid));
136
+ }
137
+ catch (error) {
138
+ logger.trace('ignoring malformed me lid jid while resolving peer devices', {
139
+ meLid,
140
+ message: (0, primitives_1.toError)(error).message
141
+ });
142
+ }
143
+ }
144
+ try {
145
+ const synced = await signalDeviceSync.syncDeviceList([meUserJid]);
146
+ const peerDevices = new Set();
147
+ for (const entry of synced) {
148
+ const sourceDevices = entry.deviceJids.length > 0 ? entry.deviceJids : [entry.jid];
149
+ for (const deviceJid of sourceDevices) {
150
+ try {
151
+ const normalized = (0, jid_1.normalizeDeviceJid)(deviceJid);
152
+ if (meDevices.has(normalized)) {
153
+ continue;
154
+ }
155
+ peerDevices.add(normalized);
156
+ }
157
+ catch (error) {
158
+ logger.trace('ignoring malformed peer device jid while resolving app-state peers', {
159
+ deviceJid,
160
+ message: (0, primitives_1.toError)(error).message
161
+ });
162
+ }
163
+ }
164
+ }
165
+ return [...peerDevices];
166
+ }
167
+ catch (error) {
168
+ logger.warn('failed to resolve peer devices for app-state key request', {
169
+ message: (0, primitives_1.toError)(error).message
170
+ });
171
+ return [];
172
+ }
173
+ };
174
+ const resolveSelfDeviceJidForRecipient = (recipientJid, meJid, meLid) => {
175
+ if ((0, jid_1.splitJid)(recipientJid).server !== 'lid') {
176
+ return meJid;
177
+ }
178
+ if (!meLid || !meLid.includes('@')) {
179
+ return meJid;
180
+ }
181
+ return meLid;
182
+ };
183
+ return {
184
+ resolveDirectFanoutDeviceJids,
185
+ resolveGroupParticipantDeviceJids,
186
+ resolveOwnPeerDeviceJids,
187
+ resolveSelfDeviceJidForRecipient
188
+ };
189
+ }
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAppStateSyncKeyProtocol = createAppStateSyncKeyProtocol;
4
+ const padding_1 = require("../../message/padding");
5
+ const _proto_1 = require("../../proto.js");
6
+ const jid_1 = require("../../protocol/jid");
7
+ const bytes_1 = require("../../util/bytes");
8
+ function createAppStateSyncKeyProtocol(options) {
9
+ const { publishSignalMessage, fanoutResolver, getCurrentMeJid, getCurrentMeLid, logger } = options;
10
+ const requireCurrentIdentity = (context) => {
11
+ const meJid = getCurrentMeJid();
12
+ const meLid = getCurrentMeLid();
13
+ if (meJid || meLid) {
14
+ return;
15
+ }
16
+ throw new Error(`${context} requires registered identity`);
17
+ };
18
+ const publishProtocolMessageToDevice = async (deviceJid, protocolMessage) => {
19
+ const plaintext = await (0, padding_1.writeRandomPadMax16)(_proto_1.proto.Message.encode({
20
+ protocolMessage
21
+ }).finish());
22
+ await publishSignalMessage({
23
+ to: deviceJid,
24
+ plaintext,
25
+ type: 'protocol',
26
+ category: 'peer',
27
+ pushPriority: 'high'
28
+ });
29
+ };
30
+ const requestKeys = async (keyIds) => {
31
+ requireCurrentIdentity('requestKeys');
32
+ const normalizedKeyIds = [];
33
+ const seenKeyIds = new Set();
34
+ for (const keyId of keyIds) {
35
+ if (keyId.byteLength === 0) {
36
+ continue;
37
+ }
38
+ const keyHex = (0, bytes_1.bytesToHex)(keyId);
39
+ if (seenKeyIds.has(keyHex)) {
40
+ continue;
41
+ }
42
+ seenKeyIds.add(keyHex);
43
+ normalizedKeyIds.push(keyId);
44
+ }
45
+ if (normalizedKeyIds.length === 0) {
46
+ return [];
47
+ }
48
+ const peerDeviceJids = await fanoutResolver.resolveOwnPeerDeviceJids();
49
+ if (peerDeviceJids.length === 0) {
50
+ logger.warn('app-state sync key request skipped: no peer devices available', {
51
+ keys: normalizedKeyIds.length
52
+ });
53
+ return [];
54
+ }
55
+ const protocolMessage = {
56
+ type: _proto_1.proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_REQUEST,
57
+ appStateSyncKeyRequest: {
58
+ keyIds: normalizedKeyIds.map((keyId) => ({
59
+ keyId
60
+ }))
61
+ }
62
+ };
63
+ const publishResults = await Promise.allSettled(peerDeviceJids.map((deviceJid) => publishProtocolMessageToDevice(deviceJid, protocolMessage)));
64
+ const failedPublishes = publishResults.filter((result) => result.status === 'rejected').length;
65
+ if (failedPublishes > 0) {
66
+ logger.warn('some app-state sync key requests failed', {
67
+ total: peerDeviceJids.length,
68
+ failed: failedPublishes
69
+ });
70
+ }
71
+ logger.info('app-state sync key request sent to peer devices', {
72
+ devices: peerDeviceJids.length,
73
+ keys: normalizedKeyIds.length,
74
+ keyIds: normalizedKeyIds.map((keyId) => (0, bytes_1.bytesToHex)(keyId)).join(',')
75
+ });
76
+ return peerDeviceJids;
77
+ };
78
+ const sendKeyShare = async (toDeviceJid, keys, missingKeyIds = []) => {
79
+ requireCurrentIdentity('sendKeyShare');
80
+ const normalizedTo = (0, jid_1.normalizeDeviceJid)(toDeviceJid);
81
+ const seenKeyIds = new Set();
82
+ const keyShareEntries = [];
83
+ let sharedKeyCount = 0;
84
+ for (const key of keys) {
85
+ const keyHex = (0, bytes_1.bytesToHex)(key.keyId);
86
+ if (seenKeyIds.has(keyHex)) {
87
+ continue;
88
+ }
89
+ seenKeyIds.add(keyHex);
90
+ sharedKeyCount += 1;
91
+ keyShareEntries.push({
92
+ keyId: { keyId: key.keyId },
93
+ keyData: {
94
+ keyData: key.keyData,
95
+ timestamp: key.timestamp,
96
+ ...(key.fingerprint ? { fingerprint: key.fingerprint } : {})
97
+ }
98
+ });
99
+ }
100
+ for (const keyId of missingKeyIds) {
101
+ if (keyId.byteLength === 0) {
102
+ continue;
103
+ }
104
+ const keyHex = (0, bytes_1.bytesToHex)(keyId);
105
+ if (seenKeyIds.has(keyHex)) {
106
+ continue;
107
+ }
108
+ seenKeyIds.add(keyHex);
109
+ keyShareEntries.push({
110
+ keyId: { keyId }
111
+ });
112
+ }
113
+ const protocolMessage = {
114
+ type: _proto_1.proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_SHARE,
115
+ appStateSyncKeyShare: {
116
+ keys: keyShareEntries
117
+ }
118
+ };
119
+ await publishProtocolMessageToDevice(normalizedTo, protocolMessage);
120
+ logger.info('app-state sync key share sent', {
121
+ to: normalizedTo,
122
+ keys: sharedKeyCount,
123
+ orphanKeys: keyShareEntries.length - sharedKeyCount
124
+ });
125
+ };
126
+ return {
127
+ requestKeys,
128
+ sendKeyShare
129
+ };
130
+ }