@tonconnect/sdk 3.0.0 → 3.0.1-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/dist/tonconnect-sdk.min.js +1 -1
- package/dist/tonconnect-sdk.min.js.map +1 -1
- package/lib/cjs/index.cjs +538 -154
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/esm/index.mjs +538 -154
- package/lib/esm/index.mjs.map +1 -1
- package/lib/types/index.d.ts +38 -7
- package/package.json +1 -1
package/lib/cjs/index.cjs
CHANGED
|
@@ -346,6 +346,194 @@ function encodeTelegramUrlParameters(parameters) {
|
|
|
346
346
|
.replaceAll('%', '--');
|
|
347
347
|
}
|
|
348
348
|
|
|
349
|
+
/**
|
|
350
|
+
* Creates an AbortController instance with an optional AbortSignal.
|
|
351
|
+
*
|
|
352
|
+
* @param {AbortSignal} [signal] - An optional AbortSignal to use for aborting the controller.
|
|
353
|
+
* @returns {AbortController} - An instance of AbortController.
|
|
354
|
+
*/
|
|
355
|
+
function createAbortController(signal) {
|
|
356
|
+
const abortController = new AbortController();
|
|
357
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
358
|
+
abortController.abort();
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', () => abortController.abort(), { once: true });
|
|
362
|
+
}
|
|
363
|
+
return abortController;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Executes a function and provides deferred behavior, allowing for a timeout and abort functionality.
|
|
367
|
+
*
|
|
368
|
+
* @param {Deferrable<T>} fn - The function to execute. It should return a promise that resolves with the desired result.
|
|
369
|
+
* @param {DeferOptions} options - Optional configuration options for the defer behavior.
|
|
370
|
+
* @returns {Promise<T>} - A promise that resolves with the result of the executed function, or rejects with an error if it times out or is aborted.
|
|
371
|
+
*/
|
|
372
|
+
function defer(fn, options) {
|
|
373
|
+
const timeout = options === null || options === void 0 ? void 0 : options.timeout;
|
|
374
|
+
const signal = options === null || options === void 0 ? void 0 : options.signal;
|
|
375
|
+
const abortController = createAbortController(signal);
|
|
376
|
+
return new Promise((resolve, reject) => {
|
|
377
|
+
if (abortController.signal.aborted) {
|
|
378
|
+
reject(new TonConnectError('Operation aborted'));
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
let timeoutId;
|
|
382
|
+
if (typeof timeout !== 'undefined') {
|
|
383
|
+
timeoutId = setTimeout(() => {
|
|
384
|
+
reject(new TonConnectError(`Timeout after ${timeout}ms`));
|
|
385
|
+
abortController.abort();
|
|
386
|
+
}, timeout);
|
|
387
|
+
}
|
|
388
|
+
abortController.signal.addEventListener('abort', () => {
|
|
389
|
+
clearTimeout(timeoutId);
|
|
390
|
+
reject(new TonConnectError('Operation aborted'));
|
|
391
|
+
}, { once: true });
|
|
392
|
+
const deferOptions = { timeout, abort: abortController.signal };
|
|
393
|
+
fn(resolve, reject, deferOptions).finally(() => clearTimeout(timeoutId));
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Delays the execution of code for a specified number of milliseconds.
|
|
399
|
+
* @param {number} timeout - The number of milliseconds to delay the execution.
|
|
400
|
+
* @param {DelayOptions} [options] - Optional configuration options for the delay.
|
|
401
|
+
* @return {Promise<void>} - A promise that resolves after the specified delay, or rejects if the delay is aborted.
|
|
402
|
+
*/
|
|
403
|
+
function delay(timeout, options) {
|
|
404
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
405
|
+
return yield defer((resolve, reject, options) => __awaiter(this, void 0, void 0, function* () {
|
|
406
|
+
var _a, _b;
|
|
407
|
+
if ((_a = options.signal) === null || _a === void 0 ? void 0 : _a.aborted) {
|
|
408
|
+
reject(new TonConnectError('Delay aborted'));
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
const timeoutId = setTimeout(() => resolve(), timeout);
|
|
412
|
+
(_b = options.signal) === null || _b === void 0 ? void 0 : _b.addEventListener('abort', () => {
|
|
413
|
+
clearTimeout(timeoutId);
|
|
414
|
+
reject(new TonConnectError('Delay aborted'));
|
|
415
|
+
});
|
|
416
|
+
}), { signal: options === null || options === void 0 ? void 0 : options.signal });
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Function to call ton api until we get response.
|
|
422
|
+
* Because ton network is pretty unstable we need to make sure response is final.
|
|
423
|
+
* @param {T} fn - function to call
|
|
424
|
+
* @param {CallForSuccessOptions} [options] - optional configuration options
|
|
425
|
+
*/
|
|
426
|
+
function callForSuccess(fn, options) {
|
|
427
|
+
var _a, _b;
|
|
428
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
429
|
+
const attempts = (_a = options === null || options === void 0 ? void 0 : options.attempts) !== null && _a !== void 0 ? _a : 10;
|
|
430
|
+
const delayMs = (_b = options === null || options === void 0 ? void 0 : options.delayMs) !== null && _b !== void 0 ? _b : 200;
|
|
431
|
+
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
432
|
+
if (typeof fn !== 'function') {
|
|
433
|
+
throw new TonConnectError(`Expected a function, got ${typeof fn}`);
|
|
434
|
+
}
|
|
435
|
+
let i = 0;
|
|
436
|
+
let lastError;
|
|
437
|
+
while (i < attempts) {
|
|
438
|
+
if (abortController.signal.aborted) {
|
|
439
|
+
throw new TonConnectError(`Aborted after attempts ${i}`);
|
|
440
|
+
}
|
|
441
|
+
try {
|
|
442
|
+
return yield fn({ signal: abortController.signal });
|
|
443
|
+
}
|
|
444
|
+
catch (err) {
|
|
445
|
+
lastError = err;
|
|
446
|
+
i++;
|
|
447
|
+
yield delay(delayMs);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
throw lastError;
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
function logDebug(...args) {
|
|
455
|
+
{
|
|
456
|
+
try {
|
|
457
|
+
console.debug('[TON_CONNECT_SDK]', ...args);
|
|
458
|
+
}
|
|
459
|
+
catch (_a) { }
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
function logError(...args) {
|
|
463
|
+
{
|
|
464
|
+
try {
|
|
465
|
+
console.error('[TON_CONNECT_SDK]', ...args);
|
|
466
|
+
}
|
|
467
|
+
catch (_a) { }
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
function logWarning(...args) {
|
|
471
|
+
{
|
|
472
|
+
try {
|
|
473
|
+
console.warn('[TON_CONNECT_SDK]', ...args);
|
|
474
|
+
}
|
|
475
|
+
catch (_a) { }
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Create a resource.
|
|
481
|
+
*
|
|
482
|
+
* @template T - The type of the resource.
|
|
483
|
+
* @template Args - The type of the arguments for creating the resource.
|
|
484
|
+
*
|
|
485
|
+
* @param {(...args: Args) => Promise<T>} createFn - A function that creates the resource.
|
|
486
|
+
* @param {(resource: T) => Promise<void>} [disposeFn] - An optional function that disposes the resource.
|
|
487
|
+
*/
|
|
488
|
+
function createResource(createFn, disposeFn) {
|
|
489
|
+
let currentResource = null;
|
|
490
|
+
let currentArgs = null;
|
|
491
|
+
let currentPromise = null;
|
|
492
|
+
let abortController = null;
|
|
493
|
+
// create a new resource
|
|
494
|
+
const create = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
495
|
+
abortController === null || abortController === void 0 ? void 0 : abortController.abort();
|
|
496
|
+
abortController = createAbortController();
|
|
497
|
+
currentArgs = args;
|
|
498
|
+
const promise = createFn(abortController.signal, ...args);
|
|
499
|
+
currentPromise = promise;
|
|
500
|
+
const resource = yield promise;
|
|
501
|
+
if (currentPromise !== promise) {
|
|
502
|
+
yield disposeFn(resource);
|
|
503
|
+
throw new TonConnectError('Resource creation was aborted by a new resource creation');
|
|
504
|
+
}
|
|
505
|
+
currentResource = resource;
|
|
506
|
+
return currentResource;
|
|
507
|
+
});
|
|
508
|
+
// get the current resource
|
|
509
|
+
const current = () => {
|
|
510
|
+
return currentResource !== null && currentResource !== void 0 ? currentResource : null;
|
|
511
|
+
};
|
|
512
|
+
// dispose the current resource
|
|
513
|
+
const dispose = () => __awaiter(this, void 0, void 0, function* () {
|
|
514
|
+
const resource = currentResource;
|
|
515
|
+
currentResource = null;
|
|
516
|
+
const promise = currentPromise;
|
|
517
|
+
currentPromise = null;
|
|
518
|
+
abortController === null || abortController === void 0 ? void 0 : abortController.abort();
|
|
519
|
+
yield Promise.allSettled([
|
|
520
|
+
resource ? disposeFn(resource) : Promise.resolve(),
|
|
521
|
+
promise ? disposeFn(yield promise) : Promise.resolve()
|
|
522
|
+
]);
|
|
523
|
+
});
|
|
524
|
+
// recreate the current resource
|
|
525
|
+
const recreate = () => __awaiter(this, void 0, void 0, function* () {
|
|
526
|
+
yield dispose();
|
|
527
|
+
return create(...(currentArgs !== null && currentArgs !== void 0 ? currentArgs : []));
|
|
528
|
+
});
|
|
529
|
+
return {
|
|
530
|
+
create,
|
|
531
|
+
current,
|
|
532
|
+
dispose,
|
|
533
|
+
recreate
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
|
|
349
537
|
class BridgeGateway {
|
|
350
538
|
constructor(storage, bridgeUrl, sessionId, listener, errorsListener) {
|
|
351
539
|
this.bridgeUrl = bridgeUrl;
|
|
@@ -356,67 +544,77 @@ class BridgeGateway {
|
|
|
356
544
|
this.postPath = 'message';
|
|
357
545
|
this.heartbeatMessage = 'heartbeat';
|
|
358
546
|
this.defaultTtl = 300;
|
|
359
|
-
this.
|
|
547
|
+
this.eventSource = createResource((signal, options) => __awaiter(this, void 0, void 0, function* () {
|
|
548
|
+
const eventSourceConfig = {
|
|
549
|
+
bridgeUrl: this.bridgeUrl,
|
|
550
|
+
ssePath: this.ssePath,
|
|
551
|
+
sessionId: this.sessionId,
|
|
552
|
+
bridgeGatewayStorage: this.bridgeGatewayStorage,
|
|
553
|
+
errorHandler: this.errorsHandler.bind(this),
|
|
554
|
+
messageHandler: this.messagesHandler.bind(this),
|
|
555
|
+
signal: signal
|
|
556
|
+
};
|
|
557
|
+
return yield createEventSource(eventSourceConfig, options);
|
|
558
|
+
}), (resource) => __awaiter(this, void 0, void 0, function* () {
|
|
559
|
+
resource.close();
|
|
560
|
+
}));
|
|
360
561
|
this.bridgeGatewayStorage = new HttpBridgeGatewayStorage(storage, bridgeUrl);
|
|
361
562
|
}
|
|
563
|
+
get isReady() {
|
|
564
|
+
const eventSource = this.eventSource.current();
|
|
565
|
+
return (eventSource === null || eventSource === void 0 ? void 0 : eventSource.readyState) === EventSource.OPEN;
|
|
566
|
+
}
|
|
567
|
+
get isClosed() {
|
|
568
|
+
const eventSource = this.eventSource.current();
|
|
569
|
+
return (eventSource === null || eventSource === void 0 ? void 0 : eventSource.readyState) !== EventSource.OPEN;
|
|
570
|
+
}
|
|
571
|
+
get isConnecting() {
|
|
572
|
+
const eventSource = this.eventSource.current();
|
|
573
|
+
return (eventSource === null || eventSource === void 0 ? void 0 : eventSource.readyState) === EventSource.CONNECTING;
|
|
574
|
+
}
|
|
362
575
|
registerSession(options) {
|
|
363
576
|
return __awaiter(this, void 0, void 0, function* () {
|
|
364
|
-
|
|
365
|
-
url.searchParams.append('client_id', this.sessionId);
|
|
366
|
-
const lastEventId = yield this.bridgeGatewayStorage.getLastEventId();
|
|
367
|
-
if (this.isClosed) {
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
if (lastEventId) {
|
|
371
|
-
url.searchParams.append('last_event_id', lastEventId);
|
|
372
|
-
}
|
|
373
|
-
this.eventSource = new EventSource(url.toString());
|
|
374
|
-
return new Promise((resolve, reject) => {
|
|
375
|
-
const timeout = (options === null || options === void 0 ? void 0 : options.openingDeadlineMS) ? setTimeout(() => {
|
|
376
|
-
var _a;
|
|
377
|
-
if (((_a = this.eventSource) === null || _a === void 0 ? void 0 : _a.readyState) !== EventSource.OPEN) {
|
|
378
|
-
reject(new TonConnectError('Bridge connection timeout'));
|
|
379
|
-
this.close();
|
|
380
|
-
}
|
|
381
|
-
}, options.openingDeadlineMS) : undefined;
|
|
382
|
-
this.eventSource.onerror = () => reject;
|
|
383
|
-
this.eventSource.onopen = () => {
|
|
384
|
-
clearTimeout(timeout);
|
|
385
|
-
this.isClosed = false;
|
|
386
|
-
this.eventSource.onerror = this.errorsHandler.bind(this);
|
|
387
|
-
this.eventSource.onmessage = this.messagesHandler.bind(this);
|
|
388
|
-
resolve();
|
|
389
|
-
};
|
|
390
|
-
});
|
|
577
|
+
yield this.eventSource.create(options);
|
|
391
578
|
});
|
|
392
579
|
}
|
|
393
|
-
send(message, receiver, topic,
|
|
580
|
+
send(message, receiver, topic, ttlOrOptions) {
|
|
394
581
|
return __awaiter(this, void 0, void 0, function* () {
|
|
582
|
+
// TODO: remove deprecated method
|
|
583
|
+
const options = {};
|
|
584
|
+
if (typeof ttlOrOptions === 'number') {
|
|
585
|
+
options.ttl = ttlOrOptions;
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
options.ttl = ttlOrOptions === null || ttlOrOptions === void 0 ? void 0 : ttlOrOptions.ttl;
|
|
589
|
+
options.signal = ttlOrOptions === null || ttlOrOptions === void 0 ? void 0 : ttlOrOptions.signal;
|
|
590
|
+
}
|
|
395
591
|
const url = new URL(addPathToUrl(this.bridgeUrl, this.postPath));
|
|
396
592
|
url.searchParams.append('client_id', this.sessionId);
|
|
397
593
|
url.searchParams.append('to', receiver);
|
|
398
|
-
url.searchParams.append('ttl', (ttl || this.defaultTtl).toString());
|
|
594
|
+
url.searchParams.append('ttl', ((options === null || options === void 0 ? void 0 : options.ttl) || this.defaultTtl).toString());
|
|
399
595
|
url.searchParams.append('topic', topic);
|
|
400
|
-
const
|
|
401
|
-
|
|
402
|
-
body
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
596
|
+
const body = protocol.Base64.encode(message);
|
|
597
|
+
yield callForSuccess((options) => __awaiter(this, void 0, void 0, function* () {
|
|
598
|
+
const response = yield this.post(url, body, options.signal);
|
|
599
|
+
if (!response.ok) {
|
|
600
|
+
throw new TonConnectError(`Bridge send failed, status ${response.status}`);
|
|
601
|
+
}
|
|
602
|
+
}), { attempts: Number.MAX_SAFE_INTEGER, delayMs: 5000, signal: options === null || options === void 0 ? void 0 : options.signal });
|
|
407
603
|
});
|
|
408
604
|
}
|
|
409
605
|
pause() {
|
|
410
606
|
var _a;
|
|
411
|
-
(_a = this.eventSource) === null || _a === void 0 ? void 0 : _a.
|
|
607
|
+
(_a = this.eventSource) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
412
608
|
}
|
|
413
609
|
unPause() {
|
|
414
|
-
return this
|
|
610
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
611
|
+
yield this.eventSource.recreate();
|
|
612
|
+
});
|
|
415
613
|
}
|
|
416
614
|
close() {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
615
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
616
|
+
yield this.eventSource.dispose();
|
|
617
|
+
});
|
|
420
618
|
}
|
|
421
619
|
setListener(listener) {
|
|
422
620
|
this.listener = listener;
|
|
@@ -424,20 +622,36 @@ class BridgeGateway {
|
|
|
424
622
|
setErrorsListener(errorsListener) {
|
|
425
623
|
this.errorsListener = errorsListener;
|
|
426
624
|
}
|
|
625
|
+
post(url, body, signal) {
|
|
626
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
627
|
+
const response = yield fetch(url, {
|
|
628
|
+
method: 'post',
|
|
629
|
+
body: body,
|
|
630
|
+
signal: signal
|
|
631
|
+
});
|
|
632
|
+
if (!response.ok) {
|
|
633
|
+
throw new TonConnectError(`Bridge send failed, status ${response.status}`);
|
|
634
|
+
}
|
|
635
|
+
return response;
|
|
636
|
+
});
|
|
637
|
+
}
|
|
427
638
|
errorsHandler(e) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
this.eventSource.close();
|
|
432
|
-
this.registerSession();
|
|
639
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
640
|
+
if (this.isConnecting) {
|
|
641
|
+
logError('Bridge error', JSON.stringify(e));
|
|
433
642
|
return;
|
|
434
643
|
}
|
|
435
|
-
if (
|
|
436
|
-
|
|
644
|
+
if (this.isReady) {
|
|
645
|
+
this.errorsListener(e);
|
|
437
646
|
return;
|
|
438
647
|
}
|
|
439
|
-
this.
|
|
440
|
-
|
|
648
|
+
if (this.isClosed) {
|
|
649
|
+
logDebug('Bridge reconnecting, 200ms delay');
|
|
650
|
+
yield delay(200);
|
|
651
|
+
yield this.eventSource.recreate();
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
});
|
|
441
655
|
}
|
|
442
656
|
messagesHandler(e) {
|
|
443
657
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -445,19 +659,66 @@ class BridgeGateway {
|
|
|
445
659
|
return;
|
|
446
660
|
}
|
|
447
661
|
yield this.bridgeGatewayStorage.storeLastEventId(e.lastEventId);
|
|
448
|
-
if (
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
662
|
+
if (this.isClosed) {
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
let bridgeIncomingMessage;
|
|
666
|
+
try {
|
|
667
|
+
bridgeIncomingMessage = JSON.parse(e.data);
|
|
668
|
+
}
|
|
669
|
+
catch (e) {
|
|
670
|
+
throw new TonConnectError(`Bridge message parse failed, message ${e.data}`);
|
|
457
671
|
}
|
|
672
|
+
this.listener(bridgeIncomingMessage);
|
|
458
673
|
});
|
|
459
674
|
}
|
|
460
675
|
}
|
|
676
|
+
function createEventSource(config, options) {
|
|
677
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
678
|
+
return yield defer((resolve, reject, deferOptions) => __awaiter(this, void 0, void 0, function* () {
|
|
679
|
+
var _a;
|
|
680
|
+
const abortController = createAbortController(deferOptions.signal);
|
|
681
|
+
const signal = abortController.signal;
|
|
682
|
+
if (signal.aborted) {
|
|
683
|
+
reject(new TonConnectError('Bridge connection aborted'));
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
const url = new URL(addPathToUrl(config.bridgeUrl, config.ssePath));
|
|
687
|
+
url.searchParams.append('client_id', config.sessionId);
|
|
688
|
+
const lastEventId = yield config.bridgeGatewayStorage.getLastEventId();
|
|
689
|
+
if (lastEventId) {
|
|
690
|
+
url.searchParams.append('last_event_id', lastEventId);
|
|
691
|
+
}
|
|
692
|
+
if (signal.aborted) {
|
|
693
|
+
reject(new TonConnectError('Bridge connection aborted'));
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
const eventSource = new EventSource(url.toString());
|
|
697
|
+
eventSource.onerror = (reason) => {
|
|
698
|
+
if (signal.aborted) {
|
|
699
|
+
reject(new TonConnectError('Bridge connection aborted'));
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
config.errorHandler(reason);
|
|
703
|
+
};
|
|
704
|
+
eventSource.onopen = () => {
|
|
705
|
+
if (signal.aborted) {
|
|
706
|
+
reject(new TonConnectError('Bridge connection aborted'));
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
resolve(eventSource);
|
|
710
|
+
};
|
|
711
|
+
eventSource.onmessage = (event) => {
|
|
712
|
+
config.messageHandler(event);
|
|
713
|
+
};
|
|
714
|
+
(_a = config === null || config === void 0 ? void 0 : config.signal) === null || _a === void 0 ? void 0 : _a.addEventListener('abort', () => {
|
|
715
|
+
logError('Bridge connection aborted');
|
|
716
|
+
eventSource.close();
|
|
717
|
+
reject(new TonConnectError('Bridge connection aborted'));
|
|
718
|
+
});
|
|
719
|
+
}), { timeout: options === null || options === void 0 ? void 0 : options.openingDeadlineMS, signal: config === null || config === void 0 ? void 0 : config.signal });
|
|
720
|
+
});
|
|
721
|
+
}
|
|
461
722
|
|
|
462
723
|
function isPendingConnectionHttp(connection) {
|
|
463
724
|
return !('connectEvent' in connection);
|
|
@@ -622,31 +883,6 @@ class BridgeConnectionStorage {
|
|
|
622
883
|
|
|
623
884
|
const PROTOCOL_VERSION = 2;
|
|
624
885
|
|
|
625
|
-
function logDebug(...args) {
|
|
626
|
-
{
|
|
627
|
-
try {
|
|
628
|
-
console.debug('[TON_CONNECT_SDK]', ...args);
|
|
629
|
-
}
|
|
630
|
-
catch (_a) { }
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
function logError(...args) {
|
|
634
|
-
{
|
|
635
|
-
try {
|
|
636
|
-
console.error('[TON_CONNECT_SDK]', ...args);
|
|
637
|
-
}
|
|
638
|
-
catch (_a) { }
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
function logWarning(...args) {
|
|
642
|
-
{
|
|
643
|
-
try {
|
|
644
|
-
console.warn('[TON_CONNECT_SDK]', ...args);
|
|
645
|
-
}
|
|
646
|
-
catch (_a) { }
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
|
|
650
886
|
class BridgeProvider {
|
|
651
887
|
constructor(storage, walletConnectionSource) {
|
|
652
888
|
this.storage = storage;
|
|
@@ -658,6 +894,7 @@ class BridgeProvider {
|
|
|
658
894
|
this.gateway = null;
|
|
659
895
|
this.pendingGateways = [];
|
|
660
896
|
this.listeners = [];
|
|
897
|
+
this.defaultOpeningDeadlineMS = 5000;
|
|
661
898
|
this.connectionStorage = new BridgeConnectionStorage(storage);
|
|
662
899
|
}
|
|
663
900
|
static fromStorage(storage) {
|
|
@@ -670,7 +907,7 @@ class BridgeProvider {
|
|
|
670
907
|
return new BridgeProvider(storage, { bridgeUrl: connection.session.bridgeUrl });
|
|
671
908
|
});
|
|
672
909
|
}
|
|
673
|
-
connect(message) {
|
|
910
|
+
connect(message, options) {
|
|
674
911
|
this.closeGateways();
|
|
675
912
|
const sessionCrypto = new protocol.SessionCrypto();
|
|
676
913
|
this.session = {
|
|
@@ -685,20 +922,40 @@ class BridgeProvider {
|
|
|
685
922
|
connectionSource: this.walletConnectionSource,
|
|
686
923
|
sessionCrypto
|
|
687
924
|
})
|
|
688
|
-
.then(() => this
|
|
925
|
+
.then(() => __awaiter(this, void 0, void 0, function* () {
|
|
926
|
+
yield callForSuccess(_options => this.openGateways(sessionCrypto, {
|
|
927
|
+
openingDeadlineMS: options === null || options === void 0 ? void 0 : options.openingDeadlineMS,
|
|
928
|
+
signal: _options === null || _options === void 0 ? void 0 : _options.signal
|
|
929
|
+
}), {
|
|
930
|
+
attempts: Number.MAX_SAFE_INTEGER,
|
|
931
|
+
delayMs: 5000,
|
|
932
|
+
signal: options === null || options === void 0 ? void 0 : options.signal
|
|
933
|
+
});
|
|
934
|
+
}));
|
|
689
935
|
const universalLink = 'universalLink' in this.walletConnectionSource &&
|
|
690
936
|
this.walletConnectionSource.universalLink
|
|
691
937
|
? this.walletConnectionSource.universalLink
|
|
692
938
|
: this.standardUniversalLink;
|
|
693
939
|
return this.generateUniversalLink(universalLink, message);
|
|
694
940
|
}
|
|
695
|
-
restoreConnection() {
|
|
941
|
+
restoreConnection(options) {
|
|
942
|
+
var _a, _b;
|
|
696
943
|
return __awaiter(this, void 0, void 0, function* () {
|
|
944
|
+
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
945
|
+
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
|
946
|
+
this.abortController = abortController;
|
|
947
|
+
if (abortController.signal.aborted) {
|
|
948
|
+
return;
|
|
949
|
+
}
|
|
697
950
|
this.closeGateways();
|
|
698
951
|
const storedConnection = yield this.connectionStorage.getHttpConnection();
|
|
699
952
|
if (!storedConnection) {
|
|
700
953
|
return;
|
|
701
954
|
}
|
|
955
|
+
if (abortController.signal.aborted) {
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
const openingDeadlineMS = (_b = options === null || options === void 0 ? void 0 : options.openingDeadlineMS) !== null && _b !== void 0 ? _b : this.defaultOpeningDeadlineMS;
|
|
702
959
|
if (isPendingConnectionHttp(storedConnection)) {
|
|
703
960
|
this.session = {
|
|
704
961
|
sessionCrypto: storedConnection.sessionCrypto,
|
|
@@ -706,25 +963,54 @@ class BridgeProvider {
|
|
|
706
963
|
? this.walletConnectionSource.bridgeUrl
|
|
707
964
|
: ''
|
|
708
965
|
};
|
|
709
|
-
return this.openGateways(storedConnection.sessionCrypto, {
|
|
966
|
+
return yield this.openGateways(storedConnection.sessionCrypto, {
|
|
967
|
+
openingDeadlineMS: openingDeadlineMS,
|
|
968
|
+
signal: abortController === null || abortController === void 0 ? void 0 : abortController.signal
|
|
969
|
+
});
|
|
710
970
|
}
|
|
711
971
|
if (Array.isArray(this.walletConnectionSource)) {
|
|
712
972
|
throw new TonConnectError('Internal error. Connection source is array while WalletConnectionSourceHTTP was expected.');
|
|
713
973
|
}
|
|
714
974
|
this.session = storedConnection.session;
|
|
975
|
+
if (this.gateway) {
|
|
976
|
+
logDebug('Gateway is already opened, closing previous gateway');
|
|
977
|
+
yield this.gateway.close();
|
|
978
|
+
}
|
|
715
979
|
this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, storedConnection.session.sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
|
|
980
|
+
if (abortController.signal.aborted) {
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
// notify listeners about stored connection
|
|
984
|
+
this.listeners.forEach(listener => listener(storedConnection.connectEvent));
|
|
985
|
+
// wait for the connection to be opened
|
|
716
986
|
try {
|
|
717
|
-
yield this.gateway.registerSession({
|
|
987
|
+
yield callForSuccess(options => this.gateway.registerSession({
|
|
988
|
+
openingDeadlineMS: openingDeadlineMS,
|
|
989
|
+
signal: options.signal
|
|
990
|
+
}), {
|
|
991
|
+
attempts: Number.MAX_SAFE_INTEGER,
|
|
992
|
+
delayMs: 5000,
|
|
993
|
+
signal: abortController.signal
|
|
994
|
+
});
|
|
718
995
|
}
|
|
719
996
|
catch (e) {
|
|
720
|
-
yield this.disconnect();
|
|
997
|
+
yield this.disconnect({ signal: abortController.signal });
|
|
721
998
|
return;
|
|
722
999
|
}
|
|
723
|
-
this.listeners.forEach(listener => listener(storedConnection.connectEvent));
|
|
724
1000
|
});
|
|
725
1001
|
}
|
|
726
|
-
sendRequest(request,
|
|
1002
|
+
sendRequest(request, optionsOrOnRequestSent) {
|
|
1003
|
+
// TODO: remove deprecated method
|
|
1004
|
+
const options = {};
|
|
1005
|
+
if (typeof optionsOrOnRequestSent === 'function') {
|
|
1006
|
+
options.onRequestSent = optionsOrOnRequestSent;
|
|
1007
|
+
}
|
|
1008
|
+
else {
|
|
1009
|
+
options.onRequestSent = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.onRequestSent;
|
|
1010
|
+
options.signal = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.signal;
|
|
1011
|
+
}
|
|
727
1012
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
1013
|
+
var _a;
|
|
728
1014
|
if (!this.gateway || !this.session || !('walletPublicKey' in this.session)) {
|
|
729
1015
|
throw new TonConnectError('Trying to send bridge request without session');
|
|
730
1016
|
}
|
|
@@ -733,8 +1019,8 @@ class BridgeProvider {
|
|
|
733
1019
|
logDebug('Send http-bridge request:', Object.assign(Object.assign({}, request), { id }));
|
|
734
1020
|
const encodedRequest = this.session.sessionCrypto.encrypt(JSON.stringify(Object.assign(Object.assign({}, request), { id })), protocol.hexToByteArray(this.session.walletPublicKey));
|
|
735
1021
|
try {
|
|
736
|
-
yield this.gateway.send(encodedRequest, this.session.walletPublicKey, request.method);
|
|
737
|
-
|
|
1022
|
+
yield this.gateway.send(encodedRequest, this.session.walletPublicKey, request.method, { signal: options === null || options === void 0 ? void 0 : options.signal });
|
|
1023
|
+
(_a = options === null || options === void 0 ? void 0 : options.onRequestSent) === null || _a === void 0 ? void 0 : _a.call(options);
|
|
738
1024
|
this.pendingRequests.set(id.toString(), resolve);
|
|
739
1025
|
}
|
|
740
1026
|
catch (e) {
|
|
@@ -748,7 +1034,7 @@ class BridgeProvider {
|
|
|
748
1034
|
this.session = null;
|
|
749
1035
|
this.gateway = null;
|
|
750
1036
|
}
|
|
751
|
-
disconnect() {
|
|
1037
|
+
disconnect(options) {
|
|
752
1038
|
return __awaiter(this, void 0, void 0, function* () {
|
|
753
1039
|
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
|
754
1040
|
let called = false;
|
|
@@ -757,10 +1043,14 @@ class BridgeProvider {
|
|
|
757
1043
|
this.removeBridgeAndSession().then(resolve);
|
|
758
1044
|
};
|
|
759
1045
|
try {
|
|
760
|
-
|
|
1046
|
+
this.closeGateways();
|
|
1047
|
+
yield this.sendRequest({ method: 'disconnect', params: [] }, {
|
|
1048
|
+
onRequestSent: onRequestSent,
|
|
1049
|
+
signal: options === null || options === void 0 ? void 0 : options.signal
|
|
1050
|
+
});
|
|
761
1051
|
}
|
|
762
1052
|
catch (e) {
|
|
763
|
-
|
|
1053
|
+
logDebug('Disconnect error:', e);
|
|
764
1054
|
if (!called) {
|
|
765
1055
|
this.removeBridgeAndSession().then(resolve);
|
|
766
1056
|
}
|
|
@@ -789,10 +1079,14 @@ class BridgeProvider {
|
|
|
789
1079
|
pendingGatewaysListener(gateway, bridgeUrl, bridgeIncomingMessage) {
|
|
790
1080
|
return __awaiter(this, void 0, void 0, function* () {
|
|
791
1081
|
if (!this.pendingGateways.includes(gateway)) {
|
|
792
|
-
gateway.close();
|
|
1082
|
+
yield gateway.close();
|
|
793
1083
|
return;
|
|
794
1084
|
}
|
|
795
1085
|
this.closeGateways({ except: gateway });
|
|
1086
|
+
if (this.gateway) {
|
|
1087
|
+
logDebug('Gateway is already opened, closing previous gateway');
|
|
1088
|
+
yield this.gateway.close();
|
|
1089
|
+
}
|
|
796
1090
|
this.session.bridgeUrl = bridgeUrl;
|
|
797
1091
|
this.gateway = gateway;
|
|
798
1092
|
this.gateway.setErrorsListener(this.gatewayErrorsListener.bind(this));
|
|
@@ -831,6 +1125,7 @@ class BridgeProvider {
|
|
|
831
1125
|
yield this.updateSession(walletMessage, bridgeIncomingMessage.from);
|
|
832
1126
|
}
|
|
833
1127
|
if (walletMessage.event === 'disconnect') {
|
|
1128
|
+
logDebug(`Removing bridge and session: received disconnect event`);
|
|
834
1129
|
yield this.removeBridgeAndSession();
|
|
835
1130
|
}
|
|
836
1131
|
listeners.forEach(listener => listener(walletMessage));
|
|
@@ -894,8 +1189,15 @@ class BridgeProvider {
|
|
|
894
1189
|
return url.toString();
|
|
895
1190
|
}
|
|
896
1191
|
openGateways(sessionCrypto, options) {
|
|
1192
|
+
var _a;
|
|
897
1193
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1194
|
+
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
1195
|
+
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
|
1196
|
+
this.abortController = abortController;
|
|
898
1197
|
if (Array.isArray(this.walletConnectionSource)) {
|
|
1198
|
+
// close all gateways before opening new ones
|
|
1199
|
+
this.pendingGateways.map(bridge => bridge.close().catch(e => console.error(e)));
|
|
1200
|
+
// open new gateways
|
|
899
1201
|
this.pendingGateways = this.walletConnectionSource.map(source => {
|
|
900
1202
|
const gateway = new BridgeGateway(this.storage, source.bridgeUrl, sessionCrypto.sessionId, () => { }, e => {
|
|
901
1203
|
console.error(e);
|
|
@@ -903,12 +1205,28 @@ class BridgeProvider {
|
|
|
903
1205
|
gateway.setListener(message => this.pendingGatewaysListener(gateway, source.bridgeUrl, message));
|
|
904
1206
|
return gateway;
|
|
905
1207
|
});
|
|
906
|
-
yield Promise.allSettled(this.pendingGateways.map(bridge =>
|
|
1208
|
+
yield Promise.allSettled(this.pendingGateways.map(bridge => callForSuccess((_options) => {
|
|
1209
|
+
return bridge.registerSession({
|
|
1210
|
+
openingDeadlineMS: options === null || options === void 0 ? void 0 : options.openingDeadlineMS,
|
|
1211
|
+
signal: _options.signal
|
|
1212
|
+
});
|
|
1213
|
+
}, {
|
|
1214
|
+
attempts: Number.MAX_SAFE_INTEGER,
|
|
1215
|
+
delayMs: 5000,
|
|
1216
|
+
signal: abortController.signal
|
|
1217
|
+
})));
|
|
907
1218
|
return;
|
|
908
1219
|
}
|
|
909
1220
|
else {
|
|
1221
|
+
if (this.gateway) {
|
|
1222
|
+
logDebug(`Gateway is already opened, closing previous gateway`);
|
|
1223
|
+
yield this.gateway.close();
|
|
1224
|
+
}
|
|
910
1225
|
this.gateway = new BridgeGateway(this.storage, this.walletConnectionSource.bridgeUrl, sessionCrypto.sessionId, this.gatewayListener.bind(this), this.gatewayErrorsListener.bind(this));
|
|
911
|
-
return this.gateway.registerSession(
|
|
1226
|
+
return yield this.gateway.registerSession({
|
|
1227
|
+
openingDeadlineMS: options === null || options === void 0 ? void 0 : options.openingDeadlineMS,
|
|
1228
|
+
signal: abortController.signal
|
|
1229
|
+
});
|
|
912
1230
|
}
|
|
913
1231
|
});
|
|
914
1232
|
}
|
|
@@ -1171,14 +1489,24 @@ class InjectedProvider {
|
|
|
1171
1489
|
this.listeners.push(eventsCallback);
|
|
1172
1490
|
return () => (this.listeners = this.listeners.filter(listener => listener !== eventsCallback));
|
|
1173
1491
|
}
|
|
1174
|
-
sendRequest(request,
|
|
1492
|
+
sendRequest(request, optionsOrOnRequestSent) {
|
|
1493
|
+
var _a;
|
|
1175
1494
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1495
|
+
// TODO: remove deprecated method
|
|
1496
|
+
const options = {};
|
|
1497
|
+
if (typeof optionsOrOnRequestSent === 'function') {
|
|
1498
|
+
options.onRequestSent = optionsOrOnRequestSent;
|
|
1499
|
+
}
|
|
1500
|
+
else {
|
|
1501
|
+
options.onRequestSent = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.onRequestSent;
|
|
1502
|
+
options.signal = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.signal;
|
|
1503
|
+
}
|
|
1176
1504
|
const id = (yield this.connectionStorage.getNextRpcRequestId()).toString();
|
|
1177
1505
|
yield this.connectionStorage.increaseNextRpcRequestId();
|
|
1178
1506
|
logDebug('Send injected-bridge request:', Object.assign(Object.assign({}, request), { id }));
|
|
1179
1507
|
const result = this.injectedWallet.send(Object.assign(Object.assign({}, request), { id }));
|
|
1180
1508
|
result.then(response => logDebug('Wallet message received:', response));
|
|
1181
|
-
|
|
1509
|
+
(_a = options === null || options === void 0 ? void 0 : options.onRequestSent) === null || _a === void 0 ? void 0 : _a.call(options);
|
|
1182
1510
|
return result;
|
|
1183
1511
|
});
|
|
1184
1512
|
}
|
|
@@ -1195,7 +1523,7 @@ class InjectedProvider {
|
|
|
1195
1523
|
this.listeners.forEach(listener => listener(connectEvent));
|
|
1196
1524
|
}
|
|
1197
1525
|
catch (e) {
|
|
1198
|
-
logDebug(e);
|
|
1526
|
+
logDebug('Injected Provider connect error:', e);
|
|
1199
1527
|
const connectEventError = {
|
|
1200
1528
|
event: 'connect_error',
|
|
1201
1529
|
payload: {
|
|
@@ -1324,19 +1652,6 @@ const FALLBACK_WALLETS_LIST = [
|
|
|
1324
1652
|
],
|
|
1325
1653
|
platforms: ['ios', 'android', 'chrome', 'firefox', 'macos']
|
|
1326
1654
|
},
|
|
1327
|
-
{
|
|
1328
|
-
app_name: 'openmask',
|
|
1329
|
-
name: 'OpenMask',
|
|
1330
|
-
image: 'https://raw.githubusercontent.com/OpenProduct/openmask-extension/main/public/openmask-logo-288.png',
|
|
1331
|
-
about_url: 'https://www.openmask.app/',
|
|
1332
|
-
bridge: [
|
|
1333
|
-
{
|
|
1334
|
-
type: 'js',
|
|
1335
|
-
key: 'openmask'
|
|
1336
|
-
}
|
|
1337
|
-
],
|
|
1338
|
-
platforms: ['chrome']
|
|
1339
|
-
},
|
|
1340
1655
|
{
|
|
1341
1656
|
app_name: 'mytonwallet',
|
|
1342
1657
|
name: 'MyTonWallet',
|
|
@@ -1353,7 +1668,20 @@ const FALLBACK_WALLETS_LIST = [
|
|
|
1353
1668
|
url: 'https://tonconnectbridge.mytonwallet.org/bridge/'
|
|
1354
1669
|
}
|
|
1355
1670
|
],
|
|
1356
|
-
platforms: ['chrome', 'windows', 'macos', 'linux']
|
|
1671
|
+
platforms: ['chrome', 'windows', 'macos', 'linux', 'ios', 'android', 'firefox']
|
|
1672
|
+
},
|
|
1673
|
+
{
|
|
1674
|
+
app_name: 'openmask',
|
|
1675
|
+
name: 'OpenMask',
|
|
1676
|
+
image: 'https://raw.githubusercontent.com/OpenProduct/openmask-extension/main/public/openmask-logo-288.png',
|
|
1677
|
+
about_url: 'https://www.openmask.app/',
|
|
1678
|
+
bridge: [
|
|
1679
|
+
{
|
|
1680
|
+
type: 'js',
|
|
1681
|
+
key: 'openmask'
|
|
1682
|
+
}
|
|
1683
|
+
],
|
|
1684
|
+
platforms: ['chrome']
|
|
1357
1685
|
},
|
|
1358
1686
|
{
|
|
1359
1687
|
app_name: 'tonhub',
|
|
@@ -1373,19 +1701,6 @@ const FALLBACK_WALLETS_LIST = [
|
|
|
1373
1701
|
],
|
|
1374
1702
|
platforms: ['ios', 'android']
|
|
1375
1703
|
},
|
|
1376
|
-
{
|
|
1377
|
-
app_name: 'tonflow',
|
|
1378
|
-
name: 'TonFlow',
|
|
1379
|
-
image: 'https://tonflow.net/assets/images/tonflow_ico_192.png',
|
|
1380
|
-
about_url: 'https://tonflow.net',
|
|
1381
|
-
bridge: [
|
|
1382
|
-
{
|
|
1383
|
-
type: 'js',
|
|
1384
|
-
key: 'tonflow'
|
|
1385
|
-
}
|
|
1386
|
-
],
|
|
1387
|
-
platforms: ['chrome']
|
|
1388
|
-
},
|
|
1389
1704
|
{
|
|
1390
1705
|
app_name: 'dewallet',
|
|
1391
1706
|
name: 'DeWallet',
|
|
@@ -1692,59 +2007,119 @@ class TonConnect {
|
|
|
1692
2007
|
}
|
|
1693
2008
|
};
|
|
1694
2009
|
}
|
|
1695
|
-
connect(wallet,
|
|
1696
|
-
var _a;
|
|
2010
|
+
connect(wallet, requestOrOptions) {
|
|
2011
|
+
var _a, _b;
|
|
2012
|
+
// TODO: remove deprecated method
|
|
2013
|
+
const options = {};
|
|
2014
|
+
if (typeof requestOrOptions === 'object' && 'tonProof' in requestOrOptions) {
|
|
2015
|
+
options.request = requestOrOptions;
|
|
2016
|
+
}
|
|
2017
|
+
if (typeof requestOrOptions === 'object' &&
|
|
2018
|
+
('openingDeadlineMS' in requestOrOptions ||
|
|
2019
|
+
'signal' in requestOrOptions ||
|
|
2020
|
+
'request' in requestOrOptions)) {
|
|
2021
|
+
options.request = requestOrOptions === null || requestOrOptions === void 0 ? void 0 : requestOrOptions.request;
|
|
2022
|
+
options.openingDeadlineMS = requestOrOptions === null || requestOrOptions === void 0 ? void 0 : requestOrOptions.openingDeadlineMS;
|
|
2023
|
+
options.signal = requestOrOptions === null || requestOrOptions === void 0 ? void 0 : requestOrOptions.signal;
|
|
2024
|
+
}
|
|
1697
2025
|
if (this.connected) {
|
|
1698
2026
|
throw new WalletAlreadyConnectedError();
|
|
1699
2027
|
}
|
|
1700
|
-
|
|
2028
|
+
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
2029
|
+
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
|
2030
|
+
this.abortController = abortController;
|
|
2031
|
+
if (abortController.signal.aborted) {
|
|
2032
|
+
throw new TonConnectError('Connection was aborted');
|
|
2033
|
+
}
|
|
2034
|
+
(_b = this.provider) === null || _b === void 0 ? void 0 : _b.closeConnection();
|
|
1701
2035
|
this.provider = this.createProvider(wallet);
|
|
1702
|
-
return this.provider.connect(this.createConnectRequest(request)
|
|
2036
|
+
return this.provider.connect(this.createConnectRequest(options === null || options === void 0 ? void 0 : options.request), {
|
|
2037
|
+
openingDeadlineMS: options === null || options === void 0 ? void 0 : options.openingDeadlineMS,
|
|
2038
|
+
signal: abortController.signal
|
|
2039
|
+
});
|
|
1703
2040
|
}
|
|
1704
2041
|
/**
|
|
1705
2042
|
* Try to restore existing session and reconnect to the corresponding wallet. Call it immediately when your app is loaded.
|
|
1706
2043
|
*/
|
|
1707
|
-
restoreConnection() {
|
|
2044
|
+
restoreConnection(options) {
|
|
2045
|
+
var _a, _b;
|
|
1708
2046
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2047
|
+
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
2048
|
+
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
|
2049
|
+
this.abortController = abortController;
|
|
2050
|
+
if (abortController.signal.aborted) {
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
2053
|
+
// TODO: potentially race condition here
|
|
1709
2054
|
const [bridgeConnectionType, embeddedWallet] = yield Promise.all([
|
|
1710
2055
|
this.bridgeConnectionStorage.storedConnectionType(),
|
|
1711
2056
|
this.walletsList.getEmbeddedWallet()
|
|
1712
2057
|
]);
|
|
2058
|
+
if (abortController.signal.aborted) {
|
|
2059
|
+
return;
|
|
2060
|
+
}
|
|
2061
|
+
let provider = null;
|
|
1713
2062
|
try {
|
|
1714
2063
|
switch (bridgeConnectionType) {
|
|
1715
2064
|
case 'http':
|
|
1716
|
-
|
|
2065
|
+
provider = yield BridgeProvider.fromStorage(this.dappSettings.storage);
|
|
1717
2066
|
break;
|
|
1718
2067
|
case 'injected':
|
|
1719
|
-
|
|
2068
|
+
provider = yield InjectedProvider.fromStorage(this.dappSettings.storage);
|
|
1720
2069
|
break;
|
|
1721
2070
|
default:
|
|
1722
2071
|
if (embeddedWallet) {
|
|
1723
|
-
|
|
2072
|
+
provider = this.createProvider(embeddedWallet);
|
|
1724
2073
|
}
|
|
1725
2074
|
else {
|
|
1726
2075
|
return;
|
|
1727
2076
|
}
|
|
1728
2077
|
}
|
|
1729
2078
|
}
|
|
1730
|
-
catch (
|
|
2079
|
+
catch (_c) {
|
|
1731
2080
|
yield this.bridgeConnectionStorage.removeConnection();
|
|
1732
|
-
|
|
2081
|
+
provider === null || provider === void 0 ? void 0 : provider.closeConnection();
|
|
2082
|
+
provider = null;
|
|
1733
2083
|
return;
|
|
1734
2084
|
}
|
|
1735
|
-
|
|
1736
|
-
|
|
2085
|
+
if (abortController.signal.aborted) {
|
|
2086
|
+
provider === null || provider === void 0 ? void 0 : provider.closeConnection();
|
|
2087
|
+
return;
|
|
2088
|
+
}
|
|
2089
|
+
if (!provider) {
|
|
2090
|
+
logError('Provider is not restored');
|
|
2091
|
+
return;
|
|
2092
|
+
}
|
|
2093
|
+
(_b = this.provider) === null || _b === void 0 ? void 0 : _b.closeConnection();
|
|
2094
|
+
this.provider = provider;
|
|
2095
|
+
provider.listen(this.walletEventsListener.bind(this));
|
|
2096
|
+
return yield callForSuccess((_options) => __awaiter(this, void 0, void 0, function* () {
|
|
2097
|
+
return provider === null || provider === void 0 ? void 0 : provider.restoreConnection({
|
|
2098
|
+
openingDeadlineMS: options === null || options === void 0 ? void 0 : options.openingDeadlineMS,
|
|
2099
|
+
signal: _options.signal
|
|
2100
|
+
});
|
|
2101
|
+
}), {
|
|
2102
|
+
attempts: Number.MAX_SAFE_INTEGER,
|
|
2103
|
+
delayMs: 5000,
|
|
2104
|
+
signal: options === null || options === void 0 ? void 0 : options.signal
|
|
2105
|
+
});
|
|
1737
2106
|
});
|
|
1738
2107
|
}
|
|
1739
|
-
|
|
1740
|
-
* Asks connected wallet to sign and send the transaction.
|
|
1741
|
-
* @param transaction transaction to send.
|
|
1742
|
-
* @param onRequestSent (optional) will be called after the transaction is sent to the wallet.
|
|
1743
|
-
* @returns signed transaction boc that allows you to find the transaction in the blockchain.
|
|
1744
|
-
* If user rejects transaction, method will throw the corresponding error.
|
|
1745
|
-
*/
|
|
1746
|
-
sendTransaction(transaction, onRequestSent) {
|
|
2108
|
+
sendTransaction(transaction, optionsOrOnRequestSent) {
|
|
1747
2109
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2110
|
+
// TODO: remove deprecated method
|
|
2111
|
+
const options = {};
|
|
2112
|
+
if (typeof optionsOrOnRequestSent === 'function') {
|
|
2113
|
+
options.onRequestSent = optionsOrOnRequestSent;
|
|
2114
|
+
}
|
|
2115
|
+
else {
|
|
2116
|
+
options.onRequestSent = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.onRequestSent;
|
|
2117
|
+
options.signal = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.signal;
|
|
2118
|
+
}
|
|
2119
|
+
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
2120
|
+
if (abortController.signal.aborted) {
|
|
2121
|
+
throw new TonConnectError('Transaction sending was aborted');
|
|
2122
|
+
}
|
|
1748
2123
|
this.checkConnection();
|
|
1749
2124
|
checkSendTransactionSupport(this.wallet.device.features, {
|
|
1750
2125
|
requiredMessagesNumber: transaction.messages.length
|
|
@@ -1753,7 +2128,7 @@ class TonConnect {
|
|
|
1753
2128
|
const from = transaction.from || this.account.address;
|
|
1754
2129
|
const network = transaction.network || this.account.chain;
|
|
1755
2130
|
const response = yield this.provider.sendRequest(sendTransactionParser.convertToRpcRequest(Object.assign(Object.assign({}, tx), { valid_until: validUntil, from,
|
|
1756
|
-
network })), onRequestSent);
|
|
2131
|
+
network })), { onRequestSent: options.onRequestSent, signal: abortController.signal });
|
|
1757
2132
|
if (sendTransactionParser.isError(response)) {
|
|
1758
2133
|
return sendTransactionParser.parseAndThrowError(response);
|
|
1759
2134
|
}
|
|
@@ -1763,13 +2138,22 @@ class TonConnect {
|
|
|
1763
2138
|
/**
|
|
1764
2139
|
* Disconnect form thw connected wallet and drop current session.
|
|
1765
2140
|
*/
|
|
1766
|
-
disconnect() {
|
|
2141
|
+
disconnect(options) {
|
|
2142
|
+
var _a, _b;
|
|
1767
2143
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1768
2144
|
if (!this.connected) {
|
|
1769
2145
|
throw new WalletNotConnectedError();
|
|
1770
2146
|
}
|
|
1771
|
-
|
|
2147
|
+
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
2148
|
+
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
|
2149
|
+
this.abortController = abortController;
|
|
2150
|
+
if (abortController.signal.aborted) {
|
|
2151
|
+
throw new TonConnectError('Disconnect was aborted');
|
|
2152
|
+
}
|
|
1772
2153
|
this.onWalletDisconnected();
|
|
2154
|
+
yield ((_b = this.provider) === null || _b === void 0 ? void 0 : _b.disconnect({
|
|
2155
|
+
signal: abortController.signal
|
|
2156
|
+
}));
|
|
1773
2157
|
});
|
|
1774
2158
|
}
|
|
1775
2159
|
/**
|