zapo-js 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (589) hide show
  1. package/README.md +20 -4
  2. package/dist/appstate/WaAppStateCrypto.js +19 -26
  3. package/dist/appstate/WaAppStateSyncClient.js +293 -181
  4. package/dist/appstate/WaAppStateSyncResponseParser.js +16 -5
  5. package/dist/appstate/constants.js +4 -3
  6. package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
  7. package/dist/appstate/index.js +8 -6
  8. package/dist/appstate/utils.js +9 -34
  9. package/dist/auth/WaAuthClient.js +43 -61
  10. package/dist/auth/flow/WaAuthCredentialsFlow.js +22 -15
  11. package/dist/auth/index.js +1 -8
  12. package/dist/auth/pairing/WaPairingCodeCrypto.js +6 -4
  13. package/dist/auth/pairing/WaPairingFlow.js +34 -26
  14. package/dist/auth/pairing/WaQrFlow.js +37 -24
  15. package/dist/client/WaClient.js +275 -324
  16. package/dist/client/WaClientFactory.js +500 -133
  17. package/dist/client/connection/WaConnectionManager.js +301 -0
  18. package/dist/client/connection/WaKeyShareCoordinator.js +63 -0
  19. package/dist/client/connection/WaReceiptQueue.js +51 -0
  20. package/dist/client/coordinators/WaAppStateMutationCoordinator.js +471 -0
  21. package/dist/client/coordinators/WaBusinessCoordinator.js +241 -0
  22. package/dist/client/coordinators/WaGroupCoordinator.js +30 -16
  23. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
  24. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +439 -701
  25. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  26. package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
  27. package/dist/client/coordinators/WaProfileCoordinator.js +212 -0
  28. package/dist/client/coordinators/WaRetryCoordinator.js +242 -57
  29. package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
  30. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +166 -0
  31. package/dist/client/dirty.js +74 -48
  32. package/dist/client/events/chat.js +4 -3
  33. package/dist/client/events/devices.js +72 -0
  34. package/dist/client/events/group.js +62 -47
  35. package/dist/client/events/identity.js +22 -0
  36. package/dist/client/events/privacy-token.js +39 -0
  37. package/dist/client/history-sync.js +94 -63
  38. package/dist/client/incoming.js +60 -27
  39. package/dist/client/mailbox.js +24 -23
  40. package/dist/client/messages.js +107 -31
  41. package/dist/client/messaging/fanout.js +199 -0
  42. package/dist/client/messaging/key-protocol.js +130 -0
  43. package/dist/client/messaging/participants.js +193 -0
  44. package/dist/client/persistence/WriteBehindPersistence.js +129 -0
  45. package/dist/client/tokens/cs-token.js +50 -0
  46. package/dist/client/tokens/tc-token.js +25 -0
  47. package/dist/crypto/core/hkdf.js +3 -8
  48. package/dist/crypto/core/index.js +2 -5
  49. package/dist/crypto/core/keys.js +6 -7
  50. package/dist/crypto/core/nonce.js +2 -0
  51. package/dist/crypto/core/primitives.js +12 -23
  52. package/dist/crypto/core/random.js +26 -23
  53. package/dist/crypto/curves/Ed25519.js +7 -8
  54. package/dist/crypto/curves/X25519.js +38 -22
  55. package/dist/crypto/index.js +1 -3
  56. package/dist/crypto/math/constants.js +13 -36
  57. package/dist/crypto/math/edwards.js +171 -44
  58. package/dist/crypto/math/fe.js +706 -0
  59. package/dist/crypto/math/mod.js +10 -3
  60. package/dist/esm/appstate/WaAppStateCrypto.js +7 -14
  61. package/dist/esm/appstate/WaAppStateSyncClient.js +284 -172
  62. package/dist/esm/appstate/WaAppStateSyncResponseParser.js +17 -6
  63. package/dist/esm/appstate/constants.js +3 -2
  64. package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
  65. package/dist/esm/appstate/index.js +2 -2
  66. package/dist/esm/appstate/utils.js +8 -30
  67. package/dist/esm/auth/WaAuthClient.js +43 -61
  68. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +22 -15
  69. package/dist/esm/auth/index.js +0 -3
  70. package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +6 -4
  71. package/dist/esm/auth/pairing/WaPairingFlow.js +28 -20
  72. package/dist/esm/auth/pairing/WaQrFlow.js +37 -24
  73. package/dist/esm/client/WaClient.js +275 -324
  74. package/dist/esm/client/WaClientFactory.js +501 -134
  75. package/dist/esm/client/connection/WaConnectionManager.js +297 -0
  76. package/dist/esm/client/connection/WaKeyShareCoordinator.js +59 -0
  77. package/dist/esm/client/connection/WaReceiptQueue.js +47 -0
  78. package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +467 -0
  79. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +238 -0
  80. package/dist/esm/client/coordinators/WaGroupCoordinator.js +23 -9
  81. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +21 -27
  82. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +443 -705
  83. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  84. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
  85. package/dist/esm/client/coordinators/WaProfileCoordinator.js +209 -0
  86. package/dist/esm/client/coordinators/WaRetryCoordinator.js +244 -59
  87. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
  88. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +162 -0
  89. package/dist/esm/client/dirty.js +69 -43
  90. package/dist/esm/client/events/chat.js +4 -3
  91. package/dist/esm/client/events/devices.js +68 -0
  92. package/dist/esm/client/events/group.js +53 -39
  93. package/dist/esm/client/events/identity.js +19 -0
  94. package/dist/esm/client/events/privacy-token.js +36 -0
  95. package/dist/esm/client/history-sync.js +91 -60
  96. package/dist/esm/client/incoming.js +61 -28
  97. package/dist/esm/client/mailbox.js +24 -23
  98. package/dist/esm/client/messages.js +108 -32
  99. package/dist/esm/client/messaging/fanout.js +196 -0
  100. package/dist/esm/client/messaging/key-protocol.js +127 -0
  101. package/dist/esm/client/messaging/participants.js +190 -0
  102. package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
  103. package/dist/esm/client/tokens/cs-token.js +46 -0
  104. package/dist/esm/client/tokens/tc-token.js +18 -0
  105. package/dist/esm/crypto/core/hkdf.js +3 -8
  106. package/dist/esm/crypto/core/index.js +2 -3
  107. package/dist/esm/crypto/core/keys.js +3 -4
  108. package/dist/esm/crypto/core/nonce.js +2 -0
  109. package/dist/esm/crypto/core/primitives.js +12 -22
  110. package/dist/esm/crypto/core/random.js +25 -23
  111. package/dist/esm/crypto/curves/Ed25519.js +4 -5
  112. package/dist/esm/crypto/curves/X25519.js +35 -19
  113. package/dist/esm/crypto/index.js +0 -1
  114. package/dist/esm/crypto/math/constants.js +12 -35
  115. package/dist/esm/crypto/math/edwards.js +174 -47
  116. package/dist/esm/crypto/math/fe.js +691 -0
  117. package/dist/esm/crypto/math/mod.js +10 -1
  118. package/dist/esm/index.js +1 -1
  119. package/dist/esm/infra/log/ConsoleLogger.js +18 -17
  120. package/dist/esm/infra/log/PinoLogger.js +15 -9
  121. package/dist/esm/infra/log/types.js +11 -1
  122. package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
  123. package/dist/esm/infra/perf/BoundedTaskQueue.js +16 -18
  124. package/dist/esm/infra/perf/PromiseDedup.js +20 -0
  125. package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
  126. package/dist/esm/infra/perf/StoreLock.js +77 -0
  127. package/dist/esm/media/WaMediaCrypto.js +96 -16
  128. package/dist/esm/media/WaMediaTransferClient.js +251 -91
  129. package/dist/esm/media/conn.js +10 -6
  130. package/dist/esm/media/constants.js +6 -2
  131. package/dist/esm/message/WaMessageClient.js +30 -32
  132. package/dist/esm/message/ack.js +6 -6
  133. package/dist/esm/message/addon-crypto.js +59 -0
  134. package/dist/esm/message/content.js +195 -9
  135. package/dist/esm/message/icdc.js +76 -0
  136. package/dist/esm/message/incoming.js +129 -122
  137. package/dist/esm/message/index.js +2 -0
  138. package/dist/esm/message/phash.js +3 -1
  139. package/dist/esm/message/reporting-token.js +425 -0
  140. package/dist/esm/message/use-case-secret.js +49 -0
  141. package/dist/esm/protocol/appstate.js +27 -0
  142. package/dist/esm/protocol/browser.js +10 -18
  143. package/dist/esm/protocol/constants.js +6 -3
  144. package/dist/esm/protocol/defaults.js +6 -0
  145. package/dist/esm/protocol/index.js +2 -11
  146. package/dist/esm/protocol/jid.js +133 -52
  147. package/dist/esm/protocol/media.js +3 -3
  148. package/dist/esm/protocol/message.js +61 -1
  149. package/dist/esm/protocol/nodes.js +4 -0
  150. package/dist/esm/protocol/notification.js +3 -1
  151. package/dist/esm/protocol/privacy-token.js +17 -0
  152. package/dist/esm/protocol/privacy.js +55 -0
  153. package/dist/esm/protocol/stream.js +26 -1
  154. package/dist/esm/protocol/usync.js +11 -0
  155. package/dist/esm/retry/codec.js +216 -0
  156. package/dist/esm/retry/constants.js +1 -1
  157. package/dist/esm/retry/index.js +3 -2
  158. package/dist/esm/retry/parse.js +88 -86
  159. package/dist/esm/retry/replay.js +54 -51
  160. package/dist/esm/retry/tracker.js +94 -0
  161. package/dist/esm/signal/api/SignalDeviceSyncApi.js +276 -92
  162. package/dist/esm/signal/api/SignalDigestSyncApi.js +17 -8
  163. package/dist/esm/signal/api/SignalIdentitySyncApi.js +67 -37
  164. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +86 -67
  165. package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
  166. package/dist/esm/signal/api/SignalSessionSyncApi.js +36 -34
  167. package/dist/esm/signal/api/result-map.js +10 -0
  168. package/dist/esm/signal/constants.js +0 -4
  169. package/dist/esm/signal/crypto/WaAdvSignature.js +13 -9
  170. package/dist/esm/signal/{store/sqlite.js → encoding.js} +93 -60
  171. package/dist/esm/signal/group/SenderKeyChain.js +28 -23
  172. package/dist/esm/signal/group/SenderKeyCodec.js +5 -6
  173. package/dist/esm/signal/group/SenderKeyManager.js +144 -115
  174. package/dist/esm/signal/index.js +2 -0
  175. package/dist/esm/signal/registration/keygen.js +6 -2
  176. package/dist/esm/signal/registration/utils.js +1 -0
  177. package/dist/esm/signal/session/SignalProtocol.js +164 -53
  178. package/dist/esm/signal/session/SignalRatchet.js +24 -15
  179. package/dist/esm/signal/session/SignalSession.js +14 -9
  180. package/dist/esm/signal/session/resolver.js +221 -0
  181. package/dist/esm/store/contracts/privacy-token.store.js +1 -0
  182. package/dist/esm/store/createStore.js +100 -188
  183. package/dist/esm/store/index.js +1 -10
  184. package/dist/esm/store/locks/appstate.lock.js +26 -0
  185. package/dist/esm/store/locks/auth.lock.js +15 -0
  186. package/dist/esm/store/locks/contact.lock.js +20 -0
  187. package/dist/esm/store/locks/device-list.lock.js +20 -0
  188. package/dist/esm/store/locks/message.lock.js +21 -0
  189. package/dist/esm/store/locks/participants.lock.js +20 -0
  190. package/dist/esm/store/locks/privacy-token.lock.js +18 -0
  191. package/dist/esm/store/locks/retry.lock.js +29 -0
  192. package/dist/esm/store/locks/sender-key.lock.js +52 -0
  193. package/dist/esm/store/locks/signal.lock.js +63 -0
  194. package/dist/esm/store/locks/thread.lock.js +21 -0
  195. package/dist/esm/store/noop.store.js +4 -7
  196. package/dist/esm/store/providers/memory/appstate.store.js +38 -16
  197. package/dist/esm/store/providers/memory/contact.store.js +5 -0
  198. package/dist/esm/store/providers/memory/device-list.store.js +12 -34
  199. package/dist/esm/store/providers/memory/message.store.js +11 -5
  200. package/dist/esm/store/providers/memory/participants.store.js +1 -8
  201. package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
  202. package/dist/esm/store/providers/memory/retry.store.js +77 -2
  203. package/dist/esm/store/providers/memory/sender-key.store.js +11 -8
  204. package/dist/esm/store/providers/memory/signal.store.js +47 -18
  205. package/dist/esm/store/providers/memory/thread.store.js +5 -0
  206. package/dist/esm/transport/WaComms.js +28 -24
  207. package/dist/esm/transport/WaWebSocket.js +115 -18
  208. package/dist/esm/transport/binary/constants.js +0 -30
  209. package/dist/esm/transport/binary/decoder.js +8 -8
  210. package/dist/esm/transport/binary/encoder.js +10 -9
  211. package/dist/esm/transport/binary/index.js +0 -1
  212. package/dist/esm/transport/index.js +1 -0
  213. package/dist/esm/transport/keepalive/WaKeepAlive.js +2 -8
  214. package/dist/esm/transport/node/WaNodeOrchestrator.js +25 -21
  215. package/dist/esm/transport/node/WaNodeTransport.js +0 -3
  216. package/dist/esm/transport/node/builders/{accountSync.js → account-sync.js} +16 -36
  217. package/dist/esm/transport/node/builders/business.js +129 -0
  218. package/dist/esm/transport/node/builders/global.js +370 -0
  219. package/dist/esm/transport/node/builders/index.js +7 -3
  220. package/dist/esm/transport/node/builders/message.js +63 -230
  221. package/dist/esm/transport/node/builders/pairing.js +2 -27
  222. package/dist/esm/transport/node/builders/privacy-token.js +41 -0
  223. package/dist/esm/transport/node/builders/privacy.js +48 -0
  224. package/dist/esm/transport/node/builders/profile.js +70 -0
  225. package/dist/esm/transport/node/builders/retry.js +10 -22
  226. package/dist/esm/transport/node/builders/usync.js +45 -0
  227. package/dist/esm/transport/node/helpers.js +125 -5
  228. package/dist/esm/transport/node/usync.js +5 -0
  229. package/dist/esm/transport/node/xml.js +35 -14
  230. package/dist/esm/transport/noise/WaClientPayload.js +10 -10
  231. package/dist/esm/transport/noise/WaFrameCodec.js +48 -33
  232. package/dist/esm/transport/noise/WaNoiseCert.js +4 -7
  233. package/dist/esm/transport/noise/WaNoiseSession.js +77 -29
  234. package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
  235. package/dist/esm/transport/proxy.js +27 -0
  236. package/dist/esm/transport/stream/parse.js +17 -48
  237. package/dist/esm/util/bytes.js +67 -45
  238. package/dist/esm/util/coercion.js +6 -14
  239. package/dist/esm/util/index.js +5 -0
  240. package/dist/esm/util/primitives.js +40 -14
  241. package/dist/index.js +7 -1
  242. package/dist/infra/log/ConsoleLogger.js +18 -17
  243. package/dist/infra/log/PinoLogger.js +15 -9
  244. package/dist/infra/log/types.js +12 -0
  245. package/dist/infra/perf/BackgroundQueue.js +482 -0
  246. package/dist/infra/perf/BoundedTaskQueue.js +16 -18
  247. package/dist/infra/perf/PromiseDedup.js +24 -0
  248. package/dist/infra/perf/SharedExclusiveGate.js +113 -0
  249. package/dist/infra/perf/StoreLock.js +81 -0
  250. package/dist/media/WaMediaCrypto.js +95 -15
  251. package/dist/media/WaMediaTransferClient.js +284 -91
  252. package/dist/media/conn.js +10 -6
  253. package/dist/media/constants.js +6 -2
  254. package/dist/message/WaMessageClient.js +31 -33
  255. package/dist/message/ack.js +6 -6
  256. package/dist/message/addon-crypto.js +65 -0
  257. package/dist/message/content.js +198 -9
  258. package/dist/message/icdc.js +81 -0
  259. package/dist/message/incoming.js +127 -120
  260. package/dist/message/index.js +2 -0
  261. package/dist/message/phash.js +3 -1
  262. package/dist/message/reporting-token.js +429 -0
  263. package/dist/message/use-case-secret.js +55 -0
  264. package/dist/protocol/appstate.js +28 -1
  265. package/dist/protocol/browser.js +10 -18
  266. package/dist/protocol/constants.js +26 -1
  267. package/dist/protocol/defaults.js +6 -0
  268. package/dist/protocol/index.js +23 -42
  269. package/dist/protocol/jid.js +140 -52
  270. package/dist/protocol/media.js +3 -3
  271. package/dist/protocol/message.js +62 -2
  272. package/dist/protocol/nodes.js +4 -0
  273. package/dist/protocol/notification.js +3 -1
  274. package/dist/protocol/privacy-token.js +20 -0
  275. package/dist/protocol/privacy.js +58 -0
  276. package/dist/protocol/stream.js +27 -2
  277. package/dist/protocol/usync.js +14 -0
  278. package/dist/retry/codec.js +220 -0
  279. package/dist/retry/constants.js +1 -1
  280. package/dist/retry/index.js +7 -5
  281. package/dist/retry/parse.js +88 -85
  282. package/dist/retry/replay.js +52 -49
  283. package/dist/retry/tracker.js +97 -0
  284. package/dist/signal/api/SignalDeviceSyncApi.js +273 -89
  285. package/dist/signal/api/SignalDigestSyncApi.js +17 -8
  286. package/dist/signal/api/SignalIdentitySyncApi.js +66 -36
  287. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +82 -63
  288. package/dist/signal/api/SignalRotateKeyApi.js +4 -2
  289. package/dist/signal/api/SignalSessionSyncApi.js +36 -34
  290. package/dist/signal/api/result-map.js +13 -0
  291. package/dist/signal/constants.js +1 -5
  292. package/dist/signal/crypto/WaAdvSignature.js +11 -7
  293. package/dist/signal/{store/sqlite.js → encoding.js} +94 -61
  294. package/dist/signal/group/SenderKeyChain.js +27 -22
  295. package/dist/signal/group/SenderKeyCodec.js +5 -6
  296. package/dist/signal/group/SenderKeyManager.js +144 -115
  297. package/dist/signal/index.js +15 -1
  298. package/dist/signal/registration/keygen.js +6 -2
  299. package/dist/signal/registration/utils.js +1 -0
  300. package/dist/signal/session/SignalProtocol.js +164 -53
  301. package/dist/signal/session/SignalRatchet.js +24 -15
  302. package/dist/signal/session/SignalSession.js +14 -9
  303. package/dist/signal/session/resolver.js +224 -0
  304. package/dist/store/contracts/privacy-token.store.js +2 -0
  305. package/dist/store/createStore.js +100 -188
  306. package/dist/store/index.js +15 -33
  307. package/dist/store/locks/appstate.lock.js +29 -0
  308. package/dist/store/locks/auth.lock.js +18 -0
  309. package/dist/store/locks/contact.lock.js +23 -0
  310. package/dist/store/locks/device-list.lock.js +23 -0
  311. package/dist/store/locks/message.lock.js +24 -0
  312. package/dist/store/locks/participants.lock.js +23 -0
  313. package/dist/store/locks/privacy-token.lock.js +21 -0
  314. package/dist/store/locks/retry.lock.js +32 -0
  315. package/dist/store/locks/sender-key.lock.js +55 -0
  316. package/dist/store/locks/signal.lock.js +66 -0
  317. package/dist/store/locks/thread.lock.js +24 -0
  318. package/dist/store/noop.store.js +4 -7
  319. package/dist/store/providers/memory/appstate.store.js +36 -14
  320. package/dist/store/providers/memory/contact.store.js +5 -0
  321. package/dist/store/providers/memory/device-list.store.js +12 -34
  322. package/dist/store/providers/memory/message.store.js +11 -5
  323. package/dist/store/providers/memory/participants.store.js +1 -8
  324. package/dist/store/providers/memory/privacy-token.store.js +47 -0
  325. package/dist/store/providers/memory/retry.store.js +77 -2
  326. package/dist/store/providers/memory/sender-key.store.js +14 -11
  327. package/dist/store/providers/memory/signal.store.js +54 -25
  328. package/dist/store/providers/memory/thread.store.js +5 -0
  329. package/dist/transport/WaComms.js +30 -26
  330. package/dist/transport/WaWebSocket.js +148 -18
  331. package/dist/transport/binary/constants.js +1 -31
  332. package/dist/transport/binary/decoder.js +8 -8
  333. package/dist/transport/binary/encoder.js +10 -9
  334. package/dist/transport/binary/index.js +0 -4
  335. package/dist/transport/index.js +7 -1
  336. package/dist/transport/keepalive/WaKeepAlive.js +1 -7
  337. package/dist/transport/node/WaNodeOrchestrator.js +25 -21
  338. package/dist/transport/node/WaNodeTransport.js +0 -3
  339. package/dist/transport/node/builders/{accountSync.js → account-sync.js} +15 -35
  340. package/dist/transport/node/builders/business.js +137 -0
  341. package/dist/transport/node/builders/global.js +375 -0
  342. package/dist/transport/node/builders/index.js +29 -17
  343. package/dist/transport/node/builders/message.js +64 -236
  344. package/dist/transport/node/builders/pairing.js +2 -29
  345. package/dist/transport/node/builders/privacy-token.js +46 -0
  346. package/dist/transport/node/builders/privacy.js +55 -0
  347. package/dist/transport/node/builders/profile.js +78 -0
  348. package/dist/transport/node/builders/retry.js +9 -21
  349. package/dist/transport/node/builders/usync.js +49 -0
  350. package/dist/transport/node/helpers.js +131 -4
  351. package/dist/transport/node/usync.js +8 -0
  352. package/dist/transport/node/xml.js +35 -14
  353. package/dist/transport/noise/WaClientPayload.js +13 -13
  354. package/dist/transport/noise/WaFrameCodec.js +47 -32
  355. package/dist/transport/noise/WaNoiseCert.js +5 -8
  356. package/dist/transport/noise/WaNoiseSession.js +77 -29
  357. package/dist/transport/noise/WaNoiseSocket.js +8 -4
  358. package/dist/transport/proxy.js +34 -0
  359. package/dist/transport/stream/parse.js +20 -52
  360. package/dist/types/appstate/WaAppStateCrypto.d.ts +0 -1
  361. package/dist/types/appstate/WaAppStateSyncClient.d.ts +5 -2
  362. package/dist/types/appstate/constants.d.ts +1 -0
  363. package/dist/types/appstate/encoding.d.ts +7 -0
  364. package/dist/types/appstate/index.d.ts +3 -3
  365. package/dist/types/appstate/utils.d.ts +0 -3
  366. package/dist/types/auth/WaAuthClient.d.ts +10 -12
  367. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +1 -1
  368. package/dist/types/auth/index.d.ts +0 -4
  369. package/dist/types/auth/pairing/WaQrFlow.d.ts +1 -1
  370. package/dist/types/auth/types.d.ts +7 -9
  371. package/dist/types/client/WaClient.d.ts +42 -25
  372. package/dist/types/client/WaClientFactory.d.ts +33 -26
  373. package/dist/types/client/connection/WaConnectionManager.d.ts +66 -0
  374. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +14 -0
  375. package/dist/types/client/connection/WaReceiptQueue.d.ts +13 -0
  376. package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +46 -0
  377. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
  378. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +3 -2
  379. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +29 -38
  380. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -0
  381. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
  382. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +36 -0
  383. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +8 -0
  384. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
  385. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +45 -0
  386. package/dist/types/client/dirty.d.ts +1 -0
  387. package/dist/types/client/events/devices.d.ts +20 -0
  388. package/dist/types/client/events/group.d.ts +2 -1
  389. package/dist/types/client/events/identity.d.ts +9 -0
  390. package/dist/types/client/events/privacy-token.d.ts +7 -0
  391. package/dist/types/client/history-sync.d.ts +9 -6
  392. package/dist/types/client/incoming.d.ts +3 -1
  393. package/dist/types/client/index.d.ts +1 -1
  394. package/dist/types/client/mailbox.d.ts +3 -5
  395. package/dist/types/client/messages.d.ts +1 -2
  396. package/dist/types/client/messaging/fanout.d.ts +14 -0
  397. package/dist/types/client/messaging/key-protocol.d.ts +18 -0
  398. package/dist/types/client/messaging/participants.d.ts +13 -0
  399. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
  400. package/dist/types/client/tokens/cs-token.d.ts +10 -0
  401. package/dist/types/client/tokens/tc-token.d.ts +5 -0
  402. package/dist/types/client/types.d.ts +75 -4
  403. package/dist/types/crypto/core/hkdf.d.ts +0 -6
  404. package/dist/types/crypto/core/index.d.ts +2 -3
  405. package/dist/types/crypto/core/nonce.d.ts +2 -0
  406. package/dist/types/crypto/core/primitives.d.ts +0 -1
  407. package/dist/types/crypto/core/random.d.ts +2 -7
  408. package/dist/types/crypto/index.d.ts +0 -1
  409. package/dist/types/crypto/math/constants.d.ts +4 -2
  410. package/dist/types/crypto/math/fe.d.ts +30 -0
  411. package/dist/types/crypto/math/mod.d.ts +0 -2
  412. package/dist/types/crypto/math/types.d.ts +11 -4
  413. package/dist/types/index.d.ts +5 -3
  414. package/dist/types/infra/log/ConsoleLogger.d.ts +2 -1
  415. package/dist/types/infra/log/PinoLogger.d.ts +1 -1
  416. package/dist/types/infra/log/types.d.ts +1 -0
  417. package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
  418. package/dist/types/infra/perf/BoundedTaskQueue.d.ts +1 -1
  419. package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
  420. package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
  421. package/dist/types/infra/perf/StoreLock.d.ts +10 -0
  422. package/dist/types/media/WaMediaCrypto.d.ts +3 -2
  423. package/dist/types/media/WaMediaTransferClient.d.ts +16 -15
  424. package/dist/types/media/constants.d.ts +1 -1
  425. package/dist/types/media/index.d.ts +1 -1
  426. package/dist/types/media/types.d.ts +15 -2
  427. package/dist/types/message/addon-crypto.d.ts +25 -0
  428. package/dist/types/message/content.d.ts +8 -0
  429. package/dist/types/message/icdc.d.ts +13 -0
  430. package/dist/types/message/index.d.ts +2 -0
  431. package/dist/types/message/reporting-token.d.ts +18 -0
  432. package/dist/types/message/types.d.ts +45 -6
  433. package/dist/types/message/use-case-secret.d.ts +20 -0
  434. package/dist/types/protocol/appstate.d.ts +47 -0
  435. package/dist/types/protocol/constants.d.ts +8 -3
  436. package/dist/types/protocol/defaults.d.ts +6 -0
  437. package/dist/types/protocol/index.d.ts +2 -11
  438. package/dist/types/protocol/jid.d.ts +22 -5
  439. package/dist/types/protocol/message.d.ts +60 -0
  440. package/dist/types/protocol/nodes.d.ts +4 -0
  441. package/dist/types/protocol/notification.d.ts +2 -0
  442. package/dist/types/protocol/privacy-token.d.ts +17 -0
  443. package/dist/types/protocol/privacy.d.ts +75 -0
  444. package/dist/types/protocol/stream.d.ts +30 -0
  445. package/dist/types/protocol/usync.d.ts +11 -0
  446. package/dist/types/retry/codec.d.ts +3 -0
  447. package/dist/types/retry/index.d.ts +4 -3
  448. package/dist/types/retry/parse.d.ts +5 -2
  449. package/dist/types/retry/replay.d.ts +0 -4
  450. package/dist/types/retry/tracker.d.ts +20 -0
  451. package/dist/types/retry/types.d.ts +10 -4
  452. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +15 -2
  453. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +6 -0
  454. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +2 -0
  455. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
  456. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
  457. package/dist/types/signal/api/result-map.d.ts +1 -0
  458. package/dist/types/signal/constants.d.ts +0 -3
  459. package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +3 -3
  460. package/dist/types/signal/group/SenderKeyCodec.d.ts +4 -6
  461. package/dist/types/signal/group/SenderKeyManager.d.ts +10 -5
  462. package/dist/types/signal/index.d.ts +3 -0
  463. package/dist/types/signal/session/SignalProtocol.d.ts +19 -4
  464. package/dist/types/signal/session/resolver.d.ts +22 -0
  465. package/dist/types/store/contracts/appstate.store.d.ts +4 -1
  466. package/dist/types/store/contracts/contact.store.d.ts +1 -0
  467. package/dist/types/store/contracts/device-list.store.d.ts +0 -3
  468. package/dist/types/store/contracts/message.store.d.ts +1 -0
  469. package/dist/types/store/contracts/participants.store.d.ts +0 -1
  470. package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
  471. package/dist/types/store/contracts/retry.store.d.ts +7 -0
  472. package/dist/types/store/contracts/sender-key.store.d.ts +0 -1
  473. package/dist/types/store/contracts/signal.store.d.ts +13 -0
  474. package/dist/types/store/contracts/thread.store.d.ts +1 -0
  475. package/dist/types/store/createStore.d.ts +1 -1
  476. package/dist/types/store/index.d.ts +5 -13
  477. package/dist/types/store/locks/appstate.lock.d.ts +3 -0
  478. package/dist/types/store/locks/auth.lock.d.ts +3 -0
  479. package/dist/types/store/locks/contact.lock.d.ts +3 -0
  480. package/dist/types/store/locks/device-list.lock.d.ts +2 -0
  481. package/dist/types/store/locks/message.lock.d.ts +3 -0
  482. package/dist/types/store/locks/participants.lock.d.ts +2 -0
  483. package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
  484. package/dist/types/store/locks/retry.lock.d.ts +2 -0
  485. package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
  486. package/dist/types/store/locks/signal.lock.d.ts +3 -0
  487. package/dist/types/store/locks/thread.lock.d.ts +3 -0
  488. package/dist/types/store/providers/memory/appstate.store.d.ts +3 -1
  489. package/dist/types/store/providers/memory/contact.store.d.ts +1 -0
  490. package/dist/types/store/providers/memory/device-list.store.d.ts +0 -3
  491. package/dist/types/store/providers/memory/message.store.d.ts +1 -0
  492. package/dist/types/store/providers/memory/participants.store.d.ts +0 -1
  493. package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
  494. package/dist/types/store/providers/memory/retry.store.d.ts +8 -0
  495. package/dist/types/store/providers/memory/sender-key.store.d.ts +0 -1
  496. package/dist/types/store/providers/memory/signal.store.d.ts +8 -1
  497. package/dist/types/store/providers/memory/thread.store.d.ts +1 -0
  498. package/dist/types/store/types.d.ts +49 -58
  499. package/dist/types/transport/WaWebSocket.d.ts +3 -1
  500. package/dist/types/transport/binary/constants.d.ts +0 -30
  501. package/dist/types/transport/binary/index.d.ts +0 -1
  502. package/dist/types/transport/index.d.ts +2 -1
  503. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +0 -1
  504. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +3 -4
  505. package/dist/types/transport/node/WaNodeTransport.d.ts +0 -9
  506. package/dist/types/transport/node/builders/business.d.ts +29 -0
  507. package/dist/types/transport/node/builders/global.d.ts +102 -0
  508. package/dist/types/transport/node/builders/group.d.ts +4 -6
  509. package/dist/types/transport/node/builders/index.d.ts +7 -3
  510. package/dist/types/transport/node/builders/message.d.ts +20 -30
  511. package/dist/types/transport/node/builders/pairing.d.ts +0 -2
  512. package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
  513. package/dist/types/transport/node/builders/privacy.d.ts +7 -0
  514. package/dist/types/transport/node/builders/profile.d.ts +8 -0
  515. package/dist/types/transport/node/builders/retry.d.ts +2 -5
  516. package/dist/types/transport/node/builders/usync.d.ts +21 -0
  517. package/dist/types/transport/node/helpers.d.ts +13 -0
  518. package/dist/types/transport/node/usync.d.ts +2 -0
  519. package/dist/types/transport/noise/WaFrameCodec.d.ts +3 -0
  520. package/dist/types/transport/noise/WaNoiseSession.d.ts +4 -2
  521. package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
  522. package/dist/types/transport/proxy.d.ts +6 -0
  523. package/dist/types/transport/stream/parse.d.ts +0 -1
  524. package/dist/types/transport/types.d.ts +18 -1
  525. package/dist/types/util/bytes.d.ts +5 -0
  526. package/dist/types/util/index.d.ts +5 -0
  527. package/dist/types/util/primitives.d.ts +2 -0
  528. package/dist/util/bytes.js +72 -46
  529. package/dist/util/coercion.js +6 -14
  530. package/dist/util/index.js +23 -0
  531. package/dist/util/primitives.js +42 -14
  532. package/package.json +52 -9
  533. package/proto/index.js +1 -1
  534. package/dist/crypto/core/constants.js +0 -4
  535. package/dist/crypto/core/encoding.js +0 -29
  536. package/dist/esm/crypto/core/constants.js +0 -1
  537. package/dist/esm/crypto/core/encoding.js +0 -25
  538. package/dist/esm/retry/outbound.js +0 -83
  539. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
  540. package/dist/esm/store/providers/sqlite/appstate.store.js +0 -169
  541. package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
  542. package/dist/esm/store/providers/sqlite/connection.js +0 -240
  543. package/dist/esm/store/providers/sqlite/contact.store.js +0 -61
  544. package/dist/esm/store/providers/sqlite/device-list.store.js +0 -155
  545. package/dist/esm/store/providers/sqlite/message.store.js +0 -119
  546. package/dist/esm/store/providers/sqlite/migrations.js +0 -347
  547. package/dist/esm/store/providers/sqlite/participants.store.js +0 -85
  548. package/dist/esm/store/providers/sqlite/retry.store.js +0 -144
  549. package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -203
  550. package/dist/esm/store/providers/sqlite/signal.store.js +0 -353
  551. package/dist/esm/store/providers/sqlite/thread.store.js +0 -72
  552. package/dist/esm/util/base64.js +0 -18
  553. package/dist/esm/util/signal-address.js +0 -5
  554. package/dist/retry/outbound.js +0 -88
  555. package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
  556. package/dist/store/providers/sqlite/appstate.store.js +0 -173
  557. package/dist/store/providers/sqlite/auth.store.js +0 -180
  558. package/dist/store/providers/sqlite/connection.js +0 -276
  559. package/dist/store/providers/sqlite/contact.store.js +0 -65
  560. package/dist/store/providers/sqlite/device-list.store.js +0 -159
  561. package/dist/store/providers/sqlite/message.store.js +0 -123
  562. package/dist/store/providers/sqlite/migrations.js +0 -350
  563. package/dist/store/providers/sqlite/participants.store.js +0 -89
  564. package/dist/store/providers/sqlite/retry.store.js +0 -148
  565. package/dist/store/providers/sqlite/sender-key.store.js +0 -207
  566. package/dist/store/providers/sqlite/signal.store.js +0 -357
  567. package/dist/store/providers/sqlite/thread.store.js +0 -76
  568. package/dist/types/appstate/store/sqlite.d.ts +0 -21
  569. package/dist/types/crypto/core/constants.d.ts +0 -1
  570. package/dist/types/crypto/core/encoding.d.ts +0 -11
  571. package/dist/types/retry/outbound.d.ts +0 -4
  572. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
  573. package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -15
  574. package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
  575. package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
  576. package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -10
  577. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -18
  578. package/dist/types/store/providers/sqlite/message.store.d.ts +0 -11
  579. package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
  580. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -13
  581. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -16
  582. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -25
  583. package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -46
  584. package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -11
  585. package/dist/types/util/base64.d.ts +0 -4
  586. package/dist/types/util/signal-address.d.ts +0 -2
  587. package/dist/util/base64.js +0 -24
  588. package/dist/util/signal-address.js +0 -8
  589. /package/dist/types/transport/node/builders/{accountSync.d.ts → account-sync.d.ts} +0 -0
@@ -1,15 +1,118 @@
1
- import { base64ToBytes, TEXT_ENCODER } from '../../util/bytes.js';
1
+ import { randomFillAsync } from '../../crypto/index.js';
2
+ import { base64ToBytesChecked, TEXT_DECODER, TEXT_ENCODER } from '../../util/bytes.js';
3
+ const EMPTY_NODE_CHILDREN = Object.freeze([]);
4
+ const EMPTY_NODE_TAGS = Object.freeze([]);
5
+ const EMPTY_NODE_VALUES = Object.freeze([]);
6
+ const NODE_ID_PREFIX_SEED = new Uint8Array(4);
2
7
  export function getNodeChildren(node) {
3
- return Array.isArray(node.content) ? node.content : [];
8
+ return Array.isArray(node.content) ? node.content : EMPTY_NODE_CHILDREN;
4
9
  }
5
10
  export function findNodeChild(node, tag) {
6
- return getNodeChildren(node).find((child) => child.tag === tag);
11
+ const content = node.content;
12
+ if (!Array.isArray(content))
13
+ return undefined;
14
+ for (let i = 0; i < content.length; i++) {
15
+ if (content[i].tag === tag)
16
+ return content[i];
17
+ }
7
18
  }
8
19
  export function getFirstNodeChild(node) {
9
20
  return getNodeChildren(node)[0];
10
21
  }
11
22
  export function getNodeChildrenByTag(node, tag) {
12
- return getNodeChildren(node).filter((child) => child.tag === tag);
23
+ const content = node.content;
24
+ if (!Array.isArray(content))
25
+ return EMPTY_NODE_CHILDREN;
26
+ let tagged = null;
27
+ for (let i = 0; i < content.length; i++) {
28
+ if (content[i].tag !== tag)
29
+ continue;
30
+ if (!tagged)
31
+ tagged = [];
32
+ tagged.push(content[i]);
33
+ }
34
+ return tagged ?? EMPTY_NODE_CHILDREN;
35
+ }
36
+ export function getNodeChildrenByTagFromChildren(node, tag) {
37
+ let tagged = null;
38
+ const content = node.content;
39
+ if (!Array.isArray(content))
40
+ return EMPTY_NODE_CHILDREN;
41
+ for (let i = 0; i < content.length; i += 1) {
42
+ const nested = content[i].content;
43
+ if (!Array.isArray(nested))
44
+ continue;
45
+ for (let j = 0; j < nested.length; j += 1) {
46
+ if (nested[j].tag !== tag)
47
+ continue;
48
+ if (!tagged)
49
+ tagged = [];
50
+ tagged.push(nested[j]);
51
+ }
52
+ }
53
+ return tagged ?? EMPTY_NODE_CHILDREN;
54
+ }
55
+ export function getNodeChildrenTags(node) {
56
+ const content = node.content;
57
+ if (!Array.isArray(content) || content.length === 0)
58
+ return EMPTY_NODE_TAGS;
59
+ const tags = new Array(content.length);
60
+ for (let i = 0; i < content.length; i += 1) {
61
+ tags[i] = content[i].tag;
62
+ }
63
+ return tags;
64
+ }
65
+ export function getNodeChildrenNonEmptyAttrValuesByTag(node, tag, attr) {
66
+ let values = null;
67
+ const children = getNodeChildren(node);
68
+ for (let index = 0; index < children.length; index += 1) {
69
+ const child = children[index];
70
+ if (child.tag !== tag) {
71
+ continue;
72
+ }
73
+ const value = child.attrs[attr];
74
+ if (!value) {
75
+ continue;
76
+ }
77
+ if (!values) {
78
+ values = [];
79
+ }
80
+ values.push(value);
81
+ }
82
+ return values ?? EMPTY_NODE_VALUES;
83
+ }
84
+ export function getNodeChildrenNonEmptyUtf8ByTag(node, tag, field) {
85
+ let values = null;
86
+ const children = getNodeChildren(node);
87
+ for (let index = 0; index < children.length; index += 1) {
88
+ const child = children[index];
89
+ if (child.tag !== tag) {
90
+ continue;
91
+ }
92
+ const raw = child.content;
93
+ if (raw === null || raw === undefined) {
94
+ continue;
95
+ }
96
+ if (raw instanceof Uint8Array && raw.length === 0) {
97
+ continue;
98
+ }
99
+ const value = TEXT_DECODER.decode(decodeNodeContentUtf8OrBytes(raw, field));
100
+ if (value.length === 0) {
101
+ continue;
102
+ }
103
+ if (!values) {
104
+ values = [];
105
+ }
106
+ values.push(value);
107
+ }
108
+ return values ?? EMPTY_NODE_VALUES;
109
+ }
110
+ export function findNodeChildrenByTags(node, tags) {
111
+ const out = new Array(tags.length);
112
+ for (let index = 0; index < tags.length; index += 1) {
113
+ out[index] = findNodeChild(node, tags[index]);
114
+ }
115
+ return out;
13
116
  }
14
117
  export function hasNodeChild(node, tag) {
15
118
  return findNodeChild(node, tag) !== undefined;
@@ -28,10 +131,27 @@ export function decodeNodeContentBase64OrBytes(value, field) {
28
131
  throw new Error(`missing binary node content for ${field}`);
29
132
  }
30
133
  if (typeof value === 'string') {
31
- return base64ToBytes(value);
134
+ return base64ToBytesChecked(value, field);
32
135
  }
33
136
  if (value instanceof Uint8Array) {
34
137
  return value;
35
138
  }
36
139
  throw new Error(`missing binary node content for ${field}`);
37
140
  }
141
+ export function formatNodeIdPrefixFromSeed(seed) {
142
+ const left = ((seed[0] << 8) | seed[1]) >>> 0;
143
+ const right = ((seed[2] << 8) | seed[3]) >>> 0;
144
+ return `${left}.${right}-`;
145
+ }
146
+ export async function createNodeIdGenerator() {
147
+ await randomFillAsync(NODE_ID_PREFIX_SEED);
148
+ const prefix = formatNodeIdPrefixFromSeed(NODE_ID_PREFIX_SEED);
149
+ let counter = 0;
150
+ return {
151
+ prefix,
152
+ next() {
153
+ counter += 1;
154
+ return `${prefix}${counter}`;
155
+ }
156
+ };
157
+ }
@@ -0,0 +1,5 @@
1
+ import { createNodeIdGenerator } from './helpers.js';
2
+ export function createUsyncSidGenerator() {
3
+ const generatorPromise = createNodeIdGenerator();
4
+ return async () => (await generatorPromise).next();
5
+ }
@@ -1,23 +1,41 @@
1
1
  import { bytesToBase64 } from '../../util/bytes.js';
2
2
  const XML_INDENT = ' ';
3
3
  function escapeXml(value) {
4
- return value
5
- .replace(/&/g, '&amp;')
6
- .replace(/</g, '&lt;')
7
- .replace(/>/g, '&gt;')
8
- .replace(/"/g, '&quot;')
9
- .replace(/'/g, '&apos;');
10
- }
11
- function renderAttrs(attrs) {
12
- const entries = Object.entries(attrs);
13
- if (entries.length === 0) {
14
- return '';
4
+ let out = '';
5
+ let last = 0;
6
+ for (let i = 0; i < value.length; i++) {
7
+ let esc;
8
+ switch (value.charCodeAt(i)) {
9
+ case 38:
10
+ esc = '&amp;';
11
+ break;
12
+ case 60:
13
+ esc = '&lt;';
14
+ break;
15
+ case 62:
16
+ esc = '&gt;';
17
+ break;
18
+ case 34:
19
+ esc = '&quot;';
20
+ break;
21
+ case 39:
22
+ esc = '&apos;';
23
+ break;
24
+ }
25
+ if (esc) {
26
+ out += value.slice(last, i) + esc;
27
+ last = i + 1;
28
+ }
15
29
  }
16
- return entries.map(([key, value]) => ` ${key}='${escapeXml(value)}'`).join('');
30
+ return last === 0 ? value : out + value.slice(last);
17
31
  }
18
32
  function renderNode(node, depth) {
19
33
  const indent = XML_INDENT.repeat(depth);
20
- const attrs = renderAttrs(node.attrs);
34
+ const keys = Object.keys(node.attrs);
35
+ let attrs = '';
36
+ for (let i = 0; i < keys.length; i++) {
37
+ attrs += ` ${keys[i]}='${escapeXml(node.attrs[keys[i]])}'`;
38
+ }
21
39
  const content = node.content;
22
40
  if (content === undefined) {
23
41
  return `${indent}<${node.tag}${attrs}/>`;
@@ -31,7 +49,10 @@ function renderNode(node, depth) {
31
49
  if (content.length === 0) {
32
50
  return `${indent}<${node.tag}${attrs}/>`;
33
51
  }
34
- const children = content.map((child) => renderNode(child, depth + 1)).join('\n');
52
+ let children = renderNode(content[0], depth + 1);
53
+ for (let i = 1; i < content.length; i++) {
54
+ children += '\n' + renderNode(content[i], depth + 1);
55
+ }
35
56
  return `${indent}<${node.tag}${attrs}>\n${children}\n${indent}</${node.tag}>`;
36
57
  }
37
58
  export function formatBinaryNodeAsXml(node) {
@@ -1,7 +1,6 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { md5Bytes } from '../../crypto/core/primitives.js';
3
3
  import { proto } from '../../proto.js';
4
- import { KEY_TYPE_CURVE25519 } from '../../signal/constants.js';
5
4
  import { DEFAULT_VERSION_BASE } from '../noise/constants.js';
6
5
  import { intToBytes, toBytesView } from '../../util/bytes.js';
7
6
  function parseVersion(versionBase) {
@@ -60,8 +59,8 @@ function resolveDevicePropsPlatformType(deviceBrowser) {
60
59
  return proto.DeviceProps.PlatformType.UNKNOWN;
61
60
  }
62
61
  }
63
- function defaultUserAgent(versionBase, deviceOsDisplayName) {
64
- const { primary, secondary, tertiary } = parseVersion(versionBase);
62
+ function defaultUserAgent(versionBase, deviceOsDisplayName, version) {
63
+ const { primary, secondary, tertiary } = version ?? parseVersion(versionBase);
65
64
  const locale = resolveLocale();
66
65
  return {
67
66
  platform: proto.ClientPayload.UserAgent.Platform.WEB,
@@ -82,8 +81,8 @@ function defaultUserAgent(versionBase, deviceOsDisplayName) {
82
81
  localeCountryIso31661Alpha2: locale.lc
83
82
  };
84
83
  }
85
- function defaultDeviceProps(versionBase, config) {
86
- const { primary, secondary, tertiary } = parseVersion(versionBase);
84
+ function defaultDeviceProps(versionBase, config, version) {
85
+ const { primary, secondary, tertiary } = version ?? parseVersion(versionBase);
87
86
  return proto.DeviceProps.encode({
88
87
  os: config.deviceOsDisplayName ?? process.platform,
89
88
  version: {
@@ -105,7 +104,7 @@ function defaultDeviceProps(versionBase, config) {
105
104
  }
106
105
  }).finish();
107
106
  }
108
- function buildCommonPayload(config) {
107
+ function buildCommonPayload(config, version) {
109
108
  const versionBase = config.versionBase ?? DEFAULT_VERSION_BASE;
110
109
  const pull = config.pull ?? true;
111
110
  return {
@@ -113,7 +112,7 @@ function buildCommonPayload(config) {
113
112
  pull,
114
113
  connectType: proto.ClientPayload.ConnectType.WIFI_UNKNOWN,
115
114
  connectReason: proto.ClientPayload.ConnectReason.USER_ACTIVATED,
116
- userAgent: config.userAgent ?? defaultUserAgent(versionBase, config.deviceOsDisplayName),
115
+ userAgent: config.userAgent ?? defaultUserAgent(versionBase, config.deviceOsDisplayName, version),
117
116
  webInfo: config.webInfo ??
118
117
  {
119
118
  webSubPlatform: defaultWebSubPlatform()
@@ -142,14 +141,15 @@ export function buildRegistrationPayload(config) {
142
141
  throw new Error('registration payload requires a valid signedPreKeyId');
143
142
  }
144
143
  const versionBase = config.versionBase ?? DEFAULT_VERSION_BASE;
145
- const common = buildCommonPayload(config);
144
+ const version = parseVersion(versionBase);
145
+ const common = buildCommonPayload(config, version);
146
146
  const devicePairingData = {
147
147
  buildHash: config.buildHash ? toBytesView(config.buildHash) : md5Bytes(versionBase),
148
148
  deviceProps: config.deviceProps
149
149
  ? toBytesView(config.deviceProps)
150
- : defaultDeviceProps(versionBase, config),
150
+ : defaultDeviceProps(versionBase, config, version),
151
151
  eRegid: intToBytes(4, registrationId),
152
- eKeytype: intToBytes(1, KEY_TYPE_CURVE25519),
152
+ eKeytype: intToBytes(1, 5),
153
153
  eIdent: toBytesView(config.registrationInfo.identityKeyPair.pubKey),
154
154
  eSkeyId: intToBytes(3, signedPreKeyId),
155
155
  eSkeyVal: toBytesView(config.signedPreKey.keyPair.pubKey),
@@ -1,4 +1,4 @@
1
- import { concatBytes, EMPTY_BYTES, toBytesView } from '../../util/bytes.js';
1
+ import { EMPTY_BYTES, toBytesView } from '../../util/bytes.js';
2
2
  const WA_MAX_FRAME_LENGTH = (1 << 24) - 1;
3
3
  function frameLength(header) {
4
4
  return (header[0] << 16) | (header[1] << 8) | header[2];
@@ -15,6 +15,31 @@ export class WaFrameCodec {
15
15
  this.maxFrameLength = maxFrameLength;
16
16
  this.introSent = false;
17
17
  this.buffered = EMPTY_BYTES;
18
+ this.bufferedLength = 0;
19
+ }
20
+ assertFrameLength(length) {
21
+ if (length <= this.maxFrameLength) {
22
+ return;
23
+ }
24
+ throw new Error(`incoming frame is too large: ${length} bytes (max allowed: ${this.maxFrameLength})`);
25
+ }
26
+ appendBuffered(chunk) {
27
+ if (chunk.length === 0) {
28
+ return;
29
+ }
30
+ if (this.bufferedLength === 0) {
31
+ this.buffered = chunk;
32
+ }
33
+ else {
34
+ const nextLength = this.bufferedLength + chunk.length;
35
+ if (this.buffered.length < nextLength) {
36
+ const nextBuffered = new Uint8Array(Math.max(nextLength, this.bufferedLength * 2));
37
+ nextBuffered.set(this.buffered.subarray(0, this.bufferedLength));
38
+ this.buffered = nextBuffered;
39
+ }
40
+ this.buffered.set(chunk, this.bufferedLength);
41
+ }
42
+ this.bufferedLength += chunk.length;
18
43
  }
19
44
  encodeFrame(frame) {
20
45
  if (frame.length > this.maxFrameLength) {
@@ -45,67 +70,56 @@ export class WaFrameCodec {
45
70
  }
46
71
  const frames = [];
47
72
  let chunkOffset = 0;
48
- if (this.buffered.length > 0) {
49
- if (this.buffered.length < 3) {
50
- const missingHeaderBytes = 3 - this.buffered.length;
73
+ if (this.bufferedLength > 0) {
74
+ if (this.bufferedLength < 3) {
75
+ const missingHeaderBytes = 3 - this.bufferedLength;
51
76
  if (chunk.length < missingHeaderBytes) {
52
- this.buffered = concatBytes([this.buffered, chunk]);
77
+ this.appendBuffered(chunk);
53
78
  return frames;
54
79
  }
55
- const header = new Uint8Array(3);
56
- header.set(this.buffered, 0);
57
- header.set(chunk.subarray(0, missingHeaderBytes), this.buffered.length);
58
- const length = frameLength(header);
59
- if (length > this.maxFrameLength) {
60
- throw new Error(`incoming frame is too large: ${length} bytes (max allowed: ${this.maxFrameLength})`);
61
- }
80
+ this.appendBuffered(chunk.subarray(0, missingHeaderBytes));
81
+ const length = frameLength(this.buffered);
82
+ this.assertFrameLength(length);
62
83
  const remainingAfterHeader = chunk.length - missingHeaderBytes;
63
84
  if (remainingAfterHeader < length) {
64
- const nextBuffered = new Uint8Array(3 + remainingAfterHeader);
65
- nextBuffered.set(header, 0);
66
- nextBuffered.set(chunk.subarray(missingHeaderBytes), 3);
67
- this.buffered = nextBuffered;
85
+ this.appendBuffered(chunk.subarray(missingHeaderBytes));
68
86
  return frames;
69
87
  }
70
88
  frames.push(chunk.subarray(missingHeaderBytes, missingHeaderBytes + length));
71
89
  chunkOffset = missingHeaderBytes + length;
72
- this.buffered = EMPTY_BYTES;
73
90
  }
74
91
  else {
75
- const header = this.buffered.subarray(0, 3);
76
- const length = frameLength(header);
77
- if (length > this.maxFrameLength) {
78
- throw new Error(`incoming frame is too large: ${length} bytes (max allowed: ${this.maxFrameLength})`);
79
- }
80
- const bufferedPayloadLength = this.buffered.length - 3;
92
+ const length = frameLength(this.buffered);
93
+ this.assertFrameLength(length);
94
+ const bufferedPayloadLength = this.bufferedLength - 3;
81
95
  const missingPayloadBytes = length - bufferedPayloadLength;
82
96
  if (missingPayloadBytes > chunk.length) {
83
- this.buffered = concatBytes([this.buffered, chunk]);
97
+ this.appendBuffered(chunk);
84
98
  return frames;
85
99
  }
86
- if (bufferedPayloadLength === 0) {
100
+ if (missingPayloadBytes === 0) {
101
+ frames.push(this.buffered.subarray(3, 3 + length));
102
+ }
103
+ else if (bufferedPayloadLength === 0) {
87
104
  frames.push(chunk.subarray(0, missingPayloadBytes));
88
105
  }
89
106
  else {
90
107
  const frame = new Uint8Array(length);
91
- frame.set(this.buffered.subarray(3), 0);
92
- if (missingPayloadBytes > 0) {
93
- frame.set(chunk.subarray(0, missingPayloadBytes), bufferedPayloadLength);
94
- }
108
+ frame.set(this.buffered.subarray(3, this.bufferedLength));
109
+ frame.set(chunk.subarray(0, missingPayloadBytes), bufferedPayloadLength);
95
110
  frames.push(frame);
96
111
  }
97
112
  chunkOffset = missingPayloadBytes;
98
- this.buffered = EMPTY_BYTES;
99
113
  }
114
+ this.buffered = EMPTY_BYTES;
115
+ this.bufferedLength = 0;
100
116
  }
101
117
  const remainingChunk = chunk.subarray(chunkOffset);
102
118
  let offset = 0;
103
119
  while (remainingChunk.length - offset >= 3) {
104
120
  const header = remainingChunk.subarray(offset, offset + 3);
105
121
  const length = frameLength(header);
106
- if (length > this.maxFrameLength) {
107
- throw new Error(`incoming frame is too large: ${length} bytes (max allowed: ${this.maxFrameLength})`);
108
- }
122
+ this.assertFrameLength(length);
109
123
  if (remainingChunk.length - offset - 3 < length) {
110
124
  break;
111
125
  }
@@ -116,6 +130,7 @@ export class WaFrameCodec {
116
130
  }
117
131
  this.buffered =
118
132
  offset >= remainingChunk.length ? EMPTY_BYTES : remainingChunk.subarray(offset);
133
+ this.bufferedLength = this.buffered.length;
119
134
  return frames;
120
135
  }
121
136
  }
@@ -1,9 +1,8 @@
1
- import { ed25519VerifyRaw, toSerializedPubKey } from '../../crypto/index.js';
1
+ import { Ed25519, toSerializedPubKey } from '../../crypto/index.js';
2
2
  import { montgomeryToEdwardsPublic } from '../../crypto/curves/X25519.js';
3
3
  import { proto } from '../../proto.js';
4
4
  import { ROOT_CA_PUBLIC_KEY_HEX, ROOT_CA_SERIAL } from '../noise/constants.js';
5
- import { decodeProtoBytes } from '../../util/base64.js';
6
- import { hexToBytes, uint8Equal } from '../../util/bytes.js';
5
+ import { assertByteLength, decodeProtoBytes, hexToBytes, uint8Equal } from '../../util/bytes.js';
7
6
  import { toSafeNumber } from '../../util/primitives.js';
8
7
  async function verifySignalVariant(serializedPublicKey, message, signatureInput) {
9
8
  const publicKey = toSerializedPubKey(serializedPublicKey);
@@ -18,7 +17,7 @@ async function verifySignalVariant(serializedPublicKey, message, signatureInput)
18
17
  const signBit = lastByte & 0x80;
19
18
  signature[63] = lastByte & 0x7f;
20
19
  const edwardsPublicKey = montgomeryToEdwardsPublic(publicKey.subarray(1), signBit);
21
- return ed25519VerifyRaw(edwardsPublicKey, signature, message);
20
+ return Ed25519.verify(message, signature, edwardsPublicKey);
22
21
  }
23
22
  function parseNoiseCertificate(certificate) {
24
23
  if (!certificate) {
@@ -26,9 +25,7 @@ function parseNoiseCertificate(certificate) {
26
25
  }
27
26
  const detailsBytes = decodeProtoBytes(certificate.details, 'certificate.details');
28
27
  const signatureBytes = decodeProtoBytes(certificate.signature, 'certificate.signature');
29
- if (signatureBytes.length !== 64) {
30
- throw new Error('invalid certificate signature size');
31
- }
28
+ assertByteLength(signatureBytes, 64, 'invalid certificate signature size');
32
29
  const details = proto.CertChain.NoiseCertificate.Details.decode(detailsBytes);
33
30
  const serial = toSafeNumber(details.serial, 'certificate.serial');
34
31
  const issuerSerial = toSafeNumber(details.issuerSerial, 'certificate.issuerSerial');
@@ -1,6 +1,5 @@
1
1
  import { X25519 } from '../../crypto/index.js';
2
2
  import { ConsoleLogger } from '../../infra/log/ConsoleLogger.js';
3
- import { BoundedTaskQueue } from '../../infra/perf/BoundedTaskQueue.js';
4
3
  import { proto } from '../../proto.js';
5
4
  import { WA_DEFAULTS } from '../../protocol/constants.js';
6
5
  import { NOISE_IK_NAME, NOISE_XX_FALLBACK_NAME, NOISE_XX_NAME, WA_PROTO_HEADER } from '../noise/constants.js';
@@ -48,12 +47,11 @@ function buildRoutingInfoPrefix(routingInfo) {
48
47
  }
49
48
  export class WaNoiseSession {
50
49
  constructor(sendWire, logger = new ConsoleLogger('info')) {
51
- this.sendWire = sendWire;
52
- this.logger = logger;
53
- this.writeQueue = new BoundedTaskQueue(4096, 1);
54
- this.readQueue = new BoundedTaskQueue(4096, 1);
50
+ this.writeChain = Promise.resolve();
51
+ this.readChain = Promise.resolve();
55
52
  this.frameCodec = null;
56
53
  this.handshakeInbox = [];
54
+ this.handshakeInboxHead = 0;
57
55
  this.handshakeWaiter = null;
58
56
  this.handshakeRejecter = null;
59
57
  this.pendingDecryptedFrames = [];
@@ -61,6 +59,8 @@ export class WaNoiseSession {
61
59
  this.noiseSocket = null;
62
60
  this.serverStaticKey = null;
63
61
  this.handshakeFrameTimeoutMs = WA_DEFAULTS.CONNECT_TIMEOUT_MS;
62
+ this.sendWire = sendWire;
63
+ this.logger = logger;
64
64
  }
65
65
  async start(config) {
66
66
  this.reset();
@@ -92,12 +92,24 @@ export class WaNoiseSession {
92
92
  await this.decodeBufferedPostHandshakeFrames();
93
93
  this.logger.info('noise session established via full handshake');
94
94
  }
95
- async encryptFrame(frame) {
96
- if (!this.noiseSocket || !this.frameCodec) {
97
- throw new Error('noise session is not established');
95
+ encryptFrame(frame) {
96
+ const socket = this.noiseSocket;
97
+ const codec = this.frameCodec;
98
+ if (!socket || !codec) {
99
+ return Promise.reject(new Error('noise session is not established'));
98
100
  }
99
- const encrypted = await this.writeQueue.enqueue(() => this.noiseSocket.encrypt(frame));
100
- return this.frameCodec.encodeFrame(encrypted);
101
+ let encryptPromise;
102
+ try {
103
+ encryptPromise = socket.encrypt(socket.reserveWriteNonce(), frame);
104
+ }
105
+ catch (error) {
106
+ return Promise.reject(error);
107
+ }
108
+ const result = this.writeChain
109
+ .then(() => encryptPromise)
110
+ .then((encrypted) => codec.encodeFrame(encrypted));
111
+ this.writeChain = result.then(() => { }, () => { });
112
+ return result;
101
113
  }
102
114
  async pushWireChunk(chunk) {
103
115
  const codec = this.frameCodec;
@@ -106,7 +118,9 @@ export class WaNoiseSession {
106
118
  }
107
119
  const out = [];
108
120
  if (this.pendingDecryptedFrames.length > 0) {
109
- out.push(...this.pendingDecryptedFrames);
121
+ for (let i = 0; i < this.pendingDecryptedFrames.length; i += 1) {
122
+ out.push(this.pendingDecryptedFrames[i]);
123
+ }
110
124
  this.pendingDecryptedFrames = [];
111
125
  }
112
126
  const frames = codec.pushWireChunk(chunk);
@@ -124,9 +138,15 @@ export class WaNoiseSession {
124
138
  }
125
139
  return out;
126
140
  }
127
- for (const frame of frames) {
128
- const decrypted = await this.readQueue.enqueue(() => this.noiseSocket.decrypt(frame));
129
- out.push(decrypted);
141
+ if (frames.length > 0) {
142
+ const decryptBatch = this.decryptFramesBatch(this.noiseSocket, frames);
143
+ this.readChain = this.readChain
144
+ .then(() => decryptBatch)
145
+ .then(() => { }, () => { });
146
+ const decrypted = await decryptBatch;
147
+ for (let i = 0; i < decrypted.length; i++) {
148
+ out.push(decrypted[i]);
149
+ }
130
150
  }
131
151
  return out;
132
152
  }
@@ -141,21 +161,30 @@ export class WaNoiseSession {
141
161
  rejecter(closeError);
142
162
  }
143
163
  }
164
+ async decryptFramesBatch(socket, frames) {
165
+ if (frames.length === 1) {
166
+ return [await socket.decrypt(socket.reserveReadNonce(), frames[0])];
167
+ }
168
+ const pending = new Array(frames.length);
169
+ for (let i = 0; i < frames.length; i++) {
170
+ pending[i] = socket.decrypt(socket.reserveReadNonce(), frames[i]);
171
+ }
172
+ return Promise.all(pending);
173
+ }
144
174
  reset() {
145
175
  this.logger.trace('noise session reset');
146
176
  this.frameCodec = null;
147
- this.handshakeInbox = [];
177
+ this.handshakeInbox.length = this.handshakeInboxHead = 0;
148
178
  this.handshakeWaiter = null;
149
179
  this.handshakeRejecter = null;
150
180
  this.pendingDecryptedFrames = [];
151
181
  this.closedError = null;
152
182
  this.noiseSocket = null;
153
183
  this.serverStaticKey = null;
184
+ this.writeChain = Promise.resolve();
185
+ this.readChain = Promise.resolve();
154
186
  }
155
187
  getServerStaticKey() {
156
- if (!this.serverStaticKey) {
157
- return null;
158
- }
159
188
  return this.serverStaticKey;
160
189
  }
161
190
  async fullHandshake(clientStaticKeyPair, ephemeralKeyPair, payload, protocolHeader, verifyCertificates) {
@@ -185,10 +214,12 @@ export class WaNoiseSession {
185
214
  await handshake.start(NOISE_IK_NAME, protocolHeader);
186
215
  await handshake.authenticate(serverStaticKey);
187
216
  await handshake.authenticate(ephemeralKeyPair.pubKey);
188
- const agreement1 = await X25519.scalarMult(ephemeralKeyPair.privKey, serverStaticKey);
217
+ const [agreement1, agreement2] = await Promise.all([
218
+ X25519.scalarMult(ephemeralKeyPair.privKey, serverStaticKey),
219
+ X25519.scalarMult(clientStaticKeyPair.privKey, serverStaticKey)
220
+ ]);
189
221
  await handshake.mixIntoKey(agreement1);
190
222
  const encryptedClientStatic = await handshake.encrypt(clientStaticKeyPair.pubKey);
191
- const agreement2 = await X25519.scalarMult(clientStaticKeyPair.privKey, serverStaticKey);
192
223
  await handshake.mixIntoKey(agreement2);
193
224
  const encryptedPayload = await handshake.encrypt(payload);
194
225
  const clientHello = proto.HandshakeMessage.encode({
@@ -215,8 +246,12 @@ export class WaNoiseSession {
215
246
  }
216
247
  const serverEphemeral = toBytesView(serverHello.ephemeral);
217
248
  await handshake.authenticate(serverEphemeral);
218
- await handshake.mixIntoKey(await X25519.scalarMult(ephemeralKeyPair.privKey, serverEphemeral));
219
- await handshake.mixIntoKey(await X25519.scalarMult(clientStaticKeyPair.privKey, serverEphemeral));
249
+ const [dh1, dh2] = await Promise.all([
250
+ X25519.scalarMult(ephemeralKeyPair.privKey, serverEphemeral),
251
+ X25519.scalarMult(clientStaticKeyPair.privKey, serverEphemeral)
252
+ ]);
253
+ await handshake.mixIntoKey(dh1);
254
+ await handshake.mixIntoKey(dh2);
220
255
  await handshake.decrypt(toBytesView(serverHello.payload));
221
256
  this.serverStaticKey = serverStaticKey;
222
257
  this.logger.info('noise resume handshake successful without fallback');
@@ -275,8 +310,13 @@ export class WaNoiseSession {
275
310
  if (this.closedError) {
276
311
  throw this.closedError;
277
312
  }
278
- const queued = this.handshakeInbox.shift();
313
+ const queued = this.handshakeInboxHead < this.handshakeInbox.length
314
+ ? this.handshakeInbox[this.handshakeInboxHead++]
315
+ : undefined;
279
316
  if (queued) {
317
+ if (this.handshakeInboxHead === this.handshakeInbox.length) {
318
+ this.handshakeInbox.length = this.handshakeInboxHead = 0;
319
+ }
280
320
  this.logger.trace('noise handshake frame consumed from queue');
281
321
  return queued;
282
322
  }
@@ -307,16 +347,24 @@ export class WaNoiseSession {
307
347
  });
308
348
  }
309
349
  async decodeBufferedPostHandshakeFrames() {
310
- if (!this.noiseSocket || this.handshakeInbox.length === 0) {
350
+ if (!this.noiseSocket || this.handshakeInboxHead >= this.handshakeInbox.length) {
311
351
  return;
312
352
  }
313
353
  this.logger.debug('decoding buffered post-handshake frames', {
314
- count: this.handshakeInbox.length
354
+ count: this.handshakeInbox.length - this.handshakeInboxHead
315
355
  });
316
- const buffered = this.handshakeInbox.splice(0, this.handshakeInbox.length);
317
- for (const frame of buffered) {
318
- const decrypted = await this.readQueue.enqueue(() => this.noiseSocket.decrypt(frame));
319
- this.pendingDecryptedFrames.push(decrypted);
356
+ const start = this.handshakeInboxHead;
357
+ const frames = this.handshakeInbox.slice(start);
358
+ if (frames.length > 0) {
359
+ const decryptBatch = this.decryptFramesBatch(this.noiseSocket, frames);
360
+ this.readChain = this.readChain
361
+ .then(() => decryptBatch)
362
+ .then(() => { }, () => { });
363
+ const decrypted = await decryptBatch;
364
+ for (let i = 0; i < decrypted.length; i++) {
365
+ this.pendingDecryptedFrames.push(decrypted[i]);
366
+ }
320
367
  }
368
+ this.handshakeInbox.length = this.handshakeInboxHead = 0;
321
369
  }
322
370
  }