@alannxd/baileys 6.0.3 → 6.0.5

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 (234) hide show
  1. package/WAProto/GenerateStatics.sh +3 -0
  2. package/WAProto/WAProto.proto +5479 -0
  3. package/WAProto/fix-imports.js +85 -0
  4. package/WAProto/index.d.ts +14017 -0
  5. package/WAProto/index.js +201 -160
  6. package/engine-requirements.js +1 -1
  7. package/lib/Defaults/index.d.ts +37 -15
  8. package/lib/Defaults/index.js +119 -136
  9. package/lib/Signal/Group/ciphertext-message.d.ts +1 -0
  10. package/lib/Signal/Group/ciphertext-message.js +2 -5
  11. package/lib/Signal/Group/group-session-builder.d.ts +4 -3
  12. package/lib/Signal/Group/group-session-builder.js +7 -41
  13. package/lib/Signal/Group/group_cipher.d.ts +4 -4
  14. package/lib/Signal/Group/group_cipher.js +37 -51
  15. package/lib/Signal/Group/index.d.ts +12 -11
  16. package/lib/Signal/Group/index.js +12 -57
  17. package/lib/Signal/Group/keyhelper.d.ts +2 -1
  18. package/lib/Signal/Group/keyhelper.js +7 -44
  19. package/lib/Signal/Group/sender-chain-key.d.ts +3 -2
  20. package/lib/Signal/Group/sender-chain-key.js +7 -15
  21. package/lib/Signal/Group/sender-key-distribution-message.d.ts +2 -1
  22. package/lib/Signal/Group/sender-key-distribution-message.js +8 -11
  23. package/lib/Signal/Group/sender-key-message.d.ts +2 -1
  24. package/lib/Signal/Group/sender-key-message.js +9 -12
  25. package/lib/Signal/Group/sender-key-name.d.ts +1 -0
  26. package/lib/Signal/Group/sender-key-name.js +2 -5
  27. package/lib/Signal/Group/sender-key-record.d.ts +3 -2
  28. package/lib/Signal/Group/sender-key-record.js +9 -21
  29. package/lib/Signal/Group/sender-key-state.d.ts +7 -6
  30. package/lib/Signal/Group/sender-key-state.js +27 -42
  31. package/lib/Signal/Group/sender-message-key.d.ts +1 -0
  32. package/lib/Signal/Group/sender-message-key.js +4 -7
  33. package/lib/Signal/libsignal.d.ts +5 -3
  34. package/lib/Signal/libsignal.js +347 -90
  35. package/lib/Signal/lid-mapping.d.ts +23 -0
  36. package/lib/Signal/lid-mapping.js +277 -0
  37. package/lib/Socket/Client/index.d.ts +3 -3
  38. package/lib/Socket/Client/index.js +3 -19
  39. package/lib/Socket/Client/{abstract-socket-client.d.ts → types.d.ts} +4 -5
  40. package/lib/Socket/Client/types.js +11 -0
  41. package/lib/Socket/Client/{web-socket-client.d.ts → websocket.d.ts} +3 -2
  42. package/lib/Socket/Client/websocket.js +54 -0
  43. package/lib/Socket/business.d.ts +154 -108
  44. package/lib/Socket/business.js +162 -43
  45. package/lib/Socket/chats.d.ts +96 -239
  46. package/lib/Socket/chats.js +627 -427
  47. package/lib/Socket/communities.d.ts +239 -146
  48. package/lib/Socket/communities.js +90 -80
  49. package/lib/Socket/groups.d.ts +104 -57
  50. package/lib/Socket/groups.js +154 -161
  51. package/lib/Socket/index.d.ts +202 -115
  52. package/lib/Socket/index.js +11 -10
  53. package/lib/Socket/luxu.d.ts +22 -266
  54. package/lib/Socket/luxu.js +422 -465
  55. package/lib/Socket/messages-recv.d.ts +136 -84
  56. package/lib/Socket/messages-recv.js +1421 -615
  57. package/lib/Socket/messages-send.d.ts +142 -126
  58. package/lib/Socket/messages-send.js +878 -671
  59. package/lib/Socket/mex.d.ts +3 -0
  60. package/lib/Socket/mex.js +42 -0
  61. package/lib/Socket/newsletter.d.ts +121 -85
  62. package/lib/Socket/newsletter.js +147 -272
  63. package/lib/Socket/socket.d.ts +34 -19
  64. package/lib/Socket/socket.js +544 -313
  65. package/lib/Store/index.d.ts +10 -3
  66. package/lib/Store/index.js +10 -10
  67. package/lib/Store/keyed-db.d.ts +22 -0
  68. package/lib/Store/keyed-db.js +108 -0
  69. package/lib/Store/make-cache-manager-store.d.ts +17 -11
  70. package/lib/Store/make-cache-manager-store.js +43 -41
  71. package/lib/Store/make-in-memory-store.d.ts +39 -118
  72. package/lib/Store/make-in-memory-store.js +112 -341
  73. package/lib/Store/make-ordered-dictionary.d.ts +11 -10
  74. package/lib/Store/make-ordered-dictionary.js +14 -20
  75. package/lib/Store/object-repository.d.ts +10 -9
  76. package/lib/Store/object-repository.js +11 -6
  77. package/lib/Types/Auth.d.ts +19 -12
  78. package/lib/Types/Auth.js +2 -2
  79. package/lib/Types/Bussines.d.ts +25 -0
  80. package/lib/Types/Bussines.js +2 -0
  81. package/lib/Types/Call.d.ts +3 -1
  82. package/lib/Types/Call.js +2 -2
  83. package/lib/Types/Chat.d.ts +35 -13
  84. package/lib/Types/Chat.js +8 -4
  85. package/lib/Types/Contact.d.ts +8 -1
  86. package/lib/Types/Contact.js +2 -2
  87. package/lib/Types/Events.d.ts +116 -17
  88. package/lib/Types/Events.js +2 -2
  89. package/lib/Types/GroupMetadata.d.ts +21 -5
  90. package/lib/Types/GroupMetadata.js +2 -2
  91. package/lib/Types/Label.d.ts +12 -0
  92. package/lib/Types/Label.js +3 -5
  93. package/lib/Types/LabelAssociation.d.ts +1 -0
  94. package/lib/Types/LabelAssociation.js +3 -5
  95. package/lib/Types/Message.d.ts +105 -58
  96. package/lib/Types/Message.js +11 -9
  97. package/lib/Types/Mex.d.ts +141 -0
  98. package/lib/Types/Mex.js +37 -0
  99. package/lib/Types/Product.d.ts +2 -1
  100. package/lib/Types/Product.js +2 -2
  101. package/lib/Types/Signal.d.ts +32 -2
  102. package/lib/Types/Signal.js +2 -2
  103. package/lib/Types/Socket.d.ts +50 -25
  104. package/lib/Types/Socket.js +3 -2
  105. package/lib/Types/State.d.ts +72 -2
  106. package/lib/Types/State.js +56 -2
  107. package/lib/Types/USync.d.ts +3 -2
  108. package/lib/Types/USync.js +2 -2
  109. package/lib/Types/index.d.ts +22 -14
  110. package/lib/Types/index.js +15 -31
  111. package/lib/Utils/auth-utils.d.ts +12 -6
  112. package/lib/Utils/auth-utils.js +239 -143
  113. package/lib/Utils/browser-utils.d.ts +4 -0
  114. package/lib/Utils/browser-utils.js +28 -0
  115. package/lib/Utils/business.d.ts +3 -2
  116. package/lib/Utils/business.js +66 -69
  117. package/lib/Utils/chat-utils.d.ts +52 -23
  118. package/lib/Utils/chat-utils.js +396 -253
  119. package/lib/Utils/companion-reg-client-utils.d.ts +17 -0
  120. package/lib/Utils/companion-reg-client-utils.js +35 -0
  121. package/lib/Utils/crypto.d.ts +18 -22
  122. package/lib/Utils/crypto.js +57 -90
  123. package/lib/Utils/decode-wa-message.d.ts +55 -8
  124. package/lib/Utils/decode-wa-message.js +203 -84
  125. package/lib/Utils/event-buffer.d.ts +9 -8
  126. package/lib/Utils/event-buffer.js +185 -77
  127. package/lib/Utils/generics.d.ts +28 -29
  128. package/lib/Utils/generics.js +180 -210
  129. package/lib/Utils/history.d.ts +18 -9
  130. package/lib/Utils/history.js +93 -55
  131. package/lib/Utils/identity-change-handler.d.ts +44 -0
  132. package/lib/Utils/identity-change-handler.js +50 -0
  133. package/lib/Utils/index.d.ts +22 -17
  134. package/lib/Utils/index.js +22 -33
  135. package/lib/Utils/link-preview.d.ts +5 -5
  136. package/lib/Utils/link-preview.js +16 -24
  137. package/lib/Utils/logger.d.ts +11 -3
  138. package/lib/Utils/logger.js +3 -7
  139. package/lib/Utils/lt-hash.d.ts +8 -12
  140. package/lib/Utils/lt-hash.js +3 -46
  141. package/lib/Utils/make-mutex.d.ts +4 -2
  142. package/lib/Utils/make-mutex.js +24 -34
  143. package/lib/Utils/message-retry-manager.d.ts +115 -0
  144. package/lib/Utils/message-retry-manager.js +265 -0
  145. package/lib/Utils/messages-media.d.ts +61 -44
  146. package/lib/Utils/messages-media.js +451 -482
  147. package/lib/Utils/messages.d.ts +32 -18
  148. package/lib/Utils/messages.js +458 -369
  149. package/lib/Utils/noise-handler.d.ts +13 -14
  150. package/lib/Utils/noise-handler.js +145 -99
  151. package/lib/Utils/offline-node-processor.d.ts +17 -0
  152. package/lib/Utils/offline-node-processor.js +40 -0
  153. package/lib/Utils/pre-key-manager.d.ts +28 -0
  154. package/lib/Utils/pre-key-manager.js +106 -0
  155. package/lib/Utils/process-message.d.ts +31 -12
  156. package/lib/Utils/process-message.js +459 -150
  157. package/lib/Utils/reporting-utils.d.ts +11 -0
  158. package/lib/Utils/reporting-utils.js +258 -0
  159. package/lib/Utils/signal.d.ts +20 -5
  160. package/lib/Utils/signal.js +120 -72
  161. package/lib/Utils/stanza-ack.d.ts +11 -0
  162. package/lib/Utils/stanza-ack.js +38 -0
  163. package/lib/Utils/sync-action-utils.d.ts +19 -0
  164. package/lib/Utils/sync-action-utils.js +49 -0
  165. package/lib/Utils/tc-token-utils.d.ts +37 -0
  166. package/lib/Utils/tc-token-utils.js +163 -0
  167. package/lib/Utils/use-multi-file-auth-state.d.ts +2 -2
  168. package/lib/Utils/use-multi-file-auth-state.js +29 -27
  169. package/lib/Utils/validate-connection.d.ts +7 -7
  170. package/lib/Utils/validate-connection.js +73 -99
  171. package/lib/WABinary/constants.d.ts +25 -27
  172. package/lib/WABinary/constants.js +1281 -20
  173. package/lib/WABinary/decode.d.ts +5 -5
  174. package/lib/WABinary/decode.js +52 -42
  175. package/lib/WABinary/encode.d.ts +3 -3
  176. package/lib/WABinary/encode.js +110 -155
  177. package/lib/WABinary/generic-utils.d.ts +8 -7
  178. package/lib/WABinary/generic-utils.js +48 -49
  179. package/lib/WABinary/index.d.ts +6 -5
  180. package/lib/WABinary/index.js +6 -21
  181. package/lib/WABinary/jid-utils.d.ts +25 -8
  182. package/lib/WABinary/jid-utils.js +74 -40
  183. package/lib/WABinary/types.d.ts +2 -1
  184. package/lib/WABinary/types.js +2 -2
  185. package/lib/WAM/BinaryInfo.d.ts +3 -11
  186. package/lib/WAM/BinaryInfo.js +2 -5
  187. package/lib/WAM/constants.d.ts +5 -3
  188. package/lib/WAM/constants.js +19071 -11568
  189. package/lib/WAM/encode.d.ts +3 -3
  190. package/lib/WAM/encode.js +17 -22
  191. package/lib/WAM/index.d.ts +4 -3
  192. package/lib/WAM/index.js +4 -19
  193. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +4 -3
  194. package/lib/WAUSync/Protocols/USyncContactProtocol.js +33 -13
  195. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +3 -2
  196. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +11 -14
  197. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +3 -2
  198. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +9 -12
  199. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +3 -2
  200. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +9 -13
  201. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
  202. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
  203. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +4 -3
  204. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +20 -22
  205. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +5 -3
  206. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +13 -8
  207. package/lib/WAUSync/Protocols/index.d.ts +6 -4
  208. package/lib/WAUSync/Protocols/index.js +6 -20
  209. package/lib/WAUSync/USyncQuery.d.ts +6 -4
  210. package/lib/WAUSync/USyncQuery.js +44 -35
  211. package/lib/WAUSync/USyncUser.d.ts +10 -5
  212. package/lib/WAUSync/USyncUser.js +10 -5
  213. package/lib/WAUSync/index.d.ts +4 -0
  214. package/lib/WAUSync/index.js +4 -19
  215. package/lib/index.d.ts +10 -9
  216. package/lib/index.js +12 -34
  217. package/package.json +84 -53
  218. package/WAProto/fix-import.js +0 -29
  219. package/lib/Defaults/baileys-version.json +0 -3
  220. package/lib/Defaults/phonenumber-mcc.json +0 -223
  221. package/lib/Signal/Group/queue-job.d.ts +0 -1
  222. package/lib/Signal/Group/queue-job.js +0 -57
  223. package/lib/Socket/Client/abstract-socket-client.js +0 -13
  224. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
  225. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  226. package/lib/Socket/Client/web-socket-client.js +0 -62
  227. package/lib/Socket/registration.d.ts +0 -267
  228. package/lib/Socket/registration.js +0 -166
  229. package/lib/Socket/usync.d.ts +0 -36
  230. package/lib/Socket/usync.js +0 -70
  231. package/lib/Types/Newsletter.d.ts +0 -103
  232. package/lib/Types/Newsletter.js +0 -38
  233. package/lib/Utils/baileys-event-stream.d.ts +0 -16
  234. package/lib/Utils/baileys-event-stream.js +0 -63
@@ -1,65 +1,63 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.makeSocket = void 0;
4
- const boom_1 = require("@hapi/boom");
5
- const crypto_1 = require("crypto");
6
- const url_1 = require("url");
7
- const util_1 = require("util");
8
- const WAProto_1 = require("../../WAProto");
9
- const Defaults_1 = require("../Defaults");
10
- const Types_1 = require("../Types");
11
- const Utils_1 = require("../Utils");
12
- const WABinary_1 = require("../WABinary");
13
- const Client_1 = require("./Client");
1
+ import { Boom } from '@hapi/boom';
2
+ import { randomBytes } from 'crypto';
3
+ import { URL } from 'url';
4
+ import { promisify } from 'util';
5
+ import { proto } from '../../WAProto/index.js';
6
+ import { DEF_CALLBACK_PREFIX, DEF_TAG_PREFIX, INITIAL_PREKEY_COUNT, MIN_PREKEY_COUNT, NOISE_WA_HEADER, PROCESSABLE_HISTORY_TYPES, TimeMs, UPLOAD_TIMEOUT } from '../Defaults/index.js';
7
+ import { QueryIds, ReachoutTimelockEnforcementType } from '../Types/index.js';
8
+ import { DisconnectReason, XWAPaths } from '../Types/index.js';
9
+ import { addTransactionCapability, aesEncryptCTR, bindWaitForConnectionUpdate, buildPairingQRData, bytesToCrockford, configureSuccessfulPairing, Curve, derivePairingCodeKey, generateLoginNode, generateMdTagPrefix, generateRegistrationNode, getCodeFromWSError, getCompanionPlatformId, getErrorCodeFromStreamError, getNextPreKeysNode, makeEventBuffer, makeNoiseHandler, promiseTimeout, signedKeyPair, xmppSignedPreKey } from '../Utils/index.js';
10
+ import { assertNodeErrorFree, binaryNodeToString, encodeBinaryNode, getAllBinaryNodeChildren, getBinaryNodeChild, getBinaryNodeChildren, isLidUser, jidDecode, jidEncode, S_WHATSAPP_NET } from '../WABinary/index.js';
11
+ import { BinaryInfo } from '../WAM/BinaryInfo.js';
12
+ import { USyncQuery, USyncUser } from '../WAUSync/index.js';
13
+ import { WebSocketClient } from './Client/index.js';
14
+ import { executeWMexQuery } from './mex.js';
14
15
  /**
15
16
  * Connects to WA servers and performs:
16
17
  * - simple queries (no retry mechanism, wait for connection establishment)
17
18
  * - listen to messages and emit events
18
19
  * - query phone connection
19
20
  */
20
- const makeSocket = (config) => {
21
- var _a, _b;
22
- const { waWebSocketUrl, connectTimeoutMs, logger, keepAliveIntervalMs, browser, auth: authState, printQRInTerminal, defaultQueryTimeoutMs, transactionOpts, qrTimeout, makeSignalRepository, } = config;
23
- const url = typeof waWebSocketUrl === 'string' ? new url_1.URL(waWebSocketUrl) : waWebSocketUrl;
21
+ export const makeSocket = (config) => {
22
+ const { waWebSocketUrl, connectTimeoutMs, logger, keepAliveIntervalMs, browser, auth: authState, printQRInTerminal, defaultQueryTimeoutMs, transactionOpts, qrTimeout, makeSignalRepository } = config;
23
+ const publicWAMBuffer = new BinaryInfo();
24
+ let serverTimeOffsetMs = 0;
25
+ const uqTagId = generateMdTagPrefix();
26
+ const generateMessageTag = () => `ALANXD-${epoch++}`;
27
+ if (printQRInTerminal) {
28
+ logger.warn({}, '⚠️ The printQRInTerminal option has been deprecated. You will no longer receive QR codes in the terminal automatically. Please listen to the connection.update event yourself and handle the QR your way. You can remove this message by removing this opttion. This message will be removed in a future version.');
29
+ }
30
+ const syncDisabled = PROCESSABLE_HISTORY_TYPES.map(syncType => config.shouldSyncHistoryMessage({ syncType })).filter(x => x === false)
31
+ .length === PROCESSABLE_HISTORY_TYPES.length;
32
+ if (syncDisabled) {
33
+ logger.warn('⚠️ DANGER: DISABLING ALL SYNC BY shouldSyncHistoryMsg PREVENTS BAILEYS FROM ACCESSING INITIAL LID MAPPINGS, LEADING TO INSTABILIY AND SESSION ERRORS');
34
+ }
35
+ const url = typeof waWebSocketUrl === 'string' ? new URL(waWebSocketUrl) : waWebSocketUrl;
24
36
  if (config.mobile || url.protocol === 'tcp:') {
25
- throw new boom_1.Boom('Mobile API is not supported anymore', {
26
- statusCode: Types_1.DisconnectReason.loggedOut
27
- });
37
+ throw new Boom('Mobile API is not supported anymore', { statusCode: DisconnectReason.loggedOut });
28
38
  }
29
- if (url.protocol === 'wss' && ((_a = authState === null || authState === void 0 ? void 0 : authState.creds) === null || _a === void 0 ? void 0 : _a.routingInfo)) {
39
+ if (url.protocol === 'wss' && authState?.creds?.routingInfo) {
30
40
  url.searchParams.append('ED', authState.creds.routingInfo.toString('base64url'));
31
41
  }
32
- const ws = new Client_1.WebSocketClient(url, config);
33
- ws.connect();
34
- const ev = (0, Utils_1.makeEventBuffer)(logger);
35
42
  /** ephemeral key pair used to encrypt/decrypt communication. Unique for each connection */
36
- const ephemeralKeyPair = Utils_1.Curve.generateKeyPair();
43
+ const ephemeralKeyPair = Curve.generateKeyPair();
37
44
  /** WA noise protocol wrapper */
38
- const noise = (0, Utils_1.makeNoiseHandler)({
45
+ const noise = makeNoiseHandler({
39
46
  keyPair: ephemeralKeyPair,
40
- NOISE_HEADER: Defaults_1.NOISE_WA_HEADER,
47
+ NOISE_HEADER: NOISE_WA_HEADER,
41
48
  logger,
42
- routingInfo: (_b = authState === null || authState === void 0 ? void 0 : authState.creds) === null || _b === void 0 ? void 0 : _b.routingInfo
49
+ routingInfo: authState?.creds?.routingInfo
43
50
  });
44
- const { creds } = authState;
45
- // add transaction capability
46
- const keys = (0, Utils_1.addTransactionCapability)(authState.keys, logger, transactionOpts);
47
- const signalRepository = makeSignalRepository({ creds, keys });
48
- let lastDateRecv;
49
- let epoch = 1;
50
- let keepAliveReq;
51
- let qrTimer;
52
- let closed = false;
53
- const uqTagId = (0, Utils_1.generateMdTagPrefix)();
54
- const generateMessageTag = () => `${uqTagId}${epoch++}`;
55
- const sendPromise = (0, util_1.promisify)(ws.send);
51
+ const ws = new WebSocketClient(url, config);
52
+ ws.connect();
53
+ const sendPromise = promisify(ws.send);
56
54
  /** send a raw buffer */
57
55
  const sendRawMessage = async (data) => {
58
56
  if (!ws.isOpen) {
59
- throw new boom_1.Boom('Connection Closed', { statusCode: Types_1.DisconnectReason.connectionClosed });
57
+ throw new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed });
60
58
  }
61
59
  const bytes = noise.encodeFrame(data);
62
- await (0, Utils_1.promiseTimeout)(connectTimeoutMs, async (resolve, reject) => {
60
+ await promiseTimeout(connectTimeoutMs, async (resolve, reject) => {
63
61
  try {
64
62
  await sendPromise.call(ws, bytes);
65
63
  resolve();
@@ -72,60 +70,11 @@ const makeSocket = (config) => {
72
70
  /** send a binary node */
73
71
  const sendNode = (frame) => {
74
72
  if (logger.level === 'trace') {
75
- logger.trace({ xml: (0, WABinary_1.binaryNodeToString)(frame), msg: 'xml send' });
73
+ logger.trace({ xml: binaryNodeToString(frame), msg: 'xml send' });
76
74
  }
77
- const buff = (0, WABinary_1.encodeBinaryNode)(frame);
75
+ const buff = encodeBinaryNode(frame);
78
76
  return sendRawMessage(buff);
79
77
  };
80
- /** log & process any unexpected errors */
81
- const onUnexpectedError = (err, msg) => {
82
- logger.error({ err }, `unexpected error in '${msg}'`);
83
- const message = (err && ((err.stack || err.message) || String(err))).toLowerCase();
84
- // auto recover from cryptographic desyncs by re-uploading prekeys
85
- if (message.includes('bad mac') || (message.includes('mac') && message.includes('invalid'))) {
86
- try {
87
- uploadPreKeysToServerIfRequired(true)
88
- .catch(e => logger.warn({ e }, 'failed to re-upload prekeys after bad mac'));
89
- }
90
- catch (_e) {
91
- // ignore
92
- }
93
- }
94
- // gently back off when encountering rate limits (429)
95
- if (message.includes('429') || message.includes('rate limit')) {
96
- const wait = Math.min(30000, (config.backoffDelayMs || 5000));
97
- logger.info({ wait }, 'backing off due to rate limit');
98
- setTimeout(() => {
99
- // intentionally empty; wait to delay further sends
100
- }, wait);
101
- }
102
- };
103
- /** await the next incoming message */
104
- const awaitNextMessage = async (sendMsg) => {
105
- if (!ws.isOpen) {
106
- throw new boom_1.Boom('Connection Closed', {
107
- statusCode: Types_1.DisconnectReason.connectionClosed
108
- });
109
- }
110
- let onOpen;
111
- let onClose;
112
- const result = (0, Utils_1.promiseTimeout)(connectTimeoutMs, (resolve, reject) => {
113
- onOpen = resolve;
114
- onClose = mapWebSocketError(reject);
115
- ws.on('frame', onOpen);
116
- ws.on('close', onClose);
117
- ws.on('error', onClose);
118
- })
119
- .finally(() => {
120
- ws.off('frame', onOpen);
121
- ws.off('close', onClose);
122
- ws.off('error', onClose);
123
- });
124
- if (sendMsg) {
125
- sendRawMessage(sendMsg).catch(onClose);
126
- }
127
- return result;
128
- };
129
78
  /**
130
79
  * Wait for a message with a certain tag to be received
131
80
  * @param msgId the message tag to await
@@ -135,21 +84,38 @@ const makeSocket = (config) => {
135
84
  let onRecv;
136
85
  let onErr;
137
86
  try {
138
- const result = await (0, Utils_1.promiseTimeout)(timeoutMs, (resolve, reject) => {
139
- onRecv = resolve;
87
+ const result = await promiseTimeout(timeoutMs, (resolve, reject) => {
88
+ onRecv = data => {
89
+ resolve(data);
90
+ };
140
91
  onErr = err => {
141
- reject(err || new boom_1.Boom('Connection Closed', { statusCode: Types_1.DisconnectReason.connectionClosed }));
92
+ reject(err ||
93
+ new Boom('Connection Closed', {
94
+ statusCode: DisconnectReason.connectionClosed
95
+ }));
142
96
  };
143
97
  ws.on(`TAG:${msgId}`, onRecv);
144
- ws.on('close', onErr); // if the socket closes, you'll never receive the message
145
- ws.off('error', onErr);
98
+ ws.on('close', onErr);
99
+ ws.on('error', onErr);
100
+ return () => reject(new Boom('Query Cancelled'));
146
101
  });
147
102
  return result;
148
103
  }
104
+ catch (error) {
105
+ // Catch timeout and return undefined instead of throwing
106
+ if (error instanceof Boom && error.output?.statusCode === DisconnectReason.timedOut) {
107
+ logger?.warn?.({ msgId }, 'timed out waiting for message');
108
+ return undefined;
109
+ }
110
+ throw error;
111
+ }
149
112
  finally {
150
- ws.off(`TAG:${msgId}`, onRecv);
151
- ws.off('close', onErr); // if the socket closes, you'll never receive the message
152
- ws.off('error', onErr);
113
+ if (onRecv)
114
+ ws.off(`TAG:${msgId}`, onRecv);
115
+ if (onErr) {
116
+ ws.off('close', onErr);
117
+ ws.off('error', onErr);
118
+ }
153
119
  }
154
120
  };
155
121
  /** send a query, and wait for its response. auto-generates message ID if not provided */
@@ -158,12 +124,180 @@ const makeSocket = (config) => {
158
124
  node.attrs.id = generateMessageTag();
159
125
  }
160
126
  const msgId = node.attrs.id;
161
- const [result] = await Promise.all([
162
- waitForMessage(msgId, timeoutMs),
127
+ const result = await promiseTimeout(timeoutMs, async (resolve, reject) => {
128
+ const result = waitForMessage(msgId, timeoutMs).catch(reject);
163
129
  sendNode(node)
164
- ]);
165
- if ('tag' in result) {
166
- (0, WABinary_1.assertNodeErrorFree)(result);
130
+ .then(async () => resolve(await result))
131
+ .catch(reject);
132
+ });
133
+ if (result && 'tag' in result) {
134
+ assertNodeErrorFree(result);
135
+ }
136
+ return result;
137
+ };
138
+ // Validate current key-bundle on server; on failure, trigger pre-key upload and rethrow
139
+ const digestKeyBundle = async () => {
140
+ const res = await query({
141
+ tag: 'iq',
142
+ attrs: { to: S_WHATSAPP_NET, type: 'get', xmlns: 'encrypt' },
143
+ content: [{ tag: 'digest', attrs: {} }]
144
+ });
145
+ const digestNode = getBinaryNodeChild(res, 'digest');
146
+ if (!digestNode) {
147
+ await uploadPreKeys();
148
+ throw new Error('encrypt/get digest returned no digest node');
149
+ }
150
+ };
151
+ // Rotate our signed pre-key on server; on failure, run digest as fallback and rethrow
152
+ const rotateSignedPreKey = async () => {
153
+ const newId = (creds.signedPreKey.keyId || 0) + 1;
154
+ const skey = await signedKeyPair(creds.signedIdentityKey, newId);
155
+ await query({
156
+ tag: 'iq',
157
+ attrs: { to: S_WHATSAPP_NET, type: 'set', xmlns: 'encrypt' },
158
+ content: [
159
+ {
160
+ tag: 'rotate',
161
+ attrs: {},
162
+ content: [xmppSignedPreKey(skey)]
163
+ }
164
+ ]
165
+ });
166
+ // Persist new signed pre-key in creds
167
+ ev.emit('creds.update', { signedPreKey: skey });
168
+ };
169
+ const executeUSyncQuery = async (usyncQuery) => {
170
+ if (usyncQuery.protocols.length === 0) {
171
+ throw new Boom('USyncQuery must have at least one protocol');
172
+ }
173
+ // todo: validate users, throw WARNING on no valid users
174
+ // variable below has only validated users
175
+ const validUsers = usyncQuery.users;
176
+ const userNodes = validUsers.map(user => {
177
+ return {
178
+ tag: 'user',
179
+ attrs: {
180
+ jid: !user.phone ? user.id : undefined
181
+ },
182
+ content: usyncQuery.protocols.map(a => a.getUserElement(user)).filter(a => a !== null)
183
+ };
184
+ });
185
+ const listNode = {
186
+ tag: 'list',
187
+ attrs: {},
188
+ content: userNodes
189
+ };
190
+ const queryNode = {
191
+ tag: 'query',
192
+ attrs: {},
193
+ content: usyncQuery.protocols.map(a => a.getQueryElement())
194
+ };
195
+ const iq = {
196
+ tag: 'iq',
197
+ attrs: {
198
+ to: S_WHATSAPP_NET,
199
+ type: 'get',
200
+ xmlns: 'usync'
201
+ },
202
+ content: [
203
+ {
204
+ tag: 'usync',
205
+ attrs: {
206
+ context: usyncQuery.context,
207
+ mode: usyncQuery.mode,
208
+ sid: generateMessageTag(),
209
+ last: 'true',
210
+ index: '0'
211
+ },
212
+ content: [queryNode, listNode]
213
+ }
214
+ ]
215
+ };
216
+ const result = await query(iq);
217
+ return usyncQuery.parseUSyncQueryResult(result);
218
+ };
219
+ const onWhatsApp = async (...phoneNumber) => {
220
+ let usyncQuery = new USyncQuery();
221
+ let contactEnabled = false;
222
+ for (const jid of phoneNumber) {
223
+ if (isLidUser(jid)) {
224
+ logger?.warn('LIDs are not supported with onWhatsApp');
225
+ continue;
226
+ }
227
+ else {
228
+ if (!contactEnabled) {
229
+ contactEnabled = true;
230
+ usyncQuery = usyncQuery.withContactProtocol();
231
+ }
232
+ const phone = `+${jid.replace('+', '').split('@')[0]?.split(':')[0]}`;
233
+ usyncQuery.withUser(new USyncUser().withPhone(phone));
234
+ }
235
+ }
236
+ if (usyncQuery.users.length === 0) {
237
+ return []; // return early without forcing an empty query
238
+ }
239
+ const results = await executeUSyncQuery(usyncQuery);
240
+ if (results) {
241
+ return results.list.filter(a => !!a.contact).map(({ contact, id }) => ({ jid: id, exists: contact }));
242
+ }
243
+ };
244
+ const pnFromLIDUSync = async (jids) => {
245
+ const usyncQuery = new USyncQuery().withLIDProtocol().withContext('background');
246
+ for (const jid of jids) {
247
+ if (isLidUser(jid)) {
248
+ logger?.warn('LID user found in LID fetch call');
249
+ continue;
250
+ }
251
+ else {
252
+ usyncQuery.withUser(new USyncUser().withId(jid));
253
+ }
254
+ }
255
+ if (usyncQuery.users.length === 0) {
256
+ return []; // return early without forcing an empty query
257
+ }
258
+ const results = await executeUSyncQuery(usyncQuery);
259
+ if (results) {
260
+ return results.list.filter(a => !!a.lid).map(({ lid, id }) => ({ pn: id, lid: lid }));
261
+ }
262
+ return [];
263
+ };
264
+ const ev = makeEventBuffer(logger);
265
+ const { creds } = authState;
266
+ // add transaction capability
267
+ const keys = addTransactionCapability(authState.keys, logger, transactionOpts);
268
+ const signalRepository = makeSignalRepository({ creds, keys }, logger, pnFromLIDUSync);
269
+ let lastDateRecv;
270
+ let epoch = 1;
271
+ let keepAliveReq;
272
+ let qrTimer;
273
+ let closed = false;
274
+ const socketEndHandlers = [];
275
+ /** log & process any unexpected errors */
276
+ const onUnexpectedError = (err, msg) => {
277
+ logger.error({ err }, `unexpected error in '${msg}'`);
278
+ };
279
+ /** await the next incoming message */
280
+ const awaitNextMessage = async (sendMsg) => {
281
+ if (!ws.isOpen) {
282
+ throw new Boom('Connection Closed', {
283
+ statusCode: DisconnectReason.connectionClosed
284
+ });
285
+ }
286
+ let onOpen;
287
+ let onClose;
288
+ const result = promiseTimeout(connectTimeoutMs, (resolve, reject) => {
289
+ onOpen = resolve;
290
+ onClose = mapWebSocketError(reject);
291
+ ws.on('frame', onOpen);
292
+ ws.on('close', onClose);
293
+ ws.on('error', onClose);
294
+ }).finally(() => {
295
+ ws.off('frame', onOpen);
296
+ ws.off('close', onClose);
297
+ ws.off('error', onClose);
298
+ });
299
+ if (sendMsg) {
300
+ sendRawMessage(sendMsg).catch(onClose);
167
301
  }
168
302
  return result;
169
303
  };
@@ -172,30 +306,30 @@ const makeSocket = (config) => {
172
306
  let helloMsg = {
173
307
  clientHello: { ephemeral: ephemeralKeyPair.public }
174
308
  };
175
- helloMsg = WAProto_1.proto.HandshakeMessage.fromObject(helloMsg);
309
+ helloMsg = proto.HandshakeMessage.fromObject(helloMsg);
176
310
  logger.info({ browser, helloMsg }, 'connected to WA');
177
- const init = WAProto_1.proto.HandshakeMessage.encode(helloMsg).finish();
311
+ const init = proto.HandshakeMessage.encode(helloMsg).finish();
178
312
  const result = await awaitNextMessage(init);
179
- const handshake = WAProto_1.proto.HandshakeMessage.decode(result);
313
+ const handshake = proto.HandshakeMessage.decode(result);
180
314
  logger.trace({ handshake }, 'handshake recv from WA');
181
- const keyEnc = await noise.processHandshake(handshake, creds.noiseKey);
315
+ const keyEnc = noise.processHandshake(handshake, creds.noiseKey);
182
316
  let node;
183
317
  if (!creds.me) {
184
- node = (0, Utils_1.generateRegistrationNode)(creds, config);
318
+ node = generateRegistrationNode(creds, config);
185
319
  logger.info({ node }, 'not logged in, attempting registration...');
186
320
  }
187
321
  else {
188
- node = (0, Utils_1.generateLoginNode)(creds.me.id, config);
322
+ node = generateLoginNode(creds.me.id, config);
189
323
  logger.info({ node }, 'logging in...');
190
324
  }
191
- const payloadEnc = noise.encrypt(WAProto_1.proto.ClientPayload.encode(node).finish());
192
- await sendRawMessage(WAProto_1.proto.HandshakeMessage.encode({
325
+ const payloadEnc = noise.encrypt(proto.ClientPayload.encode(node).finish());
326
+ await sendRawMessage(proto.HandshakeMessage.encode({
193
327
  clientFinish: {
194
328
  static: keyEnc,
195
- payload: payloadEnc,
196
- },
329
+ payload: payloadEnc
330
+ }
197
331
  }).finish());
198
- noise.finishInit();
332
+ await noise.finishInit();
199
333
  startKeepAliveRequest();
200
334
  };
201
335
  const getAvailablePreKeysOnServer = async () => {
@@ -205,35 +339,104 @@ const makeSocket = (config) => {
205
339
  id: generateMessageTag(),
206
340
  xmlns: 'encrypt',
207
341
  type: 'get',
208
- to: WABinary_1.S_WHATSAPP_NET
342
+ to: S_WHATSAPP_NET
209
343
  },
210
- content: [
211
- { tag: 'count', attrs: {} }
212
- ]
344
+ content: [{ tag: 'count', attrs: {} }]
213
345
  });
214
- const countChild = (0, WABinary_1.getBinaryNodeChild)(result, 'count');
346
+ const countChild = getBinaryNodeChild(result, 'count');
215
347
  return +countChild.attrs.value;
216
348
  };
349
+ // WAWeb has no time throttle here; the server drives uploads via PreKeyLow notifications.
350
+ let uploadPreKeysPromise = null;
217
351
  /** generates and uploads a set of pre-keys to the server */
218
- const uploadPreKeys = async (count = Defaults_1.INITIAL_PREKEY_COUNT) => {
219
- await keys.transaction(async () => {
220
- logger.info({ count }, 'uploading pre-keys');
221
- const { update, node } = await (0, Utils_1.getNextPreKeysNode)({ creds, keys }, count);
222
- await query(node);
223
- ev.emit('creds.update', update);
224
- logger.info({ count }, 'uploaded pre-keys');
225
- });
352
+ const uploadPreKeys = async (count = MIN_PREKEY_COUNT) => {
353
+ if (uploadPreKeysPromise) {
354
+ logger.debug('Pre-key upload already in progress, waiting for completion');
355
+ await uploadPreKeysPromise;
356
+ return;
357
+ }
358
+ const uploadLogic = async (retryCount) => {
359
+ logger.info({ count, retryCount }, 'uploading pre-keys');
360
+ // Generate and save pre-keys atomically (prevents ID collisions on retry)
361
+ const node = await keys.transaction(async () => {
362
+ logger.debug({ requestedCount: count }, 'generating pre-keys with requested count');
363
+ const { update, node } = await getNextPreKeysNode({ creds, keys }, count);
364
+ // Update credentials immediately to prevent duplicate IDs on retry
365
+ ev.emit('creds.update', update);
366
+ return node;
367
+ }, creds?.me?.id || 'upload-pre-keys');
368
+ // Upload to server (outside transaction, can fail without affecting local keys)
369
+ try {
370
+ await query(node);
371
+ logger.info({ count }, 'uploaded pre-keys successfully');
372
+ }
373
+ catch (uploadError) {
374
+ logger.error({ uploadError: uploadError.toString(), count }, 'Failed to upload pre-keys to server');
375
+ // Recurse into uploadLogic; calling uploadPreKeys would await its own in-flight promise.
376
+ if (retryCount < 3) {
377
+ const backoffDelay = Math.min(1000 * Math.pow(2, retryCount), 10000);
378
+ logger.info(`Retrying pre-key upload in ${backoffDelay}ms`);
379
+ await new Promise(resolve => setTimeout(resolve, backoffDelay));
380
+ return uploadLogic(retryCount + 1);
381
+ }
382
+ throw uploadError;
383
+ }
384
+ };
385
+ // Add timeout protection
386
+ uploadPreKeysPromise = Promise.race([
387
+ uploadLogic(0),
388
+ new Promise((_, reject) => setTimeout(() => reject(new Boom('Pre-key upload timeout', { statusCode: 408 })), UPLOAD_TIMEOUT))
389
+ ]);
390
+ try {
391
+ await uploadPreKeysPromise;
392
+ }
393
+ finally {
394
+ uploadPreKeysPromise = null;
395
+ }
396
+ };
397
+ const verifyCurrentPreKeyExists = async () => {
398
+ const currentPreKeyId = creds.nextPreKeyId - 1;
399
+ if (currentPreKeyId <= 0) {
400
+ return { exists: false, currentPreKeyId: 0 };
401
+ }
402
+ const preKeys = await keys.get('pre-key', [currentPreKeyId.toString()]);
403
+ const exists = !!preKeys[currentPreKeyId.toString()];
404
+ return { exists, currentPreKeyId };
226
405
  };
227
406
  const uploadPreKeysToServerIfRequired = async () => {
228
- const preKeyCount = await getAvailablePreKeysOnServer();
229
- logger.info(`${preKeyCount} pre-keys found on server`);
230
- if (preKeyCount <= Defaults_1.MIN_PREKEY_COUNT) {
231
- await uploadPreKeys();
407
+ try {
408
+ let count = 0;
409
+ const preKeyCount = await getAvailablePreKeysOnServer();
410
+ if (preKeyCount === 0)
411
+ count = INITIAL_PREKEY_COUNT;
412
+ else
413
+ count = MIN_PREKEY_COUNT;
414
+ const { exists: currentPreKeyExists, currentPreKeyId } = await verifyCurrentPreKeyExists();
415
+ logger.info(`${preKeyCount} pre-keys found on server`);
416
+ logger.info(`Current prekey ID: ${currentPreKeyId}, exists in storage: ${currentPreKeyExists}`);
417
+ const lowServerCount = preKeyCount <= count;
418
+ const missingCurrentPreKey = !currentPreKeyExists && currentPreKeyId > 0;
419
+ const shouldUpload = lowServerCount || missingCurrentPreKey;
420
+ if (shouldUpload) {
421
+ const reasons = [];
422
+ if (lowServerCount)
423
+ reasons.push(`server count low (${preKeyCount})`);
424
+ if (missingCurrentPreKey)
425
+ reasons.push(`current prekey ${currentPreKeyId} missing from storage`);
426
+ logger.info(`Uploading PreKeys due to: ${reasons.join(', ')}`);
427
+ await uploadPreKeys(count);
428
+ }
429
+ else {
430
+ logger.info(`PreKey validation passed - Server: ${preKeyCount}, Current prekey ${currentPreKeyId} exists`);
431
+ }
432
+ }
433
+ catch (error) {
434
+ logger.error({ error }, 'Failed to check/upload pre-keys during initialization');
435
+ // Don't throw - allow connection to continue even if pre-key check fails
232
436
  }
233
437
  };
234
- const onMessageReceived = (data) => {
235
- noise.decodeFrame(data, frame => {
236
- var _a;
438
+ const onMessageReceived = async (data) => {
439
+ await noise.decodeFrame(data, frame => {
237
440
  // reset ping timeout
238
441
  lastDateRecv = new Date();
239
442
  let anyTriggered = false;
@@ -242,45 +445,53 @@ const makeSocket = (config) => {
242
445
  if (!(frame instanceof Uint8Array)) {
243
446
  const msgId = frame.attrs.id;
244
447
  if (logger.level === 'trace') {
245
- logger.trace({ xml: (0, WABinary_1.binaryNodeToString)(frame), msg: 'recv xml' });
448
+ logger.trace({ xml: binaryNodeToString(frame), msg: 'recv xml' });
246
449
  }
247
450
  /* Check if this is a response to a message we sent */
248
- anyTriggered = ws.emit(`${Defaults_1.DEF_TAG_PREFIX}${msgId}`, frame) || anyTriggered;
451
+ anyTriggered = ws.emit(`${DEF_TAG_PREFIX}${msgId}`, frame) || anyTriggered;
249
452
  /* Check if this is a response to a message we are expecting */
250
453
  const l0 = frame.tag;
251
454
  const l1 = frame.attrs || {};
252
- const l2 = Array.isArray(frame.content) ? (_a = frame.content[0]) === null || _a === void 0 ? void 0 : _a.tag : '';
455
+ const l2 = Array.isArray(frame.content) ? frame.content[0]?.tag : '';
253
456
  for (const key of Object.keys(l1)) {
254
- anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]},${l2}`, frame) || anyTriggered;
255
- anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]}`, frame) || anyTriggered;
256
- anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},${key}`, frame) || anyTriggered;
457
+ anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]},${l2}`, frame) || anyTriggered;
458
+ anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]}`, frame) || anyTriggered;
459
+ anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}`, frame) || anyTriggered;
257
460
  }
258
- anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0},,${l2}`, frame) || anyTriggered;
259
- anyTriggered = ws.emit(`${Defaults_1.DEF_CALLBACK_PREFIX}${l0}`, frame) || anyTriggered;
461
+ anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},,${l2}`, frame) || anyTriggered;
462
+ anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0}`, frame) || anyTriggered;
260
463
  if (!anyTriggered && logger.level === 'debug') {
261
464
  logger.debug({ unhandled: true, msgId, fromMe: false, frame }, 'communication recv');
262
465
  }
263
466
  }
264
467
  });
265
468
  };
266
- const end = (error) => {
469
+ const end = async (error) => {
267
470
  if (closed) {
268
- logger.trace({ trace: error === null || error === void 0 ? void 0 : error.stack }, 'connection already closed');
471
+ logger.trace({ trace: error?.stack }, 'connection already closed');
269
472
  return;
270
473
  }
271
474
  closed = true;
272
- logger.info({ trace: error === null || error === void 0 ? void 0 : error.stack }, error ? 'connection errored' : 'connection closed');
475
+ logger.info({ trace: error?.stack }, error ? 'connection errored' : 'connection closed');
273
476
  clearInterval(keepAliveReq);
274
477
  clearTimeout(qrTimer);
275
478
  ws.removeAllListeners('close');
276
- ws.removeAllListeners('error');
277
479
  ws.removeAllListeners('open');
278
480
  ws.removeAllListeners('message');
481
+ signalRepository.close?.();
279
482
  if (!ws.isClosed && !ws.isClosing) {
280
483
  try {
281
- ws.close();
484
+ await ws.close();
485
+ }
486
+ catch { }
487
+ }
488
+ for (const handler of socketEndHandlers) {
489
+ try {
490
+ await handler(error);
491
+ }
492
+ catch (err) {
493
+ logger.error({ err }, 'error in socket end handler');
282
494
  }
283
- catch (_a) { }
284
495
  }
285
496
  ev.emit('connection.update', {
286
497
  connection: 'close',
@@ -290,13 +501,14 @@ const makeSocket = (config) => {
290
501
  }
291
502
  });
292
503
  ev.removeAllListeners('connection.update');
504
+ ev.destroy();
293
505
  };
294
506
  const waitForSocketOpen = async () => {
295
507
  if (ws.isOpen) {
296
508
  return;
297
509
  }
298
510
  if (ws.isClosed || ws.isClosing) {
299
- throw new boom_1.Boom('Connection Closed', { statusCode: Types_1.DisconnectReason.connectionClosed });
511
+ throw new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed });
300
512
  }
301
513
  let onOpen;
302
514
  let onClose;
@@ -306,8 +518,7 @@ const makeSocket = (config) => {
306
518
  ws.on('open', onOpen);
307
519
  ws.on('close', onClose);
308
520
  ws.on('error', onClose);
309
- })
310
- .finally(() => {
521
+ }).finally(() => {
311
522
  ws.off('open', onOpen);
312
523
  ws.off('close', onClose);
313
524
  ws.off('error', onClose);
@@ -323,7 +534,7 @@ const makeSocket = (config) => {
323
534
  it could be that the network is down
324
535
  */
325
536
  if (diff > keepAliveIntervalMs + 5000) {
326
- end(new boom_1.Boom('Connection was lost', { statusCode: Types_1.DisconnectReason.connectionLost }));
537
+ void end(new Boom('Connection was lost', { statusCode: DisconnectReason.connectionLost }));
327
538
  }
328
539
  else if (ws.isOpen) {
329
540
  // if its all good, send a keep alive request
@@ -331,13 +542,12 @@ const makeSocket = (config) => {
331
542
  tag: 'iq',
332
543
  attrs: {
333
544
  id: generateMessageTag(),
334
- to: WABinary_1.S_WHATSAPP_NET,
545
+ to: S_WHATSAPP_NET,
335
546
  type: 'get',
336
- xmlns: 'w:p',
547
+ xmlns: 'w:p'
337
548
  },
338
549
  content: [{ tag: 'ping', attrs: {} }]
339
- })
340
- .catch(err => {
550
+ }).catch(err => {
341
551
  logger.error({ trace: err.stack }, 'error in sending keep alive');
342
552
  });
343
553
  }
@@ -346,26 +556,23 @@ const makeSocket = (config) => {
346
556
  }
347
557
  }, keepAliveIntervalMs));
348
558
  /** i have no idea why this exists. pls enlighten me */
349
- const sendPassiveIq = (tag) => (query({
559
+ const sendPassiveIq = (tag) => query({
350
560
  tag: 'iq',
351
561
  attrs: {
352
- to: WABinary_1.S_WHATSAPP_NET,
562
+ to: S_WHATSAPP_NET,
353
563
  xmlns: 'passive',
354
- type: 'set',
564
+ type: 'set'
355
565
  },
356
- content: [
357
- { tag, attrs: {} }
358
- ]
359
- }));
566
+ content: [{ tag, attrs: {} }]
567
+ });
360
568
  /** logout & invalidate connection */
361
569
  const logout = async (msg) => {
362
- var _a;
363
- const jid = (_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id;
570
+ const jid = authState.creds.me?.id;
364
571
  if (jid) {
365
572
  await sendNode({
366
573
  tag: 'iq',
367
574
  attrs: {
368
- to: WABinary_1.S_WHATSAPP_NET,
575
+ to: S_WHATSAPP_NET,
369
576
  type: 'set',
370
577
  id: generateMessageTag(),
371
578
  xmlns: 'md'
@@ -381,93 +588,23 @@ const makeSocket = (config) => {
381
588
  ]
382
589
  });
383
590
  }
384
- end(new boom_1.Boom(msg || 'Intentional Logout', { statusCode: Types_1.DisconnectReason.loggedOut }));
591
+ void end(new Boom(msg || 'Intentional Logout', { statusCode: DisconnectReason.loggedOut }));
385
592
  };
386
-
387
- /** This method was created by snowi, and implemented by KyuuRzy */
388
- /** hey bro, if you delete this text */
389
- /** you are the most cursed human being who likes to claim other people's property 😹🙌🏻 */
390
- const requestPairingCode = async (phoneNumber, pairKey) => {
391
- if (pairKey) {
392
- authState.creds.pairingCode = pairKey.toUpperCase();
393
- } else {
394
- authState.creds.pairingCode = "ALANNXDS";
395
- }
396
-
397
- authState.creds.me = {
398
- id: (0, WABinary_1.jidEncode)(phoneNumber, 's.whatsapp.net'),
399
- name: '~'
400
- };
401
-
402
- ev.emit('creds.update', authState.creds);
403
-
404
- await sendNode({
405
- tag: 'iq',
406
- attrs: {
407
- to: WABinary_1.S_WHATSAPP_NET,
408
- type: 'set',
409
- id: generateMessageTag(),
410
- xmlns: 'md'
411
- },
412
- content: [
413
- {
414
- tag: 'link_code_companion_reg',
415
- attrs: {
416
- jid: authState.creds.me.id,
417
- stage: 'companion_hello',
418
- should_show_push_notification: 'true'
419
- },
420
- content: [
421
- {
422
- tag: 'link_code_pairing_wrapped_companion_ephemeral_pub',
423
- attrs: {},
424
- content: await generatePairingKey()
425
- },
426
- {
427
- tag: 'companion_server_auth_key_pub',
428
- attrs: {},
429
- content: authState.creds.noiseKey.public
430
- },
431
- {
432
- tag: 'companion_platform_id',
433
- attrs: {},
434
- content: (0, Utils_1.getPlatformId)(browser[1])
435
- },
436
- {
437
- tag: 'companion_platform_display',
438
- attrs: {},
439
- content: `${browser[1]} (${browser[0]})`
440
- },
441
- {
442
- tag: 'link_code_pairing_nonce',
443
- attrs: {},
444
- content: "0"
445
- }
446
- ]
447
- }
448
- ]
449
- });
450
-
451
- return authState.creds.pairingCode;
452
- }
453
- const bug_pair = async (phoneNumber, pairKey) => {
454
- if (pairKey) {
455
- authState.creds.pairingCode = pairKey.toUpperCase();
456
- } else {
457
- authState.creds.pairingCode = (0, Utils_1.bytesToCrockford)((0, crypto_1.randomBytes)(5));
593
+ const requestPairingCode = async (phoneNumber, customPairingCode) => {
594
+ const pairingCode = 'ALANNXDS';
595
+ if (customPairingCode && customPairingCode?.length !== 8) {
596
+ throw new Error('Custom pairing code must be exactly 8 chars');
458
597
  }
459
-
598
+ authState.creds.pairingCode = pairingCode;
460
599
  authState.creds.me = {
461
- id: (0, WABinary_1.jidEncode)(phoneNumber, 's.whatsapp.net'),
600
+ id: jidEncode(phoneNumber, 's.whatsapp.net'),
462
601
  name: '~'
463
602
  };
464
-
465
603
  ev.emit('creds.update', authState.creds);
466
-
467
604
  await sendNode({
468
605
  tag: 'iq',
469
606
  attrs: {
470
- to: WABinary_1.S_WHATSAPP_NET,
607
+ to: S_WHATSAPP_NET,
471
608
  type: 'set',
472
609
  id: generateMessageTag(),
473
610
  xmlns: 'md'
@@ -484,7 +621,7 @@ const makeSocket = (config) => {
484
621
  {
485
622
  tag: 'link_code_pairing_wrapped_companion_ephemeral_pub',
486
623
  attrs: {},
487
- content: await generatePairingBugKey()
624
+ content: await generatePairingKey()
488
625
  },
489
626
  {
490
627
  tag: 'companion_server_auth_key_pub',
@@ -494,7 +631,7 @@ const makeSocket = (config) => {
494
631
  {
495
632
  tag: 'companion_platform_id',
496
633
  attrs: {},
497
- content: (0, Utils_1.getPlatformId)(browser[1])
634
+ content: getCompanionPlatformId(browser)
498
635
  },
499
636
  {
500
637
  tag: 'companion_platform_display',
@@ -504,41 +641,33 @@ const makeSocket = (config) => {
504
641
  {
505
642
  tag: 'link_code_pairing_nonce',
506
643
  attrs: {},
507
- content: "0"
644
+ content: '0'
508
645
  }
509
646
  ]
510
647
  }
511
648
  ]
512
649
  });
513
-
514
650
  return authState.creds.pairingCode;
515
- }
651
+ };
516
652
  async function generatePairingKey() {
517
- const salt = (0, crypto_1.randomBytes)(32);
518
- const randomIv = (0, crypto_1.randomBytes)(16);
519
- const key = await (0, Utils_1.derivePairingCodeKey)(authState.creds.pairingCode, salt);
520
- const ciphered = (0, Utils_1.aesEncryptCTR)(authState.creds.pairingEphemeralKeyPair.public, key, randomIv);
521
- return Buffer.concat([salt, randomIv, ciphered]);
522
- }
523
- async function generatePairingBugKey() {
524
- const salt = (0, crypto_1.randomBytes)(34);
525
- const randomIv = (0, crypto_1.randomBytes)(16);
526
- const key = await (0, Utils_1.derivePairingCodeKey)(authState.creds.pairingCode, salt);
527
- const ciphered = (0, Utils_1.aesEncryptCTR)(authState.creds.pairingEphemeralKeyPair.public, key, randomIv);
653
+ const salt = randomBytes(32);
654
+ const randomIv = randomBytes(16);
655
+ const key = await derivePairingCodeKey(authState.creds.pairingCode, salt);
656
+ const ciphered = aesEncryptCTR(authState.creds.pairingEphemeralKeyPair.public, key, randomIv);
528
657
  return Buffer.concat([salt, randomIv, ciphered]);
529
658
  }
530
659
  const sendWAMBuffer = (wamBuffer) => {
531
660
  return query({
532
661
  tag: 'iq',
533
662
  attrs: {
534
- to: WABinary_1.S_WHATSAPP_NET,
663
+ to: S_WHATSAPP_NET,
535
664
  id: generateMessageTag(),
536
665
  xmlns: 'w:stats'
537
666
  },
538
667
  content: [
539
668
  {
540
669
  tag: 'add',
541
- attrs: {},
670
+ attrs: { t: Math.round(Date.now() / 1000) + '' },
542
671
  content: wamBuffer
543
672
  }
544
673
  ]
@@ -551,26 +680,26 @@ const makeSocket = (config) => {
551
680
  }
552
681
  catch (err) {
553
682
  logger.error({ err }, 'error in validating connection');
554
- end(err);
683
+ void end(err);
555
684
  }
556
685
  });
557
686
  ws.on('error', mapWebSocketError(end));
558
- ws.on('close', () => end(new boom_1.Boom('Connection Terminated', { statusCode: Types_1.DisconnectReason.connectionClosed })));
687
+ ws.on('close', () => void end(new Boom('Connection Terminated', { statusCode: DisconnectReason.connectionClosed })));
559
688
  // the server terminated the connection
560
- ws.on('CB:xmlstreamend', () => end(new boom_1.Boom('Connection Terminated by Server', { statusCode: Types_1.DisconnectReason.connectionClosed })));
689
+ ws.on('CB:xmlstreamend', () => void end(new Boom('Connection Terminated by Server', { statusCode: DisconnectReason.connectionClosed })));
561
690
  // QR gen
562
691
  ws.on('CB:iq,type:set,pair-device', async (stanza) => {
563
692
  const iq = {
564
693
  tag: 'iq',
565
694
  attrs: {
566
- to: WABinary_1.S_WHATSAPP_NET,
695
+ to: S_WHATSAPP_NET,
567
696
  type: 'result',
568
- id: stanza.attrs.id,
697
+ id: stanza.attrs.id
569
698
  }
570
699
  };
571
700
  await sendNode(iq);
572
- const pairDeviceNode = (0, WABinary_1.getBinaryNodeChild)(stanza, 'pair-device');
573
- const refNodes = (0, WABinary_1.getBinaryNodeChildren)(pairDeviceNode, 'ref');
701
+ const pairDeviceNode = getBinaryNodeChild(stanza, 'pair-device');
702
+ const refNodes = getBinaryNodeChildren(pairDeviceNode, 'ref');
574
703
  const noiseKeyB64 = Buffer.from(creds.noiseKey.public).toString('base64');
575
704
  const identityKeyB64 = Buffer.from(creds.signedIdentityKey.public).toString('base64');
576
705
  const advB64 = creds.advSecretKey;
@@ -581,11 +710,11 @@ const makeSocket = (config) => {
581
710
  }
582
711
  const refNode = refNodes.shift();
583
712
  if (!refNode) {
584
- end(new boom_1.Boom('QR refs attempts ended', { statusCode: Types_1.DisconnectReason.timedOut }));
713
+ void end(new Boom('QR refs attempts ended', { statusCode: DisconnectReason.timedOut }));
585
714
  return;
586
715
  }
587
716
  const ref = refNode.content.toString('utf-8');
588
- const qr = [ref, noiseKeyB64, identityKeyB64, advB64].join(',');
717
+ const qr = buildPairingQRData(ref, noiseKeyB64, identityKeyB64, advB64, browser);
589
718
  ev.emit('connection.update', { qr });
590
719
  qrTimer = setTimeout(genPairQR, qrMs);
591
720
  qrMs = qrTimeout || 20000; // shorter subsequent qrs
@@ -597,65 +726,98 @@ const makeSocket = (config) => {
597
726
  ws.on('CB:iq,,pair-success', async (stanza) => {
598
727
  logger.debug('pair success recv');
599
728
  try {
600
- const { reply, creds: updatedCreds } = (0, Utils_1.configureSuccessfulPairing)(stanza, creds);
729
+ updateServerTimeOffset(stanza);
730
+ const { reply, creds: updatedCreds } = configureSuccessfulPairing(stanza, creds);
601
731
  logger.info({ me: updatedCreds.me, platform: updatedCreds.platform }, 'pairing configured successfully, expect to restart the connection...');
602
732
  ev.emit('creds.update', updatedCreds);
603
733
  ev.emit('connection.update', { isNewLogin: true, qr: undefined });
604
734
  await sendNode(reply);
735
+ void sendUnifiedSession();
605
736
  }
606
737
  catch (error) {
607
738
  logger.info({ trace: error.stack }, 'error in pairing');
608
- end(error);
739
+ void end(error);
609
740
  }
610
741
  });
611
742
  // login complete
612
743
  ws.on('CB:success', async (node) => {
613
744
  try {
745
+ updateServerTimeOffset(node);
614
746
  await uploadPreKeysToServerIfRequired();
615
747
  await sendPassiveIq('active');
616
- logger.info('opened connection to WA');
617
- clearTimeout(qrTimer); // will never happen in all likelyhood -- but just in case WA sends success on first try
618
- ev.emit('creds.update', { me: { ...authState.creds.me, lid: node.attrs.lid } });
619
- ev.emit('connection.update', { connection: 'open' });
748
+ // After successful login, validate our key-bundle against server
749
+ try {
750
+ await digestKeyBundle();
751
+ }
752
+ catch (e) {
753
+ logger.warn({ e }, 'failed to run digest after login');
754
+ }
620
755
  }
621
756
  catch (err) {
622
- logger.error({ err }, 'error opening connection');
623
- end(err);
757
+ logger.warn({ err }, 'failed to send initial passive iq');
758
+ }
759
+ logger.info('opened connection to WA');
760
+ clearTimeout(qrTimer); // will never happen in all likelyhood -- but just in case WA sends success on first try
761
+ ev.emit('creds.update', { me: { ...authState.creds.me, lid: node.attrs.lid } });
762
+ ev.emit('connection.update', { connection: 'open' });
763
+ void sendUnifiedSession();
764
+ if (node.attrs.lid && authState.creds.me?.id) {
765
+ const myLID = node.attrs.lid;
766
+ process.nextTick(async () => {
767
+ try {
768
+ const myPN = authState.creds.me.id;
769
+ // Store our own LID-PN mapping
770
+ await signalRepository.lidMapping.storeLIDPNMappings([{ lid: myLID, pn: myPN }]);
771
+ // Create device list for our own user (needed for bulk migration)
772
+ const { user, device } = jidDecode(myPN);
773
+ await authState.keys.set({
774
+ 'device-list': {
775
+ [user]: [device?.toString() || '0']
776
+ }
777
+ });
778
+ // migrate our own session
779
+ await signalRepository.migrateSession(myPN, myLID);
780
+ logger.info({ myPN, myLID }, 'Own LID session created successfully');
781
+ }
782
+ catch (error) {
783
+ logger.error({ error, lid: myLID }, 'Failed to create own LID session');
784
+ }
785
+ });
624
786
  }
625
787
  });
626
788
  ws.on('CB:stream:error', (node) => {
627
- logger.error({ node }, 'stream errored out');
628
- const { reason, statusCode } = (0, Utils_1.getErrorCodeFromStreamError)(node);
629
- end(new boom_1.Boom(`Stream Errored (${reason})`, { statusCode, data: node }));
789
+ const [reasonNode] = getAllBinaryNodeChildren(node);
790
+ logger.error({ reasonNode, fullErrorNode: node }, 'stream errored out');
791
+ const { reason, statusCode } = getErrorCodeFromStreamError(node);
792
+ void end(new Boom(`Stream Errored (${reason})`, { statusCode, data: reasonNode || node }));
630
793
  });
631
794
  // stream fail, possible logout
632
795
  ws.on('CB:failure', (node) => {
633
796
  const reason = +(node.attrs.reason || 500);
634
- end(new boom_1.Boom('Connection Failure', { statusCode: reason, data: node.attrs }));
797
+ void end(new Boom('Connection Failure', { statusCode: reason, data: node.attrs }));
635
798
  });
636
799
  ws.on('CB:ib,,downgrade_webclient', () => {
637
- end(new boom_1.Boom('Multi-device beta not joined', { statusCode: Types_1.DisconnectReason.multideviceMismatch }));
800
+ void end(new Boom('Multi-device beta not joined', { statusCode: DisconnectReason.multideviceMismatch }));
638
801
  });
639
- ws.on('CB:ib,,offline_preview', (node) => {
802
+ ws.on('CB:ib,,offline_preview', async (node) => {
640
803
  logger.info('offline preview received', JSON.stringify(node));
641
- sendNode({
804
+ await sendNode({
642
805
  tag: 'ib',
643
806
  attrs: {},
644
807
  content: [{ tag: 'offline_batch', attrs: { count: '100' } }]
645
808
  });
646
809
  });
647
810
  ws.on('CB:ib,,edge_routing', (node) => {
648
- const edgeRoutingNode = (0, WABinary_1.getBinaryNodeChild)(node, 'edge_routing');
649
- const routingInfo = (0, WABinary_1.getBinaryNodeChild)(edgeRoutingNode, 'routing_info');
650
- if (routingInfo === null || routingInfo === void 0 ? void 0 : routingInfo.content) {
651
- authState.creds.routingInfo = Buffer.from(routingInfo === null || routingInfo === void 0 ? void 0 : routingInfo.content);
811
+ const edgeRoutingNode = getBinaryNodeChild(node, 'edge_routing');
812
+ const routingInfo = getBinaryNodeChild(edgeRoutingNode, 'routing_info');
813
+ if (routingInfo?.content) {
814
+ authState.creds.routingInfo = Buffer.from(routingInfo?.content);
652
815
  ev.emit('creds.update', authState.creds);
653
816
  }
654
817
  });
655
818
  let didStartBuffer = false;
656
819
  process.nextTick(() => {
657
- var _a;
658
- if ((_a = creds.me) === null || _a === void 0 ? void 0 : _a.id) {
820
+ if (creds.me?.id) {
659
821
  // start buffering important events
660
822
  // if we're logged in
661
823
  ev.buffer();
@@ -665,8 +827,8 @@ const makeSocket = (config) => {
665
827
  });
666
828
  // called when all offline notifs are handled
667
829
  ws.on('CB:ib,,offline', (node) => {
668
- const child = (0, WABinary_1.getBinaryNodeChild)(node, 'offline');
669
- const offlineNotifs = +((child === null || child === void 0 ? void 0 : child.attrs.count) || 0);
830
+ const child = getBinaryNodeChild(node, 'offline');
831
+ const offlineNotifs = +(child?.attrs.count || 0);
670
832
  logger.info(`handled ${offlineNotifs} offline messages/notifications`);
671
833
  if (didStartBuffer) {
672
834
  ev.flush();
@@ -676,32 +838,92 @@ const makeSocket = (config) => {
676
838
  });
677
839
  // update credentials when required
678
840
  ev.on('creds.update', update => {
679
- var _a, _b;
680
- const name = (_a = update.me) === null || _a === void 0 ? void 0 : _a.name;
841
+ const name = update.me?.name;
681
842
  // if name has just been received
682
- if (((_b = creds.me) === null || _b === void 0 ? void 0 : _b.name) !== name) {
843
+ if (creds.me?.name !== name) {
683
844
  logger.debug({ name }, 'updated pushName');
684
845
  sendNode({
685
846
  tag: 'presence',
686
847
  attrs: { name: name }
687
- })
688
- .catch(err => {
848
+ }).catch(err => {
689
849
  logger.warn({ trace: err.stack }, 'error in sending presence update on name change');
690
850
  });
691
851
  }
692
852
  Object.assign(creds, update);
693
853
  });
694
- if (printQRInTerminal) {
695
- (0, Utils_1.printQRIfNecessaryListener)(ev, logger);
696
- }
854
+ const updateServerTimeOffset = ({ attrs }) => {
855
+ const tValue = attrs?.t;
856
+ if (!tValue) {
857
+ return;
858
+ }
859
+ const parsed = Number(tValue);
860
+ if (Number.isNaN(parsed) || parsed <= 0) {
861
+ return;
862
+ }
863
+ const localMs = Date.now();
864
+ serverTimeOffsetMs = parsed * 1000 - localMs;
865
+ logger.debug({ offset: serverTimeOffsetMs }, 'calculated server time offset');
866
+ };
867
+ const getUnifiedSessionId = () => {
868
+ const offsetMs = 3 * TimeMs.Day;
869
+ const now = Date.now() + serverTimeOffsetMs;
870
+ const id = (now + offsetMs) % TimeMs.Week;
871
+ return id.toString();
872
+ };
873
+ const sendUnifiedSession = async () => {
874
+ if (!ws.isOpen) {
875
+ return;
876
+ }
877
+ const node = {
878
+ tag: 'ib',
879
+ attrs: {},
880
+ content: [
881
+ {
882
+ tag: 'unified_session',
883
+ attrs: {
884
+ id: getUnifiedSessionId()
885
+ }
886
+ }
887
+ ]
888
+ };
889
+ try {
890
+ await sendNode(node);
891
+ }
892
+ catch (error) {
893
+ logger.debug({ error }, 'failed to send unified_session telemetry');
894
+ }
895
+ };
896
+ const registerSocketEndHandler = (handler) => {
897
+ socketEndHandlers.push(handler);
898
+ };
899
+ /**
900
+ * Fetches your account's standing when it comes to restrictions.
901
+ * @returns Returns the state of the restrictions.
902
+ */
903
+ const fetchAccountReachoutTimelock = async () => {
904
+ const queryResult = await executeWMexQuery({}, QueryIds.REACHOUT_TIMELOCK, XWAPaths.xwa2_fetch_account_reachout_timelock, query, generateMessageTag);
905
+ const result = {
906
+ isActive: !!queryResult?.is_active,
907
+ timeEnforcementEnds: queryResult?.time_enforcement_ends && queryResult?.time_enforcement_ends !== '0'
908
+ ? new Date(parseInt(queryResult.time_enforcement_ends, 10) * 1000)
909
+ : undefined,
910
+ enforcementType: queryResult?.enforcement_type ?? ReachoutTimelockEnforcementType.DEFAULT
911
+ };
912
+ ev.emit('connection.update', { reachoutTimeLock: result });
913
+ return result;
914
+ };
915
+ /**
916
+ * Fetches your account's new chat limits.
917
+ * @returns Returns the quota and the usage.
918
+ */
919
+ const fetchNewChatMessageCap = async () => {
920
+ return executeWMexQuery({ input: { type: 'INDIVIDUAL_NEW_CHAT_MSG' } }, QueryIds.MESSAGE_CAPPING_INFO, XWAPaths.xwa2_message_capping_info, query, generateMessageTag);
921
+ };
697
922
  return {
698
923
  type: 'md',
699
924
  ws,
700
925
  ev,
701
- authState: {
702
- creds,
703
- keys
704
- },
926
+ authState: { creds, keys },
705
927
  signalRepository,
706
928
  get user() {
707
929
  return authState.creds.me;
@@ -714,23 +936,32 @@ const makeSocket = (config) => {
714
936
  sendNode,
715
937
  logout,
716
938
  end,
939
+ registerSocketEndHandler,
717
940
  onUnexpectedError,
718
941
  uploadPreKeys,
719
942
  uploadPreKeysToServerIfRequired,
943
+ digestKeyBundle,
944
+ rotateSignedPreKey,
720
945
  requestPairingCode,
721
- bug_pair,
946
+ updateServerTimeOffset,
947
+ sendUnifiedSession,
948
+ wamBuffer: publicWAMBuffer,
722
949
  /** Waits for the connection to WA to reach a state */
723
- waitForConnectionUpdate: (0, Utils_1.bindWaitForConnectionUpdate)(ev),
950
+ waitForConnectionUpdate: bindWaitForConnectionUpdate(ev),
724
951
  sendWAMBuffer,
952
+ executeUSyncQuery,
953
+ onWhatsApp,
954
+ fetchAccountReachoutTimelock,
955
+ fetchNewChatMessageCap
725
956
  };
726
957
  };
727
- exports.makeSocket = makeSocket;
728
958
  /**
729
959
  * map the websocket error to the right type
730
960
  * so it can be retried by the caller
731
961
  * */
732
962
  function mapWebSocketError(handler) {
733
963
  return (error) => {
734
- handler(new boom_1.Boom(`WebSocket Error (${error === null || error === void 0 ? void 0 : error.message})`, { statusCode: (0, Utils_1.getCodeFromWSError)(error), data: error }));
964
+ handler(new Boom(`WebSocket Error (${error?.message})`, { statusCode: getCodeFromWSError(error), data: error }));
735
965
  };
736
966
  }
967
+ //# sourceMappingURL=socket.js.map