@tonconnect/ui 2.0.2 → 2.0.3-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { WalletInfoBase, WalletInfoInjectable, WalletInfoRemote, ITonConnect, Wallet, WalletInfo, Account, ConnectAdditionalRequest, TonConnectError, SendTransactionRequest, SendTransactionResponse } from '@tonconnect/sdk';
1
+ import { WalletInfoBase, WalletInfoInjectable, WalletInfoRemote, ConnectionEvent, ConnectionRestoringEvent, DisconnectionEvent, TransactionSigningEvent, ITonConnect, EventDispatcher, SdkActionEvent, Wallet, WalletInfo, Account, ConnectAdditionalRequest, TonConnectError, SendTransactionRequest, SendTransactionResponse } from '@tonconnect/sdk';
2
2
  export * from '@tonconnect/sdk';
3
3
  import { Property } from 'csstype';
4
4
 
@@ -168,6 +168,11 @@ interface TonConnectUiOptions {
168
168
  enableAndroidBackHandler?: boolean;
169
169
  }
170
170
 
171
+ /**
172
+ * User action events.
173
+ */
174
+ declare type UserActionEvent = ConnectionEvent | ConnectionRestoringEvent | DisconnectionEvent | TransactionSigningEvent;
175
+
171
176
  declare type TonConnectUiCreateOptions = TonConnectUiOptionsWithConnector | TonConnectUiOptionsWithManifest;
172
177
  interface TonConnectUiOptionsWithManifest extends TonConnectUiCreateOptionsBase {
173
178
  /**
@@ -193,6 +198,11 @@ interface TonConnectUiCreateOptionsBase extends TonConnectUiOptions {
193
198
  * @default `div#tc-widget-root`.
194
199
  */
195
200
  widgetRootId?: string;
201
+ /**
202
+ * Event dispatcher to track user actions. By default, it uses `window.dispatchEvent` for browser environment.
203
+ * @default BrowserEventDispatcher.
204
+ */
205
+ eventDispatcher?: EventDispatcher<UserActionEvent | SdkActionEvent>;
196
206
  }
197
207
 
198
208
  declare type WalletOpenMethod = 'qrcode' | 'universal-link' | 'custom-deeplink';
@@ -218,8 +228,9 @@ interface WalletsModal {
218
228
  open: () => void;
219
229
  /**
220
230
  * Close the modal.
231
+ * @default 'action-cancelled'
221
232
  */
222
- close: () => void;
233
+ close: (reason?: WalletsModalCloseReason) => void;
223
234
  /**
224
235
  * Subscribe to the modal window status changes.
225
236
  */
@@ -307,6 +318,11 @@ declare class TonConnectUI {
307
318
  static getWallets(): Promise<WalletInfo[]>;
308
319
  private readonly walletInfoStorage;
309
320
  private readonly preferredWalletStorage;
321
+ /**
322
+ * Emits user action event to the EventDispatcher. By default, it uses `window.dispatchEvent` for browser environment.
323
+ * @private
324
+ */
325
+ private readonly tracker;
310
326
  private walletInfo;
311
327
  private systemThemeChangeUnsubscribe;
312
328
  private actionsConfiguration?;
@@ -377,7 +393,7 @@ declare class TonConnectUI {
377
393
  /**
378
394
  * Closes the modal window.
379
395
  */
380
- closeModal(): void;
396
+ closeModal(reason?: WalletsModalCloseReason): void;
381
397
  /**
382
398
  * Subscribe to the modal window state changes, returns a function which has to be called to unsubscribe.
383
399
  */
@@ -395,7 +411,7 @@ declare class TonConnectUI {
395
411
  * Close the single wallet modal window.
396
412
  * @experimental
397
413
  */
398
- closeSingleWalletModal(): void;
414
+ closeSingleWalletModal(closeReason?: WalletsModalCloseReason): void;
399
415
  /**
400
416
  * Subscribe to the single wallet modal window state changes, returns a function which has to be called to unsubscribe.
401
417
  * @experimental
@@ -480,4 +496,4 @@ declare class TonConnectUIError extends TonConnectError {
480
496
  constructor(...args: ConstructorParameters<typeof Error>);
481
497
  }
482
498
 
483
- export { ActionConfiguration, BorderRadius, Color, ColorsSet, ConnectedWallet, Loadable, LoadableLoading, LoadableReady, Locales, PartialColorsSet, ReturnStrategy, THEME, Theme, TonConnectUI, TonConnectUIError, TonConnectUiCreateOptions, TonConnectUiCreateOptionsBase, TonConnectUiOptions, TonConnectUiOptionsWithConnector, TonConnectUiOptionsWithManifest, UIPreferences, UIWallet, WalletInfoRemoteWithOpenMethod, WalletInfoWithOpenMethod, WalletModalClosed, WalletModalOpened, WalletOpenMethod, WalletsListConfiguration, WalletsModal, WalletsModalCloseReason, WalletsModalState };
499
+ export { ActionConfiguration, BorderRadius, Color, ColorsSet, ConnectedWallet, Loadable, LoadableLoading, LoadableReady, Locales, PartialColorsSet, ReturnStrategy, THEME, Theme, TonConnectUI, TonConnectUIError, TonConnectUiCreateOptions, TonConnectUiCreateOptionsBase, TonConnectUiOptions, TonConnectUiOptionsWithConnector, TonConnectUiOptionsWithManifest, UIPreferences, UIWallet, UserActionEvent, WalletInfoRemoteWithOpenMethod, WalletInfoWithOpenMethod, WalletModalClosed, WalletModalOpened, WalletOpenMethod, WalletsListConfiguration, WalletsModal, WalletsModalCloseReason, WalletsModalState };
package/lib/index.mjs CHANGED
@@ -42,7 +42,7 @@ var __async = (__this, __arguments, generator) => {
42
42
  });
43
43
  };
44
44
  var _a, _b, _c, _d, _e, _f, _g, _h;
45
- import { TonConnectError, isWalletInfoCurrentlyInjected, toUserFriendlyAddress, CHAIN, TonConnect, isTelegramUrl, encodeTelegramUrlParameters, isWalletInfoRemote, isWalletInfoCurrentlyEmbedded } from "@tonconnect/sdk";
45
+ import { TonConnectError, isWalletInfoCurrentlyInjected, toUserFriendlyAddress, CHAIN, TonConnect, isTelegramUrl, encodeTelegramUrlParameters, isWalletInfoRemote, isWalletInfoCurrentlyEmbedded, BrowserEventDispatcher, createConnectionStartedEvent, createConnectionCompletedEvent, createConnectionErrorEvent, createConnectionRestoringStartedEvent, createConnectionRestoringCompletedEvent, createConnectionRestoringErrorEvent, createDisconnectionEvent, createTransactionSentForSignatureEvent, createTransactionSignedEvent, createTransactionSigningFailedEvent } from "@tonconnect/sdk";
46
46
  export * from "@tonconnect/sdk";
47
47
  import UAParser from "ua-parser-js";
48
48
  import deepmerge from "deepmerge";
@@ -10031,18 +10031,26 @@ const WalletsModal = () => {
10031
10031
  return (_a2 = appState.connectRequestParameters) == null ? void 0 : _a2.value;
10032
10032
  });
10033
10033
  const onClose = (closeReason) => {
10034
- setWalletsModalState({
10035
- status: "closed",
10036
- closeReason
10037
- });
10038
- setSelectedWalletInfo(null);
10039
- setInfoTab(false);
10034
+ tonConnectUI.closeModal(closeReason);
10040
10035
  };
10041
10036
  const unsubscribe = connector.onStatusChange((wallet) => {
10042
10037
  if (wallet) {
10043
10038
  onClose("wallet-selected");
10044
10039
  }
10045
10040
  });
10041
+ const onSelectAllWallets = () => {
10042
+ setSelectedTab("all-wallets");
10043
+ };
10044
+ const onSelectUniversal = () => {
10045
+ setSelectedTab("universal");
10046
+ };
10047
+ const clearSelectedWalletInfo = () => {
10048
+ setSelectedWalletInfo(null);
10049
+ };
10050
+ onCleanup(() => {
10051
+ setSelectedWalletInfo(null);
10052
+ setInfoTab(false);
10053
+ });
10046
10054
  onCleanup(unsubscribe);
10047
10055
  return createComponent(StyledModal, {
10048
10056
  get opened() {
@@ -10107,7 +10115,7 @@ const WalletsModal = () => {
10107
10115
  get additionalRequest() {
10108
10116
  return additionalRequest();
10109
10117
  },
10110
- onBackClick: () => setSelectedWalletInfo(null)
10118
+ onBackClick: clearSelectedWalletInfo
10111
10119
  });
10112
10120
  }
10113
10121
  }), createComponent(Match, {
@@ -10126,7 +10134,7 @@ const WalletsModal = () => {
10126
10134
  get additionalRequest() {
10127
10135
  return additionalRequest();
10128
10136
  },
10129
- onSelectAllWallets: () => setSelectedTab("all-wallets")
10137
+ onSelectAllWallets
10130
10138
  });
10131
10139
  }
10132
10140
  }), createComponent(Match, {
@@ -10138,7 +10146,7 @@ const WalletsModal = () => {
10138
10146
  get walletsList() {
10139
10147
  return walletsList();
10140
10148
  },
10141
- onBack: () => setSelectedTab("universal"),
10149
+ onBack: onSelectUniversal,
10142
10150
  onSelect: setSelectedWalletInfo
10143
10151
  });
10144
10152
  }
@@ -10393,6 +10401,7 @@ const SingleWalletModal = () => {
10393
10401
  }
10394
10402
  });
10395
10403
  const connector = useContext(ConnectorContext);
10404
+ const tonConnectUI = useContext(TonConnectUiContext);
10396
10405
  const [infoTab, setInfoTab] = createSignal(false);
10397
10406
  const additionalRequestLoading = () => {
10398
10407
  var _a2;
@@ -10406,11 +10415,7 @@ const SingleWalletModal = () => {
10406
10415
  return (_a2 = appState.connectRequestParameters) == null ? void 0 : _a2.value;
10407
10416
  });
10408
10417
  const onClose = (closeReason) => {
10409
- setSingleWalletModalState({
10410
- status: "closed",
10411
- closeReason
10412
- });
10413
- setInfoTab(false);
10418
+ tonConnectUI.closeSingleWalletModal(closeReason);
10414
10419
  };
10415
10420
  const unsubscribe = connector.onStatusChange((wallet) => {
10416
10421
  if (wallet) {
@@ -10418,6 +10423,9 @@ const SingleWalletModal = () => {
10418
10423
  }
10419
10424
  });
10420
10425
  onCleanup(unsubscribe);
10426
+ onCleanup(() => {
10427
+ setInfoTab(false);
10428
+ });
10421
10429
  return createComponent(StyledModal, {
10422
10430
  get opened() {
10423
10431
  return getSingleWalletModalIsOpened();
@@ -10567,8 +10575,10 @@ class WalletsModalManager {
10567
10575
  __publicField(this, "connector");
10568
10576
  __publicField(this, "setConnectRequestParametersCallback");
10569
10577
  __publicField(this, "consumers", []);
10578
+ __publicField(this, "tracker");
10570
10579
  __publicField(this, "state", walletsModalState());
10571
10580
  this.connector = options.connector;
10581
+ this.tracker = options.tracker;
10572
10582
  this.setConnectRequestParametersCallback = options.setConnectRequestParametersCallback;
10573
10583
  createEffect(() => {
10574
10584
  const state = walletsModalState();
@@ -10578,6 +10588,7 @@ class WalletsModalManager {
10578
10588
  }
10579
10589
  open() {
10580
10590
  return __async(this, null, function* () {
10591
+ this.tracker.trackConnectionStarted();
10581
10592
  const walletsList = yield this.connector.getWallets();
10582
10593
  const embeddedWallet = walletsList.find(isWalletInfoCurrentlyEmbedded);
10583
10594
  if (embeddedWallet) {
@@ -10587,8 +10598,11 @@ class WalletsModalManager {
10587
10598
  }
10588
10599
  });
10589
10600
  }
10590
- close() {
10591
- widgetController.closeWalletsModal("action-cancelled");
10601
+ close(reason = "action-cancelled") {
10602
+ if (reason === "action-cancelled") {
10603
+ this.tracker.trackConnectionError("Connection was cancelled");
10604
+ }
10605
+ widgetController.closeWalletsModal(reason);
10592
10606
  }
10593
10607
  onStateChange(onChange) {
10594
10608
  this.consumers.push(onChange);
@@ -10648,8 +10662,10 @@ class SingleWalletModalManager {
10648
10662
  __publicField(this, "connector");
10649
10663
  __publicField(this, "setConnectRequestParametersCallback");
10650
10664
  __publicField(this, "consumers", []);
10665
+ __publicField(this, "tracker");
10651
10666
  __publicField(this, "state", singleWalletModalState());
10652
10667
  this.connector = options.connector;
10668
+ this.tracker = options.tracker;
10653
10669
  this.setConnectRequestParametersCallback = options.setConnectRequestParametersCallback;
10654
10670
  createEffect(() => {
10655
10671
  const state = singleWalletModalState();
@@ -10659,6 +10675,7 @@ class SingleWalletModalManager {
10659
10675
  }
10660
10676
  open(wallet) {
10661
10677
  return __async(this, null, function* () {
10678
+ this.tracker.trackConnectionStarted();
10662
10679
  const fetchedWalletsList = yield this.connector.getWallets();
10663
10680
  const walletsList = applyWalletsListConfiguration(
10664
10681
  fetchedWalletsList,
@@ -10675,10 +10692,15 @@ class SingleWalletModalManager {
10675
10692
  if (isExternalWalletExist) {
10676
10693
  return this.openSingleWalletModal(externalWallet);
10677
10694
  }
10678
- throw new TonConnectUIError(`Trying to open modal window with unknown wallet "${wallet}".`);
10695
+ const error = `Trying to open modal window with unknown wallet "${wallet}".`;
10696
+ this.tracker.trackConnectionError(error);
10697
+ throw new TonConnectUIError(error);
10679
10698
  });
10680
10699
  }
10681
- close() {
10700
+ close(reason = "action-cancelled") {
10701
+ if (reason === "action-cancelled") {
10702
+ this.tracker.trackConnectionError("Connection was cancelled");
10703
+ }
10682
10704
  widgetController.closeSingleWalletModal("action-cancelled");
10683
10705
  }
10684
10706
  onStateChange(onChange) {
@@ -10717,10 +10739,96 @@ class SingleWalletModalManager {
10717
10739
  });
10718
10740
  }
10719
10741
  }
10742
+ class TonConnectUITracker {
10743
+ constructor(eventDispatcher) {
10744
+ __publicField(this, "eventPrefix", "ton-connect-ui-");
10745
+ __publicField(this, "eventDispatcher");
10746
+ this.eventDispatcher = eventDispatcher != null ? eventDispatcher : new BrowserEventDispatcher();
10747
+ }
10748
+ dispatchUserActionEvent(eventDetails) {
10749
+ var _a2;
10750
+ try {
10751
+ const eventName = `${this.eventPrefix}${eventDetails.type}`;
10752
+ (_a2 = this.eventDispatcher) == null ? void 0 : _a2.dispatchEvent(eventName, eventDetails).catch();
10753
+ } catch (e2) {
10754
+ }
10755
+ }
10756
+ trackConnectionStarted(...args) {
10757
+ try {
10758
+ const event = createConnectionStartedEvent(...args);
10759
+ this.dispatchUserActionEvent(event);
10760
+ } catch (e2) {
10761
+ }
10762
+ }
10763
+ trackConnectionCompleted(...args) {
10764
+ try {
10765
+ const event = createConnectionCompletedEvent(...args);
10766
+ this.dispatchUserActionEvent(event);
10767
+ } catch (e2) {
10768
+ }
10769
+ }
10770
+ trackConnectionError(...args) {
10771
+ try {
10772
+ const event = createConnectionErrorEvent(...args);
10773
+ this.dispatchUserActionEvent(event);
10774
+ } catch (e2) {
10775
+ }
10776
+ }
10777
+ trackConnectionRestoringStarted(...args) {
10778
+ try {
10779
+ const event = createConnectionRestoringStartedEvent(...args);
10780
+ this.dispatchUserActionEvent(event);
10781
+ } catch (e2) {
10782
+ }
10783
+ }
10784
+ trackConnectionRestoringCompleted(...args) {
10785
+ try {
10786
+ const event = createConnectionRestoringCompletedEvent(...args);
10787
+ this.dispatchUserActionEvent(event);
10788
+ } catch (e2) {
10789
+ }
10790
+ }
10791
+ trackConnectionRestoringError(...args) {
10792
+ try {
10793
+ const event = createConnectionRestoringErrorEvent(...args);
10794
+ this.dispatchUserActionEvent(event);
10795
+ } catch (e2) {
10796
+ }
10797
+ }
10798
+ trackDisconnection(...args) {
10799
+ try {
10800
+ const event = createDisconnectionEvent(...args);
10801
+ this.dispatchUserActionEvent(event);
10802
+ } catch (e2) {
10803
+ }
10804
+ }
10805
+ trackTransactionSentForSignature(...args) {
10806
+ try {
10807
+ const event = createTransactionSentForSignatureEvent(...args);
10808
+ this.dispatchUserActionEvent(event);
10809
+ } catch (e2) {
10810
+ }
10811
+ }
10812
+ trackTransactionSigned(...args) {
10813
+ try {
10814
+ const event = createTransactionSignedEvent(...args);
10815
+ this.dispatchUserActionEvent(event);
10816
+ } catch (e2) {
10817
+ }
10818
+ }
10819
+ trackTransactionSigningFailed(...args) {
10820
+ try {
10821
+ const event = createTransactionSigningFailedEvent(...args);
10822
+ this.dispatchUserActionEvent(event);
10823
+ } catch (e2) {
10824
+ }
10825
+ }
10826
+ }
10720
10827
  class TonConnectUI {
10721
10828
  constructor(options) {
10722
10829
  __publicField(this, "walletInfoStorage", new WalletInfoStorage());
10723
10830
  __publicField(this, "preferredWalletStorage", new PreferredWalletStorage());
10831
+ __publicField(this, "tracker");
10724
10832
  __publicField(this, "walletInfo", null);
10725
10833
  __publicField(this, "systemThemeChangeUnsubscribe", null);
10726
10834
  __publicField(this, "actionsConfiguration");
@@ -10734,20 +10842,26 @@ class TonConnectUI {
10734
10842
  if (options && "connector" in options && options.connector) {
10735
10843
  this.connector = options.connector;
10736
10844
  } else if (options && "manifestUrl" in options && options.manifestUrl) {
10737
- this.connector = new TonConnect({ manifestUrl: options.manifestUrl });
10845
+ this.connector = new TonConnect({
10846
+ manifestUrl: options.manifestUrl,
10847
+ eventDispatcher: options == null ? void 0 : options.eventDispatcher
10848
+ });
10738
10849
  } else {
10739
10850
  throw new TonConnectUIError(
10740
10851
  "You have to specify a `manifestUrl` or a `connector` in the options."
10741
10852
  );
10742
10853
  }
10854
+ this.tracker = new TonConnectUITracker(options == null ? void 0 : options.eventDispatcher);
10743
10855
  this.modal = new WalletsModalManager({
10744
10856
  connector: this.connector,
10857
+ tracker: this.tracker,
10745
10858
  setConnectRequestParametersCallback: (callback) => {
10746
10859
  this.connectRequestParametersCallback = callback;
10747
10860
  }
10748
10861
  });
10749
10862
  this.singleWalletModal = new SingleWalletModalManager({
10750
10863
  connector: this.connector,
10864
+ tracker: this.tracker,
10751
10865
  setConnectRequestParametersCallback: (callback) => {
10752
10866
  this.connectRequestParametersCallback = callback;
10753
10867
  }
@@ -10760,10 +10874,14 @@ class TonConnectUI {
10760
10874
  const rootId = this.normalizeWidgetRoot(options == null ? void 0 : options.widgetRootId);
10761
10875
  this.subscribeToWalletChange();
10762
10876
  if ((options == null ? void 0 : options.restoreConnection) !== false) {
10877
+ this.tracker.trackConnectionRestoringStarted();
10763
10878
  this.connectionRestored = new Promise((resolve) => __async(this, null, function* () {
10764
10879
  yield this.connector.restoreConnection();
10765
10880
  if (!this.connector.connected) {
10881
+ this.tracker.trackConnectionRestoringError("Connection was not restored");
10766
10882
  this.walletInfoStorage.removeWalletInfo();
10883
+ } else {
10884
+ this.tracker.trackConnectionRestoringCompleted(this.wallet);
10767
10885
  }
10768
10886
  resolve(this.connector.connected);
10769
10887
  }));
@@ -10861,8 +10979,8 @@ class TonConnectUI {
10861
10979
  return this.modal.open();
10862
10980
  });
10863
10981
  }
10864
- closeModal() {
10865
- this.modal.close();
10982
+ closeModal(reason) {
10983
+ this.modal.close(reason);
10866
10984
  }
10867
10985
  onModalStateChange(onChange) {
10868
10986
  return this.modal.onStateChange(onChange);
@@ -10875,8 +10993,8 @@ class TonConnectUI {
10875
10993
  return this.singleWalletModal.open(wallet);
10876
10994
  });
10877
10995
  }
10878
- closeSingleWalletModal() {
10879
- this.singleWalletModal.close();
10996
+ closeSingleWalletModal(closeReason) {
10997
+ this.singleWalletModal.close(closeReason);
10880
10998
  }
10881
10999
  onSingleWalletModalStateChange(onChange) {
10882
11000
  return this.singleWalletModal.onStateChange(onChange);
@@ -10896,6 +11014,7 @@ class TonConnectUI {
10896
11014
  });
10897
11015
  }
10898
11016
  disconnect() {
11017
+ this.tracker.trackDisconnection(this.wallet, "dapp");
10899
11018
  widgetController.clearAction();
10900
11019
  widgetController.removeSelectedWalletInfo();
10901
11020
  this.walletInfoStorage.removeWalletInfo();
@@ -10903,7 +11022,9 @@ class TonConnectUI {
10903
11022
  }
10904
11023
  sendTransaction(tx, options) {
10905
11024
  return __async(this, null, function* () {
11025
+ this.tracker.trackTransactionSentForSignature(this.wallet, tx);
10906
11026
  if (!this.connected) {
11027
+ this.tracker.trackTransactionSigningFailed(this.wallet, tx, "Wallet was not connected");
10907
11028
  throw new TonConnectUIError("Connect wallet to send a transaction.");
10908
11029
  }
10909
11030
  if (isInTMA()) {
@@ -10965,6 +11086,7 @@ class TonConnectUI {
10965
11086
  },
10966
11087
  onRequestSent
10967
11088
  );
11089
+ this.tracker.trackTransactionSigned(this.wallet, tx, result);
10968
11090
  widgetController.setAction({
10969
11091
  name: "transaction-sent",
10970
11092
  showNotification: notifications2.includes("success"),
@@ -10972,6 +11094,7 @@ class TonConnectUI {
10972
11094
  });
10973
11095
  return result;
10974
11096
  } catch (e2) {
11097
+ this.tracker.trackTransactionSigningFailed(this.wallet, tx, e2.message);
10975
11098
  widgetController.setAction({
10976
11099
  name: "transaction-canceled",
10977
11100
  showNotification: notifications2.includes("error"),
@@ -11028,23 +11151,28 @@ class TonConnectUI {
11028
11151
  waitForWalletConnection(options) {
11029
11152
  return __async(this, null, function* () {
11030
11153
  return new Promise((resolve, reject) => {
11154
+ this.tracker.trackConnectionStarted();
11031
11155
  const { ignoreErrors = false, signal = null } = options;
11032
11156
  if (signal && signal.aborted) {
11157
+ this.tracker.trackConnectionError("Connection was cancelled");
11033
11158
  return reject(new TonConnectUIError("Wallet was not connected"));
11034
11159
  }
11035
11160
  const onStatusChangeHandler = (wallet) => __async(this, null, function* () {
11036
11161
  if (!wallet) {
11162
+ this.tracker.trackConnectionError("Connection was cancelled");
11037
11163
  if (ignoreErrors) {
11038
11164
  return;
11039
11165
  }
11040
11166
  unsubscribe();
11041
11167
  reject(new TonConnectUIError("Wallet was not connected"));
11042
11168
  } else {
11169
+ this.tracker.trackConnectionCompleted(wallet);
11043
11170
  unsubscribe();
11044
11171
  resolve(wallet);
11045
11172
  }
11046
11173
  });
11047
11174
  const onErrorsHandler = (reason) => {
11175
+ this.tracker.trackConnectionError(reason.message);
11048
11176
  if (ignoreErrors) {
11049
11177
  return;
11050
11178
  }