@tonconnect/ui 0.0.7 → 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/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;
@@ -10062,8 +10086,64 @@ const LoaderContainerStyled = styled.div`
10062
10086
  `;
10063
10087
  const [appState, setAppState] = createStore({
10064
10088
  buttonRootId: null,
10065
- language: "en"
10089
+ language: "en",
10090
+ buttonConfiguration: {},
10091
+ widgetConfiguration: {}
10066
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
+ }
10067
10147
  const WalletsModal = () => {
10068
10148
  const {
10069
10149
  locale
@@ -10071,8 +10151,14 @@ const WalletsModal = () => {
10071
10151
  createEffect(() => locale(appState.language));
10072
10152
  const connector = useContext(ConnectorContext);
10073
10153
  const tonConnectUI = useContext(TonConnectUiContext);
10074
- const [walletsList] = createResource(() => tonConnectUI.getWallets());
10154
+ const [fetchedWalletsList] = createResource(() => tonConnectUI.getWallets());
10075
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
+ });
10076
10162
  const onClose = () => {
10077
10163
  setWalletsModalOpen(false);
10078
10164
  setSelectedWalletInfo(null);
@@ -10085,7 +10171,11 @@ const WalletsModal = () => {
10085
10171
  if (isWalletInfoInjected(walletInfo) && walletInfo.injected) {
10086
10172
  return onSelectIfInjected(walletInfo);
10087
10173
  }
10088
- setSelectedWalletInfo(walletInfo);
10174
+ if ("bridgeUrl" in walletInfo) {
10175
+ setSelectedWalletInfo(walletInfo);
10176
+ return;
10177
+ }
10178
+ openLink(walletInfo.aboutUrl, "_blank");
10089
10179
  };
10090
10180
  const onSelectIfMobile = (walletInfo) => {
10091
10181
  const universalLink = connector.connect({
@@ -10115,7 +10205,7 @@ const WalletsModal = () => {
10115
10205
  get children() {
10116
10206
  return [createComponent(Show, {
10117
10207
  get when() {
10118
- return walletsList.state !== "ready";
10208
+ return !walletsList();
10119
10209
  },
10120
10210
  get children() {
10121
10211
  return [createComponent(H1Styled$1, {
@@ -10131,7 +10221,7 @@ const WalletsModal = () => {
10131
10221
  }
10132
10222
  }), createComponent(Show, {
10133
10223
  get when() {
10134
- return walletsList.state === "ready";
10224
+ return walletsList();
10135
10225
  },
10136
10226
  get children() {
10137
10227
  return [createComponent(Show, {
@@ -10361,12 +10451,6 @@ const widgetController = {
10361
10451
  tonConnectUI
10362
10452
  }), document.getElementById(root))
10363
10453
  };
10364
- class TonConnectUIError extends TonConnectError {
10365
- constructor(...args) {
10366
- super(...args);
10367
- Object.setPrototypeOf(this, TonConnectUIError.prototype);
10368
- }
10369
- }
10370
10454
  class WalletInfoStorage {
10371
10455
  constructor() {
10372
10456
  __publicField(this, "localStorage");
@@ -10531,7 +10615,10 @@ class TonConnectUI {
10531
10615
  if (options && "connector" in options && options.connector) {
10532
10616
  this.connector = options.connector;
10533
10617
  } else if (options && "manifestUrl" in options && options.manifestUrl) {
10534
- this.connector = new TonConnect({ manifestUrl: options.manifestUrl });
10618
+ this.connector = new TonConnect({
10619
+ manifestUrl: options.manifestUrl,
10620
+ walletsListSource: options.walletsListSource
10621
+ });
10535
10622
  } else {
10536
10623
  throw new TonConnectUIError(
10537
10624
  "You have to specify a `manifestUrl` or a `connector` in the options."
@@ -10541,7 +10628,11 @@ class TonConnectUI {
10541
10628
  const rootId = this.normalizeWidgetRoot(options == null ? void 0 : options.widgetRootId);
10542
10629
  this.subscribeToWalletChange();
10543
10630
  if ((options == null ? void 0 : options.restoreConnection) !== false) {
10544
- this.connector.restoreConnection();
10631
+ this.connector.restoreConnection().then(() => {
10632
+ if (!this.connector.connected) {
10633
+ this.walletInfoStorage.removeWalletInfo();
10634
+ }
10635
+ });
10545
10636
  }
10546
10637
  this.uiOptions = options || {};
10547
10638
  setAppState({ connector: this.connector });
@@ -10580,11 +10671,11 @@ class TonConnectUI {
10580
10671
  }
10581
10672
  setAppState((state) => {
10582
10673
  const merged = mergeOptions(
10583
- {
10584
- language: options.language,
10585
- buttonConfiguration: options.buttonConfiguration,
10674
+ __spreadValues(__spreadValues(__spreadValues({}, options.language && { language: options.language }), options.buttonConfiguration && {
10675
+ buttonConfiguration: options.buttonConfiguration
10676
+ }), options.widgetConfiguration && {
10586
10677
  widgetConfiguration: options.widgetConfiguration
10587
- },
10678
+ }),
10588
10679
  unwrap(state)
10589
10680
  );
10590
10681
  if (options.buttonRootId !== void 0) {