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