@tonconnect/sdk 3.3.1 → 3.4.0-beta.1

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.
package/lib/cjs/index.cjs CHANGED
@@ -169,6 +169,14 @@ class WalletMissingRequiredFeaturesError extends TonConnectError {
169
169
  }
170
170
  }
171
171
 
172
+ class WalletWrongNetworkError extends TonConnectError {
173
+ constructor(message, options) {
174
+ super(message, options);
175
+ this.name = 'WalletWrongNetworkError';
176
+ Object.setPrototypeOf(this, WalletWrongNetworkError.prototype);
177
+ }
178
+ }
179
+
172
180
  function isWalletConnectionSourceJS(value) {
173
181
  return 'jsBridgeKey' in value;
174
182
  }
@@ -395,6 +403,12 @@ function isTelegramUrl(link) {
395
403
  const url = new URL(link);
396
404
  return url.protocol === 'tg:' || url.hostname === 't.me';
397
405
  }
406
+ function isConnectUrl(link) {
407
+ if (!link) {
408
+ return false;
409
+ }
410
+ return link.includes('ton_addr') || link.includes('ton--5Faddr');
411
+ }
398
412
  function encodeTelegramUrlParameters(parameters) {
399
413
  return parameters
400
414
  .replaceAll('.', '%2E')
@@ -404,6 +418,15 @@ function encodeTelegramUrlParameters(parameters) {
404
418
  .replaceAll('=', '__')
405
419
  .replaceAll('%', '--');
406
420
  }
421
+ function decodeTelegramUrlParameters(parameters) {
422
+ return parameters
423
+ .replaceAll('--', '%')
424
+ .replaceAll('__', '=')
425
+ .replaceAll('-', '&')
426
+ .replaceAll('%5F', '_')
427
+ .replaceAll('%2D', '-')
428
+ .replaceAll('%2E', '.');
429
+ }
407
430
 
408
431
  /**
409
432
  * Delays the execution of code for a specified number of milliseconds.
@@ -638,7 +661,7 @@ class BridgeGateway {
638
661
  const eventSource = this.eventSource.current();
639
662
  return (eventSource === null || eventSource === void 0 ? void 0 : eventSource.readyState) === EventSource.CONNECTING;
640
663
  }
641
- constructor(storage, bridgeUrl, sessionId, listener, errorsListener) {
664
+ constructor(storage, bridgeUrl, sessionId, listener, errorsListener, analyticsManager) {
642
665
  this.bridgeUrl = bridgeUrl;
643
666
  this.sessionId = sessionId;
644
667
  this.listener = listener;
@@ -649,7 +672,7 @@ class BridgeGateway {
649
672
  this.defaultTtl = 300;
650
673
  this.defaultReconnectDelay = 2000;
651
674
  this.defaultResendDelay = 5000;
652
- this.eventSource = createResource((signal, openingDeadlineMS) => __awaiter(this, void 0, void 0, function* () {
675
+ this.eventSource = createResource((signal, openingDeadlineMS, traceId) => __awaiter(this, void 0, void 0, function* () {
653
676
  const eventSourceConfig = {
654
677
  bridgeUrl: this.bridgeUrl,
655
678
  ssePath: this.ssePath,
@@ -658,17 +681,41 @@ class BridgeGateway {
658
681
  errorHandler: this.errorsHandler.bind(this),
659
682
  messageHandler: this.messagesHandler.bind(this),
660
683
  signal: signal,
661
- openingDeadlineMS: openingDeadlineMS
684
+ openingDeadlineMS: openingDeadlineMS,
685
+ traceId
662
686
  };
663
687
  return yield createEventSource(eventSourceConfig);
664
688
  }), (resource) => __awaiter(this, void 0, void 0, function* () {
665
689
  resource.close();
666
690
  }));
667
691
  this.bridgeGatewayStorage = new HttpBridgeGatewayStorage(storage, bridgeUrl);
692
+ this.analytics = analyticsManager === null || analyticsManager === void 0 ? void 0 : analyticsManager.scoped({
693
+ bridge_url: bridgeUrl,
694
+ client_id: sessionId
695
+ });
668
696
  }
669
697
  registerSession(options) {
670
698
  return __awaiter(this, void 0, void 0, function* () {
671
- yield this.eventSource.create(options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.openingDeadlineMS);
699
+ var _a, _b, _c;
700
+ try {
701
+ (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.emitBridgeClientConnectStarted({
702
+ trace_id: options === null || options === void 0 ? void 0 : options.traceId
703
+ });
704
+ const connectionStarted = Date.now();
705
+ yield this.eventSource.create(options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.openingDeadlineMS, options === null || options === void 0 ? void 0 : options.traceId);
706
+ const bridgeConnectDuration = Date.now() - connectionStarted;
707
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitBridgeClientConnectEstablished({
708
+ bridge_connect_duration: bridgeConnectDuration,
709
+ trace_id: options === null || options === void 0 ? void 0 : options.traceId
710
+ });
711
+ }
712
+ catch (error) {
713
+ (_c = this.analytics) === null || _c === void 0 ? void 0 : _c.emitBridgeClientConnectError({
714
+ trace_id: options === null || options === void 0 ? void 0 : options.traceId,
715
+ error_message: String(error)
716
+ });
717
+ throw error;
718
+ }
672
719
  });
673
720
  }
674
721
  send(message, receiver, topic, ttlOrOptions) {
@@ -683,12 +730,16 @@ class BridgeGateway {
683
730
  options.ttl = ttlOrOptions === null || ttlOrOptions === void 0 ? void 0 : ttlOrOptions.ttl;
684
731
  options.signal = ttlOrOptions === null || ttlOrOptions === void 0 ? void 0 : ttlOrOptions.signal;
685
732
  options.attempts = ttlOrOptions === null || ttlOrOptions === void 0 ? void 0 : ttlOrOptions.attempts;
733
+ options.traceId = ttlOrOptions === null || ttlOrOptions === void 0 ? void 0 : ttlOrOptions.traceId;
686
734
  }
687
735
  const url = new URL(addPathToUrl(this.bridgeUrl, this.postPath));
688
736
  url.searchParams.append('client_id', this.sessionId);
689
737
  url.searchParams.append('to', receiver);
690
738
  url.searchParams.append('ttl', ((options === null || options === void 0 ? void 0 : options.ttl) || this.defaultTtl).toString());
691
739
  url.searchParams.append('topic', topic);
740
+ if (options === null || options === void 0 ? void 0 : options.traceId) {
741
+ url.searchParams.append('trace_id', options.traceId);
742
+ }
692
743
  const body = protocol.Base64.encode(message);
693
744
  yield callForSuccess((options) => __awaiter(this, void 0, void 0, function* () {
694
745
  const response = yield this.post(url, body, options.signal);
@@ -767,7 +818,12 @@ class BridgeGateway {
767
818
  }
768
819
  let bridgeIncomingMessage;
769
820
  try {
770
- bridgeIncomingMessage = JSON.parse(e.data);
821
+ const bridgeIncomingMessageRaw = JSON.parse(e.data);
822
+ bridgeIncomingMessage = {
823
+ message: bridgeIncomingMessageRaw.message,
824
+ from: bridgeIncomingMessageRaw.from,
825
+ traceId: bridgeIncomingMessageRaw.trace_id
826
+ };
771
827
  }
772
828
  catch (_) {
773
829
  throw new TonConnectError(`Bridge message parse failed, message ${e.data}`);
@@ -796,6 +852,9 @@ function createEventSource(config) {
796
852
  if (lastEventId) {
797
853
  url.searchParams.append('last_event_id', lastEventId);
798
854
  }
855
+ if (config.traceId) {
856
+ url.searchParams.append('trace_id', config.traceId);
857
+ }
799
858
  if (signal.aborted) {
800
859
  reject(new TonConnectError('Bridge connection aborted'));
801
860
  return;
@@ -1021,20 +1080,189 @@ class BridgeConnectionStorage {
1021
1080
 
1022
1081
  const PROTOCOL_VERSION = 2;
1023
1082
 
1083
+ /**
1084
+ * The MIT License (MIT)
1085
+ *
1086
+ * Copyright (c) 2010-2020 Robert Kieffer and other contributors
1087
+ *
1088
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
1089
+ *
1090
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1091
+ *
1092
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1093
+ */
1094
+ // Unique ID creation requires a high quality random # generator. In the browser we therefore
1095
+ // require the crypto API and do not support built-in fallback to lower quality random number
1096
+ // generators (like Math.random()).
1097
+ let getRandomValues;
1098
+ const rnds8 = new Uint8Array(16);
1099
+ function rng() {
1100
+ // lazy load so that environments that need to polyfill have a chance to do so
1101
+ if (!getRandomValues) {
1102
+ if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
1103
+ throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
1104
+ }
1105
+ getRandomValues = crypto.getRandomValues.bind(crypto);
1106
+ }
1107
+ return getRandomValues(rnds8);
1108
+ }
1109
+
1110
+ /**
1111
+ * The MIT License (MIT)
1112
+ *
1113
+ * Copyright (c) 2010-2020 Robert Kieffer and other contributors
1114
+ *
1115
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
1116
+ *
1117
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1118
+ *
1119
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1120
+ */
1121
+ /**
1122
+ * Convert array of 16 byte values to UUID string format of the form:
1123
+ * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
1124
+ */
1125
+ const byteToHex = [];
1126
+ for (let i = 0; i < 256; ++i) {
1127
+ byteToHex.push((i + 0x100).toString(16).slice(1));
1128
+ }
1129
+ function unsafeStringify(arr, offset = 0) {
1130
+ // Note: Be careful editing this code! It's been tuned for performance
1131
+ // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
1132
+ //
1133
+ // Note to future-self: No, you can't remove the `toLowerCase()` call.
1134
+ // REF: https://github.com/uuidjs/uuid/pull/677#issuecomment-1757351351
1135
+ return (byteToHex[arr[offset + 0]] +
1136
+ byteToHex[arr[offset + 1]] +
1137
+ byteToHex[arr[offset + 2]] +
1138
+ byteToHex[arr[offset + 3]] +
1139
+ '-' +
1140
+ byteToHex[arr[offset + 4]] +
1141
+ byteToHex[arr[offset + 5]] +
1142
+ '-' +
1143
+ byteToHex[arr[offset + 6]] +
1144
+ byteToHex[arr[offset + 7]] +
1145
+ '-' +
1146
+ byteToHex[arr[offset + 8]] +
1147
+ byteToHex[arr[offset + 9]] +
1148
+ '-' +
1149
+ byteToHex[arr[offset + 10]] +
1150
+ byteToHex[arr[offset + 11]] +
1151
+ byteToHex[arr[offset + 12]] +
1152
+ byteToHex[arr[offset + 13]] +
1153
+ byteToHex[arr[offset + 14]] +
1154
+ byteToHex[arr[offset + 15]]).toLowerCase();
1155
+ }
1156
+
1157
+ /**
1158
+ * The MIT License (MIT)
1159
+ *
1160
+ * Copyright (c) 2010-2020 Robert Kieffer and other contributors
1161
+ *
1162
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
1163
+ *
1164
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1165
+ *
1166
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1167
+ */
1168
+ const _state = {};
1169
+ function UUIDv7(options, buf, offset) {
1170
+ var _a, _b, _c;
1171
+ let bytes;
1172
+ if (options) {
1173
+ // With options: Make UUID independent of internal state
1174
+ bytes = v7Bytes((_c = (_a = options.random) !== null && _a !== void 0 ? _a : (_b = options.rng) === null || _b === void 0 ? void 0 : _b.call(options)) !== null && _c !== void 0 ? _c : rng(), options.msecs, options.seq, buf, offset);
1175
+ }
1176
+ else {
1177
+ // No options: Use internal state
1178
+ const now = Date.now();
1179
+ const rnds = rng();
1180
+ updateV7State(_state, now, rnds);
1181
+ bytes = v7Bytes(rnds, _state.msecs, _state.seq, buf, offset);
1182
+ }
1183
+ return buf !== null && buf !== void 0 ? buf : unsafeStringify(bytes);
1184
+ }
1185
+ // (Private!) Do not use. This method is only exported for testing purposes
1186
+ // and may change without notice.
1187
+ function updateV7State(state, now, rnds) {
1188
+ var _a, _b;
1189
+ (_a = state.msecs) !== null && _a !== void 0 ? _a : (state.msecs = -Infinity);
1190
+ (_b = state.seq) !== null && _b !== void 0 ? _b : (state.seq = 0);
1191
+ if (now > state.msecs) {
1192
+ // Time has moved on! Pick a new random sequence number
1193
+ state.seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9];
1194
+ state.msecs = now;
1195
+ }
1196
+ else {
1197
+ // Bump sequence counter w/ 32-bit rollover
1198
+ state.seq = (state.seq + 1) | 0;
1199
+ // In case of rollover, bump timestamp to preserve monotonicity. This is
1200
+ // allowed by the RFC and should self-correct as the system clock catches
1201
+ // up. See https://www.rfc-editor.org/rfc/rfc9562.html#section-6.2-9.4
1202
+ if (state.seq === 0) {
1203
+ state.msecs++;
1204
+ }
1205
+ }
1206
+ return state;
1207
+ }
1208
+ function v7Bytes(rnds, msecs, seq, buf, offset = 0) {
1209
+ if (rnds.length < 16) {
1210
+ throw new Error('Random bytes length must be >= 16');
1211
+ }
1212
+ if (!buf) {
1213
+ buf = new Uint8Array(16);
1214
+ offset = 0;
1215
+ }
1216
+ else {
1217
+ if (offset < 0 || offset + 16 > buf.length) {
1218
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
1219
+ }
1220
+ }
1221
+ // Defaults
1222
+ msecs !== null && msecs !== void 0 ? msecs : (msecs = Date.now());
1223
+ seq !== null && seq !== void 0 ? seq : (seq = ((rnds[6] * 0x7f) << 24) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]);
1224
+ // byte 0-5: timestamp (48 bits)
1225
+ buf[offset++] = (msecs / 0x10000000000) & 0xff;
1226
+ buf[offset++] = (msecs / 0x100000000) & 0xff;
1227
+ buf[offset++] = (msecs / 0x1000000) & 0xff;
1228
+ buf[offset++] = (msecs / 0x10000) & 0xff;
1229
+ buf[offset++] = (msecs / 0x100) & 0xff;
1230
+ buf[offset++] = msecs & 0xff;
1231
+ // byte 6: `version` (4 bits) | sequence bits 28-31 (4 bits)
1232
+ buf[offset++] = 0x70 | ((seq >>> 28) & 0x0f);
1233
+ // byte 7: sequence bits 20-27 (8 bits)
1234
+ buf[offset++] = (seq >>> 20) & 0xff;
1235
+ // byte 8: `variant` (2 bits) | sequence bits 14-19 (6 bits)
1236
+ buf[offset++] = 0x80 | ((seq >>> 14) & 0x3f);
1237
+ // byte 9: sequence bits 6-13 (8 bits)
1238
+ buf[offset++] = (seq >>> 6) & 0xff;
1239
+ // byte 10: sequence bits 0-5 (6 bits) | random (2 bits)
1240
+ buf[offset++] = ((seq << 2) & 0xff) | (rnds[10] & 0x03);
1241
+ // bytes 11-15: random (40 bits)
1242
+ buf[offset++] = rnds[11];
1243
+ buf[offset++] = rnds[12];
1244
+ buf[offset++] = rnds[13];
1245
+ buf[offset++] = rnds[14];
1246
+ buf[offset++] = rnds[15];
1247
+ return buf;
1248
+ }
1249
+
1024
1250
  class BridgeProvider {
1025
- static fromStorage(storage) {
1251
+ static fromStorage(storage, analyticsManager) {
1026
1252
  return __awaiter(this, void 0, void 0, function* () {
1027
1253
  const bridgeConnectionStorage = new BridgeConnectionStorage(storage);
1028
1254
  const connection = yield bridgeConnectionStorage.getHttpConnection();
1029
1255
  if (isPendingConnectionHttp(connection)) {
1030
- return new BridgeProvider(storage, connection.connectionSource);
1256
+ return new BridgeProvider(storage, connection.connectionSource, analyticsManager);
1031
1257
  }
1032
- return new BridgeProvider(storage, { bridgeUrl: connection.session.bridgeUrl });
1258
+ return new BridgeProvider(storage, { bridgeUrl: connection.session.bridgeUrl }, analyticsManager);
1033
1259
  });
1034
1260
  }
1035
- constructor(storage, walletConnectionSource) {
1261
+ constructor(storage, walletConnectionSource, analyticsManager) {
1262
+ var _a;
1036
1263
  this.storage = storage;
1037
1264
  this.walletConnectionSource = walletConnectionSource;
1265
+ this.analyticsManager = analyticsManager;
1038
1266
  this.type = 'http';
1039
1267
  this.standardUniversalLink = 'tc://';
1040
1268
  this.pendingRequests = new Map();
@@ -1045,11 +1273,13 @@ class BridgeProvider {
1045
1273
  this.defaultOpeningDeadlineMS = 12000;
1046
1274
  this.defaultRetryTimeoutMS = 2000;
1047
1275
  this.connectionStorage = new BridgeConnectionStorage(storage);
1276
+ this.analytics = (_a = this.analyticsManager) === null || _a === void 0 ? void 0 : _a.scoped();
1048
1277
  }
1049
1278
  connect(message, options) {
1050
- var _a;
1279
+ var _a, _b;
1280
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1051
1281
  const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
1052
- (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
1282
+ (_b = this.abortController) === null || _b === void 0 ? void 0 : _b.abort();
1053
1283
  this.abortController = abortController;
1054
1284
  this.closeGateways();
1055
1285
  const sessionCrypto = new protocol.SessionCrypto();
@@ -1073,7 +1303,8 @@ class BridgeProvider {
1073
1303
  var _a;
1074
1304
  return this.openGateways(sessionCrypto, {
1075
1305
  openingDeadlineMS: (_a = options === null || options === void 0 ? void 0 : options.openingDeadlineMS) !== null && _a !== void 0 ? _a : this.defaultOpeningDeadlineMS,
1076
- signal: _options === null || _options === void 0 ? void 0 : _options.signal
1306
+ signal: _options === null || _options === void 0 ? void 0 : _options.signal,
1307
+ traceId
1077
1308
  });
1078
1309
  }, {
1079
1310
  attempts: Number.MAX_SAFE_INTEGER,
@@ -1085,13 +1316,14 @@ class BridgeProvider {
1085
1316
  this.walletConnectionSource.universalLink
1086
1317
  ? this.walletConnectionSource.universalLink
1087
1318
  : this.standardUniversalLink;
1088
- return this.generateUniversalLink(universalLink, message);
1319
+ return this.generateUniversalLink(universalLink, message, { traceId });
1089
1320
  }
1090
1321
  restoreConnection(options) {
1091
1322
  return __awaiter(this, void 0, void 0, function* () {
1092
- var _a, _b;
1323
+ var _a, _b, _c;
1324
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1093
1325
  const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
1094
- (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
1326
+ (_b = this.abortController) === null || _b === void 0 ? void 0 : _b.abort();
1095
1327
  this.abortController = abortController;
1096
1328
  if (abortController.signal.aborted) {
1097
1329
  return;
@@ -1104,7 +1336,7 @@ class BridgeProvider {
1104
1336
  if (abortController.signal.aborted) {
1105
1337
  return;
1106
1338
  }
1107
- const openingDeadlineMS = (_b = options === null || options === void 0 ? void 0 : options.openingDeadlineMS) !== null && _b !== void 0 ? _b : this.defaultOpeningDeadlineMS;
1339
+ const openingDeadlineMS = (_c = options === null || options === void 0 ? void 0 : options.openingDeadlineMS) !== null && _c !== void 0 ? _c : this.defaultOpeningDeadlineMS;
1108
1340
  if (isPendingConnectionHttp(storedConnection)) {
1109
1341
  this.session = {
1110
1342
  sessionCrypto: storedConnection.sessionCrypto,
@@ -1114,7 +1346,8 @@ class BridgeProvider {
1114
1346
  };
1115
1347
  return yield this.openGateways(storedConnection.sessionCrypto, {
1116
1348
  openingDeadlineMS: openingDeadlineMS,
1117
- signal: abortController === null || abortController === void 0 ? void 0 : abortController.signal
1349
+ signal: abortController === null || abortController === void 0 ? void 0 : abortController.signal,
1350
+ traceId: options === null || options === void 0 ? void 0 : options.traceId
1118
1351
  });
1119
1352
  }
1120
1353
  if (Array.isArray(this.walletConnectionSource)) {
@@ -1125,17 +1358,18 @@ class BridgeProvider {
1125
1358
  logDebug('Gateway is already opened, closing previous gateway');
1126
1359
  yield this.gateway.close();
1127
1360
  }
1128
- this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, storedConnection.session.sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
1361
+ this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, storedConnection.session.sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this), this.analyticsManager);
1129
1362
  if (abortController.signal.aborted) {
1130
1363
  return;
1131
1364
  }
1132
1365
  // notify listeners about stored connection
1133
- this.listeners.forEach(listener => listener(storedConnection.connectEvent));
1366
+ this.listeners.forEach(listener => listener(Object.assign(Object.assign({}, storedConnection.connectEvent), { traceId })));
1134
1367
  // wait for the connection to be opened
1135
1368
  try {
1136
1369
  yield callForSuccess(options => this.gateway.registerSession({
1137
1370
  openingDeadlineMS: openingDeadlineMS,
1138
- signal: options.signal
1371
+ signal: options.signal,
1372
+ traceId
1139
1373
  }), {
1140
1374
  attempts: Number.MAX_SAFE_INTEGER,
1141
1375
  delayMs: this.defaultRetryTimeoutMS,
@@ -1143,12 +1377,13 @@ class BridgeProvider {
1143
1377
  });
1144
1378
  }
1145
1379
  catch (e) {
1146
- yield this.disconnect({ signal: abortController.signal });
1380
+ yield this.disconnect({ signal: abortController.signal, traceId });
1147
1381
  return;
1148
1382
  }
1149
1383
  });
1150
1384
  }
1151
1385
  sendRequest(request, optionsOrOnRequestSent) {
1386
+ var _a;
1152
1387
  // TODO: remove deprecated method
1153
1388
  const options = {};
1154
1389
  if (typeof optionsOrOnRequestSent === 'function') {
@@ -1158,9 +1393,11 @@ class BridgeProvider {
1158
1393
  options.onRequestSent = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.onRequestSent;
1159
1394
  options.signal = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.signal;
1160
1395
  options.attempts = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.attempts;
1396
+ options.traceId = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.traceId;
1161
1397
  }
1398
+ (_a = options.traceId) !== null && _a !== void 0 ? _a : (options.traceId = UUIDv7());
1162
1399
  return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
1163
- var _a;
1400
+ var _a, _b;
1164
1401
  if (!this.gateway || !this.session || !('walletPublicKey' in this.session)) {
1165
1402
  throw new TonConnectError('Trying to send bridge request without session');
1166
1403
  }
@@ -1169,8 +1406,20 @@ class BridgeProvider {
1169
1406
  logDebug('Send http-bridge request:', Object.assign(Object.assign({}, request), { id }));
1170
1407
  const encodedRequest = this.session.sessionCrypto.encrypt(JSON.stringify(Object.assign(Object.assign({}, request), { id })), protocol.hexToByteArray(this.session.walletPublicKey));
1171
1408
  try {
1172
- yield this.gateway.send(encodedRequest, this.session.walletPublicKey, request.method, { attempts: options === null || options === void 0 ? void 0 : options.attempts, signal: options === null || options === void 0 ? void 0 : options.signal });
1173
- (_a = options === null || options === void 0 ? void 0 : options.onRequestSent) === null || _a === void 0 ? void 0 : _a.call(options);
1409
+ (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.emitBridgeClientMessageSent({
1410
+ bridge_url: this.gateway.bridgeUrl,
1411
+ client_id: this.session.sessionCrypto.sessionId,
1412
+ wallet_id: this.session.walletPublicKey,
1413
+ message_id: id,
1414
+ request_type: request.method,
1415
+ trace_id: options.traceId
1416
+ });
1417
+ yield this.gateway.send(encodedRequest, this.session.walletPublicKey, request.method, {
1418
+ attempts: options === null || options === void 0 ? void 0 : options.attempts,
1419
+ signal: options === null || options === void 0 ? void 0 : options.signal,
1420
+ traceId: options.traceId
1421
+ });
1422
+ (_b = options === null || options === void 0 ? void 0 : options.onRequestSent) === null || _b === void 0 ? void 0 : _b.call(options);
1174
1423
  this.pendingRequests.set(id.toString(), resolve);
1175
1424
  }
1176
1425
  catch (e) {
@@ -1186,6 +1435,8 @@ class BridgeProvider {
1186
1435
  }
1187
1436
  disconnect(options) {
1188
1437
  return __awaiter(this, void 0, void 0, function* () {
1438
+ var _a;
1439
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1189
1440
  return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
1190
1441
  let called = false;
1191
1442
  let timeoutId = null;
@@ -1204,7 +1455,8 @@ class BridgeProvider {
1204
1455
  yield this.sendRequest({ method: 'disconnect', params: [] }, {
1205
1456
  onRequestSent: onRequestSent,
1206
1457
  signal: abortController.signal,
1207
- attempts: 1
1458
+ attempts: 1,
1459
+ traceId
1208
1460
  });
1209
1461
  }
1210
1462
  catch (e) {
@@ -1260,8 +1512,32 @@ class BridgeProvider {
1260
1512
  }
1261
1513
  gatewayListener(bridgeIncomingMessage) {
1262
1514
  return __awaiter(this, void 0, void 0, function* () {
1263
- const walletMessage = JSON.parse(this.session.sessionCrypto.decrypt(protocol.Base64.decode(bridgeIncomingMessage.message).toUint8Array(), protocol.hexToByteArray(bridgeIncomingMessage.from)));
1515
+ var _a, _b, _c;
1516
+ const traceId = (_a = bridgeIncomingMessage.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1517
+ let walletMessage;
1518
+ try {
1519
+ walletMessage = JSON.parse(this.session.sessionCrypto.decrypt(protocol.Base64.decode(bridgeIncomingMessage.message).toUint8Array(), protocol.hexToByteArray(bridgeIncomingMessage.from)));
1520
+ }
1521
+ catch (err) {
1522
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitBridgeClientMessageDecodeError({
1523
+ bridge_url: this.session.bridgeUrl,
1524
+ client_id: this.session.sessionCrypto.sessionId,
1525
+ wallet_id: bridgeIncomingMessage.from,
1526
+ error_message: String(err),
1527
+ trace_id: bridgeIncomingMessage === null || bridgeIncomingMessage === void 0 ? void 0 : bridgeIncomingMessage.traceId
1528
+ });
1529
+ throw err;
1530
+ }
1264
1531
  logDebug('Wallet message received:', walletMessage);
1532
+ const requestType = 'event' in walletMessage ? walletMessage.event : '';
1533
+ (_c = this.analytics) === null || _c === void 0 ? void 0 : _c.emitBridgeClientMessageReceived({
1534
+ bridge_url: this.session.bridgeUrl,
1535
+ client_id: this.session.sessionCrypto.sessionId,
1536
+ wallet_id: bridgeIncomingMessage.from,
1537
+ message_id: String(walletMessage.id),
1538
+ request_type: requestType,
1539
+ trace_id: bridgeIncomingMessage === null || bridgeIncomingMessage === void 0 ? void 0 : bridgeIncomingMessage.traceId
1540
+ });
1265
1541
  if (!('event' in walletMessage)) {
1266
1542
  const id = walletMessage.id.toString();
1267
1543
  const resolve = this.pendingRequests.get(id);
@@ -1269,7 +1545,7 @@ class BridgeProvider {
1269
1545
  logDebug(`Response id ${id} doesn't match any request's id`);
1270
1546
  return;
1271
1547
  }
1272
- resolve(walletMessage);
1548
+ resolve(Object.assign(Object.assign({}, walletMessage), { traceId }));
1273
1549
  this.pendingRequests.delete(id);
1274
1550
  return;
1275
1551
  }
@@ -1292,7 +1568,7 @@ class BridgeProvider {
1292
1568
  logDebug(`Removing bridge and session: received disconnect event`);
1293
1569
  yield this.removeBridgeAndSession();
1294
1570
  }
1295
- listeners.forEach(listener => listener(walletMessage));
1571
+ listeners.forEach(listener => listener(Object.assign(Object.assign({}, walletMessage), { traceId })));
1296
1572
  });
1297
1573
  }
1298
1574
  gatewayErrorsListener(e) {
@@ -1320,21 +1596,22 @@ class BridgeProvider {
1320
1596
  yield this.connectionStorage.removeConnection();
1321
1597
  });
1322
1598
  }
1323
- generateUniversalLink(universalLink, message) {
1599
+ generateUniversalLink(universalLink, message, options) {
1324
1600
  if (isTelegramUrl(universalLink)) {
1325
- return this.generateTGUniversalLink(universalLink, message);
1601
+ return this.generateTGUniversalLink(universalLink, message, options);
1326
1602
  }
1327
- return this.generateRegularUniversalLink(universalLink, message);
1603
+ return this.generateRegularUniversalLink(universalLink, message, options);
1328
1604
  }
1329
- generateRegularUniversalLink(universalLink, message) {
1605
+ generateRegularUniversalLink(universalLink, message, options) {
1330
1606
  const url = new URL(universalLink);
1331
1607
  url.searchParams.append('v', PROTOCOL_VERSION.toString());
1332
1608
  url.searchParams.append('id', this.session.sessionCrypto.sessionId);
1609
+ url.searchParams.append('trace_id', options.traceId);
1333
1610
  url.searchParams.append('r', JSON.stringify(message));
1334
1611
  return url.toString();
1335
1612
  }
1336
- generateTGUniversalLink(universalLink, message) {
1337
- const urlToWrap = this.generateRegularUniversalLink('about:blank', message);
1613
+ generateTGUniversalLink(universalLink, message, options) {
1614
+ const urlToWrap = this.generateRegularUniversalLink('about:blank', message, options);
1338
1615
  const linkParams = urlToWrap.split('?')[1];
1339
1616
  const startapp = 'tonconnect-' + encodeTelegramUrlParameters(linkParams);
1340
1617
  // TODO: Remove this line after all dApps and the wallets-list.json have been updated
@@ -1354,12 +1631,14 @@ class BridgeProvider {
1354
1631
  }
1355
1632
  openGateways(sessionCrypto, options) {
1356
1633
  return __awaiter(this, void 0, void 0, function* () {
1634
+ var _a;
1635
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1357
1636
  if (Array.isArray(this.walletConnectionSource)) {
1358
1637
  // close all gateways before opening new ones
1359
1638
  this.pendingGateways.map(bridge => bridge.close().catch());
1360
1639
  // open new gateways
1361
1640
  this.pendingGateways = this.walletConnectionSource.map(source => {
1362
- const gateway = new BridgeGateway(this.storage, source.bridgeUrl, sessionCrypto.sessionId, () => { }, () => { });
1641
+ const gateway = new BridgeGateway(this.storage, source.bridgeUrl, sessionCrypto.sessionId, () => { }, () => { }, this.analyticsManager);
1363
1642
  gateway.setListener(message => this.pendingGatewaysListener(gateway, source.bridgeUrl, message));
1364
1643
  return gateway;
1365
1644
  });
@@ -1370,7 +1649,8 @@ class BridgeProvider {
1370
1649
  }
1371
1650
  return bridge.registerSession({
1372
1651
  openingDeadlineMS: (_a = options === null || options === void 0 ? void 0 : options.openingDeadlineMS) !== null && _a !== void 0 ? _a : this.defaultOpeningDeadlineMS,
1373
- signal: _options.signal
1652
+ signal: _options.signal,
1653
+ traceId
1374
1654
  });
1375
1655
  }, {
1376
1656
  attempts: Number.MAX_SAFE_INTEGER,
@@ -1384,10 +1664,11 @@ class BridgeProvider {
1384
1664
  logDebug(`Gateway is already opened, closing previous gateway`);
1385
1665
  yield this.gateway.close();
1386
1666
  }
1387
- this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
1667
+ this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this), this.analyticsManager);
1388
1668
  return yield this.gateway.registerSession({
1389
1669
  openingDeadlineMS: options === null || options === void 0 ? void 0 : options.openingDeadlineMS,
1390
- signal: options === null || options === void 0 ? void 0 : options.signal
1670
+ signal: options === null || options === void 0 ? void 0 : options.signal,
1671
+ traceId
1391
1672
  });
1392
1673
  }
1393
1674
  });
@@ -1490,6 +1771,15 @@ function getWebPageManifest() {
1490
1771
  }
1491
1772
  return '';
1492
1773
  }
1774
+ function getOriginWithPath() {
1775
+ var _a, _b, _c, _d;
1776
+ const origin = (_b = (_a = getWindow()) === null || _a === void 0 ? void 0 : _a.location) === null || _b === void 0 ? void 0 : _b.origin;
1777
+ const path = (_d = (_c = getWindow()) === null || _c === void 0 ? void 0 : _c.location) === null || _d === void 0 ? void 0 : _d.pathname;
1778
+ if (origin && path) {
1779
+ return origin + path;
1780
+ }
1781
+ return '';
1782
+ }
1493
1783
  /**
1494
1784
  * Returns `localStorage` if it is available. In Safari's private mode, it returns `InMemoryStorage`. In Node.js, it throws an error.
1495
1785
  */
@@ -1559,11 +1849,11 @@ function getWindowEntries() {
1559
1849
  }
1560
1850
 
1561
1851
  class InjectedProvider {
1562
- static fromStorage(storage) {
1852
+ static fromStorage(storage, analyticsManager) {
1563
1853
  return __awaiter(this, void 0, void 0, function* () {
1564
1854
  const bridgeConnectionStorage = new BridgeConnectionStorage(storage);
1565
1855
  const connection = yield bridgeConnectionStorage.getInjectedConnection();
1566
- return new InjectedProvider(storage, connection.jsBridgeKey);
1856
+ return new InjectedProvider(storage, connection.jsBridgeKey, analyticsManager);
1567
1857
  });
1568
1858
  }
1569
1859
  static isWalletInjected(injectedWalletKey) {
@@ -1600,7 +1890,7 @@ class InjectedProvider {
1600
1890
  typeof window[injectedWalletKey] === 'object' &&
1601
1891
  'tonconnect' in window[injectedWalletKey]);
1602
1892
  }
1603
- constructor(storage, injectedWalletKey) {
1893
+ constructor(storage, injectedWalletKey, analyticsManager) {
1604
1894
  this.injectedWalletKey = injectedWalletKey;
1605
1895
  this.type = 'injected';
1606
1896
  this.unsubscribeCallback = null;
@@ -1612,25 +1902,49 @@ class InjectedProvider {
1612
1902
  }
1613
1903
  this.connectionStorage = new BridgeConnectionStorage(storage);
1614
1904
  this.injectedWallet = window[injectedWalletKey].tonconnect;
1905
+ if (analyticsManager) {
1906
+ this.analytics = analyticsManager.scoped({
1907
+ bridge_key: injectedWalletKey,
1908
+ wallet_app_name: this.injectedWallet.deviceInfo.appName,
1909
+ wallet_app_version: this.injectedWallet.deviceInfo.appVersion
1910
+ });
1911
+ }
1615
1912
  }
1616
- connect(message) {
1617
- this._connect(PROTOCOL_VERSION, message);
1913
+ connect(message, options) {
1914
+ this._connect(PROTOCOL_VERSION, message, options);
1618
1915
  }
1619
- restoreConnection() {
1916
+ restoreConnection(options) {
1620
1917
  return __awaiter(this, void 0, void 0, function* () {
1918
+ var _a, _b, _c, _d;
1919
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1621
1920
  try {
1622
1921
  logDebug(`Injected Provider restoring connection...`);
1623
- const connectEvent = yield this.injectedWallet.restoreConnection();
1922
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitJsBridgeCall({
1923
+ js_bridge_method: 'restoreConnection',
1924
+ trace_id: traceId
1925
+ });
1926
+ const connectEvent = yield this.injectedWallet.restoreConnection({
1927
+ traceId
1928
+ });
1929
+ (_c = this.analytics) === null || _c === void 0 ? void 0 : _c.emitJsBridgeResponse({
1930
+ js_bridge_method: 'restoreConnection',
1931
+ trace_id: traceId
1932
+ });
1624
1933
  logDebug('Injected Provider restoring connection response', connectEvent);
1625
1934
  if (connectEvent.event === 'connect') {
1626
- this.makeSubscriptions();
1627
- this.listeners.forEach(listener => listener(connectEvent));
1935
+ this.makeSubscriptions({ traceId });
1936
+ this.listeners.forEach(listener => listener(Object.assign(Object.assign({}, connectEvent), { traceId })));
1628
1937
  }
1629
1938
  else {
1630
1939
  yield this.connectionStorage.removeConnection();
1631
1940
  }
1632
1941
  }
1633
1942
  catch (e) {
1943
+ (_d = this.analytics) === null || _d === void 0 ? void 0 : _d.emitJsBridgeError({
1944
+ js_bridge_method: 'restoreConnection',
1945
+ error_message: String(e),
1946
+ trace_id: traceId
1947
+ });
1634
1948
  yield this.connectionStorage.removeConnection();
1635
1949
  console.error(e);
1636
1950
  }
@@ -1642,8 +1956,10 @@ class InjectedProvider {
1642
1956
  }
1643
1957
  this.closeAllListeners();
1644
1958
  }
1645
- disconnect() {
1959
+ disconnect(options) {
1646
1960
  return __awaiter(this, void 0, void 0, function* () {
1961
+ var _a;
1962
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1647
1963
  return new Promise(resolve => {
1648
1964
  const onRequestSent = () => {
1649
1965
  this.closeAllListeners();
@@ -1658,7 +1974,7 @@ class InjectedProvider {
1658
1974
  this.sendRequest({
1659
1975
  method: 'disconnect',
1660
1976
  params: []
1661
- }, onRequestSent);
1977
+ }, { onRequestSent, traceId });
1662
1978
  }
1663
1979
  });
1664
1980
  });
@@ -1675,38 +1991,76 @@ class InjectedProvider {
1675
1991
  }
1676
1992
  sendRequest(request, optionsOrOnRequestSent) {
1677
1993
  return __awaiter(this, void 0, void 0, function* () {
1678
- var _a;
1994
+ var _a, _b, _c;
1679
1995
  // TODO: remove deprecated method
1680
1996
  const options = {};
1681
1997
  if (typeof optionsOrOnRequestSent === 'function') {
1682
1998
  options.onRequestSent = optionsOrOnRequestSent;
1999
+ options.traceId = UUIDv7();
1683
2000
  }
1684
2001
  else {
1685
2002
  options.onRequestSent = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.onRequestSent;
1686
2003
  options.signal = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.signal;
2004
+ options.attempts = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.attempts;
2005
+ options.traceId = (_a = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1687
2006
  }
1688
2007
  const id = (yield this.connectionStorage.getNextRpcRequestId()).toString();
1689
2008
  yield this.connectionStorage.increaseNextRpcRequestId();
1690
2009
  logDebug('Send injected-bridge request:', Object.assign(Object.assign({}, request), { id }));
1691
- const result = this.injectedWallet.send(Object.assign(Object.assign({}, request), { id }));
1692
- result.then(response => logDebug('Wallet message received:', response));
1693
- (_a = options === null || options === void 0 ? void 0 : options.onRequestSent) === null || _a === void 0 ? void 0 : _a.call(options);
2010
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitJsBridgeCall({
2011
+ js_bridge_method: 'send'
2012
+ });
2013
+ const result = this.injectedWallet.send(Object.assign(Object.assign({}, request), { id }), {
2014
+ traceId: options.traceId
2015
+ });
2016
+ result
2017
+ .then(response => {
2018
+ var _a;
2019
+ (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.emitJsBridgeResponse({
2020
+ js_bridge_method: 'send'
2021
+ });
2022
+ logDebug('Wallet message received:', response);
2023
+ })
2024
+ .catch(error => {
2025
+ var _a;
2026
+ (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.emitJsBridgeError({
2027
+ js_bridge_method: 'send',
2028
+ error_message: String(error)
2029
+ });
2030
+ });
2031
+ (_c = options === null || options === void 0 ? void 0 : options.onRequestSent) === null || _c === void 0 ? void 0 : _c.call(options);
1694
2032
  return result;
1695
2033
  });
1696
2034
  }
1697
- _connect(protocolVersion, message) {
2035
+ _connect(protocolVersion, message, options) {
1698
2036
  return __awaiter(this, void 0, void 0, function* () {
2037
+ var _a, _b, _c, _d;
2038
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1699
2039
  try {
1700
2040
  logDebug(`Injected Provider connect request: protocolVersion: ${protocolVersion}, message:`, message);
1701
- const connectEvent = yield this.injectedWallet.connect(protocolVersion, message);
2041
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitJsBridgeCall({
2042
+ js_bridge_method: 'connect',
2043
+ trace_id: traceId
2044
+ });
2045
+ const connectEvent = yield this.injectedWallet.connect(protocolVersion, message, {
2046
+ traceId
2047
+ });
2048
+ (_c = this.analytics) === null || _c === void 0 ? void 0 : _c.emitJsBridgeResponse({
2049
+ js_bridge_method: 'connect'
2050
+ });
1702
2051
  logDebug('Injected Provider connect response:', connectEvent);
1703
2052
  if (connectEvent.event === 'connect') {
1704
2053
  yield this.updateSession();
1705
- this.makeSubscriptions();
2054
+ this.makeSubscriptions({ traceId });
1706
2055
  }
1707
- this.listeners.forEach(listener => listener(connectEvent));
2056
+ this.listeners.forEach(listener => listener(Object.assign(Object.assign({}, connectEvent), { traceId })));
1708
2057
  }
1709
2058
  catch (e) {
2059
+ (_d = this.analytics) === null || _d === void 0 ? void 0 : _d.emitJsBridgeError({
2060
+ js_bridge_method: 'connect',
2061
+ error_message: String(e),
2062
+ trace_id: traceId
2063
+ });
1710
2064
  logDebug('Injected Provider connect error:', e);
1711
2065
  const connectEventError = {
1712
2066
  event: 'connect_error',
@@ -1715,21 +2069,42 @@ class InjectedProvider {
1715
2069
  message: e === null || e === void 0 ? void 0 : e.toString()
1716
2070
  }
1717
2071
  };
1718
- this.listeners.forEach(listener => listener(connectEventError));
2072
+ this.listeners.forEach(listener => listener(Object.assign(Object.assign({}, connectEventError), { traceId })));
1719
2073
  }
1720
2074
  });
1721
2075
  }
1722
- makeSubscriptions() {
2076
+ makeSubscriptions(options) {
2077
+ var _a, _b, _c;
1723
2078
  this.listenSubscriptions = true;
1724
- this.unsubscribeCallback = this.injectedWallet.listen(e => {
1725
- logDebug('Wallet message received:', e);
1726
- if (this.listenSubscriptions) {
1727
- this.listeners.forEach(listener => listener(e));
1728
- }
1729
- if (e.event === 'disconnect') {
1730
- this.disconnect();
1731
- }
2079
+ (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.emitJsBridgeCall({
2080
+ js_bridge_method: 'listen',
2081
+ trace_id: options.traceId
1732
2082
  });
2083
+ try {
2084
+ this.unsubscribeCallback = this.injectedWallet.listen(e => {
2085
+ var _a;
2086
+ const traceId = (_a = e.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
2087
+ logDebug('Wallet message received:', e);
2088
+ if (this.listenSubscriptions) {
2089
+ this.listeners.forEach(listener => listener(Object.assign(Object.assign({}, e), { traceId })));
2090
+ }
2091
+ if (e.event === 'disconnect') {
2092
+ this.disconnect({ traceId });
2093
+ }
2094
+ });
2095
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitJsBridgeResponse({
2096
+ js_bridge_method: 'listen',
2097
+ trace_id: options.traceId
2098
+ });
2099
+ }
2100
+ catch (err) {
2101
+ (_c = this.analytics) === null || _c === void 0 ? void 0 : _c.emitJsBridgeError({
2102
+ js_bridge_method: 'listen',
2103
+ error_message: String(err),
2104
+ trace_id: options.traceId
2105
+ });
2106
+ throw err;
2107
+ }
1733
2108
  }
1734
2109
  updateSession() {
1735
2110
  return this.connectionStorage.storeConnection({
@@ -2974,77 +3349,91 @@ function createVersionInfo(version) {
2974
3349
  ton_connect_ui_lib: version.ton_connect_ui_lib
2975
3350
  };
2976
3351
  }
2977
- function createConnectionInfo(version, wallet) {
2978
- var _a, _b, _c, _d, _e, _f, _g, _h;
3352
+ // eslint-disable-next-line complexity
3353
+ function createConnectionInfo(version, wallet, sessionInfo) {
3354
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
2979
3355
  const isTonProof = ((_a = wallet === null || wallet === void 0 ? void 0 : wallet.connectItems) === null || _a === void 0 ? void 0 : _a.tonProof) && 'proof' in wallet.connectItems.tonProof;
2980
3356
  const authType = isTonProof ? 'ton_proof' : 'ton_addr';
2981
3357
  return {
2982
3358
  wallet_address: (_c = (_b = wallet === null || wallet === void 0 ? void 0 : wallet.account) === null || _b === void 0 ? void 0 : _b.address) !== null && _c !== void 0 ? _c : null,
2983
- wallet_type: (_d = wallet === null || wallet === void 0 ? void 0 : wallet.device.appName) !== null && _d !== void 0 ? _d : null,
2984
- wallet_version: (_e = wallet === null || wallet === void 0 ? void 0 : wallet.device.appVersion) !== null && _e !== void 0 ? _e : null,
3359
+ wallet_state_init: (_d = wallet === null || wallet === void 0 ? void 0 : wallet.account.walletStateInit) !== null && _d !== void 0 ? _d : null,
3360
+ wallet_type: (_e = wallet === null || wallet === void 0 ? void 0 : wallet.device.appName) !== null && _e !== void 0 ? _e : null,
3361
+ wallet_version: (_f = wallet === null || wallet === void 0 ? void 0 : wallet.device.appVersion) !== null && _f !== void 0 ? _f : null,
2985
3362
  auth_type: authType,
2986
- custom_data: Object.assign({ chain_id: (_g = (_f = wallet === null || wallet === void 0 ? void 0 : wallet.account) === null || _f === void 0 ? void 0 : _f.chain) !== null && _g !== void 0 ? _g : null, provider: (_h = wallet === null || wallet === void 0 ? void 0 : wallet.provider) !== null && _h !== void 0 ? _h : null }, createVersionInfo(version))
3363
+ custom_data: Object.assign({ client_id: (_g = sessionInfo === null || sessionInfo === void 0 ? void 0 : sessionInfo.clientId) !== null && _g !== void 0 ? _g : null, wallet_id: (_h = sessionInfo === null || sessionInfo === void 0 ? void 0 : sessionInfo.walletId) !== null && _h !== void 0 ? _h : null, chain_id: (_k = (_j = wallet === null || wallet === void 0 ? void 0 : wallet.account) === null || _j === void 0 ? void 0 : _j.chain) !== null && _k !== void 0 ? _k : null, provider: (_l = wallet === null || wallet === void 0 ? void 0 : wallet.provider) !== null && _l !== void 0 ? _l : null }, createVersionInfo(version))
2987
3364
  };
2988
3365
  }
2989
3366
  /**
2990
3367
  * Create a connection init event.
2991
3368
  */
2992
- function createConnectionStartedEvent(version) {
3369
+ function createConnectionStartedEvent(version, traceId) {
2993
3370
  return {
2994
3371
  type: 'connection-started',
2995
- custom_data: createVersionInfo(version)
3372
+ custom_data: createVersionInfo(version),
3373
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null
2996
3374
  };
2997
3375
  }
2998
3376
  /**
2999
3377
  * Create a connection completed event.
3000
3378
  * @param version
3001
3379
  * @param wallet
3380
+ * @param sessionInfo
3381
+ * @param traceId
3002
3382
  */
3003
- function createConnectionCompletedEvent(version, wallet) {
3004
- return Object.assign({ type: 'connection-completed', is_success: true }, createConnectionInfo(version, wallet));
3383
+ function createConnectionCompletedEvent(version, wallet, sessionInfo, traceId) {
3384
+ return Object.assign({ type: 'connection-completed', is_success: true, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo));
3005
3385
  }
3006
3386
  /**
3007
3387
  * Create a connection error event.
3008
3388
  * @param version
3009
3389
  * @param error_message
3010
3390
  * @param errorCode
3391
+ * @param sessionInfo
3392
+ * @param traceId
3011
3393
  */
3012
- function createConnectionErrorEvent(version, error_message, errorCode) {
3394
+ function createConnectionErrorEvent(version, error_message, errorCode, sessionInfo, traceId) {
3395
+ var _a, _b;
3013
3396
  return {
3014
3397
  type: 'connection-error',
3015
3398
  is_success: false,
3016
3399
  error_message: error_message,
3017
3400
  error_code: errorCode !== null && errorCode !== void 0 ? errorCode : null,
3018
- custom_data: createVersionInfo(version)
3401
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null,
3402
+ custom_data: Object.assign({ client_id: (_a = sessionInfo === null || sessionInfo === void 0 ? void 0 : sessionInfo.clientId) !== null && _a !== void 0 ? _a : null, wallet_id: (_b = sessionInfo === null || sessionInfo === void 0 ? void 0 : sessionInfo.walletId) !== null && _b !== void 0 ? _b : null }, createVersionInfo(version))
3019
3403
  };
3020
3404
  }
3021
3405
  /**
3022
3406
  * Create a connection restoring started event.
3023
3407
  */
3024
- function createConnectionRestoringStartedEvent(version) {
3408
+ function createConnectionRestoringStartedEvent(version, traceId) {
3025
3409
  return {
3026
3410
  type: 'connection-restoring-started',
3027
- custom_data: createVersionInfo(version)
3411
+ custom_data: createVersionInfo(version),
3412
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null
3028
3413
  };
3029
3414
  }
3030
3415
  /**
3031
3416
  * Create a connection restoring completed event.
3032
3417
  * @param version
3033
3418
  * @param wallet
3419
+ * @param sessionInfo
3420
+ * @param traceId
3034
3421
  */
3035
- function createConnectionRestoringCompletedEvent(version, wallet) {
3036
- return Object.assign({ type: 'connection-restoring-completed', is_success: true }, createConnectionInfo(version, wallet));
3422
+ function createConnectionRestoringCompletedEvent(version, wallet, sessionInfo, traceId) {
3423
+ return Object.assign({ type: 'connection-restoring-completed', is_success: true, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo));
3037
3424
  }
3038
3425
  /**
3039
3426
  * Create a connection restoring error event.
3040
3427
  * @param version
3041
3428
  * @param errorMessage
3429
+ * @param traceId
3042
3430
  */
3043
- function createConnectionRestoringErrorEvent(version, errorMessage) {
3431
+ function createConnectionRestoringErrorEvent(version, errorMessage, traceId) {
3044
3432
  return {
3045
3433
  type: 'connection-restoring-error',
3046
3434
  is_success: false,
3047
3435
  error_message: errorMessage,
3436
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null,
3048
3437
  custom_data: createVersionInfo(version)
3049
3438
  };
3050
3439
  }
@@ -3062,14 +3451,32 @@ function createTransactionInfo(wallet, transaction) {
3062
3451
  })
3063
3452
  };
3064
3453
  }
3454
+ function createTransactionFullInfo(wallet, transaction) {
3455
+ var _a, _b, _c, _d;
3456
+ return {
3457
+ valid_until: (_a = String(transaction.validUntil)) !== null && _a !== void 0 ? _a : null,
3458
+ from: (_d = (_b = transaction.from) !== null && _b !== void 0 ? _b : (_c = wallet === null || wallet === void 0 ? void 0 : wallet.account) === null || _c === void 0 ? void 0 : _c.address) !== null && _d !== void 0 ? _d : null,
3459
+ messages: transaction.messages.map(message => {
3460
+ var _a, _b, _c, _d;
3461
+ return ({
3462
+ address: (_a = message.address) !== null && _a !== void 0 ? _a : null,
3463
+ amount: (_b = message.amount) !== null && _b !== void 0 ? _b : null,
3464
+ payload: (_c = message.payload) !== null && _c !== void 0 ? _c : null,
3465
+ state_init: (_d = message.stateInit) !== null && _d !== void 0 ? _d : null
3466
+ });
3467
+ })
3468
+ };
3469
+ }
3065
3470
  /**
3066
3471
  * Create a transaction init event.
3067
3472
  * @param version
3068
3473
  * @param wallet
3069
3474
  * @param transaction
3475
+ * @param sessionInfo
3476
+ * @param traceId
3070
3477
  */
3071
- function createTransactionSentForSignatureEvent(version, wallet, transaction) {
3072
- return Object.assign(Object.assign({ type: 'transaction-sent-for-signature' }, createConnectionInfo(version, wallet)), createTransactionInfo(wallet, transaction));
3478
+ function createTransactionSentForSignatureEvent(version, wallet, transaction, sessionInfo, traceId) {
3479
+ return Object.assign(Object.assign({ type: 'transaction-sent-for-signature', trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo)), createTransactionInfo(wallet, transaction));
3073
3480
  }
3074
3481
  /**
3075
3482
  * Create a transaction signed event.
@@ -3077,9 +3484,11 @@ function createTransactionSentForSignatureEvent(version, wallet, transaction) {
3077
3484
  * @param wallet
3078
3485
  * @param transaction
3079
3486
  * @param signedTransaction
3487
+ * @param sessionInfo
3488
+ * @param traceId
3080
3489
  */
3081
- function createTransactionSignedEvent(version, wallet, transaction, signedTransaction) {
3082
- return Object.assign(Object.assign({ type: 'transaction-signed', is_success: true, signed_transaction: signedTransaction.boc }, createConnectionInfo(version, wallet)), createTransactionInfo(wallet, transaction));
3490
+ function createTransactionSignedEvent(version, wallet, transaction, signedTransaction, sessionInfo, traceId) {
3491
+ return Object.assign(Object.assign({ type: 'transaction-signed', is_success: true, signed_transaction: signedTransaction.boc, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo)), createTransactionInfo(wallet, transaction));
3083
3492
  }
3084
3493
  /**
3085
3494
  * Create a transaction error event.
@@ -3088,71 +3497,50 @@ function createTransactionSignedEvent(version, wallet, transaction, signedTransa
3088
3497
  * @param transaction
3089
3498
  * @param errorMessage
3090
3499
  * @param errorCode
3500
+ * @param sessionInfo
3501
+ * @param traceId
3091
3502
  */
3092
- function createTransactionSigningFailedEvent(version, wallet, transaction, errorMessage, errorCode) {
3093
- return Object.assign(Object.assign({ type: 'transaction-signing-failed', is_success: false, error_message: errorMessage, error_code: errorCode !== null && errorCode !== void 0 ? errorCode : null }, createConnectionInfo(version, wallet)), createTransactionInfo(wallet, transaction));
3503
+ function createTransactionSigningFailedEvent(version, wallet, transaction, errorMessage, errorCode, sessionInfo, traceId) {
3504
+ return Object.assign(Object.assign({ type: 'transaction-signing-failed', is_success: false, error_message: errorMessage, error_code: errorCode !== null && errorCode !== void 0 ? errorCode : null, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo)), createTransactionFullInfo(wallet, transaction));
3094
3505
  }
3095
- function createDataSentForSignatureEvent(version, wallet, data) {
3096
- return Object.assign({ type: 'sign-data-request-initiated', data }, createConnectionInfo(version, wallet));
3506
+ function createDataSentForSignatureEvent(version, wallet, data, sessionInfo, traceId) {
3507
+ return Object.assign({ type: 'sign-data-request-initiated', data, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo));
3097
3508
  }
3098
- function createDataSignedEvent(version, wallet, data, signedData) {
3099
- return Object.assign({ type: 'sign-data-request-completed', is_success: true, data, signed_data: signedData }, createConnectionInfo(version, wallet));
3509
+ function createDataSignedEvent(version, wallet, data, signedData, sessionInfo, traceId) {
3510
+ return Object.assign({ type: 'sign-data-request-completed', is_success: true, data, signed_data: signedData, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo));
3100
3511
  }
3101
- function createDataSigningFailedEvent(version, wallet, data, errorMessage, errorCode) {
3102
- return Object.assign({ type: 'sign-data-request-failed', is_success: false, data, error_message: errorMessage, error_code: errorCode !== null && errorCode !== void 0 ? errorCode : null }, createConnectionInfo(version, wallet));
3512
+ function createDataSigningFailedEvent(version, wallet, data, errorMessage, errorCode, sessionInfo, traceId) {
3513
+ return Object.assign({ type: 'sign-data-request-failed', is_success: false, data, error_message: errorMessage, error_code: errorCode !== null && errorCode !== void 0 ? errorCode : null, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo));
3103
3514
  }
3104
- /**
3105
- * Create a disconnect event.
3106
- * @param version
3107
- * @param wallet
3108
- * @param scope
3109
- * @returns
3110
- */
3111
- function createDisconnectionEvent(version, wallet, scope) {
3112
- return Object.assign({ type: 'disconnection', scope: scope }, createConnectionInfo(version, wallet));
3515
+ function createDisconnectionEvent(version, wallet, scope, sessionInfo, traceId) {
3516
+ return Object.assign({ type: 'disconnection', scope: scope, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo));
3113
3517
  }
3114
-
3115
- /**
3116
- * A concrete implementation of EventDispatcher that dispatches events to the browser window.
3117
- */
3118
- class BrowserEventDispatcher {
3119
- constructor() {
3120
- /**
3121
- * The window object, possibly undefined in a server environment.
3122
- * @private
3123
- */
3124
- this.window = getWindow();
3125
- }
3126
- /**
3127
- * Dispatches an event with the given name and details to the browser window.
3128
- * @param eventName - The name of the event to dispatch.
3129
- * @param eventDetails - The details of the event to dispatch.
3130
- * @returns A promise that resolves when the event has been dispatched.
3131
- */
3132
- dispatchEvent(eventName, eventDetails) {
3133
- return __awaiter(this, void 0, void 0, function* () {
3134
- var _a;
3135
- const event = new CustomEvent(eventName, { detail: eventDetails });
3136
- (_a = this.window) === null || _a === void 0 ? void 0 : _a.dispatchEvent(event);
3137
- });
3138
- }
3139
- /**
3140
- * Adds an event listener to the browser window.
3141
- * @param eventName - The name of the event to listen for.
3142
- * @param listener - The listener to add.
3143
- * @param options - The options for the listener.
3144
- * @returns A function that removes the listener.
3145
- */
3146
- addEventListener(eventName, listener, options) {
3147
- return __awaiter(this, void 0, void 0, function* () {
3148
- var _a;
3149
- (_a = this.window) === null || _a === void 0 ? void 0 : _a.addEventListener(eventName, listener, options);
3150
- return () => {
3151
- var _a;
3152
- return (_a = this.window) === null || _a === void 0 ? void 0 : _a.removeEventListener(eventName, listener);
3153
- };
3154
- });
3518
+ function createWalletModalOpenedEvent(version, visibleWallets, clientId, traceId) {
3519
+ return {
3520
+ type: 'wallet-modal-opened',
3521
+ visible_wallets: visibleWallets,
3522
+ client_id: clientId !== null && clientId !== void 0 ? clientId : null,
3523
+ custom_data: version,
3524
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null
3525
+ };
3526
+ }
3527
+ function createSelectedWalletEvent(version, visibleWallets, lastSelectedWallet, walletsMenu, redirectLink, redirectLinkType, clientId, traceId) {
3528
+ var _a;
3529
+ let walletRedirectMethod = redirectLinkType;
3530
+ if (!walletRedirectMethod && redirectLink) {
3531
+ walletRedirectMethod = isTelegramUrl(redirectLink) ? 'tg_link' : 'external_link';
3155
3532
  }
3533
+ return {
3534
+ type: 'selected-wallet',
3535
+ wallets_menu: walletsMenu,
3536
+ visible_wallets: visibleWallets,
3537
+ client_id: clientId !== null && clientId !== void 0 ? clientId : null,
3538
+ custom_data: version,
3539
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null,
3540
+ wallet_redirect_method: walletRedirectMethod,
3541
+ wallet_redirect_link: redirectLink || undefined,
3542
+ wallet_type: (_a = lastSelectedWallet === null || lastSelectedWallet === void 0 ? void 0 : lastSelectedWallet.appName) !== null && _a !== void 0 ? _a : null
3543
+ };
3156
3544
  }
3157
3545
 
3158
3546
  /**
@@ -3193,7 +3581,6 @@ class TonConnectTracker {
3193
3581
  });
3194
3582
  }
3195
3583
  constructor(options) {
3196
- var _a;
3197
3584
  /**
3198
3585
  * Event prefix for user actions.
3199
3586
  * @private
@@ -3203,7 +3590,7 @@ class TonConnectTracker {
3203
3590
  * TonConnect UI version.
3204
3591
  */
3205
3592
  this.tonConnectUiVersion = null;
3206
- this.eventDispatcher = (_a = options === null || options === void 0 ? void 0 : options.eventDispatcher) !== null && _a !== void 0 ? _a : new BrowserEventDispatcher();
3593
+ this.eventDispatcher = options === null || options === void 0 ? void 0 : options.eventDispatcher;
3207
3594
  this.tonConnectSdkVersion = options.tonConnectSdkVersion;
3208
3595
  this.init().catch();
3209
3596
  }
@@ -3407,7 +3794,7 @@ class TonConnectTracker {
3407
3794
  }
3408
3795
  }
3409
3796
 
3410
- const tonConnectSdkVersion = "3.3.1";
3797
+ const tonConnectSdkVersion = "3.4.0-beta.1";
3411
3798
 
3412
3799
  const bounceableTag = 0x11;
3413
3800
  const noBounceableTag = 0x51;
@@ -3906,6 +4293,403 @@ function normalizeBase64(data) {
3906
4293
  return data.replace(/-/g, '+').replace(/_/g, '/').padEnd(paddedLength, '=');
3907
4294
  }
3908
4295
 
4296
+ /**
4297
+ * Converts a PascalCase (or camelCase) string to kebab-case.
4298
+ *
4299
+ * For example:
4300
+ * - "PascalCase" → "pascal-case"
4301
+ * - "camelCaseExample" → "camel-case-example"
4302
+ *
4303
+ * @param value - The input string in PascalCase or camelCase format.
4304
+ * @returns The converted kebab-case string.
4305
+ */
4306
+ function pascalToKebab(value) {
4307
+ return value.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
4308
+ }
4309
+
4310
+ class AnalyticsManager {
4311
+ constructor(options = {}) {
4312
+ var _a, _b, _c, _d, _e;
4313
+ this.events = [];
4314
+ this.timeoutId = null;
4315
+ this.isProcessing = false;
4316
+ this.backoff = 1;
4317
+ this.shouldSend = true;
4318
+ this.batchTimeoutMs = (_a = options.batchTimeoutMs) !== null && _a !== void 0 ? _a : 2000;
4319
+ this.currentBatchTimeoutMs = this.batchTimeoutMs;
4320
+ this.maxBatchSize = (_b = options.maxBatchSize) !== null && _b !== void 0 ? _b : 100;
4321
+ this.analyticsUrl = (_c = options.analyticsUrl) !== null && _c !== void 0 ? _c : 'https://analytics.ton.org/events';
4322
+ this.enabled = (_d = options.enabled) !== null && _d !== void 0 ? _d : true;
4323
+ this.baseEvent = {
4324
+ subsystem: 'dapp-sdk',
4325
+ version: tonConnectSdkVersion,
4326
+ client_environment: (_e = options.environment) === null || _e === void 0 ? void 0 : _e.getClientEnvironment()
4327
+ };
4328
+ this.addWindowFocusAndBlurSubscriptions();
4329
+ }
4330
+ scoped(sharedData) {
4331
+ return new Proxy(this, {
4332
+ get(target, prop) {
4333
+ const propName = prop.toString();
4334
+ if (propName.startsWith('emit')) {
4335
+ const eventNamePascal = propName.replace('emit', '');
4336
+ const eventNameKebab = pascalToKebab(eventNamePascal);
4337
+ return function (event) {
4338
+ const executedData = Object.fromEntries(Object.entries(sharedData !== null && sharedData !== void 0 ? sharedData : {}).map(([key, value]) => [
4339
+ key,
4340
+ typeof value === 'function' ? value() : value
4341
+ ]));
4342
+ return target.emit(Object.assign(Object.assign({ event_name: eventNameKebab }, executedData), event));
4343
+ };
4344
+ }
4345
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4346
+ return target[prop];
4347
+ }
4348
+ });
4349
+ }
4350
+ emit(event) {
4351
+ var _a;
4352
+ if (!this.enabled) {
4353
+ return;
4354
+ }
4355
+ const traceId = (_a = event.trace_id) !== null && _a !== void 0 ? _a : UUIDv7();
4356
+ const enhancedEvent = Object.assign(Object.assign(Object.assign({}, this.baseEvent), event), { event_id: UUIDv7(), client_timestamp: Math.floor(Date.now() / 1000), trace_id: traceId });
4357
+ if (isQaModeEnabled()) {
4358
+ logDebug(enhancedEvent);
4359
+ }
4360
+ this.events.push(enhancedEvent);
4361
+ if (this.events.length >= this.maxBatchSize) {
4362
+ void this.flush();
4363
+ return;
4364
+ }
4365
+ this.startTimeout();
4366
+ }
4367
+ startTimeout() {
4368
+ if (this.timeoutId || this.isProcessing) {
4369
+ return;
4370
+ }
4371
+ this.timeoutId = setTimeout(() => {
4372
+ void this.flush();
4373
+ }, this.currentBatchTimeoutMs);
4374
+ }
4375
+ flush() {
4376
+ return __awaiter(this, void 0, void 0, function* () {
4377
+ if (this.isProcessing || this.events.length === 0 || !this.shouldSend) {
4378
+ return;
4379
+ }
4380
+ this.clearTimeout();
4381
+ this.isProcessing = true;
4382
+ const eventsToSend = this.extractEventsToSend();
4383
+ try {
4384
+ yield this.processEventsBatch(eventsToSend);
4385
+ logDebug('Analytics events sent successfully');
4386
+ }
4387
+ catch (error) {
4388
+ this.restoreEvents(eventsToSend);
4389
+ logError('Failed to send analytics events:', error);
4390
+ }
4391
+ finally {
4392
+ this.isProcessing = false;
4393
+ this.scheduleNextFlushIfNeeded();
4394
+ }
4395
+ });
4396
+ }
4397
+ clearTimeout() {
4398
+ if (this.timeoutId) {
4399
+ clearTimeout(this.timeoutId);
4400
+ this.timeoutId = null;
4401
+ }
4402
+ }
4403
+ extractEventsToSend() {
4404
+ const eventsToSend = this.events.slice(0, this.maxBatchSize);
4405
+ this.events = this.events.slice(this.maxBatchSize);
4406
+ return eventsToSend;
4407
+ }
4408
+ processEventsBatch(eventsToSend) {
4409
+ return __awaiter(this, void 0, void 0, function* () {
4410
+ logDebug('Sending analytics events...', eventsToSend.length);
4411
+ try {
4412
+ const response = yield this.sendEvents(eventsToSend);
4413
+ this.handleResponse(response);
4414
+ }
4415
+ catch (err) {
4416
+ this.handleUnknownError(err);
4417
+ }
4418
+ });
4419
+ }
4420
+ handleResponse(response) {
4421
+ const { status, statusText } = response;
4422
+ if (this.isTooManyRequests(status)) {
4423
+ this.handleTooManyRequests(status, statusText);
4424
+ }
4425
+ else if (this.isClientError(status)) {
4426
+ this.handleClientError(status, statusText);
4427
+ }
4428
+ else if (this.isServerError(status)) {
4429
+ this.handleUnknownError({ status, statusText });
4430
+ }
4431
+ }
4432
+ restoreEvents(eventsToSend) {
4433
+ this.events.unshift(...eventsToSend);
4434
+ }
4435
+ scheduleNextFlushIfNeeded() {
4436
+ if (this.events.length > 0) {
4437
+ this.startTimeout();
4438
+ }
4439
+ }
4440
+ sendEvents(events) {
4441
+ return __awaiter(this, void 0, void 0, function* () {
4442
+ return yield fetch(this.analyticsUrl, {
4443
+ method: 'POST',
4444
+ headers: {
4445
+ 'Content-Type': 'application/json',
4446
+ 'X-Client-Timestamp': Math.floor(Date.now() / 1000).toString()
4447
+ },
4448
+ body: JSON.stringify(events)
4449
+ });
4450
+ });
4451
+ }
4452
+ isClientError(status) {
4453
+ return (status >= AnalyticsManager.HTTP_STATUS.CLIENT_ERROR_START &&
4454
+ status < AnalyticsManager.HTTP_STATUS.SERVER_ERROR_START);
4455
+ }
4456
+ isServerError(status) {
4457
+ return status >= AnalyticsManager.HTTP_STATUS.SERVER_ERROR_START;
4458
+ }
4459
+ isTooManyRequests(status) {
4460
+ return status === AnalyticsManager.HTTP_STATUS.TOO_MANY_REQUESTS;
4461
+ }
4462
+ handleClientError(status, statusText) {
4463
+ // Don't retry
4464
+ logError('Failed to send analytics events:', new TonConnectError(`Analytics API error: ${status} ${statusText}`));
4465
+ }
4466
+ handleUnknownError(error) {
4467
+ if (this.backoff < AnalyticsManager.MAX_BACKOFF_ATTEMPTS) {
4468
+ this.backoff++;
4469
+ this.currentBatchTimeoutMs *= AnalyticsManager.BACKOFF_MULTIPLIER;
4470
+ throw new TonConnectError(`Unknown analytics API error: ${error}`);
4471
+ }
4472
+ else {
4473
+ this.currentBatchTimeoutMs = this.batchTimeoutMs;
4474
+ this.backoff = 1;
4475
+ return; // Don't retry
4476
+ }
4477
+ }
4478
+ handleTooManyRequests(status, statusText) {
4479
+ throw new TonConnectError(`Analytics API error: ${status} ${statusText}`);
4480
+ }
4481
+ addWindowFocusAndBlurSubscriptions() {
4482
+ const document = getDocument();
4483
+ if (!document) {
4484
+ return;
4485
+ }
4486
+ try {
4487
+ document.addEventListener('visibilitychange', () => {
4488
+ if (document.hidden) {
4489
+ this.clearTimeout();
4490
+ this.shouldSend = false;
4491
+ }
4492
+ else {
4493
+ this.shouldSend = true;
4494
+ this.scheduleNextFlushIfNeeded();
4495
+ }
4496
+ });
4497
+ }
4498
+ catch (e) {
4499
+ logError('Cannot subscribe to the document.visibilitychange: ', e);
4500
+ }
4501
+ }
4502
+ setEnabled(enabled) {
4503
+ this.enabled = enabled;
4504
+ }
4505
+ isEnabled() {
4506
+ return this.enabled;
4507
+ }
4508
+ getPendingEventsCount() {
4509
+ return this.events.length;
4510
+ }
4511
+ }
4512
+ AnalyticsManager.HTTP_STATUS = {
4513
+ TOO_MANY_REQUESTS: 429,
4514
+ CLIENT_ERROR_START: 400,
4515
+ SERVER_ERROR_START: 500
4516
+ };
4517
+ AnalyticsManager.MAX_BACKOFF_ATTEMPTS = 5;
4518
+ AnalyticsManager.BACKOFF_MULTIPLIER = 2;
4519
+
4520
+ /**
4521
+ * A concrete implementation of EventDispatcher that dispatches events to the browser window.
4522
+ */
4523
+ class BrowserEventDispatcher {
4524
+ constructor() {
4525
+ /**
4526
+ * The window object, possibly undefined in a server environment.
4527
+ * @private
4528
+ */
4529
+ this.window = getWindow();
4530
+ }
4531
+ /**
4532
+ * Dispatches an event with the given name and details to the browser window.
4533
+ * @param eventName - The name of the event to dispatch.
4534
+ * @param eventDetails - The details of the event to dispatch.
4535
+ * @returns A promise that resolves when the event has been dispatched.
4536
+ */
4537
+ dispatchEvent(eventName, eventDetails) {
4538
+ return __awaiter(this, void 0, void 0, function* () {
4539
+ var _a;
4540
+ const event = new CustomEvent(eventName, { detail: eventDetails });
4541
+ (_a = this.window) === null || _a === void 0 ? void 0 : _a.dispatchEvent(event);
4542
+ });
4543
+ }
4544
+ /**
4545
+ * Adds an event listener to the browser window.
4546
+ * @param eventName - The name of the event to listen for.
4547
+ * @param listener - The listener to add.
4548
+ * @param options - The options for the listener.
4549
+ * @returns A function that removes the listener.
4550
+ */
4551
+ addEventListener(eventName, listener, options) {
4552
+ return __awaiter(this, void 0, void 0, function* () {
4553
+ var _a;
4554
+ (_a = this.window) === null || _a === void 0 ? void 0 : _a.addEventListener(eventName, listener, options);
4555
+ return () => {
4556
+ var _a;
4557
+ return (_a = this.window) === null || _a === void 0 ? void 0 : _a.removeEventListener(eventName, listener);
4558
+ };
4559
+ });
4560
+ }
4561
+ }
4562
+
4563
+ function buildVersionInfo(version) {
4564
+ return {
4565
+ '@tonconnect/sdk': version.ton_connect_sdk_lib || '',
4566
+ '@tonconnect/ui': version.ton_connect_ui_lib || ''
4567
+ };
4568
+ }
4569
+ function buildTonConnectEvent(detail) {
4570
+ var _a, _b, _c, _d, _e, _f, _g, _h;
4571
+ return {
4572
+ versions: buildVersionInfo(detail.custom_data),
4573
+ network_id: (_a = detail.custom_data.chain_id) !== null && _a !== void 0 ? _a : '',
4574
+ client_id: (_b = detail.custom_data.client_id) !== null && _b !== void 0 ? _b : '',
4575
+ wallet_id: (_c = detail.custom_data.wallet_id) !== null && _c !== void 0 ? _c : '',
4576
+ wallet_address: (_d = detail.wallet_address) !== null && _d !== void 0 ? _d : '',
4577
+ wallet_app_name: (_e = detail.wallet_type) !== null && _e !== void 0 ? _e : '',
4578
+ wallet_app_version: (_f = detail.wallet_version) !== null && _f !== void 0 ? _f : '',
4579
+ wallet_state_init: (_g = detail.wallet_state_init) !== null && _g !== void 0 ? _g : '',
4580
+ trace_id: (_h = detail.trace_id) !== null && _h !== void 0 ? _h : undefined
4581
+ };
4582
+ }
4583
+ function bindEventsTo(eventDispatcher, analytics) {
4584
+ eventDispatcher.addEventListener('ton-connect-ui-wallet-modal-opened', event => {
4585
+ var _a;
4586
+ const { detail } = event;
4587
+ analytics.emitConnectionStarted({
4588
+ client_id: detail.client_id || '',
4589
+ versions: buildVersionInfo(detail.custom_data),
4590
+ main_screen: detail.visible_wallets,
4591
+ trace_id: (_a = detail.trace_id) !== null && _a !== void 0 ? _a : undefined
4592
+ });
4593
+ });
4594
+ eventDispatcher.addEventListener('ton-connect-ui-selected-wallet', event => {
4595
+ var _a, _b;
4596
+ const { detail } = event;
4597
+ analytics.emitConnectionSelectedWallet({
4598
+ client_id: detail.client_id || '',
4599
+ versions: buildVersionInfo(detail.custom_data),
4600
+ main_screen: detail.visible_wallets,
4601
+ wallets_menu: detail.wallets_menu,
4602
+ trace_id: (_a = detail.trace_id) !== null && _a !== void 0 ? _a : undefined,
4603
+ wallet_app_name: (_b = detail.wallet_type) !== null && _b !== void 0 ? _b : '',
4604
+ wallet_redirect_method: detail.wallet_redirect_method,
4605
+ wallet_redirect_link: detail.wallet_redirect_link
4606
+ });
4607
+ });
4608
+ eventDispatcher.addEventListener('ton-connect-connection-completed', event => {
4609
+ const { detail } = event;
4610
+ analytics.emitConnectionCompleted(buildTonConnectEvent(detail));
4611
+ });
4612
+ eventDispatcher.addEventListener('ton-connect-connection-error', event => {
4613
+ var _a, _b;
4614
+ const { detail } = event;
4615
+ analytics.emitConnectionError({
4616
+ client_id: detail.custom_data.client_id || '',
4617
+ wallet_id: detail.custom_data.wallet_id || '',
4618
+ error_code: (_a = detail.error_code) !== null && _a !== void 0 ? _a : 0,
4619
+ error_message: detail.error_message,
4620
+ trace_id: (_b = detail.trace_id) !== null && _b !== void 0 ? _b : undefined
4621
+ });
4622
+ });
4623
+ eventDispatcher.addEventListener('ton-connect-disconnection', event => {
4624
+ const { detail } = event;
4625
+ analytics.emitDisconnection(buildTonConnectEvent(detail));
4626
+ });
4627
+ eventDispatcher.addEventListener('ton-connect-transaction-sent-for-signature', event => {
4628
+ const { detail } = event;
4629
+ analytics.emitTransactionSent(buildTonConnectEvent(detail));
4630
+ });
4631
+ eventDispatcher.addEventListener('ton-connect-transaction-signed', event => {
4632
+ const { detail } = event;
4633
+ analytics.emitTransactionSigned(Object.assign(Object.assign({}, buildTonConnectEvent(detail)), { signed_boc: event.detail.signed_transaction }));
4634
+ });
4635
+ eventDispatcher.addEventListener('ton-connect-transaction-signing-failed', event => {
4636
+ var _a;
4637
+ const { detail } = event;
4638
+ analytics.emitTransactionSigningFailed(Object.assign(Object.assign({}, buildTonConnectEvent(detail)), { valid_until: Number(detail.valid_until), messages: detail.messages.map(message => {
4639
+ var _a, _b, _c, _d;
4640
+ return ({
4641
+ address: (_a = message.address) !== null && _a !== void 0 ? _a : '',
4642
+ amount: (_b = message.amount) !== null && _b !== void 0 ? _b : '',
4643
+ payload: (_c = message.payload) !== null && _c !== void 0 ? _c : '',
4644
+ state_init: (_d = message.state_init) !== null && _d !== void 0 ? _d : ''
4645
+ });
4646
+ }), error_message: detail.error_message, error_code: (_a = detail.error_code) !== null && _a !== void 0 ? _a : 0 }));
4647
+ });
4648
+ eventDispatcher.addEventListener('ton-connect-sign-data-request-initiated', event => {
4649
+ const { detail } = event;
4650
+ analytics === null || analytics === void 0 ? void 0 : analytics.emitSignDataRequestInitiated(buildTonConnectEvent(detail));
4651
+ });
4652
+ eventDispatcher.addEventListener('ton-connect-sign-data-request-completed', event => {
4653
+ const { detail } = event;
4654
+ analytics === null || analytics === void 0 ? void 0 : analytics.emitSignDataRequestCompleted(buildTonConnectEvent(detail));
4655
+ });
4656
+ eventDispatcher.addEventListener('ton-connect-sign-data-request-failed', event => {
4657
+ var _a;
4658
+ const { detail } = event;
4659
+ let signDataValue = '';
4660
+ let signDataSchema = undefined;
4661
+ if (detail.data.type === 'text') {
4662
+ signDataValue = detail.data.text;
4663
+ }
4664
+ if (detail.data.type === 'cell') {
4665
+ signDataValue = detail.data.cell;
4666
+ signDataSchema = detail.data.schema;
4667
+ }
4668
+ if (detail.data.type === 'binary') {
4669
+ signDataValue = detail.data.bytes;
4670
+ }
4671
+ analytics === null || analytics === void 0 ? void 0 : analytics.emitSignDataRequestFailed(Object.assign(Object.assign({}, buildTonConnectEvent(detail)), { sign_data_type: detail.data.type, sign_data_value: signDataValue, sign_data_schema: signDataSchema, error_code: (_a = detail.error_code) !== null && _a !== void 0 ? _a : 0, error_message: detail.error_message }));
4672
+ });
4673
+ }
4674
+
4675
+ class DefaultEnvironment {
4676
+ getClientEnvironment() {
4677
+ return '';
4678
+ }
4679
+ getBrowser() {
4680
+ return '';
4681
+ }
4682
+ getLocale() {
4683
+ return '';
4684
+ }
4685
+ getPlatform() {
4686
+ return '';
4687
+ }
4688
+ getTelegramUser() {
4689
+ return undefined;
4690
+ }
4691
+ }
4692
+
3909
4693
  class TonConnect {
3910
4694
  /**
3911
4695
  * Returns available wallets list.
@@ -3937,13 +4721,15 @@ class TonConnect {
3937
4721
  this.statusChangeSubscriptions.forEach(callback => callback(this._wallet));
3938
4722
  }
3939
4723
  constructor(options) {
4724
+ var _a, _b;
3940
4725
  this.walletsList = new WalletsListManager();
3941
4726
  this._wallet = null;
3942
4727
  this.provider = null;
3943
4728
  this.statusChangeSubscriptions = [];
3944
4729
  this.statusChangeErrorSubscriptions = [];
4730
+ const manifestUrl = (options === null || options === void 0 ? void 0 : options.manifestUrl) || getWebPageManifest();
3945
4731
  this.dappSettings = {
3946
- manifestUrl: (options === null || options === void 0 ? void 0 : options.manifestUrl) || getWebPageManifest(),
4732
+ manifestUrl,
3947
4733
  storage: (options === null || options === void 0 ? void 0 : options.storage) || new DefaultStorage()
3948
4734
  };
3949
4735
  this.walletsRequiredFeatures = options === null || options === void 0 ? void 0 : options.walletsRequiredFeatures;
@@ -3951,10 +4737,24 @@ class TonConnect {
3951
4737
  walletsListSource: options === null || options === void 0 ? void 0 : options.walletsListSource,
3952
4738
  cacheTTLMs: options === null || options === void 0 ? void 0 : options.walletsListCacheTTLMs
3953
4739
  });
4740
+ const eventDispatcher = (_a = options === null || options === void 0 ? void 0 : options.eventDispatcher) !== null && _a !== void 0 ? _a : new BrowserEventDispatcher();
3954
4741
  this.tracker = new TonConnectTracker({
3955
- eventDispatcher: options === null || options === void 0 ? void 0 : options.eventDispatcher,
4742
+ eventDispatcher,
3956
4743
  tonConnectSdkVersion: tonConnectSdkVersion
3957
4744
  });
4745
+ this.environment = (_b = options === null || options === void 0 ? void 0 : options.environment) !== null && _b !== void 0 ? _b : new DefaultEnvironment();
4746
+ // TODO: in production ready make flag to enable them?
4747
+ this.analytics = new AnalyticsManager({ environment: this.environment });
4748
+ const telegramUser = this.environment.getTelegramUser();
4749
+ bindEventsTo(eventDispatcher, this.analytics.scoped({
4750
+ locale: this.environment.getLocale(),
4751
+ browser: this.environment.getBrowser(),
4752
+ platform: this.environment.getPlatform(),
4753
+ tg_id: telegramUser === null || telegramUser === void 0 ? void 0 : telegramUser.id,
4754
+ tma_is_premium: telegramUser === null || telegramUser === void 0 ? void 0 : telegramUser.isPremium,
4755
+ manifest_json_url: manifestUrl,
4756
+ origin_url: getOriginWithPath
4757
+ }));
3958
4758
  if (!this.dappSettings.manifestUrl) {
3959
4759
  throw new DappMetadataError('Dapp tonconnect-manifest.json must be specified if window.location.origin is undefined. See more https://github.com/ton-connect/docs/blob/main/requests-responses.md#app-manifest');
3960
4760
  }
@@ -3987,17 +4787,22 @@ class TonConnect {
3987
4787
  }
3988
4788
  };
3989
4789
  }
3990
- connect(wallet, requestOrOptions) {
3991
- var _a, _b;
4790
+ // eslint-disable-next-line complexity
4791
+ connect(wallet, requestOrOptions, additionalOptions) {
4792
+ var _a, _b, _c;
3992
4793
  // TODO: remove deprecated method
3993
- const options = {};
3994
- if (typeof requestOrOptions === 'object' && 'tonProof' in requestOrOptions) {
4794
+ const options = Object.assign({}, additionalOptions);
4795
+ if (typeof requestOrOptions === 'object' &&
4796
+ requestOrOptions !== null &&
4797
+ 'tonProof' in requestOrOptions) {
3995
4798
  options.request = requestOrOptions;
3996
4799
  }
3997
4800
  if (typeof requestOrOptions === 'object' &&
4801
+ requestOrOptions !== null &&
3998
4802
  ('openingDeadlineMS' in requestOrOptions ||
3999
4803
  'signal' in requestOrOptions ||
4000
- 'request' in requestOrOptions)) {
4804
+ 'request' in requestOrOptions ||
4805
+ 'traceId' in requestOrOptions)) {
4001
4806
  options.request = requestOrOptions === null || requestOrOptions === void 0 ? void 0 : requestOrOptions.request;
4002
4807
  options.openingDeadlineMS = requestOrOptions === null || requestOrOptions === void 0 ? void 0 : requestOrOptions.openingDeadlineMS;
4003
4808
  options.signal = requestOrOptions === null || requestOrOptions === void 0 ? void 0 : requestOrOptions.signal;
@@ -4029,10 +4834,12 @@ class TonConnect {
4029
4834
  (_a = this.provider) === null || _a === void 0 ? void 0 : _a.closeConnection();
4030
4835
  this.provider = null;
4031
4836
  });
4032
- this.tracker.trackConnectionStarted();
4837
+ const traceId = (_c = options === null || options === void 0 ? void 0 : options.traceId) !== null && _c !== void 0 ? _c : UUIDv7();
4838
+ this.tracker.trackConnectionStarted(traceId);
4033
4839
  return this.provider.connect(this.createConnectRequest(options === null || options === void 0 ? void 0 : options.request), {
4034
4840
  openingDeadlineMS: options === null || options === void 0 ? void 0 : options.openingDeadlineMS,
4035
- signal: abortController.signal
4841
+ signal: abortController.signal,
4842
+ traceId
4036
4843
  });
4037
4844
  }
4038
4845
  /**
@@ -4040,13 +4847,14 @@ class TonConnect {
4040
4847
  */
4041
4848
  restoreConnection(options) {
4042
4849
  return __awaiter(this, void 0, void 0, function* () {
4043
- var _a, _b;
4044
- this.tracker.trackConnectionRestoringStarted();
4850
+ var _a, _b, _c;
4851
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
4852
+ this.tracker.trackConnectionRestoringStarted(traceId);
4045
4853
  const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
4046
- (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
4854
+ (_b = this.abortController) === null || _b === void 0 ? void 0 : _b.abort();
4047
4855
  this.abortController = abortController;
4048
4856
  if (abortController.signal.aborted) {
4049
- this.tracker.trackConnectionRestoringError('Connection restoring was aborted');
4857
+ this.tracker.trackConnectionRestoringError('Connection restoring was aborted', traceId);
4050
4858
  return;
4051
4859
  }
4052
4860
  // TODO: potentially race condition here
@@ -4055,17 +4863,17 @@ class TonConnect {
4055
4863
  this.walletsList.getEmbeddedWallet()
4056
4864
  ]);
4057
4865
  if (abortController.signal.aborted) {
4058
- this.tracker.trackConnectionRestoringError('Connection restoring was aborted');
4866
+ this.tracker.trackConnectionRestoringError('Connection restoring was aborted', traceId);
4059
4867
  return;
4060
4868
  }
4061
4869
  let provider = null;
4062
4870
  try {
4063
4871
  switch (bridgeConnectionType) {
4064
4872
  case 'http':
4065
- provider = yield BridgeProvider.fromStorage(this.dappSettings.storage);
4873
+ provider = yield BridgeProvider.fromStorage(this.dappSettings.storage, this.analytics);
4066
4874
  break;
4067
4875
  case 'injected':
4068
- provider = yield InjectedProvider.fromStorage(this.dappSettings.storage);
4876
+ provider = yield InjectedProvider.fromStorage(this.dappSettings.storage, this.analytics);
4069
4877
  break;
4070
4878
  default:
4071
4879
  if (embeddedWallet) {
@@ -4076,8 +4884,8 @@ class TonConnect {
4076
4884
  }
4077
4885
  }
4078
4886
  }
4079
- catch (_c) {
4080
- this.tracker.trackConnectionRestoringError('Provider is not restored');
4887
+ catch (_d) {
4888
+ this.tracker.trackConnectionRestoringError('Provider is not restored', traceId);
4081
4889
  yield this.bridgeConnectionStorage.removeConnection();
4082
4890
  provider === null || provider === void 0 ? void 0 : provider.closeConnection();
4083
4891
  provider = null;
@@ -4085,19 +4893,19 @@ class TonConnect {
4085
4893
  }
4086
4894
  if (abortController.signal.aborted) {
4087
4895
  provider === null || provider === void 0 ? void 0 : provider.closeConnection();
4088
- this.tracker.trackConnectionRestoringError('Connection restoring was aborted');
4896
+ this.tracker.trackConnectionRestoringError('Connection restoring was aborted', traceId);
4089
4897
  return;
4090
4898
  }
4091
4899
  if (!provider) {
4092
4900
  logError('Provider is not restored');
4093
- this.tracker.trackConnectionRestoringError('Provider is not restored');
4901
+ this.tracker.trackConnectionRestoringError('Provider is not restored', traceId);
4094
4902
  return;
4095
4903
  }
4096
- (_b = this.provider) === null || _b === void 0 ? void 0 : _b.closeConnection();
4904
+ (_c = this.provider) === null || _c === void 0 ? void 0 : _c.closeConnection();
4097
4905
  this.provider = provider;
4098
4906
  provider.listen(this.walletEventsListener.bind(this));
4099
4907
  const onAbortRestore = () => {
4100
- this.tracker.trackConnectionRestoringError('Connection restoring was aborted');
4908
+ this.tracker.trackConnectionRestoringError('Connection restoring was aborted', traceId);
4101
4909
  provider === null || provider === void 0 ? void 0 : provider.closeConnection();
4102
4910
  provider = null;
4103
4911
  };
@@ -4105,14 +4913,16 @@ class TonConnect {
4105
4913
  const restoreConnectionTask = callForSuccess((_options) => __awaiter(this, void 0, void 0, function* () {
4106
4914
  yield (provider === null || provider === void 0 ? void 0 : provider.restoreConnection({
4107
4915
  openingDeadlineMS: options === null || options === void 0 ? void 0 : options.openingDeadlineMS,
4108
- signal: _options.signal
4916
+ signal: _options.signal,
4917
+ traceId
4109
4918
  }));
4110
4919
  abortController.signal.removeEventListener('abort', onAbortRestore);
4111
4920
  if (this.connected) {
4112
- this.tracker.trackConnectionRestoringCompleted(this.wallet);
4921
+ const sessionInfo = this.getSessionInfo();
4922
+ this.tracker.trackConnectionRestoringCompleted(this.wallet, sessionInfo, traceId);
4113
4923
  }
4114
4924
  else {
4115
- this.tracker.trackConnectionRestoringError('Connection restoring failed');
4925
+ this.tracker.trackConnectionRestoringError('Connection restoring failed', traceId);
4116
4926
  }
4117
4927
  }), {
4118
4928
  attempts: Number.MAX_SAFE_INTEGER,
@@ -4126,6 +4936,7 @@ class TonConnect {
4126
4936
  }
4127
4937
  sendTransaction(transaction, optionsOrOnRequestSent) {
4128
4938
  return __awaiter(this, void 0, void 0, function* () {
4939
+ var _a, _b, _c;
4129
4940
  // TODO: remove deprecated method
4130
4941
  const options = {};
4131
4942
  if (typeof optionsOrOnRequestSent === 'function') {
@@ -4134,6 +4945,7 @@ class TonConnect {
4134
4945
  else {
4135
4946
  options.onRequestSent = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.onRequestSent;
4136
4947
  options.signal = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.signal;
4948
+ options.traceId = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.traceId;
4137
4949
  }
4138
4950
  // Validate transaction
4139
4951
  const validationError = validateSendTransactionRequest(transaction);
@@ -4156,26 +4968,41 @@ class TonConnect {
4156
4968
  requiredMessagesNumber,
4157
4969
  requireExtraCurrencies
4158
4970
  });
4159
- this.tracker.trackTransactionSentForSignature(this.wallet, transaction);
4971
+ const sessionInfo = this.getSessionInfo();
4972
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
4973
+ this.tracker.trackTransactionSentForSignature(this.wallet, transaction, sessionInfo, traceId);
4160
4974
  const { validUntil, messages } = transaction, tx = __rest(transaction, ["validUntil", "messages"]);
4161
4975
  const from = transaction.from || this.account.address;
4162
4976
  const network = transaction.network || this.account.chain;
4977
+ if (((_b = this.wallet) === null || _b === void 0 ? void 0 : _b.account.chain) && network !== this.wallet.account.chain) {
4978
+ throw new WalletWrongNetworkError('Wallet connected to a wrong network', {
4979
+ cause: {
4980
+ expectedChainId: (_c = this.wallet) === null || _c === void 0 ? void 0 : _c.account.chain,
4981
+ actualChainId: network
4982
+ }
4983
+ });
4984
+ }
4163
4985
  const response = yield this.provider.sendRequest(sendTransactionParser.convertToRpcRequest(Object.assign(Object.assign({}, tx), { from,
4164
4986
  network, valid_until: validUntil, messages: messages.map((_a) => {
4165
4987
  var { extraCurrency, payload, stateInit } = _a, msg = __rest(_a, ["extraCurrency", "payload", "stateInit"]);
4166
4988
  return (Object.assign(Object.assign({}, msg), { payload: normalizeBase64(payload), stateInit: normalizeBase64(stateInit), extra_currency: extraCurrency }));
4167
- }) })), { onRequestSent: options.onRequestSent, signal: abortController.signal });
4989
+ }) })), {
4990
+ onRequestSent: options.onRequestSent,
4991
+ signal: abortController.signal,
4992
+ traceId
4993
+ });
4168
4994
  if (sendTransactionParser.isError(response)) {
4169
- this.tracker.trackTransactionSigningFailed(this.wallet, transaction, response.error.message, response.error.code);
4995
+ this.tracker.trackTransactionSigningFailed(this.wallet, transaction, response.error.message, response.error.code, sessionInfo, traceId);
4170
4996
  return sendTransactionParser.parseAndThrowError(response);
4171
4997
  }
4172
4998
  const result = sendTransactionParser.convertFromRpcResponse(response);
4173
- this.tracker.trackTransactionSigned(this.wallet, transaction, result);
4174
- return result;
4999
+ this.tracker.trackTransactionSigned(this.wallet, transaction, result, sessionInfo, traceId);
5000
+ return Object.assign(Object.assign({}, result), { traceId: response.traceId });
4175
5001
  });
4176
5002
  }
4177
5003
  signData(data, options) {
4178
5004
  return __awaiter(this, void 0, void 0, function* () {
5005
+ var _a, _b, _c;
4179
5006
  const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
4180
5007
  if (abortController.signal.aborted) {
4181
5008
  throw new TonConnectError('data sending was aborted');
@@ -4192,26 +5019,47 @@ class TonConnect {
4192
5019
  }
4193
5020
  this.checkConnection();
4194
5021
  checkSignDataSupport(this.wallet.device.features, { requiredTypes: [data.type] });
4195
- this.tracker.trackDataSentForSignature(this.wallet, data);
5022
+ const sessionInfo = this.getSessionInfo();
5023
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
5024
+ this.tracker.trackDataSentForSignature(this.wallet, data, sessionInfo, traceId);
4196
5025
  const from = data.from || this.account.address;
4197
5026
  const network = data.network || this.account.chain;
5027
+ if (((_b = this.wallet) === null || _b === void 0 ? void 0 : _b.account.chain) && network !== this.wallet.account.chain) {
5028
+ throw new WalletWrongNetworkError('Wallet connected to a wrong network', {
5029
+ cause: {
5030
+ expectedChainId: (_c = this.wallet) === null || _c === void 0 ? void 0 : _c.account.chain,
5031
+ actualChainId: network
5032
+ }
5033
+ });
5034
+ }
4198
5035
  const response = yield this.provider.sendRequest(signDataParser.convertToRpcRequest(Object.assign(Object.assign(Object.assign({}, data), (data.type === 'cell' ? { cell: normalizeBase64(data.cell) } : {})), { from,
4199
- network })), { onRequestSent: options === null || options === void 0 ? void 0 : options.onRequestSent, signal: abortController.signal });
5036
+ network })), { onRequestSent: options === null || options === void 0 ? void 0 : options.onRequestSent, signal: abortController.signal, traceId });
4200
5037
  if (signDataParser.isError(response)) {
4201
- this.tracker.trackDataSigningFailed(this.wallet, data, response.error.message, response.error.code);
5038
+ this.tracker.trackDataSigningFailed(this.wallet, data, response.error.message, response.error.code, sessionInfo, traceId);
4202
5039
  return signDataParser.parseAndThrowError(response);
4203
5040
  }
4204
5041
  const result = signDataParser.convertFromRpcResponse(response);
4205
- this.tracker.trackDataSigned(this.wallet, data, result);
4206
- return result;
5042
+ this.tracker.trackDataSigned(this.wallet, data, result, sessionInfo, traceId);
5043
+ return Object.assign(Object.assign({}, result), { traceId });
4207
5044
  });
4208
5045
  }
5046
+ /**
5047
+ * Set desired network for the connection. Can only be set before connecting.
5048
+ * If wallet connects with a different chain, the SDK will throw an error and abort connection.
5049
+ * @param network desired network id (e.g., '-239', '-3', or custom). Pass undefined to allow any network.
5050
+ */
5051
+ setConnectionNetwork(network) {
5052
+ if (this.connected) {
5053
+ throw new TonConnectError('Cannot change network while wallet is connected');
5054
+ }
5055
+ this.desiredChainId = network;
5056
+ }
4209
5057
  /**
4210
5058
  * Disconnect form thw connected wallet and drop current session.
4211
5059
  */
4212
5060
  disconnect(options) {
4213
5061
  return __awaiter(this, void 0, void 0, function* () {
4214
- var _a;
5062
+ var _a, _b;
4215
5063
  if (!this.connected) {
4216
5064
  throw new WalletNotConnectedError();
4217
5065
  }
@@ -4221,9 +5069,11 @@ class TonConnect {
4221
5069
  if (abortController.signal.aborted) {
4222
5070
  throw new TonConnectError('Disconnect was aborted');
4223
5071
  }
4224
- this.onWalletDisconnected('dapp');
4225
- yield ((_a = this.provider) === null || _a === void 0 ? void 0 : _a.disconnect({
4226
- signal: abortController.signal
5072
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
5073
+ this.onWalletDisconnected('dapp', { traceId });
5074
+ yield ((_b = this.provider) === null || _b === void 0 ? void 0 : _b.disconnect({
5075
+ signal: abortController.signal,
5076
+ traceId
4227
5077
  }));
4228
5078
  prevAbortController === null || prevAbortController === void 0 ? void 0 : prevAbortController.abort();
4229
5079
  });
@@ -4234,7 +5084,7 @@ class TonConnect {
4234
5084
  */
4235
5085
  getSessionId() {
4236
5086
  return __awaiter(this, void 0, void 0, function* () {
4237
- if (!this.provider || !this.connected) {
5087
+ if (!this.provider) {
4238
5088
  return null;
4239
5089
  }
4240
5090
  try {
@@ -4256,6 +5106,30 @@ class TonConnect {
4256
5106
  }
4257
5107
  });
4258
5108
  }
5109
+ getSessionInfo() {
5110
+ var _a;
5111
+ if (((_a = this.provider) === null || _a === void 0 ? void 0 : _a.type) !== 'http') {
5112
+ return null;
5113
+ }
5114
+ if (!('session' in this.provider)) {
5115
+ return null;
5116
+ }
5117
+ try {
5118
+ const session = this.provider.session;
5119
+ if (!session) {
5120
+ return null;
5121
+ }
5122
+ const clientId = session.sessionCrypto.sessionId;
5123
+ let walletId = null;
5124
+ if ('walletPublicKey' in session) {
5125
+ walletId = session.walletPublicKey;
5126
+ }
5127
+ return { clientId, walletId };
5128
+ }
5129
+ catch (_b) {
5130
+ return null;
5131
+ }
5132
+ }
4259
5133
  /**
4260
5134
  * Pause bridge HTTP connection. Might be helpful, if you want to pause connections while browser tab is unfocused,
4261
5135
  * or if you use SDK with NodeJS and want to save server resources.
@@ -4299,10 +5173,10 @@ class TonConnect {
4299
5173
  createProvider(wallet) {
4300
5174
  let provider;
4301
5175
  if (!Array.isArray(wallet) && isWalletConnectionSourceJS(wallet)) {
4302
- provider = new InjectedProvider(this.dappSettings.storage, wallet.jsBridgeKey);
5176
+ provider = new InjectedProvider(this.dappSettings.storage, wallet.jsBridgeKey, this.analytics);
4303
5177
  }
4304
5178
  else {
4305
- provider = new BridgeProvider(this.dappSettings.storage, wallet);
5179
+ provider = new BridgeProvider(this.dappSettings.storage, wallet, this.analytics);
4306
5180
  }
4307
5181
  provider.listen(this.walletEventsListener.bind(this));
4308
5182
  return provider;
@@ -4310,19 +5184,19 @@ class TonConnect {
4310
5184
  walletEventsListener(e) {
4311
5185
  switch (e.event) {
4312
5186
  case 'connect':
4313
- this.onWalletConnected(e.payload);
5187
+ this.onWalletConnected(e.payload, { traceId: e.traceId });
4314
5188
  break;
4315
5189
  case 'connect_error':
4316
- this.tracker.trackConnectionError(e.payload.message, e.payload.code);
5190
+ this.tracker.trackConnectionError(e.payload.message, e.payload.code, this.getSessionInfo(), e.traceId);
4317
5191
  const walletError = connectErrorsParser.parseError(e.payload);
4318
5192
  this.onWalletConnectError(walletError);
4319
5193
  break;
4320
5194
  case 'disconnect':
4321
- this.onWalletDisconnected('wallet');
5195
+ this.onWalletDisconnected('wallet', { traceId: e.traceId });
4322
5196
  }
4323
5197
  }
4324
- onWalletConnected(connectEvent) {
4325
- var _a;
5198
+ onWalletConnected(connectEvent, options) {
5199
+ var _a, _b;
4326
5200
  const tonAccountItem = connectEvent.items.find(item => item.name === 'ton_addr');
4327
5201
  const tonProofItem = connectEvent.items.find(item => item.name === 'ton_proof');
4328
5202
  if (!tonAccountItem) {
@@ -4344,6 +5218,15 @@ class TonConnect {
4344
5218
  publicKey: tonAccountItem.publicKey
4345
5219
  }
4346
5220
  };
5221
+ if (this.desiredChainId && wallet.account.chain !== this.desiredChainId) {
5222
+ const expectedChainId = this.desiredChainId;
5223
+ const actualChainId = wallet.account.chain;
5224
+ (_b = this.provider) === null || _b === void 0 ? void 0 : _b.disconnect();
5225
+ this.onWalletConnectError(new WalletWrongNetworkError('Wallet connected to a wrong network', {
5226
+ cause: { expectedChainId, actualChainId }
5227
+ }));
5228
+ return;
5229
+ }
4347
5230
  if (tonProofItem) {
4348
5231
  const validationError = validateTonProofItemReply(tonProofItem);
4349
5232
  let tonProof = undefined;
@@ -4401,7 +5284,8 @@ class TonConnect {
4401
5284
  wallet.connectItems = { tonProof };
4402
5285
  }
4403
5286
  this.wallet = wallet;
4404
- this.tracker.trackConnectionCompleted(wallet);
5287
+ const sessionInfo = this.getSessionInfo();
5288
+ this.tracker.trackConnectionCompleted(wallet, sessionInfo, options === null || options === void 0 ? void 0 : options.traceId);
4405
5289
  }
4406
5290
  onWalletConnectError(error) {
4407
5291
  this.statusChangeErrorSubscriptions.forEach(errorsHandler => errorsHandler(error));
@@ -4411,8 +5295,9 @@ class TonConnect {
4411
5295
  throw error;
4412
5296
  }
4413
5297
  }
4414
- onWalletDisconnected(scope) {
4415
- this.tracker.trackDisconnection(this.wallet, scope);
5298
+ onWalletDisconnected(scope, options) {
5299
+ const sessionInfo = this.getSessionInfo();
5300
+ this.tracker.trackDisconnection(this.wallet, scope, sessionInfo, options === null || options === void 0 ? void 0 : options.traceId);
4416
5301
  this.wallet = null;
4417
5302
  }
4418
5303
  checkConnection() {
@@ -4422,9 +5307,7 @@ class TonConnect {
4422
5307
  }
4423
5308
  createConnectRequest(request) {
4424
5309
  const items = [
4425
- {
4426
- name: 'ton_addr'
4427
- }
5310
+ Object.assign({ name: 'ton_addr' }, (this.desiredChainId ? { network: this.desiredChainId } : {}))
4428
5311
  ];
4429
5312
  if (request === null || request === void 0 ? void 0 : request.tonProof) {
4430
5313
  items.push({
@@ -4481,6 +5364,7 @@ exports.LocalstorageNotFoundError = LocalstorageNotFoundError;
4481
5364
  exports.ParseHexError = ParseHexError;
4482
5365
  exports.TonConnect = TonConnect;
4483
5366
  exports.TonConnectError = TonConnectError;
5367
+ exports.UUIDv7 = UUIDv7;
4484
5368
  exports.UnknownAppError = UnknownAppError;
4485
5369
  exports.UnknownError = UnknownError;
4486
5370
  exports.UserRejectsError = UserRejectsError;
@@ -4489,6 +5373,7 @@ exports.WalletMissingRequiredFeaturesError = WalletMissingRequiredFeaturesError;
4489
5373
  exports.WalletNotConnectedError = WalletNotConnectedError;
4490
5374
  exports.WalletNotInjectedError = WalletNotInjectedError;
4491
5375
  exports.WalletNotSupportFeatureError = WalletNotSupportFeatureError;
5376
+ exports.WalletWrongNetworkError = WalletWrongNetworkError;
4492
5377
  exports.WalletsListManager = WalletsListManager;
4493
5378
  exports.WrongAddressError = WrongAddressError;
4494
5379
  exports.checkRequiredWalletFeatures = checkRequiredWalletFeatures;
@@ -4504,13 +5389,17 @@ exports.createDataSigningFailedEvent = createDataSigningFailedEvent;
4504
5389
  exports.createDisconnectionEvent = createDisconnectionEvent;
4505
5390
  exports.createRequestVersionEvent = createRequestVersionEvent;
4506
5391
  exports.createResponseVersionEvent = createResponseVersionEvent;
5392
+ exports.createSelectedWalletEvent = createSelectedWalletEvent;
4507
5393
  exports.createTransactionSentForSignatureEvent = createTransactionSentForSignatureEvent;
4508
5394
  exports.createTransactionSignedEvent = createTransactionSignedEvent;
4509
5395
  exports.createTransactionSigningFailedEvent = createTransactionSigningFailedEvent;
4510
5396
  exports.createVersionInfo = createVersionInfo;
5397
+ exports.createWalletModalOpenedEvent = createWalletModalOpenedEvent;
5398
+ exports.decodeTelegramUrlParameters = decodeTelegramUrlParameters;
4511
5399
  exports.default = TonConnect;
4512
5400
  exports.enableQaMode = enableQaMode;
4513
5401
  exports.encodeTelegramUrlParameters = encodeTelegramUrlParameters;
5402
+ exports.isConnectUrl = isConnectUrl;
4514
5403
  exports.isQaModeEnabled = isQaModeEnabled;
4515
5404
  exports.isTelegramUrl = isTelegramUrl;
4516
5405
  exports.isWalletInfoCurrentlyEmbedded = isWalletInfoCurrentlyEmbedded;