@tonconnect/sdk 2.1.4 → 3.0.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/esm/index.mjs CHANGED
@@ -326,6 +326,19 @@ function removeUrlLastSlash(url) {
326
326
  function addPathToUrl(url, path) {
327
327
  return removeUrlLastSlash(url) + '/' + path;
328
328
  }
329
+ function isTelegramUrl(link) {
330
+ const url = new URL(link);
331
+ return url.protocol === 'tg:' || url.hostname === 't.me';
332
+ }
333
+ function encodeTelegramUrlParameters(parameters) {
334
+ return parameters
335
+ .replaceAll('.', '%2E')
336
+ .replaceAll('-', '%2D')
337
+ .replaceAll('_', '%5F')
338
+ .replaceAll('&', '-')
339
+ .replaceAll('=', '__')
340
+ .replaceAll('%', '--');
341
+ }
329
342
 
330
343
  class BridgeGateway {
331
344
  constructor(storage, bridgeUrl, sessionId, listener, errorsListener) {
@@ -428,6 +441,10 @@ class BridgeGateway {
428
441
  }
429
442
  }
430
443
 
444
+ function isPendingConnectionHttp(connection) {
445
+ return !('connectEvent' in connection);
446
+ }
447
+
431
448
  class BridgeConnectionStorage {
432
449
  constructor(storage) {
433
450
  this.storage = storage;
@@ -438,17 +455,25 @@ class BridgeConnectionStorage {
438
455
  if (connection.type === 'injected') {
439
456
  return this.storage.setItem(this.storeKey, JSON.stringify(connection));
440
457
  }
441
- const rawSession = {
442
- sessionKeyPair: connection.session.sessionCrypto.stringifyKeypair(),
443
- walletPublicKey: connection.session.walletPublicKey,
444
- bridgeUrl: connection.session.bridgeUrl
445
- };
458
+ if (!isPendingConnectionHttp(connection)) {
459
+ const rawSession = {
460
+ sessionKeyPair: connection.session.sessionCrypto.stringifyKeypair(),
461
+ walletPublicKey: connection.session.walletPublicKey,
462
+ bridgeUrl: connection.session.bridgeUrl
463
+ };
464
+ const rawConnection = {
465
+ type: 'http',
466
+ connectEvent: connection.connectEvent,
467
+ session: rawSession,
468
+ lastWalletEventId: connection.lastWalletEventId,
469
+ nextRpcRequestId: connection.nextRpcRequestId
470
+ };
471
+ return this.storage.setItem(this.storeKey, JSON.stringify(rawConnection));
472
+ }
446
473
  const rawConnection = {
447
474
  type: 'http',
448
- connectEvent: connection.connectEvent,
449
- session: rawSession,
450
- lastWalletEventId: connection.lastWalletEventId,
451
- nextRpcRequestId: connection.nextRpcRequestId
475
+ connectionSource: connection.connectionSource,
476
+ sessionCrypto: connection.sessionCrypto.stringifyKeypair()
452
477
  };
453
478
  return this.storage.setItem(this.storeKey, JSON.stringify(rawConnection));
454
479
  });
@@ -468,17 +493,24 @@ class BridgeConnectionStorage {
468
493
  if (connection.type === 'injected') {
469
494
  return connection;
470
495
  }
471
- const sessionCrypto = new SessionCrypto(connection.session.sessionKeyPair);
496
+ if ('connectEvent' in connection) {
497
+ const sessionCrypto = new SessionCrypto(connection.session.sessionKeyPair);
498
+ return {
499
+ type: 'http',
500
+ connectEvent: connection.connectEvent,
501
+ lastWalletEventId: connection.lastWalletEventId,
502
+ nextRpcRequestId: connection.nextRpcRequestId,
503
+ session: {
504
+ sessionCrypto,
505
+ bridgeUrl: connection.session.bridgeUrl,
506
+ walletPublicKey: connection.session.walletPublicKey
507
+ }
508
+ };
509
+ }
472
510
  return {
473
511
  type: 'http',
474
- connectEvent: connection.connectEvent,
475
- lastWalletEventId: connection.lastWalletEventId,
476
- nextRpcRequestId: connection.nextRpcRequestId,
477
- session: {
478
- sessionCrypto,
479
- bridgeUrl: connection.session.bridgeUrl,
480
- walletPublicKey: connection.session.walletPublicKey
481
- }
512
+ sessionCrypto: new SessionCrypto(connection.sessionCrypto),
513
+ connectionSource: connection.connectionSource
482
514
  };
483
515
  });
484
516
  }
@@ -494,6 +526,21 @@ class BridgeConnectionStorage {
494
526
  return connection;
495
527
  });
496
528
  }
529
+ getHttpPendingConnection() {
530
+ return __awaiter(this, void 0, void 0, function* () {
531
+ const connection = yield this.getConnection();
532
+ if (!connection) {
533
+ throw new TonConnectError('Trying to read HTTP connection source while nothing is stored');
534
+ }
535
+ if (connection.type === 'injected') {
536
+ throw new TonConnectError('Trying to read HTTP connection source while injected connection is stored');
537
+ }
538
+ if (!isPendingConnectionHttp(connection)) {
539
+ throw new TonConnectError('Trying to read HTTP-pending connection while http connection is stored');
540
+ }
541
+ return connection;
542
+ });
543
+ }
497
544
  getInjectedConnection() {
498
545
  return __awaiter(this, void 0, void 0, function* () {
499
546
  const connection = yield this.getConnection();
@@ -519,7 +566,7 @@ class BridgeConnectionStorage {
519
566
  storeLastWalletEventId(id) {
520
567
  return __awaiter(this, void 0, void 0, function* () {
521
568
  const connection = yield this.getConnection();
522
- if (connection && connection.type === 'http') {
569
+ if (connection && connection.type === 'http' && !isPendingConnectionHttp(connection)) {
523
570
  connection.lastWalletEventId = id;
524
571
  return this.storeConnection(connection);
525
572
  }
@@ -537,7 +584,7 @@ class BridgeConnectionStorage {
537
584
  increaseNextRpcRequestId() {
538
585
  return __awaiter(this, void 0, void 0, function* () {
539
586
  const connection = yield this.getConnection();
540
- if (connection) {
587
+ if (connection && 'nextRpcRequestId' in connection) {
541
588
  const lastId = connection.nextRpcRequestId || 0;
542
589
  connection.nextRpcRequestId = lastId + 1;
543
590
  return this.storeConnection(connection);
@@ -547,7 +594,7 @@ class BridgeConnectionStorage {
547
594
  getNextRpcRequestId() {
548
595
  return __awaiter(this, void 0, void 0, function* () {
549
596
  const connection = yield this.getConnection();
550
- if (connection) {
597
+ if (connection && 'nextRpcRequestId' in connection) {
551
598
  return connection.nextRpcRequestId || 0;
552
599
  }
553
600
  return 0;
@@ -599,48 +646,53 @@ class BridgeProvider {
599
646
  return __awaiter(this, void 0, void 0, function* () {
600
647
  const bridgeConnectionStorage = new BridgeConnectionStorage(storage);
601
648
  const connection = yield bridgeConnectionStorage.getHttpConnection();
649
+ if (isPendingConnectionHttp(connection)) {
650
+ return new BridgeProvider(storage, connection.connectionSource);
651
+ }
602
652
  return new BridgeProvider(storage, { bridgeUrl: connection.session.bridgeUrl });
603
653
  });
604
654
  }
605
655
  connect(message) {
606
656
  this.closeGateways();
607
657
  const sessionCrypto = new SessionCrypto();
608
- let bridgeUrl = '';
609
- let universalLink = this.standardUniversalLink;
610
- if (Array.isArray(this.walletConnectionSource)) {
611
- this.pendingGateways = this.walletConnectionSource.map(source => {
612
- const gateway = new BridgeGateway(this.storage, source.bridgeUrl, sessionCrypto.sessionId, () => { }, e => {
613
- console.error(e);
614
- });
615
- gateway.setListener(message => this.pendingGatewaysListener(gateway, source.bridgeUrl, message));
616
- return gateway;
617
- });
618
- this.pendingGateways.forEach(bridge => bridge.registerSession());
619
- }
620
- else {
621
- bridgeUrl = this.walletConnectionSource.bridgeUrl;
622
- if (this.walletConnectionSource.universalLink) {
623
- universalLink = this.walletConnectionSource.universalLink;
624
- }
625
- this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
626
- this.gateway.registerSession();
627
- }
628
658
  this.session = {
629
659
  sessionCrypto,
630
- bridgeUrl
660
+ bridgeUrl: 'bridgeUrl' in this.walletConnectionSource
661
+ ? this.walletConnectionSource.bridgeUrl
662
+ : ''
631
663
  };
664
+ this.connectionStorage
665
+ .storeConnection({
666
+ type: 'http',
667
+ connectionSource: this.walletConnectionSource,
668
+ sessionCrypto
669
+ })
670
+ .then(() => this.openGateways(sessionCrypto));
671
+ const universalLink = 'universalLink' in this.walletConnectionSource &&
672
+ this.walletConnectionSource.universalLink
673
+ ? this.walletConnectionSource.universalLink
674
+ : this.standardUniversalLink;
632
675
  return this.generateUniversalLink(universalLink, message);
633
676
  }
634
677
  restoreConnection() {
635
678
  return __awaiter(this, void 0, void 0, function* () {
636
- if (Array.isArray(this.walletConnectionSource)) {
637
- throw new TonConnectError('Internal error. Connection source is array while WalletConnectionSourceHTTP was expected.');
638
- }
639
679
  this.closeGateways();
640
680
  const storedConnection = yield this.connectionStorage.getHttpConnection();
641
681
  if (!storedConnection) {
642
682
  return;
643
683
  }
684
+ if (isPendingConnectionHttp(storedConnection)) {
685
+ this.session = {
686
+ sessionCrypto: storedConnection.sessionCrypto,
687
+ bridgeUrl: 'bridgeUrl' in this.walletConnectionSource
688
+ ? this.walletConnectionSource.bridgeUrl
689
+ : ''
690
+ };
691
+ return this.openGateways(storedConnection.sessionCrypto);
692
+ }
693
+ if (Array.isArray(this.walletConnectionSource)) {
694
+ throw new TonConnectError('Internal error. Connection source is array while WalletConnectionSourceHTTP was expected.');
695
+ }
644
696
  this.session = storedConnection.session;
645
697
  this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, storedConnection.session.sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
646
698
  yield this.gateway.registerSession();
@@ -783,12 +835,45 @@ class BridgeProvider {
783
835
  });
784
836
  }
785
837
  generateUniversalLink(universalLink, message) {
838
+ if (isTelegramUrl(universalLink)) {
839
+ return this.generateTGUniversalLink(universalLink, message);
840
+ }
841
+ return this.generateRegularUniversalLink(universalLink, message);
842
+ }
843
+ generateRegularUniversalLink(universalLink, message) {
786
844
  const url = new URL(universalLink);
787
845
  url.searchParams.append('v', PROTOCOL_VERSION.toString());
788
846
  url.searchParams.append('id', this.session.sessionCrypto.sessionId);
789
847
  url.searchParams.append('r', JSON.stringify(message));
790
848
  return url.toString();
791
849
  }
850
+ generateTGUniversalLink(universalLink, message) {
851
+ const urlToWrap = this.generateRegularUniversalLink('about:blank', message);
852
+ const linkParams = urlToWrap.split('?')[1];
853
+ const startattach = 'tonconnect-' + encodeTelegramUrlParameters(linkParams);
854
+ const url = new URL(universalLink);
855
+ url.searchParams.append('startattach', startattach);
856
+ return url.toString();
857
+ }
858
+ openGateways(sessionCrypto) {
859
+ return __awaiter(this, void 0, void 0, function* () {
860
+ if (Array.isArray(this.walletConnectionSource)) {
861
+ this.pendingGateways = this.walletConnectionSource.map(source => {
862
+ const gateway = new BridgeGateway(this.storage, source.bridgeUrl, sessionCrypto.sessionId, () => { }, e => {
863
+ console.error(e);
864
+ });
865
+ gateway.setListener(message => this.pendingGatewaysListener(gateway, source.bridgeUrl, message));
866
+ return gateway;
867
+ });
868
+ yield Promise.race(this.pendingGateways.map(bridge => bridge.registerSession()));
869
+ return;
870
+ }
871
+ else {
872
+ this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
873
+ return this.gateway.registerSession();
874
+ }
875
+ });
876
+ }
792
877
  closeGateways(options) {
793
878
  var _a;
794
879
  (_a = this.gateway) === null || _a === void 0 ? void 0 : _a.close();
@@ -816,6 +901,7 @@ function isJSBridgeWithMetadata(value) {
816
901
  }
817
902
  return hasProperties(value.tonconnect.walletInfo, [
818
903
  'name',
904
+ 'app_name',
819
905
  'image',
820
906
  'about_url',
821
907
  'platforms'
@@ -884,6 +970,7 @@ class InjectedProvider {
884
970
  const wallets = Object.entries(this.window).filter(([_, value]) => isJSBridgeWithMetadata(value));
885
971
  return wallets.map(([jsBridgeKey, wallet]) => ({
886
972
  name: wallet.tonconnect.walletInfo.name,
973
+ appName: wallet.tonconnect.walletInfo.app_name,
887
974
  aboutUrl: wallet.tonconnect.walletInfo.about_url,
888
975
  imageUrl: wallet.tonconnect.walletInfo.image,
889
976
  tondns: wallet.tonconnect.walletInfo.tondns,
@@ -1080,6 +1167,21 @@ function isWalletInfoInjected(value) {
1080
1167
 
1081
1168
  const FALLBACK_WALLETS_LIST = [
1082
1169
  {
1170
+ app_name: 'telegram-wallet',
1171
+ name: 'Wallet',
1172
+ image: 'https://wallet.tg/images/logo-288.png',
1173
+ about_url: 'https://wallet.tg/',
1174
+ universal_url: 'https://t.me/wallet?attach=wallet',
1175
+ bridge: [
1176
+ {
1177
+ type: 'sse',
1178
+ url: 'https://bridge.tonapi.io/bridge'
1179
+ }
1180
+ ],
1181
+ platforms: ['ios', 'android', 'macos', 'windows', 'linux']
1182
+ },
1183
+ {
1184
+ app_name: 'tonkeeper',
1083
1185
  name: 'Tonkeeper',
1084
1186
  image: 'https://tonkeeper.com/assets/tonconnect-icon.png',
1085
1187
  tondns: 'tonkeeper.ton',
@@ -1098,6 +1200,7 @@ const FALLBACK_WALLETS_LIST = [
1098
1200
  platforms: ['ios', 'android', 'chrome', 'firefox']
1099
1201
  },
1100
1202
  {
1203
+ app_name: 'openmask',
1101
1204
  name: 'OpenMask',
1102
1205
  image: 'https://raw.githubusercontent.com/OpenProduct/openmask-extension/main/public/openmask-logo-288.png',
1103
1206
  about_url: 'https://www.openmask.app/',
@@ -1110,6 +1213,7 @@ const FALLBACK_WALLETS_LIST = [
1110
1213
  platforms: ['chrome']
1111
1214
  },
1112
1215
  {
1216
+ app_name: 'mytonwallet',
1113
1217
  name: 'MyTonWallet',
1114
1218
  image: 'https://mytonwallet.io/icon-256.png',
1115
1219
  about_url: 'https://mytonwallet.io',
@@ -1127,6 +1231,7 @@ const FALLBACK_WALLETS_LIST = [
1127
1231
  platforms: ['chrome', 'windows', 'macos', 'linux']
1128
1232
  },
1129
1233
  {
1234
+ app_name: 'tonhub',
1130
1235
  name: 'Tonhub',
1131
1236
  image: 'https://tonhub.com/tonconnect_logo.png',
1132
1237
  about_url: 'https://tonhub.com',
@@ -1144,6 +1249,7 @@ const FALLBACK_WALLETS_LIST = [
1144
1249
  platforms: ['ios', 'android']
1145
1250
  },
1146
1251
  {
1252
+ app_name: 'tonflow',
1147
1253
  name: 'TonFlow',
1148
1254
  image: 'https://tonflow.net/assets/images/tonflow_ico_192.png',
1149
1255
  about_url: 'https://tonflow.net',
@@ -1156,6 +1262,7 @@ const FALLBACK_WALLETS_LIST = [
1156
1262
  platforms: ['chrome']
1157
1263
  },
1158
1264
  {
1265
+ app_name: 'dewallet',
1159
1266
  name: 'DeWallet',
1160
1267
  image: 'https://app.delabwallet.com/logo_black.png',
1161
1268
  about_url: 'https://delabwallet.com',
@@ -1168,6 +1275,7 @@ const FALLBACK_WALLETS_LIST = [
1168
1275
  platforms: ['chrome']
1169
1276
  },
1170
1277
  {
1278
+ app_name: 'xtonwallet',
1171
1279
  name: 'XTONWallet',
1172
1280
  image: 'https://xtonwallet.com/assets/img/icon-256-back.png',
1173
1281
  about_url: 'https://xtonwallet.com',
@@ -1180,6 +1288,7 @@ const FALLBACK_WALLETS_LIST = [
1180
1288
  platforms: ['chrome', 'firefox']
1181
1289
  },
1182
1290
  {
1291
+ app_name: 'tonwallet',
1183
1292
  name: 'TON Wallet',
1184
1293
  image: 'https://wallet.ton.org/assets/ui/qr-logo.png',
1185
1294
  about_url: 'https://chrome.google.com/webstore/detail/ton-wallet/nphplpgoakhhjchkkhmiggakijnkhfnd',
@@ -1197,7 +1306,7 @@ class WalletsListManager {
1197
1306
  constructor(options) {
1198
1307
  this.walletsListCache = null;
1199
1308
  this.walletsListCacheCreationTimestamp = null;
1200
- this.walletsListSource = 'https://raw.githubusercontent.com/ton-blockchain/wallets-list/main/wallets.json';
1309
+ this.walletsListSource = 'https://raw.githubusercontent.com/ton-blockchain/wallets-list/main/wallets-v2.json';
1201
1310
  if (options === null || options === void 0 ? void 0 : options.walletsListSource) {
1202
1311
  this.walletsListSource = options.walletsListSource;
1203
1312
  }
@@ -1269,13 +1378,15 @@ class WalletsListManager {
1269
1378
  }
1270
1379
  walletConfigDTOListToWalletConfigList(walletConfigDTO) {
1271
1380
  return walletConfigDTO.map(walletConfigDTO => {
1272
- const walletConfig = {
1381
+ const walletConfigBase = {
1273
1382
  name: walletConfigDTO.name,
1383
+ appName: walletConfigDTO.app_name,
1274
1384
  imageUrl: walletConfigDTO.image,
1275
1385
  aboutUrl: walletConfigDTO.about_url,
1276
1386
  tondns: walletConfigDTO.tondns,
1277
1387
  platforms: walletConfigDTO.platforms
1278
1388
  };
1389
+ const walletConfig = walletConfigBase;
1279
1390
  walletConfigDTO.bridge.forEach(bridge => {
1280
1391
  if (bridge.type === 'sse') {
1281
1392
  walletConfig.bridgeUrl = bridge.url;
@@ -1303,15 +1414,21 @@ class WalletsListManager {
1303
1414
  return Object.assign(Object.assign({}, (list1Item && Object.assign({}, list1Item))), (list2Item && Object.assign({}, list2Item)));
1304
1415
  });
1305
1416
  }
1417
+ // eslint-disable-next-line complexity
1306
1418
  isCorrectWalletConfigDTO(value) {
1307
1419
  if (!value || !(typeof value === 'object')) {
1308
1420
  return false;
1309
1421
  }
1310
1422
  const containsName = 'name' in value;
1423
+ const containsAppName = 'app_name' in value;
1311
1424
  const containsImage = 'image' in value;
1312
1425
  const containsAbout = 'about_url' in value;
1313
1426
  const containsPlatforms = 'platforms' in value;
1314
- if (!containsName || !containsImage || !containsAbout || !containsPlatforms) {
1427
+ if (!containsName ||
1428
+ !containsImage ||
1429
+ !containsAbout ||
1430
+ !containsPlatforms ||
1431
+ !containsAppName) {
1315
1432
  return false;
1316
1433
  }
1317
1434
  if (!value.platforms ||
@@ -1754,5 +1871,5 @@ function hexToBytes(hex) {
1754
1871
  return result;
1755
1872
  }
1756
1873
 
1757
- export { BadRequestError, FetchWalletsError, LocalstorageNotFoundError, ParseHexError, TonConnect, TonConnectError, UnknownAppError, UnknownError, UserRejectsError, WalletAlreadyConnectedError, WalletNotConnectedError, WalletNotInjectedError, WalletsListManager, WrongAddressError, TonConnect as default, isWalletInfoCurrentlyEmbedded, isWalletInfoCurrentlyInjected, isWalletInfoInjectable, isWalletInfoInjected, isWalletInfoRemote, toUserFriendlyAddress };
1874
+ export { BadRequestError, FetchWalletsError, LocalstorageNotFoundError, ParseHexError, TonConnect, TonConnectError, UnknownAppError, UnknownError, UserRejectsError, WalletAlreadyConnectedError, WalletNotConnectedError, WalletNotInjectedError, WalletsListManager, WrongAddressError, TonConnect as default, encodeTelegramUrlParameters, isTelegramUrl, isWalletInfoCurrentlyEmbedded, isWalletInfoCurrentlyInjected, isWalletInfoInjectable, isWalletInfoInjected, isWalletInfoRemote, toUserFriendlyAddress };
1758
1875
  //# sourceMappingURL=index.mjs.map