@metamask/connect-multichain 1.0.0 → 1.1.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/dist/browser/es/connect-multichain.d.mts +11 -2
  3. package/dist/browser/es/connect-multichain.mjs +111 -14
  4. package/dist/browser/es/connect-multichain.mjs.map +1 -1
  5. package/dist/browser/es/metafile-esm.json +1 -1
  6. package/dist/browser/iife/connect-multichain.d.ts +11 -2
  7. package/dist/browser/iife/connect-multichain.js +110 -13
  8. package/dist/browser/iife/connect-multichain.js.map +1 -1
  9. package/dist/browser/iife/metafile-iife.json +1 -1
  10. package/dist/browser/umd/connect-multichain.d.ts +11 -2
  11. package/dist/browser/umd/connect-multichain.js +119 -22
  12. package/dist/browser/umd/connect-multichain.js.map +1 -1
  13. package/dist/browser/umd/metafile-cjs.json +1 -1
  14. package/dist/node/cjs/connect-multichain.d.ts +11 -2
  15. package/dist/node/cjs/connect-multichain.js +119 -22
  16. package/dist/node/cjs/connect-multichain.js.map +1 -1
  17. package/dist/node/cjs/metafile-cjs.json +1 -1
  18. package/dist/node/es/connect-multichain.d.mts +11 -2
  19. package/dist/node/es/connect-multichain.mjs +111 -14
  20. package/dist/node/es/connect-multichain.mjs.map +1 -1
  21. package/dist/node/es/metafile-esm.json +1 -1
  22. package/dist/react-native/es/connect-multichain.d.mts +11 -2
  23. package/dist/react-native/es/connect-multichain.mjs +111 -14
  24. package/dist/react-native/es/connect-multichain.mjs.map +1 -1
  25. package/dist/react-native/es/metafile-esm.json +1 -1
  26. package/dist/src/domain/errors/rpc.d.ts +11 -1
  27. package/dist/src/domain/errors/rpc.d.ts.map +1 -1
  28. package/dist/src/domain/errors/rpc.js +10 -2
  29. package/dist/src/domain/errors/rpc.js.map +1 -1
  30. package/dist/src/multichain/rpc/invocationError.d.ts +9 -0
  31. package/dist/src/multichain/rpc/invocationError.d.ts.map +1 -0
  32. package/dist/src/multichain/rpc/invocationError.js +99 -0
  33. package/dist/src/multichain/rpc/invocationError.js.map +1 -0
  34. package/dist/src/multichain/rpc/requestRouter.d.ts.map +1 -1
  35. package/dist/src/multichain/rpc/requestRouter.js +10 -18
  36. package/dist/src/multichain/rpc/requestRouter.js.map +1 -1
  37. package/dist/src/multichain/transports/default/index.d.ts.map +1 -1
  38. package/dist/src/multichain/transports/default/index.js +9 -0
  39. package/dist/src/multichain/transports/default/index.js.map +1 -1
  40. package/dist/src/multichain/transports/mwp/index.d.ts.map +1 -1
  41. package/dist/src/multichain/transports/mwp/index.js +9 -3
  42. package/dist/src/multichain/transports/mwp/index.js.map +1 -1
  43. package/dist/types/connect-multichain.d.ts +11 -2
  44. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.1.0]
11
+
12
+ ### Fixed
13
+
14
+ - Normalize `invokeMethod()` wallet errors across transports. Wallet-side JSON-RPC / EIP-1193 `code`, `message`, and `data` fields are now preserved in `RPCInvokeMethodErr` as `rpcCode`, `rpcMessage`, and `rpcData` whether the wallet error arrives as a resolved JSON-RPC error response or as a rejected transport error. Wrapped transport errors now walk a capped `cause` chain so wallet error details are not hidden by transport/API wrapper errors. ([#312](https://github.com/MetaMask/connect-monorepo/pull/312))
15
+ - `DefaultTransport` and `MWPTransport` now preserve the wallet's JSON-RPC error `data` when parsing a failed wallet response. Previously both transports dropped `data` while constructing the rejected error, so revert reasons / custom-error bytes never reached `RequestRouter` (leaving `RPCInvokeMethodErr.rpcData` unset). ([#312](https://github.com/MetaMask/connect-monorepo/pull/312))
16
+
10
17
  ## [1.0.0]
11
18
 
12
19
  ### Added
@@ -309,7 +316,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
309
316
 
310
317
  - Initial release
311
318
 
312
- [Unreleased]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@1.0.0...HEAD
319
+ [Unreleased]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@1.1.0...HEAD
320
+ [1.1.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@1.0.0...@metamask/connect-multichain@1.1.0
313
321
  [1.0.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.15.0...@metamask/connect-multichain@1.0.0
314
322
  [0.15.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.14.0...@metamask/connect-multichain@0.15.0
315
323
  [0.14.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.13.0...@metamask/connect-multichain@0.14.0
@@ -1,7 +1,7 @@
1
+ import { Json, CaipAccountId, CaipChainId } from '@metamask/utils';
1
2
  import debug from 'debug';
2
3
  import { SessionData, Transport, SessionProperties, TransportRequest, TransportResponse, MultichainApiClient } from '@metamask/multichain-api-client';
3
4
  export { SessionData } from '@metamask/multichain-api-client';
4
- import { CaipAccountId, CaipChainId, Json } from '@metamask/utils';
5
5
  import { SessionRequest, Session } from '@metamask/mobile-wallet-protocol-core';
6
6
  import { Components } from '@metamask/multichain-ui';
7
7
 
@@ -39,8 +39,17 @@ declare class RPCInvokeMethodErr extends BaseErr<'RPC', RPCErrorCodes> {
39
39
  readonly reason: string;
40
40
  readonly rpcCode?: number | undefined;
41
41
  readonly rpcMessage?: string | undefined;
42
+ readonly rpcData?: Json | undefined;
42
43
  static readonly code = 53;
43
- constructor(reason: string, rpcCode?: number | undefined, rpcMessage?: string | undefined);
44
+ /**
45
+ * @param reason - MetaMask Connect invokeMethod reason.
46
+ * @param rpcCode - Original wallet JSON-RPC / EIP-1193 error code.
47
+ * @param rpcMessage - Original provider-facing wallet message, sourced only
48
+ * from the wallet's coded error. Unset when the wallet provides no message,
49
+ * so it may differ from `reason`, which can fall back through the cause chain.
50
+ * @param rpcData - Original JSON-RPC error data, when provided by the wallet.
51
+ */
52
+ constructor(reason: string, rpcCode?: number | undefined, rpcMessage?: string | undefined, rpcData?: Json | undefined);
44
53
  }
45
54
 
46
55
  type SDKEvents = {
@@ -112,7 +112,15 @@ var init_rpc = __esm({
112
112
  _RPCReadonlyRequestErr.code = 52;
113
113
  RPCReadonlyRequestErr = _RPCReadonlyRequestErr;
114
114
  _RPCInvokeMethodErr = class _RPCInvokeMethodErr extends BaseErr {
115
- constructor(reason, rpcCode, rpcMessage) {
115
+ /**
116
+ * @param reason - MetaMask Connect invokeMethod reason.
117
+ * @param rpcCode - Original wallet JSON-RPC / EIP-1193 error code.
118
+ * @param rpcMessage - Original provider-facing wallet message, sourced only
119
+ * from the wallet's coded error. Unset when the wallet provides no message,
120
+ * so it may differ from `reason`, which can fall back through the cause chain.
121
+ * @param rpcData - Original JSON-RPC error data, when provided by the wallet.
122
+ */
123
+ constructor(reason, rpcCode, rpcMessage, rpcData) {
116
124
  super(
117
125
  `RPCErr${_RPCInvokeMethodErr.code}: RPC Client invoke method reason (${reason})`,
118
126
  _RPCInvokeMethodErr.code
@@ -120,6 +128,7 @@ var init_rpc = __esm({
120
128
  this.reason = reason;
121
129
  this.rpcCode = rpcCode;
122
130
  this.rpcMessage = rpcMessage;
131
+ this.rpcData = rpcData;
123
132
  }
124
133
  };
125
134
  _RPCInvokeMethodErr.code = 53;
@@ -870,7 +879,7 @@ var init_utils = __esm({
870
879
  "src/domain/utils/index.ts"() {
871
880
  "use strict";
872
881
  init_analytics();
873
- packageVersion = false ? "unknown" : "1.0.0";
882
+ packageVersion = false ? "unknown" : "1.1.0";
874
883
  }
875
884
  });
876
885
 
@@ -1177,7 +1186,7 @@ import {
1177
1186
  TransportTimeoutError
1178
1187
  } from "@metamask/multichain-api-client";
1179
1188
  import { JsonRpcError, providerErrors as providerErrors2, rpcErrors } from "@metamask/rpc-errors";
1180
- import { createDeferredPromise } from "@metamask/utils";
1189
+ import { createDeferredPromise, isValidJson as isValidJson3 } from "@metamask/utils";
1181
1190
  var DEFAULT_REQUEST_TIMEOUT2, CONNECTION_GRACE_PERIOD, DEFAULT_CONNECTION_TIMEOUT, DEFAULT_RESUME_TIMEOUT, SESSION_STORE_KEY, ACCOUNTS_STORE_KEY, CHAIN_STORE_KEY, PENDING_SESSION_REQUEST_KEY, CACHED_METHOD_LIST, CACHED_RESET_METHOD_LIST, logger, _MWPTransport_instances, onResumeHandler_fn, resumeSession_fn, startSession_fn, MWPTransport;
1182
1191
  var init_mwp = __esm({
1183
1192
  "src/multichain/transports/mwp/index.ts"() {
@@ -1284,10 +1293,12 @@ var init_mwp = __esm({
1284
1293
  const errorData = errorPayload;
1285
1294
  if (typeof errorData.code === "number" && typeof errorData.message === "string") {
1286
1295
  const { code, message: message2 } = errorData;
1296
+ const rawData = errorData.data;
1297
+ const data = isValidJson3(rawData) ? rawData : void 0;
1287
1298
  if (code >= 1e3 && code <= 4999) {
1288
- return providerErrors2.custom({ code, message: message2 });
1299
+ return providerErrors2.custom({ code, message: message2, data });
1289
1300
  }
1290
- return new JsonRpcError(code, message2);
1301
+ return new JsonRpcError(code, message2, data);
1291
1302
  }
1292
1303
  const message = errorPayload instanceof Error ? errorPayload.message : JSON.stringify(errorPayload);
1293
1304
  return rpcErrors.internal({ message });
@@ -2348,17 +2359,93 @@ import { analytics } from "@metamask/analytics";
2348
2359
  init_domain();
2349
2360
  init_utils2();
2350
2361
  init_analytics();
2362
+
2363
+ // src/multichain/rpc/invocationError.ts
2364
+ init_domain();
2365
+ import { isValidJson } from "@metamask/utils";
2366
+ var MAX_ERROR_CAUSE_DEPTH = 5;
2367
+ function getErrorObject(value) {
2368
+ if (typeof value === "object" && value !== null) {
2369
+ return value;
2370
+ }
2371
+ return void 0;
2372
+ }
2373
+ function getNumericCode(value) {
2374
+ return typeof value === "number" ? value : void 0;
2375
+ }
2376
+ function getNonEmptyMessage(value) {
2377
+ return typeof value === "string" && value.length > 0 ? value : void 0;
2378
+ }
2379
+ function getJsonData(value) {
2380
+ return value !== void 0 && isValidJson(value) ? value : void 0;
2381
+ }
2382
+ function getFirstNonEmptyMessage(values) {
2383
+ for (const value of values) {
2384
+ const message = getNonEmptyMessage(value);
2385
+ if (message !== void 0) {
2386
+ return message;
2387
+ }
2388
+ }
2389
+ return void 0;
2390
+ }
2391
+ function getErrorObjectChain(errorObject) {
2392
+ const chain = [];
2393
+ let currentObject = errorObject;
2394
+ for (let depth = 0; currentObject !== void 0 && depth < MAX_ERROR_CAUSE_DEPTH; depth += 1) {
2395
+ chain.push(currentObject);
2396
+ currentObject = getErrorObject(currentObject.cause);
2397
+ }
2398
+ return chain;
2399
+ }
2400
+ function getCodedErrorDetails(value) {
2401
+ const code = getNumericCode(value == null ? void 0 : value.code);
2402
+ if (code === void 0) {
2403
+ return void 0;
2404
+ }
2405
+ const message = getNonEmptyMessage(value == null ? void 0 : value.message);
2406
+ const data = getJsonData(value == null ? void 0 : value.data);
2407
+ return __spreadValues(__spreadValues({
2408
+ code
2409
+ }, message === void 0 ? {} : { message }), data === void 0 ? {} : { data });
2410
+ }
2411
+ function getInvocationErrorDetails(error) {
2412
+ var _a3, _b, _c, _d;
2413
+ const errorObject = getErrorObject(error);
2414
+ const errorObjectChain = getErrorObjectChain(errorObject);
2415
+ const primitiveMessage = getNonEmptyMessage(error);
2416
+ for (const [index, currentObject] of errorObjectChain.entries()) {
2417
+ const codedDetails = getCodedErrorDetails(currentObject);
2418
+ if (codedDetails) {
2419
+ const descendantObjects = errorObjectChain.slice(index + 1);
2420
+ const ancestorObjects = errorObjectChain.slice(0, index);
2421
+ const descendantMessage = getFirstNonEmptyMessage(
2422
+ descendantObjects.map((object) => object.message)
2423
+ );
2424
+ const ancestorMessage = getFirstNonEmptyMessage([
2425
+ primitiveMessage,
2426
+ ...ancestorObjects.map((object) => object.message)
2427
+ ]);
2428
+ const reason2 = (_c = (_b = (_a3 = codedDetails.message) != null ? _a3 : descendantMessage) != null ? _b : ancestorMessage) != null ? _c : "Unknown error";
2429
+ return __spreadValues(__spreadValues({
2430
+ reason: reason2,
2431
+ rpcCode: codedDetails.code
2432
+ }, codedDetails.message === void 0 ? {} : { rpcMessage: codedDetails.message }), codedDetails.data === void 0 ? {} : { rpcData: codedDetails.data });
2433
+ }
2434
+ }
2435
+ const reason = (_d = primitiveMessage != null ? primitiveMessage : getFirstNonEmptyMessage(errorObjectChain.map((object) => object.message))) != null ? _d : "Unknown error";
2436
+ return {
2437
+ reason
2438
+ };
2439
+ }
2351
2440
  function toRPCInvokeMethodErr(error) {
2352
- var _a3;
2353
2441
  if (error instanceof RPCInvokeMethodErr) {
2354
2442
  return error;
2355
2443
  }
2356
- const castError = error;
2357
- return new RPCInvokeMethodErr(
2358
- (_a3 = castError.message) != null ? _a3 : "Unknown error",
2359
- castError.code
2360
- );
2444
+ const { reason, rpcCode, rpcMessage, rpcData } = getInvocationErrorDetails(error);
2445
+ return new RPCInvokeMethodErr(reason, rpcCode, rpcMessage, rpcData);
2361
2446
  }
2447
+
2448
+ // src/multichain/rpc/requestRouter.ts
2362
2449
  var _RequestRouter_instances, withAnalyticsTracking_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, trackWalletActionRejected_fn;
2363
2450
  var RequestRouter = class {
2364
2451
  constructor(transport, rpcClient, config, transportType) {
@@ -2444,6 +2531,9 @@ var RequestRouter = class {
2444
2531
  }), 10);
2445
2532
  }
2446
2533
  const response = yield request;
2534
+ if (response.error) {
2535
+ throw toRPCInvokeMethodErr(response.error);
2536
+ }
2447
2537
  return response.result;
2448
2538
  }));
2449
2539
  });
@@ -2496,13 +2586,15 @@ withAnalyticsTracking_fn = function(options, execute) {
2496
2586
  yield __privateMethod(this, _RequestRouter_instances, trackWalletActionSucceeded_fn).call(this, options);
2497
2587
  return result;
2498
2588
  } catch (error) {
2499
- const isRejection = isRejectionError(error);
2589
+ const normalizedError = toRPCInvokeMethodErr(error);
2590
+ const analyticsError = normalizedError.rpcCode === void 0 ? error : normalizedError;
2591
+ const isRejection = isRejectionError(analyticsError);
2500
2592
  if (isRejection) {
2501
2593
  yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRejected_fn).call(this, options);
2502
2594
  } else {
2503
- yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options, error);
2595
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options, analyticsError);
2504
2596
  }
2505
- throw toRPCInvokeMethodErr(error);
2597
+ throw normalizedError;
2506
2598
  }
2507
2599
  });
2508
2600
  };
@@ -2557,6 +2649,7 @@ init_utils2();
2557
2649
  import {
2558
2650
  getDefaultTransport
2559
2651
  } from "@metamask/multichain-api-client";
2652
+ import { isValidJson as isValidJson2 } from "@metamask/utils";
2560
2653
  var DEFAULT_REQUEST_TIMEOUT = 60 * 1e3;
2561
2654
  var _notificationCallbacks, _transport, _defaultRequestOptions, _pendingRequests, _handleResponseListener, _handleNotificationListener, _DefaultTransport_instances, notifyCallbacks_fn, parseWalletError_fn, isMetamaskProviderEvent_fn, handleResponse_fn, handleNotification_fn, setupMessageListener_fn, init_fn;
2562
2655
  var DefaultTransport = class {
@@ -2750,6 +2843,10 @@ parseWalletError_fn = function(errorPayload) {
2750
2843
  if (typeof errorData.code === "number") {
2751
2844
  error.code = errorData.code;
2752
2845
  }
2846
+ const { data } = errorData;
2847
+ if (isValidJson2(data)) {
2848
+ error.data = data;
2849
+ }
2753
2850
  return error;
2754
2851
  };
2755
2852
  isMetamaskProviderEvent_fn = function(event) {