@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/cjs/index.cjs CHANGED
@@ -143,8 +143,8 @@ class WalletNotSupportFeatureError extends TonConnectError {
143
143
  get info() {
144
144
  return "Wallet doesn't support requested feature method.";
145
145
  }
146
- constructor(...args) {
147
- super(...args);
146
+ constructor(message, options) {
147
+ super(message, options);
148
148
  Object.setPrototypeOf(this, WalletNotSupportFeatureError.prototype);
149
149
  }
150
150
  }
@@ -320,6 +320,32 @@ class SendTransactionParser extends RpcParser {
320
320
  }
321
321
  const sendTransactionParser = new SendTransactionParser();
322
322
 
323
+ const signDataErrors = {
324
+ [protocol.SIGN_DATA_ERROR_CODES.UNKNOWN_ERROR]: UnknownError,
325
+ [protocol.SIGN_DATA_ERROR_CODES.USER_REJECTS_ERROR]: UserRejectsError,
326
+ [protocol.SIGN_DATA_ERROR_CODES.BAD_REQUEST_ERROR]: BadRequestError,
327
+ [protocol.SIGN_DATA_ERROR_CODES.UNKNOWN_APP_ERROR]: UnknownAppError
328
+ };
329
+ class SignDataParser extends RpcParser {
330
+ convertToRpcRequest(payload) {
331
+ return {
332
+ method: 'signData',
333
+ params: [JSON.stringify(payload)]
334
+ };
335
+ }
336
+ parseAndThrowError(response) {
337
+ let ErrorConstructor = UnknownError;
338
+ if (response.error.code in signDataErrors) {
339
+ ErrorConstructor = signDataErrors[response.error.code] || UnknownError;
340
+ }
341
+ throw new ErrorConstructor(response.error.message);
342
+ }
343
+ convertFromRpcResponse(rpcResponse) {
344
+ return rpcResponse.result;
345
+ }
346
+ }
347
+ const signDataParser = new SignDataParser();
348
+
323
349
  class HttpBridgeGatewayStorage {
324
350
  constructor(storage, bridgeUrl) {
325
351
  this.storage = storage;
@@ -810,9 +836,17 @@ function createEventSource(config) {
810
836
  });
811
837
  }
812
838
 
839
+ const CONNECTION_HTTP_EXPIRATION_TIME = 5 * 60 * 1000;
813
840
  function isPendingConnectionHttp(connection) {
814
841
  return !('connectEvent' in connection);
815
842
  }
843
+ function isPendingConnectionHttpRaw(connection) {
844
+ return !('connectEvent' in connection);
845
+ }
846
+ function isExpiredPendingConnectionHttpRaw(connection) {
847
+ var _a;
848
+ return Date.now() - ((_a = connection.createdAt) !== null && _a !== void 0 ? _a : 0) > CONNECTION_HTTP_EXPIRATION_TIME;
849
+ }
816
850
 
817
851
  class BridgeConnectionStorage {
818
852
  constructor(storage) {
@@ -842,7 +876,8 @@ class BridgeConnectionStorage {
842
876
  const rawConnection = {
843
877
  type: 'http',
844
878
  connectionSource: connection.connectionSource,
845
- sessionCrypto: connection.sessionCrypto.stringifyKeypair()
879
+ sessionCrypto: connection.sessionCrypto.stringifyKeypair(),
880
+ createdAt: Date.now()
846
881
  };
847
882
  return this.storage.setItem(this.storeKey, JSON.stringify(rawConnection));
848
883
  });
@@ -862,7 +897,7 @@ class BridgeConnectionStorage {
862
897
  if (connection.type === 'injected') {
863
898
  return connection;
864
899
  }
865
- if ('connectEvent' in connection) {
900
+ if (!isPendingConnectionHttpRaw(connection)) {
866
901
  const sessionCrypto = new protocol.SessionCrypto(connection.session.sessionKeyPair);
867
902
  return {
868
903
  type: 'http',
@@ -876,6 +911,10 @@ class BridgeConnectionStorage {
876
911
  }
877
912
  };
878
913
  }
914
+ if (isExpiredPendingConnectionHttpRaw(connection)) {
915
+ yield this.removeConnection();
916
+ return null;
917
+ }
879
918
  return {
880
919
  type: 'http',
881
920
  sessionCrypto: new protocol.SessionCrypto(connection.sessionCrypto),
@@ -2205,27 +2244,62 @@ class WalletsListManager {
2205
2244
  function checkSendTransactionSupport(features, options) {
2206
2245
  const supportsDeprecatedSendTransactionFeature = features.includes('SendTransaction');
2207
2246
  const sendTransactionFeature = findFeature(features, 'SendTransaction');
2247
+ const requiredFeature = {
2248
+ minMessages: options.requiredMessagesNumber,
2249
+ extraCurrencyRequired: options.requireExtraCurrencies
2250
+ };
2208
2251
  if (!supportsDeprecatedSendTransactionFeature && !sendTransactionFeature) {
2209
- throw new WalletNotSupportFeatureError("Wallet doesn't support SendTransaction feature.");
2252
+ throw new WalletNotSupportFeatureError("Wallet doesn't support SendTransaction feature.", {
2253
+ cause: { requiredFeature: { featureName: 'SendTransaction', value: requiredFeature } }
2254
+ });
2210
2255
  }
2211
2256
  if (options.requireExtraCurrencies) {
2212
2257
  if (!sendTransactionFeature || !sendTransactionFeature.extraCurrencySupported) {
2213
- throw new WalletNotSupportFeatureError(`Wallet is not able to handle such SendTransaction request. Extra currencies support is required.`);
2258
+ throw new WalletNotSupportFeatureError(`Wallet is not able to handle such SendTransaction request. Extra currencies support is required.`, {
2259
+ cause: {
2260
+ requiredFeature: { featureName: 'SendTransaction', value: requiredFeature }
2261
+ }
2262
+ });
2214
2263
  }
2215
2264
  }
2216
2265
  if (sendTransactionFeature && sendTransactionFeature.maxMessages !== undefined) {
2217
2266
  if (sendTransactionFeature.maxMessages < options.requiredMessagesNumber) {
2218
- throw new WalletNotSupportFeatureError(`Wallet is not able to handle such SendTransaction request. Max support messages number is ${sendTransactionFeature.maxMessages}, but ${options.requiredMessagesNumber} is required.`);
2267
+ throw new WalletNotSupportFeatureError(`Wallet is not able to handle such SendTransaction request. Max support messages number is ${sendTransactionFeature.maxMessages}, but ${options.requiredMessagesNumber} is required.`, {
2268
+ cause: {
2269
+ requiredFeature: { featureName: 'SendTransaction', value: requiredFeature }
2270
+ }
2271
+ });
2219
2272
  }
2220
2273
  return;
2221
2274
  }
2222
2275
  logWarning("Connected wallet didn't provide information about max allowed messages in the SendTransaction request. Request may be rejected by the wallet.");
2223
2276
  }
2277
+ function checkSignDataSupport(features, options) {
2278
+ const signDataFeature = features.find(feature => feature && typeof feature === 'object' && feature.name === 'SignData');
2279
+ if (!signDataFeature) {
2280
+ throw new WalletNotSupportFeatureError("Wallet doesn't support SignData feature.", {
2281
+ cause: {
2282
+ requiredFeature: {
2283
+ featureName: 'SignData',
2284
+ value: { types: options.requiredTypes }
2285
+ }
2286
+ }
2287
+ });
2288
+ }
2289
+ const unsupportedTypes = options.requiredTypes.filter(requiredType => !signDataFeature.types.includes(requiredType));
2290
+ if (unsupportedTypes.length) {
2291
+ throw new WalletNotSupportFeatureError(`Wallet doesn't support required SignData types: ${unsupportedTypes.join(', ')}.`, {
2292
+ cause: {
2293
+ requiredFeature: { featureName: 'SignData', value: { types: unsupportedTypes } }
2294
+ }
2295
+ });
2296
+ }
2297
+ }
2224
2298
  function checkRequiredWalletFeatures(features, walletsRequiredFeatures) {
2225
2299
  if (typeof walletsRequiredFeatures !== 'object') {
2226
2300
  return true;
2227
2301
  }
2228
- const { sendTransaction } = walletsRequiredFeatures;
2302
+ const { sendTransaction, signData } = walletsRequiredFeatures;
2229
2303
  if (sendTransaction) {
2230
2304
  const feature = findFeature(features, 'SendTransaction');
2231
2305
  if (!feature) {
@@ -2235,6 +2309,15 @@ function checkRequiredWalletFeatures(features, walletsRequiredFeatures) {
2235
2309
  return false;
2236
2310
  }
2237
2311
  }
2312
+ if (signData) {
2313
+ const feature = findFeature(features, 'SignData');
2314
+ if (!feature) {
2315
+ return false;
2316
+ }
2317
+ if (!checkSignData(feature, signData)) {
2318
+ return false;
2319
+ }
2320
+ }
2238
2321
  return true;
2239
2322
  }
2240
2323
  function findFeature(features, requiredFeatureName) {
@@ -2246,6 +2329,9 @@ function checkSendTransaction(feature, requiredFeature) {
2246
2329
  const correctExtraCurrency = !requiredFeature.extraCurrencyRequired || feature.extraCurrencySupported;
2247
2330
  return !!(correctMessagesNumber && correctExtraCurrency);
2248
2331
  }
2332
+ function checkSignData(feature, requiredFeature) {
2333
+ return requiredFeature.types.every(requiredType => feature.types.includes(requiredType));
2334
+ }
2249
2335
 
2250
2336
  /**
2251
2337
  * Create a request version event.
@@ -2393,6 +2479,15 @@ function createTransactionSignedEvent(version, wallet, transaction, signedTransa
2393
2479
  function createTransactionSigningFailedEvent(version, wallet, transaction, errorMessage, errorCode) {
2394
2480
  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));
2395
2481
  }
2482
+ function createDataSentForSignatureEvent(version, wallet, data) {
2483
+ return Object.assign({ type: 'sign-data-request-initiated', data }, createConnectionInfo(version, wallet));
2484
+ }
2485
+ function createDataSignedEvent(version, wallet, data, signedData) {
2486
+ return Object.assign({ type: 'sign-data-request-completed', is_success: true, data, signed_data: signedData }, createConnectionInfo(version, wallet));
2487
+ }
2488
+ function createDataSigningFailedEvent(version, wallet, data, errorMessage, errorCode) {
2489
+ 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));
2490
+ }
2396
2491
  /**
2397
2492
  * Create a disconnect event.
2398
2493
  * @param version
@@ -2461,6 +2556,9 @@ class BrowserEventDispatcher {
2461
2556
  * * `transaction-sent-for-signature`: when a user sends a transaction for signature.
2462
2557
  * * `transaction-signed`: when a user successfully signs a transaction.
2463
2558
  * * `transaction-signing-failed`: when a user cancels transaction signing or there is an error during the signing process.
2559
+ * * `sign-data-request-initiated`: when a user sends data for signature.
2560
+ * * `sign-data-request-completed`: when a user successfully signs data.
2561
+ * * `sign-data-request-failed`: when a user cancels data signing or there is an error during the signing process.
2464
2562
  *
2465
2563
  * If you want to track user actions, you can subscribe to the window events with prefix `ton-connect-`:
2466
2564
  *
@@ -2661,9 +2759,42 @@ class TonConnectTracker {
2661
2759
  }
2662
2760
  catch (e) { }
2663
2761
  }
2762
+ /**
2763
+ * Track sign data init event.
2764
+ * @param args
2765
+ */
2766
+ trackDataSentForSignature(...args) {
2767
+ try {
2768
+ const event = createDataSentForSignatureEvent(this.version, ...args);
2769
+ this.dispatchUserActionEvent(event);
2770
+ }
2771
+ catch (e) { }
2772
+ }
2773
+ /**
2774
+ * Track sign data success event.
2775
+ * @param args
2776
+ */
2777
+ trackDataSigned(...args) {
2778
+ try {
2779
+ const event = createDataSignedEvent(this.version, ...args);
2780
+ this.dispatchUserActionEvent(event);
2781
+ }
2782
+ catch (e) { }
2783
+ }
2784
+ /**
2785
+ * Track sign data error event.
2786
+ * @param args
2787
+ */
2788
+ trackDataSigningFailed(...args) {
2789
+ try {
2790
+ const event = createDataSigningFailedEvent(this.version, ...args);
2791
+ this.dispatchUserActionEvent(event);
2792
+ }
2793
+ catch (e) { }
2794
+ }
2664
2795
  }
2665
2796
 
2666
- const tonConnectSdkVersion = "3.1.0";
2797
+ const tonConnectSdkVersion = "3.2.0-beta.0";
2667
2798
 
2668
2799
  class TonConnect {
2669
2800
  constructor(options) {
@@ -2912,6 +3043,25 @@ class TonConnect {
2912
3043
  return result;
2913
3044
  });
2914
3045
  }
3046
+ signData(data, options) {
3047
+ return __awaiter(this, void 0, void 0, function* () {
3048
+ const abortController = createAbortController(options === null || options === void 0 ? void 0 : options.signal);
3049
+ if (abortController.signal.aborted) {
3050
+ throw new TonConnectError('data sending was aborted');
3051
+ }
3052
+ this.checkConnection();
3053
+ checkSignDataSupport(this.wallet.device.features, { requiredTypes: [data.type] });
3054
+ this.tracker.trackDataSentForSignature(this.wallet, data);
3055
+ const response = yield this.provider.sendRequest(signDataParser.convertToRpcRequest(data));
3056
+ if (signDataParser.isError(response)) {
3057
+ this.tracker.trackDataSigningFailed(this.wallet, data, response.error.message, response.error.code);
3058
+ return signDataParser.parseAndThrowError(response);
3059
+ }
3060
+ const result = signDataParser.convertFromRpcResponse(response);
3061
+ this.tracker.trackDataSigned(this.wallet, data, result);
3062
+ return result;
3063
+ });
3064
+ }
2915
3065
  /**
2916
3066
  * Disconnect form thw connected wallet and drop current session.
2917
3067
  */
@@ -3185,6 +3335,10 @@ Object.defineProperty(exports, 'SEND_TRANSACTION_ERROR_CODES', {
3185
3335
  enumerable: true,
3186
3336
  get: function () { return protocol.SEND_TRANSACTION_ERROR_CODES; }
3187
3337
  });
3338
+ Object.defineProperty(exports, 'SIGN_DATA_ERROR_CODES', {
3339
+ enumerable: true,
3340
+ get: function () { return protocol.SIGN_DATA_ERROR_CODES; }
3341
+ });
3188
3342
  exports.BadRequestError = BadRequestError;
3189
3343
  exports.BrowserEventDispatcher = BrowserEventDispatcher;
3190
3344
  exports.FetchWalletsError = FetchWalletsError;
@@ -3209,6 +3363,9 @@ exports.createConnectionRestoringCompletedEvent = createConnectionRestoringCompl
3209
3363
  exports.createConnectionRestoringErrorEvent = createConnectionRestoringErrorEvent;
3210
3364
  exports.createConnectionRestoringStartedEvent = createConnectionRestoringStartedEvent;
3211
3365
  exports.createConnectionStartedEvent = createConnectionStartedEvent;
3366
+ exports.createDataSentForSignatureEvent = createDataSentForSignatureEvent;
3367
+ exports.createDataSignedEvent = createDataSignedEvent;
3368
+ exports.createDataSigningFailedEvent = createDataSigningFailedEvent;
3212
3369
  exports.createDisconnectionEvent = createDisconnectionEvent;
3213
3370
  exports.createRequestVersionEvent = createRequestVersionEvent;
3214
3371
  exports.createResponseVersionEvent = createResponseVersionEvent;