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
@@ -167,14 +167,22 @@ function writeListSize(size, writer) {
167
167
  writer.writeUint16(size);
168
168
  }
169
169
  function writeNodeInternal(node, writer) {
170
- const attrs = Object.entries(node.attrs);
170
+ let attrsLen = 0;
171
+ for (const key in node.attrs) {
172
+ if (Object.prototype.hasOwnProperty.call(node.attrs, key)) {
173
+ attrsLen += 1;
174
+ }
175
+ }
171
176
  const hasContent = node.content !== null && node.content !== undefined;
172
- const listSize = 1 + attrs.length * 2 + (hasContent ? 1 : 0);
177
+ const listSize = 1 + attrsLen * 2 + (hasContent ? 1 : 0);
173
178
  writeListSize(listSize, writer);
174
179
  writeString(node.tag, writer);
175
- for (const [key, value] of attrs) {
180
+ for (const key in node.attrs) {
181
+ if (!Object.prototype.hasOwnProperty.call(node.attrs, key)) {
182
+ continue;
183
+ }
176
184
  writeString(key, writer);
177
- writeString(value, writer);
185
+ writeString(node.attrs[key], writer);
178
186
  }
179
187
  if (!hasContent) {
180
188
  return;
@@ -1,3 +1,4 @@
1
+ export { isProxyAgent, isProxyDispatcher, isProxyTransport, toProxyAgent, toProxyDispatcher } from './proxy.js';
1
2
  export { WaComms } from './WaComms.js';
2
3
  export { WaWebSocket } from './WaWebSocket.js';
3
4
  export { WaKeepAlive } from './keepalive/WaKeepAlive.js';
@@ -1,5 +1,5 @@
1
1
  import { WA_DEFAULTS, WA_IQ_TYPES, WA_NODE_TAGS, WA_XMLNS } from '../../protocol/constants.js';
2
- import { toError } from '../../util/primitives.js';
2
+ import { normalizeNonNegativeInteger, toError } from '../../util/primitives.js';
3
3
  const KEEPALIVE_DEFAULT_JITTER_RATIO = 0.1;
4
4
  const KEEPALIVE_DEFAULT_MIN_JITTER_MS = 250;
5
5
  const KEEPALIVE_MAX_JITTER_RATIO = 0.5;
@@ -12,7 +12,7 @@ export class WaKeepAlive {
12
12
  this.timeoutMs = options.timeoutMs ?? WA_DEFAULTS.DEAD_SOCKET_TIMEOUT_MS;
13
13
  this.hostDomain = options.hostDomain ?? WA_DEFAULTS.HOST_DOMAIN;
14
14
  this.jitterRatio = this.normalizeJitterRatio(options.jitterRatio);
15
- this.minJitterMs = this.normalizeMinJitterMs(options.minJitterMs);
15
+ this.minJitterMs = normalizeNonNegativeInteger(options.minJitterMs, KEEPALIVE_DEFAULT_MIN_JITTER_MS);
16
16
  this.timer = null;
17
17
  this.generation = 0;
18
18
  this.inFlight = false;
@@ -110,12 +110,6 @@ export class WaKeepAlive {
110
110
  const normalized = value;
111
111
  return Math.min(Math.max(normalized, 0), KEEPALIVE_MAX_JITTER_RATIO);
112
112
  }
113
- normalizeMinJitterMs(value) {
114
- if (!Number.isFinite(value)) {
115
- return KEEPALIVE_DEFAULT_MIN_JITTER_MS;
116
- }
117
- return Math.max(0, Math.trunc(value));
118
- }
119
113
  computeNextDelayMs() {
120
114
  if (this.intervalMs <= 0) {
121
115
  return 0;
@@ -1,5 +1,6 @@
1
1
  import { WA_DEFAULTS, WA_IQ_TYPES, WA_NODE_TAGS, WA_XMLNS } from '../../protocol/constants.js';
2
2
  import { toError } from '../../util/primitives.js';
3
+ import { formatNodeIdPrefixFromSeed } from './helpers.js';
3
4
  export class WaNodeOrchestrator {
4
5
  constructor(options) {
5
6
  this.logger = options.logger;
@@ -133,10 +134,7 @@ export class WaNodeOrchestrator {
133
134
  return this.stanzaPrefix;
134
135
  }
135
136
  generateStanzaPrefix() {
136
- const seed = crypto.getRandomValues(new Uint8Array(4));
137
- const left = seed[0] * 256 + seed[1];
138
- const right = seed[2] * 256 + seed[3];
139
- const prefix = `${left}.${right}-`;
137
+ const prefix = formatNodeIdPrefixFromSeed(crypto.getRandomValues(new Uint8Array(4)));
140
138
  this.logger.debug('generated stanza prefix', { prefix });
141
139
  return prefix;
142
140
  }
@@ -9,9 +9,6 @@ export class WaNodeTransport extends EventEmitter {
9
9
  this.logger = logger;
10
10
  this.comms = null;
11
11
  }
12
- on(event, listener) {
13
- return super.on(event, listener);
14
- }
15
12
  bindComms(comms) {
16
13
  this.comms = comms;
17
14
  this.logger.debug('node transport bindComms', { connected: comms !== null });
@@ -1,42 +1,22 @@
1
- import { WA_DEFAULTS, WA_NODE_TAGS, WA_XMLNS } from '../../../protocol/constants.js';
1
+ import { WA_DEFAULTS, WA_NODE_TAGS, WA_USYNC_CONTEXTS, WA_XMLNS } from '../../../protocol/constants.js';
2
+ import { buildUsyncIq } from '../../node/builders/usync.js';
2
3
  import { buildIqNode } from '../../node/query.js';
3
4
  export function buildAccountDevicesSyncIq(userJids, sid) {
4
- return buildIqNode('get', WA_DEFAULTS.HOST_DOMAIN, WA_XMLNS.USYNC, [
5
- {
6
- tag: WA_NODE_TAGS.USYNC,
7
- attrs: {
8
- sid,
9
- index: '0',
10
- last: 'true',
11
- mode: WA_NODE_TAGS.QUERY,
12
- context: WA_NODE_TAGS.NOTIFICATION
13
- },
14
- content: [
15
- {
16
- tag: WA_NODE_TAGS.QUERY,
17
- attrs: {},
18
- content: [
19
- {
20
- tag: WA_NODE_TAGS.DEVICES,
21
- attrs: {
22
- version: '2'
23
- }
24
- }
25
- ]
26
- },
27
- {
28
- tag: WA_NODE_TAGS.LIST,
29
- attrs: {},
30
- content: userJids.map((jid) => ({
31
- tag: WA_NODE_TAGS.USER,
32
- attrs: {
33
- jid
34
- }
35
- }))
5
+ return buildUsyncIq({
6
+ sid,
7
+ context: WA_USYNC_CONTEXTS.NOTIFICATION,
8
+ queryProtocolNodes: [
9
+ {
10
+ tag: WA_NODE_TAGS.DEVICES,
11
+ attrs: {
12
+ version: '2'
36
13
  }
37
- ]
38
- }
39
- ]);
14
+ }
15
+ ],
16
+ users: userJids.map((jid) => ({
17
+ jid
18
+ }))
19
+ });
40
20
  }
41
21
  export function buildAccountPictureSyncIq(meJid) {
42
22
  return buildIqNode('get', WA_DEFAULTS.HOST_DOMAIN, WA_XMLNS.PROFILE_PICTURE, [
@@ -1,7 +1,8 @@
1
- export { buildAccountBlocklistSyncIq, buildAccountDevicesSyncIq, buildAccountPictureSyncIq, buildAccountPrivacySyncIq, buildClearDirtyBitsIq, buildGroupsDirtySyncIq, buildNewsletterMetadataSyncIq } from '../../node/builders/accountSync.js';
1
+ export { buildAccountBlocklistSyncIq, buildAccountDevicesSyncIq, buildAccountPictureSyncIq, buildAccountPrivacySyncIq, buildClearDirtyBitsIq, buildGroupsDirtySyncIq, buildNewsletterMetadataSyncIq } from '../../node/builders/account-sync.js';
2
2
  export { buildCompanionFinishRequestNode, buildCompanionHelloRequestNode, buildGetCountryCodeRequestNode, buildIqResultNode, buildNotificationAckNode } from '../../node/builders/pairing.js';
3
3
  export { buildMediaConnIq } from '../../node/builders/media.js';
4
4
  export { buildDirectMessageFanoutNode, buildGroupDirectMessageNode, buildGroupRetryMessageNode, buildGroupSenderKeyMessageNode, buildInboundDeliveryReceiptNode, buildInboundMessageAckNode, buildInboundReceiptAckNode, buildInboundRetryReceiptNode, buildInboundRetryReceiptAckNode } from '../../node/builders/message.js';
5
5
  export { buildRetryReceiptNode } from '../../node/builders/retry.js';
6
6
  export { buildMissingPreKeysFetchIq, buildPreKeyUploadIq, buildSignedPreKeyRotateIq } from '../../node/builders/prekeys.js';
7
7
  export { buildCreateGroupIq, buildGroupParticipantChangeIq, buildLeaveGroupIq } from '../../node/builders/group.js';
8
+ export { buildUsyncIq, buildUsyncUserNode } from '../../node/builders/usync.js';
@@ -39,6 +39,9 @@ export function buildDirectMessageFanoutNode(input) {
39
39
  content: input.deviceIdentity
40
40
  });
41
41
  }
42
+ if (input.reportingNode) {
43
+ content.push(input.reportingNode);
44
+ }
42
45
  return {
43
46
  tag: WA_MESSAGE_TAGS.MESSAGE,
44
47
  attrs,
@@ -97,6 +100,9 @@ export function buildGroupSenderKeyMessageNode(input) {
97
100
  content: input.deviceIdentity
98
101
  });
99
102
  }
103
+ if (input.reportingNode) {
104
+ content.push(input.reportingNode);
105
+ }
100
106
  return {
101
107
  tag: WA_MESSAGE_TAGS.MESSAGE,
102
108
  attrs,
@@ -149,6 +155,9 @@ export function buildGroupDirectMessageNode(input) {
149
155
  content: input.deviceIdentity
150
156
  });
151
157
  }
158
+ if (input.reportingNode) {
159
+ content.push(input.reportingNode);
160
+ }
152
161
  return {
153
162
  tag: WA_MESSAGE_TAGS.MESSAGE,
154
163
  attrs,
@@ -1,6 +1,5 @@
1
1
  import { WA_DEFAULTS, WA_IQ_TYPES, WA_NODE_TAGS, WA_SIGNALING, WA_XMLNS } from '../../../protocol/constants.js';
2
- const ZERO_BYTE = new Uint8Array([0]);
3
- const NOTIFICATION_CLASS = WA_NODE_TAGS.NOTIFICATION;
2
+ import { ZERO_BYTES } from '../../../util/bytes.js';
4
3
  export function buildCompanionHelloRequestNode(args) {
5
4
  return {
6
5
  tag: WA_NODE_TAGS.IQ,
@@ -43,7 +42,7 @@ export function buildCompanionHelloRequestNode(args) {
43
42
  {
44
43
  tag: 'link_code_pairing_nonce',
45
44
  attrs: {},
46
- content: ZERO_BYTE
45
+ content: ZERO_BYTES
47
46
  }
48
47
  ]
49
48
  }
@@ -107,8 +106,8 @@ export function buildCompanionFinishRequestNode(args) {
107
106
  export function buildNotificationAckNode(node, typeOverride) {
108
107
  const attrs = {
109
108
  to: node.attrs.from ?? WA_DEFAULTS.HOST_DOMAIN,
110
- class: NOTIFICATION_CLASS,
111
- type: typeOverride ?? node.attrs.type ?? NOTIFICATION_CLASS
109
+ class: WA_NODE_TAGS.NOTIFICATION,
110
+ type: typeOverride ?? node.attrs.type ?? WA_NODE_TAGS.NOTIFICATION
112
111
  };
113
112
  if (node.attrs.id) {
114
113
  attrs.id = node.attrs.id;
@@ -0,0 +1,41 @@
1
+ import { WA_DEFAULTS, WA_NODE_TAGS, WA_USYNC_CONTEXTS, WA_USYNC_DEFAULTS, WA_USYNC_MODES, WA_XMLNS } from '../../../protocol/constants.js';
2
+ import { buildIqNode } from '../../node/query.js';
3
+ export function buildUsyncUserNode(input) {
4
+ return {
5
+ tag: WA_NODE_TAGS.USER,
6
+ attrs: {
7
+ ...input.attrs,
8
+ jid: input.jid
9
+ },
10
+ ...(input.content !== undefined ? { content: input.content } : {})
11
+ };
12
+ }
13
+ export function buildUsyncIq(input) {
14
+ if (input.queryProtocolNodes.length === 0) {
15
+ throw new Error('usync query must include at least one protocol node');
16
+ }
17
+ return buildIqNode('get', input.hostDomain ?? WA_DEFAULTS.HOST_DOMAIN, WA_XMLNS.USYNC, [
18
+ {
19
+ tag: WA_NODE_TAGS.USYNC,
20
+ attrs: {
21
+ sid: input.sid,
22
+ index: input.index ?? WA_USYNC_DEFAULTS.INDEX,
23
+ last: input.last ?? WA_USYNC_DEFAULTS.LAST,
24
+ mode: input.mode ?? WA_USYNC_MODES.QUERY,
25
+ context: input.context ?? WA_USYNC_CONTEXTS.INTERACTIVE
26
+ },
27
+ content: [
28
+ {
29
+ tag: WA_NODE_TAGS.QUERY,
30
+ attrs: {},
31
+ content: [...input.queryProtocolNodes]
32
+ },
33
+ {
34
+ tag: WA_NODE_TAGS.LIST,
35
+ attrs: {},
36
+ content: input.users.map((user) => buildUsyncUserNode(user))
37
+ }
38
+ ]
39
+ }
40
+ ]);
41
+ }
@@ -1,15 +1,112 @@
1
- import { base64ToBytes, TEXT_ENCODER } from '../../util/bytes.js';
1
+ import { base64ToBytesChecked, TEXT_DECODER, TEXT_ENCODER } from '../../util/bytes.js';
2
+ const EMPTY_NODE_CHILDREN = Object.freeze([]);
3
+ const EMPTY_NODE_TAGS = Object.freeze([]);
4
+ const EMPTY_NODE_VALUES = Object.freeze([]);
2
5
  export function getNodeChildren(node) {
3
- return Array.isArray(node.content) ? node.content : [];
6
+ return Array.isArray(node.content) ? node.content : EMPTY_NODE_CHILDREN;
4
7
  }
5
8
  export function findNodeChild(node, tag) {
6
- return getNodeChildren(node).find((child) => child.tag === tag);
9
+ const content = node.content;
10
+ if (!Array.isArray(content))
11
+ return undefined;
12
+ for (let i = 0; i < content.length; i++) {
13
+ if (content[i].tag === tag)
14
+ return content[i];
15
+ }
7
16
  }
8
17
  export function getFirstNodeChild(node) {
9
18
  return getNodeChildren(node)[0];
10
19
  }
11
20
  export function getNodeChildrenByTag(node, tag) {
12
- return getNodeChildren(node).filter((child) => child.tag === tag);
21
+ const content = node.content;
22
+ if (!Array.isArray(content))
23
+ return EMPTY_NODE_CHILDREN;
24
+ let tagged = null;
25
+ for (let i = 0; i < content.length; i++) {
26
+ if (content[i].tag !== tag)
27
+ continue;
28
+ if (!tagged)
29
+ tagged = [];
30
+ tagged.push(content[i]);
31
+ }
32
+ return tagged ?? EMPTY_NODE_CHILDREN;
33
+ }
34
+ export function getNodeChildrenByTagFromChildren(node, tag) {
35
+ let tagged = null;
36
+ const content = node.content;
37
+ if (!Array.isArray(content))
38
+ return EMPTY_NODE_CHILDREN;
39
+ for (let i = 0; i < content.length; i += 1) {
40
+ const nested = content[i].content;
41
+ if (!Array.isArray(nested))
42
+ continue;
43
+ for (let j = 0; j < nested.length; j += 1) {
44
+ if (nested[j].tag !== tag)
45
+ continue;
46
+ if (!tagged)
47
+ tagged = [];
48
+ tagged.push(nested[j]);
49
+ }
50
+ }
51
+ return tagged ?? EMPTY_NODE_CHILDREN;
52
+ }
53
+ export function getNodeChildrenTags(node) {
54
+ const content = node.content;
55
+ if (!Array.isArray(content) || content.length === 0)
56
+ return EMPTY_NODE_TAGS;
57
+ return content.map((c) => c.tag);
58
+ }
59
+ export function getNodeChildrenNonEmptyAttrValuesByTag(node, tag, attr) {
60
+ let values = null;
61
+ const children = getNodeChildren(node);
62
+ for (let index = 0; index < children.length; index += 1) {
63
+ const child = children[index];
64
+ if (child.tag !== tag) {
65
+ continue;
66
+ }
67
+ const value = child.attrs[attr];
68
+ if (!value) {
69
+ continue;
70
+ }
71
+ if (!values) {
72
+ values = [];
73
+ }
74
+ values.push(value);
75
+ }
76
+ return values ?? EMPTY_NODE_VALUES;
77
+ }
78
+ export function getNodeChildrenNonEmptyUtf8ByTag(node, tag, field) {
79
+ let values = null;
80
+ const children = getNodeChildren(node);
81
+ for (let index = 0; index < children.length; index += 1) {
82
+ const child = children[index];
83
+ if (child.tag !== tag) {
84
+ continue;
85
+ }
86
+ const raw = child.content;
87
+ if (raw === null || raw === undefined) {
88
+ continue;
89
+ }
90
+ if (raw instanceof Uint8Array && raw.length === 0) {
91
+ continue;
92
+ }
93
+ const value = TEXT_DECODER.decode(decodeNodeContentUtf8OrBytes(raw, field));
94
+ if (value.length === 0) {
95
+ continue;
96
+ }
97
+ if (!values) {
98
+ values = [];
99
+ }
100
+ values.push(value);
101
+ }
102
+ return values ?? EMPTY_NODE_VALUES;
103
+ }
104
+ export function findNodeChildrenByTags(node, tags) {
105
+ const out = new Array(tags.length);
106
+ for (let index = 0; index < tags.length; index += 1) {
107
+ out[index] = findNodeChild(node, tags[index]);
108
+ }
109
+ return out;
13
110
  }
14
111
  export function hasNodeChild(node, tag) {
15
112
  return findNodeChild(node, tag) !== undefined;
@@ -28,10 +125,15 @@ export function decodeNodeContentBase64OrBytes(value, field) {
28
125
  throw new Error(`missing binary node content for ${field}`);
29
126
  }
30
127
  if (typeof value === 'string') {
31
- return base64ToBytes(value);
128
+ return base64ToBytesChecked(value, field);
32
129
  }
33
130
  if (value instanceof Uint8Array) {
34
131
  return value;
35
132
  }
36
133
  throw new Error(`missing binary node content for ${field}`);
37
134
  }
135
+ export function formatNodeIdPrefixFromSeed(seed) {
136
+ const left = ((seed[0] << 8) | seed[1]) >>> 0;
137
+ const right = ((seed[2] << 8) | seed[3]) >>> 0;
138
+ return `${left}.${right}-`;
139
+ }
@@ -0,0 +1,35 @@
1
+ import { randomBytesAsync } from '../../crypto/index.js';
2
+ import { formatNodeIdPrefixFromSeed } from './helpers.js';
3
+ export function createUsyncSidGenerator() {
4
+ const state = {
5
+ prefix: null,
6
+ prefixPromise: null,
7
+ counter: 1
8
+ };
9
+ return async () => {
10
+ const prefix = await getUsyncPrefix(state);
11
+ const sid = `${prefix}${state.counter}`;
12
+ state.counter += 1;
13
+ return sid;
14
+ };
15
+ }
16
+ async function getUsyncPrefix(state) {
17
+ if (state.prefix) {
18
+ return state.prefix;
19
+ }
20
+ if (!state.prefixPromise) {
21
+ state.prefixPromise = buildUsyncPrefix()
22
+ .then((prefix) => {
23
+ state.prefix = prefix;
24
+ return prefix;
25
+ })
26
+ .finally(() => {
27
+ state.prefixPromise = null;
28
+ });
29
+ }
30
+ return state.prefixPromise;
31
+ }
32
+ async function buildUsyncPrefix() {
33
+ const seed = await randomBytesAsync(4);
34
+ return formatNodeIdPrefixFromSeed(seed);
35
+ }
@@ -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
  }
@@ -2,12 +2,11 @@ import { ed25519VerifyRaw, 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);
10
- if (signatureInput.length !== 64) {
9
+ if (!assertByteLength(signatureInput, 64, 'invalid certificate signature size', false)) {
11
10
  return false;
12
11
  }
13
12
  const signature = new Uint8Array(signatureInput);
@@ -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');
@@ -48,12 +48,9 @@ function buildRoutingInfoPrefix(routingInfo) {
48
48
  }
49
49
  export class WaNoiseSession {
50
50
  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);
55
51
  this.frameCodec = null;
56
52
  this.handshakeInbox = [];
53
+ this.handshakeInboxHead = 0;
57
54
  this.handshakeWaiter = null;
58
55
  this.handshakeRejecter = null;
59
56
  this.pendingDecryptedFrames = [];
@@ -61,6 +58,10 @@ export class WaNoiseSession {
61
58
  this.noiseSocket = null;
62
59
  this.serverStaticKey = null;
63
60
  this.handshakeFrameTimeoutMs = WA_DEFAULTS.CONNECT_TIMEOUT_MS;
61
+ this.sendWire = sendWire;
62
+ this.logger = logger;
63
+ this.writeQueue = new BoundedTaskQueue(4096, 1);
64
+ this.readQueue = new BoundedTaskQueue(4096, 1);
64
65
  }
65
66
  async start(config) {
66
67
  this.reset();
@@ -144,7 +145,7 @@ export class WaNoiseSession {
144
145
  reset() {
145
146
  this.logger.trace('noise session reset');
146
147
  this.frameCodec = null;
147
- this.handshakeInbox = [];
148
+ this.handshakeInbox.length = this.handshakeInboxHead = 0;
148
149
  this.handshakeWaiter = null;
149
150
  this.handshakeRejecter = null;
150
151
  this.pendingDecryptedFrames = [];
@@ -275,8 +276,13 @@ export class WaNoiseSession {
275
276
  if (this.closedError) {
276
277
  throw this.closedError;
277
278
  }
278
- const queued = this.handshakeInbox.shift();
279
+ const queued = this.handshakeInboxHead < this.handshakeInbox.length
280
+ ? this.handshakeInbox[this.handshakeInboxHead++]
281
+ : undefined;
279
282
  if (queued) {
283
+ if (this.handshakeInboxHead === this.handshakeInbox.length) {
284
+ this.handshakeInbox.length = this.handshakeInboxHead = 0;
285
+ }
280
286
  this.logger.trace('noise handshake frame consumed from queue');
281
287
  return queued;
282
288
  }
@@ -307,16 +313,17 @@ export class WaNoiseSession {
307
313
  });
308
314
  }
309
315
  async decodeBufferedPostHandshakeFrames() {
310
- if (!this.noiseSocket || this.handshakeInbox.length === 0) {
316
+ if (!this.noiseSocket || this.handshakeInboxHead >= this.handshakeInbox.length) {
311
317
  return;
312
318
  }
313
319
  this.logger.debug('decoding buffered post-handshake frames', {
314
- count: this.handshakeInbox.length
320
+ count: this.handshakeInbox.length - this.handshakeInboxHead
315
321
  });
316
- const buffered = this.handshakeInbox.splice(0, this.handshakeInbox.length);
317
- for (const frame of buffered) {
322
+ for (let index = this.handshakeInboxHead; index < this.handshakeInbox.length; index += 1) {
323
+ const frame = this.handshakeInbox[index];
318
324
  const decrypted = await this.readQueue.enqueue(() => this.noiseSocket.decrypt(frame));
319
325
  this.pendingDecryptedFrames.push(decrypted);
320
326
  }
327
+ this.handshakeInbox.length = this.handshakeInboxHead = 0;
321
328
  }
322
329
  }