@metamask/connect-multichain 0.5.2 → 0.6.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 (139) hide show
  1. package/CHANGELOG.md +38 -1
  2. package/README.md +415 -3
  3. package/dist/browser/es/connect-multichain.d.mts +33 -9
  4. package/dist/browser/es/connect-multichain.mjs +864 -510
  5. package/dist/browser/es/connect-multichain.mjs.map +1 -1
  6. package/dist/browser/es/metafile-esm.json +1 -1
  7. package/dist/browser/iife/connect-multichain.d.ts +33 -9
  8. package/dist/browser/iife/connect-multichain.js +24802 -24331
  9. package/dist/browser/iife/connect-multichain.js.map +1 -1
  10. package/dist/browser/iife/metafile-iife.json +1 -1
  11. package/dist/browser/umd/connect-multichain.d.ts +33 -9
  12. package/dist/browser/umd/connect-multichain.js +864 -510
  13. package/dist/browser/umd/connect-multichain.js.map +1 -1
  14. package/dist/browser/umd/metafile-cjs.json +1 -1
  15. package/dist/node/cjs/connect-multichain.d.ts +33 -9
  16. package/dist/node/cjs/connect-multichain.js +693 -340
  17. package/dist/node/cjs/connect-multichain.js.map +1 -1
  18. package/dist/node/cjs/metafile-cjs.json +1 -1
  19. package/dist/node/es/connect-multichain.d.mts +33 -9
  20. package/dist/node/es/connect-multichain.mjs +694 -339
  21. package/dist/node/es/connect-multichain.mjs.map +1 -1
  22. package/dist/node/es/metafile-esm.json +1 -1
  23. package/dist/react-native/es/connect-multichain.d.mts +33 -9
  24. package/dist/react-native/es/connect-multichain.mjs +857 -503
  25. package/dist/react-native/es/connect-multichain.mjs.map +1 -1
  26. package/dist/react-native/es/metafile-esm.json +1 -1
  27. package/dist/src/domain/logger/index.d.ts +1 -1
  28. package/dist/src/domain/logger/index.d.ts.map +1 -1
  29. package/dist/src/domain/logger/index.js.map +1 -1
  30. package/dist/src/domain/multichain/api/constants.js.map +1 -1
  31. package/dist/src/domain/multichain/api/types.d.ts +1 -1
  32. package/dist/src/domain/multichain/api/types.d.ts.map +1 -1
  33. package/dist/src/domain/multichain/index.d.ts +15 -4
  34. package/dist/src/domain/multichain/index.d.ts.map +1 -1
  35. package/dist/src/domain/multichain/index.js +14 -0
  36. package/dist/src/domain/multichain/index.js.map +1 -1
  37. package/dist/src/domain/multichain/types.d.ts +14 -0
  38. package/dist/src/domain/multichain/types.d.ts.map +1 -1
  39. package/dist/src/domain/platform/index.d.ts.map +1 -1
  40. package/dist/src/domain/platform/index.js +1 -0
  41. package/dist/src/domain/platform/index.js.map +1 -1
  42. package/dist/src/index.browser.d.ts.map +1 -1
  43. package/dist/src/index.browser.js +9 -4
  44. package/dist/src/index.browser.js.map +1 -1
  45. package/dist/src/index.native.d.ts.map +1 -1
  46. package/dist/src/index.native.js +9 -4
  47. package/dist/src/index.native.js.map +1 -1
  48. package/dist/src/index.node.d.ts.map +1 -1
  49. package/dist/src/index.node.js +8 -4
  50. package/dist/src/index.node.js.map +1 -1
  51. package/dist/src/multichain/index.d.ts +4 -3
  52. package/dist/src/multichain/index.d.ts.map +1 -1
  53. package/dist/src/multichain/index.js +181 -59
  54. package/dist/src/multichain/index.js.map +1 -1
  55. package/dist/src/multichain/rpc/handlers/rpcClient.d.ts +9 -2
  56. package/dist/src/multichain/rpc/handlers/rpcClient.d.ts.map +1 -1
  57. package/dist/src/multichain/rpc/handlers/rpcClient.js +13 -3
  58. package/dist/src/multichain/rpc/handlers/rpcClient.js.map +1 -1
  59. package/dist/src/multichain/rpc/requestRouter.d.ts +14 -1
  60. package/dist/src/multichain/rpc/requestRouter.d.ts.map +1 -1
  61. package/dist/src/multichain/rpc/requestRouter.js +27 -5
  62. package/dist/src/multichain/rpc/requestRouter.js.map +1 -1
  63. package/dist/src/multichain/transports/default/index.d.ts +5 -3
  64. package/dist/src/multichain/transports/default/index.d.ts.map +1 -1
  65. package/dist/src/multichain/transports/default/index.js +31 -28
  66. package/dist/src/multichain/transports/default/index.js.map +1 -1
  67. package/dist/src/multichain/transports/multichainApiClientWrapper/index.d.ts +3 -3
  68. package/dist/src/multichain/transports/multichainApiClientWrapper/index.d.ts.map +1 -1
  69. package/dist/src/multichain/transports/multichainApiClientWrapper/index.js +33 -29
  70. package/dist/src/multichain/transports/multichainApiClientWrapper/index.js.map +1 -1
  71. package/dist/src/multichain/transports/mwp/KeyManager.d.ts.map +1 -1
  72. package/dist/src/multichain/transports/mwp/KeyManager.js.map +1 -1
  73. package/dist/src/multichain/transports/mwp/index.d.ts +16 -3
  74. package/dist/src/multichain/transports/mwp/index.d.ts.map +1 -1
  75. package/dist/src/multichain/transports/mwp/index.js +157 -39
  76. package/dist/src/multichain/transports/mwp/index.js.map +1 -1
  77. package/dist/src/multichain/utils/analytics.d.ts.map +1 -1
  78. package/dist/src/multichain/utils/analytics.js +1 -0
  79. package/dist/src/multichain/utils/analytics.js.map +1 -1
  80. package/dist/src/multichain/utils/index.d.ts +48 -0
  81. package/dist/src/multichain/utils/index.d.ts.map +1 -1
  82. package/dist/src/multichain/utils/index.js +91 -6
  83. package/dist/src/multichain/utils/index.js.map +1 -1
  84. package/dist/src/polyfills/buffer-shim.js +5 -11
  85. package/dist/src/polyfills/buffer-shim.js.map +1 -1
  86. package/dist/src/store/adapters/node.d.ts +1 -1
  87. package/dist/src/store/adapters/node.d.ts.map +1 -1
  88. package/dist/src/store/adapters/node.js +11 -4
  89. package/dist/src/store/adapters/node.js.map +1 -1
  90. package/dist/src/store/adapters/rn.d.ts.map +1 -1
  91. package/dist/src/store/adapters/rn.js +1 -0
  92. package/dist/src/store/adapters/rn.js.map +1 -1
  93. package/dist/src/store/adapters/web.d.ts +5 -5
  94. package/dist/src/store/adapters/web.d.ts.map +1 -1
  95. package/dist/src/store/adapters/web.js +7 -1
  96. package/dist/src/store/adapters/web.js.map +1 -1
  97. package/dist/src/store/index.d.ts.map +1 -1
  98. package/dist/src/store/index.js +2 -0
  99. package/dist/src/store/index.js.map +1 -1
  100. package/dist/src/ui/ModalFactory.d.ts.map +1 -1
  101. package/dist/src/ui/ModalFactory.js +1 -4
  102. package/dist/src/ui/ModalFactory.js.map +1 -1
  103. package/dist/src/ui/index.d.ts.map +1 -1
  104. package/dist/src/ui/index.js +2 -0
  105. package/dist/src/ui/index.js.map +1 -1
  106. package/dist/src/ui/index.native.d.ts.map +1 -1
  107. package/dist/src/ui/index.native.js +4 -1
  108. package/dist/src/ui/index.native.js.map +1 -1
  109. package/dist/src/ui/modals/base/AbstractInstallModal.d.ts +2 -3
  110. package/dist/src/ui/modals/base/AbstractInstallModal.d.ts.map +1 -1
  111. package/dist/src/ui/modals/base/AbstractInstallModal.js +28 -12
  112. package/dist/src/ui/modals/base/AbstractInstallModal.js.map +1 -1
  113. package/dist/src/ui/modals/base/AbstractOTPModal.d.ts +2 -2
  114. package/dist/src/ui/modals/base/AbstractOTPModal.d.ts.map +1 -1
  115. package/dist/src/ui/modals/base/AbstractOTPModal.js.map +1 -1
  116. package/dist/src/ui/modals/base/utils.d.ts +12 -0
  117. package/dist/src/ui/modals/base/utils.d.ts.map +1 -1
  118. package/dist/src/ui/modals/base/utils.js +16 -5
  119. package/dist/src/ui/modals/base/utils.js.map +1 -1
  120. package/dist/src/ui/modals/node/install.d.ts.map +1 -1
  121. package/dist/src/ui/modals/node/install.js +1 -1
  122. package/dist/src/ui/modals/node/install.js.map +1 -1
  123. package/dist/src/ui/modals/node/otp.d.ts.map +1 -1
  124. package/dist/src/ui/modals/node/otp.js +6 -2
  125. package/dist/src/ui/modals/node/otp.js.map +1 -1
  126. package/dist/src/ui/modals/rn/install.d.ts.map +1 -1
  127. package/dist/src/ui/modals/rn/install.js +7 -3
  128. package/dist/src/ui/modals/rn/install.js.map +1 -1
  129. package/dist/src/ui/modals/rn/otp.d.ts.map +1 -1
  130. package/dist/src/ui/modals/rn/otp.js +6 -2
  131. package/dist/src/ui/modals/rn/otp.js.map +1 -1
  132. package/dist/src/ui/modals/web/install.d.ts.map +1 -1
  133. package/dist/src/ui/modals/web/install.js +1 -1
  134. package/dist/src/ui/modals/web/install.js.map +1 -1
  135. package/dist/src/ui/modals/web/otp.d.ts.map +1 -1
  136. package/dist/src/ui/modals/web/otp.js +6 -2
  137. package/dist/src/ui/modals/web/otp.js.map +1 -1
  138. package/dist/types/connect-multichain.d.ts +33 -9
  139. package/package.json +3 -3
@@ -399,6 +399,34 @@ var init_multichain = __esm({
399
399
  super();
400
400
  this.options = options;
401
401
  }
402
+ /**
403
+ * Merges the given options into the current instance options.
404
+ * Only the mergeable keys are updated (api.supportedNetworks, ui.*, mobile.*, transport.extensionId, debug).
405
+ * The main thing to note is that the value for `dapp` is not merged as it does not make sense for
406
+ * subsequent calls to `createMultichainClient` to have a different `dapp` value.
407
+ * Used when createMultichainClient is called with an existing singleton.
408
+ *
409
+ * @param partial - Options to merge/overwrite onto the current instance
410
+ */
411
+ mergeOptions(partial) {
412
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
413
+ const opts = this.options;
414
+ this.options = __spreadProps(__spreadValues({}, opts), {
415
+ api: __spreadProps(__spreadValues({}, opts.api), {
416
+ supportedNetworks: __spreadValues(__spreadValues({}, opts.api.supportedNetworks), (_b = (_a2 = partial.api) == null ? void 0 : _a2.supportedNetworks) != null ? _b : {})
417
+ }),
418
+ ui: __spreadProps(__spreadValues({}, opts.ui), {
419
+ headless: (_d = (_c = partial.ui) == null ? void 0 : _c.headless) != null ? _d : opts.ui.headless,
420
+ preferExtension: (_f = (_e = partial.ui) == null ? void 0 : _e.preferExtension) != null ? _f : opts.ui.preferExtension,
421
+ showInstallModal: (_h = (_g = partial.ui) == null ? void 0 : _g.showInstallModal) != null ? _h : opts.ui.showInstallModal
422
+ }),
423
+ mobile: __spreadValues(__spreadValues({}, opts.mobile), (_i = partial.mobile) != null ? _i : {}),
424
+ transport: __spreadProps(__spreadValues({}, (_j = opts.transport) != null ? _j : {}), {
425
+ extensionId: (_m = (_k = partial.transport) == null ? void 0 : _k.extensionId) != null ? _m : (_l = opts.transport) == null ? void 0 : _l.extensionId
426
+ }),
427
+ debug: (_n = partial.debug) != null ? _n : opts.debug
428
+ });
429
+ }
402
430
  };
403
431
  }
404
432
  });
@@ -584,11 +612,26 @@ var init_ui = __esm({
584
612
  });
585
613
 
586
614
  // src/multichain/utils/index.ts
587
- import { deflate } from "pako";
588
615
  import {
589
616
  parseCaipAccountId,
590
617
  parseCaipChainId
591
618
  } from "@metamask/utils";
619
+ import { deflate } from "pako";
620
+ function getGlobalObject() {
621
+ if (typeof globalThis !== "undefined") {
622
+ return globalThis;
623
+ }
624
+ if (typeof global !== "undefined") {
625
+ return global;
626
+ }
627
+ if (typeof self !== "undefined") {
628
+ return self;
629
+ }
630
+ if (typeof window !== "undefined") {
631
+ return window;
632
+ }
633
+ throw new Error("Unable to locate global object");
634
+ }
592
635
  function base64Encode(str) {
593
636
  if (typeof btoa !== "undefined") {
594
637
  return btoa(str);
@@ -607,8 +650,9 @@ function getDappId(dapp) {
607
650
  return (_a2 = dapp.url) != null ? _a2 : dapp.name;
608
651
  }
609
652
  function openDeeplink(options, deeplink, universalLink) {
653
+ var _a2;
610
654
  const { mobile } = options;
611
- const useDeeplink = mobile && mobile.useDeeplink !== void 0 ? mobile.useDeeplink : true;
655
+ const useDeeplink = (_a2 = mobile == null ? void 0 : mobile.useDeeplink) != null ? _a2 : true;
612
656
  if (useDeeplink) {
613
657
  if (typeof window !== "undefined") {
614
658
  window.location.href = deeplink;
@@ -621,6 +665,29 @@ function openDeeplink(options, deeplink, universalLink) {
621
665
  link.click();
622
666
  }
623
667
  }
668
+ function mergeRequestedSessionWithExisting(sessionData, scopes, caipAccountIds, sessionProperties) {
669
+ const existingCaipChainIds = Object.keys(sessionData.sessionScopes);
670
+ const existingCaipAccountIds = [];
671
+ Object.values(sessionData.sessionScopes).forEach((scopeObject) => {
672
+ if ((scopeObject == null ? void 0 : scopeObject.accounts) && Array.isArray(scopeObject.accounts)) {
673
+ scopeObject.accounts.forEach((account) => {
674
+ existingCaipAccountIds.push(account);
675
+ });
676
+ }
677
+ });
678
+ const mergedScopes = Array.from(
679
+ /* @__PURE__ */ new Set([...existingCaipChainIds, ...scopes])
680
+ );
681
+ const mergedCaipAccountIds = Array.from(
682
+ /* @__PURE__ */ new Set([...existingCaipAccountIds, ...caipAccountIds])
683
+ );
684
+ const mergedSessionProperties = __spreadValues(__spreadValues({}, sessionData.sessionProperties), sessionProperties);
685
+ return {
686
+ mergedScopes,
687
+ mergedCaipAccountIds,
688
+ mergedSessionProperties
689
+ };
690
+ }
624
691
  function getOptionalScopes(scopes) {
625
692
  return scopes.reduce(
626
693
  (prev, scope) => __spreadProps(__spreadValues({}, prev), {
@@ -649,7 +716,7 @@ function setupDappMetadata(options) {
649
716
  throw new Error("You must provide dapp url");
650
717
  }
651
718
  const BASE_64_ICON_MAX_LENGTH = 163400;
652
- const urlPattern = /^(http|https):\/\/[^\s]*$/;
719
+ const urlPattern = /^(http|https):\/\/[^\s]*$/u;
653
720
  if (options.dapp) {
654
721
  if ("iconUrl" in options.dapp) {
655
722
  if (options.dapp.iconUrl && !urlPattern.test(options.dapp.iconUrl)) {
@@ -698,9 +765,12 @@ function getValidAccounts(caipAccountIds) {
698
765
  (caipAccounts, caipAccountId) => {
699
766
  try {
700
767
  return [...caipAccounts, parseCaipAccountId(caipAccountId)];
701
- } catch (err) {
768
+ } catch (error) {
702
769
  const stringifiedAccountId = JSON.stringify(caipAccountId);
703
- console.error(`Invalid CAIP account ID: ${stringifiedAccountId}`, err);
770
+ console.error(
771
+ `Invalid CAIP account ID: ${stringifiedAccountId}`,
772
+ error
773
+ );
704
774
  return caipAccounts;
705
775
  }
706
776
  },
@@ -756,7 +826,7 @@ function addValidAccounts(optionalScopes, validAccounts) {
756
826
  }
757
827
  return result;
758
828
  }
759
- var extractFavicon;
829
+ var extractFavicon, MAX, idCounter, getUniqueRequestId;
760
830
  var init_utils = __esm({
761
831
  "src/multichain/utils/index.ts"() {
762
832
  "use strict";
@@ -775,6 +845,12 @@ var init_utils = __esm({
775
845
  }
776
846
  return favicon;
777
847
  };
848
+ MAX = 4294967295;
849
+ idCounter = Math.floor(Math.random() * MAX);
850
+ getUniqueRequestId = () => {
851
+ idCounter = (idCounter + 1) % MAX;
852
+ return idCounter;
853
+ };
778
854
  }
779
855
  });
780
856
 
@@ -861,7 +937,9 @@ var init_domain = __esm({
861
937
 
862
938
  // src/ui/modals/base/utils.ts
863
939
  function formatRemainingTime(milliseconds) {
864
- if (milliseconds <= 0) return "EXPIRED";
940
+ if (milliseconds <= 0) {
941
+ return "EXPIRED";
942
+ }
865
943
  const seconds = Math.floor(milliseconds / 1e3);
866
944
  return `${seconds}s`;
867
945
  }
@@ -874,9 +952,8 @@ function shouldLogCountdown(remainingSeconds) {
874
952
  return remainingSeconds % 10 === 0;
875
953
  } else if (remainingSeconds <= 300) {
876
954
  return remainingSeconds % 30 === 0;
877
- } else {
878
- return remainingSeconds % 60 === 0;
879
955
  }
956
+ return remainingSeconds % 60 === 0;
880
957
  }
881
958
  var init_utils3 = __esm({
882
959
  "src/ui/modals/base/utils.ts"() {
@@ -885,18 +962,18 @@ var init_utils3 = __esm({
885
962
  });
886
963
 
887
964
  // src/ui/modals/base/AbstractInstallModal.ts
888
- var logger3, AbstractInstallModal;
965
+ var logger3, _expirationInterval, _lastLoggedCountdown, AbstractInstallModal;
889
966
  var init_AbstractInstallModal = __esm({
890
967
  "src/ui/modals/base/AbstractInstallModal.ts"() {
891
968
  "use strict";
892
- init_domain();
893
969
  init_utils3();
970
+ init_domain();
894
971
  logger3 = createLogger("metamask-sdk:ui");
895
972
  AbstractInstallModal = class extends Modal {
896
973
  constructor() {
897
974
  super(...arguments);
898
- this.expirationInterval = null;
899
- this.lastLoggedCountdown = -1;
975
+ __privateAdd(this, _expirationInterval, null);
976
+ __privateAdd(this, _lastLoggedCountdown, -1);
900
977
  }
901
978
  get link() {
902
979
  return this.data;
@@ -924,17 +1001,17 @@ var init_AbstractInstallModal = __esm({
924
1001
  startExpirationCheck(connectionRequest) {
925
1002
  this.stopExpirationCheck();
926
1003
  let currentConnectionRequest = connectionRequest;
927
- this.expirationInterval = setInterval(() => __async(this, null, function* () {
1004
+ __privateSet(this, _expirationInterval, setInterval(() => __async(this, null, function* () {
928
1005
  const { sessionRequest } = currentConnectionRequest;
929
1006
  const now = Date.now();
930
1007
  const remainingMs = sessionRequest.expiresAt - now;
931
1008
  const remainingSeconds = Math.floor(remainingMs / 1e3);
932
- if (remainingMs > 0 && shouldLogCountdown(remainingSeconds) && this.lastLoggedCountdown !== remainingSeconds) {
1009
+ if (remainingMs > 0 && shouldLogCountdown(remainingSeconds) && __privateGet(this, _lastLoggedCountdown) !== remainingSeconds) {
933
1010
  const formattedTime = formatRemainingTime(remainingMs);
934
1011
  logger3(
935
1012
  `[UI: InstallModal-nodejs()] QR code expires in: ${formattedTime} (${remainingSeconds}s)`
936
1013
  );
937
- this.lastLoggedCountdown = remainingSeconds;
1014
+ __privateSet(this, _lastLoggedCountdown, remainingSeconds);
938
1015
  }
939
1016
  if (now >= sessionRequest.expiresAt) {
940
1017
  this.stopExpirationCheck();
@@ -946,7 +1023,7 @@ var init_AbstractInstallModal = __esm({
946
1023
  const generateQRCode = yield this.options.generateQRCode(
947
1024
  currentConnectionRequest
948
1025
  );
949
- this.lastLoggedCountdown = -1;
1026
+ __privateSet(this, _lastLoggedCountdown, -1);
950
1027
  this.updateLink(generateQRCode);
951
1028
  this.updateExpiresIn(remainingSeconds);
952
1029
  this.renderQRCode(generateQRCode, currentConnectionRequest);
@@ -956,18 +1033,20 @@ var init_AbstractInstallModal = __esm({
956
1033
  );
957
1034
  }
958
1035
  }
959
- }), 1e3);
1036
+ }), 1e3));
960
1037
  }
961
1038
  stopExpirationCheck() {
962
- if (this.expirationInterval) {
963
- clearInterval(this.expirationInterval);
964
- this.expirationInterval = null;
1039
+ if (__privateGet(this, _expirationInterval)) {
1040
+ clearInterval(__privateGet(this, _expirationInterval));
1041
+ __privateSet(this, _expirationInterval, null);
965
1042
  logger3(
966
1043
  "[UI: InstallModal-nodejs()] \u{1F6D1} Stopped QR code expiration checking"
967
1044
  );
968
1045
  }
969
1046
  }
970
1047
  };
1048
+ _expirationInterval = new WeakMap();
1049
+ _lastLoggedCountdown = new WeakMap();
971
1050
  }
972
1051
  });
973
1052
 
@@ -1080,7 +1159,7 @@ var node_exports2 = {};
1080
1159
  __export(node_exports2, {
1081
1160
  StoreAdapterNode: () => StoreAdapterNode
1082
1161
  });
1083
- var StoreAdapterNode;
1162
+ var _storage, StoreAdapterNode;
1084
1163
  var init_node2 = __esm({
1085
1164
  "src/store/adapters/node.ts"() {
1086
1165
  "use strict";
@@ -1089,28 +1168,32 @@ var init_node2 = __esm({
1089
1168
  constructor() {
1090
1169
  super(...arguments);
1091
1170
  this.platform = "node";
1092
- this.storage = /* @__PURE__ */ new Map();
1171
+ __privateAdd(this, _storage, /* @__PURE__ */ new Map());
1093
1172
  }
1094
1173
  get(key) {
1095
1174
  return __async(this, null, function* () {
1096
1175
  var _a2;
1097
- return (_a2 = this.storage.get(key)) != null ? _a2 : null;
1176
+ return (_a2 = __privateGet(this, _storage).get(key)) != null ? _a2 : null;
1098
1177
  });
1099
1178
  }
1100
1179
  set(key, value) {
1101
1180
  return __async(this, null, function* () {
1102
- this.storage.set(key, value);
1181
+ __privateGet(this, _storage).set(key, value);
1103
1182
  });
1104
1183
  }
1105
1184
  delete(key) {
1106
1185
  return __async(this, null, function* () {
1107
- this.storage.delete(key);
1186
+ __privateGet(this, _storage).delete(key);
1108
1187
  });
1109
1188
  }
1110
1189
  };
1190
+ _storage = new WeakMap();
1111
1191
  }
1112
1192
  });
1113
1193
 
1194
+ // src/index.node.ts
1195
+ init_domain();
1196
+
1114
1197
  // src/multichain/index.ts
1115
1198
  import { analytics as analytics2 } from "@metamask/analytics";
1116
1199
  import {
@@ -1153,7 +1236,9 @@ var RpcClient = class {
1153
1236
  }
1154
1237
  /**
1155
1238
  * Routes the request to a configured RPC node.
1156
- * @param options - The invoke method options
1239
+ *
1240
+ * @param options - The invoke method options.
1241
+ * @returns The JSON response from the RPC node.
1157
1242
  */
1158
1243
  request(options) {
1159
1244
  return __async(this, null, function* () {
@@ -1165,7 +1250,13 @@ var RpcClient = class {
1165
1250
  id: getNextRpcId()
1166
1251
  });
1167
1252
  const rpcEndpoint = this.getRpcEndpoint(options.scope);
1168
- const rpcRequest = yield this.fetchWithTimeout(rpcEndpoint, body, "POST", this.getHeaders(rpcEndpoint), 3e4);
1253
+ const rpcRequest = yield this.fetchWithTimeout(
1254
+ rpcEndpoint,
1255
+ body,
1256
+ "POST",
1257
+ this.getHeaders(rpcEndpoint),
1258
+ 3e4
1259
+ );
1169
1260
  const response = yield this.parseResponse(rpcRequest);
1170
1261
  return response;
1171
1262
  });
@@ -1175,7 +1266,9 @@ var RpcClient = class {
1175
1266
  const supportedNetworks = (_c = (_b = (_a2 = this.config) == null ? void 0 : _a2.api) == null ? void 0 : _b.supportedNetworks) != null ? _c : {};
1176
1267
  const rpcEndpoint = supportedNetworks[scope];
1177
1268
  if (!rpcEndpoint) {
1178
- throw new MissingRpcEndpointErr(`No RPC endpoint found for scope ${scope}`);
1269
+ throw new MissingRpcEndpointErr(
1270
+ `No RPC endpoint found for scope ${scope}`
1271
+ );
1179
1272
  }
1180
1273
  return rpcEndpoint;
1181
1274
  }
@@ -1203,7 +1296,7 @@ var RpcClient = class {
1203
1296
  if (error instanceof Error && error.name === "AbortError") {
1204
1297
  throw new RPCReadonlyRequestErr(`Request timeout after ${timeout}ms`);
1205
1298
  }
1206
- throw new RPCReadonlyRequestErr(error instanceof Error ? error.message : "Unknown error");
1299
+ throw new RPCReadonlyRequestErr(error.message);
1207
1300
  }
1208
1301
  });
1209
1302
  }
@@ -1248,10 +1341,12 @@ var RequestRouter = class {
1248
1341
  * The main entry point for invoking an RPC method.
1249
1342
  * This method acts as a router, determining the correct handling strategy
1250
1343
  * for the request and delegating to the appropriate private handler.
1344
+ *
1345
+ * @param options
1251
1346
  */
1252
1347
  invokeMethod(options) {
1253
1348
  return __async(this, null, function* () {
1254
- const method = options.request.method;
1349
+ const { method } = options.request;
1255
1350
  if (RPC_HANDLED_METHODS.has(method)) {
1256
1351
  return this.handleWithRpcNode(options);
1257
1352
  }
@@ -1263,6 +1358,8 @@ var RequestRouter = class {
1263
1358
  }
1264
1359
  /**
1265
1360
  * Forwards the request directly to the wallet via the transport.
1361
+ *
1362
+ * @param options
1266
1363
  */
1267
1364
  handleWithWallet(options) {
1268
1365
  return __async(this, null, function* () {
@@ -1291,7 +1388,10 @@ var RequestRouter = class {
1291
1388
  }
1292
1389
  const response = yield request;
1293
1390
  if (response.error) {
1294
- throw new RPCInvokeMethodErr(`RPC Request failed with code ${response.error.code}: ${response.error.message}`);
1391
+ const { error } = response;
1392
+ throw new RPCInvokeMethodErr(
1393
+ `RPC Request failed with code ${error.code}: ${error.message}`
1394
+ );
1295
1395
  }
1296
1396
  return response.result;
1297
1397
  }));
@@ -1299,6 +1399,8 @@ var RequestRouter = class {
1299
1399
  }
1300
1400
  /**
1301
1401
  * Routes the request to a configured RPC node.
1402
+ *
1403
+ * @param options
1302
1404
  */
1303
1405
  handleWithRpcNode(options) {
1304
1406
  return __async(this, null, function* () {
@@ -1316,10 +1418,14 @@ var RequestRouter = class {
1316
1418
  }
1317
1419
  /**
1318
1420
  * Responds directly from the SDK's session state.
1421
+ *
1422
+ * @param options
1319
1423
  */
1320
1424
  handleWithSdkState(options) {
1321
1425
  return __async(this, null, function* () {
1322
- console.warn(`Method "${options.request.method}" is configured for SDK state handling, but this is not yet implemented. Falling back to wallet passthrough.`);
1426
+ console.warn(
1427
+ `Method "${options.request.method}" is configured for SDK state handling, but this is not yet implemented. Falling back to wallet passthrough.`
1428
+ );
1323
1429
  return this.handleWithWallet(options);
1324
1430
  });
1325
1431
  }
@@ -1339,31 +1445,50 @@ withAnalyticsTracking_fn = function(options, execute) {
1339
1445
  } else {
1340
1446
  yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options);
1341
1447
  }
1448
+ if (error instanceof RPCInvokeMethodErr) {
1449
+ throw error;
1450
+ }
1342
1451
  throw new RPCInvokeMethodErr(error.message);
1343
1452
  }
1344
1453
  });
1345
1454
  };
1346
1455
  trackWalletActionRequested_fn = function(options) {
1347
1456
  return __async(this, null, function* () {
1348
- const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1457
+ const props = yield getWalletActionAnalyticsProperties(
1458
+ this.config,
1459
+ this.config.storage,
1460
+ options
1461
+ );
1349
1462
  analytics.track("mmconnect_wallet_action_requested", props);
1350
1463
  });
1351
1464
  };
1352
1465
  trackWalletActionSucceeded_fn = function(options) {
1353
1466
  return __async(this, null, function* () {
1354
- const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1467
+ const props = yield getWalletActionAnalyticsProperties(
1468
+ this.config,
1469
+ this.config.storage,
1470
+ options
1471
+ );
1355
1472
  analytics.track("mmconnect_wallet_action_succeeded", props);
1356
1473
  });
1357
1474
  };
1358
1475
  trackWalletActionFailed_fn = function(options) {
1359
1476
  return __async(this, null, function* () {
1360
- const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1477
+ const props = yield getWalletActionAnalyticsProperties(
1478
+ this.config,
1479
+ this.config.storage,
1480
+ options
1481
+ );
1361
1482
  analytics.track("mmconnect_wallet_action_failed", props);
1362
1483
  });
1363
1484
  };
1364
1485
  trackWalletActionRejected_fn = function(options) {
1365
1486
  return __async(this, null, function* () {
1366
- const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1487
+ const props = yield getWalletActionAnalyticsProperties(
1488
+ this.config,
1489
+ this.config.storage,
1490
+ options
1491
+ );
1367
1492
  analytics.track("mmconnect_wallet_action_rejected", props);
1368
1493
  });
1369
1494
  };
@@ -1374,7 +1499,7 @@ import {
1374
1499
  getDefaultTransport
1375
1500
  } from "@metamask/multichain-api-client";
1376
1501
  var DEFAULT_REQUEST_TIMEOUT = 60 * 1e3;
1377
- var _notificationCallbacks, _transport, _defaultRequestOptions, _reqId, _pendingRequests, _handleResponseListener, _handleNotificationListener, _DefaultTransport_instances, notifyCallbacks_fn, isMetamaskProviderEvent_fn, handleResponse_fn, handleNotification_fn, setupMessageListener_fn;
1502
+ var _notificationCallbacks, _transport, _defaultRequestOptions, _pendingRequests, _handleResponseListener, _handleNotificationListener, _DefaultTransport_instances, notifyCallbacks_fn, isMetamaskProviderEvent_fn, handleResponse_fn, handleNotification_fn, setupMessageListener_fn;
1378
1503
  var DefaultTransport = class {
1379
1504
  constructor() {
1380
1505
  __privateAdd(this, _DefaultTransport_instances);
@@ -1383,8 +1508,6 @@ var DefaultTransport = class {
1383
1508
  __privateAdd(this, _defaultRequestOptions, {
1384
1509
  timeout: DEFAULT_REQUEST_TIMEOUT
1385
1510
  });
1386
- // Use timestamp-based ID to avoid conflicts across disconnect/reconnect cycles
1387
- __privateAdd(this, _reqId, Date.now());
1388
1511
  __privateAdd(this, _pendingRequests, /* @__PURE__ */ new Map());
1389
1512
  __privateAdd(this, _handleResponseListener);
1390
1513
  __privateAdd(this, _handleNotificationListener);
@@ -1392,8 +1515,7 @@ var DefaultTransport = class {
1392
1515
  sendEip1193Message(payload, options) {
1393
1516
  return __async(this, null, function* () {
1394
1517
  __privateMethod(this, _DefaultTransport_instances, setupMessageListener_fn).call(this);
1395
- __privateSet(this, _reqId, __privateGet(this, _reqId) + 1);
1396
- const requestId = `${__privateGet(this, _reqId)}`;
1518
+ const requestId = String(getUniqueRequestId());
1397
1519
  const request = __spreadValues({
1398
1520
  jsonrpc: "2.0",
1399
1521
  id: requestId
@@ -1427,7 +1549,7 @@ var DefaultTransport = class {
1427
1549
  }
1428
1550
  connect(options) {
1429
1551
  return __async(this, null, function* () {
1430
- var _a2, _b, _c, _d, _e, _f, _g;
1552
+ var _a2, _b, _c, _d, _e;
1431
1553
  __privateMethod(this, _DefaultTransport_instances, setupMessageListener_fn).call(this);
1432
1554
  yield __privateGet(this, _transport).connect();
1433
1555
  const sessionRequest = yield this.request(
@@ -1438,12 +1560,19 @@ var DefaultTransport = class {
1438
1560
  throw new Error(sessionRequest.error.message);
1439
1561
  }
1440
1562
  let walletSession = sessionRequest.result;
1563
+ const createSessionParams = {
1564
+ optionalScopes: addValidAccounts(
1565
+ getOptionalScopes((_a2 = options == null ? void 0 : options.scopes) != null ? _a2 : []),
1566
+ getValidAccounts((_b = options == null ? void 0 : options.caipAccountIds) != null ? _b : [])
1567
+ ),
1568
+ sessionProperties: options == null ? void 0 : options.sessionProperties
1569
+ };
1441
1570
  if (walletSession && options && !options.forceRequest) {
1442
1571
  const currentScopes = Object.keys(
1443
- (_a2 = walletSession == null ? void 0 : walletSession.sessionScopes) != null ? _a2 : {}
1572
+ (_c = walletSession == null ? void 0 : walletSession.sessionScopes) != null ? _c : {}
1444
1573
  );
1445
- const proposedScopes = (_b = options == null ? void 0 : options.scopes) != null ? _b : [];
1446
- const proposedCaipAccountIds = (_c = options == null ? void 0 : options.caipAccountIds) != null ? _c : [];
1574
+ const proposedScopes = (_d = options == null ? void 0 : options.scopes) != null ? _d : [];
1575
+ const proposedCaipAccountIds = (_e = options == null ? void 0 : options.caipAccountIds) != null ? _e : [];
1447
1576
  const hasSameScopesAndAccounts = isSameScopesAndAccounts(
1448
1577
  currentScopes,
1449
1578
  proposedScopes,
@@ -1451,17 +1580,6 @@ var DefaultTransport = class {
1451
1580
  proposedCaipAccountIds
1452
1581
  );
1453
1582
  if (!hasSameScopesAndAccounts) {
1454
- yield this.request(
1455
- { method: "wallet_revokeSession", params: walletSession },
1456
- __privateGet(this, _defaultRequestOptions)
1457
- );
1458
- const optionalScopes = addValidAccounts(
1459
- getOptionalScopes((_d = options == null ? void 0 : options.scopes) != null ? _d : []),
1460
- getValidAccounts((_e = options == null ? void 0 : options.caipAccountIds) != null ? _e : [])
1461
- );
1462
- const createSessionParams = {
1463
- optionalScopes
1464
- };
1465
1583
  const response = yield this.request(
1466
1584
  { method: "wallet_createSession", params: createSessionParams },
1467
1585
  __privateGet(this, _defaultRequestOptions)
@@ -1472,14 +1590,6 @@ var DefaultTransport = class {
1472
1590
  walletSession = response.result;
1473
1591
  }
1474
1592
  } else if (!walletSession || (options == null ? void 0 : options.forceRequest)) {
1475
- const optionalScopes = addValidAccounts(
1476
- getOptionalScopes((_f = options == null ? void 0 : options.scopes) != null ? _f : []),
1477
- getValidAccounts((_g = options == null ? void 0 : options.caipAccountIds) != null ? _g : [])
1478
- );
1479
- const createSessionParams = {
1480
- optionalScopes,
1481
- sessionProperties: options == null ? void 0 : options.sessionProperties
1482
- };
1483
1593
  const response = yield this.request(
1484
1594
  { method: "wallet_createSession", params: createSessionParams },
1485
1595
  __privateGet(this, _defaultRequestOptions)
@@ -1496,9 +1606,14 @@ var DefaultTransport = class {
1496
1606
  });
1497
1607
  }
1498
1608
  disconnect() {
1499
- return __async(this, null, function* () {
1609
+ return __async(this, arguments, function* (scopes = []) {
1610
+ yield this.request({ method: "wallet_revokeSession", params: { scopes } });
1611
+ const response = yield this.request({ method: "wallet_getSession" });
1612
+ const { sessionScopes } = response.result;
1613
+ if (Object.keys(sessionScopes).length > 0) {
1614
+ return;
1615
+ }
1500
1616
  __privateGet(this, _notificationCallbacks).clear();
1501
- yield this.request({ method: "wallet_revokeSession", params: {} });
1502
1617
  if (__privateGet(this, _handleResponseListener)) {
1503
1618
  window.removeEventListener("message", __privateGet(this, _handleResponseListener));
1504
1619
  __privateSet(this, _handleResponseListener, void 0);
@@ -1512,7 +1627,7 @@ var DefaultTransport = class {
1512
1627
  request.reject(new Error("Transport disconnected"));
1513
1628
  }
1514
1629
  __privateGet(this, _pendingRequests).clear();
1515
- return __privateGet(this, _transport).disconnect();
1630
+ yield __privateGet(this, _transport).disconnect();
1516
1631
  });
1517
1632
  }
1518
1633
  isConnected() {
@@ -1531,13 +1646,23 @@ var DefaultTransport = class {
1531
1646
  };
1532
1647
  }
1533
1648
  getActiveSession() {
1534
- throw new Error("getActiveSession is purposely not implemented for the DefaultTransport");
1649
+ return __async(this, null, function* () {
1650
+ throw new Error(
1651
+ "getActiveSession is purposely not implemented for the DefaultTransport"
1652
+ );
1653
+ });
1654
+ }
1655
+ getStoredPendingSessionRequest() {
1656
+ return __async(this, null, function* () {
1657
+ throw new Error(
1658
+ "getStoredPendingSessionRequest is purposely not implemented for the DefaultTransport"
1659
+ );
1660
+ });
1535
1661
  }
1536
1662
  };
1537
1663
  _notificationCallbacks = new WeakMap();
1538
1664
  _transport = new WeakMap();
1539
1665
  _defaultRequestOptions = new WeakMap();
1540
- _reqId = new WeakMap();
1541
1666
  _pendingRequests = new WeakMap();
1542
1667
  _handleResponseListener = new WeakMap();
1543
1668
  _handleNotificationListener = new WeakMap();
@@ -1605,6 +1730,166 @@ setupMessageListener_fn = function() {
1605
1730
  window.addEventListener("message", __privateGet(this, _handleNotificationListener));
1606
1731
  };
1607
1732
 
1733
+ // src/multichain/transports/multichainApiClientWrapper/index.ts
1734
+ init_utils();
1735
+ import { providerErrors } from "@metamask/rpc-errors";
1736
+ var _notificationCallbacks2, _MultichainApiClientWrapperTransport_instances, walletCreateSession_fn, walletGetSession_fn, walletRevokeSession_fn, walletInvokeMethod_fn;
1737
+ var MultichainApiClientWrapperTransport = class {
1738
+ constructor(metamaskConnectMultichain) {
1739
+ this.metamaskConnectMultichain = metamaskConnectMultichain;
1740
+ __privateAdd(this, _MultichainApiClientWrapperTransport_instances);
1741
+ __privateAdd(this, _notificationCallbacks2, /* @__PURE__ */ new Set());
1742
+ }
1743
+ isTransportDefined() {
1744
+ try {
1745
+ return Boolean(this.metamaskConnectMultichain.transport);
1746
+ } catch (_error) {
1747
+ return false;
1748
+ }
1749
+ }
1750
+ clearNotificationCallbacks() {
1751
+ __privateGet(this, _notificationCallbacks2).clear();
1752
+ }
1753
+ notifyCallbacks(data) {
1754
+ __privateGet(this, _notificationCallbacks2).forEach((callback) => {
1755
+ callback(data);
1756
+ });
1757
+ }
1758
+ clearTransportNotificationListener() {
1759
+ var _a2;
1760
+ (_a2 = this.notificationListener) == null ? void 0 : _a2.call(this);
1761
+ this.notificationListener = void 0;
1762
+ }
1763
+ setupTransportNotificationListener() {
1764
+ if (!this.isTransportDefined() || this.notificationListener) {
1765
+ return;
1766
+ }
1767
+ this.notificationListener = this.metamaskConnectMultichain.transport.onNotification(
1768
+ this.notifyCallbacks.bind(this)
1769
+ );
1770
+ }
1771
+ connect() {
1772
+ return __async(this, null, function* () {
1773
+ console.log("\u{1F4DA} connect");
1774
+ yield this.metamaskConnectMultichain.emitSessionChanged();
1775
+ });
1776
+ }
1777
+ disconnect() {
1778
+ return __async(this, null, function* () {
1779
+ return Promise.resolve();
1780
+ });
1781
+ }
1782
+ isConnected() {
1783
+ return true;
1784
+ }
1785
+ request(_0) {
1786
+ return __async(this, arguments, function* (params, _options = {}) {
1787
+ const id = getUniqueRequestId();
1788
+ const requestPayload = __spreadValues({
1789
+ id,
1790
+ jsonrpc: "2.0"
1791
+ }, params);
1792
+ switch (requestPayload.method) {
1793
+ case "wallet_createSession":
1794
+ return __privateMethod(this, _MultichainApiClientWrapperTransport_instances, walletCreateSession_fn).call(this, requestPayload);
1795
+ case "wallet_getSession":
1796
+ return __privateMethod(this, _MultichainApiClientWrapperTransport_instances, walletGetSession_fn).call(this, requestPayload);
1797
+ case "wallet_revokeSession":
1798
+ return __privateMethod(this, _MultichainApiClientWrapperTransport_instances, walletRevokeSession_fn).call(this, requestPayload);
1799
+ case "wallet_invokeMethod":
1800
+ return __privateMethod(this, _MultichainApiClientWrapperTransport_instances, walletInvokeMethod_fn).call(this, requestPayload);
1801
+ default:
1802
+ throw new Error(`Unsupported method: ${requestPayload.method}`);
1803
+ }
1804
+ throw new Error(`Unknown method: ${requestPayload.method}`);
1805
+ });
1806
+ }
1807
+ onNotification(callback) {
1808
+ this.setupTransportNotificationListener();
1809
+ __privateGet(this, _notificationCallbacks2).add(callback);
1810
+ return () => {
1811
+ __privateGet(this, _notificationCallbacks2).delete(callback);
1812
+ };
1813
+ }
1814
+ };
1815
+ _notificationCallbacks2 = new WeakMap();
1816
+ _MultichainApiClientWrapperTransport_instances = new WeakSet();
1817
+ walletCreateSession_fn = function(request) {
1818
+ return __async(this, null, function* () {
1819
+ console.log("\u{1F4DA} #walletCreateSession", request);
1820
+ const createSessionParams = request.params;
1821
+ const scopes = Object.keys(__spreadValues(__spreadValues({}, createSessionParams.optionalScopes), createSessionParams.requiredScopes));
1822
+ const scopeAccounts = [];
1823
+ scopes.forEach((scope) => {
1824
+ var _a2, _b, _c, _d;
1825
+ const requiredScope = (_a2 = createSessionParams.requiredScopes) == null ? void 0 : _a2[scope];
1826
+ const optionalScope = (_b = createSessionParams.optionalScopes) == null ? void 0 : _b[scope];
1827
+ if (requiredScope) {
1828
+ scopeAccounts.push(...(_c = requiredScope.accounts) != null ? _c : []);
1829
+ }
1830
+ if (optionalScope) {
1831
+ scopeAccounts.push(...(_d = optionalScope.accounts) != null ? _d : []);
1832
+ }
1833
+ });
1834
+ const accounts = [...new Set(scopeAccounts)];
1835
+ console.log("\u{1F4DA} SDK connect");
1836
+ yield this.metamaskConnectMultichain.connect(
1837
+ scopes,
1838
+ accounts,
1839
+ createSessionParams.sessionProperties
1840
+ );
1841
+ console.log("\u{1F4DA} SDK connected");
1842
+ return this.metamaskConnectMultichain.transport.request({
1843
+ method: "wallet_getSession"
1844
+ });
1845
+ });
1846
+ };
1847
+ walletGetSession_fn = function(request) {
1848
+ return __async(this, null, function* () {
1849
+ if (!this.isTransportDefined()) {
1850
+ return {
1851
+ jsonrpc: "2.0",
1852
+ id: request.id,
1853
+ result: {
1854
+ sessionScopes: {}
1855
+ }
1856
+ };
1857
+ }
1858
+ return this.metamaskConnectMultichain.transport.request({
1859
+ method: "wallet_getSession"
1860
+ });
1861
+ });
1862
+ };
1863
+ walletRevokeSession_fn = function(request) {
1864
+ return __async(this, null, function* () {
1865
+ var _a2;
1866
+ if (!this.isTransportDefined()) {
1867
+ return { jsonrpc: "2.0", id: request.id, result: true };
1868
+ }
1869
+ const revokeSessionParams = request.params;
1870
+ const scopes = (_a2 = revokeSessionParams == null ? void 0 : revokeSessionParams.scopes) != null ? _a2 : [];
1871
+ try {
1872
+ yield this.metamaskConnectMultichain.disconnect(scopes);
1873
+ return { jsonrpc: "2.0", id: request.id, result: true };
1874
+ } catch (_error) {
1875
+ return { jsonrpc: "2.0", id: request.id, result: false };
1876
+ }
1877
+ });
1878
+ };
1879
+ walletInvokeMethod_fn = function(request) {
1880
+ return __async(this, null, function* () {
1881
+ if (!this.isTransportDefined()) {
1882
+ return { error: providerErrors.unauthorized() };
1883
+ }
1884
+ const result = this.metamaskConnectMultichain.invokeMethod(
1885
+ request.params
1886
+ );
1887
+ return {
1888
+ result
1889
+ };
1890
+ });
1891
+ };
1892
+
1608
1893
  // src/multichain/transports/mwp/index.ts
1609
1894
  init_domain();
1610
1895
  init_utils();
@@ -1612,6 +1897,7 @@ import { SessionStore } from "@metamask/mobile-wallet-protocol-core";
1612
1897
  import {
1613
1898
  TransportTimeoutError
1614
1899
  } from "@metamask/multichain-api-client";
1900
+ import { providerErrors as providerErrors2, rpcErrors } from "@metamask/rpc-errors";
1615
1901
 
1616
1902
  // src/multichain/transports/constants.ts
1617
1903
  var MULTICHAIN_PROVIDER_STREAM_NAME = "metamask-multichain-provider";
@@ -1624,6 +1910,7 @@ var DEFAULT_RESUME_TIMEOUT = 10 * 1e3;
1624
1910
  var SESSION_STORE_KEY = "cache_wallet_getSession";
1625
1911
  var ACCOUNTS_STORE_KEY = "cache_eth_accounts";
1626
1912
  var CHAIN_STORE_KEY = "cache_eth_chainId";
1913
+ var PENDING_SESSION_REQUEST_KEY = "pending_session_request";
1627
1914
  var CACHED_METHOD_LIST = [
1628
1915
  "wallet_getSession",
1629
1916
  "wallet_createSession",
@@ -1643,10 +1930,15 @@ var MWPTransport = class {
1643
1930
  this.dappClient = dappClient;
1644
1931
  this.kvstore = kvstore;
1645
1932
  this.options = options;
1646
- this.__reqId = 0;
1647
1933
  this.__pendingRequests = /* @__PURE__ */ new Map();
1648
1934
  this.notificationCallbacks = /* @__PURE__ */ new Set();
1649
1935
  this.dappClient.on("message", this.handleMessage.bind(this));
1936
+ this.dappClient.on("session_request", (sessionRequest) => {
1937
+ this.currentSessionRequest = sessionRequest;
1938
+ this.kvstore.set(PENDING_SESSION_REQUEST_KEY, JSON.stringify(sessionRequest)).catch((err) => {
1939
+ logger("Failed to store pending session request", err);
1940
+ });
1941
+ });
1650
1942
  if (typeof window !== "undefined" && typeof window.addEventListener !== "undefined") {
1651
1943
  this.windowFocusHandler = this.onWindowFocus.bind(this);
1652
1944
  window.addEventListener("focus", this.windowFocusHandler);
@@ -1661,6 +1953,34 @@ var MWPTransport = class {
1661
1953
  get sessionRequest() {
1662
1954
  return this.currentSessionRequest;
1663
1955
  }
1956
+ /**
1957
+ * Returns the stored pending session request from the dappClient session_request event, if any.
1958
+ *
1959
+ * @returns The stored SessionRequest, or null if none or invalid.
1960
+ */
1961
+ getStoredPendingSessionRequest() {
1962
+ return __async(this, null, function* () {
1963
+ try {
1964
+ const raw = yield this.kvstore.get(PENDING_SESSION_REQUEST_KEY);
1965
+ if (!raw) {
1966
+ return null;
1967
+ }
1968
+ return JSON.parse(raw);
1969
+ } catch (e) {
1970
+ return null;
1971
+ }
1972
+ });
1973
+ }
1974
+ /**
1975
+ * Removes the stored pending session request from the KVStore.
1976
+ * This is necessary to ensure that ConnectMultichain is able to correctly
1977
+ * infer the MWP Transport connection attempt status.
1978
+ */
1979
+ removeStoredPendingSessionRequest() {
1980
+ return __async(this, null, function* () {
1981
+ yield this.kvstore.delete(PENDING_SESSION_REQUEST_KEY);
1982
+ });
1983
+ }
1664
1984
  onWindowFocus() {
1665
1985
  if (!this.isConnected()) {
1666
1986
  this.dappClient.reconnect();
@@ -1677,6 +1997,17 @@ var MWPTransport = class {
1677
1997
  request.reject(error);
1678
1998
  }
1679
1999
  }
2000
+ parseWalletError(errorPayload) {
2001
+ const errorData = errorPayload;
2002
+ if (typeof errorData.code === "number" && typeof errorData.message === "string") {
2003
+ return providerErrors2.custom({
2004
+ code: errorData.code,
2005
+ message: errorData.message
2006
+ });
2007
+ }
2008
+ const message = errorPayload instanceof Error ? errorPayload.message : JSON.stringify(errorPayload);
2009
+ return rpcErrors.internal({ message });
2010
+ }
1680
2011
  handleMessage(message) {
1681
2012
  if (typeof message === "object" && message !== null) {
1682
2013
  if ("data" in message) {
@@ -1684,6 +2015,12 @@ var MWPTransport = class {
1684
2015
  if ("id" in messagePayload && typeof messagePayload.id === "string") {
1685
2016
  const request = this.pendingRequests.get(messagePayload.id);
1686
2017
  if (request) {
2018
+ clearTimeout(request.timeout);
2019
+ if ("error" in messagePayload && messagePayload.error) {
2020
+ this.pendingRequests.delete(messagePayload.id);
2021
+ request.reject(this.parseWalletError(messagePayload.error));
2022
+ return;
2023
+ }
1687
2024
  const requestWithName = __spreadProps(__spreadValues({}, messagePayload), {
1688
2025
  method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method
1689
2026
  });
@@ -1691,7 +2028,6 @@ var MWPTransport = class {
1691
2028
  method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method,
1692
2029
  params: requestWithName.result
1693
2030
  });
1694
- clearTimeout(request.timeout);
1695
2031
  this.notifyCallbacks(notification);
1696
2032
  request.resolve(requestWithName);
1697
2033
  this.pendingRequests.delete(messagePayload.id);
@@ -1781,6 +2117,7 @@ var MWPTransport = class {
1781
2117
  }
1782
2118
  walletSession = response.result;
1783
2119
  }
2120
+ yield this.removeStoredPendingSessionRequest();
1784
2121
  this.notifyCallbacks({
1785
2122
  method: "wallet_sessionChanged",
1786
2123
  params: walletSession
@@ -1796,7 +2133,7 @@ var MWPTransport = class {
1796
2133
  return __async(this, null, function* () {
1797
2134
  const request = __spreadValues({
1798
2135
  jsonrpc: "2.0",
1799
- id: `${this.__reqId++}`
2136
+ id: String(getUniqueRequestId())
1800
2137
  }, payload);
1801
2138
  const cachedWalletSession = yield this.getCachedResponse(request);
1802
2139
  if (cachedWalletSession) {
@@ -1832,6 +2169,7 @@ var MWPTransport = class {
1832
2169
  if (session) {
1833
2170
  logger("active session found", session);
1834
2171
  }
2172
+ const storedSessionRequestBeforeConnectionAttempt = yield this.getStoredPendingSessionRequest();
1835
2173
  let timeout;
1836
2174
  let initialConnectionMessageHandler;
1837
2175
  const connectionPromise = new Promise((resolve, reject) => __async(this, null, function* () {
@@ -1862,33 +2200,35 @@ var MWPTransport = class {
1862
2200
  };
1863
2201
  const request = {
1864
2202
  jsonrpc: "2.0",
1865
- id: `${this.__reqId++}`,
2203
+ id: String(getUniqueRequestId()),
1866
2204
  method: "wallet_createSession",
1867
2205
  params: sessionRequest
1868
2206
  };
1869
2207
  initialConnectionMessageHandler = (message) => __async(this, null, function* () {
1870
- if (typeof message === "object" && message !== null) {
1871
- if ("data" in message) {
1872
- const messagePayload = message.data;
1873
- if (messagePayload.method === "wallet_createSession" || messagePayload.method === "wallet_sessionChanged") {
1874
- if (messagePayload.error) {
1875
- if (initialConnectionMessageHandler) {
1876
- this.dappClient.off(
1877
- "message",
1878
- initialConnectionMessageHandler
1879
- );
1880
- }
1881
- return rejectConnection(messagePayload.error);
1882
- }
1883
- yield this.storeWalletSession(
1884
- request,
1885
- messagePayload
1886
- );
1887
- this.notifyCallbacks(messagePayload);
1888
- return resolveConnection();
1889
- }
1890
- }
2208
+ if (typeof message !== "object" || message === null) {
2209
+ return;
2210
+ }
2211
+ if (!("data" in message)) {
2212
+ return;
2213
+ }
2214
+ const messagePayload = message.data;
2215
+ const isMatchingId = messagePayload.id === request.id;
2216
+ const isMatchingMethod = messagePayload.method === "wallet_createSession" || messagePayload.method === "wallet_sessionChanged";
2217
+ if (!isMatchingId && !isMatchingMethod) {
2218
+ return;
1891
2219
  }
2220
+ if (messagePayload.error) {
2221
+ return rejectConnection(
2222
+ this.parseWalletError(messagePayload.error)
2223
+ );
2224
+ }
2225
+ yield this.storeWalletSession(
2226
+ request,
2227
+ messagePayload
2228
+ );
2229
+ yield this.removeStoredPendingSessionRequest();
2230
+ this.notifyCallbacks(messagePayload);
2231
+ return resolveConnection();
1892
2232
  });
1893
2233
  this.dappClient.on("message", initialConnectionMessageHandler);
1894
2234
  dappClient.connect({
@@ -1909,14 +2249,18 @@ var MWPTransport = class {
1909
2249
  }
1910
2250
  );
1911
2251
  }
1912
- timeout = setTimeout(() => {
1913
- reject(new TransportTimeoutError());
1914
- }, this.options.connectionTimeout);
2252
+ timeout = setTimeout(
2253
+ () => {
2254
+ reject(new TransportTimeoutError());
2255
+ },
2256
+ storedSessionRequestBeforeConnectionAttempt ? this.options.resumeTimeout : this.options.connectionTimeout
2257
+ );
1915
2258
  connection.then(resolve).catch(reject);
1916
2259
  }));
1917
- return connectionPromise.catch((error) => {
2260
+ return connectionPromise.catch((error) => __async(this, null, function* () {
2261
+ yield this.dappClient.disconnect();
1918
2262
  throw error;
1919
- }).finally(() => {
2263
+ })).finally(() => {
1920
2264
  if (timeout) {
1921
2265
  clearTimeout(timeout);
1922
2266
  }
@@ -1924,24 +2268,68 @@ var MWPTransport = class {
1924
2268
  this.dappClient.off("message", initialConnectionMessageHandler);
1925
2269
  initialConnectionMessageHandler = void 0;
1926
2270
  }
2271
+ this.removeStoredPendingSessionRequest();
1927
2272
  });
1928
2273
  });
1929
2274
  }
1930
2275
  /**
1931
2276
  * Disconnects from the Mobile Wallet Protocol
1932
2277
  *
2278
+ * @param [scopes] - The scopes to revoke. If not provided or empty, all scopes will be revoked.
1933
2279
  * @returns Nothing
1934
2280
  */
1935
2281
  disconnect() {
1936
- return __async(this, null, function* () {
1937
- if (typeof window !== "undefined" && typeof window.removeEventListener !== "undefined" && this.windowFocusHandler) {
1938
- window.removeEventListener("focus", this.windowFocusHandler);
1939
- this.windowFocusHandler = void 0;
1940
- }
1941
- this.kvstore.delete(SESSION_STORE_KEY);
1942
- this.kvstore.delete(ACCOUNTS_STORE_KEY);
1943
- this.kvstore.delete(CHAIN_STORE_KEY);
1944
- return this.dappClient.disconnect();
2282
+ return __async(this, arguments, function* (scopes = []) {
2283
+ var _a2, _b;
2284
+ const cachedSession = yield this.getCachedResponse({
2285
+ jsonrpc: "2.0",
2286
+ id: "0",
2287
+ method: "wallet_getSession"
2288
+ });
2289
+ const cachedSessionScopes = (_b = (_a2 = cachedSession == null ? void 0 : cachedSession.result) == null ? void 0 : _a2.sessionScopes) != null ? _b : {};
2290
+ const remainingScopes = scopes.length === 0 ? [] : Object.keys(cachedSessionScopes).filter(
2291
+ (scope) => !scopes.includes(scope)
2292
+ );
2293
+ const newSessionScopes = Object.fromEntries(
2294
+ Object.entries(cachedSessionScopes).filter(
2295
+ ([key]) => remainingScopes.includes(key)
2296
+ )
2297
+ );
2298
+ this.request({ method: "wallet_revokeSession", params: { scopes } }).catch(
2299
+ (err) => {
2300
+ console.error("error revoking session", err);
2301
+ }
2302
+ );
2303
+ const remainingScopesIncludeEip155 = remainingScopes.some(
2304
+ (scope) => scope.includes("eip155")
2305
+ );
2306
+ if (!remainingScopesIncludeEip155) {
2307
+ this.kvstore.delete(ACCOUNTS_STORE_KEY);
2308
+ this.kvstore.delete(CHAIN_STORE_KEY);
2309
+ }
2310
+ if (remainingScopes.length > 0) {
2311
+ this.kvstore.set(
2312
+ SESSION_STORE_KEY,
2313
+ JSON.stringify({
2314
+ result: {
2315
+ sessionScopes: newSessionScopes
2316
+ }
2317
+ })
2318
+ );
2319
+ } else {
2320
+ this.kvstore.delete(SESSION_STORE_KEY);
2321
+ if (typeof window !== "undefined" && typeof window.removeEventListener !== "undefined" && this.windowFocusHandler) {
2322
+ window.removeEventListener("focus", this.windowFocusHandler);
2323
+ this.windowFocusHandler = void 0;
2324
+ }
2325
+ yield this.dappClient.disconnect();
2326
+ }
2327
+ this.notifyCallbacks({
2328
+ method: "wallet_sessionChanged",
2329
+ params: {
2330
+ sessionScopes: newSessionScopes
2331
+ }
2332
+ });
1945
2333
  });
1946
2334
  }
1947
2335
  /**
@@ -2047,7 +2435,7 @@ var MWPTransport = class {
2047
2435
  return __async(this, null, function* () {
2048
2436
  const request = __spreadValues({
2049
2437
  jsonrpc: "2.0",
2050
- id: `${this.__reqId++}`
2438
+ id: String(getUniqueRequestId())
2051
2439
  }, payload);
2052
2440
  const cachedWalletSession = yield this.getCachedResponse(request);
2053
2441
  if (cachedWalletSession) {
@@ -2129,6 +2517,7 @@ var MWPTransport = class {
2129
2517
  const timeoutPromise = new Promise((_resolve, reject) => {
2130
2518
  setTimeout(() => {
2131
2519
  unsubscribe();
2520
+ this.removeStoredPendingSessionRequest();
2132
2521
  reject(new TransportTimeoutError());
2133
2522
  }, this.options.resumeTimeout);
2134
2523
  });
@@ -2166,166 +2555,9 @@ var keymanager = new KeyManager();
2166
2555
 
2167
2556
  // src/multichain/index.ts
2168
2557
  init_utils();
2169
-
2170
- // src/multichain/transports/multichainApiClientWrapper/index.ts
2171
- import { providerErrors } from "@metamask/rpc-errors";
2172
- var MAX = 4294967295;
2173
- var idCounter = Math.floor(Math.random() * MAX);
2174
- var getUniqueId = () => {
2175
- idCounter = (idCounter + 1) % MAX;
2176
- return idCounter;
2177
- };
2178
- var _MultichainApiClientWrapperTransport_instances, walletCreateSession_fn, walletGetSession_fn, walletRevokeSession_fn, walletInvokeMethod_fn;
2179
- var MultichainApiClientWrapperTransport = class {
2180
- constructor(metamaskConnectMultichain) {
2181
- this.metamaskConnectMultichain = metamaskConnectMultichain;
2182
- __privateAdd(this, _MultichainApiClientWrapperTransport_instances);
2183
- this.requestId = getUniqueId();
2184
- this.notificationCallbacks = /* @__PURE__ */ new Set();
2185
- }
2186
- isTransportDefined() {
2187
- try {
2188
- return Boolean(this.metamaskConnectMultichain.transport);
2189
- } catch (error) {
2190
- return false;
2191
- }
2192
- }
2193
- clearNotificationCallbacks() {
2194
- this.notificationCallbacks.clear();
2195
- }
2196
- notifyCallbacks(data) {
2197
- this.notificationCallbacks.forEach((callback) => {
2198
- callback(data);
2199
- });
2200
- }
2201
- setupNotifcationListener() {
2202
- this.metamaskConnectMultichain.transport.onNotification(
2203
- this.notifyCallbacks.bind(this)
2204
- );
2205
- }
2206
- connect() {
2207
- return __async(this, null, function* () {
2208
- console.log("\u{1F4DA} connect");
2209
- return Promise.resolve();
2210
- });
2211
- }
2212
- disconnect() {
2213
- return __async(this, null, function* () {
2214
- return Promise.resolve();
2215
- });
2216
- }
2217
- isConnected() {
2218
- return true;
2219
- }
2220
- request(_0) {
2221
- return __async(this, arguments, function* (params, _options = {}) {
2222
- const id = this.requestId++;
2223
- const requestPayload = __spreadValues({
2224
- id,
2225
- jsonrpc: "2.0"
2226
- }, params);
2227
- switch (requestPayload.method) {
2228
- case "wallet_createSession":
2229
- return __privateMethod(this, _MultichainApiClientWrapperTransport_instances, walletCreateSession_fn).call(this, requestPayload);
2230
- case "wallet_getSession":
2231
- return __privateMethod(this, _MultichainApiClientWrapperTransport_instances, walletGetSession_fn).call(this, requestPayload);
2232
- case "wallet_revokeSession":
2233
- return __privateMethod(this, _MultichainApiClientWrapperTransport_instances, walletRevokeSession_fn).call(this, requestPayload);
2234
- case "wallet_invokeMethod":
2235
- return __privateMethod(this, _MultichainApiClientWrapperTransport_instances, walletInvokeMethod_fn).call(this, requestPayload);
2236
- default:
2237
- throw new Error(`Unsupported method: ${requestPayload.method}`);
2238
- }
2239
- throw new Error(`Unknown method: ${requestPayload.method}`);
2240
- });
2241
- }
2242
- onNotification(callback) {
2243
- if (!this.isTransportDefined()) {
2244
- this.notificationCallbacks.add(callback);
2245
- return () => {
2246
- this.notificationCallbacks.delete(callback);
2247
- };
2248
- }
2249
- return this.metamaskConnectMultichain.transport.onNotification(callback);
2250
- }
2251
- };
2252
- _MultichainApiClientWrapperTransport_instances = new WeakSet();
2253
- walletCreateSession_fn = function(request) {
2254
- return __async(this, null, function* () {
2255
- console.log("\u{1F4DA} #walletCreateSession", request);
2256
- const createSessionParams = request.params;
2257
- const scopes = Object.keys(__spreadValues(__spreadValues({}, createSessionParams.optionalScopes), createSessionParams.requiredScopes));
2258
- const scopeAccounts = [];
2259
- scopes.forEach((scope) => {
2260
- var _a2, _b, _c, _d;
2261
- const requiredScope = (_a2 = createSessionParams.requiredScopes) == null ? void 0 : _a2[scope];
2262
- const optionalScope = (_b = createSessionParams.optionalScopes) == null ? void 0 : _b[scope];
2263
- if (requiredScope) {
2264
- scopeAccounts.push(...(_c = requiredScope.accounts) != null ? _c : []);
2265
- }
2266
- if (optionalScope) {
2267
- scopeAccounts.push(...(_d = optionalScope.accounts) != null ? _d : []);
2268
- }
2269
- });
2270
- const accounts = [...new Set(scopeAccounts)];
2271
- console.log("\u{1F4DA} SDK connect");
2272
- yield this.metamaskConnectMultichain.connect(
2273
- scopes,
2274
- accounts,
2275
- createSessionParams.sessionProperties
2276
- );
2277
- console.log("\u{1F4DA} SDK connected");
2278
- return this.metamaskConnectMultichain.transport.request({
2279
- method: "wallet_getSession"
2280
- });
2281
- });
2282
- };
2283
- walletGetSession_fn = function(request) {
2284
- return __async(this, null, function* () {
2285
- if (!this.isTransportDefined()) {
2286
- return {
2287
- jsonrpc: "2.0",
2288
- id: request.id,
2289
- result: {
2290
- sessionScopes: {}
2291
- }
2292
- };
2293
- }
2294
- return this.metamaskConnectMultichain.transport.request({
2295
- method: "wallet_getSession"
2296
- });
2297
- });
2298
- };
2299
- walletRevokeSession_fn = function(request) {
2300
- return __async(this, null, function* () {
2301
- if (!this.isTransportDefined()) {
2302
- return { jsonrpc: "2.0", id: request.id, result: true };
2303
- }
2304
- try {
2305
- this.metamaskConnectMultichain.disconnect();
2306
- return { jsonrpc: "2.0", id: request.id, result: true };
2307
- } catch (error) {
2308
- return { jsonrpc: "2.0", id: request.id, result: false };
2309
- }
2310
- });
2311
- };
2312
- walletInvokeMethod_fn = function(request) {
2313
- return __async(this, null, function* () {
2314
- if (!this.isTransportDefined()) {
2315
- return { error: providerErrors.unauthorized() };
2316
- }
2317
- const result = this.metamaskConnectMultichain.invokeMethod(
2318
- request.params
2319
- );
2320
- return {
2321
- result
2322
- };
2323
- });
2324
- };
2325
-
2326
- // src/multichain/index.ts
2327
2558
  var logger2 = createLogger("metamask-sdk:core");
2328
- var _a, _provider, _providerTransportWrapper, _transport2, _dappClient, _beforeUnloadListener, _listener, _sdkInfo, _MetaMaskConnectMultichain_instances, setupAnalytics_fn, onTransportNotification_fn, getStoredTransport_fn, setupTransport_fn, init_fn, createDappClient_fn, setupMWP_fn, onBeforeUnload_fn, createBeforeUnloadListener_fn, renderInstallModalAsync_fn, showInstallModal_fn, headlessConnect_fn, setupDefaultTransport_fn, deeplinkConnect_fn, handleConnection_fn;
2559
+ var SINGLETON_KEY = "__METAMASK_CONNECT_MULTICHAIN_SINGLETON__";
2560
+ var _a, _provider, _providerTransportWrapper, _transport2, _dappClient, _beforeUnloadListener, _listener, _sdkInfo, _MetaMaskConnectMultichain_instances, setupAnalytics_fn, onTransportNotification_fn, getStoredTransport_fn, setupTransport_fn, init_fn, createDappClient_fn, setupMWP_fn, onBeforeUnload_fn, createBeforeUnloadListener_fn, renderInstallModalAsync_fn, showInstallModal_fn, headlessConnect_fn, setupDefaultTransport_fn, deeplinkConnect_fn, handleConnection_fn, getCaipSession_fn, openConnectDeeplinkIfNeeded_fn;
2329
2561
  var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends MultichainCore {
2330
2562
  constructor(options) {
2331
2563
  var _a2, _b, _c, _d, _e, _f;
@@ -2351,8 +2583,12 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2351
2583
  this._status = "pending";
2352
2584
  __privateAdd(this, _listener);
2353
2585
  __privateAdd(this, _sdkInfo, `Sdk/Javascript SdkVersion/${getVersion()} Platform/${getPlatformType()} dApp/${(_a = this.options.dapp.url) != null ? _a : this.options.dapp.name} dAppTitle/${this.options.dapp.name}`);
2354
- __privateSet(this, _providerTransportWrapper, new MultichainApiClientWrapperTransport(this));
2355
- __privateSet(this, _provider, getMultichainClient({ transport: __privateGet(this, _providerTransportWrapper) }));
2586
+ __privateSet(this, _providerTransportWrapper, new MultichainApiClientWrapperTransport(
2587
+ this
2588
+ ));
2589
+ __privateSet(this, _provider, getMultichainClient({
2590
+ transport: __privateGet(this, _providerTransportWrapper)
2591
+ }));
2356
2592
  }
2357
2593
  get status() {
2358
2594
  return this._status;
@@ -2386,27 +2622,54 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2386
2622
  get transportType() {
2387
2623
  return __privateGet(this, _transport2) instanceof MWPTransport ? "mwp" /* MWP */ : "browser" /* Browser */;
2388
2624
  }
2625
+ // Creates a singleton instance of MetaMaskConnectMultichain.
2626
+ // If the singleton already exists, it merges the incoming options with the
2627
+ // existing singleton options for the following keys: `api.supportedNetworks`,
2628
+ // `ui.*`, `mobile.*`, `transport.extensionId`, `debug`. Take note that the
2629
+ // value for `dapp` is not merged as it does not make sense for subsequent calls to
2630
+ // `createMultichainClient` to have a different `dapp` value.
2389
2631
  static create(options) {
2390
2632
  return __async(this, null, function* () {
2391
- var _a2;
2392
- const instance = new _MetaMaskConnectMultichain(options);
2393
- const isEnabled2 = yield isEnabled(
2394
- "metamask-sdk:core",
2395
- instance.options.storage
2396
- );
2397
- if (isEnabled2) {
2398
- enableDebug("metamask-sdk:core");
2633
+ const globalObject = getGlobalObject();
2634
+ const existing = globalObject[SINGLETON_KEY];
2635
+ if (existing) {
2636
+ const instance = yield existing;
2637
+ instance.mergeOptions(options);
2638
+ if (options.debug) {
2639
+ enableDebug("metamask-sdk:*");
2640
+ }
2641
+ return instance;
2399
2642
  }
2400
- yield __privateMethod(_a2 = instance, _MetaMaskConnectMultichain_instances, init_fn).call(_a2);
2401
- return instance;
2643
+ const instancePromise = (() => __async(null, null, function* () {
2644
+ var _a2;
2645
+ const instance = new _MetaMaskConnectMultichain(options);
2646
+ const isEnabled2 = yield isEnabled(
2647
+ "metamask-sdk:core",
2648
+ instance.options.storage
2649
+ );
2650
+ if (isEnabled2) {
2651
+ enableDebug("metamask-sdk:core");
2652
+ }
2653
+ yield __privateMethod(_a2 = instance, _MetaMaskConnectMultichain_instances, init_fn).call(_a2);
2654
+ return instance;
2655
+ }))();
2656
+ globalObject[SINGLETON_KEY] = instancePromise;
2657
+ instancePromise.catch((error) => {
2658
+ globalObject[SINGLETON_KEY] = void 0;
2659
+ console.error("Error initializing MetaMaskConnectMultichain", error);
2660
+ });
2661
+ return instancePromise;
2402
2662
  });
2403
2663
  }
2404
2664
  // TODO: make this into param object
2405
2665
  connect(scopes, caipAccountIds, sessionProperties, forceRequest) {
2406
2666
  return __async(this, null, function* () {
2407
2667
  var _a2;
2408
- if (this.status !== "connected") {
2409
- yield this.disconnect();
2668
+ if (this.status === "connecting" && this.transportType === "mwp" /* MWP */) {
2669
+ yield __privateMethod(this, _MetaMaskConnectMultichain_instances, openConnectDeeplinkIfNeeded_fn).call(this);
2670
+ throw new Error(
2671
+ "Existing connection is pending. Please check your MetaMask Mobile app to continue."
2672
+ );
2410
2673
  }
2411
2674
  const { ui } = this.options;
2412
2675
  const platformType = getPlatformType();
@@ -2436,9 +2699,21 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2436
2699
  } catch (error) {
2437
2700
  logger2("Error tracking connection_initiated event", error);
2438
2701
  }
2439
- const nonEmptySessionProperites = Object.keys(sessionProperties != null ? sessionProperties : {}).length > 0 ? sessionProperties : void 0;
2702
+ const sessionData = yield __privateMethod(this, _MetaMaskConnectMultichain_instances, getCaipSession_fn).call(this);
2703
+ const { mergedScopes, mergedCaipAccountIds, mergedSessionProperties } = mergeRequestedSessionWithExisting(
2704
+ sessionData,
2705
+ scopes,
2706
+ caipAccountIds,
2707
+ sessionProperties
2708
+ );
2709
+ const nonEmptySessionProperties = Object.keys(mergedSessionProperties != null ? mergedSessionProperties : {}).length > 0 ? mergedSessionProperties : void 0;
2440
2710
  if (((_a2 = __privateGet(this, _transport2)) == null ? void 0 : _a2.isConnected()) && !secure) {
2441
- return __privateMethod(this, _MetaMaskConnectMultichain_instances, handleConnection_fn).call(this, __privateGet(this, _transport2).connect({ scopes, caipAccountIds, sessionProperties: nonEmptySessionProperites, forceRequest }).then(() => __async(this, null, function* () {
2711
+ return __privateMethod(this, _MetaMaskConnectMultichain_instances, handleConnection_fn).call(this, __privateGet(this, _transport2).connect({
2712
+ scopes: mergedScopes,
2713
+ caipAccountIds: mergedCaipAccountIds,
2714
+ sessionProperties: nonEmptySessionProperties,
2715
+ forceRequest
2716
+ }).then(() => __async(this, null, function* () {
2442
2717
  if (__privateGet(this, _transport2) instanceof MWPTransport) {
2443
2718
  return this.storage.setTransport("mwp" /* MWP */);
2444
2719
  }
@@ -2447,18 +2722,28 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2447
2722
  }
2448
2723
  if (platformType === "in-app-browser" /* MetaMaskMobileWebview */) {
2449
2724
  const defaultTransport = yield __privateMethod(this, _MetaMaskConnectMultichain_instances, setupDefaultTransport_fn).call(this);
2450
- return __privateMethod(this, _MetaMaskConnectMultichain_instances, handleConnection_fn).call(this, defaultTransport.connect({ scopes, caipAccountIds, sessionProperties: nonEmptySessionProperites, forceRequest }), scopes, transportType);
2725
+ return __privateMethod(this, _MetaMaskConnectMultichain_instances, handleConnection_fn).call(this, defaultTransport.connect({
2726
+ scopes: mergedScopes,
2727
+ caipAccountIds: mergedCaipAccountIds,
2728
+ sessionProperties: nonEmptySessionProperties,
2729
+ forceRequest
2730
+ }), scopes, transportType);
2451
2731
  }
2452
2732
  if (isWeb && hasExtensionInstalled && preferExtension) {
2453
2733
  const defaultTransport = yield __privateMethod(this, _MetaMaskConnectMultichain_instances, setupDefaultTransport_fn).call(this);
2454
- return __privateMethod(this, _MetaMaskConnectMultichain_instances, handleConnection_fn).call(this, defaultTransport.connect({ scopes, caipAccountIds, sessionProperties: nonEmptySessionProperites, forceRequest }), scopes, transportType);
2734
+ return __privateMethod(this, _MetaMaskConnectMultichain_instances, handleConnection_fn).call(this, defaultTransport.connect({
2735
+ scopes: mergedScopes,
2736
+ caipAccountIds: mergedCaipAccountIds,
2737
+ sessionProperties: nonEmptySessionProperties,
2738
+ forceRequest
2739
+ }), scopes, transportType);
2455
2740
  }
2456
2741
  yield __privateMethod(this, _MetaMaskConnectMultichain_instances, setupMWP_fn).call(this);
2457
2742
  const shouldShowInstallModal = hasExtensionInstalled ? showInstallModal : !preferExtension || showInstallModal;
2458
2743
  if (secure && !shouldShowInstallModal) {
2459
- return __privateMethod(this, _MetaMaskConnectMultichain_instances, handleConnection_fn).call(this, __privateMethod(this, _MetaMaskConnectMultichain_instances, deeplinkConnect_fn).call(this, scopes, caipAccountIds, nonEmptySessionProperites), scopes, transportType);
2744
+ return __privateMethod(this, _MetaMaskConnectMultichain_instances, handleConnection_fn).call(this, __privateMethod(this, _MetaMaskConnectMultichain_instances, deeplinkConnect_fn).call(this, mergedScopes, mergedCaipAccountIds, nonEmptySessionProperties), scopes, transportType);
2460
2745
  }
2461
- return __privateMethod(this, _MetaMaskConnectMultichain_instances, handleConnection_fn).call(this, __privateMethod(this, _MetaMaskConnectMultichain_instances, showInstallModal_fn).call(this, shouldShowInstallModal, scopes, caipAccountIds, nonEmptySessionProperites), scopes, transportType);
2746
+ return __privateMethod(this, _MetaMaskConnectMultichain_instances, handleConnection_fn).call(this, __privateMethod(this, _MetaMaskConnectMultichain_instances, showInstallModal_fn).call(this, shouldShowInstallModal, mergedScopes, mergedCaipAccountIds, nonEmptySessionProperties), scopes, transportType);
2462
2747
  });
2463
2748
  }
2464
2749
  emit(event, args) {
@@ -2467,18 +2752,24 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2467
2752
  super.emit(event, args);
2468
2753
  }
2469
2754
  disconnect() {
2470
- return __async(this, null, function* () {
2755
+ return __async(this, arguments, function* (scopes = []) {
2471
2756
  var _a2, _b, _c;
2472
- yield (_a2 = __privateGet(this, _listener)) == null ? void 0 : _a2.call(this);
2473
- (_b = __privateGet(this, _beforeUnloadListener)) == null ? void 0 : _b.call(this);
2474
- yield (_c = __privateGet(this, _transport2)) == null ? void 0 : _c.disconnect();
2475
- yield this.storage.removeTransport();
2476
- this.emit("stateChanged", "disconnected");
2477
- __privateSet(this, _listener, void 0);
2478
- __privateSet(this, _beforeUnloadListener, void 0);
2479
- __privateSet(this, _transport2, void 0);
2480
- __privateGet(this, _providerTransportWrapper).clearNotificationCallbacks();
2481
- __privateSet(this, _dappClient, void 0);
2757
+ const sessionData = yield __privateMethod(this, _MetaMaskConnectMultichain_instances, getCaipSession_fn).call(this);
2758
+ const remainingScopes = scopes.length === 0 ? [] : Object.keys(sessionData.sessionScopes).filter(
2759
+ (scope) => !scopes.includes(scope)
2760
+ );
2761
+ yield (_a2 = __privateGet(this, _transport2)) == null ? void 0 : _a2.disconnect(scopes);
2762
+ if (remainingScopes.length === 0) {
2763
+ yield (_b = __privateGet(this, _listener)) == null ? void 0 : _b.call(this);
2764
+ (_c = __privateGet(this, _beforeUnloadListener)) == null ? void 0 : _c.call(this);
2765
+ yield this.storage.removeTransport();
2766
+ __privateSet(this, _listener, void 0);
2767
+ __privateSet(this, _beforeUnloadListener, void 0);
2768
+ __privateSet(this, _transport2, void 0);
2769
+ __privateGet(this, _providerTransportWrapper).clearTransportNotificationListener();
2770
+ __privateSet(this, _dappClient, void 0);
2771
+ this.status = "disconnected";
2772
+ }
2482
2773
  });
2483
2774
  }
2484
2775
  invokeMethod(request) {
@@ -2490,7 +2781,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2490
2781
  });
2491
2782
  }
2492
2783
  // DRY THIS WITH REQUEST ROUTER
2493
- openDeeplinkIfNeeded() {
2784
+ openSimpleDeeplinkIfNeeded() {
2494
2785
  const { ui, mobile } = this.options;
2495
2786
  const { showInstallModal = false } = ui != null ? ui : {};
2496
2787
  const secure = isSecure();
@@ -2510,6 +2801,23 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2510
2801
  }), 10);
2511
2802
  }
2512
2803
  }
2804
+ // Provides a way for ecosystem clients (EVM, Solana, etc.) to get the current CAIP session data
2805
+ // when instantiating themselves (as they would have already missed any initial sessionChanged events emitted by ConnectMultichain)
2806
+ // without having to concern themselves with the current transport connection status.
2807
+ emitSessionChanged() {
2808
+ return __async(this, null, function* () {
2809
+ var _a2;
2810
+ const emptySession = { sessionScopes: {} };
2811
+ if (this.status !== "connected" && this.status !== "connecting") {
2812
+ this.emit("wallet_sessionChanged", emptySession);
2813
+ return;
2814
+ }
2815
+ const response = yield this.transport.request({
2816
+ method: "wallet_getSession"
2817
+ });
2818
+ this.emit("wallet_sessionChanged", (_a2 = response.result) != null ? _a2 : emptySession);
2819
+ });
2820
+ }
2513
2821
  };
2514
2822
  _provider = new WeakMap();
2515
2823
  _providerTransportWrapper = new WeakMap();
@@ -2559,7 +2867,7 @@ getStoredTransport_fn = function() {
2559
2867
  if (hasExtensionInstalled) {
2560
2868
  const apiTransport = new DefaultTransport();
2561
2869
  __privateSet(this, _transport2, apiTransport);
2562
- __privateGet(this, _providerTransportWrapper).setupNotifcationListener();
2870
+ __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
2563
2871
  __privateSet(this, _listener, apiTransport.onNotification(
2564
2872
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
2565
2873
  ));
@@ -2571,7 +2879,7 @@ getStoredTransport_fn = function() {
2571
2879
  const apiTransport = new MWPTransport(dappClient, kvstore);
2572
2880
  __privateSet(this, _dappClient, dappClient);
2573
2881
  __privateSet(this, _transport2, apiTransport);
2574
- __privateGet(this, _providerTransportWrapper).setupNotifcationListener();
2882
+ __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
2575
2883
  __privateSet(this, _listener, apiTransport.onNotification(
2576
2884
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
2577
2885
  ));
@@ -2603,25 +2911,17 @@ setupTransport_fn = function() {
2603
2911
  };
2604
2912
  init_fn = function() {
2605
2913
  return __async(this, null, function* () {
2606
- var _a2;
2607
2914
  try {
2608
- if (typeof window !== "undefined" && ((_a2 = window.mmsdk) == null ? void 0 : _a2.isInitialized)) {
2609
- logger2("MetaMaskSDK: init already initialized");
2610
- } else {
2611
- yield __privateMethod(this, _MetaMaskConnectMultichain_instances, setupAnalytics_fn).call(this);
2612
- yield __privateMethod(this, _MetaMaskConnectMultichain_instances, setupTransport_fn).call(this);
2613
- try {
2614
- const baseProps = yield getBaseAnalyticsProperties(
2615
- this.options,
2616
- this.storage
2617
- );
2618
- analytics2.track("mmconnect_initialized", baseProps);
2619
- } catch (error) {
2620
- logger2("Error tracking initialized event", error);
2621
- }
2622
- if (typeof window !== "undefined") {
2623
- window.mmsdk = this;
2624
- }
2915
+ yield __privateMethod(this, _MetaMaskConnectMultichain_instances, setupAnalytics_fn).call(this);
2916
+ yield __privateMethod(this, _MetaMaskConnectMultichain_instances, setupTransport_fn).call(this);
2917
+ try {
2918
+ const baseProps = yield getBaseAnalyticsProperties(
2919
+ this.options,
2920
+ this.storage
2921
+ );
2922
+ analytics2.track("mmconnect_initialized", baseProps);
2923
+ } catch (error) {
2924
+ logger2("Error tracking initialized event", error);
2625
2925
  }
2626
2926
  } catch (error) {
2627
2927
  yield this.storage.removeTransport();
@@ -2657,7 +2957,7 @@ setupMWP_fn = function() {
2657
2957
  __privateSet(this, _dappClient, dappClient);
2658
2958
  const apiTransport = new MWPTransport(dappClient, kvstore);
2659
2959
  __privateSet(this, _transport2, apiTransport);
2660
- __privateGet(this, _providerTransportWrapper).setupNotifcationListener();
2960
+ __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
2661
2961
  __privateSet(this, _listener, this.transport.onNotification(
2662
2962
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
2663
2963
  ));
@@ -2673,15 +2973,13 @@ onBeforeUnload_fn = function() {
2673
2973
  });
2674
2974
  };
2675
2975
  createBeforeUnloadListener_fn = function() {
2976
+ const handler = __privateMethod(this, _MetaMaskConnectMultichain_instances, onBeforeUnload_fn).bind(this);
2676
2977
  if (typeof window !== "undefined" && typeof window.addEventListener !== "undefined") {
2677
- window.addEventListener("beforeunload", __privateMethod(this, _MetaMaskConnectMultichain_instances, onBeforeUnload_fn).bind(this));
2978
+ window.addEventListener("beforeunload", handler);
2678
2979
  }
2679
2980
  return () => {
2680
2981
  if (typeof window !== "undefined" && typeof window.removeEventListener !== "undefined") {
2681
- window.removeEventListener(
2682
- "beforeunload",
2683
- __privateMethod(this, _MetaMaskConnectMultichain_instances, onBeforeUnload_fn).bind(this)
2684
- );
2982
+ window.removeEventListener("beforeunload", handler);
2685
2983
  }
2686
2984
  };
2687
2985
  };
@@ -2713,7 +3011,11 @@ renderInstallModalAsync_fn = function(desktopPreferred, scopes, caipAccountIds,
2713
3011
  (() => __async(this, null, function* () {
2714
3012
  var _a2;
2715
3013
  try {
2716
- yield this.transport.connect({ scopes, caipAccountIds, sessionProperties });
3014
+ yield this.transport.connect({
3015
+ scopes,
3016
+ caipAccountIds,
3017
+ sessionProperties
3018
+ });
2717
3019
  yield this.options.ui.factory.unload();
2718
3020
  (_a2 = this.options.ui.factory.modal) == null ? void 0 : _a2.unmount();
2719
3021
  this.status = "connected";
@@ -2722,13 +3024,14 @@ renderInstallModalAsync_fn = function(desktopPreferred, scopes, caipAccountIds,
2722
3024
  if (error instanceof ProtocolError) {
2723
3025
  if (error.code !== ErrorCode.REQUEST_EXPIRED) {
2724
3026
  this.status = "disconnected";
3027
+ yield this.options.ui.factory.unload(error);
2725
3028
  reject(error);
2726
3029
  }
2727
3030
  } else {
2728
3031
  this.status = "disconnected";
2729
- reject(
2730
- error instanceof Error ? error : new Error(String(error))
2731
- );
3032
+ const normalizedError = error instanceof Error ? error : new Error(String(error));
3033
+ yield this.options.ui.factory.unload(normalizedError);
3034
+ reject(normalizedError);
2732
3035
  }
2733
3036
  }
2734
3037
  }))().catch(() => {
@@ -2815,13 +3118,13 @@ setupDefaultTransport_fn = function() {
2815
3118
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
2816
3119
  ));
2817
3120
  __privateSet(this, _transport2, transport);
2818
- __privateGet(this, _providerTransportWrapper).setupNotifcationListener();
3121
+ __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
2819
3122
  return transport;
2820
3123
  });
2821
3124
  };
2822
3125
  deeplinkConnect_fn = function(scopes, caipAccountIds, sessionProperties) {
2823
3126
  return __async(this, null, function* () {
2824
- return new Promise((resolve, reject) => {
3127
+ return new Promise((resolve, reject) => __async(this, null, function* () {
2825
3128
  const dappClientMessageHandler = (payload) => {
2826
3129
  var _a2;
2827
3130
  if (typeof payload !== "object" || payload === null || !("data" in payload)) {
@@ -2842,7 +3145,7 @@ deeplinkConnect_fn = function(scopes, caipAccountIds, sessionProperties) {
2842
3145
  let timeout;
2843
3146
  if (this.transport.isConnected()) {
2844
3147
  timeout = setTimeout(() => {
2845
- this.openDeeplinkIfNeeded();
3148
+ this.openSimpleDeeplinkIfNeeded();
2846
3149
  }, 250);
2847
3150
  } else {
2848
3151
  this.dappClient.once(
@@ -2880,7 +3183,7 @@ deeplinkConnect_fn = function(scopes, caipAccountIds, sessionProperties) {
2880
3183
  clearTimeout(timeout);
2881
3184
  }
2882
3185
  });
2883
- });
3186
+ }));
2884
3187
  });
2885
3188
  };
2886
3189
  handleConnection_fn = function(promise, scopes, transportType) {
@@ -2925,6 +3228,53 @@ handleConnection_fn = function(promise, scopes, transportType) {
2925
3228
  }));
2926
3229
  });
2927
3230
  };
3231
+ getCaipSession_fn = function() {
3232
+ return __async(this, null, function* () {
3233
+ let sessionData = {
3234
+ sessionScopes: {},
3235
+ sessionProperties: {}
3236
+ };
3237
+ if (this.status === "connected") {
3238
+ const response = yield this.transport.request({
3239
+ method: "wallet_getSession"
3240
+ });
3241
+ if (response.result) {
3242
+ sessionData = response.result;
3243
+ }
3244
+ }
3245
+ return sessionData;
3246
+ });
3247
+ };
3248
+ openConnectDeeplinkIfNeeded_fn = function() {
3249
+ return __async(this, null, function* () {
3250
+ var _a2, _b;
3251
+ const { ui } = this.options;
3252
+ const { showInstallModal = false } = ui != null ? ui : {};
3253
+ const secure = isSecure();
3254
+ const shouldOpenDeeplink = secure && !showInstallModal;
3255
+ if (!shouldOpenDeeplink) {
3256
+ return;
3257
+ }
3258
+ const storedSessionRequest = yield (_a2 = __privateGet(this, _transport2)) == null ? void 0 : _a2.getStoredPendingSessionRequest();
3259
+ if (!storedSessionRequest) {
3260
+ return;
3261
+ }
3262
+ const connectionRequest = {
3263
+ sessionRequest: storedSessionRequest,
3264
+ metadata: {
3265
+ dapp: this.options.dapp,
3266
+ sdk: { version: getVersion(), platform: getPlatformType() }
3267
+ }
3268
+ };
3269
+ const deeplink = this.options.ui.factory.createConnectionDeeplink(connectionRequest);
3270
+ const universalLink = this.options.ui.factory.createConnectionUniversalLink(connectionRequest);
3271
+ if ((_b = this.options.mobile) == null ? void 0 : _b.preferredOpenLink) {
3272
+ this.options.mobile.preferredOpenLink(deeplink, "_self");
3273
+ } else {
3274
+ openDeeplink(this.options, deeplink, universalLink);
3275
+ }
3276
+ });
3277
+ };
2928
3278
  var MetaMaskConnectMultichain = _MetaMaskConnectMultichain;
2929
3279
 
2930
3280
  // src/store/index.ts
@@ -3173,7 +3523,9 @@ var BaseModalFactory = class {
3173
3523
  }
3174
3524
  createConnectionDeeplink(connectionRequest) {
3175
3525
  if (!connectionRequest) {
3176
- throw new Error("createConnectionDeeplink can only be called with a connection request");
3526
+ throw new Error(
3527
+ "createConnectionDeeplink can only be called with a connection request"
3528
+ );
3177
3529
  }
3178
3530
  const json = JSON.stringify(connectionRequest);
3179
3531
  const compressed = compressString(json);
@@ -3279,14 +3631,17 @@ var ModalFactory = class extends BaseModalFactory {
3279
3631
  // src/index.node.ts
3280
3632
  init_domain();
3281
3633
  var createMultichainClient = (options) => __async(null, null, function* () {
3634
+ if (options.debug) {
3635
+ enableDebug("metamask-sdk:*");
3636
+ }
3282
3637
  const uiModules = yield Promise.resolve().then(() => (init_node(), node_exports));
3283
3638
  let storage;
3284
- if (!options.storage) {
3639
+ if (options.storage) {
3640
+ storage = options.storage;
3641
+ } else {
3285
3642
  const { StoreAdapterNode: StoreAdapterNode2 } = yield Promise.resolve().then(() => (init_node2(), node_exports2));
3286
3643
  const adapter = new StoreAdapterNode2();
3287
3644
  storage = new Store(adapter);
3288
- } else {
3289
- storage = options.storage;
3290
3645
  }
3291
3646
  const factory = new ModalFactory(uiModules);
3292
3647
  return MetaMaskConnectMultichain.create(__spreadProps(__spreadValues({}, options), {