@tonconnect/ui 2.3.1 → 2.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/index.mjs CHANGED
@@ -50,7 +50,7 @@ var __async = (__this, __arguments, generator) => {
50
50
  });
51
51
  };
52
52
  var _a, _b, _c, _d, _e, _f, _g, _h;
53
- import { TonConnectError, isWalletInfoCurrentlyInjected, toUserFriendlyAddress, CHAIN, TonConnect, isTelegramUrl, encodeTelegramUrlParameters, WalletMissingRequiredFeaturesError, isWalletInfoRemote, checkRequiredWalletFeatures, isWalletInfoCurrentlyEmbedded, BrowserEventDispatcher, createVersionInfo, createResponseVersionEvent, createRequestVersionEvent, createConnectionStartedEvent, createConnectionCompletedEvent, createConnectionErrorEvent, createConnectionRestoringStartedEvent, createConnectionRestoringCompletedEvent, createConnectionRestoringErrorEvent, createDisconnectionEvent, createTransactionSentForSignatureEvent, createTransactionSignedEvent, createTransactionSigningFailedEvent, createDataSentForSignatureEvent, createDataSignedEvent, createDataSigningFailedEvent, WalletNotSupportFeatureError, SessionCrypto } from "@tonconnect/sdk";
53
+ import { TonConnectError, isWalletInfoCurrentlyInjected, toUserFriendlyAddress, CHAIN, TonConnect, isTelegramUrl, decodeTelegramUrlParameters, encodeTelegramUrlParameters, WalletMissingRequiredFeaturesError, isWalletInfoRemote, checkRequiredWalletFeatures, isConnectUrl, UUIDv7, isWalletInfoCurrentlyEmbedded, createVersionInfo, createResponseVersionEvent, createRequestVersionEvent, createWalletModalOpenedEvent, createSelectedWalletEvent, createConnectionStartedEvent, createConnectionCompletedEvent, createConnectionErrorEvent, createConnectionRestoringStartedEvent, createConnectionRestoringCompletedEvent, createConnectionRestoringErrorEvent, createDisconnectionEvent, createTransactionSentForSignatureEvent, createTransactionSignedEvent, createTransactionSigningFailedEvent, createDataSentForSignatureEvent, createDataSignedEvent, createDataSigningFailedEvent, BrowserEventDispatcher, WalletNotSupportFeatureError, SessionCrypto } from "@tonconnect/sdk";
54
54
  export * from "@tonconnect/sdk";
55
55
  import UAParser from "ua-parser-js";
56
56
  import deepmerge from "deepmerge";
@@ -1717,6 +1717,7 @@ function logWarning(...args) {
1717
1717
  }
1718
1718
  }
1719
1719
  function openLink(href, target = "_self") {
1720
+ setLastOpenedLink({ link: href });
1720
1721
  logDebug("openLink", href, target);
1721
1722
  window.open(href, target, "noopener noreferrer");
1722
1723
  }
@@ -1962,6 +1963,13 @@ const setLastSelectedWalletInfo = (walletInfo) => {
1962
1963
  _setLastSelectedWalletInfo(walletInfo);
1963
1964
  };
1964
1965
  const [action, setAction] = createSignal(null);
1966
+ const [lastVisibleWalletsInfo, setLastVisibleWalletsInfo] = createSignal({
1967
+ walletsMenu: "explicit_wallet",
1968
+ wallets: []
1969
+ });
1970
+ const [lastOpenedLink, setLastOpenedLink] = createSignal({
1971
+ link: ""
1972
+ });
1965
1973
  const common$1 = { "close": "Close", "openWallet": "Open wallet", "copyLink": "Copy Link", "linkCopied": "Link Copied", "copied": "Copied", "yourWallet": "Your Wallet", "retry": "Retry", "get": "GET", "mobile": "Mobile", "browserExtension": "Browser Extension", "desktop": "Desktop" };
1966
1974
  const button$1 = { "connectWallet": "Connect Wallet", "dropdown": { "copy": "Copy address", "copied": "Address copied!", "disconnect": "Disconnect" } };
1967
1975
  const notifications$1 = { "confirm": { "header": "Open {{ name }} to confirm the transaction." }, "transactionSent": { "header": "Transaction sent", "text": "Your transaction will be processed in a few seconds." }, "transactionCanceled": { "header": "Transaction canceled", "text": "There will be no changes to your account." }, "dataSigned": { "header": "Data signed" }, "signDataCanceled": { "header": "Sign data canceled" } };
@@ -2436,6 +2444,27 @@ if (!webAppVersion) {
2436
2444
  const window2 = getWindow$1();
2437
2445
  webAppVersion = (_g = (_f = (_e = window2 == null ? void 0 : window2.Telegram) == null ? void 0 : _e.WebApp) == null ? void 0 : _f.version) != null ? _g : "6.0";
2438
2446
  }
2447
+ const initDataRaw = initParams == null ? void 0 : initParams.tgWebAppData;
2448
+ let telegramUser = void 0;
2449
+ try {
2450
+ if (initDataRaw) {
2451
+ let initData = urlParseQueryString(initDataRaw);
2452
+ let userRaw = initData.user;
2453
+ if (userRaw) {
2454
+ let user = JSON.parse(userRaw);
2455
+ if (typeof user.id === "number" && typeof user.is_premium === "boolean") {
2456
+ telegramUser = {
2457
+ id: user.id,
2458
+ isPremium: user.is_premium
2459
+ };
2460
+ }
2461
+ }
2462
+ }
2463
+ } catch (e2) {
2464
+ }
2465
+ function getTgUser() {
2466
+ return telegramUser;
2467
+ }
2439
2468
  function isTmaPlatform(...platforms) {
2440
2469
  return platforms.includes(tmaPlatform);
2441
2470
  }
@@ -2467,6 +2496,7 @@ function sendOpenTelegramLink(link, fallback) {
2467
2496
  }
2468
2497
  const pathFull = url.pathname + url.search;
2469
2498
  if (isIframe() || versionAtLeast("6.1")) {
2499
+ setLastOpenedLink({ link: pathFull, type: "tg_link" });
2470
2500
  postEvent("web_app_open_tg_link", { path_full: pathFull });
2471
2501
  } else {
2472
2502
  openLinkBlank("https://t.me" + pathFull);
@@ -8711,6 +8741,10 @@ const AllWalletsListModal = (props) => {
8711
8741
  };
8712
8742
  const walletsList = () => isMobile() ? props.walletsList.filter(supportsMobile) : props.walletsList;
8713
8743
  const supportedWallets = () => walletsList().filter((wallet) => wallet.isSupportRequiredFeatures);
8744
+ setLastVisibleWalletsInfo({
8745
+ walletsMenu: "other_wallets",
8746
+ wallets: supportedWallets()
8747
+ });
8714
8748
  const unsupportedWallets = () => walletsList().filter((wallet) => !wallet.isSupportRequiredFeatures);
8715
8749
  return createComponent(DesktopSelectWalletModalStyled, {
8716
8750
  "data-tc-wallets-modal-list": "true",
@@ -9245,28 +9279,48 @@ function redirectToWallet(universalLink, deepLink, options, setOpenMethod) {
9245
9279
  }
9246
9280
  }
9247
9281
  }
9248
- function addSessionIdToUniversalLink(universalLink, sessionId) {
9249
- if (!sessionId) {
9250
- return universalLink;
9251
- }
9282
+ function enrichUniversalLink(universalLink, params) {
9283
+ var _a2, _b2;
9252
9284
  if (!isTelegramUrl(universalLink)) {
9253
- const newUrl2 = addQueryParameter(universalLink, "id", sessionId);
9254
- return newUrl2;
9285
+ return addQueryParametersIfNotPresented(universalLink, {
9286
+ id: params.sessionId,
9287
+ trace_id: params.traceId
9288
+ });
9255
9289
  }
9256
9290
  const directLink = convertToTGDirectLink(universalLink);
9257
9291
  const directLinkUrl = new URL(directLink);
9258
- if (!directLinkUrl.searchParams.has("startapp")) {
9259
- directLinkUrl.searchParams.append("startapp", "tonconnect");
9260
- }
9261
- const newUrl = addQueryParameter(directLinkUrl.toString(), "id", sessionId);
9262
- const lastParam = newUrl.slice(newUrl.lastIndexOf("&") + 1);
9263
- return newUrl.slice(0, newUrl.lastIndexOf("&")) + "-v__2-" + encodeTelegramUrlParameters(lastParam);
9292
+ const previousStartApp = decodeTelegramUrlParameters(
9293
+ (_a2 = directLinkUrl.searchParams.get("startapp")) != null ? _a2 : ""
9294
+ );
9295
+ let searchParams = buildSearchParams(previousStartApp);
9296
+ const sessionId = (_b2 = params.sessionId) != null ? _b2 : searchParams.get("id");
9297
+ const traceId = params.traceId;
9298
+ const orderedKeys = ["tonconnect", "v", "id", "trace_id"];
9299
+ const unorderedParams = searchParams.entries().filter(([key]) => !orderedKeys.includes(key));
9300
+ const startApp = buildQueryParams(__spreadProps(__spreadValues({
9301
+ tonconnect: "",
9302
+ v: "2",
9303
+ id: sessionId
9304
+ }, Object.fromEntries(unorderedParams)), {
9305
+ trace_id: traceId
9306
+ })).replace("=&", "&");
9307
+ directLinkUrl.searchParams.set("startapp", encodeTelegramUrlParameters(startApp));
9308
+ return directLinkUrl.toString();
9264
9309
  }
9265
9310
  function addQueryParameter(url, key, value) {
9266
9311
  const parsed = new URL(url);
9267
9312
  parsed.searchParams.append(key, value);
9268
9313
  return parsed.toString();
9269
9314
  }
9315
+ function addQueryParametersIfNotPresented(url, params) {
9316
+ const parsed = new URL(url);
9317
+ for (const [key, value] of Object.entries(params)) {
9318
+ if (value !== void 0 && value !== null) {
9319
+ parsed.searchParams.set(key, value);
9320
+ }
9321
+ }
9322
+ return parsed.toString();
9323
+ }
9270
9324
  function convertToTGDirectLink(universalLink) {
9271
9325
  const url = new URL(universalLink);
9272
9326
  if (url.searchParams.has("attach")) {
@@ -9275,6 +9329,20 @@ function convertToTGDirectLink(universalLink) {
9275
9329
  }
9276
9330
  return url.toString();
9277
9331
  }
9332
+ function buildSearchParams(search = "") {
9333
+ const url = new URL("https://example.com");
9334
+ url.search = search;
9335
+ return url.searchParams;
9336
+ }
9337
+ function buildQueryParams(params) {
9338
+ const searchParams = buildSearchParams();
9339
+ for (const [key, value] of Object.entries(params)) {
9340
+ if (value !== void 0 && value !== null) {
9341
+ searchParams.append(key, value);
9342
+ }
9343
+ }
9344
+ return searchParams.toString();
9345
+ }
9278
9346
  function convertToTGDeepLink(directLink) {
9279
9347
  const parsed = new URL(directLink);
9280
9348
  const [, domain, appname] = parsed.pathname.split("/");
@@ -9303,11 +9371,14 @@ const DesktopConnectionModal = (props) => {
9303
9371
  });
9304
9372
  onCleanup(unsubscribe);
9305
9373
  const generateUniversalLink = () => {
9374
+ var _a2;
9306
9375
  try {
9307
9376
  const universalLink2 = connector.connect({
9308
9377
  universalLink: props.wallet.universalLink,
9309
9378
  bridgeUrl: props.wallet.bridgeUrl
9310
- }, props.additionalRequest);
9379
+ }, props.additionalRequest, {
9380
+ traceId: (_a2 = props.walletsModalState) == null ? void 0 : _a2.traceId
9381
+ });
9311
9382
  setUniversalLink(universalLink2);
9312
9383
  } catch (e2) {
9313
9384
  }
@@ -9361,13 +9432,16 @@ const DesktopConnectionModal = (props) => {
9361
9432
  });
9362
9433
  };
9363
9434
  const onClickExtension = () => {
9435
+ var _a2;
9364
9436
  setConnectionErrored(null);
9365
9437
  setMode("extension");
9366
9438
  if (isWalletInfoCurrentlyInjected(props.wallet)) {
9367
9439
  setLastSelectedWalletInfo(props.wallet);
9368
9440
  connector.connect({
9369
9441
  jsBridgeKey: props.wallet.jsBridgeKey
9370
- }, props.additionalRequest);
9442
+ }, props.additionalRequest, {
9443
+ traceId: (_a2 = props.walletsModalState) == null ? void 0 : _a2.traceId
9444
+ });
9371
9445
  }
9372
9446
  };
9373
9447
  if (supportsMobile(props.wallet)) {
@@ -10079,10 +10153,15 @@ const MobileConnectionModal = (props) => {
10079
10153
  }, () => {
10080
10154
  setConnectionErrored(null);
10081
10155
  });
10082
- const universalLink = createMemo(() => connector.connect({
10083
- universalLink: props.wallet.universalLink,
10084
- bridgeUrl: props.wallet.bridgeUrl
10085
- }, props.additionalRequest));
10156
+ const universalLink = createMemo(() => {
10157
+ var _a2;
10158
+ return connector.connect({
10159
+ universalLink: props.wallet.universalLink,
10160
+ bridgeUrl: props.wallet.bridgeUrl
10161
+ }, props.additionalRequest, {
10162
+ traceId: (_a2 = props.walletModalState) == null ? void 0 : _a2.traceId
10163
+ });
10164
+ });
10086
10165
  const onClickTelegram = () => {
10087
10166
  const alwaysForceRedirect = true;
10088
10167
  setLastSelectedWalletInfo(__spreadProps(__spreadValues({}, props.wallet), {
@@ -10626,7 +10705,9 @@ const MobileUniversalModal = (props) => {
10626
10705
  }, null);
10627
10706
  const getUniversalLink = () => {
10628
10707
  if (!universalLink()) {
10629
- setUniversalLink(connector.connect(walletsBridges(), props.additionalRequest));
10708
+ setUniversalLink(connector.connect(walletsBridges(), props.additionalRequest, {
10709
+ traceId: props.walletModalState.traceId
10710
+ }));
10630
10711
  }
10631
10712
  return universalLink();
10632
10713
  };
@@ -10663,7 +10744,9 @@ const MobileUniversalModal = (props) => {
10663
10744
  const walletLink = connector.connect({
10664
10745
  bridgeUrl: atWallet.bridgeUrl,
10665
10746
  universalLink: atWallet.universalLink
10666
- }, props.additionalRequest);
10747
+ }, props.additionalRequest, {
10748
+ traceId: props.walletModalState.traceId
10749
+ });
10667
10750
  const forceRedirect = !firstClick();
10668
10751
  setFirstClick(false);
10669
10752
  redirectToTelegram(walletLink, {
@@ -10686,6 +10769,10 @@ const MobileUniversalModal = (props) => {
10686
10769
  };
10687
10770
  const supportedWallets = createMemo(() => walletsList().filter((wallet) => wallet.isSupportRequiredFeatures), null);
10688
10771
  const visibleWallets = createMemo(() => supportedWallets().slice(0, 3), null);
10772
+ setLastVisibleWalletsInfo({
10773
+ walletsMenu: "main_screen",
10774
+ wallets: atWalletSupportFeatures() ? [props.walletsList.find((wallet) => wallet.appName === AT_WALLET_APP_NAME), ...visibleWallets()] : visibleWallets()
10775
+ });
10689
10776
  const fourWalletsItem = createMemo(() => walletsList().filter((wallet) => !visibleWallets().find((w) => w.appName === wallet.appName)).slice(0, 4), null);
10690
10777
  return (() => {
10691
10778
  var _el$ = _tmpl$2();
@@ -10916,9 +11003,15 @@ const DesktopUniversalModal = (props) => {
10916
11003
  setLastSelectedWalletInfo({
10917
11004
  openMethod: "qrcode"
10918
11005
  });
10919
- const request = createMemo(() => connector.connect(walletsBridges(), props.additionalRequest));
11006
+ const request = createMemo(() => connector.connect(walletsBridges(), props.additionalRequest, {
11007
+ traceId: props.walletModalState.traceId
11008
+ }));
10920
11009
  const supportedWallets = createMemo(() => props.walletsList.filter((wallet) => wallet.isSupportRequiredFeatures), null);
10921
11010
  const visibleWallets = createMemo(() => supportedWallets().slice(0, 3), null);
11011
+ setLastVisibleWalletsInfo({
11012
+ walletsMenu: "main_screen",
11013
+ wallets: visibleWallets()
11014
+ });
10922
11015
  const fourWalletsItem = createMemo(() => props.walletsList.filter((wallet) => !visibleWallets().find((w) => w.appName === wallet.appName)).slice(0, 4), null);
10923
11016
  return createComponent(DesktopUniversalModalStyled, {
10924
11017
  onClick: () => setPopupOpened(false),
@@ -11513,6 +11606,9 @@ const WalletsModal = () => {
11513
11606
  get component() {
11514
11607
  return isMobile() ? MobileConnectionModal : DesktopConnectionModal;
11515
11608
  },
11609
+ get walletsModalState() {
11610
+ return walletsModalState();
11611
+ },
11516
11612
  get wallet() {
11517
11613
  return selectedWalletInfo();
11518
11614
  },
@@ -11535,6 +11631,9 @@ const WalletsModal = () => {
11535
11631
  return isMobile() ? MobileUniversalModal : DesktopUniversalModal;
11536
11632
  },
11537
11633
  onSelect: setSelectedWalletInfo,
11634
+ get walletModalState() {
11635
+ return walletsModalState();
11636
+ },
11538
11637
  get walletsList() {
11539
11638
  return walletsList();
11540
11639
  },
@@ -11625,7 +11724,10 @@ const ActionModal = (props) => {
11625
11724
  const returnStrategy = "returnStrategy" in currentAction ? currentAction.returnStrategy : appState.returnStrategy;
11626
11725
  const forceRedirect = !firstClick();
11627
11726
  setFirstClick(false);
11628
- const linkWithSessionId = addSessionIdToUniversalLink(universalLink, currentAction.sessionId);
11727
+ const linkWithSessionId = enrichUniversalLink(universalLink, {
11728
+ sessionId: currentAction.sessionId,
11729
+ traceId: currentAction.traceId
11730
+ });
11629
11731
  if (isTelegramUrl(universalLink)) {
11630
11732
  redirectToTelegram(linkWithSessionId, {
11631
11733
  returnStrategy,
@@ -12034,9 +12136,13 @@ const App = (props) => {
12034
12136
  });
12035
12137
  };
12036
12138
  const widgetController = {
12037
- openWalletsModal: () => void setTimeout(() => setWalletsModalState({
12038
- status: "opened",
12039
- closeReason: null
12139
+ openWalletsModal: (options) => void setTimeout(() => setWalletsModalState((prev) => {
12140
+ var _a2;
12141
+ return {
12142
+ status: "opened",
12143
+ traceId: (_a2 = options == null ? void 0 : options.traceId) != null ? _a2 : prev == null ? void 0 : prev.traceId,
12144
+ closeReason: null
12145
+ };
12040
12146
  })),
12041
12147
  closeWalletsModal: (reason) => void setTimeout(() => setWalletsModalState({
12042
12148
  status: "closed",
@@ -12053,8 +12159,9 @@ const widgetController = {
12053
12159
  status: "closed",
12054
12160
  closeReason: reason
12055
12161
  })),
12056
- openWalletNotSupportFeatureModal: (cause) => void setTimeout(() => setWalletsModalState({
12162
+ openWalletNotSupportFeatureModal: (cause, options) => void setTimeout(() => setWalletsModalState({
12057
12163
  status: "opened",
12164
+ traceId: options.traceId,
12058
12165
  closeReason: null,
12059
12166
  type: "wallet-not-support-feature",
12060
12167
  requiredFeature: cause.requiredFeature
@@ -12062,6 +12169,7 @@ const widgetController = {
12062
12169
  setAction: (action2) => void setTimeout(() => setAction(action2)),
12063
12170
  clearAction: () => void setTimeout(() => setAction(null)),
12064
12171
  getSelectedWalletInfo: () => lastSelectedWalletInfo(),
12172
+ getLastVisibleWallets: () => lastVisibleWalletsInfo(),
12065
12173
  removeSelectedWalletInfo: () => setLastSelectedWalletInfo(null),
12066
12174
  renderApp: (root, tonConnectUI) => render(() => createComponent(App, {
12067
12175
  tonConnectUI
@@ -12079,19 +12187,67 @@ class WalletsModalManager {
12079
12187
  this.state = state;
12080
12188
  this.consumers.forEach((consumer) => consumer(state));
12081
12189
  });
12190
+ createEffect(
12191
+ on(lastSelectedWalletInfo, (selectedWallet, previousWallet) => __async(this, null, function* () {
12192
+ try {
12193
+ const { wallets, walletsMenu } = widgetController.getLastVisibleWallets();
12194
+ if (selectedWallet && "appName" in selectedWallet) {
12195
+ if (previousWallet && "appName" in previousWallet && previousWallet.appName === selectedWallet.appName) {
12196
+ return;
12197
+ }
12198
+ const clientId = yield this.connector.getSessionId();
12199
+ this.tracker.trackSelectedWallet(
12200
+ wallets.map((wallet) => wallet.name),
12201
+ selectedWallet,
12202
+ walletsMenu,
12203
+ "",
12204
+ void 0,
12205
+ clientId,
12206
+ this.state.traceId
12207
+ );
12208
+ }
12209
+ } catch (error) {
12210
+ logError(error);
12211
+ }
12212
+ }))
12213
+ );
12214
+ createEffect(
12215
+ on(lastOpenedLink, (openedLink) => __async(this, null, function* () {
12216
+ try {
12217
+ const { wallets, walletsMenu } = widgetController.getLastVisibleWallets();
12218
+ if (isConnectUrl(openedLink.link)) {
12219
+ const selectedWallet = lastSelectedWalletInfo();
12220
+ const clientId = yield this.connector.getSessionId();
12221
+ this.tracker.trackSelectedWallet(
12222
+ wallets.map((wallet) => wallet.name),
12223
+ selectedWallet && "appName" in selectedWallet ? selectedWallet : null,
12224
+ walletsMenu,
12225
+ openedLink.link,
12226
+ openedLink.type,
12227
+ clientId,
12228
+ this.state.traceId
12229
+ );
12230
+ }
12231
+ } catch (error) {
12232
+ logError(error);
12233
+ }
12234
+ }))
12235
+ );
12082
12236
  }
12083
12237
  /**
12084
12238
  * Opens the modal window.
12085
12239
  */
12086
- open() {
12240
+ open(options) {
12087
12241
  return __async(this, null, function* () {
12242
+ var _a2;
12243
+ const traceId = (_a2 = options == null ? void 0 : options.traceId) != null ? _a2 : UUIDv7();
12088
12244
  this.tracker.trackConnectionStarted();
12089
12245
  const walletsList = yield this.connector.getWallets();
12090
12246
  const embeddedWallet = walletsList.find(isWalletInfoCurrentlyEmbedded);
12091
12247
  if (embeddedWallet) {
12092
- return this.connectEmbeddedWallet(embeddedWallet);
12248
+ return this.connectEmbeddedWallet(embeddedWallet, { traceId });
12093
12249
  } else {
12094
- return this.openWalletsModal();
12250
+ return this.openWalletsModal({ traceId });
12095
12251
  }
12096
12252
  });
12097
12253
  }
@@ -12119,10 +12275,12 @@ class WalletsModalManager {
12119
12275
  * @param embeddedWallet - Information about the embedded wallet to connect to.
12120
12276
  * @internal
12121
12277
  */
12122
- connectEmbeddedWallet(embeddedWallet) {
12278
+ connectEmbeddedWallet(embeddedWallet, options) {
12123
12279
  const connect = (parameters) => {
12124
12280
  setLastSelectedWalletInfo(embeddedWallet);
12125
- this.connector.connect({ jsBridgeKey: embeddedWallet.jsBridgeKey }, parameters);
12281
+ this.connector.connect({ jsBridgeKey: embeddedWallet.jsBridgeKey }, parameters, {
12282
+ traceId: options.traceId
12283
+ });
12126
12284
  };
12127
12285
  const additionalRequest = appState.connectRequestParameters;
12128
12286
  if ((additionalRequest == null ? void 0 : additionalRequest.state) === "loading") {
@@ -12135,12 +12293,12 @@ class WalletsModalManager {
12135
12293
  * Opens the modal window to connect to an external wallet, and waits when modal window is opened.
12136
12294
  * @internal
12137
12295
  */
12138
- openWalletsModal() {
12296
+ openWalletsModal(options) {
12139
12297
  return __async(this, null, function* () {
12140
12298
  if (isInTMA()) {
12141
12299
  sendExpand();
12142
12300
  }
12143
- widgetController.openWalletsModal();
12301
+ widgetController.openWalletsModal({ traceId: options.traceId });
12144
12302
  return new Promise((resolve) => {
12145
12303
  const unsubscribe = this.onStateChange((state) => {
12146
12304
  const { status } = state;
@@ -12273,10 +12431,9 @@ class SingleWalletModalManager {
12273
12431
  }
12274
12432
  class TonConnectUITracker {
12275
12433
  constructor(options) {
12276
- var _a2;
12277
12434
  this.eventPrefix = "ton-connect-ui-";
12278
12435
  this.tonConnectSdkVersion = null;
12279
- this.eventDispatcher = (_a2 = options == null ? void 0 : options.eventDispatcher) != null ? _a2 : new BrowserEventDispatcher();
12436
+ this.eventDispatcher = options == null ? void 0 : options.eventDispatcher;
12280
12437
  this.tonConnectUiVersion = options.tonConnectUiVersion;
12281
12438
  this.init().catch();
12282
12439
  }
@@ -12352,6 +12509,29 @@ class TonConnectUITracker {
12352
12509
  } catch (e2) {
12353
12510
  }
12354
12511
  }
12512
+ /**
12513
+ * Track wallet opened event.
12514
+ * @param args
12515
+ */
12516
+ trackWalletModalOpened(...args) {
12517
+ try {
12518
+ const event = createWalletModalOpenedEvent(this.version, ...args);
12519
+ this.dispatchUserActionEvent(event);
12520
+ } catch (e2) {
12521
+ }
12522
+ }
12523
+ /**
12524
+ * Track wallet selected event.
12525
+ * @param args
12526
+ */
12527
+ trackSelectedWallet(...args) {
12528
+ try {
12529
+ const event = createSelectedWalletEvent(this.version, ...args);
12530
+ this.dispatchUserActionEvent(event);
12531
+ } catch (e2) {
12532
+ logError(e2);
12533
+ }
12534
+ }
12355
12535
  /**
12356
12536
  * Track connection init event.
12357
12537
  * @param args
@@ -12496,22 +12676,48 @@ class TonConnectUITracker {
12496
12676
  }
12497
12677
  }
12498
12678
  }
12499
- const tonConnectUiVersion = "2.3.1";
12679
+ const tonConnectUiVersion = "2.4.0-beta.0";
12680
+ class TonConnectEnvironment {
12681
+ constructor() {
12682
+ this.userAgent = getUserAgent();
12683
+ }
12684
+ getLocale() {
12685
+ var _a2;
12686
+ return ((_a2 = navigator.languages) == null ? void 0 : _a2[0]) || navigator.language || "";
12687
+ }
12688
+ getBrowser() {
12689
+ var _a2;
12690
+ return (_a2 = this.userAgent.browser) != null ? _a2 : "";
12691
+ }
12692
+ getPlatform() {
12693
+ var _a2;
12694
+ return (_a2 = this.userAgent.os) != null ? _a2 : "";
12695
+ }
12696
+ getTelegramUser() {
12697
+ return getTgUser();
12698
+ }
12699
+ getClientEnvironment() {
12700
+ return isInTMA() ? "miniapp" : "web";
12701
+ }
12702
+ }
12500
12703
  class TonConnectUI {
12501
12704
  // TODO: `actionsConfiguration.twaReturnUrl` is used only in `connectWallet` method, but it's not used in `sendTransaction` method, NEED TO FIX IT
12502
12705
  constructor(options) {
12706
+ var _a2;
12503
12707
  this.walletInfoStorage = new WalletInfoStorage();
12504
12708
  this.preferredWalletStorage = new PreferredWalletStorage();
12505
12709
  this.walletInfo = null;
12506
12710
  this.systemThemeChangeUnsubscribe = null;
12507
12711
  this.connectionRestored = Promise.resolve(false);
12712
+ let eventDispatcher = (_a2 = options == null ? void 0 : options.eventDispatcher) != null ? _a2 : new BrowserEventDispatcher();
12508
12713
  if (options && "connector" in options && options.connector) {
12509
12714
  this.connector = options.connector;
12510
12715
  } else if (options && "manifestUrl" in options && options.manifestUrl) {
12511
12716
  this.connector = new TonConnect({
12512
12717
  manifestUrl: options.manifestUrl,
12513
- eventDispatcher: options.eventDispatcher,
12514
- walletsRequiredFeatures: options.walletsRequiredFeatures
12718
+ eventDispatcher,
12719
+ walletsRequiredFeatures: options.walletsRequiredFeatures,
12720
+ environment: new TonConnectEnvironment()
12515
12721
  });
12516
12722
  } else {
12517
12723
  throw new TonConnectUIError(
@@ -12519,7 +12725,7 @@ class TonConnectUI {
12519
12725
  );
12520
12726
  }
12521
12727
  this.tracker = new TonConnectUITracker({
12522
- eventDispatcher: options == null ? void 0 : options.eventDispatcher,
12728
+ eventDispatcher,
12523
12729
  tonConnectUiVersion
12524
12730
  });
12525
12731
  this.modal = new WalletsModalManager({
@@ -12687,9 +12893,18 @@ class TonConnectUI {
12687
12893
  /**
12688
12894
  * Opens the modal window, returns a promise that resolves after the modal window is opened.
12689
12895
  */
12690
- openModal() {
12896
+ openModal(options) {
12691
12897
  return __async(this, null, function* () {
12692
- return this.modal.open();
12898
+ var _a2;
12899
+ const traceId = (_a2 = options == null ? void 0 : options.traceId) != null ? _a2 : UUIDv7();
12900
+ yield this.modal.open({ traceId });
12901
+ const sessionId = yield this.getSessionId();
12902
+ const visibleWallets = widgetController.getLastVisibleWallets();
12903
+ this.tracker.trackWalletModalOpened(
12904
+ visibleWallets.wallets.map((wallet) => wallet.name),
12905
+ sessionId,
12906
+ options == null ? void 0 : options.traceId
12907
+ );
12693
12908
  });
12694
12909
  }
12695
12910
  /**
@@ -12746,26 +12961,30 @@ class TonConnectUI {
12746
12961
  * @return Connected wallet.
12747
12962
  * @throws TonConnectUIError if connection was aborted.
12748
12963
  */
12749
- connectWallet() {
12964
+ connectWallet(options) {
12750
12965
  return __async(this, null, function* () {
12966
+ var _a2;
12967
+ const traceId = (_a2 = options == null ? void 0 : options.traceId) != null ? _a2 : UUIDv7();
12751
12968
  const walletsList = yield this.getWallets();
12752
12969
  const embeddedWallet = walletsList.find(isWalletInfoCurrentlyEmbedded);
12753
12970
  if (embeddedWallet) {
12754
- return yield this.connectEmbeddedWallet(embeddedWallet);
12971
+ return yield this.connectEmbeddedWallet(embeddedWallet, { traceId });
12755
12972
  } else {
12756
- return yield this.connectExternalWallet();
12973
+ return yield this.connectExternalWallet({ traceId });
12757
12974
  }
12758
12975
  });
12759
12976
  }
12760
12977
  /**
12761
12978
  * Disconnect wallet and clean localstorage.
12762
12979
  */
12763
- disconnect() {
12980
+ disconnect(options) {
12981
+ var _a2;
12982
+ const traceId = (_a2 = options == null ? void 0 : options.traceId) != null ? _a2 : UUIDv7();
12764
12983
  this.tracker.trackDisconnection(this.wallet, "dapp");
12765
12984
  widgetController.clearAction();
12766
12985
  widgetController.removeSelectedWalletInfo();
12767
12986
  this.walletInfoStorage.removeWalletInfo();
12768
- return this.connector.disconnect();
12987
+ return this.connector.disconnect({ traceId });
12769
12988
  }
12770
12989
  /**
12771
12990
  * Opens the modal window and handles the transaction sending.
@@ -12774,6 +12993,8 @@ class TonConnectUI {
12774
12993
  */
12775
12994
  sendTransaction(tx, options) {
12776
12995
  return __async(this, null, function* () {
12996
+ var _a2;
12997
+ const traceId = (_a2 = options == null ? void 0 : options.traceId) != null ? _a2 : UUIDv7();
12777
12998
  this.tracker.trackTransactionSentForSignature(this.wallet, tx);
12778
12999
  if (!this.connected) {
12779
13000
  this.tracker.trackTransactionSigningFailed(this.wallet, tx, "Wallet was not connected");
@@ -12789,11 +13010,12 @@ class TonConnectUI {
12789
13010
  showNotification: notifications2.includes("before"),
12790
13011
  openModal: modals.includes("before"),
12791
13012
  sent: false,
12792
- sessionId: sessionId || void 0
13013
+ sessionId: sessionId || void 0,
13014
+ traceId
12793
13015
  });
12794
13016
  const abortController = new AbortController();
12795
13017
  const onRequestSent = () => {
12796
- var _a2;
13018
+ var _a3;
12797
13019
  if (abortController.signal.aborted) {
12798
13020
  return;
12799
13021
  }
@@ -12802,12 +13024,14 @@ class TonConnectUI {
12802
13024
  showNotification: notifications2.includes("before"),
12803
13025
  openModal: modals.includes("before"),
12804
13026
  sent: true,
12805
- sessionId: sessionId || void 0
13027
+ sessionId: sessionId || void 0,
13028
+ traceId
12806
13029
  });
12807
13030
  this.redirectAfterRequestSent({
12808
13031
  returnStrategy,
12809
13032
  twaReturnUrl,
12810
- sessionId: sessionId || void 0
13033
+ sessionId: sessionId || void 0,
13034
+ traceId
12811
13035
  });
12812
13036
  let firstClick = true;
12813
13037
  const redirectToWallet2 = () => __async(this, null, function* () {
@@ -12820,10 +13044,11 @@ class TonConnectUI {
12820
13044
  returnStrategy,
12821
13045
  twaReturnUrl,
12822
13046
  forceRedirect,
12823
- sessionId: sessionId || void 0
13047
+ sessionId: sessionId || void 0,
13048
+ traceId
12824
13049
  });
12825
13050
  });
12826
- (_a2 = options == null ? void 0 : options.onRequestSent) == null ? void 0 : _a2.call(options, redirectToWallet2);
13051
+ (_a3 = options == null ? void 0 : options.onRequestSent) == null ? void 0 : _a3.call(options, redirectToWallet2);
12827
13052
  };
12828
13053
  const unsubscribe = this.onTransactionModalStateChange((action2) => {
12829
13054
  if (action2 == null ? void 0 : action2.openModal) {
@@ -12838,7 +13063,8 @@ class TonConnectUI {
12838
13063
  const result = yield this.waitForSendTransaction(
12839
13064
  {
12840
13065
  transaction: tx,
12841
- signal: abortController.signal
13066
+ signal: abortController.signal,
13067
+ traceId
12842
13068
  },
12843
13069
  onRequestSent
12844
13070
  );
@@ -12846,19 +13072,21 @@ class TonConnectUI {
12846
13072
  widgetController.setAction({
12847
13073
  name: "transaction-sent",
12848
13074
  showNotification: notifications2.includes("success"),
12849
- openModal: modals.includes("success")
13075
+ openModal: modals.includes("success"),
13076
+ traceId
12850
13077
  });
12851
13078
  return result;
12852
13079
  } catch (e2) {
12853
13080
  if (e2 instanceof WalletNotSupportFeatureError) {
12854
13081
  widgetController.clearAction();
12855
- widgetController.openWalletNotSupportFeatureModal(e2.cause);
13082
+ widgetController.openWalletNotSupportFeatureModal(e2.cause, { traceId });
12856
13083
  throw e2;
12857
13084
  }
12858
13085
  widgetController.setAction({
12859
13086
  name: "transaction-canceled",
12860
13087
  showNotification: notifications2.includes("error"),
12861
- openModal: modals.includes("error")
13088
+ openModal: modals.includes("error"),
13089
+ traceId
12862
13090
  });
12863
13091
  if (e2 instanceof TonConnectError) {
12864
13092
  throw e2;
@@ -12877,6 +13105,8 @@ class TonConnectUI {
12877
13105
  */
12878
13106
  signData(data, options) {
12879
13107
  return __async(this, null, function* () {
13108
+ var _a2;
13109
+ const traceId = (_a2 = options == null ? void 0 : options.traceId) != null ? _a2 : UUIDv7();
12880
13110
  this.tracker.trackDataSentForSignature(this.wallet, data);
12881
13111
  if (!this.connected) {
12882
13112
  this.tracker.trackDataSigningFailed(this.wallet, data, "Wallet was not connected");
@@ -12892,11 +13122,12 @@ class TonConnectUI {
12892
13122
  showNotification: notifications2.includes("before"),
12893
13123
  openModal: modals.includes("before"),
12894
13124
  signed: false,
12895
- sessionId: sessionId || void 0
13125
+ sessionId: sessionId || void 0,
13126
+ traceId
12896
13127
  });
12897
13128
  const abortController = new AbortController();
12898
13129
  const onRequestSent = () => {
12899
- var _a2;
13130
+ var _a3;
12900
13131
  if (abortController.signal.aborted) {
12901
13132
  return;
12902
13133
  }
@@ -12905,12 +13136,14 @@ class TonConnectUI {
12905
13136
  showNotification: notifications2.includes("before"),
12906
13137
  openModal: modals.includes("before"),
12907
13138
  signed: true,
12908
- sessionId: sessionId || void 0
13139
+ sessionId: sessionId || void 0,
13140
+ traceId
12909
13141
  });
12910
13142
  this.redirectAfterRequestSent({
12911
13143
  returnStrategy,
12912
13144
  twaReturnUrl,
12913
- sessionId: sessionId || void 0
13145
+ sessionId: sessionId || void 0,
13146
+ traceId
12914
13147
  });
12915
13148
  let firstClick = true;
12916
13149
  const redirectToWallet2 = () => {
@@ -12923,10 +13156,11 @@ class TonConnectUI {
12923
13156
  returnStrategy,
12924
13157
  twaReturnUrl,
12925
13158
  forceRedirect,
12926
- sessionId: sessionId || void 0
13159
+ sessionId: sessionId || void 0,
13160
+ traceId
12927
13161
  });
12928
13162
  };
12929
- (_a2 = options == null ? void 0 : options.onRequestSent) == null ? void 0 : _a2.call(options, redirectToWallet2);
13163
+ (_a3 = options == null ? void 0 : options.onRequestSent) == null ? void 0 : _a3.call(options, redirectToWallet2);
12930
13164
  };
12931
13165
  const unsubscribe = this.onTransactionModalStateChange((action2) => {
12932
13166
  if (action2 == null ? void 0 : action2.openModal) {
@@ -12941,7 +13175,8 @@ class TonConnectUI {
12941
13175
  const result = yield this.waitForSignData(
12942
13176
  {
12943
13177
  data,
12944
- signal: new AbortController().signal
13178
+ signal: new AbortController().signal,
13179
+ traceId
12945
13180
  },
12946
13181
  onRequestSent
12947
13182
  );
@@ -12949,19 +13184,21 @@ class TonConnectUI {
12949
13184
  widgetController.setAction({
12950
13185
  name: "data-signed",
12951
13186
  showNotification: notifications2.includes("success"),
12952
- openModal: modals.includes("success")
13187
+ openModal: modals.includes("success"),
13188
+ traceId
12953
13189
  });
12954
13190
  return result;
12955
13191
  } catch (e2) {
12956
13192
  if (e2 instanceof WalletNotSupportFeatureError) {
12957
13193
  widgetController.clearAction();
12958
- widgetController.openWalletNotSupportFeatureModal(e2.cause);
13194
+ widgetController.openWalletNotSupportFeatureModal(e2.cause, { traceId });
12959
13195
  throw e2;
12960
13196
  }
12961
13197
  widgetController.setAction({
12962
13198
  name: "sign-data-canceled",
12963
13199
  showNotification: notifications2.includes("error"),
12964
- openModal: modals.includes("error")
13200
+ openModal: modals.includes("error"),
13201
+ traceId
12965
13202
  });
12966
13203
  if (e2 instanceof TonConnectError) {
12967
13204
  throw e2;
@@ -12981,9 +13218,6 @@ class TonConnectUI {
12981
13218
  getSessionId() {
12982
13219
  return __async(this, null, function* () {
12983
13220
  var _a2, _b2;
12984
- if (!this.connected) {
12985
- return null;
12986
- }
12987
13221
  try {
12988
13222
  const storage = (_a2 = this.connector.dappSettings) == null ? void 0 : _a2.storage;
12989
13223
  if (storage) {
@@ -13010,13 +13244,14 @@ class TonConnectUI {
13010
13244
  returnStrategy,
13011
13245
  twaReturnUrl,
13012
13246
  forceRedirect,
13013
- sessionId
13247
+ sessionId,
13248
+ traceId
13014
13249
  }) {
13015
13250
  if (this.walletInfo && "universalLink" in this.walletInfo && (this.walletInfo.openMethod === "universal-link" || this.walletInfo.openMethod === "custom-deeplink")) {
13016
- const linkWithSessionId = addSessionIdToUniversalLink(
13017
- this.walletInfo.universalLink,
13018
- sessionId
13019
- );
13251
+ const linkWithSessionId = enrichUniversalLink(this.walletInfo.universalLink, {
13252
+ sessionId,
13253
+ traceId
13254
+ });
13020
13255
  if (isTelegramUrl(this.walletInfo.universalLink)) {
13021
13256
  redirectToTelegram(linkWithSessionId, {
13022
13257
  returnStrategy,
@@ -13044,11 +13279,13 @@ class TonConnectUI {
13044
13279
  * @throws Error if the connection process fails.
13045
13280
  * @internal
13046
13281
  */
13047
- connectEmbeddedWallet(embeddedWallet) {
13282
+ connectEmbeddedWallet(embeddedWallet, options) {
13048
13283
  return __async(this, null, function* () {
13049
13284
  const connect = (parameters) => {
13050
13285
  setLastSelectedWalletInfo(embeddedWallet);
13051
- this.connector.connect({ jsBridgeKey: embeddedWallet.jsBridgeKey }, parameters);
13286
+ this.connector.connect({ jsBridgeKey: embeddedWallet.jsBridgeKey }, parameters, {
13287
+ traceId: options.traceId
13288
+ });
13052
13289
  };
13053
13290
  const additionalRequest = appState.connectRequestParameters;
13054
13291
  if ((additionalRequest == null ? void 0 : additionalRequest.state) === "loading") {
@@ -13057,7 +13294,8 @@ class TonConnectUI {
13057
13294
  connect(additionalRequest == null ? void 0 : additionalRequest.value);
13058
13295
  }
13059
13296
  return yield this.waitForWalletConnection({
13060
- ignoreErrors: false
13297
+ ignoreErrors: false,
13298
+ traceId: options.traceId
13061
13299
  });
13062
13300
  });
13063
13301
  }
@@ -13068,10 +13306,10 @@ class TonConnectUI {
13068
13306
  * @throws Error if the user cancels the connection process or if the connection process fails.
13069
13307
  * @internal
13070
13308
  */
13071
- connectExternalWallet() {
13309
+ connectExternalWallet(options) {
13072
13310
  return __async(this, null, function* () {
13073
13311
  const abortController = new AbortController();
13074
- widgetController.openWalletsModal();
13312
+ widgetController.openWalletsModal({ traceId: options.traceId });
13075
13313
  const unsubscribe = this.onModalStateChange((state) => {
13076
13314
  const { status, closeReason } = state;
13077
13315
  if (status === "opened") {
@@ -13084,7 +13322,8 @@ class TonConnectUI {
13084
13322
  });
13085
13323
  return yield this.waitForWalletConnection({
13086
13324
  ignoreErrors: true,
13087
- signal: abortController.signal
13325
+ signal: abortController.signal,
13326
+ traceId: options.traceId
13088
13327
  });
13089
13328
  });
13090
13329
  }
@@ -13182,7 +13421,11 @@ class TonConnectUI {
13182
13421
  reject(new TonConnectUIError("Transaction was not sent"));
13183
13422
  };
13184
13423
  signal.addEventListener("abort", onCanceledHandler, { once: true });
13185
- this.connector.sendTransaction(transaction, { onRequestSent, signal }).then((result) => {
13424
+ this.connector.sendTransaction(transaction, {
13425
+ onRequestSent,
13426
+ signal,
13427
+ traceId: options.traceId
13428
+ }).then((result) => {
13186
13429
  signal.removeEventListener("abort", onCanceledHandler);
13187
13430
  return onTransactionHandler(result);
13188
13431
  }).catch((reason) => {