@tonconnect/sdk 2.2.0 → 3.0.0-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/esm/index.mjs CHANGED
@@ -330,6 +330,15 @@ function isTelegramUrl(link) {
330
330
  const url = new URL(link);
331
331
  return url.protocol === 'tg:' || url.hostname === 't.me';
332
332
  }
333
+ function encodeTelegramUrlParameters(parameters) {
334
+ return parameters
335
+ .replaceAll('.', '%2E')
336
+ .replaceAll('-', '%2D')
337
+ .replaceAll('_', '%5F')
338
+ .replaceAll('&', '-')
339
+ .replaceAll('=', '__')
340
+ .replaceAll('%', '--');
341
+ }
333
342
 
334
343
  class BridgeGateway {
335
344
  constructor(storage, bridgeUrl, sessionId, listener, errorsListener) {
@@ -344,7 +353,7 @@ class BridgeGateway {
344
353
  this.isClosed = false;
345
354
  this.bridgeGatewayStorage = new HttpBridgeGatewayStorage(storage, bridgeUrl);
346
355
  }
347
- registerSession() {
356
+ registerSession(options) {
348
357
  return __awaiter(this, void 0, void 0, function* () {
349
358
  const url = new URL(addPathToUrl(this.bridgeUrl, this.ssePath));
350
359
  url.searchParams.append('client_id', this.sessionId);
@@ -357,8 +366,17 @@ class BridgeGateway {
357
366
  }
358
367
  this.eventSource = new EventSource(url.toString());
359
368
  return new Promise((resolve, reject) => {
360
- this.eventSource.onerror = reject;
369
+ const timeout = (options === null || options === void 0 ? void 0 : options.openingDeadlineMS) ? setTimeout(() => {
370
+ var _a;
371
+ if (((_a = this.eventSource) === null || _a === void 0 ? void 0 : _a.readyState) !== EventSource.OPEN) {
372
+ reject(new TonConnectError('Bridge connection timeout'));
373
+ this.close();
374
+ }
375
+ }, options.openingDeadlineMS) : undefined;
376
+ this.eventSource.onerror = () => reject;
361
377
  this.eventSource.onopen = () => {
378
+ clearTimeout(timeout);
379
+ this.isClosed = false;
362
380
  this.eventSource.onerror = this.errorsHandler.bind(this);
363
381
  this.eventSource.onmessage = this.messagesHandler.bind(this);
364
382
  resolve();
@@ -432,6 +450,10 @@ class BridgeGateway {
432
450
  }
433
451
  }
434
452
 
453
+ function isPendingConnectionHttp(connection) {
454
+ return !('connectEvent' in connection);
455
+ }
456
+
435
457
  class BridgeConnectionStorage {
436
458
  constructor(storage) {
437
459
  this.storage = storage;
@@ -442,17 +464,25 @@ class BridgeConnectionStorage {
442
464
  if (connection.type === 'injected') {
443
465
  return this.storage.setItem(this.storeKey, JSON.stringify(connection));
444
466
  }
445
- const rawSession = {
446
- sessionKeyPair: connection.session.sessionCrypto.stringifyKeypair(),
447
- walletPublicKey: connection.session.walletPublicKey,
448
- bridgeUrl: connection.session.bridgeUrl
449
- };
467
+ if (!isPendingConnectionHttp(connection)) {
468
+ const rawSession = {
469
+ sessionKeyPair: connection.session.sessionCrypto.stringifyKeypair(),
470
+ walletPublicKey: connection.session.walletPublicKey,
471
+ bridgeUrl: connection.session.bridgeUrl
472
+ };
473
+ const rawConnection = {
474
+ type: 'http',
475
+ connectEvent: connection.connectEvent,
476
+ session: rawSession,
477
+ lastWalletEventId: connection.lastWalletEventId,
478
+ nextRpcRequestId: connection.nextRpcRequestId
479
+ };
480
+ return this.storage.setItem(this.storeKey, JSON.stringify(rawConnection));
481
+ }
450
482
  const rawConnection = {
451
483
  type: 'http',
452
- connectEvent: connection.connectEvent,
453
- session: rawSession,
454
- lastWalletEventId: connection.lastWalletEventId,
455
- nextRpcRequestId: connection.nextRpcRequestId
484
+ connectionSource: connection.connectionSource,
485
+ sessionCrypto: connection.sessionCrypto.stringifyKeypair()
456
486
  };
457
487
  return this.storage.setItem(this.storeKey, JSON.stringify(rawConnection));
458
488
  });
@@ -472,17 +502,24 @@ class BridgeConnectionStorage {
472
502
  if (connection.type === 'injected') {
473
503
  return connection;
474
504
  }
475
- const sessionCrypto = new SessionCrypto(connection.session.sessionKeyPair);
505
+ if ('connectEvent' in connection) {
506
+ const sessionCrypto = new SessionCrypto(connection.session.sessionKeyPair);
507
+ return {
508
+ type: 'http',
509
+ connectEvent: connection.connectEvent,
510
+ lastWalletEventId: connection.lastWalletEventId,
511
+ nextRpcRequestId: connection.nextRpcRequestId,
512
+ session: {
513
+ sessionCrypto,
514
+ bridgeUrl: connection.session.bridgeUrl,
515
+ walletPublicKey: connection.session.walletPublicKey
516
+ }
517
+ };
518
+ }
476
519
  return {
477
520
  type: 'http',
478
- connectEvent: connection.connectEvent,
479
- lastWalletEventId: connection.lastWalletEventId,
480
- nextRpcRequestId: connection.nextRpcRequestId,
481
- session: {
482
- sessionCrypto,
483
- bridgeUrl: connection.session.bridgeUrl,
484
- walletPublicKey: connection.session.walletPublicKey
485
- }
521
+ sessionCrypto: new SessionCrypto(connection.sessionCrypto),
522
+ connectionSource: connection.connectionSource
486
523
  };
487
524
  });
488
525
  }
@@ -498,6 +535,21 @@ class BridgeConnectionStorage {
498
535
  return connection;
499
536
  });
500
537
  }
538
+ getHttpPendingConnection() {
539
+ return __awaiter(this, void 0, void 0, function* () {
540
+ const connection = yield this.getConnection();
541
+ if (!connection) {
542
+ throw new TonConnectError('Trying to read HTTP connection source while nothing is stored');
543
+ }
544
+ if (connection.type === 'injected') {
545
+ throw new TonConnectError('Trying to read HTTP connection source while injected connection is stored');
546
+ }
547
+ if (!isPendingConnectionHttp(connection)) {
548
+ throw new TonConnectError('Trying to read HTTP-pending connection while http connection is stored');
549
+ }
550
+ return connection;
551
+ });
552
+ }
501
553
  getInjectedConnection() {
502
554
  return __awaiter(this, void 0, void 0, function* () {
503
555
  const connection = yield this.getConnection();
@@ -523,7 +575,7 @@ class BridgeConnectionStorage {
523
575
  storeLastWalletEventId(id) {
524
576
  return __awaiter(this, void 0, void 0, function* () {
525
577
  const connection = yield this.getConnection();
526
- if (connection && connection.type === 'http') {
578
+ if (connection && connection.type === 'http' && !isPendingConnectionHttp(connection)) {
527
579
  connection.lastWalletEventId = id;
528
580
  return this.storeConnection(connection);
529
581
  }
@@ -541,7 +593,7 @@ class BridgeConnectionStorage {
541
593
  increaseNextRpcRequestId() {
542
594
  return __awaiter(this, void 0, void 0, function* () {
543
595
  const connection = yield this.getConnection();
544
- if (connection) {
596
+ if (connection && 'nextRpcRequestId' in connection) {
545
597
  const lastId = connection.nextRpcRequestId || 0;
546
598
  connection.nextRpcRequestId = lastId + 1;
547
599
  return this.storeConnection(connection);
@@ -551,7 +603,7 @@ class BridgeConnectionStorage {
551
603
  getNextRpcRequestId() {
552
604
  return __awaiter(this, void 0, void 0, function* () {
553
605
  const connection = yield this.getConnection();
554
- if (connection) {
606
+ if (connection && 'nextRpcRequestId' in connection) {
555
607
  return connection.nextRpcRequestId || 0;
556
608
  }
557
609
  return 0;
@@ -603,51 +655,62 @@ class BridgeProvider {
603
655
  return __awaiter(this, void 0, void 0, function* () {
604
656
  const bridgeConnectionStorage = new BridgeConnectionStorage(storage);
605
657
  const connection = yield bridgeConnectionStorage.getHttpConnection();
658
+ if (isPendingConnectionHttp(connection)) {
659
+ return new BridgeProvider(storage, connection.connectionSource);
660
+ }
606
661
  return new BridgeProvider(storage, { bridgeUrl: connection.session.bridgeUrl });
607
662
  });
608
663
  }
609
664
  connect(message) {
610
665
  this.closeGateways();
611
666
  const sessionCrypto = new SessionCrypto();
612
- let bridgeUrl = '';
613
- let universalLink = this.standardUniversalLink;
614
- if (Array.isArray(this.walletConnectionSource)) {
615
- this.pendingGateways = this.walletConnectionSource.map(source => {
616
- const gateway = new BridgeGateway(this.storage, source.bridgeUrl, sessionCrypto.sessionId, () => { }, e => {
617
- console.error(e);
618
- });
619
- gateway.setListener(message => this.pendingGatewaysListener(gateway, source.bridgeUrl, message));
620
- return gateway;
621
- });
622
- this.pendingGateways.forEach(bridge => bridge.registerSession());
623
- }
624
- else {
625
- bridgeUrl = this.walletConnectionSource.bridgeUrl;
626
- if (this.walletConnectionSource.universalLink) {
627
- universalLink = this.walletConnectionSource.universalLink;
628
- }
629
- this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
630
- this.gateway.registerSession();
631
- }
632
667
  this.session = {
633
668
  sessionCrypto,
634
- bridgeUrl
669
+ bridgeUrl: 'bridgeUrl' in this.walletConnectionSource
670
+ ? this.walletConnectionSource.bridgeUrl
671
+ : ''
635
672
  };
673
+ this.connectionStorage
674
+ .storeConnection({
675
+ type: 'http',
676
+ connectionSource: this.walletConnectionSource,
677
+ sessionCrypto
678
+ })
679
+ .then(() => this.openGateways(sessionCrypto));
680
+ const universalLink = 'universalLink' in this.walletConnectionSource &&
681
+ this.walletConnectionSource.universalLink
682
+ ? this.walletConnectionSource.universalLink
683
+ : this.standardUniversalLink;
636
684
  return this.generateUniversalLink(universalLink, message);
637
685
  }
638
686
  restoreConnection() {
639
687
  return __awaiter(this, void 0, void 0, function* () {
640
- if (Array.isArray(this.walletConnectionSource)) {
641
- throw new TonConnectError('Internal error. Connection source is array while WalletConnectionSourceHTTP was expected.');
642
- }
643
688
  this.closeGateways();
644
689
  const storedConnection = yield this.connectionStorage.getHttpConnection();
645
690
  if (!storedConnection) {
646
691
  return;
647
692
  }
693
+ if (isPendingConnectionHttp(storedConnection)) {
694
+ this.session = {
695
+ sessionCrypto: storedConnection.sessionCrypto,
696
+ bridgeUrl: 'bridgeUrl' in this.walletConnectionSource
697
+ ? this.walletConnectionSource.bridgeUrl
698
+ : ''
699
+ };
700
+ return this.openGateways(storedConnection.sessionCrypto, { openingDeadlineMS: 5000 });
701
+ }
702
+ if (Array.isArray(this.walletConnectionSource)) {
703
+ throw new TonConnectError('Internal error. Connection source is array while WalletConnectionSourceHTTP was expected.');
704
+ }
648
705
  this.session = storedConnection.session;
649
706
  this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, storedConnection.session.sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
650
- yield this.gateway.registerSession();
707
+ try {
708
+ yield this.gateway.registerSession({ openingDeadlineMS: 5000 });
709
+ }
710
+ catch (e) {
711
+ yield this.disconnect();
712
+ return;
713
+ }
651
714
  this.listeners.forEach(listener => listener(storedConnection.connectEvent));
652
715
  });
653
716
  }
@@ -802,18 +865,30 @@ class BridgeProvider {
802
865
  generateTGUniversalLink(universalLink, message) {
803
866
  const urlToWrap = this.generateRegularUniversalLink('about:blank', message);
804
867
  const linkParams = urlToWrap.split('?')[1];
805
- const startattach = 'tonconnect-' +
806
- linkParams
807
- .replaceAll('.', '%2E')
808
- .replaceAll('-', '%2D')
809
- .replaceAll('_', '%5F')
810
- .replaceAll('&', '-')
811
- .replaceAll('=', '__')
812
- .replaceAll('%', '--');
868
+ const startattach = 'tonconnect-' + encodeTelegramUrlParameters(linkParams);
813
869
  const url = new URL(universalLink);
814
870
  url.searchParams.append('startattach', startattach);
815
871
  return url.toString();
816
872
  }
873
+ openGateways(sessionCrypto, options) {
874
+ return __awaiter(this, void 0, void 0, function* () {
875
+ if (Array.isArray(this.walletConnectionSource)) {
876
+ this.pendingGateways = this.walletConnectionSource.map(source => {
877
+ const gateway = new BridgeGateway(this.storage, source.bridgeUrl, sessionCrypto.sessionId, () => { }, e => {
878
+ console.error(e);
879
+ });
880
+ gateway.setListener(message => this.pendingGatewaysListener(gateway, source.bridgeUrl, message));
881
+ return gateway;
882
+ });
883
+ yield Promise.allSettled(this.pendingGateways.map(bridge => bridge.registerSession(options)));
884
+ return;
885
+ }
886
+ else {
887
+ this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
888
+ return this.gateway.registerSession(options);
889
+ }
890
+ });
891
+ }
817
892
  closeGateways(options) {
818
893
  var _a;
819
894
  (_a = this.gateway) === null || _a === void 0 ? void 0 : _a.close();
@@ -1106,6 +1181,20 @@ function isWalletInfoInjected(value) {
1106
1181
  }
1107
1182
 
1108
1183
  const FALLBACK_WALLETS_LIST = [
1184
+ {
1185
+ app_name: 'telegram-wallet',
1186
+ name: 'Wallet',
1187
+ image: 'https://wallet.tg/images/logo-288.png',
1188
+ about_url: 'https://wallet.tg/',
1189
+ universal_url: 'https://t.me/wallet?attach=wallet',
1190
+ bridge: [
1191
+ {
1192
+ type: 'sse',
1193
+ url: 'https://bridge.tonapi.io/bridge'
1194
+ }
1195
+ ],
1196
+ platforms: ['ios', 'android', 'macos', 'windows', 'linux']
1197
+ },
1109
1198
  {
1110
1199
  app_name: 'tonkeeper',
1111
1200
  name: 'Tonkeeper',
@@ -1232,7 +1321,7 @@ class WalletsListManager {
1232
1321
  constructor(options) {
1233
1322
  this.walletsListCache = null;
1234
1323
  this.walletsListCacheCreationTimestamp = null;
1235
- this.walletsListSource = 'https://raw.githubusercontent.com/ton-blockchain/wallets-list/main/wallets.json';
1324
+ this.walletsListSource = 'https://raw.githubusercontent.com/ton-blockchain/wallets-list/main/wallets-v2.json';
1236
1325
  if (options === null || options === void 0 ? void 0 : options.walletsListSource) {
1237
1326
  this.walletsListSource = options.walletsListSource;
1238
1327
  }
@@ -1797,5 +1886,5 @@ function hexToBytes(hex) {
1797
1886
  return result;
1798
1887
  }
1799
1888
 
1800
- export { BadRequestError, FetchWalletsError, LocalstorageNotFoundError, ParseHexError, TonConnect, TonConnectError, UnknownAppError, UnknownError, UserRejectsError, WalletAlreadyConnectedError, WalletNotConnectedError, WalletNotInjectedError, WalletsListManager, WrongAddressError, TonConnect as default, isTelegramUrl, isWalletInfoCurrentlyEmbedded, isWalletInfoCurrentlyInjected, isWalletInfoInjectable, isWalletInfoInjected, isWalletInfoRemote, toUserFriendlyAddress };
1889
+ 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 };
1801
1890
  //# sourceMappingURL=index.mjs.map