@tonconnect/ui 2.0.0 → 2.0.1-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.d.ts CHANGED
@@ -264,6 +264,45 @@ declare type WalletsModalState = WalletModalOpened | WalletModalClosed;
264
264
  */
265
265
  declare type WalletsModalCloseReason = 'action-cancelled' | 'wallet-selected';
266
266
 
267
+ /**
268
+ * Opened modal window state.
269
+ */
270
+ declare type SingleWalletModalOpened = {
271
+ /**
272
+ * Modal window status.
273
+ */
274
+ status: 'opened';
275
+ /**
276
+ * Wallet info.
277
+ */
278
+ walletInfo: WalletInfoRemote;
279
+ /**
280
+ * Always `null` for opened modal window.
281
+ */
282
+ closeReason: null;
283
+ };
284
+ /**
285
+ * Closed modal window state.
286
+ */
287
+ declare type SingleWalletModalClosed = {
288
+ /**
289
+ * Modal window status.
290
+ */
291
+ status: 'closed';
292
+ /**
293
+ * Close reason, if the modal window was closed.
294
+ */
295
+ closeReason: SingleWalletModalCloseReason | null;
296
+ };
297
+ /**
298
+ * Modal window state.
299
+ */
300
+ declare type SingleWalletModalState = SingleWalletModalOpened | SingleWalletModalClosed;
301
+ /**
302
+ * Modal window close reason.
303
+ */
304
+ declare type SingleWalletModalCloseReason = 'action-cancelled' | 'wallet-selected';
305
+
267
306
  declare class TonConnectUI {
268
307
  static getWallets(): Promise<WalletInfo[]>;
269
308
  private readonly walletInfoStorage;
@@ -281,6 +320,11 @@ declare class TonConnectUI {
281
320
  * Manages the modal window state.
282
321
  */
283
322
  readonly modal: WalletsModal;
323
+ /**
324
+ * Manages the single wallet modal window state.
325
+ * TODO: make it public when interface will be ready for external usage.
326
+ */
327
+ private readonly singleWalletModal;
284
328
  /**
285
329
  * Manages the transaction modal window state.
286
330
  * TODO: make it public when interface will be ready for external usage.
@@ -341,6 +385,26 @@ declare class TonConnectUI {
341
385
  * Returns current modal window state.
342
386
  */
343
387
  get modalState(): WalletsModalState;
388
+ /**
389
+ * Opens the single wallet modal window, returns a promise that resolves after the modal window is opened.
390
+ * @experimental
391
+ */
392
+ openSingleWalletModal(wallet: string): Promise<void>;
393
+ /**
394
+ * Close the single wallet modal window.
395
+ * @experimental
396
+ */
397
+ closeSingleWalletModal(): void;
398
+ /**
399
+ * Subscribe to the single wallet modal window state changes, returns a function which has to be called to unsubscribe.
400
+ * @experimental
401
+ */
402
+ onSingleWalletModalStateChange(onChange: (state: SingleWalletModalState) => void): () => void;
403
+ /**
404
+ * Returns current single wallet modal window state.
405
+ * @experimental
406
+ */
407
+ get singleWalletModalState(): SingleWalletModalState;
344
408
  /**
345
409
  * @deprecated Use `tonConnectUI.openModal()` instead. Will be removed in the next major version.
346
410
  * Opens the modal window and handles a wallet connection.
package/lib/index.mjs CHANGED
@@ -1951,6 +1951,20 @@ const [walletsModalState, setWalletsModalState] = createSignal({
1951
1951
  closeReason: null
1952
1952
  });
1953
1953
  const getWalletsModalIsOpened = createMemo(() => walletsModalState().status === "opened");
1954
+ const [singleWalletModalState, setSingleWalletModalState] = createSignal({
1955
+ status: "closed",
1956
+ closeReason: null
1957
+ });
1958
+ const getSingleWalletModalIsOpened = createMemo(
1959
+ () => singleWalletModalState().status === "opened"
1960
+ );
1961
+ const getSingleWalletModalWalletInfo = createMemo(() => {
1962
+ const state = singleWalletModalState();
1963
+ if (state.status === "opened") {
1964
+ return state.walletInfo;
1965
+ }
1966
+ return null;
1967
+ });
1954
1968
  let lastSelectedWalletInfoStorage = typeof window !== "undefined" ? new LastSelectedWalletInfoStorage() : void 0;
1955
1969
  const [lastSelectedWalletInfo, _setLastSelectedWalletInfo] = createSignal((lastSelectedWalletInfoStorage == null ? void 0 : lastSelectedWalletInfoStorage.getLastSelectedWalletInfo()) || null);
1956
1970
  const setLastSelectedWalletInfo = (walletInfo) => {
@@ -8424,9 +8438,16 @@ const DesktopConnectionModal = (props) => {
8424
8438
  return createComponent(DesktopConnectionModalStyled, {
8425
8439
  "data-tc-wallets-modal-connection-desktop": "true",
8426
8440
  get children() {
8427
- return [createComponent(StyledIconButton$2, {
8428
- icon: "arrow",
8429
- onClick: () => props.onBackClick()
8441
+ return [createComponent(Show, {
8442
+ get when() {
8443
+ return !props.backDisabled;
8444
+ },
8445
+ get children() {
8446
+ return createComponent(StyledIconButton$2, {
8447
+ icon: "arrow",
8448
+ onClick: () => props.onBackClick()
8449
+ });
8450
+ }
8430
8451
  }), createComponent(H1Styled$6, {
8431
8452
  get children() {
8432
8453
  return props.wallet.name;
@@ -8964,7 +8985,22 @@ const MobileConnectionModal = (props) => {
8964
8985
  universalLink: props.wallet.universalLink,
8965
8986
  bridgeUrl: props.wallet.bridgeUrl
8966
8987
  }, props.additionalRequest));
8988
+ const onClickTelegram = () => {
8989
+ const alwaysForceRedirect = true;
8990
+ setLastSelectedWalletInfo(__spreadProps(__spreadValues({}, props.wallet), {
8991
+ openMethod: "universal-link"
8992
+ }));
8993
+ redirectToTelegram(universalLink(), {
8994
+ returnStrategy: appState.returnStrategy,
8995
+ twaReturnUrl: appState.twaReturnUrl,
8996
+ forceRedirect: alwaysForceRedirect
8997
+ });
8998
+ };
8967
8999
  const onRetry = () => {
9000
+ const currentUniversalLink = universalLink();
9001
+ if (isTelegramUrl(currentUniversalLink)) {
9002
+ return onClickTelegram();
9003
+ }
8968
9004
  setConnectionErrored(false);
8969
9005
  setLastSelectedWalletInfo(__spreadProps(__spreadValues({}, props.wallet), {
8970
9006
  openMethod: "universal-link"
@@ -8996,9 +9032,16 @@ const MobileConnectionModal = (props) => {
8996
9032
  return createComponent(MobileConnectionModalStyled, {
8997
9033
  "data-tc-wallets-modal-connection-mobile": "true",
8998
9034
  get children() {
8999
- return [createComponent(StyledIconButton, {
9000
- icon: "arrow",
9001
- onClick: onBack
9035
+ return [createComponent(Show, {
9036
+ get when() {
9037
+ return !props.backDisabled || showQR();
9038
+ },
9039
+ get children() {
9040
+ return createComponent(StyledIconButton, {
9041
+ icon: "arrow",
9042
+ onClick: onBack
9043
+ });
9044
+ }
9002
9045
  }), createComponent(Show, {
9003
9046
  get when() {
9004
9047
  return showQR();
@@ -10008,6 +10051,109 @@ const ActionsModal = () => {
10008
10051
  }
10009
10052
  });
10010
10053
  };
10054
+ const SingleWalletModal = () => {
10055
+ const {
10056
+ locale
10057
+ } = useI18n()[1];
10058
+ createEffect(() => locale(appState.language));
10059
+ createEffect(() => {
10060
+ if (getSingleWalletModalIsOpened()) {
10061
+ updateIsMobile();
10062
+ }
10063
+ });
10064
+ const connector = useContext(ConnectorContext);
10065
+ const [infoTab, setInfoTab] = createSignal(false);
10066
+ const additionalRequestLoading = () => {
10067
+ var _a2;
10068
+ return ((_a2 = appState.connectRequestParameters) == null ? void 0 : _a2.state) === "loading";
10069
+ };
10070
+ const additionalRequest = createMemo(() => {
10071
+ var _a2;
10072
+ if (additionalRequestLoading()) {
10073
+ return void 0;
10074
+ }
10075
+ return (_a2 = appState.connectRequestParameters) == null ? void 0 : _a2.value;
10076
+ });
10077
+ const onClose = (closeReason) => {
10078
+ setSingleWalletModalState({
10079
+ status: "closed",
10080
+ closeReason
10081
+ });
10082
+ setInfoTab(false);
10083
+ };
10084
+ const unsubscribe = connector.onStatusChange((wallet) => {
10085
+ if (wallet) {
10086
+ onClose("wallet-selected");
10087
+ }
10088
+ });
10089
+ onCleanup(unsubscribe);
10090
+ return createComponent(StyledModal, {
10091
+ get opened() {
10092
+ return getSingleWalletModalIsOpened();
10093
+ },
10094
+ get enableAndroidBackHandler() {
10095
+ return appState.enableAndroidBackHandler;
10096
+ },
10097
+ onClose: () => onClose("action-cancelled"),
10098
+ onClickQuestion: () => setInfoTab((v) => !v),
10099
+ "data-tc-wallets-modal-container": "true",
10100
+ get children() {
10101
+ return [createComponent(Show, {
10102
+ get when() {
10103
+ return infoTab();
10104
+ },
10105
+ get children() {
10106
+ return createComponent(InfoModal, {
10107
+ onBackClick: () => setInfoTab(false)
10108
+ });
10109
+ }
10110
+ }), createComponent(Show, {
10111
+ get when() {
10112
+ return !infoTab();
10113
+ },
10114
+ get children() {
10115
+ return [createComponent(Show, {
10116
+ get when() {
10117
+ return additionalRequestLoading();
10118
+ },
10119
+ get children() {
10120
+ return [createComponent(H1Styled$8, {
10121
+ translationKey: "walletModal.loading",
10122
+ children: "Wallets list is loading"
10123
+ }), createComponent(LoaderContainerStyled, {
10124
+ get children() {
10125
+ return createComponent(LoaderIcon, {
10126
+ size: "m"
10127
+ });
10128
+ }
10129
+ })];
10130
+ }
10131
+ }), createComponent(Show, {
10132
+ get when() {
10133
+ return !additionalRequestLoading();
10134
+ },
10135
+ get children() {
10136
+ return createComponent(Dynamic, {
10137
+ get component() {
10138
+ return isMobile() ? MobileConnectionModal : DesktopConnectionModal;
10139
+ },
10140
+ get wallet() {
10141
+ return getSingleWalletModalWalletInfo();
10142
+ },
10143
+ get additionalRequest() {
10144
+ return additionalRequest();
10145
+ },
10146
+ onBackClick: () => {
10147
+ },
10148
+ backDisabled: true
10149
+ });
10150
+ }
10151
+ })];
10152
+ }
10153
+ })];
10154
+ }
10155
+ });
10156
+ };
10011
10157
  const App = (props) => {
10012
10158
  const translations = createI18nContext(i18nDictionary, appState.language);
10013
10159
  defineStylesRoot();
@@ -10045,7 +10191,7 @@ const App = (props) => {
10045
10191
  }), createComponent(Dynamic, {
10046
10192
  component: globalStylesTag,
10047
10193
  get children() {
10048
- return [createComponent(WalletsModal, {}), createComponent(ActionsModal, {})];
10194
+ return [createComponent(WalletsModal, {}), createComponent(SingleWalletModal, {}), createComponent(ActionsModal, {})];
10049
10195
  }
10050
10196
  })];
10051
10197
  }
@@ -10066,6 +10212,17 @@ const widgetController = {
10066
10212
  status: "closed",
10067
10213
  closeReason: reason
10068
10214
  })),
10215
+ openSingleWalletModal: (walletInfo) => {
10216
+ void setTimeout(() => setSingleWalletModalState({
10217
+ status: "opened",
10218
+ closeReason: null,
10219
+ walletInfo
10220
+ }));
10221
+ },
10222
+ closeSingleWalletModal: (reason) => void setTimeout(() => setSingleWalletModalState({
10223
+ status: "closed",
10224
+ closeReason: reason
10225
+ })),
10069
10226
  setAction: (action2) => void setTimeout(() => setAction(action2)),
10070
10227
  clearAction: () => void setTimeout(() => setAction(null)),
10071
10228
  getSelectedWalletInfo: () => lastSelectedWalletInfo(),
@@ -10095,7 +10252,7 @@ class WalletsModalManager {
10095
10252
  if (embeddedWallet) {
10096
10253
  return this.connectEmbeddedWallet(embeddedWallet);
10097
10254
  } else {
10098
- return this.connectExternalWallet();
10255
+ return this.openWalletsModal();
10099
10256
  }
10100
10257
  });
10101
10258
  }
@@ -10120,7 +10277,7 @@ class WalletsModalManager {
10120
10277
  connect(additionalRequest == null ? void 0 : additionalRequest.value);
10121
10278
  }
10122
10279
  }
10123
- connectExternalWallet() {
10280
+ openWalletsModal() {
10124
10281
  return __async(this, null, function* () {
10125
10282
  if (isInTMA()) {
10126
10283
  sendExpand();
@@ -10155,6 +10312,80 @@ class TransactionModalManager {
10155
10312
  };
10156
10313
  }
10157
10314
  }
10315
+ class SingleWalletModalManager {
10316
+ constructor(options) {
10317
+ __publicField(this, "connector");
10318
+ __publicField(this, "setConnectRequestParametersCallback");
10319
+ __publicField(this, "consumers", []);
10320
+ __publicField(this, "state", singleWalletModalState());
10321
+ this.connector = options.connector;
10322
+ this.setConnectRequestParametersCallback = options.setConnectRequestParametersCallback;
10323
+ createEffect(() => {
10324
+ const state = singleWalletModalState();
10325
+ this.state = state;
10326
+ this.consumers.forEach((consumer) => consumer(state));
10327
+ });
10328
+ }
10329
+ open(wallet) {
10330
+ return __async(this, null, function* () {
10331
+ const fetchedWalletsList = yield this.connector.getWallets();
10332
+ const walletsList = applyWalletsListConfiguration(
10333
+ fetchedWalletsList,
10334
+ appState.walletsListConfiguration
10335
+ );
10336
+ const embeddedWallet = walletsList.find(isWalletInfoCurrentlyEmbedded);
10337
+ const isEmbeddedWalletExist = !!embeddedWallet;
10338
+ if (isEmbeddedWalletExist) {
10339
+ return this.connectEmbeddedWallet(embeddedWallet);
10340
+ }
10341
+ const externalWallets = walletsList.filter(isWalletInfoRemote);
10342
+ const externalWallet = externalWallets.find((walletInfo) => eqWalletName(walletInfo, wallet));
10343
+ const isExternalWalletExist = !!externalWallet;
10344
+ if (isExternalWalletExist) {
10345
+ return this.openSingleWalletModal(externalWallet);
10346
+ }
10347
+ throw new TonConnectUIError(`Trying to open modal window with unknown wallet "${wallet}".`);
10348
+ });
10349
+ }
10350
+ close() {
10351
+ widgetController.closeSingleWalletModal("action-cancelled");
10352
+ }
10353
+ onStateChange(onChange) {
10354
+ this.consumers.push(onChange);
10355
+ return () => {
10356
+ this.consumers = this.consumers.filter((consumer) => consumer !== onChange);
10357
+ };
10358
+ }
10359
+ connectEmbeddedWallet(embeddedWallet) {
10360
+ const connect = (parameters) => {
10361
+ setLastSelectedWalletInfo(embeddedWallet);
10362
+ this.connector.connect({ jsBridgeKey: embeddedWallet.jsBridgeKey }, parameters);
10363
+ };
10364
+ const additionalRequest = appState.connectRequestParameters;
10365
+ if ((additionalRequest == null ? void 0 : additionalRequest.state) === "loading") {
10366
+ this.setConnectRequestParametersCallback(connect);
10367
+ } else {
10368
+ connect(additionalRequest == null ? void 0 : additionalRequest.value);
10369
+ }
10370
+ }
10371
+ openSingleWalletModal(wallet) {
10372
+ return __async(this, null, function* () {
10373
+ if (isInTMA()) {
10374
+ sendExpand();
10375
+ }
10376
+ widgetController.openSingleWalletModal(wallet);
10377
+ return new Promise((resolve) => {
10378
+ const unsubscribe = this.onStateChange((state) => {
10379
+ const { status } = state;
10380
+ if (status === "opened") {
10381
+ unsubscribe();
10382
+ resolve();
10383
+ }
10384
+ });
10385
+ });
10386
+ });
10387
+ }
10388
+ }
10158
10389
  class TonConnectUI {
10159
10390
  constructor(options) {
10160
10391
  __publicField(this, "walletInfoStorage", new WalletInfoStorage());
@@ -10166,6 +10397,7 @@ class TonConnectUI {
10166
10397
  __publicField(this, "connectRequestParametersCallback");
10167
10398
  __publicField(this, "connector");
10168
10399
  __publicField(this, "modal");
10400
+ __publicField(this, "singleWalletModal");
10169
10401
  __publicField(this, "transactionModal");
10170
10402
  __publicField(this, "connectionRestored", Promise.resolve(false));
10171
10403
  if (options && "connector" in options && options.connector) {
@@ -10183,6 +10415,12 @@ class TonConnectUI {
10183
10415
  this.connectRequestParametersCallback = callback;
10184
10416
  }
10185
10417
  });
10418
+ this.singleWalletModal = new SingleWalletModalManager({
10419
+ connector: this.connector,
10420
+ setConnectRequestParametersCallback: (callback) => {
10421
+ this.connectRequestParametersCallback = callback;
10422
+ }
10423
+ });
10186
10424
  this.transactionModal = new TransactionModalManager({
10187
10425
  connector: this.connector
10188
10426
  });
@@ -10301,6 +10539,20 @@ class TonConnectUI {
10301
10539
  get modalState() {
10302
10540
  return this.modal.state;
10303
10541
  }
10542
+ openSingleWalletModal(wallet) {
10543
+ return __async(this, null, function* () {
10544
+ return this.singleWalletModal.open(wallet);
10545
+ });
10546
+ }
10547
+ closeSingleWalletModal() {
10548
+ this.singleWalletModal.close();
10549
+ }
10550
+ onSingleWalletModalStateChange(onChange) {
10551
+ return this.singleWalletModal.onStateChange(onChange);
10552
+ }
10553
+ get singleWalletModalState() {
10554
+ return this.singleWalletModal.state;
10555
+ }
10304
10556
  connectWallet() {
10305
10557
  return __async(this, null, function* () {
10306
10558
  const walletsList = yield this.getWallets();