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