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
@@ -1,33 +1,53 @@
1
1
  import { WA_DEFAULTS } from './constants.js';
2
- export function splitJid(jid) {
3
- const atIndex = jid.indexOf('@');
4
- if (atIndex < 1 || atIndex >= jid.length - 1) {
5
- throw new Error(`invalid jid: ${jid}`);
2
+ function scanJid(jid) {
3
+ let atIndex = -1;
4
+ let colonIndex = -1;
5
+ let dotIndex = -1;
6
+ for (let index = 0; index < jid.length; index++) {
7
+ const code = jid.charCodeAt(index);
8
+ if (code === 64) {
9
+ atIndex = index;
10
+ break;
11
+ }
12
+ if (code === 58 && colonIndex === -1)
13
+ colonIndex = index;
14
+ else if (code === 46 && dotIndex === -1 && colonIndex === -1)
15
+ dotIndex = index;
6
16
  }
7
- return {
8
- user: jid.slice(0, atIndex),
9
- server: jid.slice(atIndex + 1)
10
- };
17
+ if (atIndex < 1 || atIndex >= jid.length - 1)
18
+ throw new Error(`invalid jid: ${jid}`);
19
+ return { atIndex, colonIndex, dotIndex };
20
+ }
21
+ export function splitJid(jid) {
22
+ const { atIndex } = scanJid(jid);
23
+ return { user: jid.slice(0, atIndex), server: jid.slice(atIndex + 1) };
11
24
  }
12
25
  export function normalizeRecipientJid(to) {
13
26
  const input = to.trim();
14
- if (input.length === 0) {
27
+ if (input.length === 0)
15
28
  throw new Error('recipient cannot be empty');
29
+ let hasDash = false;
30
+ let digits = '';
31
+ for (let index = 0; index < input.length; index += 1) {
32
+ const code = input.charCodeAt(index);
33
+ if (code === 64)
34
+ return input;
35
+ if (code === 45) {
36
+ hasDash = true;
37
+ continue;
38
+ }
39
+ if (code >= 48 && code <= 57)
40
+ digits += input[index];
16
41
  }
17
- if (input.includes('@')) {
18
- return input;
19
- }
20
- if (input.includes('-')) {
42
+ if (hasDash)
21
43
  return `${input}@${WA_DEFAULTS.GROUP_SERVER}`;
22
- }
23
- const digits = input.replace(/\D/g, '');
24
- if (digits.length === 0) {
44
+ if (digits.length === 0)
25
45
  throw new Error(`invalid recipient: ${to}`);
26
- }
27
46
  return `${digits}@${WA_DEFAULTS.HOST_DOMAIN}`;
28
47
  }
29
48
  export function isJidType(jid, type) {
30
- return jid.endsWith(`@${type}`);
49
+ const atIndex = jid.length - type.length - 1;
50
+ return atIndex >= 1 && jid.charCodeAt(atIndex) === 64 && jid.endsWith(type);
31
51
  }
32
52
  export function isGroupJid(jid) {
33
53
  return isJidType(jid, WA_DEFAULTS.GROUP_SERVER);
@@ -39,26 +59,14 @@ export function isGroupOrBroadcastJid(jid) {
39
59
  return isGroupJid(jid) || isBroadcastJid(jid);
40
60
  }
41
61
  export function parseSignalAddressFromJid(jid) {
42
- const parsed = splitJid(jid);
43
- const colonIndex = parsed.user.indexOf(':');
44
- if (colonIndex === -1) {
45
- return {
46
- user: parsed.user,
47
- server: parsed.server,
48
- device: 0
49
- };
50
- }
51
- const user = parsed.user.slice(0, colonIndex);
52
- const deviceRaw = parsed.user.slice(colonIndex + 1);
53
- const device = Number.parseInt(deviceRaw, 10);
54
- if (!Number.isFinite(device) || device < 0) {
62
+ const { atIndex, colonIndex } = scanJid(jid);
63
+ const server = jid.slice(atIndex + 1);
64
+ if (colonIndex === -1)
65
+ return { user: jid.slice(0, atIndex), server, device: 0 };
66
+ const device = Number.parseInt(jid.slice(colonIndex + 1, atIndex), 10);
67
+ if (!Number.isFinite(device) || device < 0)
55
68
  throw new Error(`invalid jid device: ${jid}`);
56
- }
57
- return {
58
- user,
59
- server: parsed.server,
60
- device
61
- };
69
+ return { user: jid.slice(0, colonIndex), server, device };
62
70
  }
63
71
  export function toUserJid(jid) {
64
72
  const address = parseSignalAddressFromJid(jid);
@@ -66,29 +74,33 @@ export function toUserJid(jid) {
66
74
  }
67
75
  export function normalizeDeviceJid(jid) {
68
76
  const address = parseSignalAddressFromJid(jid);
69
- if (address.device === 0) {
77
+ if (address.device === 0)
70
78
  return `${address.user}@${address.server}`;
71
- }
72
79
  return `${address.user}:${address.device}@${address.server}`;
73
80
  }
74
81
  export function getLoginIdentity(meJid) {
75
- const parsed = splitJid(meJid);
76
- const [userAndAgent, devicePart = '0'] = parsed.user.split(':');
77
- const userPart = userAndAgent.split('.')[0];
78
- const username = Number.parseInt(userPart, 10);
79
- const device = Number.parseInt(devicePart, 10);
80
- if (!Number.isSafeInteger(username) || username <= 0) {
82
+ const { atIndex, colonIndex, dotIndex } = scanJid(meJid);
83
+ const userEndIndex = dotIndex === -1 ? (colonIndex === -1 ? atIndex : colonIndex) : dotIndex;
84
+ const username = Number.parseInt(meJid.slice(0, userEndIndex), 10);
85
+ const device = colonIndex === -1 ? 0 : Number.parseInt(meJid.slice(colonIndex + 1, atIndex), 10);
86
+ if (!Number.isSafeInteger(username) || username <= 0)
81
87
  throw new Error(`invalid numeric username from ${meJid}`);
82
- }
83
- if (!Number.isSafeInteger(device) || device < 0) {
88
+ if (!Number.isSafeInteger(device) || device < 0)
84
89
  throw new Error(`invalid device from ${meJid}`);
85
- }
86
90
  return { username, device };
87
91
  }
88
92
  export function parsePhoneJid(input) {
89
- const digits = input.replace(/\D+/g, '');
90
- if (!digits) {
91
- throw new Error('phone number is empty after normalization');
93
+ let digits = '';
94
+ for (let index = 0; index < input.length; index += 1) {
95
+ const code = input.charCodeAt(index);
96
+ if (code >= 48 && code <= 57)
97
+ digits += input[index];
92
98
  }
99
+ if (!digits)
100
+ throw new Error('phone number is empty after normalization');
93
101
  return `${digits}@${WA_DEFAULTS.HOST_DOMAIN}`;
94
102
  }
103
+ export function signalAddressKey(address) {
104
+ const server = address.server ?? WA_DEFAULTS.HOST_DOMAIN;
105
+ return `${address.user}|${server}|${address.device}`;
106
+ }
@@ -13,8 +13,8 @@ export const WA_MEDIA_HKDF_INFO = Object.freeze({
13
13
  });
14
14
  export const WA_PREVIEW_MEDIA_HKDF_INFO = 'Messenger Preview Keys';
15
15
  export function getWaMediaHkdfInfo(mediaType) {
16
- if (mediaType in WA_MEDIA_HKDF_INFO) {
17
- return WA_MEDIA_HKDF_INFO[mediaType];
18
- }
16
+ const info = WA_MEDIA_HKDF_INFO[mediaType];
17
+ if (info !== undefined)
18
+ return info;
19
19
  throw new Error(`unsupported media type: ${mediaType}`);
20
20
  }
@@ -23,6 +23,8 @@ export const WA_NODE_TAGS = Object.freeze({
23
23
  KEY_FETCH: 'key_fetch',
24
24
  LIST: 'list',
25
25
  USER: 'user',
26
+ CONTACT: 'contact',
27
+ LID: 'lid',
26
28
  PICTURE: 'picture',
27
29
  PRIVACY: 'privacy',
28
30
  PARTICIPATING: 'participating',
@@ -0,0 +1,11 @@
1
+ export const WA_USYNC_MODES = Object.freeze({
2
+ QUERY: 'query'
3
+ });
4
+ export const WA_USYNC_CONTEXTS = Object.freeze({
5
+ INTERACTIVE: 'interactive',
6
+ NOTIFICATION: 'notification'
7
+ });
8
+ export const WA_USYNC_DEFAULTS = Object.freeze({
9
+ INDEX: '0',
10
+ LAST: 'true'
11
+ });
@@ -3,3 +3,4 @@ export { mapRetryReasonFromError } from './reason.js';
3
3
  export { parseRetryReceiptRequest } from './parse.js';
4
4
  export { decodeRetryReplayPayload, encodeRetryReplayPayload, pickRetryStateMax } from './outbound.js';
5
5
  export { WaRetryReplayService } from './replay.js';
6
+ export { createOutboundRetryTracker } from './tracker.js';
@@ -1,5 +1,4 @@
1
- import { base64ToBytes, bytesToBase64 } from '../util/base64.js';
2
- import { TEXT_DECODER, TEXT_ENCODER } from '../util/bytes.js';
1
+ import { base64ToBytesChecked, bytesToBase64, TEXT_DECODER, TEXT_ENCODER } from '../util/bytes.js';
3
2
  function requireObject(value) {
4
3
  if (!value || typeof value !== 'object') {
5
4
  throw new Error('invalid retry replay payload');
@@ -44,7 +43,7 @@ export function decodeRetryReplayPayload(raw) {
44
43
  mode,
45
44
  to: requireString(parsed.to, 'to'),
46
45
  type: requireString(parsed.type, 'type'),
47
- plaintext: base64ToBytes(requireString(parsed.plaintext, 'plaintext'), 'retry.plaintext')
46
+ plaintext: base64ToBytesChecked(requireString(parsed.plaintext, 'plaintext'), 'retry.plaintext')
48
47
  };
49
48
  }
50
49
  if (mode === 'encrypted') {
@@ -57,7 +56,7 @@ export function decodeRetryReplayPayload(raw) {
57
56
  to: requireString(parsed.to, 'to'),
58
57
  type: requireString(parsed.type, 'type'),
59
58
  encType,
60
- ciphertext: base64ToBytes(requireString(parsed.ciphertext, 'ciphertext'), 'retry.ciphertext'),
59
+ ciphertext: base64ToBytesChecked(requireString(parsed.ciphertext, 'ciphertext'), 'retry.ciphertext'),
61
60
  participant: parsed.participant === undefined
62
61
  ? undefined
63
62
  : requireString(parsed.participant, 'participant')
@@ -66,7 +65,7 @@ export function decodeRetryReplayPayload(raw) {
66
65
  if (mode === 'opaque_node') {
67
66
  return {
68
67
  mode,
69
- node: base64ToBytes(requireString(parsed.node, 'node'), 'retry.node')
68
+ node: base64ToBytesChecked(requireString(parsed.node, 'node'), 'retry.node')
70
69
  };
71
70
  }
72
71
  throw new Error(`invalid retry replay payload mode: ${mode}`);
@@ -1,7 +1,7 @@
1
1
  import { WA_MESSAGE_TAGS, WA_NODE_TAGS } from '../protocol/constants.js';
2
2
  import { SIGNAL_KEY_DATA_LENGTH, SIGNAL_KEY_ID_LENGTH, SIGNAL_REGISTRATION_ID_LENGTH, SIGNAL_SIGNATURE_LENGTH } from '../signal/api/constants.js';
3
- import { decodeNodeContentBase64OrBytes, findNodeChild } from '../transport/node/helpers.js';
4
- import { parseOptionalInt } from '../transport/stream/parse.js';
3
+ import { decodeNodeContentBase64OrBytes, findNodeChildrenByTags } from '../transport/node/helpers.js';
4
+ import { parseOptionalInt } from '../util/primitives.js';
5
5
  function parseFixedLengthBytes(value, byteLength, field) {
6
6
  const out = decodeNodeContentBase64OrBytes(value, field);
7
7
  if (out.byteLength !== byteLength) {
@@ -10,81 +10,62 @@ function parseFixedLengthBytes(value, byteLength, field) {
10
10
  return out;
11
11
  }
12
12
  function parseBigEndianUint(bytes, field) {
13
- if (bytes.byteLength === 0 || bytes.byteLength > 4) {
14
- throw new Error(`${field} has invalid byte length`);
13
+ switch (bytes.byteLength) {
14
+ case 1:
15
+ return bytes[0];
16
+ case 2:
17
+ return (bytes[0] << 8) | bytes[1];
18
+ case 3:
19
+ return ((bytes[0] << 16) | (bytes[1] << 8) | bytes[2]) >>> 0;
20
+ case 4:
21
+ return ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0;
22
+ default:
23
+ throw new Error(`${field} has invalid byte length`);
15
24
  }
16
- const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
17
- if (bytes.byteLength === 1) {
18
- return view.getUint8(0);
19
- }
20
- if (bytes.byteLength === 2) {
21
- return view.getUint16(0);
22
- }
23
- return bytes.byteLength === 3 ? (view.getUint16(0) << 8) | view.getUint8(2) : view.getUint32(0);
24
- }
25
- function parseRetryType(value) {
26
- if (value === 'retry' || value === 'enc_rekey_retry') {
27
- return value;
28
- }
29
- return null;
30
25
  }
31
- function parseRetryCount(value) {
32
- const parsed = parseOptionalInt(value);
33
- if (parsed === undefined) {
34
- return 0;
35
- }
36
- if (parsed < 0) {
37
- throw new Error('retry count must be >= 0');
38
- }
39
- return parsed;
40
- }
41
- function parseRetryReason(value) {
42
- const parsed = parseOptionalInt(value);
43
- if (parsed === undefined) {
44
- return undefined;
45
- }
46
- if (parsed < 0) {
47
- throw new Error('retry reason must be >= 0');
26
+ function requireNode(node, message) {
27
+ if (!node) {
28
+ throw new Error(message);
48
29
  }
49
- return parsed;
30
+ return node;
50
31
  }
51
32
  function parseRetryKeyBundle(node) {
52
33
  if (!node) {
53
34
  return undefined;
54
35
  }
55
- const identityNode = findNodeChild(node, WA_NODE_TAGS.IDENTITY);
56
- const signedKeyNode = findNodeChild(node, WA_NODE_TAGS.SKEY);
57
- if (!identityNode || !signedKeyNode) {
58
- throw new Error('retry keys section missing identity or skey');
59
- }
60
- const signedKeyIdNode = findNodeChild(signedKeyNode, WA_NODE_TAGS.ID);
61
- const signedKeyValueNode = findNodeChild(signedKeyNode, WA_NODE_TAGS.VALUE);
62
- const signedKeySignatureNode = findNodeChild(signedKeyNode, WA_NODE_TAGS.SIGNATURE);
63
- if (!signedKeyIdNode || !signedKeyValueNode || !signedKeySignatureNode) {
64
- throw new Error('retry keys section has incomplete skey');
65
- }
66
- const keyNode = findNodeChild(node, WA_NODE_TAGS.KEY);
67
- const keyIdNode = keyNode ? findNodeChild(keyNode, WA_NODE_TAGS.ID) : undefined;
68
- const keyValueNode = keyNode ? findNodeChild(keyNode, WA_NODE_TAGS.VALUE) : undefined;
69
- if (keyNode && (!keyIdNode || !keyValueNode)) {
70
- throw new Error('retry keys section has incomplete key');
71
- }
72
- const deviceIdentityNode = findNodeChild(node, WA_NODE_TAGS.DEVICE_IDENTITY);
36
+ const [identityNode, signedKeyNode, keyNode, deviceIdentityNode] = findNodeChildrenByTags(node, [WA_NODE_TAGS.IDENTITY, WA_NODE_TAGS.SKEY, WA_NODE_TAGS.KEY, WA_NODE_TAGS.DEVICE_IDENTITY]);
37
+ const identity = requireNode(identityNode, 'retry keys section missing identity or skey');
38
+ const signedKey = requireNode(signedKeyNode, 'retry keys section missing identity or skey');
39
+ const [signedKeyIdNode, signedKeyValueNode, signedKeySignatureNode] = findNodeChildrenByTags(signedKey, [WA_NODE_TAGS.ID, WA_NODE_TAGS.VALUE, WA_NODE_TAGS.SIGNATURE]);
40
+ const signedKeyId = requireNode(signedKeyIdNode, 'retry keys section has incomplete skey');
41
+ const signedKeyValue = requireNode(signedKeyValueNode, 'retry keys section has incomplete skey');
42
+ const signedKeySignature = requireNode(signedKeySignatureNode, 'retry keys section has incomplete skey');
43
+ let keyIdNode;
44
+ let keyValueNode;
45
+ if (keyNode) {
46
+ const keyNodes = findNodeChildrenByTags(keyNode, [WA_NODE_TAGS.ID, WA_NODE_TAGS.VALUE]);
47
+ keyIdNode = keyNodes[0];
48
+ keyValueNode = keyNodes[1];
49
+ }
50
+ const keyId = keyNode ? requireNode(keyIdNode, 'retry keys section has incomplete key') : null;
51
+ const keyValue = keyNode
52
+ ? requireNode(keyValueNode, 'retry keys section has incomplete key')
53
+ : null;
73
54
  return {
74
- identity: parseFixedLengthBytes(identityNode.content, SIGNAL_KEY_DATA_LENGTH, 'retry.keys.identity'),
55
+ identity: parseFixedLengthBytes(identity.content, SIGNAL_KEY_DATA_LENGTH, 'retry.keys.identity'),
75
56
  deviceIdentity: deviceIdentityNode
76
57
  ? decodeNodeContentBase64OrBytes(deviceIdentityNode.content, 'retry.keys.device-identity')
77
58
  : undefined,
78
- key: keyIdNode && keyValueNode
59
+ key: keyId && keyValue
79
60
  ? {
80
- id: parseBigEndianUint(parseFixedLengthBytes(keyIdNode.content, SIGNAL_KEY_ID_LENGTH, 'retry.keys.key.id'), 'retry.keys.key.id'),
81
- publicKey: parseFixedLengthBytes(keyValueNode.content, SIGNAL_KEY_DATA_LENGTH, 'retry.keys.key.value')
61
+ id: parseBigEndianUint(parseFixedLengthBytes(keyId.content, SIGNAL_KEY_ID_LENGTH, 'retry.keys.key.id'), 'retry.keys.key.id'),
62
+ publicKey: parseFixedLengthBytes(keyValue.content, SIGNAL_KEY_DATA_LENGTH, 'retry.keys.key.value')
82
63
  }
83
64
  : undefined,
84
65
  skey: {
85
- id: parseBigEndianUint(parseFixedLengthBytes(signedKeyIdNode.content, SIGNAL_KEY_ID_LENGTH, 'retry.keys.skey.id'), 'retry.keys.skey.id'),
86
- publicKey: parseFixedLengthBytes(signedKeyValueNode.content, SIGNAL_KEY_DATA_LENGTH, 'retry.keys.skey.value'),
87
- signature: parseFixedLengthBytes(signedKeySignatureNode.content, SIGNAL_SIGNATURE_LENGTH, 'retry.keys.skey.signature')
66
+ id: parseBigEndianUint(parseFixedLengthBytes(signedKeyId.content, SIGNAL_KEY_ID_LENGTH, 'retry.keys.skey.id'), 'retry.keys.skey.id'),
67
+ publicKey: parseFixedLengthBytes(signedKeyValue.content, SIGNAL_KEY_DATA_LENGTH, 'retry.keys.skey.value'),
68
+ signature: parseFixedLengthBytes(signedKeySignature.content, SIGNAL_SIGNATURE_LENGTH, 'retry.keys.skey.signature')
88
69
  }
89
70
  };
90
71
  }
@@ -92,7 +73,9 @@ export function parseRetryReceiptRequest(node) {
92
73
  if (node.tag !== WA_MESSAGE_TAGS.RECEIPT) {
93
74
  return null;
94
75
  }
95
- const receiptType = parseRetryType(node.attrs.type);
76
+ const receiptType = node.attrs.type === 'retry' || node.attrs.type === 'enc_rekey_retry'
77
+ ? node.attrs.type
78
+ : null;
96
79
  if (!receiptType) {
97
80
  return null;
98
81
  }
@@ -101,19 +84,18 @@ export function parseRetryReceiptRequest(node) {
101
84
  if (!stanzaId || !from) {
102
85
  throw new Error('retry receipt is missing id/from attrs');
103
86
  }
104
- const retryNode = findNodeChild(node, 'retry');
105
- if (!retryNode) {
106
- throw new Error('retry receipt is missing retry child');
107
- }
108
- const registrationNode = findNodeChild(node, WA_NODE_TAGS.REGISTRATION);
109
- if (!registrationNode) {
110
- throw new Error('retry receipt is missing registration child');
111
- }
112
- const originalMsgId = retryNode.attrs.id;
87
+ const [retryNode, registrationNode, keysNode] = findNodeChildrenByTags(node, [
88
+ 'retry',
89
+ WA_NODE_TAGS.REGISTRATION,
90
+ 'keys'
91
+ ]);
92
+ const retry = requireNode(retryNode, 'retry receipt is missing retry child');
93
+ const registrationNodeValue = requireNode(registrationNode, 'retry receipt is missing registration child');
94
+ const originalMsgId = retry.attrs.id;
113
95
  if (!originalMsgId) {
114
96
  throw new Error('retry receipt is missing retry.id');
115
97
  }
116
- const registration = parseFixedLengthBytes(registrationNode.content, SIGNAL_REGISTRATION_ID_LENGTH, 'retry.registration');
98
+ const registration = parseFixedLengthBytes(registrationNodeValue.content, SIGNAL_REGISTRATION_ID_LENGTH, 'retry.registration');
117
99
  return {
118
100
  type: receiptType,
119
101
  stanzaId,
@@ -121,10 +103,10 @@ export function parseRetryReceiptRequest(node) {
121
103
  participant: node.attrs.participant,
122
104
  recipient: node.attrs.recipient,
123
105
  originalMsgId,
124
- retryCount: parseRetryCount(retryNode.attrs.count),
125
- retryReason: parseRetryReason(retryNode.attrs.error ?? node.attrs.error),
126
- t: retryNode.attrs.t ?? node.attrs.t,
106
+ retryCount: parseOptionalInt(retry.attrs.count) ?? 0,
107
+ retryReason: parseOptionalInt(retry.attrs.error ?? node.attrs.error),
108
+ t: retry.attrs.t ?? node.attrs.t,
127
109
  regId: parseBigEndianUint(registration, 'retry.registration'),
128
- keyBundle: parseRetryKeyBundle(findNodeChild(node, 'keys'))
110
+ keyBundle: parseRetryKeyBundle(keysNode)
129
111
  };
130
112
  }
@@ -1,11 +1,11 @@
1
1
  import { wrapDeviceSentMessage } from '../message/device-sent.js';
2
2
  import { unpadPkcs7, writeRandomPadMax16 } from '../message/padding.js';
3
3
  import { proto } from '../proto.js';
4
- import { isGroupOrBroadcastJid, normalizeDeviceJid, parseSignalAddressFromJid, splitJid, toUserJid } from '../protocol/jid.js';
4
+ import { isGroupOrBroadcastJid, normalizeDeviceJid, parseSignalAddressFromJid, toUserJid } from '../protocol/jid.js';
5
5
  import { decodeRetryReplayPayload } from './outbound.js';
6
6
  import { decodeBinaryNode } from '../transport/binary/index.js';
7
7
  import { buildGroupRetryMessageNode } from '../transport/node/builders/message.js';
8
- import { findNodeChild, getNodeChildrenByTag } from '../transport/node/helpers.js';
8
+ import { findNodeChild } from '../transport/node/helpers.js';
9
9
  import { toError } from '../util/primitives.js';
10
10
  export class WaRetryReplayService {
11
11
  constructor(options) {
@@ -13,17 +13,19 @@ export class WaRetryReplayService {
13
13
  }
14
14
  async resendOutboundMessage(outbound, requesterJid, retryCount) {
15
15
  const payload = decodeRetryReplayPayload(outbound.replayPayload);
16
+ const requesterAddress = parseSignalAddressFromJid(requesterJid);
17
+ const normalizedRequesterJid = normalizeDeviceJid(requesterJid);
16
18
  if (payload.mode === 'plaintext') {
17
- return this.resendPlaintextPayload(outbound, payload, requesterJid, retryCount);
19
+ return this.resendPlaintextPayload(outbound, payload, requesterJid, requesterAddress, retryCount);
18
20
  }
19
21
  if (payload.mode === 'encrypted') {
20
- return this.resendEncryptedPayload(outbound, payload, requesterJid, retryCount);
22
+ return this.resendEncryptedPayload(outbound, payload, requesterJid, normalizedRequesterJid, retryCount);
21
23
  }
22
- return this.resendOpaquePayload(outbound, payload, requesterJid);
24
+ return this.resendOpaquePayload(outbound, payload, normalizedRequesterJid);
23
25
  }
24
- async resendPlaintextPayload(outbound, payload, requesterJid, retryCount) {
26
+ async resendPlaintextPayload(outbound, payload, requesterJid, requesterAddress, retryCount) {
25
27
  if (isGroupOrBroadcastJid(payload.to)) {
26
- return this.resendGroupPlaintextPayload(outbound, payload, requesterJid);
28
+ return this.resendGroupPlaintextPayload(outbound, payload, requesterJid, requesterAddress);
27
29
  }
28
30
  let payloadUserJid;
29
31
  let requesterUserJid;
@@ -37,8 +39,8 @@ export class WaRetryReplayService {
37
39
  if (payloadUserJid !== requesterUserJid) {
38
40
  return 'ineligible';
39
41
  }
40
- const encrypted = await this.signalProtocol.encryptMessage(parseSignalAddressFromJid(requesterJid), payload.plaintext);
41
- await this.messageClient.sendEncrypted({
42
+ const encrypted = await this.options.signalProtocol.encryptMessage(requesterAddress, payload.plaintext);
43
+ await this.options.messageClient.sendEncrypted({
42
44
  to: requesterJid,
43
45
  encType: encrypted.type,
44
46
  ciphertext: encrypted.ciphertext,
@@ -48,15 +50,15 @@ export class WaRetryReplayService {
48
50
  });
49
51
  return 'resent';
50
52
  }
51
- async resendGroupPlaintextPayload(outbound, payload, requesterJid) {
53
+ async resendGroupPlaintextPayload(outbound, payload, requesterJid, requesterAddress) {
52
54
  const plaintext = (await this.maybeWrapGroupRetryPlaintextForSelfDevice(payload, requesterJid)) ??
53
55
  payload.plaintext;
54
- const encrypted = await this.signalProtocol.encryptMessage(parseSignalAddressFromJid(requesterJid), plaintext);
56
+ const encrypted = await this.options.signalProtocol.encryptMessage(requesterAddress, plaintext);
55
57
  let deviceIdentity;
56
58
  if (encrypted.type === 'pkmsg') {
57
- const signedIdentity = this.getCurrentSignedIdentity();
59
+ const signedIdentity = this.options.getCurrentSignedIdentity();
58
60
  if (!signedIdentity) {
59
- this.logger.warn('retry request rejected: missing signed identity for pkmsg group retry');
61
+ this.options.logger.warn('retry request rejected: missing signed identity for pkmsg group retry');
60
62
  return 'ineligible';
61
63
  }
62
64
  deviceIdentity = proto.ADVSignedDeviceIdentity.encode(signedIdentity).finish();
@@ -66,22 +68,22 @@ export class WaRetryReplayService {
66
68
  type: payload.type,
67
69
  id: outbound.messageId,
68
70
  requesterJid,
69
- addressingMode: splitJid(requesterJid).server === 'lid' ? 'lid' : 'pn',
71
+ addressingMode: requesterAddress.server === 'lid' ? 'lid' : 'pn',
70
72
  encType: encrypted.type,
71
73
  ciphertext: encrypted.ciphertext,
72
74
  deviceIdentity
73
75
  });
74
- await this.messageClient.sendMessageNode(retryNode);
76
+ await this.options.messageClient.sendMessageNode(retryNode);
75
77
  return 'resent';
76
78
  }
77
- async resendEncryptedPayload(outbound, payload, requesterJid, retryCount) {
79
+ async resendEncryptedPayload(outbound, payload, requesterJid, normalizedRequesterJid, retryCount) {
78
80
  if (payload.encType === 'skmsg') {
79
81
  return 'ineligible';
80
82
  }
81
- if (normalizeDeviceJid(payload.to) !== normalizeDeviceJid(requesterJid)) {
83
+ if (normalizeDeviceJid(payload.to) !== normalizedRequesterJid) {
82
84
  return 'ineligible';
83
85
  }
84
- await this.messageClient.sendEncrypted({
86
+ await this.options.messageClient.sendEncrypted({
85
87
  to: requesterJid,
86
88
  encType: payload.encType,
87
89
  ciphertext: payload.ciphertext,
@@ -92,8 +94,11 @@ export class WaRetryReplayService {
92
94
  });
93
95
  return 'resent';
94
96
  }
95
- async resendOpaquePayload(outbound, payload, requesterJid) {
97
+ async resendOpaquePayload(outbound, payload, normalizedRequesterJid) {
96
98
  const decoded = decodeBinaryNode(payload.node);
99
+ if (!this.isOpaqueReplayCompatible(decoded, normalizedRequesterJid)) {
100
+ return 'ineligible';
101
+ }
97
102
  const replayNode = decoded.attrs.id === outbound.messageId
98
103
  ? decoded
99
104
  : {
@@ -103,10 +108,7 @@ export class WaRetryReplayService {
103
108
  id: outbound.messageId
104
109
  }
105
110
  };
106
- if (!this.isOpaqueReplayCompatible(replayNode, requesterJid)) {
107
- return 'ineligible';
108
- }
109
- await this.messageClient.sendMessageNode(replayNode);
111
+ await this.options.messageClient.sendMessageNode(replayNode);
110
112
  return 'resent';
111
113
  }
112
114
  async maybeWrapGroupRetryPlaintextForSelfDevice(payload, requesterJid) {
@@ -120,7 +122,7 @@ export class WaRetryReplayService {
120
122
  return writeRandomPadMax16(proto.Message.encode(wrapped).finish());
121
123
  }
122
124
  catch (error) {
123
- this.logger.warn('retry request failed to wrap deviceSent payload for self requester', {
125
+ this.options.logger.warn('retry request failed to wrap deviceSent payload for self requester', {
124
126
  requester: requesterJid,
125
127
  to: payload.to,
126
128
  message: toError(error).message
@@ -140,38 +142,35 @@ export class WaRetryReplayService {
140
142
  }
141
143
  return false;
142
144
  }
143
- get logger() {
144
- return this.options.logger;
145
- }
146
- get messageClient() {
147
- return this.options.messageClient;
148
- }
149
- get signalProtocol() {
150
- return this.options.signalProtocol;
151
- }
152
- getCurrentSignedIdentity() {
153
- return this.options.getCurrentSignedIdentity();
154
- }
155
- isOpaqueReplayCompatible(node, requesterJid) {
156
- const requester = normalizeDeviceJid(requesterJid);
145
+ isOpaqueReplayCompatible(node, normalizedRequesterJid) {
157
146
  const participantsNode = findNodeChild(node, 'participants');
158
147
  if (participantsNode) {
159
- const toNodes = getNodeChildrenByTag(participantsNode, 'to');
160
- if (toNodes.length !== 1) {
161
- return false;
148
+ const participantsContent = Array.isArray(participantsNode.content)
149
+ ? participantsNode.content
150
+ : [];
151
+ let participantNode;
152
+ let participantCount = 0;
153
+ for (let index = 0; index < participantsContent.length; index++) {
154
+ const child = participantsContent[index];
155
+ if (child.tag !== 'to')
156
+ continue;
157
+ participantCount++;
158
+ if (participantCount > 1)
159
+ return false;
160
+ participantNode = child;
162
161
  }
163
- const participantJid = toNodes[0].attrs.jid;
164
- if (!participantJid) {
162
+ if (participantCount !== 1 || !participantNode)
165
163
  return false;
166
- }
167
- return normalizeDeviceJid(participantJid) === requester;
164
+ const participantJid = participantNode.attrs.jid;
165
+ if (!participantJid)
166
+ return false;
167
+ return normalizeDeviceJid(participantJid) === normalizedRequesterJid;
168
168
  }
169
169
  if (node.attrs.participant) {
170
- return normalizeDeviceJid(node.attrs.participant) === requester;
171
- }
172
- if (node.attrs.to) {
173
- return normalizeDeviceJid(node.attrs.to) === requester;
170
+ return normalizeDeviceJid(node.attrs.participant) === normalizedRequesterJid;
174
171
  }
172
+ if (node.attrs.to)
173
+ return normalizeDeviceJid(node.attrs.to) === normalizedRequesterJid;
175
174
  return false;
176
175
  }
177
176
  }