@tonconnect/sdk 3.1.0 → 3.2.0-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/lib/esm/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { CONNECT_EVENT_ERROR_CODES, SEND_TRANSACTION_ERROR_CODES, Base64, SessionCrypto, hexToByteArray } from '@tonconnect/protocol';
2
- export { CHAIN, CONNECT_EVENT_ERROR_CODES, CONNECT_ITEM_ERROR_CODES, SEND_TRANSACTION_ERROR_CODES } from '@tonconnect/protocol';
1
+ import { CONNECT_EVENT_ERROR_CODES, SEND_TRANSACTION_ERROR_CODES, SIGN_DATA_ERROR_CODES, Base64, SessionCrypto, hexToByteArray } 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';
3
3
  import '@tonconnect/isomorphic-eventsource';
4
4
  import '@tonconnect/isomorphic-fetch';
5
5
 
@@ -140,8 +140,8 @@ class WalletNotSupportFeatureError extends TonConnectError {
140
140
  get info() {
141
141
  return "Wallet doesn't support requested feature method.";
142
142
  }
143
- constructor(...args) {
144
- super(...args);
143
+ constructor(message, options) {
144
+ super(message, options);
145
145
  Object.setPrototypeOf(this, WalletNotSupportFeatureError.prototype);
146
146
  }
147
147
  }
@@ -317,6 +317,32 @@ class SendTransactionParser extends RpcParser {
317
317
  }
318
318
  const sendTransactionParser = new SendTransactionParser();
319
319
 
320
+ const signDataErrors = {
321
+ [SIGN_DATA_ERROR_CODES.UNKNOWN_ERROR]: UnknownError,
322
+ [SIGN_DATA_ERROR_CODES.USER_REJECTS_ERROR]: UserRejectsError,
323
+ [SIGN_DATA_ERROR_CODES.BAD_REQUEST_ERROR]: BadRequestError,
324
+ [SIGN_DATA_ERROR_CODES.UNKNOWN_APP_ERROR]: UnknownAppError
325
+ };
326
+ class SignDataParser extends RpcParser {
327
+ convertToRpcRequest(payload) {
328
+ return {
329
+ method: 'signData',
330
+ params: [JSON.stringify(payload)]
331
+ };
332
+ }
333
+ parseAndThrowError(response) {
334
+ let ErrorConstructor = UnknownError;
335
+ if (response.error.code in signDataErrors) {
336
+ ErrorConstructor = signDataErrors[response.error.code] || UnknownError;
337
+ }
338
+ throw new ErrorConstructor(response.error.message);
339
+ }
340
+ convertFromRpcResponse(rpcResponse) {
341
+ return rpcResponse.result;
342
+ }
343
+ }
344
+ const signDataParser = new SignDataParser();
345
+
320
346
  class HttpBridgeGatewayStorage {
321
347
  constructor(storage, bridgeUrl) {
322
348
  this.storage = storage;
@@ -807,9 +833,17 @@ function createEventSource(config) {
807
833
  });
808
834
  }
809
835
 
836
+ const CONNECTION_HTTP_EXPIRATION_TIME = 5 * 60 * 1000;
810
837
  function isPendingConnectionHttp(connection) {
811
838
  return !('connectEvent' in connection);
812
839
  }
840
+ function isPendingConnectionHttpRaw(connection) {
841
+ return !('connectEvent' in connection);
842
+ }
843
+ function isExpiredPendingConnectionHttpRaw(connection) {
844
+ var _a;
845
+ return Date.now() - ((_a = connection.createdAt) !== null && _a !== void 0 ? _a : 0) > CONNECTION_HTTP_EXPIRATION_TIME;
846
+ }
813
847
 
814
848
  class BridgeConnectionStorage {
815
849
  constructor(storage) {
@@ -839,7 +873,8 @@ class BridgeConnectionStorage {
839
873
  const rawConnection = {
840
874
  type: 'http',
841
875
  connectionSource: connection.connectionSource,
842
- sessionCrypto: connection.sessionCrypto.stringifyKeypair()
876
+ sessionCrypto: connection.sessionCrypto.stringifyKeypair(),
877
+ createdAt: Date.now()
843
878
  };
844
879
  return this.storage.setItem(this.storeKey, JSON.stringify(rawConnection));
845
880
  });
@@ -859,7 +894,7 @@ class BridgeConnectionStorage {
859
894
  if (connection.type === 'injected') {
860
895
  return connection;
861
896
  }
862
- if ('connectEvent' in connection) {
897
+ if (!isPendingConnectionHttpRaw(connection)) {
863
898
  const sessionCrypto = new SessionCrypto(connection.session.sessionKeyPair);
864
899
  return {
865
900
  type: 'http',
@@ -873,6 +908,10 @@ class BridgeConnectionStorage {
873
908
  }
874
909
  };
875
910
  }
911
+ if (isExpiredPendingConnectionHttpRaw(connection)) {
912
+ yield this.removeConnection();
913
+ return null;
914
+ }
876
915
  return {
877
916
  type: 'http',
878
917
  sessionCrypto: new SessionCrypto(connection.sessionCrypto),
@@ -2202,27 +2241,62 @@ class WalletsListManager {
2202
2241
  function checkSendTransactionSupport(features, options) {
2203
2242
  const supportsDeprecatedSendTransactionFeature = features.includes('SendTransaction');
2204
2243
  const sendTransactionFeature = findFeature(features, 'SendTransaction');
2244
+ const requiredFeature = {
2245
+ minMessages: options.requiredMessagesNumber,
2246
+ extraCurrencyRequired: options.requireExtraCurrencies
2247
+ };
2205
2248
  if (!supportsDeprecatedSendTransactionFeature && !sendTransactionFeature) {
2206
- throw new WalletNotSupportFeatureError("Wallet doesn't support SendTransaction feature.");
2249
+ throw new WalletNotSupportFeatureError("Wallet doesn't support SendTransaction feature.", {
2250
+ cause: { requiredFeature: { featureName: 'SendTransaction', value: requiredFeature } }
2251
+ });
2207
2252
  }
2208
2253
  if (options.requireExtraCurrencies) {
2209
2254
  if (!sendTransactionFeature || !sendTransactionFeature.extraCurrencySupported) {
2210
- throw new WalletNotSupportFeatureError(`Wallet is not able to handle such SendTransaction request. Extra currencies support is required.`);
2255
+ throw new WalletNotSupportFeatureError(`Wallet is not able to handle such SendTransaction request. Extra currencies support is required.`, {
2256
+ cause: {
2257
+ requiredFeature: { featureName: 'SendTransaction', value: requiredFeature }
2258
+ }
2259
+ });
2211
2260
  }
2212
2261
  }
2213
2262
  if (sendTransactionFeature && sendTransactionFeature.maxMessages !== undefined) {
2214
2263
  if (sendTransactionFeature.maxMessages < options.requiredMessagesNumber) {
2215
- throw new WalletNotSupportFeatureError(`Wallet is not able to handle such SendTransaction request. Max support messages number is ${sendTransactionFeature.maxMessages}, but ${options.requiredMessagesNumber} is required.`);
2264
+ throw new WalletNotSupportFeatureError(`Wallet is not able to handle such SendTransaction request. Max support messages number is ${sendTransactionFeature.maxMessages}, but ${options.requiredMessagesNumber} is required.`, {
2265
+ cause: {
2266
+ requiredFeature: { featureName: 'SendTransaction', value: requiredFeature }
2267
+ }
2268
+ });
2216
2269
  }
2217
2270
  return;
2218
2271
  }
2219
2272
  logWarning("Connected wallet didn't provide information about max allowed messages in the SendTransaction request. Request may be rejected by the wallet.");
2220
2273
  }
2274
+ function checkSignDataSupport(features, options) {
2275
+ const signDataFeature = features.find(feature => feature && typeof feature === 'object' && feature.name === 'SignData');
2276
+ if (!signDataFeature) {
2277
+ throw new WalletNotSupportFeatureError("Wallet doesn't support SignData feature.", {
2278
+ cause: {
2279
+ requiredFeature: {
2280
+ featureName: 'SignData',
2281
+ value: { types: options.requiredTypes }
2282
+ }
2283
+ }
2284
+ });
2285
+ }
2286
+ const unsupportedTypes = options.requiredTypes.filter(requiredType => !signDataFeature.types.includes(requiredType));
2287
+ if (unsupportedTypes.length) {
2288
+ throw new WalletNotSupportFeatureError(`Wallet doesn't support required SignData types: ${unsupportedTypes.join(', ')}.`, {
2289
+ cause: {
2290
+ requiredFeature: { featureName: 'SignData', value: { types: unsupportedTypes } }
2291
+ }
2292
+ });
2293
+ }
2294
+ }
2221
2295
  function checkRequiredWalletFeatures(features, walletsRequiredFeatures) {
2222
2296
  if (typeof walletsRequiredFeatures !== 'object') {
2223
2297
  return true;
2224
2298
  }
2225
- const { sendTransaction } = walletsRequiredFeatures;
2299
+ const { sendTransaction, signData } = walletsRequiredFeatures;
2226
2300
  if (sendTransaction) {
2227
2301
  const feature = findFeature(features, 'SendTransaction');
2228
2302
  if (!feature) {
@@ -2232,6 +2306,15 @@ function checkRequiredWalletFeatures(features, walletsRequiredFeatures) {
2232
2306
  return false;
2233
2307
  }
2234
2308
  }
2309
+ if (signData) {
2310
+ const feature = findFeature(features, 'SignData');
2311
+ if (!feature) {
2312
+ return false;
2313
+ }
2314
+ if (!checkSignData(feature, signData)) {
2315
+ return false;
2316
+ }
2317
+ }
2235
2318
  return true;
2236
2319
  }
2237
2320
  function findFeature(features, requiredFeatureName) {
@@ -2243,6 +2326,9 @@ function checkSendTransaction(feature, requiredFeature) {
2243
2326
  const correctExtraCurrency = !requiredFeature.extraCurrencyRequired || feature.extraCurrencySupported;
2244
2327
  return !!(correctMessagesNumber && correctExtraCurrency);
2245
2328
  }
2329
+ function checkSignData(feature, requiredFeature) {
2330
+ return requiredFeature.types.every(requiredType => feature.types.includes(requiredType));
2331
+ }
2246
2332
 
2247
2333
  /**
2248
2334
  * Create a request version event.
@@ -2390,6 +2476,15 @@ function createTransactionSignedEvent(version, wallet, transaction, signedTransa
2390
2476
  function createTransactionSigningFailedEvent(version, wallet, transaction, errorMessage, errorCode) {
2391
2477
  return Object.assign(Object.assign({ type: 'transaction-signing-failed', is_success: false, error_message: errorMessage, error_code: errorCode !== null && errorCode !== void 0 ? errorCode : null }, createConnectionInfo(version, wallet)), createTransactionInfo(wallet, transaction));
2392
2478
  }
2479
+ function createDataSentForSignatureEvent(version, wallet, data) {
2480
+ return Object.assign({ type: 'sign-data-request-initiated', data }, createConnectionInfo(version, wallet));
2481
+ }
2482
+ function createDataSignedEvent(version, wallet, data, signedData) {
2483
+ return Object.assign({ type: 'sign-data-request-completed', is_success: true, data, signed_data: signedData }, createConnectionInfo(version, wallet));
2484
+ }
2485
+ function createDataSigningFailedEvent(version, wallet, data, errorMessage, errorCode) {
2486
+ return Object.assign({ type: 'sign-data-request-failed', is_success: false, data, error_message: errorMessage, error_code: errorCode !== null && errorCode !== void 0 ? errorCode : null }, createConnectionInfo(version, wallet));
2487
+ }
2393
2488
  /**
2394
2489
  * Create a disconnect event.
2395
2490
  * @param version
@@ -2458,6 +2553,9 @@ class BrowserEventDispatcher {
2458
2553
  * * `transaction-sent-for-signature`: when a user sends a transaction for signature.
2459
2554
  * * `transaction-signed`: when a user successfully signs a transaction.
2460
2555
  * * `transaction-signing-failed`: when a user cancels transaction signing or there is an error during the signing process.
2556
+ * * `sign-data-request-initiated`: when a user sends data for signature.
2557
+ * * `sign-data-request-completed`: when a user successfully signs data.
2558
+ * * `sign-data-request-failed`: when a user cancels data signing or there is an error during the signing process.
2461
2559
  *
2462
2560
  * If you want to track user actions, you can subscribe to the window events with prefix `ton-connect-`:
2463
2561
  *
@@ -2658,9 +2756,42 @@ class TonConnectTracker {
2658
2756
  }
2659
2757
  catch (e) { }
2660
2758
  }
2759
+ /**
2760
+ * Track sign data init event.
2761
+ * @param args
2762
+ */
2763
+ trackDataSentForSignature(...args) {
2764
+ try {
2765
+ const event = createDataSentForSignatureEvent(this.version, ...args);
2766
+ this.dispatchUserActionEvent(event);
2767
+ }
2768
+ catch (e) { }
2769
+ }
2770
+ /**
2771
+ * Track sign data success event.
2772
+ * @param args
2773
+ */
2774
+ trackDataSigned(...args) {
2775
+ try {
2776
+ const event = createDataSignedEvent(this.version, ...args);
2777
+ this.dispatchUserActionEvent(event);
2778
+ }
2779
+ catch (e) { }
2780
+ }
2781
+ /**
2782
+ * Track sign data error event.
2783
+ * @param args
2784
+ */
2785
+ trackDataSigningFailed(...args) {
2786
+ try {
2787
+ const event = createDataSigningFailedEvent(this.version, ...args);
2788
+ this.dispatchUserActionEvent(event);
2789
+ }
2790
+ catch (e) { }
2791
+ }
2661
2792
  }
2662
2793
 
2663
- const tonConnectSdkVersion = "3.1.0";
2794
+ const tonConnectSdkVersion = "3.2.0-beta.0";
2664
2795
 
2665
2796
  class TonConnect {
2666
2797
  constructor(options) {
@@ -2909,6 +3040,25 @@ class TonConnect {
2909
3040
  return result;
2910
3041
  });
2911
3042
  }
3043
+ signData(data, options) {
3044
+ return __awaiter(this, void 0, void 0, function* () {
3045
+ const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
3046
+ if (abortController.signal.aborted) {
3047
+ throw new TonConnectError('data sending was aborted');
3048
+ }
3049
+ this.checkConnection();
3050
+ checkSignDataSupport(this.wallet.device.features, { requiredTypes: [data.type] });
3051
+ this.tracker.trackDataSentForSignature(this.wallet, data);
3052
+ const response = yield this.provider.sendRequest(signDataParser.convertToRpcRequest(data));
3053
+ if (signDataParser.isError(response)) {
3054
+ this.tracker.trackDataSigningFailed(this.wallet, data, response.error.message, response.error.code);
3055
+ return signDataParser.parseAndThrowError(response);
3056
+ }
3057
+ const result = signDataParser.convertFromRpcResponse(response);
3058
+ this.tracker.trackDataSigned(this.wallet, data, result);
3059
+ return result;
3060
+ });
3061
+ }
2912
3062
  /**
2913
3063
  * Disconnect form thw connected wallet and drop current session.
2914
3064
  */
@@ -3166,5 +3316,5 @@ function hexToBytes(hex) {
3166
3316
  return result;
3167
3317
  }
3168
3318
 
3169
- 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, createDisconnectionEvent, createRequestVersionEvent, createResponseVersionEvent, createTransactionSentForSignatureEvent, createTransactionSignedEvent, createTransactionSigningFailedEvent, createVersionInfo, TonConnect as default, encodeTelegramUrlParameters, isTelegramUrl, isWalletInfoCurrentlyEmbedded, isWalletInfoCurrentlyInjected, isWalletInfoInjectable, isWalletInfoInjected, isWalletInfoRemote, toUserFriendlyAddress };
3319
+ 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 };
3170
3320
  //# sourceMappingURL=index.mjs.map