@tonconnect/sdk 3.3.0-beta.0 → 3.3.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 +615 -180
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/esm/index.mjs +614 -181
- package/lib/esm/index.mjs.map +1 -1
- package/lib/types/index.d.ts +4 -0
- package/package.json +18 -22
package/lib/esm/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ export { CHAIN, CONNECT_EVENT_ERROR_CODES, CONNECT_ITEM_ERROR_CODES, SEND_TRANSA
|
|
|
3
3
|
import '@tonconnect/isomorphic-eventsource';
|
|
4
4
|
import '@tonconnect/isomorphic-fetch';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
/******************************************************************************
|
|
7
7
|
Copyright (c) Microsoft Corporation.
|
|
8
8
|
|
|
9
9
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
@@ -17,6 +17,8 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
17
17
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
18
18
|
PERFORMANCE OF THIS SOFTWARE.
|
|
19
19
|
***************************************************************************** */
|
|
20
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
function __rest(s, e) {
|
|
22
24
|
var t = {};
|
|
@@ -38,20 +40,25 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
38
40
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
39
41
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
40
42
|
});
|
|
41
|
-
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
46
|
+
var e = new Error(message);
|
|
47
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
48
|
+
};
|
|
42
49
|
|
|
43
50
|
/**
|
|
44
51
|
* Base class for TonConnect errors. You can check if the error was triggered by the @tonconnect/sdk using `err instanceof TonConnectError`.
|
|
45
52
|
*/
|
|
46
53
|
class TonConnectError extends Error {
|
|
54
|
+
get info() {
|
|
55
|
+
return '';
|
|
56
|
+
}
|
|
47
57
|
constructor(message, options) {
|
|
48
58
|
super(message, options);
|
|
49
59
|
this.message = `${TonConnectError.prefix} ${this.constructor.name}${this.info ? ': ' + this.info : ''}${message ? '\n' + message : ''}`;
|
|
50
60
|
Object.setPrototypeOf(this, TonConnectError.prototype);
|
|
51
61
|
}
|
|
52
|
-
get info() {
|
|
53
|
-
return '';
|
|
54
|
-
}
|
|
55
62
|
}
|
|
56
63
|
TonConnectError.prefix = '[TON_CONNECT_SDK_ERROR]';
|
|
57
64
|
|
|
@@ -442,8 +449,8 @@ function createAbortController(signal) {
|
|
|
442
449
|
* @param {CallForSuccessOptions} [options] - optional configuration options
|
|
443
450
|
*/
|
|
444
451
|
function callForSuccess(fn, options) {
|
|
445
|
-
var _a, _b;
|
|
446
452
|
return __awaiter(this, void 0, void 0, function* () {
|
|
453
|
+
var _a, _b;
|
|
447
454
|
const attempts = (_a = options === null || options === void 0 ? void 0 : options.attempts) !== null && _a !== void 0 ? _a : 10;
|
|
448
455
|
const delayMs = (_b = options === null || options === void 0 ? void 0 : options.delayMs) !== null && _b !== void 0 ? _b : 200;
|
|
449
456
|
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
@@ -614,6 +621,18 @@ function timeout(fn, options) {
|
|
|
614
621
|
}
|
|
615
622
|
|
|
616
623
|
class BridgeGateway {
|
|
624
|
+
get isReady() {
|
|
625
|
+
const eventSource = this.eventSource.current();
|
|
626
|
+
return (eventSource === null || eventSource === void 0 ? void 0 : eventSource.readyState) === EventSource.OPEN;
|
|
627
|
+
}
|
|
628
|
+
get isClosed() {
|
|
629
|
+
const eventSource = this.eventSource.current();
|
|
630
|
+
return (eventSource === null || eventSource === void 0 ? void 0 : eventSource.readyState) !== EventSource.OPEN;
|
|
631
|
+
}
|
|
632
|
+
get isConnecting() {
|
|
633
|
+
const eventSource = this.eventSource.current();
|
|
634
|
+
return (eventSource === null || eventSource === void 0 ? void 0 : eventSource.readyState) === EventSource.CONNECTING;
|
|
635
|
+
}
|
|
617
636
|
constructor(storage, bridgeUrl, sessionId, listener, errorsListener) {
|
|
618
637
|
this.bridgeUrl = bridgeUrl;
|
|
619
638
|
this.sessionId = sessionId;
|
|
@@ -642,26 +661,14 @@ class BridgeGateway {
|
|
|
642
661
|
}));
|
|
643
662
|
this.bridgeGatewayStorage = new HttpBridgeGatewayStorage(storage, bridgeUrl);
|
|
644
663
|
}
|
|
645
|
-
get isReady() {
|
|
646
|
-
const eventSource = this.eventSource.current();
|
|
647
|
-
return (eventSource === null || eventSource === void 0 ? void 0 : eventSource.readyState) === EventSource.OPEN;
|
|
648
|
-
}
|
|
649
|
-
get isClosed() {
|
|
650
|
-
const eventSource = this.eventSource.current();
|
|
651
|
-
return (eventSource === null || eventSource === void 0 ? void 0 : eventSource.readyState) !== EventSource.OPEN;
|
|
652
|
-
}
|
|
653
|
-
get isConnecting() {
|
|
654
|
-
const eventSource = this.eventSource.current();
|
|
655
|
-
return (eventSource === null || eventSource === void 0 ? void 0 : eventSource.readyState) === EventSource.CONNECTING;
|
|
656
|
-
}
|
|
657
664
|
registerSession(options) {
|
|
658
665
|
return __awaiter(this, void 0, void 0, function* () {
|
|
659
666
|
yield this.eventSource.create(options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.openingDeadlineMS);
|
|
660
667
|
});
|
|
661
668
|
}
|
|
662
669
|
send(message, receiver, topic, ttlOrOptions) {
|
|
663
|
-
var _a;
|
|
664
670
|
return __awaiter(this, void 0, void 0, function* () {
|
|
671
|
+
var _a;
|
|
665
672
|
// TODO: remove deprecated method
|
|
666
673
|
const options = {};
|
|
667
674
|
if (typeof ttlOrOptions === 'number') {
|
|
@@ -1010,6 +1017,16 @@ class BridgeConnectionStorage {
|
|
|
1010
1017
|
const PROTOCOL_VERSION = 2;
|
|
1011
1018
|
|
|
1012
1019
|
class BridgeProvider {
|
|
1020
|
+
static fromStorage(storage) {
|
|
1021
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1022
|
+
const bridgeConnectionStorage = new BridgeConnectionStorage(storage);
|
|
1023
|
+
const connection = yield bridgeConnectionStorage.getHttpConnection();
|
|
1024
|
+
if (isPendingConnectionHttp(connection)) {
|
|
1025
|
+
return new BridgeProvider(storage, connection.connectionSource);
|
|
1026
|
+
}
|
|
1027
|
+
return new BridgeProvider(storage, { bridgeUrl: connection.session.bridgeUrl });
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1013
1030
|
constructor(storage, walletConnectionSource) {
|
|
1014
1031
|
this.storage = storage;
|
|
1015
1032
|
this.walletConnectionSource = walletConnectionSource;
|
|
@@ -1024,16 +1041,6 @@ class BridgeProvider {
|
|
|
1024
1041
|
this.defaultRetryTimeoutMS = 2000;
|
|
1025
1042
|
this.connectionStorage = new BridgeConnectionStorage(storage);
|
|
1026
1043
|
}
|
|
1027
|
-
static fromStorage(storage) {
|
|
1028
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1029
|
-
const bridgeConnectionStorage = new BridgeConnectionStorage(storage);
|
|
1030
|
-
const connection = yield bridgeConnectionStorage.getHttpConnection();
|
|
1031
|
-
if (isPendingConnectionHttp(connection)) {
|
|
1032
|
-
return new BridgeProvider(storage, connection.connectionSource);
|
|
1033
|
-
}
|
|
1034
|
-
return new BridgeProvider(storage, { bridgeUrl: connection.session.bridgeUrl });
|
|
1035
|
-
});
|
|
1036
|
-
}
|
|
1037
1044
|
connect(message, options) {
|
|
1038
1045
|
var _a;
|
|
1039
1046
|
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
@@ -1076,8 +1083,8 @@ class BridgeProvider {
|
|
|
1076
1083
|
return this.generateUniversalLink(universalLink, message);
|
|
1077
1084
|
}
|
|
1078
1085
|
restoreConnection(options) {
|
|
1079
|
-
var _a, _b;
|
|
1080
1086
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1087
|
+
var _a, _b;
|
|
1081
1088
|
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
1082
1089
|
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
|
1083
1090
|
this.abortController = abortController;
|
|
@@ -1423,15 +1430,15 @@ function isJSBridgeWithMetadata(value) {
|
|
|
1423
1430
|
* Uses as a fallback for localStorage in Safari's private mode.
|
|
1424
1431
|
*/
|
|
1425
1432
|
class InMemoryStorage {
|
|
1426
|
-
constructor() {
|
|
1427
|
-
this.storage = {};
|
|
1428
|
-
}
|
|
1429
1433
|
static getInstance() {
|
|
1430
1434
|
if (!InMemoryStorage.instance) {
|
|
1431
1435
|
InMemoryStorage.instance = new InMemoryStorage();
|
|
1432
1436
|
}
|
|
1433
1437
|
return InMemoryStorage.instance;
|
|
1434
1438
|
}
|
|
1439
|
+
constructor() {
|
|
1440
|
+
this.storage = {};
|
|
1441
|
+
}
|
|
1435
1442
|
get length() {
|
|
1436
1443
|
return Object.keys(this.storage).length;
|
|
1437
1444
|
}
|
|
@@ -1526,19 +1533,6 @@ function isNodeJs() {
|
|
|
1526
1533
|
}
|
|
1527
1534
|
|
|
1528
1535
|
class InjectedProvider {
|
|
1529
|
-
constructor(storage, injectedWalletKey) {
|
|
1530
|
-
this.injectedWalletKey = injectedWalletKey;
|
|
1531
|
-
this.type = 'injected';
|
|
1532
|
-
this.unsubscribeCallback = null;
|
|
1533
|
-
this.listenSubscriptions = false;
|
|
1534
|
-
this.listeners = [];
|
|
1535
|
-
const window = InjectedProvider.window;
|
|
1536
|
-
if (!InjectedProvider.isWindowContainsWallet(window, injectedWalletKey)) {
|
|
1537
|
-
throw new WalletNotInjectedError();
|
|
1538
|
-
}
|
|
1539
|
-
this.connectionStorage = new BridgeConnectionStorage(storage);
|
|
1540
|
-
this.injectedWallet = window[injectedWalletKey].tonconnect;
|
|
1541
|
-
}
|
|
1542
1536
|
static fromStorage(storage) {
|
|
1543
1537
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1544
1538
|
const bridgeConnectionStorage = new BridgeConnectionStorage(storage);
|
|
@@ -1580,6 +1574,19 @@ class InjectedProvider {
|
|
|
1580
1574
|
typeof window[injectedWalletKey] === 'object' &&
|
|
1581
1575
|
'tonconnect' in window[injectedWalletKey]);
|
|
1582
1576
|
}
|
|
1577
|
+
constructor(storage, injectedWalletKey) {
|
|
1578
|
+
this.injectedWalletKey = injectedWalletKey;
|
|
1579
|
+
this.type = 'injected';
|
|
1580
|
+
this.unsubscribeCallback = null;
|
|
1581
|
+
this.listenSubscriptions = false;
|
|
1582
|
+
this.listeners = [];
|
|
1583
|
+
const window = InjectedProvider.window;
|
|
1584
|
+
if (!InjectedProvider.isWindowContainsWallet(window, injectedWalletKey)) {
|
|
1585
|
+
throw new WalletNotInjectedError();
|
|
1586
|
+
}
|
|
1587
|
+
this.connectionStorage = new BridgeConnectionStorage(storage);
|
|
1588
|
+
this.injectedWallet = window[injectedWalletKey].tonconnect;
|
|
1589
|
+
}
|
|
1583
1590
|
connect(message) {
|
|
1584
1591
|
this._connect(PROTOCOL_VERSION, message);
|
|
1585
1592
|
}
|
|
@@ -1641,8 +1648,8 @@ class InjectedProvider {
|
|
|
1641
1648
|
return () => (this.listeners = this.listeners.filter(listener => listener !== eventsCallback));
|
|
1642
1649
|
}
|
|
1643
1650
|
sendRequest(request, optionsOrOnRequestSent) {
|
|
1644
|
-
var _a;
|
|
1645
1651
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1652
|
+
var _a;
|
|
1646
1653
|
// TODO: remove deprecated method
|
|
1647
1654
|
const options = {};
|
|
1648
1655
|
if (typeof optionsOrOnRequestSent === 'function') {
|
|
@@ -2081,13 +2088,132 @@ const FALLBACK_WALLETS_LIST = [
|
|
|
2081
2088
|
}
|
|
2082
2089
|
];
|
|
2083
2090
|
|
|
2091
|
+
let qaModeEnabled = false;
|
|
2092
|
+
let bannerObserver = null;
|
|
2093
|
+
function enableQaMode() {
|
|
2094
|
+
qaModeEnabled = true;
|
|
2095
|
+
console.warn('🚨 QA Mode enabled - validation is disabled. This is unsafe for production!');
|
|
2096
|
+
showQaModeBanner();
|
|
2097
|
+
startBannerObserver();
|
|
2098
|
+
addQaModeStyles();
|
|
2099
|
+
}
|
|
2100
|
+
function isQaModeEnabled() {
|
|
2101
|
+
return qaModeEnabled;
|
|
2102
|
+
}
|
|
2103
|
+
function logValidationError(message) {
|
|
2104
|
+
if (isQaModeEnabled()) {
|
|
2105
|
+
console.error(`[QA Mode] Validation failed: ${message}`);
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
function showQaModeBanner() {
|
|
2109
|
+
if (typeof window === 'undefined')
|
|
2110
|
+
return;
|
|
2111
|
+
const existingBanner = document.getElementById('ton-connect-qa-banner');
|
|
2112
|
+
if (existingBanner)
|
|
2113
|
+
return;
|
|
2114
|
+
const banner = document.createElement('div');
|
|
2115
|
+
banner.id = 'ton-connect-qa-banner';
|
|
2116
|
+
banner.style.cssText = `
|
|
2117
|
+
position: fixed;
|
|
2118
|
+
top: 0;
|
|
2119
|
+
left: 0;
|
|
2120
|
+
right: 0;
|
|
2121
|
+
background: linear-gradient(90deg, #ff6b6b, #ff8e8e);
|
|
2122
|
+
color: white;
|
|
2123
|
+
padding: 12px 20px;
|
|
2124
|
+
text-align: center;
|
|
2125
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
2126
|
+
font-weight: 600;
|
|
2127
|
+
font-size: 14px;
|
|
2128
|
+
z-index: 999999;
|
|
2129
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
|
|
2130
|
+
animation: slideDown 0.3s ease-out;
|
|
2131
|
+
user-select: none;
|
|
2132
|
+
pointer-events: none;
|
|
2133
|
+
`;
|
|
2134
|
+
banner.innerHTML = `
|
|
2135
|
+
🚨 QA Mode Active - Validation Disabled (Unsafe for Production)
|
|
2136
|
+
`;
|
|
2137
|
+
// Add CSS animation
|
|
2138
|
+
const style = document.createElement('style');
|
|
2139
|
+
style.textContent = `
|
|
2140
|
+
@keyframes slideDown {
|
|
2141
|
+
from { transform: translateY(-100%); }
|
|
2142
|
+
to { transform: translateY(0); }
|
|
2143
|
+
}
|
|
2144
|
+
`;
|
|
2145
|
+
document.head.appendChild(style);
|
|
2146
|
+
document.body.appendChild(banner);
|
|
2147
|
+
addQaModeStyles();
|
|
2148
|
+
}
|
|
2149
|
+
function addQaModeStyles() {
|
|
2150
|
+
if (typeof window === 'undefined')
|
|
2151
|
+
return;
|
|
2152
|
+
const existingStyle = document.getElementById('ton-connect-qa-mode-styles');
|
|
2153
|
+
if (existingStyle)
|
|
2154
|
+
return;
|
|
2155
|
+
const style = document.createElement('style');
|
|
2156
|
+
style.id = 'ton-connect-qa-mode-styles';
|
|
2157
|
+
style.textContent = `
|
|
2158
|
+
body.qa-mode-active {
|
|
2159
|
+
padding-top: 48px !important;
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
body.qa-mode-active header {
|
|
2163
|
+
margin-top: 48px !important;
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
body.qa-mode-active .qa-mode-control {
|
|
2167
|
+
top: 128px !important;
|
|
2168
|
+
}
|
|
2169
|
+
`;
|
|
2170
|
+
document.head.appendChild(style);
|
|
2171
|
+
document.body.classList.add('qa-mode-active');
|
|
2172
|
+
}
|
|
2173
|
+
function startBannerObserver() {
|
|
2174
|
+
if (typeof window === 'undefined' || bannerObserver)
|
|
2175
|
+
return;
|
|
2176
|
+
bannerObserver = new MutationObserver((mutations) => {
|
|
2177
|
+
mutations.forEach((mutation) => {
|
|
2178
|
+
if (mutation.type === 'childList') {
|
|
2179
|
+
mutation.removedNodes.forEach((node) => {
|
|
2180
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
2181
|
+
const element = node;
|
|
2182
|
+
if (element.id === 'ton-connect-qa-banner' && qaModeEnabled) {
|
|
2183
|
+
console.warn('QA Mode banner was removed, restoring...');
|
|
2184
|
+
setTimeout(() => showQaModeBanner(), 100);
|
|
2185
|
+
}
|
|
2186
|
+
else if (element.id === 'ton-connect-qa-mode-styles' && qaModeEnabled) {
|
|
2187
|
+
console.warn('QA Mode styles were removed, restoring...');
|
|
2188
|
+
setTimeout(() => addQaModeStyles(), 100);
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
});
|
|
2192
|
+
}
|
|
2193
|
+
});
|
|
2194
|
+
});
|
|
2195
|
+
bannerObserver.observe(document.body, {
|
|
2196
|
+
childList: true,
|
|
2197
|
+
subtree: false
|
|
2198
|
+
});
|
|
2199
|
+
bannerObserver.observe(document.head, {
|
|
2200
|
+
childList: true,
|
|
2201
|
+
subtree: false
|
|
2202
|
+
});
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2084
2205
|
class WalletsListManager {
|
|
2085
2206
|
constructor(options) {
|
|
2086
2207
|
var _a;
|
|
2087
2208
|
this.walletsListCache = null;
|
|
2088
2209
|
this.walletsListCacheCreationTimestamp = null;
|
|
2089
|
-
|
|
2090
|
-
|
|
2210
|
+
if (isQaModeEnabled()) {
|
|
2211
|
+
this.walletsListSource = 'https://raw.githubusercontent.com/ton-connect/wallets-list-staging/refs/heads/main/wallets-v2.json';
|
|
2212
|
+
}
|
|
2213
|
+
else {
|
|
2214
|
+
this.walletsListSource =
|
|
2215
|
+
(_a = options === null || options === void 0 ? void 0 : options.walletsListSource) !== null && _a !== void 0 ? _a : 'https://raw.githubusercontent.com/ton-blockchain/wallets-list/main/wallets-v2.json';
|
|
2216
|
+
}
|
|
2091
2217
|
this.cacheTTLMs = options === null || options === void 0 ? void 0 : options.cacheTTLMs;
|
|
2092
2218
|
}
|
|
2093
2219
|
getWallets() {
|
|
@@ -2514,8 +2640,8 @@ class BrowserEventDispatcher {
|
|
|
2514
2640
|
* @returns A promise that resolves when the event has been dispatched.
|
|
2515
2641
|
*/
|
|
2516
2642
|
dispatchEvent(eventName, eventDetails) {
|
|
2517
|
-
var _a;
|
|
2518
2643
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2644
|
+
var _a;
|
|
2519
2645
|
const event = new CustomEvent(eventName, { detail: eventDetails });
|
|
2520
2646
|
(_a = this.window) === null || _a === void 0 ? void 0 : _a.dispatchEvent(event);
|
|
2521
2647
|
});
|
|
@@ -2528,8 +2654,8 @@ class BrowserEventDispatcher {
|
|
|
2528
2654
|
* @returns A function that removes the listener.
|
|
2529
2655
|
*/
|
|
2530
2656
|
addEventListener(eventName, listener, options) {
|
|
2531
|
-
var _a;
|
|
2532
2657
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2658
|
+
var _a;
|
|
2533
2659
|
(_a = this.window) === null || _a === void 0 ? void 0 : _a.addEventListener(eventName, listener, options);
|
|
2534
2660
|
return () => {
|
|
2535
2661
|
var _a;
|
|
@@ -2567,6 +2693,15 @@ class BrowserEventDispatcher {
|
|
|
2567
2693
|
* @internal
|
|
2568
2694
|
*/
|
|
2569
2695
|
class TonConnectTracker {
|
|
2696
|
+
/**
|
|
2697
|
+
* Version of the library.
|
|
2698
|
+
*/
|
|
2699
|
+
get version() {
|
|
2700
|
+
return createVersionInfo({
|
|
2701
|
+
ton_connect_sdk_lib: this.tonConnectSdkVersion,
|
|
2702
|
+
ton_connect_ui_lib: this.tonConnectUiVersion
|
|
2703
|
+
});
|
|
2704
|
+
}
|
|
2570
2705
|
constructor(options) {
|
|
2571
2706
|
var _a;
|
|
2572
2707
|
/**
|
|
@@ -2582,15 +2717,6 @@ class TonConnectTracker {
|
|
|
2582
2717
|
this.tonConnectSdkVersion = options.tonConnectSdkVersion;
|
|
2583
2718
|
this.init().catch();
|
|
2584
2719
|
}
|
|
2585
|
-
/**
|
|
2586
|
-
* Version of the library.
|
|
2587
|
-
*/
|
|
2588
|
-
get version() {
|
|
2589
|
-
return createVersionInfo({
|
|
2590
|
-
ton_connect_sdk_lib: this.tonConnectSdkVersion,
|
|
2591
|
-
ton_connect_ui_lib: this.tonConnectUiVersion
|
|
2592
|
-
});
|
|
2593
|
-
}
|
|
2594
2720
|
/**
|
|
2595
2721
|
* Called once when the tracker is created and request version other libraries.
|
|
2596
2722
|
*/
|
|
@@ -2791,36 +2917,377 @@ class TonConnectTracker {
|
|
|
2791
2917
|
}
|
|
2792
2918
|
}
|
|
2793
2919
|
|
|
2794
|
-
const tonConnectSdkVersion = "3.3.0-beta.
|
|
2920
|
+
const tonConnectSdkVersion = "3.3.0-beta.1";
|
|
2795
2921
|
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2922
|
+
const noBounceableTag = 0x51;
|
|
2923
|
+
const testOnlyTag = 0x80;
|
|
2924
|
+
/**
|
|
2925
|
+
* Converts raw TON address to no-bounceable user-friendly format. [See details]{@link https://ton.org/docs/learn/overviews/addresses#user-friendly-address}
|
|
2926
|
+
* @param hexAddress raw TON address formatted as "0:<hex string without 0x>".
|
|
2927
|
+
* @param [testOnly=false] convert address to test-only form. [See details]{@link https://ton.org/docs/learn/overviews/addresses#user-friendly-address}
|
|
2928
|
+
*/
|
|
2929
|
+
function toUserFriendlyAddress(hexAddress, testOnly = false) {
|
|
2930
|
+
const { wc, hex } = parseHexAddress(hexAddress);
|
|
2931
|
+
let tag = noBounceableTag;
|
|
2932
|
+
if (testOnly) {
|
|
2933
|
+
tag |= testOnlyTag;
|
|
2934
|
+
}
|
|
2935
|
+
const addr = new Int8Array(34);
|
|
2936
|
+
addr[0] = tag;
|
|
2937
|
+
addr[1] = wc;
|
|
2938
|
+
addr.set(hex, 2);
|
|
2939
|
+
const addressWithChecksum = new Uint8Array(36);
|
|
2940
|
+
addressWithChecksum.set(addr);
|
|
2941
|
+
addressWithChecksum.set(crc16(addr), 34);
|
|
2942
|
+
let addressBase64 = Base64.encode(addressWithChecksum);
|
|
2943
|
+
return addressBase64.replace(/\+/g, '-').replace(/\//g, '_');
|
|
2944
|
+
}
|
|
2945
|
+
/**
|
|
2946
|
+
* Validates if the address is in user-friendly format by attempting to parse it.
|
|
2947
|
+
* @param address address to validate
|
|
2948
|
+
* @returns true if the address is valid user-friendly format, false otherwise
|
|
2949
|
+
*/
|
|
2950
|
+
function isValidUserFriendlyAddress(address) {
|
|
2951
|
+
try {
|
|
2952
|
+
parseUserFriendlyAddress(address);
|
|
2953
|
+
return true;
|
|
2954
|
+
}
|
|
2955
|
+
catch (_a) {
|
|
2956
|
+
return false;
|
|
2957
|
+
}
|
|
2958
|
+
}
|
|
2959
|
+
/**
|
|
2960
|
+
* Validates if the address is in raw hex format (e.g., "0:1234..." or "-1:1234...").
|
|
2961
|
+
* @param address address to validate
|
|
2962
|
+
* @returns true if the address is valid raw format, false otherwise
|
|
2963
|
+
*/
|
|
2964
|
+
function isValidRawAddress(address) {
|
|
2965
|
+
try {
|
|
2966
|
+
parseHexAddress(address);
|
|
2967
|
+
return true;
|
|
2968
|
+
}
|
|
2969
|
+
catch (_a) {
|
|
2970
|
+
return false;
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
/**
|
|
2974
|
+
* Parses user-friendly address and returns its components.
|
|
2975
|
+
* @param address user-friendly address
|
|
2976
|
+
* @returns parsed address components
|
|
2977
|
+
*/
|
|
2978
|
+
function parseUserFriendlyAddress(address) {
|
|
2979
|
+
const base64 = address.replace(/-/g, '+').replace(/_/g, '/');
|
|
2980
|
+
let decoded;
|
|
2981
|
+
try {
|
|
2982
|
+
decoded = Base64.decode(base64).toUint8Array();
|
|
2983
|
+
}
|
|
2984
|
+
catch (_a) {
|
|
2985
|
+
throw new WrongAddressError(`Invalid base64 encoding in address: ${address}`);
|
|
2986
|
+
}
|
|
2987
|
+
if (decoded.length !== 36) {
|
|
2988
|
+
throw new WrongAddressError(`Invalid address length: ${address}`);
|
|
2989
|
+
}
|
|
2990
|
+
const addr = decoded.slice(0, 34);
|
|
2991
|
+
const checksum = decoded.slice(34);
|
|
2992
|
+
const calculatedChecksum = crc16(addr);
|
|
2993
|
+
if (!checksum.every((byte, i) => byte === calculatedChecksum[i])) {
|
|
2994
|
+
throw new WrongAddressError(`Invalid checksum in address: ${address}`);
|
|
2995
|
+
}
|
|
2996
|
+
const tag = addr[0];
|
|
2997
|
+
const wc = addr[1];
|
|
2998
|
+
const hex = addr.slice(2);
|
|
2999
|
+
if (wc !== 0 && wc !== -1) {
|
|
3000
|
+
throw new WrongAddressError(`Invalid workchain: ${wc}`);
|
|
3001
|
+
}
|
|
3002
|
+
const testOnly = (tag & testOnlyTag) !== 0;
|
|
3003
|
+
const isBounceable = (tag & 0x40) !== 0;
|
|
3004
|
+
return {
|
|
3005
|
+
wc,
|
|
3006
|
+
hex: Array.from(hex).map(b => b.toString(16).padStart(2, '0')).join(''),
|
|
3007
|
+
testOnly,
|
|
3008
|
+
isBounceable
|
|
3009
|
+
};
|
|
3010
|
+
}
|
|
3011
|
+
function parseHexAddress(hexAddress) {
|
|
3012
|
+
if (!hexAddress.includes(':')) {
|
|
3013
|
+
throw new WrongAddressError(`Wrong address ${hexAddress}. Address must include ":".`);
|
|
3014
|
+
}
|
|
3015
|
+
const parts = hexAddress.split(':');
|
|
3016
|
+
if (parts.length !== 2) {
|
|
3017
|
+
throw new WrongAddressError(`Wrong address ${hexAddress}. Address must include ":" only once.`);
|
|
3018
|
+
}
|
|
3019
|
+
const wc = parseInt(parts[0]);
|
|
3020
|
+
if (wc !== 0 && wc !== -1) {
|
|
3021
|
+
throw new WrongAddressError(`Wrong address ${hexAddress}. WC must be eq 0 or -1, but ${wc} received.`);
|
|
3022
|
+
}
|
|
3023
|
+
const hex = parts[1];
|
|
3024
|
+
if ((hex === null || hex === void 0 ? void 0 : hex.length) !== 64) {
|
|
3025
|
+
throw new WrongAddressError(`Wrong address ${hexAddress}. Hex part must be 64bytes length, but ${hex === null || hex === void 0 ? void 0 : hex.length} received.`);
|
|
3026
|
+
}
|
|
3027
|
+
return {
|
|
3028
|
+
wc,
|
|
3029
|
+
hex: hexToBytes(hex)
|
|
3030
|
+
};
|
|
3031
|
+
}
|
|
3032
|
+
function crc16(data) {
|
|
3033
|
+
const poly = 0x1021;
|
|
3034
|
+
let reg = 0;
|
|
3035
|
+
const message = new Uint8Array(data.length + 2);
|
|
3036
|
+
message.set(data);
|
|
3037
|
+
for (let byte of message) {
|
|
3038
|
+
let mask = 0x80;
|
|
3039
|
+
while (mask > 0) {
|
|
3040
|
+
reg <<= 1;
|
|
3041
|
+
if (byte & mask) {
|
|
3042
|
+
reg += 1;
|
|
3043
|
+
}
|
|
3044
|
+
mask >>= 1;
|
|
3045
|
+
if (reg > 0xffff) {
|
|
3046
|
+
reg &= 0xffff;
|
|
3047
|
+
reg ^= poly;
|
|
3048
|
+
}
|
|
2818
3049
|
}
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
3050
|
+
}
|
|
3051
|
+
return new Uint8Array([Math.floor(reg / 256), reg % 256]);
|
|
3052
|
+
}
|
|
3053
|
+
const toByteMap = {};
|
|
3054
|
+
for (let ord = 0; ord <= 0xff; ord++) {
|
|
3055
|
+
let s = ord.toString(16);
|
|
3056
|
+
if (s.length < 2) {
|
|
3057
|
+
s = '0' + s;
|
|
3058
|
+
}
|
|
3059
|
+
toByteMap[s] = ord;
|
|
3060
|
+
}
|
|
3061
|
+
function hexToBytes(hex) {
|
|
3062
|
+
hex = hex.toLowerCase();
|
|
3063
|
+
const length2 = hex.length;
|
|
3064
|
+
if (length2 % 2 !== 0) {
|
|
3065
|
+
throw new ParseHexError('Hex string must have length a multiple of 2: ' + hex);
|
|
3066
|
+
}
|
|
3067
|
+
const length = length2 / 2;
|
|
3068
|
+
const result = new Uint8Array(length);
|
|
3069
|
+
for (let i = 0; i < length; i++) {
|
|
3070
|
+
const doubled = i * 2;
|
|
3071
|
+
const hexSubstring = hex.substring(doubled, doubled + 2);
|
|
3072
|
+
if (!toByteMap.hasOwnProperty(hexSubstring)) {
|
|
3073
|
+
throw new ParseHexError('Invalid hex character: ' + hexSubstring);
|
|
3074
|
+
}
|
|
3075
|
+
result[i] = toByteMap[hexSubstring];
|
|
3076
|
+
}
|
|
3077
|
+
return result;
|
|
3078
|
+
}
|
|
3079
|
+
|
|
3080
|
+
const BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
3081
|
+
const BOC_PREFIX = 'te6cc';
|
|
3082
|
+
const INTEGER_REGEX = /^-?\d+$/;
|
|
3083
|
+
const POSITIVE_INTEGER_REGEX = /^\d+$/;
|
|
3084
|
+
function isValidNumber(value) {
|
|
3085
|
+
return typeof value === 'number' && !isNaN(value);
|
|
3086
|
+
}
|
|
3087
|
+
function isValidString(value) {
|
|
3088
|
+
return typeof value === 'string' && value.length > 0;
|
|
3089
|
+
}
|
|
3090
|
+
function isValidBoc(value) {
|
|
3091
|
+
return typeof value === 'string' && BASE64_REGEX.test(value) && value.startsWith(BOC_PREFIX);
|
|
3092
|
+
}
|
|
3093
|
+
function isValidObject(value) {
|
|
3094
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3095
|
+
}
|
|
3096
|
+
function isValidArray(value) {
|
|
3097
|
+
return Array.isArray(value);
|
|
3098
|
+
}
|
|
3099
|
+
function hasExtraProperties(obj, allowedKeys) {
|
|
3100
|
+
return Object.keys(obj).some(key => !allowedKeys.includes(key));
|
|
3101
|
+
}
|
|
3102
|
+
function validateSendTransactionRequest(data) {
|
|
3103
|
+
console.log('[Validation Debug] validateSendTransactionRequest called');
|
|
3104
|
+
console.log('[Validation Debug] isQaModeEnabled():', isQaModeEnabled());
|
|
3105
|
+
if (!isValidObject(data)) {
|
|
3106
|
+
const error = "Request must be an object";
|
|
3107
|
+
logValidationError(error);
|
|
3108
|
+
const shouldReturnNull = isQaModeEnabled();
|
|
3109
|
+
console.log('[Validation Debug] Should return null:', shouldReturnNull);
|
|
3110
|
+
return shouldReturnNull ? null : error;
|
|
3111
|
+
}
|
|
3112
|
+
const allowedKeys = ['validUntil', 'network', 'from', 'messages'];
|
|
3113
|
+
if (hasExtraProperties(data, allowedKeys)) {
|
|
3114
|
+
const error = "Request contains extra properties";
|
|
3115
|
+
logValidationError(error);
|
|
3116
|
+
return isQaModeEnabled() ? null : error;
|
|
3117
|
+
}
|
|
3118
|
+
if (!isValidNumber(data.validUntil)) {
|
|
3119
|
+
const error = "Incorrect 'validUntil'";
|
|
3120
|
+
logValidationError(error);
|
|
3121
|
+
return isQaModeEnabled() ? null : error;
|
|
3122
|
+
}
|
|
3123
|
+
const now = Math.floor(Date.now() / 1000);
|
|
3124
|
+
const fiveMinutesFromNow = now + 300;
|
|
3125
|
+
if (data.validUntil > fiveMinutesFromNow) {
|
|
3126
|
+
console.warn(`validUntil (${data.validUntil}) is more than 5 minutes from now (${now})`);
|
|
3127
|
+
}
|
|
3128
|
+
if (data.network !== undefined) {
|
|
3129
|
+
if (!isValidString(data.network) || !/^[\d-]+$/.test(data.network)) {
|
|
3130
|
+
const error = "Invalid 'network' format";
|
|
3131
|
+
logValidationError(error);
|
|
3132
|
+
return isQaModeEnabled() ? null : error;
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
if (data.from !== undefined) {
|
|
3136
|
+
if (!isValidString(data.from) || !isValidRawAddress(data.from)) {
|
|
3137
|
+
const error = "Invalid 'from' address format";
|
|
3138
|
+
logValidationError(error);
|
|
3139
|
+
return isQaModeEnabled() ? null : error;
|
|
2822
3140
|
}
|
|
2823
3141
|
}
|
|
3142
|
+
if (!isValidArray(data.messages) || data.messages.length === 0) {
|
|
3143
|
+
const error = "'messages' is required";
|
|
3144
|
+
logValidationError(error);
|
|
3145
|
+
return isQaModeEnabled() ? null : error;
|
|
3146
|
+
}
|
|
3147
|
+
for (let i = 0; i < data.messages.length; i++) {
|
|
3148
|
+
const message = data.messages[i];
|
|
3149
|
+
const messageError = validateTransactionMessage(message, i);
|
|
3150
|
+
if (messageError) {
|
|
3151
|
+
return messageError;
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
return null;
|
|
3155
|
+
}
|
|
3156
|
+
function validateTransactionMessage(message, index) {
|
|
3157
|
+
if (!isValidObject(message)) {
|
|
3158
|
+
return `Message at index ${index} must be an object`;
|
|
3159
|
+
}
|
|
3160
|
+
const allowedKeys = ['address', 'amount', 'stateInit', 'payload', 'extraCurrency'];
|
|
3161
|
+
if (hasExtraProperties(message, allowedKeys)) {
|
|
3162
|
+
return `Message at index ${index} contains extra properties`;
|
|
3163
|
+
}
|
|
3164
|
+
if (!isValidString(message.address)) {
|
|
3165
|
+
return `'address' is required in message at index ${index}`;
|
|
3166
|
+
}
|
|
3167
|
+
if (!isValidUserFriendlyAddress(message.address)) {
|
|
3168
|
+
return `Wrong 'address' format in message at index ${index}`;
|
|
3169
|
+
}
|
|
3170
|
+
if (!isValidString(message.amount)) {
|
|
3171
|
+
return `'amount' is required in message at index ${index}`;
|
|
3172
|
+
}
|
|
3173
|
+
if (!/^[0-9]+$/.test(message.amount)) {
|
|
3174
|
+
return `Incorrect 'amount' in message at index ${index}`;
|
|
3175
|
+
}
|
|
3176
|
+
if (message.stateInit !== undefined) {
|
|
3177
|
+
if (!isValidString(message.stateInit) || !isValidBoc(message.stateInit)) {
|
|
3178
|
+
return `Invalid 'stateInit' in message at index ${index}`;
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
if (message.payload !== undefined) {
|
|
3182
|
+
if (!isValidString(message.payload) || !isValidBoc(message.payload)) {
|
|
3183
|
+
return `Invalid 'payload' in message at index ${index}`;
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
if (message.extraCurrency !== undefined) {
|
|
3187
|
+
if (!isValidObject(message.extraCurrency)) {
|
|
3188
|
+
return `Invalid 'extraCurrency' in message at index ${index}`;
|
|
3189
|
+
}
|
|
3190
|
+
for (const [key, value] of Object.entries(message.extraCurrency)) {
|
|
3191
|
+
if (!INTEGER_REGEX.test(key) || typeof value !== 'string' || !POSITIVE_INTEGER_REGEX.test(value)) {
|
|
3192
|
+
return `Invalid 'extraCurrency' format in message at index ${index}`;
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
return null;
|
|
3197
|
+
}
|
|
3198
|
+
function validateConnectAdditionalRequest(data) {
|
|
3199
|
+
if (!isValidObject(data)) {
|
|
3200
|
+
return "Request must be an object";
|
|
3201
|
+
}
|
|
3202
|
+
const allowedKeys = ['tonProof'];
|
|
3203
|
+
if (hasExtraProperties(data, allowedKeys)) {
|
|
3204
|
+
return "Request contains extra properties";
|
|
3205
|
+
}
|
|
3206
|
+
if (data.tonProof !== undefined && !isValidString(data.tonProof)) {
|
|
3207
|
+
return "Invalid 'tonProof'";
|
|
3208
|
+
}
|
|
3209
|
+
return null;
|
|
3210
|
+
}
|
|
3211
|
+
function validateSignDataPayload(data) {
|
|
3212
|
+
if (!isValidObject(data)) {
|
|
3213
|
+
return "Payload must be an object";
|
|
3214
|
+
}
|
|
3215
|
+
if (!isValidString(data.type)) {
|
|
3216
|
+
return "'type' is required";
|
|
3217
|
+
}
|
|
3218
|
+
switch (data.type) {
|
|
3219
|
+
case 'text':
|
|
3220
|
+
return validateSignDataPayloadText(data);
|
|
3221
|
+
case 'binary':
|
|
3222
|
+
return validateSignDataPayloadBinary(data);
|
|
3223
|
+
case 'cell':
|
|
3224
|
+
return validateSignDataPayloadCell(data);
|
|
3225
|
+
default:
|
|
3226
|
+
return "Invalid 'type' value";
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
function validateSignDataPayloadText(data) {
|
|
3230
|
+
const allowedKeys = ['type', 'text', 'network', 'from'];
|
|
3231
|
+
if (hasExtraProperties(data, allowedKeys)) {
|
|
3232
|
+
return "Text payload contains extra properties";
|
|
3233
|
+
}
|
|
3234
|
+
if (!isValidString(data.text)) {
|
|
3235
|
+
return "'text' is required";
|
|
3236
|
+
}
|
|
3237
|
+
if (data.network !== undefined) {
|
|
3238
|
+
if (!isValidString(data.network) || !/^\d+$/.test(data.network)) {
|
|
3239
|
+
return "Invalid 'network' format";
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
if (data.from !== undefined && !isValidString(data.from)) {
|
|
3243
|
+
return "Invalid 'from'";
|
|
3244
|
+
}
|
|
3245
|
+
return null;
|
|
3246
|
+
}
|
|
3247
|
+
function validateSignDataPayloadBinary(data) {
|
|
3248
|
+
const allowedKeys = ['type', 'bytes', 'network', 'from'];
|
|
3249
|
+
if (hasExtraProperties(data, allowedKeys)) {
|
|
3250
|
+
return "Binary payload contains extra properties";
|
|
3251
|
+
}
|
|
3252
|
+
if (!isValidString(data.bytes)) {
|
|
3253
|
+
return "'bytes' is required";
|
|
3254
|
+
}
|
|
3255
|
+
if (data.network !== undefined) {
|
|
3256
|
+
if (!isValidString(data.network) || !/^\d+$/.test(data.network)) {
|
|
3257
|
+
return "Invalid 'network' format";
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
if (data.from !== undefined && !isValidString(data.from)) {
|
|
3261
|
+
return "Invalid 'from'";
|
|
3262
|
+
}
|
|
3263
|
+
return null;
|
|
3264
|
+
}
|
|
3265
|
+
function validateSignDataPayloadCell(data) {
|
|
3266
|
+
const allowedKeys = ['type', 'schema', 'cell', 'network', 'from'];
|
|
3267
|
+
if (hasExtraProperties(data, allowedKeys)) {
|
|
3268
|
+
return "Cell payload contains extra properties";
|
|
3269
|
+
}
|
|
3270
|
+
if (!isValidString(data.schema)) {
|
|
3271
|
+
return "'schema' is required";
|
|
3272
|
+
}
|
|
3273
|
+
if (!isValidString(data.cell)) {
|
|
3274
|
+
return "'cell' is required";
|
|
3275
|
+
}
|
|
3276
|
+
if (!isValidBoc(data.cell)) {
|
|
3277
|
+
return "Invalid 'cell' format (must be valid base64)";
|
|
3278
|
+
}
|
|
3279
|
+
if (data.network !== undefined) {
|
|
3280
|
+
if (!isValidString(data.network) || !/^\d+$/.test(data.network)) {
|
|
3281
|
+
return "Invalid 'network' format";
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
if (data.from !== undefined && !isValidString(data.from)) {
|
|
3285
|
+
return "Invalid 'from'";
|
|
3286
|
+
}
|
|
3287
|
+
return null;
|
|
3288
|
+
}
|
|
3289
|
+
|
|
3290
|
+
class TonConnect {
|
|
2824
3291
|
/**
|
|
2825
3292
|
* Returns available wallets list.
|
|
2826
3293
|
*/
|
|
@@ -2850,6 +3317,33 @@ class TonConnect {
|
|
|
2850
3317
|
this._wallet = value;
|
|
2851
3318
|
this.statusChangeSubscriptions.forEach(callback => callback(this._wallet));
|
|
2852
3319
|
}
|
|
3320
|
+
constructor(options) {
|
|
3321
|
+
this.walletsList = new WalletsListManager();
|
|
3322
|
+
this._wallet = null;
|
|
3323
|
+
this.provider = null;
|
|
3324
|
+
this.statusChangeSubscriptions = [];
|
|
3325
|
+
this.statusChangeErrorSubscriptions = [];
|
|
3326
|
+
this.dappSettings = {
|
|
3327
|
+
manifestUrl: (options === null || options === void 0 ? void 0 : options.manifestUrl) || getWebPageManifest(),
|
|
3328
|
+
storage: (options === null || options === void 0 ? void 0 : options.storage) || new DefaultStorage()
|
|
3329
|
+
};
|
|
3330
|
+
this.walletsRequiredFeatures = options === null || options === void 0 ? void 0 : options.walletsRequiredFeatures;
|
|
3331
|
+
this.walletsList = new WalletsListManager({
|
|
3332
|
+
walletsListSource: options === null || options === void 0 ? void 0 : options.walletsListSource,
|
|
3333
|
+
cacheTTLMs: options === null || options === void 0 ? void 0 : options.walletsListCacheTTLMs
|
|
3334
|
+
});
|
|
3335
|
+
this.tracker = new TonConnectTracker({
|
|
3336
|
+
eventDispatcher: options === null || options === void 0 ? void 0 : options.eventDispatcher,
|
|
3337
|
+
tonConnectSdkVersion: tonConnectSdkVersion
|
|
3338
|
+
});
|
|
3339
|
+
if (!this.dappSettings.manifestUrl) {
|
|
3340
|
+
throw new DappMetadataError('Dapp tonconnect-manifest.json must be specified if window.location.origin is undefined. See more https://github.com/ton-connect/docs/blob/main/requests-responses.md#app-manifest');
|
|
3341
|
+
}
|
|
3342
|
+
this.bridgeConnectionStorage = new BridgeConnectionStorage(this.dappSettings.storage);
|
|
3343
|
+
if (!(options === null || options === void 0 ? void 0 : options.disableAutoPauseConnection)) {
|
|
3344
|
+
this.addWindowFocusAndBlurSubscriptions();
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
2853
3347
|
/**
|
|
2854
3348
|
* Returns available wallets list.
|
|
2855
3349
|
*/
|
|
@@ -2889,6 +3383,17 @@ class TonConnect {
|
|
|
2889
3383
|
options.openingDeadlineMS = requestOrOptions === null || requestOrOptions === void 0 ? void 0 : requestOrOptions.openingDeadlineMS;
|
|
2890
3384
|
options.signal = requestOrOptions === null || requestOrOptions === void 0 ? void 0 : requestOrOptions.signal;
|
|
2891
3385
|
}
|
|
3386
|
+
if (options.request) {
|
|
3387
|
+
const validationError = validateConnectAdditionalRequest(options.request);
|
|
3388
|
+
if (validationError) {
|
|
3389
|
+
if (isQaModeEnabled()) {
|
|
3390
|
+
console.error('ConnectAdditionalRequest validation failed: ' + validationError);
|
|
3391
|
+
}
|
|
3392
|
+
else {
|
|
3393
|
+
throw new TonConnectError('ConnectAdditionalRequest validation failed: ' + validationError);
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
2892
3397
|
if (this.connected) {
|
|
2893
3398
|
throw new WalletAlreadyConnectedError();
|
|
2894
3399
|
}
|
|
@@ -2915,8 +3420,8 @@ class TonConnect {
|
|
|
2915
3420
|
* Try to restore existing session and reconnect to the corresponding wallet. Call it immediately when your app is loaded.
|
|
2916
3421
|
*/
|
|
2917
3422
|
restoreConnection(options) {
|
|
2918
|
-
var _a, _b;
|
|
2919
3423
|
return __awaiter(this, void 0, void 0, function* () {
|
|
3424
|
+
var _a, _b;
|
|
2920
3425
|
this.tracker.trackConnectionRestoringStarted();
|
|
2921
3426
|
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
2922
3427
|
(_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
|
@@ -3011,6 +3516,16 @@ class TonConnect {
|
|
|
3011
3516
|
options.onRequestSent = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.onRequestSent;
|
|
3012
3517
|
options.signal = optionsOrOnRequestSent === null || optionsOrOnRequestSent === void 0 ? void 0 : optionsOrOnRequestSent.signal;
|
|
3013
3518
|
}
|
|
3519
|
+
// Validate transaction
|
|
3520
|
+
const validationError = validateSendTransactionRequest(transaction);
|
|
3521
|
+
if (validationError) {
|
|
3522
|
+
if (isQaModeEnabled()) {
|
|
3523
|
+
console.error('SendTransactionRequest validation failed: ' + validationError);
|
|
3524
|
+
}
|
|
3525
|
+
else {
|
|
3526
|
+
throw new TonConnectError('SendTransactionRequest validation failed: ' + validationError);
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3014
3529
|
const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
|
|
3015
3530
|
if (abortController.signal.aborted) {
|
|
3016
3531
|
throw new TonConnectError('Transaction sending was aborted');
|
|
@@ -3046,6 +3561,16 @@ class TonConnect {
|
|
|
3046
3561
|
if (abortController.signal.aborted) {
|
|
3047
3562
|
throw new TonConnectError('data sending was aborted');
|
|
3048
3563
|
}
|
|
3564
|
+
// Validate sign data
|
|
3565
|
+
const validationError = validateSignDataPayload(data);
|
|
3566
|
+
if (validationError) {
|
|
3567
|
+
if (isQaModeEnabled()) {
|
|
3568
|
+
console.error('SignDataPayload validation failed: ' + validationError);
|
|
3569
|
+
}
|
|
3570
|
+
else {
|
|
3571
|
+
throw new TonConnectError('SignDataPayload validation failed: ' + validationError);
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3049
3574
|
this.checkConnection();
|
|
3050
3575
|
checkSignDataSupport(this.wallet.device.features, { requiredTypes: [data.type] });
|
|
3051
3576
|
this.tracker.trackDataSentForSignature(this.wallet, data);
|
|
@@ -3066,8 +3591,8 @@ class TonConnect {
|
|
|
3066
3591
|
* Disconnect form thw connected wallet and drop current session.
|
|
3067
3592
|
*/
|
|
3068
3593
|
disconnect(options) {
|
|
3069
|
-
var _a;
|
|
3070
3594
|
return __awaiter(this, void 0, void 0, function* () {
|
|
3595
|
+
var _a;
|
|
3071
3596
|
if (!this.connected) {
|
|
3072
3597
|
throw new WalletNotConnectedError();
|
|
3073
3598
|
}
|
|
@@ -3263,97 +3788,5 @@ TonConnect.isWalletInjected = (walletJSKey) => InjectedProvider.isWalletInjected
|
|
|
3263
3788
|
*/
|
|
3264
3789
|
TonConnect.isInsideWalletBrowser = (walletJSKey) => InjectedProvider.isInsideWalletBrowser(walletJSKey);
|
|
3265
3790
|
|
|
3266
|
-
|
|
3267
|
-
const testOnlyTag = 0x80;
|
|
3268
|
-
/**
|
|
3269
|
-
* Converts raw TON address to no-bounceable user-friendly format. [See details]{@link https://ton.org/docs/learn/overviews/addresses#user-friendly-address}
|
|
3270
|
-
* @param hexAddress raw TON address formatted as "0:<hex string without 0x>".
|
|
3271
|
-
* @param [testOnly=false] convert address to test-only form. [See details]{@link https://ton.org/docs/learn/overviews/addresses#user-friendly-address}
|
|
3272
|
-
*/
|
|
3273
|
-
function toUserFriendlyAddress(hexAddress, testOnly = false) {
|
|
3274
|
-
const { wc, hex } = parseHexAddress(hexAddress);
|
|
3275
|
-
let tag = noBounceableTag;
|
|
3276
|
-
if (testOnly) {
|
|
3277
|
-
tag |= testOnlyTag;
|
|
3278
|
-
}
|
|
3279
|
-
const addr = new Int8Array(34);
|
|
3280
|
-
addr[0] = tag;
|
|
3281
|
-
addr[1] = wc;
|
|
3282
|
-
addr.set(hex, 2);
|
|
3283
|
-
const addressWithChecksum = new Uint8Array(36);
|
|
3284
|
-
addressWithChecksum.set(addr);
|
|
3285
|
-
addressWithChecksum.set(crc16(addr), 34);
|
|
3286
|
-
let addressBase64 = Base64.encode(addressWithChecksum);
|
|
3287
|
-
return addressBase64.replace(/\+/g, '-').replace(/\//g, '_');
|
|
3288
|
-
}
|
|
3289
|
-
function parseHexAddress(hexAddress) {
|
|
3290
|
-
if (!hexAddress.includes(':')) {
|
|
3291
|
-
throw new WrongAddressError(`Wrong address ${hexAddress}. Address must include ":".`);
|
|
3292
|
-
}
|
|
3293
|
-
const parts = hexAddress.split(':');
|
|
3294
|
-
if (parts.length !== 2) {
|
|
3295
|
-
throw new WrongAddressError(`Wrong address ${hexAddress}. Address must include ":" only once.`);
|
|
3296
|
-
}
|
|
3297
|
-
const wc = parseInt(parts[0]);
|
|
3298
|
-
if (wc !== 0 && wc !== -1) {
|
|
3299
|
-
throw new WrongAddressError(`Wrong address ${hexAddress}. WC must be eq 0 or -1, but ${wc} received.`);
|
|
3300
|
-
}
|
|
3301
|
-
const hex = parts[1];
|
|
3302
|
-
if ((hex === null || hex === void 0 ? void 0 : hex.length) !== 64) {
|
|
3303
|
-
throw new WrongAddressError(`Wrong address ${hexAddress}. Hex part must be 64bytes length, but ${hex === null || hex === void 0 ? void 0 : hex.length} received.`);
|
|
3304
|
-
}
|
|
3305
|
-
return {
|
|
3306
|
-
wc,
|
|
3307
|
-
hex: hexToBytes(hex)
|
|
3308
|
-
};
|
|
3309
|
-
}
|
|
3310
|
-
function crc16(data) {
|
|
3311
|
-
const poly = 0x1021;
|
|
3312
|
-
let reg = 0;
|
|
3313
|
-
const message = new Uint8Array(data.length + 2);
|
|
3314
|
-
message.set(data);
|
|
3315
|
-
for (let byte of message) {
|
|
3316
|
-
let mask = 0x80;
|
|
3317
|
-
while (mask > 0) {
|
|
3318
|
-
reg <<= 1;
|
|
3319
|
-
if (byte & mask) {
|
|
3320
|
-
reg += 1;
|
|
3321
|
-
}
|
|
3322
|
-
mask >>= 1;
|
|
3323
|
-
if (reg > 0xffff) {
|
|
3324
|
-
reg &= 0xffff;
|
|
3325
|
-
reg ^= poly;
|
|
3326
|
-
}
|
|
3327
|
-
}
|
|
3328
|
-
}
|
|
3329
|
-
return new Uint8Array([Math.floor(reg / 256), reg % 256]);
|
|
3330
|
-
}
|
|
3331
|
-
const toByteMap = {};
|
|
3332
|
-
for (let ord = 0; ord <= 0xff; ord++) {
|
|
3333
|
-
let s = ord.toString(16);
|
|
3334
|
-
if (s.length < 2) {
|
|
3335
|
-
s = '0' + s;
|
|
3336
|
-
}
|
|
3337
|
-
toByteMap[s] = ord;
|
|
3338
|
-
}
|
|
3339
|
-
function hexToBytes(hex) {
|
|
3340
|
-
hex = hex.toLowerCase();
|
|
3341
|
-
const length2 = hex.length;
|
|
3342
|
-
if (length2 % 2 !== 0) {
|
|
3343
|
-
throw new ParseHexError('Hex string must have length a multiple of 2: ' + hex);
|
|
3344
|
-
}
|
|
3345
|
-
const length = length2 / 2;
|
|
3346
|
-
const result = new Uint8Array(length);
|
|
3347
|
-
for (let i = 0; i < length; i++) {
|
|
3348
|
-
const doubled = i * 2;
|
|
3349
|
-
const hexSubstring = hex.substring(doubled, doubled + 2);
|
|
3350
|
-
if (!toByteMap.hasOwnProperty(hexSubstring)) {
|
|
3351
|
-
throw new ParseHexError('Invalid hex character: ' + hexSubstring);
|
|
3352
|
-
}
|
|
3353
|
-
result[i] = toByteMap[hexSubstring];
|
|
3354
|
-
}
|
|
3355
|
-
return result;
|
|
3356
|
-
}
|
|
3357
|
-
|
|
3358
|
-
export { BadRequestError, BrowserEventDispatcher, FetchWalletsError, LocalstorageNotFoundError, ParseHexError, TonConnect, TonConnectError, UnknownAppError, UnknownError, UserRejectsError, WalletAlreadyConnectedError, WalletMissingRequiredFeaturesError, WalletNotConnectedError, WalletNotInjectedError, WalletNotSupportFeatureError, WalletsListManager, WrongAddressError, checkRequiredWalletFeatures, createConnectionCompletedEvent, createConnectionErrorEvent, createConnectionRestoringCompletedEvent, createConnectionRestoringErrorEvent, createConnectionRestoringStartedEvent, createConnectionStartedEvent, createDataSentForSignatureEvent, createDataSignedEvent, createDataSigningFailedEvent, createDisconnectionEvent, createRequestVersionEvent, createResponseVersionEvent, createTransactionSentForSignatureEvent, createTransactionSignedEvent, createTransactionSigningFailedEvent, createVersionInfo, TonConnect as default, encodeTelegramUrlParameters, isTelegramUrl, isWalletInfoCurrentlyEmbedded, isWalletInfoCurrentlyInjected, isWalletInfoInjectable, isWalletInfoInjected, isWalletInfoRemote, toUserFriendlyAddress };
|
|
3791
|
+
export { BadRequestError, BrowserEventDispatcher, FetchWalletsError, LocalstorageNotFoundError, ParseHexError, TonConnect, TonConnectError, UnknownAppError, UnknownError, UserRejectsError, WalletAlreadyConnectedError, WalletMissingRequiredFeaturesError, WalletNotConnectedError, WalletNotInjectedError, WalletNotSupportFeatureError, WalletsListManager, WrongAddressError, checkRequiredWalletFeatures, createConnectionCompletedEvent, createConnectionErrorEvent, createConnectionRestoringCompletedEvent, createConnectionRestoringErrorEvent, createConnectionRestoringStartedEvent, createConnectionStartedEvent, createDataSentForSignatureEvent, createDataSignedEvent, createDataSigningFailedEvent, createDisconnectionEvent, createRequestVersionEvent, createResponseVersionEvent, createTransactionSentForSignatureEvent, createTransactionSignedEvent, createTransactionSigningFailedEvent, createVersionInfo, TonConnect as default, enableQaMode, encodeTelegramUrlParameters, isQaModeEnabled, isTelegramUrl, isWalletInfoCurrentlyEmbedded, isWalletInfoCurrentlyInjected, isWalletInfoInjectable, isWalletInfoInjected, isWalletInfoRemote, toUserFriendlyAddress };
|
|
3359
3792
|
//# sourceMappingURL=index.mjs.map
|