@tonconnect/sdk 3.3.0-beta.2 → 3.3.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/esm/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CONNECT_EVENT_ERROR_CODES, SEND_TRANSACTION_ERROR_CODES, SIGN_DATA_ERROR_CODES, Base64, SessionCrypto, hexToByteArray, CONNECT_ITEM_ERROR_CODES } from '@tonconnect/protocol';
2
- export { CHAIN, CONNECT_EVENT_ERROR_CODES, CONNECT_ITEM_ERROR_CODES, SEND_TRANSACTION_ERROR_CODES, SIGN_DATA_ERROR_CODES } from '@tonconnect/protocol';
2
+ export { CHAIN, CONNECT_EVENT_ERROR_CODES, CONNECT_ITEM_ERROR_CODES, SEND_TRANSACTION_ERROR_CODES, SIGN_DATA_ERROR_CODES, SessionCrypto } from '@tonconnect/protocol';
3
3
  import '@tonconnect/isomorphic-eventsource';
4
4
  import '@tonconnect/isomorphic-fetch';
5
5
 
@@ -1473,22 +1473,6 @@ function getWindow() {
1473
1473
  }
1474
1474
  return window;
1475
1475
  }
1476
- /**
1477
- * The function try to get window keys, if it is not available it returns empty array.
1478
- * As an example, for Safari's private mode it returns empty array, because the browser does not allow to get window keys.
1479
- */
1480
- function tryGetWindowKeys() {
1481
- const window = getWindow();
1482
- if (!window) {
1483
- return [];
1484
- }
1485
- try {
1486
- return Object.keys(window);
1487
- }
1488
- catch (_a) {
1489
- return [];
1490
- }
1491
- }
1492
1476
  function getDocument() {
1493
1477
  if (typeof document === 'undefined') {
1494
1478
  return undefined;
@@ -1533,6 +1517,43 @@ function isLocalStorageAvailable() {
1533
1517
  function isNodeJs() {
1534
1518
  return (typeof process !== 'undefined' && process.versions != null && process.versions.node != null);
1535
1519
  }
1520
+ /**
1521
+ * Returns the current domain (hostname) if available.
1522
+ * In browser environment, returns window.location.hostname.
1523
+ * In Node.js environment or when window is not available, returns null.
1524
+ */
1525
+ function getDomain() {
1526
+ try {
1527
+ // In browser environment
1528
+ if (typeof window !== 'undefined' && window.location) {
1529
+ return window.location.hostname;
1530
+ }
1531
+ else {
1532
+ // In Node.js environment, skip domain validation
1533
+ return null;
1534
+ }
1535
+ }
1536
+ catch (_a) {
1537
+ return null;
1538
+ }
1539
+ }
1540
+ /**
1541
+ * Returns an array of [key, value] pairs from window object if available.
1542
+ * In browser environment, returns Object.entries(window).
1543
+ * In Node.js environment or when window is not available, returns empty array.
1544
+ */
1545
+ function getWindowEntries() {
1546
+ const window = getWindow();
1547
+ if (!window) {
1548
+ return [];
1549
+ }
1550
+ try {
1551
+ return Object.entries(window);
1552
+ }
1553
+ catch (_a) {
1554
+ return [];
1555
+ }
1556
+ }
1536
1557
 
1537
1558
  class InjectedProvider {
1538
1559
  static fromStorage(storage) {
@@ -1555,8 +1576,8 @@ class InjectedProvider {
1555
1576
  if (!this.window) {
1556
1577
  return [];
1557
1578
  }
1558
- const windowKeys = tryGetWindowKeys();
1559
- const wallets = windowKeys.filter(([_, value]) => isJSBridgeWithMetadata(value));
1579
+ const windowEntries = getWindowEntries();
1580
+ const wallets = windowEntries.filter(([_key, value]) => isJSBridgeWithMetadata(value));
1560
1581
  return wallets.map(([jsBridgeKey, wallet]) => ({
1561
1582
  name: wallet.tonconnect.walletInfo.name,
1562
1583
  appName: wallet.tonconnect.walletInfo.app_name,
@@ -2102,11 +2123,6 @@ function enableQaMode() {
2102
2123
  function isQaModeEnabled() {
2103
2124
  return qaModeEnabled;
2104
2125
  }
2105
- function logValidationError(message) {
2106
- if (isQaModeEnabled()) {
2107
- console.error(`[QA Mode] Validation failed: ${message}`);
2108
- }
2109
- }
2110
2126
  function showQaModeBanner() {
2111
2127
  if (typeof window === 'undefined')
2112
2128
  return;
@@ -2207,8 +2223,8 @@ function startBannerObserver() {
2207
2223
  class WalletsListManager {
2208
2224
  constructor(options) {
2209
2225
  var _a;
2210
- this.walletsListCache = null;
2211
- this.walletsListCacheCreationTimestamp = null;
2226
+ this.walletsListDTOCache = null;
2227
+ this.walletsListDTOCacheCreationTimestamp = null;
2212
2228
  if (isQaModeEnabled()) {
2213
2229
  this.walletsListSource =
2214
2230
  'https://raw.githubusercontent.com/ton-connect/wallets-list-staging/refs/heads/main/wallets-v2.json';
@@ -2221,23 +2237,11 @@ class WalletsListManager {
2221
2237
  }
2222
2238
  getWallets() {
2223
2239
  return __awaiter(this, void 0, void 0, function* () {
2224
- if (this.cacheTTLMs &&
2225
- this.walletsListCacheCreationTimestamp &&
2226
- Date.now() > this.walletsListCacheCreationTimestamp + this.cacheTTLMs) {
2227
- this.walletsListCache = null;
2228
- }
2229
- if (!this.walletsListCache) {
2230
- this.walletsListCache = this.fetchWalletsList();
2231
- this.walletsListCache
2232
- .then(() => {
2233
- this.walletsListCacheCreationTimestamp = Date.now();
2234
- })
2235
- .catch(() => {
2236
- this.walletsListCache = null;
2237
- this.walletsListCacheCreationTimestamp = null;
2238
- });
2239
- }
2240
- return this.walletsListCache;
2240
+ const [walletsListDTO, currentlyInjectedWallets] = yield Promise.all([
2241
+ this.fetchWalletsListDTO(),
2242
+ this.getCurrentlyInjectedWallets()
2243
+ ]);
2244
+ return this.mergeWalletsLists(this.walletConfigDTOListToWalletConfigList(walletsListDTO), currentlyInjectedWallets);
2241
2245
  });
2242
2246
  }
2243
2247
  getEmbeddedWallet() {
@@ -2247,7 +2251,28 @@ class WalletsListManager {
2247
2251
  return embeddedWallets.length === 1 ? embeddedWallets[0] : null;
2248
2252
  });
2249
2253
  }
2250
- fetchWalletsList() {
2254
+ fetchWalletsListDTO() {
2255
+ return __awaiter(this, void 0, void 0, function* () {
2256
+ if (this.cacheTTLMs &&
2257
+ this.walletsListDTOCacheCreationTimestamp &&
2258
+ Date.now() > this.walletsListDTOCacheCreationTimestamp + this.cacheTTLMs) {
2259
+ this.walletsListDTOCache = null;
2260
+ }
2261
+ if (!this.walletsListDTOCache) {
2262
+ this.walletsListDTOCache = this.fetchWalletsListFromSource();
2263
+ this.walletsListDTOCache
2264
+ .then(() => {
2265
+ this.walletsListDTOCacheCreationTimestamp = Date.now();
2266
+ })
2267
+ .catch(() => {
2268
+ this.walletsListDTOCache = null;
2269
+ this.walletsListDTOCacheCreationTimestamp = null;
2270
+ });
2271
+ }
2272
+ return this.walletsListDTOCache;
2273
+ });
2274
+ }
2275
+ fetchWalletsListFromSource() {
2251
2276
  return __awaiter(this, void 0, void 0, function* () {
2252
2277
  let walletsList = [];
2253
2278
  try {
@@ -2268,16 +2293,21 @@ class WalletsListManager {
2268
2293
  logError(e);
2269
2294
  walletsList = FALLBACK_WALLETS_LIST;
2270
2295
  }
2271
- let currentlyInjectedWallets = [];
2272
- try {
2273
- currentlyInjectedWallets = InjectedProvider.getCurrentlyInjectedWallets();
2274
- }
2275
- catch (e) {
2276
- logError(e);
2277
- }
2278
- return this.mergeWalletsLists(this.walletConfigDTOListToWalletConfigList(walletsList), currentlyInjectedWallets);
2296
+ return walletsList;
2279
2297
  });
2280
2298
  }
2299
+ getCurrentlyInjectedWallets() {
2300
+ if (!isQaModeEnabled()) {
2301
+ return [];
2302
+ }
2303
+ try {
2304
+ return InjectedProvider.getCurrentlyInjectedWallets();
2305
+ }
2306
+ catch (e) {
2307
+ logError(e);
2308
+ return [];
2309
+ }
2310
+ }
2281
2311
  walletConfigDTOListToWalletConfigList(walletConfigDTO) {
2282
2312
  return walletConfigDTO.map(walletConfigDTO => {
2283
2313
  const walletConfig = {
@@ -2920,8 +2950,9 @@ class TonConnectTracker {
2920
2950
  }
2921
2951
  }
2922
2952
 
2923
- const tonConnectSdkVersion = "3.3.0-beta.2";
2953
+ const tonConnectSdkVersion = "3.3.0-beta.3";
2924
2954
 
2955
+ const bounceableTag = 0x11;
2925
2956
  const noBounceableTag = 0x51;
2926
2957
  const testOnlyTag = 0x80;
2927
2958
  /**
@@ -2991,25 +3022,40 @@ function parseUserFriendlyAddress(address) {
2991
3022
  throw new WrongAddressError(`Invalid address length: ${address}`);
2992
3023
  }
2993
3024
  const addr = decoded.slice(0, 34);
2994
- const checksum = decoded.slice(34);
3025
+ const checksum = decoded.slice(34, 36);
2995
3026
  const calculatedChecksum = crc16(addr);
2996
3027
  if (!checksum.every((byte, i) => byte === calculatedChecksum[i])) {
2997
3028
  throw new WrongAddressError(`Invalid checksum in address: ${address}`);
2998
3029
  }
2999
- const tag = addr[0];
3000
- const wc = addr[1];
3030
+ let tag = addr[0];
3031
+ let isTestOnly = false;
3032
+ let isBounceable = false;
3033
+ if (tag & testOnlyTag) {
3034
+ isTestOnly = true;
3035
+ tag = tag ^ testOnlyTag;
3036
+ }
3037
+ if (tag !== bounceableTag && tag !== noBounceableTag) {
3038
+ throw new WrongAddressError(`Unknown address tag: ${tag}`);
3039
+ }
3040
+ isBounceable = tag === bounceableTag;
3041
+ let wc = null;
3042
+ if (addr[1] === 0xff) {
3043
+ // TODO we should read signed integer here
3044
+ wc = -1;
3045
+ }
3046
+ else {
3047
+ wc = addr[1];
3048
+ }
3001
3049
  const hex = addr.slice(2);
3002
3050
  if (wc !== 0 && wc !== -1) {
3003
3051
  throw new WrongAddressError(`Invalid workchain: ${wc}`);
3004
3052
  }
3005
- const testOnly = (tag & testOnlyTag) !== 0;
3006
- const isBounceable = (tag & 0x40) !== 0;
3007
3053
  return {
3008
3054
  wc,
3009
3055
  hex: Array.from(hex)
3010
3056
  .map(b => b.toString(16).padStart(2, '0'))
3011
3057
  .join(''),
3012
- testOnly,
3058
+ testOnly: isTestOnly,
3013
3059
  isBounceable
3014
3060
  };
3015
3061
  }
@@ -3086,12 +3132,21 @@ const BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{
3086
3132
  const BOC_PREFIX = 'te6cc';
3087
3133
  const INTEGER_REGEX = /^-?\d+$/;
3088
3134
  const POSITIVE_INTEGER_REGEX = /^\d+$/;
3135
+ const MAX_DOMAIN_BYTES = 128;
3136
+ const MAX_PAYLOAD_BYTES = 128;
3137
+ const MAX_TOTAL_BYTES = 222;
3089
3138
  function isValidNumber(value) {
3090
3139
  return typeof value === 'number' && !isNaN(value);
3091
3140
  }
3092
3141
  function isValidString(value) {
3093
3142
  return typeof value === 'string' && value.length > 0;
3094
3143
  }
3144
+ function isValidAddress(value) {
3145
+ return isValidString(value) && (isValidRawAddress(value) || isValidUserFriendlyAddress(value));
3146
+ }
3147
+ function isValidNetwork(value) {
3148
+ return isValidString(value) && /^-?\d+$/.test(value);
3149
+ }
3095
3150
  function isValidBoc(value) {
3096
3151
  return typeof value === 'string' && BASE64_REGEX.test(value) && value.startsWith(BOC_PREFIX);
3097
3152
  }
@@ -3105,52 +3160,33 @@ function hasExtraProperties(obj, allowedKeys) {
3105
3160
  return Object.keys(obj).some(key => !allowedKeys.includes(key));
3106
3161
  }
3107
3162
  function validateSendTransactionRequest(data) {
3108
- // eslint-disable-next-line no-console
3109
- console.log('[Validation Debug] validateSendTransactionRequest called');
3110
- // eslint-disable-next-line no-console
3111
- console.log('[Validation Debug] isQaModeEnabled():', isQaModeEnabled());
3112
3163
  if (!isValidObject(data)) {
3113
- const error = 'Request must be an object';
3114
- logValidationError(error);
3115
- const shouldReturnNull = isQaModeEnabled();
3116
- // eslint-disable-next-line no-console
3117
- console.log('[Validation Debug] Should return null:', shouldReturnNull);
3118
- return shouldReturnNull ? null : error;
3164
+ return 'Request must be an object';
3119
3165
  }
3120
3166
  const allowedKeys = ['validUntil', 'network', 'from', 'messages'];
3121
3167
  if (hasExtraProperties(data, allowedKeys)) {
3122
- const error = 'Request contains extra properties';
3123
- logValidationError(error);
3124
- return isQaModeEnabled() ? null : error;
3125
- }
3126
- if (!isValidNumber(data.validUntil)) {
3127
- const error = "Incorrect 'validUntil'";
3128
- logValidationError(error);
3129
- return isQaModeEnabled() ? null : error;
3168
+ return 'Request contains extra properties';
3130
3169
  }
3131
- const now = Math.floor(Date.now() / 1000);
3132
- const fiveMinutesFromNow = now + 300;
3133
- if (data.validUntil > fiveMinutesFromNow) {
3134
- console.warn(`validUntil (${data.validUntil}) is more than 5 minutes from now (${now})`);
3170
+ if (data.validUntil) {
3171
+ if (!isValidNumber(data.validUntil)) {
3172
+ return "Incorrect 'validUntil'";
3173
+ }
3174
+ const now = Math.floor(Date.now() / 1000);
3175
+ const fiveMinutesFromNow = now + 300;
3176
+ if (data.validUntil > fiveMinutesFromNow) {
3177
+ console.warn(`validUntil (${data.validUntil}) is more than 5 minutes from now (${now})`);
3178
+ }
3135
3179
  }
3136
3180
  if (data.network !== undefined) {
3137
- if (!isValidString(data.network) || !/^[\d-]+$/.test(data.network)) {
3138
- const error = "Invalid 'network' format";
3139
- logValidationError(error);
3140
- return isQaModeEnabled() ? null : error;
3181
+ if (!isValidNetwork(data.network)) {
3182
+ return "Invalid 'network' format";
3141
3183
  }
3142
3184
  }
3143
- if (data.from !== undefined) {
3144
- if (!isValidString(data.from) || !isValidRawAddress(data.from)) {
3145
- const error = "Invalid 'from' address format";
3146
- logValidationError(error);
3147
- return isQaModeEnabled() ? null : error;
3148
- }
3185
+ if (data.from !== undefined && !isValidAddress(data.from)) {
3186
+ return "Invalid 'from' address format";
3149
3187
  }
3150
3188
  if (!isValidArray(data.messages) || data.messages.length === 0) {
3151
- const error = "'messages' is required";
3152
- logValidationError(error);
3153
- return isQaModeEnabled() ? null : error;
3189
+ return "'messages' is required";
3154
3190
  }
3155
3191
  for (let i = 0; i < data.messages.length; i++) {
3156
3192
  const message = data.messages[i];
@@ -3213,8 +3249,34 @@ function validateConnectAdditionalRequest(data) {
3213
3249
  if (hasExtraProperties(data, allowedKeys)) {
3214
3250
  return 'Request contains extra properties';
3215
3251
  }
3216
- if (data.tonProof !== undefined && !isValidString(data.tonProof)) {
3217
- return "Invalid 'tonProof'";
3252
+ if (data.tonProof !== undefined) {
3253
+ if (typeof data.tonProof !== 'string') {
3254
+ return "Invalid 'tonProof'";
3255
+ }
3256
+ const payload = data.tonProof;
3257
+ if (payload.length === 0) {
3258
+ return "Empty 'tonProof' payload";
3259
+ }
3260
+ // Get current domain for validation first
3261
+ const domain = getDomain();
3262
+ if (!domain) {
3263
+ // In Node.js environment, skip domain validation
3264
+ return null;
3265
+ }
3266
+ // Validate domain size (max 128 bytes)
3267
+ const domainBytes = new TextEncoder().encode(domain).length;
3268
+ if (domainBytes > MAX_DOMAIN_BYTES) {
3269
+ return 'Current domain exceeds 128 bytes limit';
3270
+ }
3271
+ // Validate payload size (max 128 bytes)
3272
+ const payloadBytes = new TextEncoder().encode(payload).length;
3273
+ if (payloadBytes > MAX_PAYLOAD_BYTES) {
3274
+ return "'tonProof' payload exceeds 128 bytes limit";
3275
+ }
3276
+ // Validate total size (domain + payload <= 222 bytes)
3277
+ if (domainBytes + payloadBytes > MAX_TOTAL_BYTES) {
3278
+ return "'tonProof' domain + payload exceeds 222 bytes limit";
3279
+ }
3218
3280
  }
3219
3281
  return null;
3220
3282
  }
@@ -3245,11 +3307,11 @@ function validateSignDataPayloadText(data) {
3245
3307
  return "'text' is required";
3246
3308
  }
3247
3309
  if (data.network !== undefined) {
3248
- if (!isValidString(data.network) || !/^\d+$/.test(data.network)) {
3310
+ if (!isValidNetwork(data.network)) {
3249
3311
  return "Invalid 'network' format";
3250
3312
  }
3251
3313
  }
3252
- if (data.from !== undefined && !isValidString(data.from)) {
3314
+ if (data.from !== undefined && !isValidAddress(data.from)) {
3253
3315
  return "Invalid 'from'";
3254
3316
  }
3255
3317
  return null;
@@ -3263,11 +3325,11 @@ function validateSignDataPayloadBinary(data) {
3263
3325
  return "'bytes' is required";
3264
3326
  }
3265
3327
  if (data.network !== undefined) {
3266
- if (!isValidString(data.network) || !/^\d+$/.test(data.network)) {
3328
+ if (!isValidNetwork(data.network)) {
3267
3329
  return "Invalid 'network' format";
3268
3330
  }
3269
3331
  }
3270
- if (data.from !== undefined && !isValidString(data.from)) {
3332
+ if (data.from !== undefined && !isValidAddress(data.from)) {
3271
3333
  return "Invalid 'from'";
3272
3334
  }
3273
3335
  return null;
@@ -3287,15 +3349,95 @@ function validateSignDataPayloadCell(data) {
3287
3349
  return "Invalid 'cell' format (must be valid base64)";
3288
3350
  }
3289
3351
  if (data.network !== undefined) {
3290
- if (!isValidString(data.network) || !/^\d+$/.test(data.network)) {
3352
+ if (!isValidNetwork(data.network)) {
3291
3353
  return "Invalid 'network' format";
3292
3354
  }
3293
3355
  }
3294
- if (data.from !== undefined && !isValidString(data.from)) {
3356
+ if (data.from !== undefined && !isValidAddress(data.from)) {
3295
3357
  return "Invalid 'from'";
3296
3358
  }
3297
3359
  return null;
3298
3360
  }
3361
+ /**
3362
+ * Validates ton_proof item received from wallet in connect event.
3363
+ */
3364
+ // eslint-disable-next-line complexity
3365
+ function validateTonProofItemReply(data) {
3366
+ if (!isValidObject(data)) {
3367
+ return 'ton_proof item must be an object';
3368
+ }
3369
+ const allowedKeys = ['error', 'proof', 'name'];
3370
+ if (hasExtraProperties(data, allowedKeys)) {
3371
+ return 'ton_proof item contains extra properties';
3372
+ }
3373
+ const hasProof = Object.prototype.hasOwnProperty.call(data, 'proof');
3374
+ const hasError = Object.prototype.hasOwnProperty.call(data, 'error');
3375
+ if (!hasProof && !hasError) {
3376
+ return "'ton_proof' item must contain either 'proof' or 'error'";
3377
+ }
3378
+ if (hasProof && hasError) {
3379
+ return "'ton_proof' item must contain either 'proof' or 'error', not both";
3380
+ }
3381
+ if (hasProof) {
3382
+ const proof = data.proof;
3383
+ if (!isValidObject(proof)) {
3384
+ return "Invalid 'proof' object";
3385
+ }
3386
+ const allowedProofKeys = ['timestamp', 'domain', 'payload', 'signature'];
3387
+ if (hasExtraProperties(proof, allowedProofKeys)) {
3388
+ return 'ton_proof item contains extra properties';
3389
+ }
3390
+ if (!isValidNumber(proof.timestamp)) {
3391
+ return "Invalid 'proof.timestamp'";
3392
+ }
3393
+ const domain = proof.domain;
3394
+ if (!isValidObject(domain)) {
3395
+ return "Invalid 'proof.domain'";
3396
+ }
3397
+ if (!isValidNumber(domain.lengthBytes)) {
3398
+ return "Invalid 'proof.domain.lengthBytes'";
3399
+ }
3400
+ if (!isValidString(domain.value)) {
3401
+ return "Invalid 'proof.domain.value'";
3402
+ }
3403
+ // Try to verify that provided byte length matches actual byte length of value
3404
+ try {
3405
+ const encoderAvailable = typeof TextEncoder !== 'undefined';
3406
+ const actualLength = encoderAvailable
3407
+ ? new TextEncoder().encode(domain.value).length
3408
+ : domain.value.length;
3409
+ if (actualLength !== domain.lengthBytes) {
3410
+ return "'proof.domain.lengthBytes' does not match 'proof.domain.value'";
3411
+ }
3412
+ }
3413
+ catch (_a) {
3414
+ // Ignore environment issues; best-effort validation
3415
+ }
3416
+ if (!isValidString(proof.payload)) {
3417
+ return "Invalid 'proof.payload'";
3418
+ }
3419
+ if (!isValidString(proof.signature) || !BASE64_REGEX.test(proof.signature)) {
3420
+ return "Invalid 'proof.signature' format";
3421
+ }
3422
+ }
3423
+ if (hasError) {
3424
+ const error = data.error;
3425
+ if (!isValidObject(error)) {
3426
+ return "Invalid 'error' object";
3427
+ }
3428
+ const allowedErrorKeys = ['code', 'message'];
3429
+ if (hasExtraProperties(error, allowedErrorKeys)) {
3430
+ return 'ton_proof error contains extra properties';
3431
+ }
3432
+ if (!isValidNumber(error.code)) {
3433
+ return "Invalid 'error.code'";
3434
+ }
3435
+ if (!isValidString(error.message)) {
3436
+ return "Invalid 'error.message'";
3437
+ }
3438
+ }
3439
+ return null;
3440
+ }
3299
3441
 
3300
3442
  class TonConnect {
3301
3443
  /**
@@ -3619,6 +3761,34 @@ class TonConnect {
3619
3761
  prevAbortController === null || prevAbortController === void 0 ? void 0 : prevAbortController.abort();
3620
3762
  });
3621
3763
  }
3764
+ /**
3765
+ * Gets the current session ID if available.
3766
+ * @returns session ID string or null if not available.
3767
+ */
3768
+ getSessionId() {
3769
+ return __awaiter(this, void 0, void 0, function* () {
3770
+ if (!this.provider || !this.connected) {
3771
+ return null;
3772
+ }
3773
+ try {
3774
+ const connection = yield this.bridgeConnectionStorage.getConnection();
3775
+ if (!connection || connection.type === 'injected') {
3776
+ return null;
3777
+ }
3778
+ if ('sessionCrypto' in connection) {
3779
+ // Pending connection
3780
+ return connection.sessionCrypto.sessionId;
3781
+ }
3782
+ else {
3783
+ // Established connection
3784
+ return connection.session.sessionCrypto.sessionId;
3785
+ }
3786
+ }
3787
+ catch (_a) {
3788
+ return null;
3789
+ }
3790
+ });
3791
+ }
3622
3792
  /**
3623
3793
  * Pause bridge HTTP connection. Might be helpful, if you want to pause connections while browser tab is unfocused,
3624
3794
  * or if you use SDK with NodeJS and want to save server resources.
@@ -3708,46 +3878,59 @@ class TonConnect {
3708
3878
  }
3709
3879
  };
3710
3880
  if (tonProofItem) {
3881
+ const validationError = validateTonProofItemReply(tonProofItem);
3711
3882
  let tonProof = undefined;
3712
- try {
3713
- if ('proof' in tonProofItem) {
3714
- // success
3715
- tonProof = {
3716
- name: 'ton_proof',
3717
- proof: {
3718
- timestamp: tonProofItem.proof.timestamp,
3719
- domain: {
3720
- lengthBytes: tonProofItem.proof.domain.lengthBytes,
3721
- value: tonProofItem.proof.domain.value
3722
- },
3723
- payload: tonProofItem.proof.payload,
3724
- signature: tonProofItem.proof.signature
3725
- }
3726
- };
3727
- }
3728
- else if ('error' in tonProofItem) {
3729
- // error
3730
- tonProof = {
3731
- name: 'ton_proof',
3732
- error: {
3733
- code: tonProofItem.error.code,
3734
- message: tonProofItem.error.message
3735
- }
3736
- };
3737
- }
3738
- else {
3739
- throw new TonConnectError('Invalid data format');
3883
+ if (validationError) {
3884
+ if (isQaModeEnabled()) {
3885
+ console.error('TonProofItem validation failed: ' + validationError);
3740
3886
  }
3741
- }
3742
- catch (e) {
3743
3887
  tonProof = {
3744
3888
  name: 'ton_proof',
3745
3889
  error: {
3746
3890
  code: CONNECT_ITEM_ERROR_CODES.UNKNOWN_ERROR,
3747
- message: 'Invalid data format'
3891
+ message: validationError
3748
3892
  }
3749
3893
  };
3750
3894
  }
3895
+ else {
3896
+ try {
3897
+ if ('proof' in tonProofItem) {
3898
+ tonProof = {
3899
+ name: 'ton_proof',
3900
+ proof: {
3901
+ timestamp: tonProofItem.proof.timestamp,
3902
+ domain: {
3903
+ lengthBytes: tonProofItem.proof.domain.lengthBytes,
3904
+ value: tonProofItem.proof.domain.value
3905
+ },
3906
+ payload: tonProofItem.proof.payload,
3907
+ signature: tonProofItem.proof.signature
3908
+ }
3909
+ };
3910
+ }
3911
+ else if ('error' in tonProofItem) {
3912
+ tonProof = {
3913
+ name: 'ton_proof',
3914
+ error: {
3915
+ code: tonProofItem.error.code,
3916
+ message: tonProofItem.error.message
3917
+ }
3918
+ };
3919
+ }
3920
+ else {
3921
+ throw new TonConnectError('Invalid data format');
3922
+ }
3923
+ }
3924
+ catch (e) {
3925
+ tonProof = {
3926
+ name: 'ton_proof',
3927
+ error: {
3928
+ code: CONNECT_ITEM_ERROR_CODES.UNKNOWN_ERROR,
3929
+ message: 'Invalid data format'
3930
+ }
3931
+ };
3932
+ }
3933
+ }
3751
3934
  wallet.connectItems = { tonProof };
3752
3935
  }
3753
3936
  this.wallet = wallet;