@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/dist/tonconnect-sdk.min.js +1 -1
- package/dist/tonconnect-sdk.min.js.map +1 -1
- package/lib/cjs/index.cjs +148 -58
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/esm/index.mjs +147 -58
- package/lib/esm/index.mjs.map +1 -1
- package/lib/types/index.d.ts +2 -0
- package/package.json +1 -1
package/lib/cjs/index.cjs
CHANGED
|
@@ -333,6 +333,15 @@ function isTelegramUrl(link) {
|
|
|
333
333
|
const url = new URL(link);
|
|
334
334
|
return url.protocol === 'tg:' || url.hostname === 't.me';
|
|
335
335
|
}
|
|
336
|
+
function encodeTelegramUrlParameters(parameters) {
|
|
337
|
+
return parameters
|
|
338
|
+
.replaceAll('.', '%2E')
|
|
339
|
+
.replaceAll('-', '%2D')
|
|
340
|
+
.replaceAll('_', '%5F')
|
|
341
|
+
.replaceAll('&', '-')
|
|
342
|
+
.replaceAll('=', '__')
|
|
343
|
+
.replaceAll('%', '--');
|
|
344
|
+
}
|
|
336
345
|
|
|
337
346
|
class BridgeGateway {
|
|
338
347
|
constructor(storage, bridgeUrl, sessionId, listener, errorsListener) {
|
|
@@ -347,7 +356,7 @@ class BridgeGateway {
|
|
|
347
356
|
this.isClosed = false;
|
|
348
357
|
this.bridgeGatewayStorage = new HttpBridgeGatewayStorage(storage, bridgeUrl);
|
|
349
358
|
}
|
|
350
|
-
registerSession() {
|
|
359
|
+
registerSession(options) {
|
|
351
360
|
return __awaiter(this, void 0, void 0, function* () {
|
|
352
361
|
const url = new URL(addPathToUrl(this.bridgeUrl, this.ssePath));
|
|
353
362
|
url.searchParams.append('client_id', this.sessionId);
|
|
@@ -360,8 +369,17 @@ class BridgeGateway {
|
|
|
360
369
|
}
|
|
361
370
|
this.eventSource = new EventSource(url.toString());
|
|
362
371
|
return new Promise((resolve, reject) => {
|
|
363
|
-
|
|
372
|
+
const timeout = (options === null || options === void 0 ? void 0 : options.openingDeadlineMS) ? setTimeout(() => {
|
|
373
|
+
var _a;
|
|
374
|
+
if (((_a = this.eventSource) === null || _a === void 0 ? void 0 : _a.readyState) !== EventSource.OPEN) {
|
|
375
|
+
reject(new TonConnectError('Bridge connection timeout'));
|
|
376
|
+
this.close();
|
|
377
|
+
}
|
|
378
|
+
}, options.openingDeadlineMS) : undefined;
|
|
379
|
+
this.eventSource.onerror = () => reject;
|
|
364
380
|
this.eventSource.onopen = () => {
|
|
381
|
+
clearTimeout(timeout);
|
|
382
|
+
this.isClosed = false;
|
|
365
383
|
this.eventSource.onerror = this.errorsHandler.bind(this);
|
|
366
384
|
this.eventSource.onmessage = this.messagesHandler.bind(this);
|
|
367
385
|
resolve();
|
|
@@ -435,6 +453,10 @@ class BridgeGateway {
|
|
|
435
453
|
}
|
|
436
454
|
}
|
|
437
455
|
|
|
456
|
+
function isPendingConnectionHttp(connection) {
|
|
457
|
+
return !('connectEvent' in connection);
|
|
458
|
+
}
|
|
459
|
+
|
|
438
460
|
class BridgeConnectionStorage {
|
|
439
461
|
constructor(storage) {
|
|
440
462
|
this.storage = storage;
|
|
@@ -445,17 +467,25 @@ class BridgeConnectionStorage {
|
|
|
445
467
|
if (connection.type === 'injected') {
|
|
446
468
|
return this.storage.setItem(this.storeKey, JSON.stringify(connection));
|
|
447
469
|
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
470
|
+
if (!isPendingConnectionHttp(connection)) {
|
|
471
|
+
const rawSession = {
|
|
472
|
+
sessionKeyPair: connection.session.sessionCrypto.stringifyKeypair(),
|
|
473
|
+
walletPublicKey: connection.session.walletPublicKey,
|
|
474
|
+
bridgeUrl: connection.session.bridgeUrl
|
|
475
|
+
};
|
|
476
|
+
const rawConnection = {
|
|
477
|
+
type: 'http',
|
|
478
|
+
connectEvent: connection.connectEvent,
|
|
479
|
+
session: rawSession,
|
|
480
|
+
lastWalletEventId: connection.lastWalletEventId,
|
|
481
|
+
nextRpcRequestId: connection.nextRpcRequestId
|
|
482
|
+
};
|
|
483
|
+
return this.storage.setItem(this.storeKey, JSON.stringify(rawConnection));
|
|
484
|
+
}
|
|
453
485
|
const rawConnection = {
|
|
454
486
|
type: 'http',
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
lastWalletEventId: connection.lastWalletEventId,
|
|
458
|
-
nextRpcRequestId: connection.nextRpcRequestId
|
|
487
|
+
connectionSource: connection.connectionSource,
|
|
488
|
+
sessionCrypto: connection.sessionCrypto.stringifyKeypair()
|
|
459
489
|
};
|
|
460
490
|
return this.storage.setItem(this.storeKey, JSON.stringify(rawConnection));
|
|
461
491
|
});
|
|
@@ -475,17 +505,24 @@ class BridgeConnectionStorage {
|
|
|
475
505
|
if (connection.type === 'injected') {
|
|
476
506
|
return connection;
|
|
477
507
|
}
|
|
478
|
-
|
|
508
|
+
if ('connectEvent' in connection) {
|
|
509
|
+
const sessionCrypto = new protocol.SessionCrypto(connection.session.sessionKeyPair);
|
|
510
|
+
return {
|
|
511
|
+
type: 'http',
|
|
512
|
+
connectEvent: connection.connectEvent,
|
|
513
|
+
lastWalletEventId: connection.lastWalletEventId,
|
|
514
|
+
nextRpcRequestId: connection.nextRpcRequestId,
|
|
515
|
+
session: {
|
|
516
|
+
sessionCrypto,
|
|
517
|
+
bridgeUrl: connection.session.bridgeUrl,
|
|
518
|
+
walletPublicKey: connection.session.walletPublicKey
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
479
522
|
return {
|
|
480
523
|
type: 'http',
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
nextRpcRequestId: connection.nextRpcRequestId,
|
|
484
|
-
session: {
|
|
485
|
-
sessionCrypto,
|
|
486
|
-
bridgeUrl: connection.session.bridgeUrl,
|
|
487
|
-
walletPublicKey: connection.session.walletPublicKey
|
|
488
|
-
}
|
|
524
|
+
sessionCrypto: new protocol.SessionCrypto(connection.sessionCrypto),
|
|
525
|
+
connectionSource: connection.connectionSource
|
|
489
526
|
};
|
|
490
527
|
});
|
|
491
528
|
}
|
|
@@ -501,6 +538,21 @@ class BridgeConnectionStorage {
|
|
|
501
538
|
return connection;
|
|
502
539
|
});
|
|
503
540
|
}
|
|
541
|
+
getHttpPendingConnection() {
|
|
542
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
543
|
+
const connection = yield this.getConnection();
|
|
544
|
+
if (!connection) {
|
|
545
|
+
throw new TonConnectError('Trying to read HTTP connection source while nothing is stored');
|
|
546
|
+
}
|
|
547
|
+
if (connection.type === 'injected') {
|
|
548
|
+
throw new TonConnectError('Trying to read HTTP connection source while injected connection is stored');
|
|
549
|
+
}
|
|
550
|
+
if (!isPendingConnectionHttp(connection)) {
|
|
551
|
+
throw new TonConnectError('Trying to read HTTP-pending connection while http connection is stored');
|
|
552
|
+
}
|
|
553
|
+
return connection;
|
|
554
|
+
});
|
|
555
|
+
}
|
|
504
556
|
getInjectedConnection() {
|
|
505
557
|
return __awaiter(this, void 0, void 0, function* () {
|
|
506
558
|
const connection = yield this.getConnection();
|
|
@@ -526,7 +578,7 @@ class BridgeConnectionStorage {
|
|
|
526
578
|
storeLastWalletEventId(id) {
|
|
527
579
|
return __awaiter(this, void 0, void 0, function* () {
|
|
528
580
|
const connection = yield this.getConnection();
|
|
529
|
-
if (connection && connection.type === 'http') {
|
|
581
|
+
if (connection && connection.type === 'http' && !isPendingConnectionHttp(connection)) {
|
|
530
582
|
connection.lastWalletEventId = id;
|
|
531
583
|
return this.storeConnection(connection);
|
|
532
584
|
}
|
|
@@ -544,7 +596,7 @@ class BridgeConnectionStorage {
|
|
|
544
596
|
increaseNextRpcRequestId() {
|
|
545
597
|
return __awaiter(this, void 0, void 0, function* () {
|
|
546
598
|
const connection = yield this.getConnection();
|
|
547
|
-
if (connection) {
|
|
599
|
+
if (connection && 'nextRpcRequestId' in connection) {
|
|
548
600
|
const lastId = connection.nextRpcRequestId || 0;
|
|
549
601
|
connection.nextRpcRequestId = lastId + 1;
|
|
550
602
|
return this.storeConnection(connection);
|
|
@@ -554,7 +606,7 @@ class BridgeConnectionStorage {
|
|
|
554
606
|
getNextRpcRequestId() {
|
|
555
607
|
return __awaiter(this, void 0, void 0, function* () {
|
|
556
608
|
const connection = yield this.getConnection();
|
|
557
|
-
if (connection) {
|
|
609
|
+
if (connection && 'nextRpcRequestId' in connection) {
|
|
558
610
|
return connection.nextRpcRequestId || 0;
|
|
559
611
|
}
|
|
560
612
|
return 0;
|
|
@@ -606,51 +658,62 @@ class BridgeProvider {
|
|
|
606
658
|
return __awaiter(this, void 0, void 0, function* () {
|
|
607
659
|
const bridgeConnectionStorage = new BridgeConnectionStorage(storage);
|
|
608
660
|
const connection = yield bridgeConnectionStorage.getHttpConnection();
|
|
661
|
+
if (isPendingConnectionHttp(connection)) {
|
|
662
|
+
return new BridgeProvider(storage, connection.connectionSource);
|
|
663
|
+
}
|
|
609
664
|
return new BridgeProvider(storage, { bridgeUrl: connection.session.bridgeUrl });
|
|
610
665
|
});
|
|
611
666
|
}
|
|
612
667
|
connect(message) {
|
|
613
668
|
this.closeGateways();
|
|
614
669
|
const sessionCrypto = new protocol.SessionCrypto();
|
|
615
|
-
let bridgeUrl = '';
|
|
616
|
-
let universalLink = this.standardUniversalLink;
|
|
617
|
-
if (Array.isArray(this.walletConnectionSource)) {
|
|
618
|
-
this.pendingGateways = this.walletConnectionSource.map(source => {
|
|
619
|
-
const gateway = new BridgeGateway(this.storage, source.bridgeUrl, sessionCrypto.sessionId, () => { }, e => {
|
|
620
|
-
console.error(e);
|
|
621
|
-
});
|
|
622
|
-
gateway.setListener(message => this.pendingGatewaysListener(gateway, source.bridgeUrl, message));
|
|
623
|
-
return gateway;
|
|
624
|
-
});
|
|
625
|
-
this.pendingGateways.forEach(bridge => bridge.registerSession());
|
|
626
|
-
}
|
|
627
|
-
else {
|
|
628
|
-
bridgeUrl = this.walletConnectionSource.bridgeUrl;
|
|
629
|
-
if (this.walletConnectionSource.universalLink) {
|
|
630
|
-
universalLink = this.walletConnectionSource.universalLink;
|
|
631
|
-
}
|
|
632
|
-
this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
|
|
633
|
-
this.gateway.registerSession();
|
|
634
|
-
}
|
|
635
670
|
this.session = {
|
|
636
671
|
sessionCrypto,
|
|
637
|
-
bridgeUrl
|
|
672
|
+
bridgeUrl: 'bridgeUrl' in this.walletConnectionSource
|
|
673
|
+
? this.walletConnectionSource.bridgeUrl
|
|
674
|
+
: ''
|
|
638
675
|
};
|
|
676
|
+
this.connectionStorage
|
|
677
|
+
.storeConnection({
|
|
678
|
+
type: 'http',
|
|
679
|
+
connectionSource: this.walletConnectionSource,
|
|
680
|
+
sessionCrypto
|
|
681
|
+
})
|
|
682
|
+
.then(() => this.openGateways(sessionCrypto));
|
|
683
|
+
const universalLink = 'universalLink' in this.walletConnectionSource &&
|
|
684
|
+
this.walletConnectionSource.universalLink
|
|
685
|
+
? this.walletConnectionSource.universalLink
|
|
686
|
+
: this.standardUniversalLink;
|
|
639
687
|
return this.generateUniversalLink(universalLink, message);
|
|
640
688
|
}
|
|
641
689
|
restoreConnection() {
|
|
642
690
|
return __awaiter(this, void 0, void 0, function* () {
|
|
643
|
-
if (Array.isArray(this.walletConnectionSource)) {
|
|
644
|
-
throw new TonConnectError('Internal error. Connection source is array while WalletConnectionSourceHTTP was expected.');
|
|
645
|
-
}
|
|
646
691
|
this.closeGateways();
|
|
647
692
|
const storedConnection = yield this.connectionStorage.getHttpConnection();
|
|
648
693
|
if (!storedConnection) {
|
|
649
694
|
return;
|
|
650
695
|
}
|
|
696
|
+
if (isPendingConnectionHttp(storedConnection)) {
|
|
697
|
+
this.session = {
|
|
698
|
+
sessionCrypto: storedConnection.sessionCrypto,
|
|
699
|
+
bridgeUrl: 'bridgeUrl' in this.walletConnectionSource
|
|
700
|
+
? this.walletConnectionSource.bridgeUrl
|
|
701
|
+
: ''
|
|
702
|
+
};
|
|
703
|
+
return this.openGateways(storedConnection.sessionCrypto, { openingDeadlineMS: 5000 });
|
|
704
|
+
}
|
|
705
|
+
if (Array.isArray(this.walletConnectionSource)) {
|
|
706
|
+
throw new TonConnectError('Internal error. Connection source is array while WalletConnectionSourceHTTP was expected.');
|
|
707
|
+
}
|
|
651
708
|
this.session = storedConnection.session;
|
|
652
709
|
this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, storedConnection.session.sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
|
|
653
|
-
|
|
710
|
+
try {
|
|
711
|
+
yield this.gateway.registerSession({ openingDeadlineMS: 5000 });
|
|
712
|
+
}
|
|
713
|
+
catch (e) {
|
|
714
|
+
yield this.disconnect();
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
654
717
|
this.listeners.forEach(listener => listener(storedConnection.connectEvent));
|
|
655
718
|
});
|
|
656
719
|
}
|
|
@@ -805,18 +868,30 @@ class BridgeProvider {
|
|
|
805
868
|
generateTGUniversalLink(universalLink, message) {
|
|
806
869
|
const urlToWrap = this.generateRegularUniversalLink('about:blank', message);
|
|
807
870
|
const linkParams = urlToWrap.split('?')[1];
|
|
808
|
-
const startattach = 'tonconnect-' +
|
|
809
|
-
linkParams
|
|
810
|
-
.replaceAll('.', '%2E')
|
|
811
|
-
.replaceAll('-', '%2D')
|
|
812
|
-
.replaceAll('_', '%5F')
|
|
813
|
-
.replaceAll('&', '-')
|
|
814
|
-
.replaceAll('=', '__')
|
|
815
|
-
.replaceAll('%', '--');
|
|
871
|
+
const startattach = 'tonconnect-' + encodeTelegramUrlParameters(linkParams);
|
|
816
872
|
const url = new URL(universalLink);
|
|
817
873
|
url.searchParams.append('startattach', startattach);
|
|
818
874
|
return url.toString();
|
|
819
875
|
}
|
|
876
|
+
openGateways(sessionCrypto, options) {
|
|
877
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
878
|
+
if (Array.isArray(this.walletConnectionSource)) {
|
|
879
|
+
this.pendingGateways = this.walletConnectionSource.map(source => {
|
|
880
|
+
const gateway = new BridgeGateway(this.storage, source.bridgeUrl, sessionCrypto.sessionId, () => { }, e => {
|
|
881
|
+
console.error(e);
|
|
882
|
+
});
|
|
883
|
+
gateway.setListener(message => this.pendingGatewaysListener(gateway, source.bridgeUrl, message));
|
|
884
|
+
return gateway;
|
|
885
|
+
});
|
|
886
|
+
yield Promise.allSettled(this.pendingGateways.map(bridge => bridge.registerSession(options)));
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
else {
|
|
890
|
+
this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
|
|
891
|
+
return this.gateway.registerSession(options);
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
}
|
|
820
895
|
closeGateways(options) {
|
|
821
896
|
var _a;
|
|
822
897
|
(_a = this.gateway) === null || _a === void 0 ? void 0 : _a.close();
|
|
@@ -1109,6 +1184,20 @@ function isWalletInfoInjected(value) {
|
|
|
1109
1184
|
}
|
|
1110
1185
|
|
|
1111
1186
|
const FALLBACK_WALLETS_LIST = [
|
|
1187
|
+
{
|
|
1188
|
+
app_name: 'telegram-wallet',
|
|
1189
|
+
name: 'Wallet',
|
|
1190
|
+
image: 'https://wallet.tg/images/logo-288.png',
|
|
1191
|
+
about_url: 'https://wallet.tg/',
|
|
1192
|
+
universal_url: 'https://t.me/wallet?attach=wallet',
|
|
1193
|
+
bridge: [
|
|
1194
|
+
{
|
|
1195
|
+
type: 'sse',
|
|
1196
|
+
url: 'https://bridge.tonapi.io/bridge'
|
|
1197
|
+
}
|
|
1198
|
+
],
|
|
1199
|
+
platforms: ['ios', 'android', 'macos', 'windows', 'linux']
|
|
1200
|
+
},
|
|
1112
1201
|
{
|
|
1113
1202
|
app_name: 'tonkeeper',
|
|
1114
1203
|
name: 'Tonkeeper',
|
|
@@ -1235,7 +1324,7 @@ class WalletsListManager {
|
|
|
1235
1324
|
constructor(options) {
|
|
1236
1325
|
this.walletsListCache = null;
|
|
1237
1326
|
this.walletsListCacheCreationTimestamp = null;
|
|
1238
|
-
this.walletsListSource = 'https://raw.githubusercontent.com/ton-blockchain/wallets-list/main/wallets.json';
|
|
1327
|
+
this.walletsListSource = 'https://raw.githubusercontent.com/ton-blockchain/wallets-list/main/wallets-v2.json';
|
|
1239
1328
|
if (options === null || options === void 0 ? void 0 : options.walletsListSource) {
|
|
1240
1329
|
this.walletsListSource = options.walletsListSource;
|
|
1241
1330
|
}
|
|
@@ -1822,7 +1911,8 @@ exports.WalletNotConnectedError = WalletNotConnectedError;
|
|
|
1822
1911
|
exports.WalletNotInjectedError = WalletNotInjectedError;
|
|
1823
1912
|
exports.WalletsListManager = WalletsListManager;
|
|
1824
1913
|
exports.WrongAddressError = WrongAddressError;
|
|
1825
|
-
exports
|
|
1914
|
+
exports["default"] = TonConnect;
|
|
1915
|
+
exports.encodeTelegramUrlParameters = encodeTelegramUrlParameters;
|
|
1826
1916
|
exports.isTelegramUrl = isTelegramUrl;
|
|
1827
1917
|
exports.isWalletInfoCurrentlyEmbedded = isWalletInfoCurrentlyEmbedded;
|
|
1828
1918
|
exports.isWalletInfoCurrentlyInjected = isWalletInfoCurrentlyInjected;
|