@tonconnect/sdk 3.3.1 → 3.4.0-beta.0

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
@@ -392,6 +392,12 @@ function isTelegramUrl(link) {
392
392
  const url = new URL(link);
393
393
  return url.protocol === 'tg:' || url.hostname === 't.me';
394
394
  }
395
+ function isConnectUrl(link) {
396
+ if (!link) {
397
+ return false;
398
+ }
399
+ return link.includes('ton_addr') || link.includes('ton--5Faddr');
400
+ }
395
401
  function encodeTelegramUrlParameters(parameters) {
396
402
  return parameters
397
403
  .replaceAll('.', '%2E')
@@ -401,6 +407,15 @@ function encodeTelegramUrlParameters(parameters) {
401
407
  .replaceAll('=', '__')
402
408
  .replaceAll('%', '--');
403
409
  }
410
+ function decodeTelegramUrlParameters(parameters) {
411
+ return parameters
412
+ .replaceAll('--', '%')
413
+ .replaceAll('__', '=')
414
+ .replaceAll('-', '&')
415
+ .replaceAll('%5F', '_')
416
+ .replaceAll('%2D', '-')
417
+ .replaceAll('%2E', '.');
418
+ }
404
419
 
405
420
  /**
406
421
  * Delays the execution of code for a specified number of milliseconds.
@@ -635,7 +650,7 @@ class BridgeGateway {
635
650
  const eventSource = this.eventSource.current();
636
651
  return (eventSource === null || eventSource === void 0 ? void 0 : eventSource.readyState) === EventSource.CONNECTING;
637
652
  }
638
- constructor(storage, bridgeUrl, sessionId, listener, errorsListener) {
653
+ constructor(storage, bridgeUrl, sessionId, listener, errorsListener, analyticsManager) {
639
654
  this.bridgeUrl = bridgeUrl;
640
655
  this.sessionId = sessionId;
641
656
  this.listener = listener;
@@ -646,7 +661,7 @@ class BridgeGateway {
646
661
  this.defaultTtl = 300;
647
662
  this.defaultReconnectDelay = 2000;
648
663
  this.defaultResendDelay = 5000;
649
- this.eventSource = createResource((signal, openingDeadlineMS) => __awaiter(this, void 0, void 0, function* () {
664
+ this.eventSource = createResource((signal, openingDeadlineMS, traceId) => __awaiter(this, void 0, void 0, function* () {
650
665
  const eventSourceConfig = {
651
666
  bridgeUrl: this.bridgeUrl,
652
667
  ssePath: this.ssePath,
@@ -655,17 +670,41 @@ class BridgeGateway {
655
670
  errorHandler: this.errorsHandler.bind(this),
656
671
  messageHandler: this.messagesHandler.bind(this),
657
672
  signal: signal,
658
- openingDeadlineMS: openingDeadlineMS
673
+ openingDeadlineMS: openingDeadlineMS,
674
+ traceId
659
675
  };
660
676
  return yield createEventSource(eventSourceConfig);
661
677
  }), (resource) => __awaiter(this, void 0, void 0, function* () {
662
678
  resource.close();
663
679
  }));
664
680
  this.bridgeGatewayStorage = new HttpBridgeGatewayStorage(storage, bridgeUrl);
681
+ this.analytics = analyticsManager === null || analyticsManager === void 0 ? void 0 : analyticsManager.scoped({
682
+ bridge_url: bridgeUrl,
683
+ client_id: sessionId
684
+ });
665
685
  }
666
686
  registerSession(options) {
667
687
  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);
688
+ var _a, _b, _c;
689
+ try {
690
+ (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.emitBridgeClientConnectStarted({
691
+ trace_id: options === null || options === void 0 ? void 0 : options.traceId
692
+ });
693
+ const connectionStarted = Date.now();
694
+ 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);
695
+ const bridgeConnectDuration = Date.now() - connectionStarted;
696
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitBridgeClientConnectEstablished({
697
+ bridge_connect_duration: bridgeConnectDuration,
698
+ trace_id: options === null || options === void 0 ? void 0 : options.traceId
699
+ });
700
+ }
701
+ catch (error) {
702
+ (_c = this.analytics) === null || _c === void 0 ? void 0 : _c.emitBridgeClientConnectError({
703
+ trace_id: options === null || options === void 0 ? void 0 : options.traceId,
704
+ error_message: String(error)
705
+ });
706
+ throw error;
707
+ }
669
708
  });
670
709
  }
671
710
  send(message, receiver, topic, ttlOrOptions) {
@@ -680,12 +719,16 @@ class BridgeGateway {
680
719
  options.ttl = ttlOrOptions === null || ttlOrOptions === void 0 ? void 0 : ttlOrOptions.ttl;
681
720
  options.signal = ttlOrOptions === null || ttlOrOptions === void 0 ? void 0 : ttlOrOptions.signal;
682
721
  options.attempts = ttlOrOptions === null || ttlOrOptions === void 0 ? void 0 : ttlOrOptions.attempts;
722
+ options.traceId = ttlOrOptions === null || ttlOrOptions === void 0 ? void 0 : ttlOrOptions.traceId;
683
723
  }
684
724
  const url = new URL(addPathToUrl(this.bridgeUrl, this.postPath));
685
725
  url.searchParams.append('client_id', this.sessionId);
686
726
  url.searchParams.append('to', receiver);
687
727
  url.searchParams.append('ttl', ((options === null || options === void 0 ? void 0 : options.ttl) || this.defaultTtl).toString());
688
728
  url.searchParams.append('topic', topic);
729
+ if (options === null || options === void 0 ? void 0 : options.traceId) {
730
+ url.searchParams.append('trace_id', options.traceId);
731
+ }
689
732
  const body = Base64.encode(message);
690
733
  yield callForSuccess((options) => __awaiter(this, void 0, void 0, function* () {
691
734
  const response = yield this.post(url, body, options.signal);
@@ -764,7 +807,12 @@ class BridgeGateway {
764
807
  }
765
808
  let bridgeIncomingMessage;
766
809
  try {
767
- bridgeIncomingMessage = JSON.parse(e.data);
810
+ const bridgeIncomingMessageRaw = JSON.parse(e.data);
811
+ bridgeIncomingMessage = {
812
+ message: bridgeIncomingMessageRaw.message,
813
+ from: bridgeIncomingMessageRaw.from,
814
+ traceId: bridgeIncomingMessageRaw.trace_id
815
+ };
768
816
  }
769
817
  catch (_) {
770
818
  throw new TonConnectError(`Bridge message parse failed, message ${e.data}`);
@@ -793,6 +841,9 @@ function createEventSource(config) {
793
841
  if (lastEventId) {
794
842
  url.searchParams.append('last_event_id', lastEventId);
795
843
  }
844
+ if (config.traceId) {
845
+ url.searchParams.append('trace_id', config.traceId);
846
+ }
796
847
  if (signal.aborted) {
797
848
  reject(new TonConnectError('Bridge connection aborted'));
798
849
  return;
@@ -1018,20 +1069,189 @@ class BridgeConnectionStorage {
1018
1069
 
1019
1070
  const PROTOCOL_VERSION = 2;
1020
1071
 
1072
+ /**
1073
+ * The MIT License (MIT)
1074
+ *
1075
+ * Copyright (c) 2010-2020 Robert Kieffer and other contributors
1076
+ *
1077
+ * 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:
1078
+ *
1079
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1080
+ *
1081
+ * 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.
1082
+ */
1083
+ // Unique ID creation requires a high quality random # generator. In the browser we therefore
1084
+ // require the crypto API and do not support built-in fallback to lower quality random number
1085
+ // generators (like Math.random()).
1086
+ let getRandomValues;
1087
+ const rnds8 = new Uint8Array(16);
1088
+ function rng() {
1089
+ // lazy load so that environments that need to polyfill have a chance to do so
1090
+ if (!getRandomValues) {
1091
+ if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
1092
+ throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
1093
+ }
1094
+ getRandomValues = crypto.getRandomValues.bind(crypto);
1095
+ }
1096
+ return getRandomValues(rnds8);
1097
+ }
1098
+
1099
+ /**
1100
+ * The MIT License (MIT)
1101
+ *
1102
+ * Copyright (c) 2010-2020 Robert Kieffer and other contributors
1103
+ *
1104
+ * 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:
1105
+ *
1106
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1107
+ *
1108
+ * 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.
1109
+ */
1110
+ /**
1111
+ * Convert array of 16 byte values to UUID string format of the form:
1112
+ * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
1113
+ */
1114
+ const byteToHex = [];
1115
+ for (let i = 0; i < 256; ++i) {
1116
+ byteToHex.push((i + 0x100).toString(16).slice(1));
1117
+ }
1118
+ function unsafeStringify(arr, offset = 0) {
1119
+ // Note: Be careful editing this code! It's been tuned for performance
1120
+ // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
1121
+ //
1122
+ // Note to future-self: No, you can't remove the `toLowerCase()` call.
1123
+ // REF: https://github.com/uuidjs/uuid/pull/677#issuecomment-1757351351
1124
+ return (byteToHex[arr[offset + 0]] +
1125
+ byteToHex[arr[offset + 1]] +
1126
+ byteToHex[arr[offset + 2]] +
1127
+ byteToHex[arr[offset + 3]] +
1128
+ '-' +
1129
+ byteToHex[arr[offset + 4]] +
1130
+ byteToHex[arr[offset + 5]] +
1131
+ '-' +
1132
+ byteToHex[arr[offset + 6]] +
1133
+ byteToHex[arr[offset + 7]] +
1134
+ '-' +
1135
+ byteToHex[arr[offset + 8]] +
1136
+ byteToHex[arr[offset + 9]] +
1137
+ '-' +
1138
+ byteToHex[arr[offset + 10]] +
1139
+ byteToHex[arr[offset + 11]] +
1140
+ byteToHex[arr[offset + 12]] +
1141
+ byteToHex[arr[offset + 13]] +
1142
+ byteToHex[arr[offset + 14]] +
1143
+ byteToHex[arr[offset + 15]]).toLowerCase();
1144
+ }
1145
+
1146
+ /**
1147
+ * The MIT License (MIT)
1148
+ *
1149
+ * Copyright (c) 2010-2020 Robert Kieffer and other contributors
1150
+ *
1151
+ * 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:
1152
+ *
1153
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1154
+ *
1155
+ * 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.
1156
+ */
1157
+ const _state = {};
1158
+ function UUIDv7(options, buf, offset) {
1159
+ var _a, _b, _c;
1160
+ let bytes;
1161
+ if (options) {
1162
+ // With options: Make UUID independent of internal state
1163
+ 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);
1164
+ }
1165
+ else {
1166
+ // No options: Use internal state
1167
+ const now = Date.now();
1168
+ const rnds = rng();
1169
+ updateV7State(_state, now, rnds);
1170
+ bytes = v7Bytes(rnds, _state.msecs, _state.seq, buf, offset);
1171
+ }
1172
+ return buf !== null && buf !== void 0 ? buf : unsafeStringify(bytes);
1173
+ }
1174
+ // (Private!) Do not use. This method is only exported for testing purposes
1175
+ // and may change without notice.
1176
+ function updateV7State(state, now, rnds) {
1177
+ var _a, _b;
1178
+ (_a = state.msecs) !== null && _a !== void 0 ? _a : (state.msecs = -Infinity);
1179
+ (_b = state.seq) !== null && _b !== void 0 ? _b : (state.seq = 0);
1180
+ if (now > state.msecs) {
1181
+ // Time has moved on! Pick a new random sequence number
1182
+ state.seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9];
1183
+ state.msecs = now;
1184
+ }
1185
+ else {
1186
+ // Bump sequence counter w/ 32-bit rollover
1187
+ state.seq = (state.seq + 1) | 0;
1188
+ // In case of rollover, bump timestamp to preserve monotonicity. This is
1189
+ // allowed by the RFC and should self-correct as the system clock catches
1190
+ // up. See https://www.rfc-editor.org/rfc/rfc9562.html#section-6.2-9.4
1191
+ if (state.seq === 0) {
1192
+ state.msecs++;
1193
+ }
1194
+ }
1195
+ return state;
1196
+ }
1197
+ function v7Bytes(rnds, msecs, seq, buf, offset = 0) {
1198
+ if (rnds.length < 16) {
1199
+ throw new Error('Random bytes length must be >= 16');
1200
+ }
1201
+ if (!buf) {
1202
+ buf = new Uint8Array(16);
1203
+ offset = 0;
1204
+ }
1205
+ else {
1206
+ if (offset < 0 || offset + 16 > buf.length) {
1207
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
1208
+ }
1209
+ }
1210
+ // Defaults
1211
+ msecs !== null && msecs !== void 0 ? msecs : (msecs = Date.now());
1212
+ seq !== null && seq !== void 0 ? seq : (seq = ((rnds[6] * 0x7f) << 24) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]);
1213
+ // byte 0-5: timestamp (48 bits)
1214
+ buf[offset++] = (msecs / 0x10000000000) & 0xff;
1215
+ buf[offset++] = (msecs / 0x100000000) & 0xff;
1216
+ buf[offset++] = (msecs / 0x1000000) & 0xff;
1217
+ buf[offset++] = (msecs / 0x10000) & 0xff;
1218
+ buf[offset++] = (msecs / 0x100) & 0xff;
1219
+ buf[offset++] = msecs & 0xff;
1220
+ // byte 6: `version` (4 bits) | sequence bits 28-31 (4 bits)
1221
+ buf[offset++] = 0x70 | ((seq >>> 28) & 0x0f);
1222
+ // byte 7: sequence bits 20-27 (8 bits)
1223
+ buf[offset++] = (seq >>> 20) & 0xff;
1224
+ // byte 8: `variant` (2 bits) | sequence bits 14-19 (6 bits)
1225
+ buf[offset++] = 0x80 | ((seq >>> 14) & 0x3f);
1226
+ // byte 9: sequence bits 6-13 (8 bits)
1227
+ buf[offset++] = (seq >>> 6) & 0xff;
1228
+ // byte 10: sequence bits 0-5 (6 bits) | random (2 bits)
1229
+ buf[offset++] = ((seq << 2) & 0xff) | (rnds[10] & 0x03);
1230
+ // bytes 11-15: random (40 bits)
1231
+ buf[offset++] = rnds[11];
1232
+ buf[offset++] = rnds[12];
1233
+ buf[offset++] = rnds[13];
1234
+ buf[offset++] = rnds[14];
1235
+ buf[offset++] = rnds[15];
1236
+ return buf;
1237
+ }
1238
+
1021
1239
  class BridgeProvider {
1022
- static fromStorage(storage) {
1240
+ static fromStorage(storage, analyticsManager) {
1023
1241
  return __awaiter(this, void 0, void 0, function* () {
1024
1242
  const bridgeConnectionStorage = new BridgeConnectionStorage(storage);
1025
1243
  const connection = yield bridgeConnectionStorage.getHttpConnection();
1026
1244
  if (isPendingConnectionHttp(connection)) {
1027
- return new BridgeProvider(storage, connection.connectionSource);
1245
+ return new BridgeProvider(storage, connection.connectionSource, analyticsManager);
1028
1246
  }
1029
- return new BridgeProvider(storage, { bridgeUrl: connection.session.bridgeUrl });
1247
+ return new BridgeProvider(storage, { bridgeUrl: connection.session.bridgeUrl }, analyticsManager);
1030
1248
  });
1031
1249
  }
1032
- constructor(storage, walletConnectionSource) {
1250
+ constructor(storage, walletConnectionSource, analyticsManager) {
1251
+ var _a;
1033
1252
  this.storage = storage;
1034
1253
  this.walletConnectionSource = walletConnectionSource;
1254
+ this.analyticsManager = analyticsManager;
1035
1255
  this.type = 'http';
1036
1256
  this.standardUniversalLink = 'tc://';
1037
1257
  this.pendingRequests = new Map();
@@ -1042,11 +1262,13 @@ class BridgeProvider {
1042
1262
  this.defaultOpeningDeadlineMS = 12000;
1043
1263
  this.defaultRetryTimeoutMS = 2000;
1044
1264
  this.connectionStorage = new BridgeConnectionStorage(storage);
1265
+ this.analytics = (_a = this.analyticsManager) === null || _a === void 0 ? void 0 : _a.scoped();
1045
1266
  }
1046
1267
  connect(message, options) {
1047
- var _a;
1268
+ var _a, _b;
1269
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1048
1270
  const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
1049
- (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
1271
+ (_b = this.abortController) === null || _b === void 0 ? void 0 : _b.abort();
1050
1272
  this.abortController = abortController;
1051
1273
  this.closeGateways();
1052
1274
  const sessionCrypto = new SessionCrypto();
@@ -1070,7 +1292,8 @@ class BridgeProvider {
1070
1292
  var _a;
1071
1293
  return this.openGateways(sessionCrypto, {
1072
1294
  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
1295
+ signal: _options === null || _options === void 0 ? void 0 : _options.signal,
1296
+ traceId
1074
1297
  });
1075
1298
  }, {
1076
1299
  attempts: Number.MAX_SAFE_INTEGER,
@@ -1082,13 +1305,14 @@ class BridgeProvider {
1082
1305
  this.walletConnectionSource.universalLink
1083
1306
  ? this.walletConnectionSource.universalLink
1084
1307
  : this.standardUniversalLink;
1085
- return this.generateUniversalLink(universalLink, message);
1308
+ return this.generateUniversalLink(universalLink, message, { traceId });
1086
1309
  }
1087
1310
  restoreConnection(options) {
1088
1311
  return __awaiter(this, void 0, void 0, function* () {
1089
- var _a, _b;
1312
+ var _a, _b, _c;
1313
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1090
1314
  const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
1091
- (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
1315
+ (_b = this.abortController) === null || _b === void 0 ? void 0 : _b.abort();
1092
1316
  this.abortController = abortController;
1093
1317
  if (abortController.signal.aborted) {
1094
1318
  return;
@@ -1101,7 +1325,7 @@ class BridgeProvider {
1101
1325
  if (abortController.signal.aborted) {
1102
1326
  return;
1103
1327
  }
1104
- const openingDeadlineMS = (_b = options === null || options === void 0 ? void 0 : options.openingDeadlineMS) !== null && _b !== void 0 ? _b : this.defaultOpeningDeadlineMS;
1328
+ const openingDeadlineMS = (_c = options === null || options === void 0 ? void 0 : options.openingDeadlineMS) !== null && _c !== void 0 ? _c : this.defaultOpeningDeadlineMS;
1105
1329
  if (isPendingConnectionHttp(storedConnection)) {
1106
1330
  this.session = {
1107
1331
  sessionCrypto: storedConnection.sessionCrypto,
@@ -1111,7 +1335,8 @@ class BridgeProvider {
1111
1335
  };
1112
1336
  return yield this.openGateways(storedConnection.sessionCrypto, {
1113
1337
  openingDeadlineMS: openingDeadlineMS,
1114
- signal: abortController === null || abortController === void 0 ? void 0 : abortController.signal
1338
+ signal: abortController === null || abortController === void 0 ? void 0 : abortController.signal,
1339
+ traceId: options === null || options === void 0 ? void 0 : options.traceId
1115
1340
  });
1116
1341
  }
1117
1342
  if (Array.isArray(this.walletConnectionSource)) {
@@ -1122,17 +1347,18 @@ class BridgeProvider {
1122
1347
  logDebug('Gateway is already opened, closing previous gateway');
1123
1348
  yield this.gateway.close();
1124
1349
  }
1125
- this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, storedConnection.session.sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
1350
+ this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, storedConnection.session.sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this), this.analyticsManager);
1126
1351
  if (abortController.signal.aborted) {
1127
1352
  return;
1128
1353
  }
1129
1354
  // notify listeners about stored connection
1130
- this.listeners.forEach(listener => listener(storedConnection.connectEvent));
1355
+ this.listeners.forEach(listener => listener(Object.assign(Object.assign({}, storedConnection.connectEvent), { traceId })));
1131
1356
  // wait for the connection to be opened
1132
1357
  try {
1133
1358
  yield callForSuccess(options => this.gateway.registerSession({
1134
1359
  openingDeadlineMS: openingDeadlineMS,
1135
- signal: options.signal
1360
+ signal: options.signal,
1361
+ traceId
1136
1362
  }), {
1137
1363
  attempts: Number.MAX_SAFE_INTEGER,
1138
1364
  delayMs: this.defaultRetryTimeoutMS,
@@ -1140,12 +1366,13 @@ class BridgeProvider {
1140
1366
  });
1141
1367
  }
1142
1368
  catch (e) {
1143
- yield this.disconnect({ signal: abortController.signal });
1369
+ yield this.disconnect({ signal: abortController.signal, traceId });
1144
1370
  return;
1145
1371
  }
1146
1372
  });
1147
1373
  }
1148
1374
  sendRequest(request, optionsOrOnRequestSent) {
1375
+ var _a;
1149
1376
  // TODO: remove deprecated method
1150
1377
  const options = {};
1151
1378
  if (typeof optionsOrOnRequestSent === 'function') {
@@ -1155,9 +1382,11 @@ class BridgeProvider {
1155
1382
  options.onRequestSent = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.onRequestSent;
1156
1383
  options.signal = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.signal;
1157
1384
  options.attempts = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.attempts;
1385
+ options.traceId = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.traceId;
1158
1386
  }
1387
+ (_a = options.traceId) !== null && _a !== void 0 ? _a : (options.traceId = UUIDv7());
1159
1388
  return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
1160
- var _a;
1389
+ var _a, _b;
1161
1390
  if (!this.gateway || !this.session || !('walletPublicKey' in this.session)) {
1162
1391
  throw new TonConnectError('Trying to send bridge request without session');
1163
1392
  }
@@ -1166,8 +1395,20 @@ class BridgeProvider {
1166
1395
  logDebug('Send http-bridge request:', Object.assign(Object.assign({}, request), { id }));
1167
1396
  const encodedRequest = this.session.sessionCrypto.encrypt(JSON.stringify(Object.assign(Object.assign({}, request), { id })), hexToByteArray(this.session.walletPublicKey));
1168
1397
  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);
1398
+ (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.emitBridgeClientMessageSent({
1399
+ bridge_url: this.gateway.bridgeUrl,
1400
+ client_id: this.session.sessionCrypto.sessionId,
1401
+ wallet_id: this.session.walletPublicKey,
1402
+ message_id: id,
1403
+ request_type: request.method,
1404
+ trace_id: options.traceId
1405
+ });
1406
+ yield this.gateway.send(encodedRequest, this.session.walletPublicKey, request.method, {
1407
+ attempts: options === null || options === void 0 ? void 0 : options.attempts,
1408
+ signal: options === null || options === void 0 ? void 0 : options.signal,
1409
+ traceId: options.traceId
1410
+ });
1411
+ (_b = options === null || options === void 0 ? void 0 : options.onRequestSent) === null || _b === void 0 ? void 0 : _b.call(options);
1171
1412
  this.pendingRequests.set(id.toString(), resolve);
1172
1413
  }
1173
1414
  catch (e) {
@@ -1183,6 +1424,8 @@ class BridgeProvider {
1183
1424
  }
1184
1425
  disconnect(options) {
1185
1426
  return __awaiter(this, void 0, void 0, function* () {
1427
+ var _a;
1428
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1186
1429
  return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
1187
1430
  let called = false;
1188
1431
  let timeoutId = null;
@@ -1201,7 +1444,8 @@ class BridgeProvider {
1201
1444
  yield this.sendRequest({ method: 'disconnect', params: [] }, {
1202
1445
  onRequestSent: onRequestSent,
1203
1446
  signal: abortController.signal,
1204
- attempts: 1
1447
+ attempts: 1,
1448
+ traceId
1205
1449
  });
1206
1450
  }
1207
1451
  catch (e) {
@@ -1257,8 +1501,32 @@ class BridgeProvider {
1257
1501
  }
1258
1502
  gatewayListener(bridgeIncomingMessage) {
1259
1503
  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)));
1504
+ var _a, _b, _c;
1505
+ const traceId = (_a = bridgeIncomingMessage.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1506
+ let walletMessage;
1507
+ try {
1508
+ walletMessage = JSON.parse(this.session.sessionCrypto.decrypt(Base64.decode(bridgeIncomingMessage.message).toUint8Array(), hexToByteArray(bridgeIncomingMessage.from)));
1509
+ }
1510
+ catch (err) {
1511
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitBridgeClientMessageDecodeError({
1512
+ bridge_url: this.session.bridgeUrl,
1513
+ client_id: this.session.sessionCrypto.sessionId,
1514
+ wallet_id: bridgeIncomingMessage.from,
1515
+ error_message: String(err),
1516
+ trace_id: bridgeIncomingMessage === null || bridgeIncomingMessage === void 0 ? void 0 : bridgeIncomingMessage.traceId
1517
+ });
1518
+ throw err;
1519
+ }
1261
1520
  logDebug('Wallet message received:', walletMessage);
1521
+ const requestType = 'event' in walletMessage ? walletMessage.event : '';
1522
+ (_c = this.analytics) === null || _c === void 0 ? void 0 : _c.emitBridgeClientMessageReceived({
1523
+ bridge_url: this.session.bridgeUrl,
1524
+ client_id: this.session.sessionCrypto.sessionId,
1525
+ wallet_id: bridgeIncomingMessage.from,
1526
+ message_id: String(walletMessage.id),
1527
+ request_type: requestType,
1528
+ trace_id: bridgeIncomingMessage === null || bridgeIncomingMessage === void 0 ? void 0 : bridgeIncomingMessage.traceId
1529
+ });
1262
1530
  if (!('event' in walletMessage)) {
1263
1531
  const id = walletMessage.id.toString();
1264
1532
  const resolve = this.pendingRequests.get(id);
@@ -1266,7 +1534,7 @@ class BridgeProvider {
1266
1534
  logDebug(`Response id ${id} doesn't match any request's id`);
1267
1535
  return;
1268
1536
  }
1269
- resolve(walletMessage);
1537
+ resolve(Object.assign(Object.assign({}, walletMessage), { traceId }));
1270
1538
  this.pendingRequests.delete(id);
1271
1539
  return;
1272
1540
  }
@@ -1289,7 +1557,7 @@ class BridgeProvider {
1289
1557
  logDebug(`Removing bridge and session: received disconnect event`);
1290
1558
  yield this.removeBridgeAndSession();
1291
1559
  }
1292
- listeners.forEach(listener => listener(walletMessage));
1560
+ listeners.forEach(listener => listener(Object.assign(Object.assign({}, walletMessage), { traceId })));
1293
1561
  });
1294
1562
  }
1295
1563
  gatewayErrorsListener(e) {
@@ -1317,21 +1585,22 @@ class BridgeProvider {
1317
1585
  yield this.connectionStorage.removeConnection();
1318
1586
  });
1319
1587
  }
1320
- generateUniversalLink(universalLink, message) {
1588
+ generateUniversalLink(universalLink, message, options) {
1321
1589
  if (isTelegramUrl(universalLink)) {
1322
- return this.generateTGUniversalLink(universalLink, message);
1590
+ return this.generateTGUniversalLink(universalLink, message, options);
1323
1591
  }
1324
- return this.generateRegularUniversalLink(universalLink, message);
1592
+ return this.generateRegularUniversalLink(universalLink, message, options);
1325
1593
  }
1326
- generateRegularUniversalLink(universalLink, message) {
1594
+ generateRegularUniversalLink(universalLink, message, options) {
1327
1595
  const url = new URL(universalLink);
1328
1596
  url.searchParams.append('v', PROTOCOL_VERSION.toString());
1329
1597
  url.searchParams.append('id', this.session.sessionCrypto.sessionId);
1598
+ url.searchParams.append('trace_id', options.traceId);
1330
1599
  url.searchParams.append('r', JSON.stringify(message));
1331
1600
  return url.toString();
1332
1601
  }
1333
- generateTGUniversalLink(universalLink, message) {
1334
- const urlToWrap = this.generateRegularUniversalLink('about:blank', message);
1602
+ generateTGUniversalLink(universalLink, message, options) {
1603
+ const urlToWrap = this.generateRegularUniversalLink('about:blank', message, options);
1335
1604
  const linkParams = urlToWrap.split('?')[1];
1336
1605
  const startapp = 'tonconnect-' + encodeTelegramUrlParameters(linkParams);
1337
1606
  // TODO: Remove this line after all dApps and the wallets-list.json have been updated
@@ -1351,12 +1620,14 @@ class BridgeProvider {
1351
1620
  }
1352
1621
  openGateways(sessionCrypto, options) {
1353
1622
  return __awaiter(this, void 0, void 0, function* () {
1623
+ var _a;
1624
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1354
1625
  if (Array.isArray(this.walletConnectionSource)) {
1355
1626
  // close all gateways before opening new ones
1356
1627
  this.pendingGateways.map(bridge => bridge.close().catch());
1357
1628
  // open new gateways
1358
1629
  this.pendingGateways = this.walletConnectionSource.map(source => {
1359
- const gateway = new BridgeGateway(this.storage, source.bridgeUrl, sessionCrypto.sessionId, () => { }, () => { });
1630
+ const gateway = new BridgeGateway(this.storage, source.bridgeUrl, sessionCrypto.sessionId, () => { }, () => { }, this.analyticsManager);
1360
1631
  gateway.setListener(message => this.pendingGatewaysListener(gateway, source.bridgeUrl, message));
1361
1632
  return gateway;
1362
1633
  });
@@ -1367,7 +1638,8 @@ class BridgeProvider {
1367
1638
  }
1368
1639
  return bridge.registerSession({
1369
1640
  openingDeadlineMS: (_a = options === null || options === void 0 ? void 0 : options.openingDeadlineMS) !== null && _a !== void 0 ? _a : this.defaultOpeningDeadlineMS,
1370
- signal: _options.signal
1641
+ signal: _options.signal,
1642
+ traceId
1371
1643
  });
1372
1644
  }, {
1373
1645
  attempts: Number.MAX_SAFE_INTEGER,
@@ -1381,10 +1653,11 @@ class BridgeProvider {
1381
1653
  logDebug(`Gateway is already opened, closing previous gateway`);
1382
1654
  yield this.gateway.close();
1383
1655
  }
1384
- this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
1656
+ this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this), this.analyticsManager);
1385
1657
  return yield this.gateway.registerSession({
1386
1658
  openingDeadlineMS: options === null || options === void 0 ? void 0 : options.openingDeadlineMS,
1387
- signal: options === null || options === void 0 ? void 0 : options.signal
1659
+ signal: options === null || options === void 0 ? void 0 : options.signal,
1660
+ traceId
1388
1661
  });
1389
1662
  }
1390
1663
  });
@@ -1487,6 +1760,15 @@ function getWebPageManifest() {
1487
1760
  }
1488
1761
  return '';
1489
1762
  }
1763
+ function getOriginWithPath() {
1764
+ var _a, _b, _c, _d;
1765
+ const origin = (_b = (_a = getWindow()) === null || _a === void 0 ? void 0 : _a.location) === null || _b === void 0 ? void 0 : _b.origin;
1766
+ const path = (_d = (_c = getWindow()) === null || _c === void 0 ? void 0 : _c.location) === null || _d === void 0 ? void 0 : _d.pathname;
1767
+ if (origin && path) {
1768
+ return origin + path;
1769
+ }
1770
+ return '';
1771
+ }
1490
1772
  /**
1491
1773
  * Returns `localStorage` if it is available. In Safari's private mode, it returns `InMemoryStorage`. In Node.js, it throws an error.
1492
1774
  */
@@ -1556,11 +1838,11 @@ function getWindowEntries() {
1556
1838
  }
1557
1839
 
1558
1840
  class InjectedProvider {
1559
- static fromStorage(storage) {
1841
+ static fromStorage(storage, analyticsManager) {
1560
1842
  return __awaiter(this, void 0, void 0, function* () {
1561
1843
  const bridgeConnectionStorage = new BridgeConnectionStorage(storage);
1562
1844
  const connection = yield bridgeConnectionStorage.getInjectedConnection();
1563
- return new InjectedProvider(storage, connection.jsBridgeKey);
1845
+ return new InjectedProvider(storage, connection.jsBridgeKey, analyticsManager);
1564
1846
  });
1565
1847
  }
1566
1848
  static isWalletInjected(injectedWalletKey) {
@@ -1597,7 +1879,7 @@ class InjectedProvider {
1597
1879
  typeof window[injectedWalletKey] === 'object' &&
1598
1880
  'tonconnect' in window[injectedWalletKey]);
1599
1881
  }
1600
- constructor(storage, injectedWalletKey) {
1882
+ constructor(storage, injectedWalletKey, analyticsManager) {
1601
1883
  this.injectedWalletKey = injectedWalletKey;
1602
1884
  this.type = 'injected';
1603
1885
  this.unsubscribeCallback = null;
@@ -1609,25 +1891,49 @@ class InjectedProvider {
1609
1891
  }
1610
1892
  this.connectionStorage = new BridgeConnectionStorage(storage);
1611
1893
  this.injectedWallet = window[injectedWalletKey].tonconnect;
1894
+ if (analyticsManager) {
1895
+ this.analytics = analyticsManager.scoped({
1896
+ bridge_key: injectedWalletKey,
1897
+ wallet_app_name: this.injectedWallet.deviceInfo.appName,
1898
+ wallet_app_version: this.injectedWallet.deviceInfo.appVersion
1899
+ });
1900
+ }
1612
1901
  }
1613
- connect(message) {
1614
- this._connect(PROTOCOL_VERSION, message);
1902
+ connect(message, options) {
1903
+ this._connect(PROTOCOL_VERSION, message, options);
1615
1904
  }
1616
- restoreConnection() {
1905
+ restoreConnection(options) {
1617
1906
  return __awaiter(this, void 0, void 0, function* () {
1907
+ var _a, _b, _c, _d;
1908
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1618
1909
  try {
1619
1910
  logDebug(`Injected Provider restoring connection...`);
1620
- const connectEvent = yield this.injectedWallet.restoreConnection();
1911
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitJsBridgeCall({
1912
+ js_bridge_method: 'restoreConnection',
1913
+ trace_id: traceId
1914
+ });
1915
+ const connectEvent = yield this.injectedWallet.restoreConnection({
1916
+ traceId
1917
+ });
1918
+ (_c = this.analytics) === null || _c === void 0 ? void 0 : _c.emitJsBridgeResponse({
1919
+ js_bridge_method: 'restoreConnection',
1920
+ trace_id: traceId
1921
+ });
1621
1922
  logDebug('Injected Provider restoring connection response', connectEvent);
1622
1923
  if (connectEvent.event === 'connect') {
1623
- this.makeSubscriptions();
1624
- this.listeners.forEach(listener => listener(connectEvent));
1924
+ this.makeSubscriptions({ traceId });
1925
+ this.listeners.forEach(listener => listener(Object.assign(Object.assign({}, connectEvent), { traceId })));
1625
1926
  }
1626
1927
  else {
1627
1928
  yield this.connectionStorage.removeConnection();
1628
1929
  }
1629
1930
  }
1630
1931
  catch (e) {
1932
+ (_d = this.analytics) === null || _d === void 0 ? void 0 : _d.emitJsBridgeError({
1933
+ js_bridge_method: 'restoreConnection',
1934
+ error_message: String(e),
1935
+ trace_id: traceId
1936
+ });
1631
1937
  yield this.connectionStorage.removeConnection();
1632
1938
  console.error(e);
1633
1939
  }
@@ -1639,8 +1945,10 @@ class InjectedProvider {
1639
1945
  }
1640
1946
  this.closeAllListeners();
1641
1947
  }
1642
- disconnect() {
1948
+ disconnect(options) {
1643
1949
  return __awaiter(this, void 0, void 0, function* () {
1950
+ var _a;
1951
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1644
1952
  return new Promise(resolve => {
1645
1953
  const onRequestSent = () => {
1646
1954
  this.closeAllListeners();
@@ -1655,7 +1963,7 @@ class InjectedProvider {
1655
1963
  this.sendRequest({
1656
1964
  method: 'disconnect',
1657
1965
  params: []
1658
- }, onRequestSent);
1966
+ }, { onRequestSent, traceId });
1659
1967
  }
1660
1968
  });
1661
1969
  });
@@ -1672,38 +1980,76 @@ class InjectedProvider {
1672
1980
  }
1673
1981
  sendRequest(request, optionsOrOnRequestSent) {
1674
1982
  return __awaiter(this, void 0, void 0, function* () {
1675
- var _a;
1983
+ var _a, _b, _c;
1676
1984
  // TODO: remove deprecated method
1677
1985
  const options = {};
1678
1986
  if (typeof optionsOrOnRequestSent === 'function') {
1679
1987
  options.onRequestSent = optionsOrOnRequestSent;
1988
+ options.traceId = UUIDv7();
1680
1989
  }
1681
1990
  else {
1682
1991
  options.onRequestSent = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.onRequestSent;
1683
1992
  options.signal = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.signal;
1993
+ options.attempts = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.attempts;
1994
+ options.traceId = (_a = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1684
1995
  }
1685
1996
  const id = (yield this.connectionStorage.getNextRpcRequestId()).toString();
1686
1997
  yield this.connectionStorage.increaseNextRpcRequestId();
1687
1998
  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);
1999
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitJsBridgeCall({
2000
+ js_bridge_method: 'send'
2001
+ });
2002
+ const result = this.injectedWallet.send(Object.assign(Object.assign({}, request), { id }), {
2003
+ traceId: options.traceId
2004
+ });
2005
+ result
2006
+ .then(response => {
2007
+ var _a;
2008
+ (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.emitJsBridgeResponse({
2009
+ js_bridge_method: 'send'
2010
+ });
2011
+ logDebug('Wallet message received:', response);
2012
+ })
2013
+ .catch(error => {
2014
+ var _a;
2015
+ (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.emitJsBridgeError({
2016
+ js_bridge_method: 'send',
2017
+ error_message: String(error)
2018
+ });
2019
+ });
2020
+ (_c = options === null || options === void 0 ? void 0 : options.onRequestSent) === null || _c === void 0 ? void 0 : _c.call(options);
1691
2021
  return result;
1692
2022
  });
1693
2023
  }
1694
- _connect(protocolVersion, message) {
2024
+ _connect(protocolVersion, message, options) {
1695
2025
  return __awaiter(this, void 0, void 0, function* () {
2026
+ var _a, _b, _c, _d;
2027
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
1696
2028
  try {
1697
2029
  logDebug(`Injected Provider connect request: protocolVersion: ${protocolVersion}, message:`, message);
1698
- const connectEvent = yield this.injectedWallet.connect(protocolVersion, message);
2030
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitJsBridgeCall({
2031
+ js_bridge_method: 'connect',
2032
+ trace_id: traceId
2033
+ });
2034
+ const connectEvent = yield this.injectedWallet.connect(protocolVersion, message, {
2035
+ traceId
2036
+ });
2037
+ (_c = this.analytics) === null || _c === void 0 ? void 0 : _c.emitJsBridgeResponse({
2038
+ js_bridge_method: 'connect'
2039
+ });
1699
2040
  logDebug('Injected Provider connect response:', connectEvent);
1700
2041
  if (connectEvent.event === 'connect') {
1701
2042
  yield this.updateSession();
1702
- this.makeSubscriptions();
2043
+ this.makeSubscriptions({ traceId });
1703
2044
  }
1704
- this.listeners.forEach(listener => listener(connectEvent));
2045
+ this.listeners.forEach(listener => listener(Object.assign(Object.assign({}, connectEvent), { traceId })));
1705
2046
  }
1706
2047
  catch (e) {
2048
+ (_d = this.analytics) === null || _d === void 0 ? void 0 : _d.emitJsBridgeError({
2049
+ js_bridge_method: 'connect',
2050
+ error_message: String(e),
2051
+ trace_id: traceId
2052
+ });
1707
2053
  logDebug('Injected Provider connect error:', e);
1708
2054
  const connectEventError = {
1709
2055
  event: 'connect_error',
@@ -1712,21 +2058,42 @@ class InjectedProvider {
1712
2058
  message: e === null || e === void 0 ? void 0 : e.toString()
1713
2059
  }
1714
2060
  };
1715
- this.listeners.forEach(listener => listener(connectEventError));
2061
+ this.listeners.forEach(listener => listener(Object.assign(Object.assign({}, connectEventError), { traceId })));
1716
2062
  }
1717
2063
  });
1718
2064
  }
1719
- makeSubscriptions() {
2065
+ makeSubscriptions(options) {
2066
+ var _a, _b, _c;
1720
2067
  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
- }
2068
+ (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.emitJsBridgeCall({
2069
+ js_bridge_method: 'listen',
2070
+ trace_id: options.traceId
1729
2071
  });
2072
+ try {
2073
+ this.unsubscribeCallback = this.injectedWallet.listen(e => {
2074
+ var _a;
2075
+ const traceId = (_a = e.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
2076
+ logDebug('Wallet message received:', e);
2077
+ if (this.listenSubscriptions) {
2078
+ this.listeners.forEach(listener => listener(Object.assign(Object.assign({}, e), { traceId })));
2079
+ }
2080
+ if (e.event === 'disconnect') {
2081
+ this.disconnect({ traceId });
2082
+ }
2083
+ });
2084
+ (_b = this.analytics) === null || _b === void 0 ? void 0 : _b.emitJsBridgeResponse({
2085
+ js_bridge_method: 'listen',
2086
+ trace_id: options.traceId
2087
+ });
2088
+ }
2089
+ catch (err) {
2090
+ (_c = this.analytics) === null || _c === void 0 ? void 0 : _c.emitJsBridgeError({
2091
+ js_bridge_method: 'listen',
2092
+ error_message: String(err),
2093
+ trace_id: options.traceId
2094
+ });
2095
+ throw err;
2096
+ }
1730
2097
  }
1731
2098
  updateSession() {
1732
2099
  return this.connectionStorage.storeConnection({
@@ -2971,77 +3338,91 @@ function createVersionInfo(version) {
2971
3338
  ton_connect_ui_lib: version.ton_connect_ui_lib
2972
3339
  };
2973
3340
  }
2974
- function createConnectionInfo(version, wallet) {
2975
- var _a, _b, _c, _d, _e, _f, _g, _h;
3341
+ // eslint-disable-next-line complexity
3342
+ function createConnectionInfo(version, wallet, sessionInfo) {
3343
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
2976
3344
  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
3345
  const authType = isTonProof ? 'ton_proof' : 'ton_addr';
2978
3346
  return {
2979
3347
  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,
3348
+ wallet_state_init: (_d = wallet === null || wallet === void 0 ? void 0 : wallet.account.walletStateInit) !== null && _d !== void 0 ? _d : null,
3349
+ wallet_type: (_e = wallet === null || wallet === void 0 ? void 0 : wallet.device.appName) !== null && _e !== void 0 ? _e : null,
3350
+ wallet_version: (_f = wallet === null || wallet === void 0 ? void 0 : wallet.device.appVersion) !== null && _f !== void 0 ? _f : null,
2982
3351
  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))
3352
+ 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
3353
  };
2985
3354
  }
2986
3355
  /**
2987
3356
  * Create a connection init event.
2988
3357
  */
2989
- function createConnectionStartedEvent(version) {
3358
+ function createConnectionStartedEvent(version, traceId) {
2990
3359
  return {
2991
3360
  type: 'connection-started',
2992
- custom_data: createVersionInfo(version)
3361
+ custom_data: createVersionInfo(version),
3362
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null
2993
3363
  };
2994
3364
  }
2995
3365
  /**
2996
3366
  * Create a connection completed event.
2997
3367
  * @param version
2998
3368
  * @param wallet
3369
+ * @param sessionInfo
3370
+ * @param traceId
2999
3371
  */
3000
- function createConnectionCompletedEvent(version, wallet) {
3001
- return Object.assign({ type: 'connection-completed', is_success: true }, createConnectionInfo(version, wallet));
3372
+ function createConnectionCompletedEvent(version, wallet, sessionInfo, traceId) {
3373
+ return Object.assign({ type: 'connection-completed', is_success: true, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo));
3002
3374
  }
3003
3375
  /**
3004
3376
  * Create a connection error event.
3005
3377
  * @param version
3006
3378
  * @param error_message
3007
3379
  * @param errorCode
3380
+ * @param sessionInfo
3381
+ * @param traceId
3008
3382
  */
3009
- function createConnectionErrorEvent(version, error_message, errorCode) {
3383
+ function createConnectionErrorEvent(version, error_message, errorCode, sessionInfo, traceId) {
3384
+ var _a, _b;
3010
3385
  return {
3011
3386
  type: 'connection-error',
3012
3387
  is_success: false,
3013
3388
  error_message: error_message,
3014
3389
  error_code: errorCode !== null && errorCode !== void 0 ? errorCode : null,
3015
- custom_data: createVersionInfo(version)
3390
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null,
3391
+ 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
3392
  };
3017
3393
  }
3018
3394
  /**
3019
3395
  * Create a connection restoring started event.
3020
3396
  */
3021
- function createConnectionRestoringStartedEvent(version) {
3397
+ function createConnectionRestoringStartedEvent(version, traceId) {
3022
3398
  return {
3023
3399
  type: 'connection-restoring-started',
3024
- custom_data: createVersionInfo(version)
3400
+ custom_data: createVersionInfo(version),
3401
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null
3025
3402
  };
3026
3403
  }
3027
3404
  /**
3028
3405
  * Create a connection restoring completed event.
3029
3406
  * @param version
3030
3407
  * @param wallet
3408
+ * @param sessionInfo
3409
+ * @param traceId
3031
3410
  */
3032
- function createConnectionRestoringCompletedEvent(version, wallet) {
3033
- return Object.assign({ type: 'connection-restoring-completed', is_success: true }, createConnectionInfo(version, wallet));
3411
+ function createConnectionRestoringCompletedEvent(version, wallet, sessionInfo, traceId) {
3412
+ return Object.assign({ type: 'connection-restoring-completed', is_success: true, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo));
3034
3413
  }
3035
3414
  /**
3036
3415
  * Create a connection restoring error event.
3037
3416
  * @param version
3038
3417
  * @param errorMessage
3418
+ * @param traceId
3039
3419
  */
3040
- function createConnectionRestoringErrorEvent(version, errorMessage) {
3420
+ function createConnectionRestoringErrorEvent(version, errorMessage, traceId) {
3041
3421
  return {
3042
3422
  type: 'connection-restoring-error',
3043
3423
  is_success: false,
3044
3424
  error_message: errorMessage,
3425
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null,
3045
3426
  custom_data: createVersionInfo(version)
3046
3427
  };
3047
3428
  }
@@ -3059,14 +3440,32 @@ function createTransactionInfo(wallet, transaction) {
3059
3440
  })
3060
3441
  };
3061
3442
  }
3443
+ function createTransactionFullInfo(wallet, transaction) {
3444
+ var _a, _b, _c, _d;
3445
+ return {
3446
+ valid_until: (_a = String(transaction.validUntil)) !== null && _a !== void 0 ? _a : null,
3447
+ 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,
3448
+ messages: transaction.messages.map(message => {
3449
+ var _a, _b, _c, _d;
3450
+ return ({
3451
+ address: (_a = message.address) !== null && _a !== void 0 ? _a : null,
3452
+ amount: (_b = message.amount) !== null && _b !== void 0 ? _b : null,
3453
+ payload: (_c = message.payload) !== null && _c !== void 0 ? _c : null,
3454
+ state_init: (_d = message.stateInit) !== null && _d !== void 0 ? _d : null
3455
+ });
3456
+ })
3457
+ };
3458
+ }
3062
3459
  /**
3063
3460
  * Create a transaction init event.
3064
3461
  * @param version
3065
3462
  * @param wallet
3066
3463
  * @param transaction
3464
+ * @param sessionInfo
3465
+ * @param traceId
3067
3466
  */
3068
- function createTransactionSentForSignatureEvent(version, wallet, transaction) {
3069
- return Object.assign(Object.assign({ type: 'transaction-sent-for-signature' }, createConnectionInfo(version, wallet)), createTransactionInfo(wallet, transaction));
3467
+ function createTransactionSentForSignatureEvent(version, wallet, transaction, sessionInfo, traceId) {
3468
+ 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
3469
  }
3071
3470
  /**
3072
3471
  * Create a transaction signed event.
@@ -3074,9 +3473,11 @@ function createTransactionSentForSignatureEvent(version, wallet, transaction) {
3074
3473
  * @param wallet
3075
3474
  * @param transaction
3076
3475
  * @param signedTransaction
3476
+ * @param sessionInfo
3477
+ * @param traceId
3077
3478
  */
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));
3479
+ function createTransactionSignedEvent(version, wallet, transaction, signedTransaction, sessionInfo, traceId) {
3480
+ 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
3481
  }
3081
3482
  /**
3082
3483
  * Create a transaction error event.
@@ -3085,71 +3486,50 @@ function createTransactionSignedEvent(version, wallet, transaction, signedTransa
3085
3486
  * @param transaction
3086
3487
  * @param errorMessage
3087
3488
  * @param errorCode
3489
+ * @param sessionInfo
3490
+ * @param traceId
3088
3491
  */
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));
3492
+ function createTransactionSigningFailedEvent(version, wallet, transaction, errorMessage, errorCode, sessionInfo, traceId) {
3493
+ 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
3494
  }
3092
- function createDataSentForSignatureEvent(version, wallet, data) {
3093
- return Object.assign({ type: 'sign-data-request-initiated', data }, createConnectionInfo(version, wallet));
3495
+ function createDataSentForSignatureEvent(version, wallet, data, sessionInfo, traceId) {
3496
+ return Object.assign({ type: 'sign-data-request-initiated', data, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo));
3094
3497
  }
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));
3498
+ function createDataSignedEvent(version, wallet, data, signedData, sessionInfo, traceId) {
3499
+ 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
3500
  }
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));
3501
+ function createDataSigningFailedEvent(version, wallet, data, errorMessage, errorCode, sessionInfo, traceId) {
3502
+ 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
3503
  }
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));
3504
+ function createDisconnectionEvent(version, wallet, scope, sessionInfo, traceId) {
3505
+ return Object.assign({ type: 'disconnection', scope: scope, trace_id: traceId !== null && traceId !== void 0 ? traceId : null }, createConnectionInfo(version, wallet, sessionInfo));
3110
3506
  }
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
- });
3507
+ function createWalletModalOpenedEvent(version, visibleWallets, clientId, traceId) {
3508
+ return {
3509
+ type: 'wallet-modal-opened',
3510
+ visible_wallets: visibleWallets,
3511
+ client_id: clientId !== null && clientId !== void 0 ? clientId : null,
3512
+ custom_data: version,
3513
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null
3514
+ };
3515
+ }
3516
+ function createSelectedWalletEvent(version, visibleWallets, lastSelectedWallet, walletsMenu, redirectLink, redirectLinkType, clientId, traceId) {
3517
+ var _a;
3518
+ let walletRedirectMethod = redirectLinkType;
3519
+ if (!walletRedirectMethod && redirectLink) {
3520
+ walletRedirectMethod = isTelegramUrl(redirectLink) ? 'tg_link' : 'external_link';
3152
3521
  }
3522
+ return {
3523
+ type: 'selected-wallet',
3524
+ wallets_menu: walletsMenu,
3525
+ visible_wallets: visibleWallets,
3526
+ client_id: clientId !== null && clientId !== void 0 ? clientId : null,
3527
+ custom_data: version,
3528
+ trace_id: traceId !== null && traceId !== void 0 ? traceId : null,
3529
+ wallet_redirect_method: walletRedirectMethod,
3530
+ wallet_redirect_link: redirectLink || undefined,
3531
+ wallet_type: (_a = lastSelectedWallet === null || lastSelectedWallet === void 0 ? void 0 : lastSelectedWallet.appName) !== null && _a !== void 0 ? _a : null
3532
+ };
3153
3533
  }
3154
3534
 
3155
3535
  /**
@@ -3190,7 +3570,6 @@ class TonConnectTracker {
3190
3570
  });
3191
3571
  }
3192
3572
  constructor(options) {
3193
- var _a;
3194
3573
  /**
3195
3574
  * Event prefix for user actions.
3196
3575
  * @private
@@ -3200,7 +3579,7 @@ class TonConnectTracker {
3200
3579
  * TonConnect UI version.
3201
3580
  */
3202
3581
  this.tonConnectUiVersion = null;
3203
- this.eventDispatcher = (_a = options === null || options === void 0 ? void 0 : options.eventDispatcher) !== null && _a !== void 0 ? _a : new BrowserEventDispatcher();
3582
+ this.eventDispatcher = options === null || options === void 0 ? void 0 : options.eventDispatcher;
3204
3583
  this.tonConnectSdkVersion = options.tonConnectSdkVersion;
3205
3584
  this.init().catch();
3206
3585
  }
@@ -3404,7 +3783,7 @@ class TonConnectTracker {
3404
3783
  }
3405
3784
  }
3406
3785
 
3407
- const tonConnectSdkVersion = "3.3.1";
3786
+ const tonConnectSdkVersion = "3.4.0-beta.0";
3408
3787
 
3409
3788
  const bounceableTag = 0x11;
3410
3789
  const noBounceableTag = 0x51;
@@ -3903,6 +4282,403 @@ function normalizeBase64(data) {
3903
4282
  return data.replace(/-/g, '+').replace(/_/g, '/').padEnd(paddedLength, '=');
3904
4283
  }
3905
4284
 
4285
+ /**
4286
+ * Converts a PascalCase (or camelCase) string to kebab-case.
4287
+ *
4288
+ * For example:
4289
+ * - "PascalCase" → "pascal-case"
4290
+ * - "camelCaseExample" → "camel-case-example"
4291
+ *
4292
+ * @param value - The input string in PascalCase or camelCase format.
4293
+ * @returns The converted kebab-case string.
4294
+ */
4295
+ function pascalToKebab(value) {
4296
+ return value.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
4297
+ }
4298
+
4299
+ class AnalyticsManager {
4300
+ constructor(options = {}) {
4301
+ var _a, _b, _c, _d, _e;
4302
+ this.events = [];
4303
+ this.timeoutId = null;
4304
+ this.isProcessing = false;
4305
+ this.backoff = 1;
4306
+ this.shouldSend = true;
4307
+ this.batchTimeoutMs = (_a = options.batchTimeoutMs) !== null && _a !== void 0 ? _a : 2000;
4308
+ this.currentBatchTimeoutMs = this.batchTimeoutMs;
4309
+ this.maxBatchSize = (_b = options.maxBatchSize) !== null && _b !== void 0 ? _b : 100;
4310
+ this.analyticsUrl = (_c = options.analyticsUrl) !== null && _c !== void 0 ? _c : 'https://analytics.ton.org/events';
4311
+ this.enabled = (_d = options.enabled) !== null && _d !== void 0 ? _d : true;
4312
+ this.baseEvent = {
4313
+ subsystem: 'dapp-sdk',
4314
+ version: tonConnectSdkVersion,
4315
+ client_environment: (_e = options.environment) === null || _e === void 0 ? void 0 : _e.getClientEnvironment()
4316
+ };
4317
+ this.addWindowFocusAndBlurSubscriptions();
4318
+ }
4319
+ scoped(sharedData) {
4320
+ return new Proxy(this, {
4321
+ get(target, prop) {
4322
+ const propName = prop.toString();
4323
+ if (propName.startsWith('emit')) {
4324
+ const eventNamePascal = propName.replace('emit', '');
4325
+ const eventNameKebab = pascalToKebab(eventNamePascal);
4326
+ return function (event) {
4327
+ const executedData = Object.fromEntries(Object.entries(sharedData !== null && sharedData !== void 0 ? sharedData : {}).map(([key, value]) => [
4328
+ key,
4329
+ typeof value === 'function' ? value() : value
4330
+ ]));
4331
+ return target.emit(Object.assign(Object.assign({ event_name: eventNameKebab }, executedData), event));
4332
+ };
4333
+ }
4334
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4335
+ return target[prop];
4336
+ }
4337
+ });
4338
+ }
4339
+ emit(event) {
4340
+ var _a;
4341
+ if (!this.enabled) {
4342
+ return;
4343
+ }
4344
+ const traceId = (_a = event.trace_id) !== null && _a !== void 0 ? _a : UUIDv7();
4345
+ const enhancedEvent = Object.assign(Object.assign(Object.assign({}, this.baseEvent), event), { event_id: UUIDv7(), client_timestamp: Math.floor(Date.now() / 1000), trace_id: traceId });
4346
+ if (isQaModeEnabled()) {
4347
+ logDebug(enhancedEvent);
4348
+ }
4349
+ this.events.push(enhancedEvent);
4350
+ if (this.events.length >= this.maxBatchSize) {
4351
+ void this.flush();
4352
+ return;
4353
+ }
4354
+ this.startTimeout();
4355
+ }
4356
+ startTimeout() {
4357
+ if (this.timeoutId || this.isProcessing) {
4358
+ return;
4359
+ }
4360
+ this.timeoutId = setTimeout(() => {
4361
+ void this.flush();
4362
+ }, this.currentBatchTimeoutMs);
4363
+ }
4364
+ flush() {
4365
+ return __awaiter(this, void 0, void 0, function* () {
4366
+ if (this.isProcessing || this.events.length === 0 || !this.shouldSend) {
4367
+ return;
4368
+ }
4369
+ this.clearTimeout();
4370
+ this.isProcessing = true;
4371
+ const eventsToSend = this.extractEventsToSend();
4372
+ try {
4373
+ yield this.processEventsBatch(eventsToSend);
4374
+ logDebug('Analytics events sent successfully');
4375
+ }
4376
+ catch (error) {
4377
+ this.restoreEvents(eventsToSend);
4378
+ logError('Failed to send analytics events:', error);
4379
+ }
4380
+ finally {
4381
+ this.isProcessing = false;
4382
+ this.scheduleNextFlushIfNeeded();
4383
+ }
4384
+ });
4385
+ }
4386
+ clearTimeout() {
4387
+ if (this.timeoutId) {
4388
+ clearTimeout(this.timeoutId);
4389
+ this.timeoutId = null;
4390
+ }
4391
+ }
4392
+ extractEventsToSend() {
4393
+ const eventsToSend = this.events.slice(0, this.maxBatchSize);
4394
+ this.events = this.events.slice(this.maxBatchSize);
4395
+ return eventsToSend;
4396
+ }
4397
+ processEventsBatch(eventsToSend) {
4398
+ return __awaiter(this, void 0, void 0, function* () {
4399
+ logDebug('Sending analytics events...', eventsToSend.length);
4400
+ try {
4401
+ const response = yield this.sendEvents(eventsToSend);
4402
+ this.handleResponse(response);
4403
+ }
4404
+ catch (err) {
4405
+ this.handleUnknownError(err);
4406
+ }
4407
+ });
4408
+ }
4409
+ handleResponse(response) {
4410
+ const { status, statusText } = response;
4411
+ if (this.isTooManyRequests(status)) {
4412
+ this.handleTooManyRequests(status, statusText);
4413
+ }
4414
+ else if (this.isClientError(status)) {
4415
+ this.handleClientError(status, statusText);
4416
+ }
4417
+ else if (this.isServerError(status)) {
4418
+ this.handleUnknownError({ status, statusText });
4419
+ }
4420
+ }
4421
+ restoreEvents(eventsToSend) {
4422
+ this.events.unshift(...eventsToSend);
4423
+ }
4424
+ scheduleNextFlushIfNeeded() {
4425
+ if (this.events.length > 0) {
4426
+ this.startTimeout();
4427
+ }
4428
+ }
4429
+ sendEvents(events) {
4430
+ return __awaiter(this, void 0, void 0, function* () {
4431
+ return yield fetch(this.analyticsUrl, {
4432
+ method: 'POST',
4433
+ headers: {
4434
+ 'Content-Type': 'application/json',
4435
+ 'X-Client-Timestamp': Math.floor(Date.now() / 1000).toString()
4436
+ },
4437
+ body: JSON.stringify(events)
4438
+ });
4439
+ });
4440
+ }
4441
+ isClientError(status) {
4442
+ return (status >= AnalyticsManager.HTTP_STATUS.CLIENT_ERROR_START &&
4443
+ status < AnalyticsManager.HTTP_STATUS.SERVER_ERROR_START);
4444
+ }
4445
+ isServerError(status) {
4446
+ return status >= AnalyticsManager.HTTP_STATUS.SERVER_ERROR_START;
4447
+ }
4448
+ isTooManyRequests(status) {
4449
+ return status === AnalyticsManager.HTTP_STATUS.TOO_MANY_REQUESTS;
4450
+ }
4451
+ handleClientError(status, statusText) {
4452
+ // Don't retry
4453
+ logError('Failed to send analytics events:', new TonConnectError(`Analytics API error: ${status} ${statusText}`));
4454
+ }
4455
+ handleUnknownError(error) {
4456
+ if (this.backoff < AnalyticsManager.MAX_BACKOFF_ATTEMPTS) {
4457
+ this.backoff++;
4458
+ this.currentBatchTimeoutMs *= AnalyticsManager.BACKOFF_MULTIPLIER;
4459
+ throw new TonConnectError(`Unknown analytics API error: ${error}`);
4460
+ }
4461
+ else {
4462
+ this.currentBatchTimeoutMs = this.batchTimeoutMs;
4463
+ this.backoff = 1;
4464
+ return; // Don't retry
4465
+ }
4466
+ }
4467
+ handleTooManyRequests(status, statusText) {
4468
+ throw new TonConnectError(`Analytics API error: ${status} ${statusText}`);
4469
+ }
4470
+ addWindowFocusAndBlurSubscriptions() {
4471
+ const document = getDocument();
4472
+ if (!document) {
4473
+ return;
4474
+ }
4475
+ try {
4476
+ document.addEventListener('visibilitychange', () => {
4477
+ if (document.hidden) {
4478
+ this.clearTimeout();
4479
+ this.shouldSend = false;
4480
+ }
4481
+ else {
4482
+ this.shouldSend = true;
4483
+ this.scheduleNextFlushIfNeeded();
4484
+ }
4485
+ });
4486
+ }
4487
+ catch (e) {
4488
+ logError('Cannot subscribe to the document.visibilitychange: ', e);
4489
+ }
4490
+ }
4491
+ setEnabled(enabled) {
4492
+ this.enabled = enabled;
4493
+ }
4494
+ isEnabled() {
4495
+ return this.enabled;
4496
+ }
4497
+ getPendingEventsCount() {
4498
+ return this.events.length;
4499
+ }
4500
+ }
4501
+ AnalyticsManager.HTTP_STATUS = {
4502
+ TOO_MANY_REQUESTS: 429,
4503
+ CLIENT_ERROR_START: 400,
4504
+ SERVER_ERROR_START: 500
4505
+ };
4506
+ AnalyticsManager.MAX_BACKOFF_ATTEMPTS = 5;
4507
+ AnalyticsManager.BACKOFF_MULTIPLIER = 2;
4508
+
4509
+ /**
4510
+ * A concrete implementation of EventDispatcher that dispatches events to the browser window.
4511
+ */
4512
+ class BrowserEventDispatcher {
4513
+ constructor() {
4514
+ /**
4515
+ * The window object, possibly undefined in a server environment.
4516
+ * @private
4517
+ */
4518
+ this.window = getWindow();
4519
+ }
4520
+ /**
4521
+ * Dispatches an event with the given name and details to the browser window.
4522
+ * @param eventName - The name of the event to dispatch.
4523
+ * @param eventDetails - The details of the event to dispatch.
4524
+ * @returns A promise that resolves when the event has been dispatched.
4525
+ */
4526
+ dispatchEvent(eventName, eventDetails) {
4527
+ return __awaiter(this, void 0, void 0, function* () {
4528
+ var _a;
4529
+ const event = new CustomEvent(eventName, { detail: eventDetails });
4530
+ (_a = this.window) === null || _a === void 0 ? void 0 : _a.dispatchEvent(event);
4531
+ });
4532
+ }
4533
+ /**
4534
+ * Adds an event listener to the browser window.
4535
+ * @param eventName - The name of the event to listen for.
4536
+ * @param listener - The listener to add.
4537
+ * @param options - The options for the listener.
4538
+ * @returns A function that removes the listener.
4539
+ */
4540
+ addEventListener(eventName, listener, options) {
4541
+ return __awaiter(this, void 0, void 0, function* () {
4542
+ var _a;
4543
+ (_a = this.window) === null || _a === void 0 ? void 0 : _a.addEventListener(eventName, listener, options);
4544
+ return () => {
4545
+ var _a;
4546
+ return (_a = this.window) === null || _a === void 0 ? void 0 : _a.removeEventListener(eventName, listener);
4547
+ };
4548
+ });
4549
+ }
4550
+ }
4551
+
4552
+ function buildVersionInfo(version) {
4553
+ return {
4554
+ '@tonconnect/sdk': version.ton_connect_sdk_lib || '',
4555
+ '@tonconnect/ui': version.ton_connect_ui_lib || ''
4556
+ };
4557
+ }
4558
+ function buildTonConnectEvent(detail) {
4559
+ var _a, _b, _c, _d, _e, _f, _g, _h;
4560
+ return {
4561
+ versions: buildVersionInfo(detail.custom_data),
4562
+ network_id: (_a = detail.custom_data.chain_id) !== null && _a !== void 0 ? _a : '',
4563
+ client_id: (_b = detail.custom_data.client_id) !== null && _b !== void 0 ? _b : '',
4564
+ wallet_id: (_c = detail.custom_data.wallet_id) !== null && _c !== void 0 ? _c : '',
4565
+ wallet_address: (_d = detail.wallet_address) !== null && _d !== void 0 ? _d : '',
4566
+ wallet_app_name: (_e = detail.wallet_type) !== null && _e !== void 0 ? _e : '',
4567
+ wallet_app_version: (_f = detail.wallet_version) !== null && _f !== void 0 ? _f : '',
4568
+ wallet_state_init: (_g = detail.wallet_state_init) !== null && _g !== void 0 ? _g : '',
4569
+ trace_id: (_h = detail.trace_id) !== null && _h !== void 0 ? _h : undefined
4570
+ };
4571
+ }
4572
+ function bindEventsTo(eventDispatcher, analytics) {
4573
+ eventDispatcher.addEventListener('ton-connect-ui-wallet-modal-opened', event => {
4574
+ var _a;
4575
+ const { detail } = event;
4576
+ analytics.emitConnectionStarted({
4577
+ client_id: detail.client_id || '',
4578
+ versions: buildVersionInfo(detail.custom_data),
4579
+ main_screen: detail.visible_wallets,
4580
+ trace_id: (_a = detail.trace_id) !== null && _a !== void 0 ? _a : undefined
4581
+ });
4582
+ });
4583
+ eventDispatcher.addEventListener('ton-connect-ui-selected-wallet', event => {
4584
+ var _a, _b;
4585
+ const { detail } = event;
4586
+ analytics.emitConnectionSelectedWallet({
4587
+ client_id: detail.client_id || '',
4588
+ versions: buildVersionInfo(detail.custom_data),
4589
+ main_screen: detail.visible_wallets,
4590
+ wallets_menu: detail.wallets_menu,
4591
+ trace_id: (_a = detail.trace_id) !== null && _a !== void 0 ? _a : undefined,
4592
+ wallet_app_name: (_b = detail.wallet_type) !== null && _b !== void 0 ? _b : '',
4593
+ wallet_redirect_method: detail.wallet_redirect_method,
4594
+ wallet_redirect_link: detail.wallet_redirect_link
4595
+ });
4596
+ });
4597
+ eventDispatcher.addEventListener('ton-connect-connection-completed', event => {
4598
+ const { detail } = event;
4599
+ analytics.emitConnectionCompleted(buildTonConnectEvent(detail));
4600
+ });
4601
+ eventDispatcher.addEventListener('ton-connect-connection-error', event => {
4602
+ var _a, _b;
4603
+ const { detail } = event;
4604
+ analytics.emitConnectionError({
4605
+ client_id: detail.custom_data.client_id || '',
4606
+ wallet_id: detail.custom_data.wallet_id || '',
4607
+ error_code: (_a = detail.error_code) !== null && _a !== void 0 ? _a : 0,
4608
+ error_message: detail.error_message,
4609
+ trace_id: (_b = detail.trace_id) !== null && _b !== void 0 ? _b : undefined
4610
+ });
4611
+ });
4612
+ eventDispatcher.addEventListener('ton-connect-disconnection', event => {
4613
+ const { detail } = event;
4614
+ analytics.emitDisconnection(buildTonConnectEvent(detail));
4615
+ });
4616
+ eventDispatcher.addEventListener('ton-connect-transaction-sent-for-signature', event => {
4617
+ const { detail } = event;
4618
+ analytics.emitTransactionSent(buildTonConnectEvent(detail));
4619
+ });
4620
+ eventDispatcher.addEventListener('ton-connect-transaction-signed', event => {
4621
+ const { detail } = event;
4622
+ analytics.emitTransactionSigned(Object.assign(Object.assign({}, buildTonConnectEvent(detail)), { signed_boc: event.detail.signed_transaction }));
4623
+ });
4624
+ eventDispatcher.addEventListener('ton-connect-transaction-signing-failed', event => {
4625
+ var _a;
4626
+ const { detail } = event;
4627
+ analytics.emitTransactionSigningFailed(Object.assign(Object.assign({}, buildTonConnectEvent(detail)), { valid_until: Number(detail.valid_until), messages: detail.messages.map(message => {
4628
+ var _a, _b, _c, _d;
4629
+ return ({
4630
+ address: (_a = message.address) !== null && _a !== void 0 ? _a : '',
4631
+ amount: (_b = message.amount) !== null && _b !== void 0 ? _b : '',
4632
+ payload: (_c = message.payload) !== null && _c !== void 0 ? _c : '',
4633
+ state_init: (_d = message.state_init) !== null && _d !== void 0 ? _d : ''
4634
+ });
4635
+ }), error_message: detail.error_message, error_code: (_a = detail.error_code) !== null && _a !== void 0 ? _a : 0 }));
4636
+ });
4637
+ eventDispatcher.addEventListener('ton-connect-sign-data-request-initiated', event => {
4638
+ const { detail } = event;
4639
+ analytics === null || analytics === void 0 ? void 0 : analytics.emitSignDataRequestInitiated(buildTonConnectEvent(detail));
4640
+ });
4641
+ eventDispatcher.addEventListener('ton-connect-sign-data-request-completed', event => {
4642
+ const { detail } = event;
4643
+ analytics === null || analytics === void 0 ? void 0 : analytics.emitSignDataRequestCompleted(buildTonConnectEvent(detail));
4644
+ });
4645
+ eventDispatcher.addEventListener('ton-connect-sign-data-request-failed', event => {
4646
+ var _a;
4647
+ const { detail } = event;
4648
+ let signDataValue = '';
4649
+ let signDataSchema = undefined;
4650
+ if (detail.data.type === 'text') {
4651
+ signDataValue = detail.data.text;
4652
+ }
4653
+ if (detail.data.type === 'cell') {
4654
+ signDataValue = detail.data.cell;
4655
+ signDataSchema = detail.data.schema;
4656
+ }
4657
+ if (detail.data.type === 'binary') {
4658
+ signDataValue = detail.data.bytes;
4659
+ }
4660
+ 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 }));
4661
+ });
4662
+ }
4663
+
4664
+ class DefaultEnvironment {
4665
+ getClientEnvironment() {
4666
+ return '';
4667
+ }
4668
+ getBrowser() {
4669
+ return '';
4670
+ }
4671
+ getLocale() {
4672
+ return '';
4673
+ }
4674
+ getPlatform() {
4675
+ return '';
4676
+ }
4677
+ getTelegramUser() {
4678
+ return undefined;
4679
+ }
4680
+ }
4681
+
3906
4682
  class TonConnect {
3907
4683
  /**
3908
4684
  * Returns available wallets list.
@@ -3934,13 +4710,15 @@ class TonConnect {
3934
4710
  this.statusChangeSubscriptions.forEach(callback => callback(this._wallet));
3935
4711
  }
3936
4712
  constructor(options) {
4713
+ var _a, _b;
3937
4714
  this.walletsList = new WalletsListManager();
3938
4715
  this._wallet = null;
3939
4716
  this.provider = null;
3940
4717
  this.statusChangeSubscriptions = [];
3941
4718
  this.statusChangeErrorSubscriptions = [];
4719
+ const manifestUrl = (options === null || options === void 0 ? void 0 : options.manifestUrl) || getWebPageManifest();
3942
4720
  this.dappSettings = {
3943
- manifestUrl: (options === null || options === void 0 ? void 0 : options.manifestUrl) || getWebPageManifest(),
4721
+ manifestUrl,
3944
4722
  storage: (options === null || options === void 0 ? void 0 : options.storage) || new DefaultStorage()
3945
4723
  };
3946
4724
  this.walletsRequiredFeatures = options === null || options === void 0 ? void 0 : options.walletsRequiredFeatures;
@@ -3948,10 +4726,24 @@ class TonConnect {
3948
4726
  walletsListSource: options === null || options === void 0 ? void 0 : options.walletsListSource,
3949
4727
  cacheTTLMs: options === null || options === void 0 ? void 0 : options.walletsListCacheTTLMs
3950
4728
  });
4729
+ const eventDispatcher = (_a = options === null || options === void 0 ? void 0 : options.eventDispatcher) !== null && _a !== void 0 ? _a : new BrowserEventDispatcher();
3951
4730
  this.tracker = new TonConnectTracker({
3952
- eventDispatcher: options === null || options === void 0 ? void 0 : options.eventDispatcher,
4731
+ eventDispatcher,
3953
4732
  tonConnectSdkVersion: tonConnectSdkVersion
3954
4733
  });
4734
+ this.environment = (_b = options === null || options === void 0 ? void 0 : options.environment) !== null && _b !== void 0 ? _b : new DefaultEnvironment();
4735
+ // TODO: in production ready make flag to enable them?
4736
+ this.analytics = new AnalyticsManager({ environment: this.environment });
4737
+ const telegramUser = this.environment.getTelegramUser();
4738
+ bindEventsTo(eventDispatcher, this.analytics.scoped({
4739
+ locale: this.environment.getLocale(),
4740
+ browser: this.environment.getBrowser(),
4741
+ platform: this.environment.getPlatform(),
4742
+ tg_id: telegramUser === null || telegramUser === void 0 ? void 0 : telegramUser.id,
4743
+ tma_is_premium: telegramUser === null || telegramUser === void 0 ? void 0 : telegramUser.isPremium,
4744
+ manifest_json_url: manifestUrl,
4745
+ origin_url: getOriginWithPath
4746
+ }));
3955
4747
  if (!this.dappSettings.manifestUrl) {
3956
4748
  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
4749
  }
@@ -3984,17 +4776,19 @@ class TonConnect {
3984
4776
  }
3985
4777
  };
3986
4778
  }
3987
- connect(wallet, requestOrOptions) {
3988
- var _a, _b;
4779
+ // eslint-disable-next-line complexity
4780
+ connect(wallet, requestOrOptions, additionalOptions) {
4781
+ var _a, _b, _c;
3989
4782
  // TODO: remove deprecated method
3990
- const options = {};
4783
+ const options = Object.assign({}, additionalOptions);
3991
4784
  if (typeof requestOrOptions === 'object' && 'tonProof' in requestOrOptions) {
3992
4785
  options.request = requestOrOptions;
3993
4786
  }
3994
4787
  if (typeof requestOrOptions === 'object' &&
3995
4788
  ('openingDeadlineMS' in requestOrOptions ||
3996
4789
  'signal' in requestOrOptions ||
3997
- 'request' in requestOrOptions)) {
4790
+ 'request' in requestOrOptions ||
4791
+ 'traceId' in requestOrOptions)) {
3998
4792
  options.request = requestOrOptions === null || requestOrOptions === void 0 ? void 0 : requestOrOptions.request;
3999
4793
  options.openingDeadlineMS = requestOrOptions === null || requestOrOptions === void 0 ? void 0 : requestOrOptions.openingDeadlineMS;
4000
4794
  options.signal = requestOrOptions === null || requestOrOptions === void 0 ? void 0 : requestOrOptions.signal;
@@ -4026,10 +4820,12 @@ class TonConnect {
4026
4820
  (_a = this.provider) === null || _a === void 0 ? void 0 : _a.closeConnection();
4027
4821
  this.provider = null;
4028
4822
  });
4029
- this.tracker.trackConnectionStarted();
4823
+ const traceId = (_c = options === null || options === void 0 ? void 0 : options.traceId) !== null && _c !== void 0 ? _c : UUIDv7();
4824
+ this.tracker.trackConnectionStarted(traceId);
4030
4825
  return this.provider.connect(this.createConnectRequest(options === null || options === void 0 ? void 0 : options.request), {
4031
4826
  openingDeadlineMS: options === null || options === void 0 ? void 0 : options.openingDeadlineMS,
4032
- signal: abortController.signal
4827
+ signal: abortController.signal,
4828
+ traceId
4033
4829
  });
4034
4830
  }
4035
4831
  /**
@@ -4037,13 +4833,14 @@ class TonConnect {
4037
4833
  */
4038
4834
  restoreConnection(options) {
4039
4835
  return __awaiter(this, void 0, void 0, function* () {
4040
- var _a, _b;
4041
- this.tracker.trackConnectionRestoringStarted();
4836
+ var _a, _b, _c;
4837
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
4838
+ this.tracker.trackConnectionRestoringStarted(traceId);
4042
4839
  const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
4043
- (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
4840
+ (_b = this.abortController) === null || _b === void 0 ? void 0 : _b.abort();
4044
4841
  this.abortController = abortController;
4045
4842
  if (abortController.signal.aborted) {
4046
- this.tracker.trackConnectionRestoringError('Connection restoring was aborted');
4843
+ this.tracker.trackConnectionRestoringError('Connection restoring was aborted', traceId);
4047
4844
  return;
4048
4845
  }
4049
4846
  // TODO: potentially race condition here
@@ -4052,17 +4849,17 @@ class TonConnect {
4052
4849
  this.walletsList.getEmbeddedWallet()
4053
4850
  ]);
4054
4851
  if (abortController.signal.aborted) {
4055
- this.tracker.trackConnectionRestoringError('Connection restoring was aborted');
4852
+ this.tracker.trackConnectionRestoringError('Connection restoring was aborted', traceId);
4056
4853
  return;
4057
4854
  }
4058
4855
  let provider = null;
4059
4856
  try {
4060
4857
  switch (bridgeConnectionType) {
4061
4858
  case 'http':
4062
- provider = yield BridgeProvider.fromStorage(this.dappSettings.storage);
4859
+ provider = yield BridgeProvider.fromStorage(this.dappSettings.storage, this.analytics);
4063
4860
  break;
4064
4861
  case 'injected':
4065
- provider = yield InjectedProvider.fromStorage(this.dappSettings.storage);
4862
+ provider = yield InjectedProvider.fromStorage(this.dappSettings.storage, this.analytics);
4066
4863
  break;
4067
4864
  default:
4068
4865
  if (embeddedWallet) {
@@ -4073,8 +4870,8 @@ class TonConnect {
4073
4870
  }
4074
4871
  }
4075
4872
  }
4076
- catch (_c) {
4077
- this.tracker.trackConnectionRestoringError('Provider is not restored');
4873
+ catch (_d) {
4874
+ this.tracker.trackConnectionRestoringError('Provider is not restored', traceId);
4078
4875
  yield this.bridgeConnectionStorage.removeConnection();
4079
4876
  provider === null || provider === void 0 ? void 0 : provider.closeConnection();
4080
4877
  provider = null;
@@ -4082,19 +4879,19 @@ class TonConnect {
4082
4879
  }
4083
4880
  if (abortController.signal.aborted) {
4084
4881
  provider === null || provider === void 0 ? void 0 : provider.closeConnection();
4085
- this.tracker.trackConnectionRestoringError('Connection restoring was aborted');
4882
+ this.tracker.trackConnectionRestoringError('Connection restoring was aborted', traceId);
4086
4883
  return;
4087
4884
  }
4088
4885
  if (!provider) {
4089
4886
  logError('Provider is not restored');
4090
- this.tracker.trackConnectionRestoringError('Provider is not restored');
4887
+ this.tracker.trackConnectionRestoringError('Provider is not restored', traceId);
4091
4888
  return;
4092
4889
  }
4093
- (_b = this.provider) === null || _b === void 0 ? void 0 : _b.closeConnection();
4890
+ (_c = this.provider) === null || _c === void 0 ? void 0 : _c.closeConnection();
4094
4891
  this.provider = provider;
4095
4892
  provider.listen(this.walletEventsListener.bind(this));
4096
4893
  const onAbortRestore = () => {
4097
- this.tracker.trackConnectionRestoringError('Connection restoring was aborted');
4894
+ this.tracker.trackConnectionRestoringError('Connection restoring was aborted', traceId);
4098
4895
  provider === null || provider === void 0 ? void 0 : provider.closeConnection();
4099
4896
  provider = null;
4100
4897
  };
@@ -4102,14 +4899,16 @@ class TonConnect {
4102
4899
  const restoreConnectionTask = callForSuccess((_options) => __awaiter(this, void 0, void 0, function* () {
4103
4900
  yield (provider === null || provider === void 0 ? void 0 : provider.restoreConnection({
4104
4901
  openingDeadlineMS: options === null || options === void 0 ? void 0 : options.openingDeadlineMS,
4105
- signal: _options.signal
4902
+ signal: _options.signal,
4903
+ traceId
4106
4904
  }));
4107
4905
  abortController.signal.removeEventListener('abort', onAbortRestore);
4108
4906
  if (this.connected) {
4109
- this.tracker.trackConnectionRestoringCompleted(this.wallet);
4907
+ const sessionInfo = this.getSessionInfo();
4908
+ this.tracker.trackConnectionRestoringCompleted(this.wallet, sessionInfo, traceId);
4110
4909
  }
4111
4910
  else {
4112
- this.tracker.trackConnectionRestoringError('Connection restoring failed');
4911
+ this.tracker.trackConnectionRestoringError('Connection restoring failed', traceId);
4113
4912
  }
4114
4913
  }), {
4115
4914
  attempts: Number.MAX_SAFE_INTEGER,
@@ -4123,6 +4922,7 @@ class TonConnect {
4123
4922
  }
4124
4923
  sendTransaction(transaction, optionsOrOnRequestSent) {
4125
4924
  return __awaiter(this, void 0, void 0, function* () {
4925
+ var _a;
4126
4926
  // TODO: remove deprecated method
4127
4927
  const options = {};
4128
4928
  if (typeof optionsOrOnRequestSent === 'function') {
@@ -4131,6 +4931,7 @@ class TonConnect {
4131
4931
  else {
4132
4932
  options.onRequestSent = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.onRequestSent;
4133
4933
  options.signal = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.signal;
4934
+ options.traceId = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.traceId;
4134
4935
  }
4135
4936
  // Validate transaction
4136
4937
  const validationError = validateSendTransactionRequest(transaction);
@@ -4153,7 +4954,9 @@ class TonConnect {
4153
4954
  requiredMessagesNumber,
4154
4955
  requireExtraCurrencies
4155
4956
  });
4156
- this.tracker.trackTransactionSentForSignature(this.wallet, transaction);
4957
+ const sessionInfo = this.getSessionInfo();
4958
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
4959
+ this.tracker.trackTransactionSentForSignature(this.wallet, transaction, sessionInfo, traceId);
4157
4960
  const { validUntil, messages } = transaction, tx = __rest(transaction, ["validUntil", "messages"]);
4158
4961
  const from = transaction.from || this.account.address;
4159
4962
  const network = transaction.network || this.account.chain;
@@ -4161,18 +4964,23 @@ class TonConnect {
4161
4964
  network, valid_until: validUntil, messages: messages.map((_a) => {
4162
4965
  var { extraCurrency, payload, stateInit } = _a, msg = __rest(_a, ["extraCurrency", "payload", "stateInit"]);
4163
4966
  return (Object.assign(Object.assign({}, msg), { payload: normalizeBase64(payload), stateInit: normalizeBase64(stateInit), extra_currency: extraCurrency }));
4164
- }) })), { onRequestSent: options.onRequestSent, signal: abortController.signal });
4967
+ }) })), {
4968
+ onRequestSent: options.onRequestSent,
4969
+ signal: abortController.signal,
4970
+ traceId
4971
+ });
4165
4972
  if (sendTransactionParser.isError(response)) {
4166
- this.tracker.trackTransactionSigningFailed(this.wallet, transaction, response.error.message, response.error.code);
4973
+ this.tracker.trackTransactionSigningFailed(this.wallet, transaction, response.error.message, response.error.code, sessionInfo, traceId);
4167
4974
  return sendTransactionParser.parseAndThrowError(response);
4168
4975
  }
4169
4976
  const result = sendTransactionParser.convertFromRpcResponse(response);
4170
- this.tracker.trackTransactionSigned(this.wallet, transaction, result);
4171
- return result;
4977
+ this.tracker.trackTransactionSigned(this.wallet, transaction, result, sessionInfo, traceId);
4978
+ return Object.assign(Object.assign({}, result), { traceId: response.traceId });
4172
4979
  });
4173
4980
  }
4174
4981
  signData(data, options) {
4175
4982
  return __awaiter(this, void 0, void 0, function* () {
4983
+ var _a;
4176
4984
  const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
4177
4985
  if (abortController.signal.aborted) {
4178
4986
  throw new TonConnectError('data sending was aborted');
@@ -4189,18 +4997,20 @@ class TonConnect {
4189
4997
  }
4190
4998
  this.checkConnection();
4191
4999
  checkSignDataSupport(this.wallet.device.features, { requiredTypes: [data.type] });
4192
- this.tracker.trackDataSentForSignature(this.wallet, data);
5000
+ const sessionInfo = this.getSessionInfo();
5001
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
5002
+ this.tracker.trackDataSentForSignature(this.wallet, data, sessionInfo, traceId);
4193
5003
  const from = data.from || this.account.address;
4194
5004
  const network = data.network || this.account.chain;
4195
5005
  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 });
5006
+ network })), { onRequestSent: options === null || options === void 0 ? void 0 : options.onRequestSent, signal: abortController.signal, traceId });
4197
5007
  if (signDataParser.isError(response)) {
4198
- this.tracker.trackDataSigningFailed(this.wallet, data, response.error.message, response.error.code);
5008
+ this.tracker.trackDataSigningFailed(this.wallet, data, response.error.message, response.error.code, sessionInfo, traceId);
4199
5009
  return signDataParser.parseAndThrowError(response);
4200
5010
  }
4201
5011
  const result = signDataParser.convertFromRpcResponse(response);
4202
- this.tracker.trackDataSigned(this.wallet, data, result);
4203
- return result;
5012
+ this.tracker.trackDataSigned(this.wallet, data, result, sessionInfo, traceId);
5013
+ return Object.assign(Object.assign({}, result), { traceId });
4204
5014
  });
4205
5015
  }
4206
5016
  /**
@@ -4208,7 +5018,7 @@ class TonConnect {
4208
5018
  */
4209
5019
  disconnect(options) {
4210
5020
  return __awaiter(this, void 0, void 0, function* () {
4211
- var _a;
5021
+ var _a, _b;
4212
5022
  if (!this.connected) {
4213
5023
  throw new WalletNotConnectedError();
4214
5024
  }
@@ -4218,9 +5028,11 @@ class TonConnect {
4218
5028
  if (abortController.signal.aborted) {
4219
5029
  throw new TonConnectError('Disconnect was aborted');
4220
5030
  }
4221
- this.onWalletDisconnected('dapp');
4222
- yield ((_a = this.provider) === null || _a === void 0 ? void 0 : _a.disconnect({
4223
- signal: abortController.signal
5031
+ const traceId = (_a = options === null || options === void 0 ? void 0 : options.traceId) !== null && _a !== void 0 ? _a : UUIDv7();
5032
+ this.onWalletDisconnected('dapp', { traceId });
5033
+ yield ((_b = this.provider) === null || _b === void 0 ? void 0 : _b.disconnect({
5034
+ signal: abortController.signal,
5035
+ traceId
4224
5036
  }));
4225
5037
  prevAbortController === null || prevAbortController === void 0 ? void 0 : prevAbortController.abort();
4226
5038
  });
@@ -4231,7 +5043,7 @@ class TonConnect {
4231
5043
  */
4232
5044
  getSessionId() {
4233
5045
  return __awaiter(this, void 0, void 0, function* () {
4234
- if (!this.provider || !this.connected) {
5046
+ if (!this.provider) {
4235
5047
  return null;
4236
5048
  }
4237
5049
  try {
@@ -4253,6 +5065,30 @@ class TonConnect {
4253
5065
  }
4254
5066
  });
4255
5067
  }
5068
+ getSessionInfo() {
5069
+ var _a;
5070
+ if (((_a = this.provider) === null || _a === void 0 ? void 0 : _a.type) !== 'http') {
5071
+ return null;
5072
+ }
5073
+ if (!('session' in this.provider)) {
5074
+ return null;
5075
+ }
5076
+ try {
5077
+ const session = this.provider.session;
5078
+ if (!session) {
5079
+ return null;
5080
+ }
5081
+ const clientId = session.sessionCrypto.sessionId;
5082
+ let walletId = null;
5083
+ if ('walletPublicKey' in session) {
5084
+ walletId = session.walletPublicKey;
5085
+ }
5086
+ return { clientId, walletId };
5087
+ }
5088
+ catch (_b) {
5089
+ return null;
5090
+ }
5091
+ }
4256
5092
  /**
4257
5093
  * Pause bridge HTTP connection. Might be helpful, if you want to pause connections while browser tab is unfocused,
4258
5094
  * or if you use SDK with NodeJS and want to save server resources.
@@ -4296,10 +5132,10 @@ class TonConnect {
4296
5132
  createProvider(wallet) {
4297
5133
  let provider;
4298
5134
  if (!Array.isArray(wallet) && isWalletConnectionSourceJS(wallet)) {
4299
- provider = new InjectedProvider(this.dappSettings.storage, wallet.jsBridgeKey);
5135
+ provider = new InjectedProvider(this.dappSettings.storage, wallet.jsBridgeKey, this.analytics);
4300
5136
  }
4301
5137
  else {
4302
- provider = new BridgeProvider(this.dappSettings.storage, wallet);
5138
+ provider = new BridgeProvider(this.dappSettings.storage, wallet, this.analytics);
4303
5139
  }
4304
5140
  provider.listen(this.walletEventsListener.bind(this));
4305
5141
  return provider;
@@ -4307,18 +5143,18 @@ class TonConnect {
4307
5143
  walletEventsListener(e) {
4308
5144
  switch (e.event) {
4309
5145
  case 'connect':
4310
- this.onWalletConnected(e.payload);
5146
+ this.onWalletConnected(e.payload, { traceId: e.traceId });
4311
5147
  break;
4312
5148
  case 'connect_error':
4313
- this.tracker.trackConnectionError(e.payload.message, e.payload.code);
5149
+ this.tracker.trackConnectionError(e.payload.message, e.payload.code, this.getSessionInfo(), e.traceId);
4314
5150
  const walletError = connectErrorsParser.parseError(e.payload);
4315
5151
  this.onWalletConnectError(walletError);
4316
5152
  break;
4317
5153
  case 'disconnect':
4318
- this.onWalletDisconnected('wallet');
5154
+ this.onWalletDisconnected('wallet', { traceId: e.traceId });
4319
5155
  }
4320
5156
  }
4321
- onWalletConnected(connectEvent) {
5157
+ onWalletConnected(connectEvent, options) {
4322
5158
  var _a;
4323
5159
  const tonAccountItem = connectEvent.items.find(item => item.name === 'ton_addr');
4324
5160
  const tonProofItem = connectEvent.items.find(item => item.name === 'ton_proof');
@@ -4398,7 +5234,8 @@ class TonConnect {
4398
5234
  wallet.connectItems = { tonProof };
4399
5235
  }
4400
5236
  this.wallet = wallet;
4401
- this.tracker.trackConnectionCompleted(wallet);
5237
+ const sessionInfo = this.getSessionInfo();
5238
+ this.tracker.trackConnectionCompleted(wallet, sessionInfo, options === null || options === void 0 ? void 0 : options.traceId);
4402
5239
  }
4403
5240
  onWalletConnectError(error) {
4404
5241
  this.statusChangeErrorSubscriptions.forEach(errorsHandler => errorsHandler(error));
@@ -4408,8 +5245,9 @@ class TonConnect {
4408
5245
  throw error;
4409
5246
  }
4410
5247
  }
4411
- onWalletDisconnected(scope) {
4412
- this.tracker.trackDisconnection(this.wallet, scope);
5248
+ onWalletDisconnected(scope, options) {
5249
+ const sessionInfo = this.getSessionInfo();
5250
+ this.tracker.trackDisconnection(this.wallet, scope, sessionInfo, options === null || options === void 0 ? void 0 : options.traceId);
4413
5251
  this.wallet = null;
4414
5252
  }
4415
5253
  checkConnection() {
@@ -4447,5 +5285,5 @@ TonConnect.isWalletInjected = (walletJSKey) => InjectedProvider.isWalletInjected
4447
5285
  */
4448
5286
  TonConnect.isInsideWalletBrowser = (walletJSKey) => InjectedProvider.isInsideWalletBrowser(walletJSKey);
4449
5287
 
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 };
5288
+ export { BadRequestError, BrowserEventDispatcher, FetchWalletsError, LocalstorageNotFoundError, ParseHexError, TonConnect, TonConnectError, UUIDv7, UnknownAppError, UnknownError, UserRejectsError, WalletAlreadyConnectedError, WalletMissingRequiredFeaturesError, WalletNotConnectedError, WalletNotInjectedError, WalletNotSupportFeatureError, 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
5289
  //# sourceMappingURL=index.mjs.map