@tonconnect/ui 0.0.6 → 0.0.8

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/README.md CHANGED
@@ -32,8 +32,10 @@ const tonConnectUI = new TonConnectUI({
32
32
  ```
33
33
 
34
34
  See all available options:
35
- [TonConnectUiOptionsWithManifest](https://ton-connect.github.io/sdk/docs/interfaces/_tonconnect_ui.TonConnectUiOptionsWithManifest.html)
36
- [TonConnectUiOptionsWithConnector](https://ton-connect.github.io/sdk/docs/interfaces/_tonconnect_ui.TonConnectUiOptionsWithConnector.html)
35
+
36
+ [TonConnectUiOptionsWithManifest](https://ton-connect.github.io/sdk/interfaces/_tonconnect_ui.TonConnectUiOptionsWithManifest.html)
37
+
38
+ [TonConnectUiOptionsWithConnector](https://ton-connect.github.io/sdk/interfaces/_tonconnect_ui.TonConnectUiOptionsWithConnector.html)
37
39
 
38
40
  ## Change options if needed
39
41
  ```ts
@@ -51,7 +53,7 @@ DON'T do this:
51
53
  tonConnectUI.uiOptions.language = 'ru'; // WRONG, WILL NOT WORK
52
54
  ```
53
55
 
54
- [See all available options](https://ton-connect.github.io/sdk/docs/interfaces/_tonconnect_ui.TonConnectUiOptions.html)
56
+ [See all available options](https://ton-connect.github.io/sdk/interfaces/_tonconnect_ui.TonConnectUiOptions.html)
55
57
 
56
58
  ## Fetch wallets list
57
59
  ```ts
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { WalletConnectionSource, ITonConnect, WalletInfo, Account, Wallet, TonConnectError, SendTransactionRequest, SendTransactionResponse } from '@tonconnect/sdk';
1
+ import { WalletInfoBase, WalletInfoInjected, WalletInfoRemote, ITonConnect, WalletInfo, Account, Wallet, TonConnectError, SendTransactionRequest, SendTransactionResponse } from '@tonconnect/sdk';
2
2
  import { Property } from 'csstype';
3
3
 
4
4
  declare enum THEME {
@@ -21,24 +21,40 @@ interface ButtonConfiguration extends Partial<Themed> {
21
21
  appearance: ButtonAppearance;
22
22
  }
23
23
 
24
- interface UiWallet {
25
- name: string;
26
- iconUrl: string;
27
- connectionSource: WalletConnectionSource;
28
- }
24
+ declare type UIWallet = WalletInfoBase & (Omit<WalletInfoInjected, 'injected' | 'embedded'> | WalletInfoRemote);
29
25
 
30
26
  declare type WalletsListConfiguration = WalletsListConfigurationExplicit | WalletsListConfigurationImplicit;
27
+ /**
28
+ * Configure whole list of wallets in the modal. Only passed wallets will be displayed.
29
+ */
31
30
  declare type WalletsListConfigurationExplicit = {
32
- wallets: (string | UiWallet)[];
31
+ /**
32
+ * Allows to configure wallets order and add custom wallets. Must be an array of wallets names from WalletsList or custom wallets.
33
+ */
34
+ wallets: (string | UIWallet)[];
33
35
  };
36
+ /**
37
+ * Add corrections to the default wallets list in the modal: exclude some wallets and add custom wallets.
38
+ */
34
39
  declare type WalletsListConfigurationImplicit = {
40
+ /**
41
+ * Allows to exclude wallets from wallets list in the modal by its names. Must be an array of wallet's names from WalletsList.
42
+ */
35
43
  excludeWallets?: string[];
36
- includeWallets?: UiWallet[];
44
+ /**
45
+ * Allows to include extra wallets to the wallets list in the modal.
46
+ */
47
+ includeWallets?: UIWallet[];
48
+ /**
49
+ * Allows to specify order of the extra wallets in the wallets list in the modal. Cannot be applied if `includeWallets` is not specified.
50
+ * @default 'end'.
51
+ */
52
+ includeWalletsOrder?: 'start' | 'end';
37
53
  };
38
54
 
39
55
  declare type ModalSize = 'm' | 'l';
40
56
  interface WidgetConfiguration extends Partial<Themed> {
41
- size: ModalSize;
57
+ size?: ModalSize;
42
58
  wallets?: WalletsListConfiguration;
43
59
  }
44
60
 
@@ -74,7 +90,11 @@ interface TonConnectUiOptions {
74
90
  /**
75
91
  * Configuration for the wallet connect modal and action modals.
76
92
  */
77
- widgetConfiguration?: Partial<WidgetConfiguration>;
93
+ widgetConfiguration?: WidgetConfiguration;
94
+ /**
95
+ * @deprecated Don't use it
96
+ */
97
+ walletsListSource?: string;
78
98
  }
79
99
 
80
100
  declare type TonConnectUiCreateOptions = TonConnectUiOptionsWithConnector | TonConnectUiOptionsWithManifest;
package/lib/index.js CHANGED
@@ -3241,7 +3241,8 @@ var __awaiter$3 = globalThis && globalThis.__awaiter || function(thisArg, _argum
3241
3241
  });
3242
3242
  };
3243
3243
  class InjectedProvider {
3244
- constructor(injectedWalletKey) {
3244
+ constructor(storage, injectedWalletKey) {
3245
+ this.injectedWalletKey = injectedWalletKey;
3245
3246
  this.type = "injected";
3246
3247
  this.unsubscribeCallback = null;
3247
3248
  this.listenSubscriptions = false;
@@ -3250,13 +3251,14 @@ class InjectedProvider {
3250
3251
  if (!InjectedProvider.isWindowContainsWallet(window2, injectedWalletKey)) {
3251
3252
  throw new WalletNotInjectedError();
3252
3253
  }
3254
+ this.connectionStorage = new BridgeConnectionStorage(storage);
3253
3255
  this.injectedWallet = window2[injectedWalletKey].tonconnect;
3254
3256
  }
3255
3257
  static fromStorage(storage) {
3256
3258
  return __awaiter$3(this, void 0, void 0, function* () {
3257
3259
  const bridgeConnectionStorage = new BridgeConnectionStorage(storage);
3258
3260
  const connection = yield bridgeConnectionStorage.getInjectedConnection();
3259
- return new InjectedProvider(connection.jsBridgeKey);
3261
+ return new InjectedProvider(storage, connection.jsBridgeKey);
3260
3262
  });
3261
3263
  }
3262
3264
  static isWalletInjected(injectedWalletKey) {
@@ -3271,23 +3273,8 @@ class InjectedProvider {
3271
3273
  static isWindowContainsWallet(window2, injectedWalletKey) {
3272
3274
  return !!window2 && injectedWalletKey in window2 && typeof window2[injectedWalletKey] === "object" && "tonconnect" in window2[injectedWalletKey];
3273
3275
  }
3274
- connect(message, auto = false) {
3275
- this.injectedWallet.connect(PROTOCOL_VERSION, message, auto).then((connectEvent) => {
3276
- if (connectEvent.event === "connect") {
3277
- this.makeSubscriptions();
3278
- this.listenSubscriptions = true;
3279
- }
3280
- this.listeners.forEach((listener) => listener(connectEvent));
3281
- }).catch((e2) => {
3282
- const connectEventError = {
3283
- event: "connect_error",
3284
- payload: {
3285
- code: 0,
3286
- message: e2 === null || e2 === void 0 ? void 0 : e2.toString()
3287
- }
3288
- };
3289
- this.listeners.forEach((listener) => listener(connectEventError));
3290
- });
3276
+ connect(message) {
3277
+ this._connect(PROTOCOL_VERSION, message);
3291
3278
  }
3292
3279
  restoreConnection() {
3293
3280
  return __awaiter$3(this, void 0, void 0, function* () {
@@ -3295,10 +3282,12 @@ class InjectedProvider {
3295
3282
  const connectEvent = yield this.injectedWallet.restoreConnection();
3296
3283
  if (connectEvent.event === "connect") {
3297
3284
  this.makeSubscriptions();
3298
- this.listenSubscriptions = true;
3299
3285
  this.listeners.forEach((listener) => listener(connectEvent));
3286
+ } else {
3287
+ yield this.connectionStorage.removeConnection();
3300
3288
  }
3301
3289
  } catch (e2) {
3290
+ yield this.connectionStorage.removeConnection();
3302
3291
  console.error(e2);
3303
3292
  }
3304
3293
  });
@@ -3312,7 +3301,7 @@ class InjectedProvider {
3312
3301
  disconnect() {
3313
3302
  this.closeAllListeners();
3314
3303
  this.injectedWallet.disconnect();
3315
- return Promise.resolve();
3304
+ return this.connectionStorage.removeConnection();
3316
3305
  }
3317
3306
  closeAllListeners() {
3318
3307
  var _a;
@@ -3329,7 +3318,30 @@ class InjectedProvider {
3329
3318
  return this.injectedWallet.send(Object.assign(Object.assign({}, request), { id: "0" }));
3330
3319
  });
3331
3320
  }
3321
+ _connect(protocolVersion, message) {
3322
+ return __awaiter$3(this, void 0, void 0, function* () {
3323
+ try {
3324
+ const connectEvent = yield this.injectedWallet.connect(protocolVersion, message);
3325
+ if (connectEvent.event === "connect") {
3326
+ yield this.updateSession();
3327
+ this.makeSubscriptions();
3328
+ }
3329
+ this.listeners.forEach((listener) => listener(connectEvent));
3330
+ } catch (e2) {
3331
+ console.debug(e2);
3332
+ const connectEventError = {
3333
+ event: "connect_error",
3334
+ payload: {
3335
+ code: 0,
3336
+ message: e2 === null || e2 === void 0 ? void 0 : e2.toString()
3337
+ }
3338
+ };
3339
+ this.listeners.forEach((listener) => listener(connectEventError));
3340
+ }
3341
+ });
3342
+ }
3332
3343
  makeSubscriptions() {
3344
+ this.listenSubscriptions = true;
3333
3345
  this.unsubscribeCallback = this.injectedWallet.listen((e2) => {
3334
3346
  if (this.listenSubscriptions) {
3335
3347
  this.listeners.forEach((listener) => listener(e2));
@@ -3339,6 +3351,12 @@ class InjectedProvider {
3339
3351
  }
3340
3352
  });
3341
3353
  }
3354
+ updateSession() {
3355
+ return this.connectionStorage.storeConnection({
3356
+ type: "injected",
3357
+ jsBridgeKey: this.injectedWalletKey
3358
+ });
3359
+ }
3342
3360
  }
3343
3361
  InjectedProvider.window = getWindow$1();
3344
3362
  var __awaiter$2 = globalThis && globalThis.__awaiter || function(thisArg, _arguments, P2, generator) {
@@ -3423,9 +3441,12 @@ var __awaiter$1 = globalThis && globalThis.__awaiter || function(thisArg, _argum
3423
3441
  });
3424
3442
  };
3425
3443
  class WalletsListManager {
3426
- constructor() {
3444
+ constructor(walletsListSource) {
3427
3445
  this.walletsListCache = null;
3428
3446
  this.walletsListSource = "https://raw.githubusercontent.com/ton-connect/wallets-list/main/wallets.json";
3447
+ if (walletsListSource) {
3448
+ this.walletsListSource = walletsListSource;
3449
+ }
3429
3450
  }
3430
3451
  getWallets() {
3431
3452
  return __awaiter$1(this, void 0, void 0, function* () {
@@ -3439,11 +3460,11 @@ class WalletsListManager {
3439
3460
  getEmbeddedWallet() {
3440
3461
  return __awaiter$1(this, void 0, void 0, function* () {
3441
3462
  const walletsList = yield this.getWallets();
3442
- const injectedWallets = walletsList.filter(isWalletInfoInjected);
3443
- if (injectedWallets.length !== 1) {
3463
+ const embeddedWallets = walletsList.filter((item) => isWalletInfoInjected(item) && item.embedded);
3464
+ if (embeddedWallets.length !== 1) {
3444
3465
  return null;
3445
3466
  }
3446
- return injectedWallets[0].embedded ? injectedWallets[0] : null;
3467
+ return embeddedWallets[0];
3447
3468
  });
3448
3469
  }
3449
3470
  fetchWalletsList() {
@@ -3566,6 +3587,7 @@ class TonConnect {
3566
3587
  manifestUrl: (options === null || options === void 0 ? void 0 : options.manifestUrl) || getWebPageManifest(),
3567
3588
  storage: (options === null || options === void 0 ? void 0 : options.storage) || new DefaultStorage()
3568
3589
  };
3590
+ this.walletsList = new WalletsListManager(options === null || options === void 0 ? void 0 : options.walletsListSource);
3569
3591
  if (!this.dappSettings.manifestUrl) {
3570
3592
  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");
3571
3593
  }
@@ -3660,7 +3682,7 @@ class TonConnect {
3660
3682
  createProvider(wallet) {
3661
3683
  let provider;
3662
3684
  if (isWalletConnectionSourceJS(wallet)) {
3663
- provider = new InjectedProvider(wallet.jsBridgeKey);
3685
+ provider = new InjectedProvider(this.dappSettings.storage, wallet.jsBridgeKey);
3664
3686
  } else {
3665
3687
  provider = new BridgeProvider(this.dappSettings.storage, wallet);
3666
3688
  }
@@ -3743,6 +3765,8 @@ class TonConnect {
3743
3765
  }
3744
3766
  }
3745
3767
  TonConnect.walletsList = new WalletsListManager();
3768
+ TonConnect.isWalletInjected = (walletJSKey) => InjectedProvider.isWalletInjected(walletJSKey);
3769
+ TonConnect.isInsideWalletBrowser = (walletJSKey) => InjectedProvider.isInsideWalletBrowser(walletJSKey);
3746
3770
  function toUserFriendlyAddress(hexAddress) {
3747
3771
  const { wc, hex } = parseHexAddress(hexAddress);
3748
3772
  const bounceableTag = 17;
@@ -6799,7 +6823,6 @@ const AccountButtonDropdown = (props) => {
6799
6823
  const connector = useContext(ConnectorContext);
6800
6824
  const [isCopiedShown, setIsCopiedShown] = createSignal(false);
6801
6825
  const onCopy = () => __async(void 0, null, function* () {
6802
- console.log(tonConnectUi.account.address);
6803
6826
  const userFriendlyAddress = toUserFriendlyAddress(tonConnectUi.account.address);
6804
6827
  yield copyToClipboard(userFriendlyAddress);
6805
6828
  setIsCopiedShown(true);
@@ -10063,8 +10086,64 @@ const LoaderContainerStyled = styled.div`
10063
10086
  `;
10064
10087
  const [appState, setAppState] = createStore({
10065
10088
  buttonRootId: null,
10066
- language: "en"
10089
+ language: "en",
10090
+ buttonConfiguration: {},
10091
+ widgetConfiguration: {}
10067
10092
  });
10093
+ class TonConnectUIError extends TonConnectError {
10094
+ constructor(...args) {
10095
+ super(...args);
10096
+ Object.setPrototypeOf(this, TonConnectUIError.prototype);
10097
+ }
10098
+ }
10099
+ class WalletNotFoundError extends TonConnectUIError {
10100
+ constructor(...args) {
10101
+ super(...args);
10102
+ Object.setPrototypeOf(this, WalletNotFoundError.prototype);
10103
+ }
10104
+ }
10105
+ function uiWalletToWalletInfo(uiWallet) {
10106
+ if ("jsBridgeKey" in uiWallet) {
10107
+ return __spreadProps(__spreadValues({}, uiWallet), {
10108
+ injected: TonConnect.isWalletInjected(uiWallet.jsBridgeKey),
10109
+ embedded: TonConnect.isInsideWalletBrowser(uiWallet.jsBridgeKey)
10110
+ });
10111
+ }
10112
+ return uiWallet;
10113
+ }
10114
+ function applyWalletsListConfiguration(walletsList, configuration) {
10115
+ var _a;
10116
+ if (!configuration) {
10117
+ return walletsList;
10118
+ }
10119
+ if ("wallets" in configuration) {
10120
+ return configuration.wallets.map((wallet) => {
10121
+ if (typeof wallet === "string") {
10122
+ const walletInfo = walletsList.find((item) => item.name === wallet);
10123
+ if (!walletInfo) {
10124
+ throw new WalletNotFoundError(
10125
+ `Wallet with name === '${wallet}' wasn't found in the wallets list. Check ${wallet} correctness.`
10126
+ );
10127
+ }
10128
+ return walletInfo;
10129
+ }
10130
+ return uiWalletToWalletInfo(wallet);
10131
+ });
10132
+ }
10133
+ const filteredWalletsList = ((_a = configuration.excludeWallets) == null ? void 0 : _a.length) ? walletsList.filter(
10134
+ (wallet) => {
10135
+ var _a2;
10136
+ return (_a2 = configuration.excludeWallets) == null ? void 0 : _a2.every((item) => item !== wallet.name);
10137
+ }
10138
+ ) : walletsList;
10139
+ if (!configuration.includeWallets) {
10140
+ return filteredWalletsList;
10141
+ }
10142
+ if (configuration.includeWalletsOrder === "start") {
10143
+ return configuration.includeWallets.map(uiWalletToWalletInfo).concat(walletsList);
10144
+ }
10145
+ return walletsList.concat(configuration.includeWallets.map(uiWalletToWalletInfo));
10146
+ }
10068
10147
  const WalletsModal = () => {
10069
10148
  const {
10070
10149
  locale
@@ -10072,8 +10151,14 @@ const WalletsModal = () => {
10072
10151
  createEffect(() => locale(appState.language));
10073
10152
  const connector = useContext(ConnectorContext);
10074
10153
  const tonConnectUI = useContext(TonConnectUiContext);
10075
- const [walletsList] = createResource(() => tonConnectUI.getWallets());
10154
+ const [fetchedWalletsList] = createResource(() => tonConnectUI.getWallets());
10076
10155
  const [selectedWalletInfo, setSelectedWalletInfo] = createSignal(null);
10156
+ const walletsList = createMemo(() => {
10157
+ if (fetchedWalletsList.state !== "ready") {
10158
+ return null;
10159
+ }
10160
+ return applyWalletsListConfiguration(fetchedWalletsList(), appState.widgetConfiguration.wallets);
10161
+ });
10077
10162
  const onClose = () => {
10078
10163
  setWalletsModalOpen(false);
10079
10164
  setSelectedWalletInfo(null);
@@ -10086,7 +10171,11 @@ const WalletsModal = () => {
10086
10171
  if (isWalletInfoInjected(walletInfo) && walletInfo.injected) {
10087
10172
  return onSelectIfInjected(walletInfo);
10088
10173
  }
10089
- setSelectedWalletInfo(walletInfo);
10174
+ if ("bridgeUrl" in walletInfo) {
10175
+ setSelectedWalletInfo(walletInfo);
10176
+ return;
10177
+ }
10178
+ openLink(walletInfo.aboutUrl, "_blank");
10090
10179
  };
10091
10180
  const onSelectIfMobile = (walletInfo) => {
10092
10181
  const universalLink = connector.connect({
@@ -10116,7 +10205,7 @@ const WalletsModal = () => {
10116
10205
  get children() {
10117
10206
  return [createComponent(Show, {
10118
10207
  get when() {
10119
- return walletsList.state !== "ready";
10208
+ return !walletsList();
10120
10209
  },
10121
10210
  get children() {
10122
10211
  return [createComponent(H1Styled$1, {
@@ -10132,7 +10221,7 @@ const WalletsModal = () => {
10132
10221
  }
10133
10222
  }), createComponent(Show, {
10134
10223
  get when() {
10135
- return walletsList.state === "ready";
10224
+ return walletsList();
10136
10225
  },
10137
10226
  get children() {
10138
10227
  return [createComponent(Show, {
@@ -10362,12 +10451,6 @@ const widgetController = {
10362
10451
  tonConnectUI
10363
10452
  }), document.getElementById(root))
10364
10453
  };
10365
- class TonConnectUIError extends TonConnectError {
10366
- constructor(...args) {
10367
- super(...args);
10368
- Object.setPrototypeOf(this, TonConnectUIError.prototype);
10369
- }
10370
- }
10371
10454
  class WalletInfoStorage {
10372
10455
  constructor() {
10373
10456
  __publicField(this, "localStorage");
@@ -10532,7 +10615,10 @@ class TonConnectUI {
10532
10615
  if (options && "connector" in options && options.connector) {
10533
10616
  this.connector = options.connector;
10534
10617
  } else if (options && "manifestUrl" in options && options.manifestUrl) {
10535
- this.connector = new TonConnect({ manifestUrl: options.manifestUrl });
10618
+ this.connector = new TonConnect({
10619
+ manifestUrl: options.manifestUrl,
10620
+ walletsListSource: options.walletsListSource
10621
+ });
10536
10622
  } else {
10537
10623
  throw new TonConnectUIError(
10538
10624
  "You have to specify a `manifestUrl` or a `connector` in the options."
@@ -10542,7 +10628,11 @@ class TonConnectUI {
10542
10628
  const rootId = this.normalizeWidgetRoot(options == null ? void 0 : options.widgetRootId);
10543
10629
  this.subscribeToWalletChange();
10544
10630
  if ((options == null ? void 0 : options.restoreConnection) !== false) {
10545
- this.connector.restoreConnection();
10631
+ this.connector.restoreConnection().then(() => {
10632
+ if (!this.connector.connected) {
10633
+ this.walletInfoStorage.removeWalletInfo();
10634
+ }
10635
+ });
10546
10636
  }
10547
10637
  this.uiOptions = options || {};
10548
10638
  setAppState({ connector: this.connector });
@@ -10581,11 +10671,11 @@ class TonConnectUI {
10581
10671
  }
10582
10672
  setAppState((state) => {
10583
10673
  const merged = mergeOptions(
10584
- {
10585
- language: options.language,
10586
- buttonConfiguration: options.buttonConfiguration,
10674
+ __spreadValues(__spreadValues(__spreadValues({}, options.language && { language: options.language }), options.buttonConfiguration && {
10675
+ buttonConfiguration: options.buttonConfiguration
10676
+ }), options.widgetConfiguration && {
10587
10677
  widgetConfiguration: options.widgetConfiguration
10588
- },
10678
+ }),
10589
10679
  unwrap(state)
10590
10680
  );
10591
10681
  if (options.buttonRootId !== void 0) {
@@ -10673,6 +10763,8 @@ class TonConnectUI {
10673
10763
  console.error(e2);
10674
10764
  throw new TonConnectUIError("Unhandled error:" + e2);
10675
10765
  }
10766
+ } finally {
10767
+ widgetController.clearAction();
10676
10768
  }
10677
10769
  });
10678
10770
  }