@metamask/connect-multichain 0.1.0 → 0.2.1

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 (83) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/dist/browser/es/connect-multichain.d.mts +67 -13
  3. package/dist/browser/es/connect-multichain.mjs +895 -384
  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 +67 -13
  7. package/dist/browser/iife/connect-multichain.js +21636 -14459
  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 +67 -13
  11. package/dist/browser/umd/connect-multichain.js +893 -382
  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 +67 -13
  15. package/dist/node/cjs/connect-multichain.js +898 -385
  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 +67 -13
  19. package/dist/node/es/connect-multichain.mjs +898 -387
  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 +67 -13
  23. package/dist/react-native/es/connect-multichain.mjs +897 -386
  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/events/index.d.ts +26 -0
  27. package/dist/src/domain/events/index.d.ts.map +1 -1
  28. package/dist/src/domain/events/index.js +35 -0
  29. package/dist/src/domain/events/index.js.map +1 -1
  30. package/dist/src/domain/multichain/index.d.ts +7 -5
  31. package/dist/src/domain/multichain/index.d.ts.map +1 -1
  32. package/dist/src/domain/multichain/index.js +2 -2
  33. package/dist/src/domain/multichain/index.js.map +1 -1
  34. package/dist/src/domain/multichain/types.d.ts +9 -7
  35. package/dist/src/domain/multichain/types.d.ts.map +1 -1
  36. package/dist/src/domain/platform/index.js +3 -3
  37. package/dist/src/domain/platform/index.js.map +1 -1
  38. package/dist/src/domain/ui/factory.d.ts +1 -1
  39. package/dist/src/domain/ui/factory.d.ts.map +1 -1
  40. package/dist/src/domain/utils/index.d.ts +1 -0
  41. package/dist/src/domain/utils/index.d.ts.map +1 -1
  42. package/dist/src/domain/utils/index.js +1 -0
  43. package/dist/src/domain/utils/index.js.map +1 -1
  44. package/dist/src/multichain/index.d.ts +5 -2
  45. package/dist/src/multichain/index.d.ts.map +1 -1
  46. package/dist/src/multichain/index.js +124 -38
  47. package/dist/src/multichain/index.js.map +1 -1
  48. package/dist/src/multichain/rpc/handlers/rpcClient.d.ts +2 -1
  49. package/dist/src/multichain/rpc/handlers/rpcClient.d.ts.map +1 -1
  50. package/dist/src/multichain/rpc/handlers/rpcClient.js +16 -17
  51. package/dist/src/multichain/rpc/handlers/rpcClient.js.map +1 -1
  52. package/dist/src/multichain/rpc/requestRouter.d.ts +1 -0
  53. package/dist/src/multichain/rpc/requestRouter.d.ts.map +1 -1
  54. package/dist/src/multichain/rpc/requestRouter.js +71 -15
  55. package/dist/src/multichain/rpc/requestRouter.js.map +1 -1
  56. package/dist/src/multichain/transports/constants.d.ts +3 -0
  57. package/dist/src/multichain/transports/constants.d.ts.map +1 -0
  58. package/dist/src/multichain/transports/constants.js +3 -0
  59. package/dist/src/multichain/transports/constants.js.map +1 -0
  60. package/dist/src/multichain/transports/default/index.d.ts +4 -0
  61. package/dist/src/multichain/transports/default/index.d.ts.map +1 -1
  62. package/dist/src/multichain/transports/default/index.js +137 -13
  63. package/dist/src/multichain/transports/default/index.js.map +1 -1
  64. package/dist/src/multichain/transports/mwp/index.d.ts +10 -1
  65. package/dist/src/multichain/transports/mwp/index.d.ts.map +1 -1
  66. package/dist/src/multichain/transports/mwp/index.js +138 -10
  67. package/dist/src/multichain/transports/mwp/index.js.map +1 -1
  68. package/dist/src/multichain/utils/analytics.d.ts +39 -0
  69. package/dist/src/multichain/utils/analytics.d.ts.map +1 -0
  70. package/dist/src/multichain/utils/analytics.js +83 -0
  71. package/dist/src/multichain/utils/analytics.js.map +1 -0
  72. package/dist/src/multichain/utils/index.d.ts +0 -1
  73. package/dist/src/multichain/utils/index.d.ts.map +1 -1
  74. package/dist/src/multichain/utils/index.js +1 -16
  75. package/dist/src/multichain/utils/index.js.map +1 -1
  76. package/dist/src/ui/index.d.ts +1 -1
  77. package/dist/src/ui/index.d.ts.map +1 -1
  78. package/dist/src/ui/index.js +35 -19
  79. package/dist/src/ui/index.js.map +1 -1
  80. package/dist/src/ui/modals/web/install.js +1 -1
  81. package/dist/src/ui/modals/web/install.js.map +1 -1
  82. package/dist/types/connect-multichain.d.ts +67 -13
  83. package/package.json +12 -9
@@ -53,6 +53,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
53
53
  var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
54
54
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
55
55
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
56
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
56
57
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
57
58
  var __async = (__this, __arguments, generator) => {
58
59
  return new Promise((resolve, reject) => {
@@ -197,6 +198,41 @@ var init_events = __esm({
197
198
  off(eventName, handler) {
198
199
  __privateGet(this, _emitter).off(eventName, handler);
199
200
  }
201
+ /**
202
+ * Removes a specific event handler for the specified event.
203
+ * Added for compatibility as some libraries use this method name.
204
+ *
205
+ * @template TEventName - The name of the event to remove the handler from (must be a key of TEvents)
206
+ * @param eventName - The name of the event to remove the handler from
207
+ * @param handler - The specific handler function to remove
208
+ */
209
+ removeListener(eventName, handler) {
210
+ __privateGet(this, _emitter).off(eventName, handler);
211
+ }
212
+ /**
213
+ * Registers an event handler for the specified event that will only be called once.
214
+ *
215
+ * @template TEventName - The name of the event to listen for (must be a key of TEvents)
216
+ * @param eventName - The name of the event to listen for
217
+ * @param handler - The function to call when the event is emitted (only once)
218
+ * @returns A function to remove the listener
219
+ */
220
+ once(eventName, handler) {
221
+ __privateGet(this, _emitter).once(eventName, handler);
222
+ return () => {
223
+ this.off(eventName, handler);
224
+ };
225
+ }
226
+ /**
227
+ * Returns the number of listeners registered for the specified event.
228
+ *
229
+ * @template TEventName - The name of the event to count listeners for (must be a key of TEvents)
230
+ * @param eventName - The name of the event to count listeners for
231
+ * @returns The number of listeners registered for the event
232
+ */
233
+ listenerCount(eventName) {
234
+ return __privateGet(this, _emitter).listenerCount(eventName);
235
+ }
200
236
  };
201
237
  _emitter = new WeakMap();
202
238
  }
@@ -361,7 +397,7 @@ function getTransportType(type) {
361
397
  case "browser":
362
398
  return "browser" /* Browser */;
363
399
  case "mwp":
364
- return "mwp" /* MPW */;
400
+ return "mwp" /* MWP */;
365
401
  default:
366
402
  return "unknown" /* UNKNOWN */;
367
403
  }
@@ -375,7 +411,7 @@ var init_multichain = __esm({
375
411
  init_infura();
376
412
  TransportType = /* @__PURE__ */ ((TransportType2) => {
377
413
  TransportType2["Browser"] = "browser";
378
- TransportType2["MPW"] = "mwp";
414
+ TransportType2["MWP"] = "mwp";
379
415
  TransportType2["UNKNOWN"] = "unknown";
380
416
  return TransportType2;
381
417
  })(TransportType || {});
@@ -417,7 +453,7 @@ function isMetaMaskMobileWebView() {
417
453
  }
418
454
  function isMobile() {
419
455
  var _a, _b;
420
- const browser = (0, import_bowser.parse)(window.navigator.userAgent);
456
+ const browser = import_bowser.default.parse(window.navigator.userAgent);
421
457
  return ((_a = browser == null ? void 0 : browser.platform) == null ? void 0 : _a.type) === "mobile" || ((_b = browser == null ? void 0 : browser.platform) == null ? void 0 : _b.type) === "tablet";
422
458
  }
423
459
  function getPlatformType() {
@@ -455,7 +491,7 @@ var import_bowser, PlatformType, detectionPromise;
455
491
  var init_platform = __esm({
456
492
  "src/domain/platform/index.ts"() {
457
493
  "use strict";
458
- import_bowser = require("bowser");
494
+ import_bowser = __toESM(require("bowser"));
459
495
  PlatformType = /* @__PURE__ */ ((PlatformType2) => {
460
496
  PlatformType2["NonBrowser"] = "nodejs";
461
497
  PlatformType2["MetaMaskMobileWebview"] = "in-app-browser";
@@ -483,8 +519,8 @@ var init_platform = __esm({
483
519
  window.removeEventListener("eip6963:announceProvider", handler);
484
520
  const hasMetaMask = providers.some(
485
521
  (provider) => {
486
- var _a;
487
- return ((_a = provider == null ? void 0 : provider.info) == null ? void 0 : _a.rdns) === "io.metamask";
522
+ var _a, _b;
523
+ return (_b = (_a = provider == null ? void 0 : provider.info) == null ? void 0 : _a.rdns) == null ? void 0 : _b.startsWith("io.metamask");
488
524
  }
489
525
  );
490
526
  resolve(hasMetaMask);
@@ -568,13 +604,262 @@ var init_ui = __esm({
568
604
  }
569
605
  });
570
606
 
607
+ // src/multichain/utils/index.ts
608
+ function base64Encode(str) {
609
+ if (typeof btoa !== "undefined") {
610
+ return btoa(str);
611
+ } else if (typeof Buffer !== "undefined") {
612
+ return Buffer.from(str).toString("base64");
613
+ }
614
+ throw new Error("No base64 encoding method available");
615
+ }
616
+ function compressString(str) {
617
+ const compressed = (0, import_pako.deflate)(str);
618
+ const binaryString = String.fromCharCode.apply(null, Array.from(compressed));
619
+ return base64Encode(binaryString);
620
+ }
621
+ function getDappId(dapp) {
622
+ var _a, _b;
623
+ if (typeof window === "undefined" || typeof window.location === "undefined") {
624
+ return (_b = (_a = dapp == null ? void 0 : dapp.name) != null ? _a : dapp == null ? void 0 : dapp.url) != null ? _b : "N/A";
625
+ }
626
+ return window.location.hostname;
627
+ }
628
+ function openDeeplink(options, deeplink, universalLink) {
629
+ const { mobile } = options;
630
+ const useDeeplink = mobile && mobile.useDeeplink !== void 0 ? mobile.useDeeplink : true;
631
+ if (useDeeplink) {
632
+ if (typeof window !== "undefined") {
633
+ window.location.href = deeplink;
634
+ }
635
+ } else if (typeof document !== "undefined") {
636
+ const link = document.createElement("a");
637
+ link.href = universalLink;
638
+ link.target = "_self";
639
+ link.rel = "noreferrer noopener";
640
+ link.click();
641
+ }
642
+ }
643
+ function getOptionalScopes(scopes) {
644
+ return scopes.reduce(
645
+ (prev, scope) => __spreadProps(__spreadValues({}, prev), {
646
+ [scope]: {
647
+ methods: [],
648
+ notifications: [],
649
+ accounts: []
650
+ }
651
+ }),
652
+ {}
653
+ );
654
+ }
655
+ function setupDappMetadata(options) {
656
+ var _a;
657
+ const platform = getPlatformType();
658
+ const isBrowser = platform === "web-desktop" /* DesktopWeb */ || platform === "web-mobile" /* MobileWeb */ || platform === "in-app-browser" /* MetaMaskMobileWebview */;
659
+ if (!((_a = options.dapp) == null ? void 0 : _a.url)) {
660
+ if (isBrowser) {
661
+ options.dapp = __spreadProps(__spreadValues({}, options.dapp), {
662
+ url: `${window.location.protocol}//${window.location.host}`
663
+ });
664
+ } else {
665
+ throw new Error("You must provide dapp url");
666
+ }
667
+ }
668
+ const BASE_64_ICON_MAX_LENGTH = 163400;
669
+ const urlPattern = /^(http|https):\/\/[^\s]*$/;
670
+ if (options.dapp) {
671
+ if ("iconUrl" in options.dapp) {
672
+ if (options.dapp.iconUrl && !urlPattern.test(options.dapp.iconUrl)) {
673
+ console.warn(
674
+ "Invalid dappMetadata.iconUrl: URL must start with http:// or https://"
675
+ );
676
+ options.dapp.iconUrl = void 0;
677
+ }
678
+ }
679
+ if ("base64Icon" in options.dapp) {
680
+ if (options.dapp.base64Icon && options.dapp.base64Icon.length > BASE_64_ICON_MAX_LENGTH) {
681
+ console.warn(
682
+ "Invalid dappMetadata.base64Icon: Base64-encoded icon string length must be less than 163400 characters"
683
+ );
684
+ options.dapp.base64Icon = void 0;
685
+ }
686
+ }
687
+ if (options.dapp.url && !urlPattern.test(options.dapp.url)) {
688
+ console.warn(
689
+ "Invalid dappMetadata.url: URL must start with http:// or https://"
690
+ );
691
+ }
692
+ const favicon = extractFavicon();
693
+ if (favicon && !("iconUrl" in options.dapp) && !("base64Icon" in options.dapp)) {
694
+ const faviconUrl = `${window.location.protocol}//${window.location.host}${favicon}`;
695
+ options.dapp.iconUrl = faviconUrl;
696
+ }
697
+ }
698
+ return options;
699
+ }
700
+ function isSameScopesAndAccounts(currentScopes, proposedScopes, walletSession, proposedCaipAccountIds) {
701
+ const isSameScopes = currentScopes.every((scope) => proposedScopes.includes(scope)) && proposedScopes.every((scope) => currentScopes.includes(scope));
702
+ if (!isSameScopes) {
703
+ return false;
704
+ }
705
+ const existingAccountIds = Object.values(
706
+ walletSession.sessionScopes
707
+ ).filter(({ accounts }) => Boolean(accounts)).flatMap(({ accounts }) => accounts != null ? accounts : []);
708
+ const allProposedAccountsIncluded = proposedCaipAccountIds.every(
709
+ (proposedAccountId) => existingAccountIds.includes(proposedAccountId)
710
+ );
711
+ return allProposedAccountsIncluded;
712
+ }
713
+ function getValidAccounts(caipAccountIds) {
714
+ return caipAccountIds.reduce(
715
+ (caipAccounts, caipAccountId) => {
716
+ try {
717
+ return [...caipAccounts, (0, import_utils.parseCaipAccountId)(caipAccountId)];
718
+ } catch (err) {
719
+ const stringifiedAccountId = JSON.stringify(caipAccountId);
720
+ console.error(`Invalid CAIP account ID: ${stringifiedAccountId}`, err);
721
+ return caipAccounts;
722
+ }
723
+ },
724
+ []
725
+ );
726
+ }
727
+ function addValidAccounts(optionalScopes, validAccounts) {
728
+ var _a;
729
+ if (!optionalScopes || !(validAccounts == null ? void 0 : validAccounts.length)) {
730
+ return optionalScopes;
731
+ }
732
+ const result = Object.fromEntries(
733
+ Object.entries(optionalScopes).map(([scope, scopeData]) => {
734
+ var _a2, _b, _c;
735
+ return [
736
+ scope,
737
+ {
738
+ methods: [...(_a2 = scopeData == null ? void 0 : scopeData.methods) != null ? _a2 : []],
739
+ notifications: [...(_b = scopeData == null ? void 0 : scopeData.notifications) != null ? _b : []],
740
+ accounts: [...(_c = scopeData == null ? void 0 : scopeData.accounts) != null ? _c : []]
741
+ }
742
+ ];
743
+ })
744
+ );
745
+ const accountsByChain = /* @__PURE__ */ new Map();
746
+ for (const account of validAccounts) {
747
+ const chainKey = `${account.chain.namespace}:${account.chain.reference}`;
748
+ const accountId = `${account.chainId}:${account.address}`;
749
+ if (!accountsByChain.has(chainKey)) {
750
+ accountsByChain.set(chainKey, []);
751
+ }
752
+ (_a = accountsByChain.get(chainKey)) == null ? void 0 : _a.push(accountId);
753
+ }
754
+ for (const [scopeKey, scopeData] of Object.entries(result)) {
755
+ if (!(scopeData == null ? void 0 : scopeData.accounts)) {
756
+ continue;
757
+ }
758
+ try {
759
+ const scope = scopeKey;
760
+ const scopeDetails = (0, import_utils.parseCaipChainId)(scope);
761
+ const chainKey = `${scopeDetails.namespace}:${scopeDetails.reference}`;
762
+ const matchingAccounts = accountsByChain.get(chainKey);
763
+ if (matchingAccounts) {
764
+ const existingAccounts = new Set(scopeData.accounts);
765
+ const newAccounts = matchingAccounts.filter(
766
+ (account) => !existingAccounts.has(account)
767
+ );
768
+ scopeData.accounts.push(...newAccounts);
769
+ }
770
+ } catch (error) {
771
+ console.error(`Invalid scope format: ${scopeKey}`, error);
772
+ }
773
+ }
774
+ return result;
775
+ }
776
+ var import_pako, import_utils, extractFavicon;
777
+ var init_utils = __esm({
778
+ "src/multichain/utils/index.ts"() {
779
+ "use strict";
780
+ import_pako = require("pako");
781
+ import_utils = require("@metamask/utils");
782
+ init_domain();
783
+ extractFavicon = () => {
784
+ var _a;
785
+ if (typeof document === "undefined") {
786
+ return void 0;
787
+ }
788
+ let favicon;
789
+ const nodeList = document.getElementsByTagName("link");
790
+ for (let i = 0; i < nodeList.length; i++) {
791
+ if (nodeList[i].getAttribute("rel") === "icon" || nodeList[i].getAttribute("rel") === "shortcut icon") {
792
+ favicon = (_a = nodeList[i].getAttribute("href")) != null ? _a : void 0;
793
+ }
794
+ }
795
+ return favicon;
796
+ };
797
+ }
798
+ });
799
+
800
+ // src/multichain/utils/analytics.ts
801
+ function isRejectionError(error) {
802
+ var _a, _b;
803
+ if (typeof error !== "object" || error === null) {
804
+ return false;
805
+ }
806
+ const errorObj = error;
807
+ const errorCode = errorObj.code;
808
+ const errorMessage = (_b = (_a = errorObj.message) == null ? void 0 : _a.toLowerCase()) != null ? _b : "";
809
+ return errorCode === 4001 || // User rejected request (common EIP-1193 code)
810
+ errorCode === 4100 || // Unauthorized (common rejection code)
811
+ errorMessage.includes("reject") || errorMessage.includes("denied") || errorMessage.includes("cancel") || errorMessage.includes("user");
812
+ }
813
+ function getBaseAnalyticsProperties(options, storage) {
814
+ return __async(this, null, function* () {
815
+ var _a, _b;
816
+ const version = getVersion();
817
+ const dappId = getDappId(options.dapp);
818
+ const platform = getPlatformType();
819
+ const anonId = yield storage.getAnonId();
820
+ const integrationType = (_b = (_a = options.analytics) == null ? void 0 : _a.integrationType) != null ? _b : "unknown" /* UNKNOWN */;
821
+ return {
822
+ mmconnect_version: version,
823
+ dapp_id: dappId,
824
+ platform,
825
+ integration_type: integrationType,
826
+ anon_id: anonId
827
+ };
828
+ });
829
+ }
830
+ function getWalletActionAnalyticsProperties(options, storage, invokeOptions) {
831
+ return __async(this, null, function* () {
832
+ var _a, _b;
833
+ const version = getVersion();
834
+ const dappId = getDappId(options.dapp);
835
+ const anonId = yield storage.getAnonId();
836
+ const integrationType = (_b = (_a = options.analytics) == null ? void 0 : _a.integrationType) != null ? _b : "unknown";
837
+ return {
838
+ mmconnect_version: version,
839
+ dapp_id: dappId,
840
+ method: invokeOptions.request.method,
841
+ integration_type: integrationType,
842
+ caip_chain_id: invokeOptions.scope,
843
+ anon_id: anonId
844
+ };
845
+ });
846
+ }
847
+ var init_analytics = __esm({
848
+ "src/multichain/utils/analytics.ts"() {
849
+ "use strict";
850
+ init_utils();
851
+ init_domain();
852
+ }
853
+ });
854
+
571
855
  // src/domain/utils/index.ts
572
856
  function getVersion() {
573
857
  return "0.0.0";
574
858
  }
575
- var init_utils = __esm({
859
+ var init_utils2 = __esm({
576
860
  "src/domain/utils/index.ts"() {
577
861
  "use strict";
862
+ init_analytics();
578
863
  }
579
864
  });
580
865
 
@@ -589,7 +874,7 @@ var init_domain = __esm({
589
874
  init_platform();
590
875
  init_store();
591
876
  init_ui();
592
- init_utils();
877
+ init_utils2();
593
878
  }
594
879
  });
595
880
 
@@ -636,7 +921,7 @@ function shouldLogCountdown(remainingSeconds) {
636
921
  return remainingSeconds % 60 === 0;
637
922
  }
638
923
  }
639
- var init_utils2 = __esm({
924
+ var init_utils3 = __esm({
640
925
  "src/ui/modals/base/utils.ts"() {
641
926
  "use strict";
642
927
  }
@@ -648,7 +933,7 @@ var init_AbstractInstallModal = __esm({
648
933
  "src/ui/modals/base/AbstractInstallModal.ts"() {
649
934
  "use strict";
650
935
  init_domain();
651
- init_utils2();
936
+ init_utils3();
652
937
  logger3 = createLogger("metamask-sdk:ui");
653
938
  AbstractInstallModal = class extends Modal {
654
939
  constructor() {
@@ -742,7 +1027,7 @@ var init_install = __esm({
742
1027
  init_domain();
743
1028
  init_qr();
744
1029
  init_AbstractInstallModal();
745
- init_utils2();
1030
+ init_utils3();
746
1031
  logger4 = createLogger("metamask-sdk:ui");
747
1032
  InstallModal = class extends AbstractInstallModal {
748
1033
  displayQRWithCountdown(qrCodeLink, expiresInMs) {
@@ -857,274 +1142,73 @@ var init_node2 = __esm({
857
1142
  get(key) {
858
1143
  return __async(this, null, function* () {
859
1144
  var _a;
860
- return (_a = this.storage.get(key)) != null ? _a : null;
861
- });
862
- }
863
- set(key, value) {
864
- return __async(this, null, function* () {
865
- this.storage.set(key, value);
866
- });
867
- }
868
- delete(key) {
869
- return __async(this, null, function* () {
870
- this.storage.delete(key);
871
- });
872
- }
873
- };
874
- }
875
- });
876
-
877
- // src/index.node.ts
878
- var index_node_exports = {};
879
- __export(index_node_exports, {
880
- EventEmitter: () => EventEmitter,
881
- Modal: () => Modal,
882
- MultichainCore: () => MultichainCore,
883
- PlatformType: () => PlatformType,
884
- RPCHttpErr: () => RPCHttpErr,
885
- RPCInvokeMethodErr: () => RPCInvokeMethodErr,
886
- RPCReadonlyRequestErr: () => RPCReadonlyRequestErr,
887
- RPCReadonlyResponseErr: () => RPCReadonlyResponseErr,
888
- RPC_HANDLED_METHODS: () => RPC_HANDLED_METHODS,
889
- SDK_HANDLED_METHODS: () => SDK_HANDLED_METHODS,
890
- StoreAdapter: () => StoreAdapter,
891
- StoreClient: () => StoreClient,
892
- TransportType: () => TransportType,
893
- createLogger: () => createLogger,
894
- createMetamaskConnect: () => createMetamaskConnect,
895
- enableDebug: () => enableDebug,
896
- getInfuraRpcUrls: () => getInfuraRpcUrls,
897
- getPlatformType: () => getPlatformType,
898
- getTransportType: () => getTransportType,
899
- getVersion: () => getVersion,
900
- hasExtension: () => hasExtension,
901
- infuraRpcUrls: () => infuraRpcUrls,
902
- isEnabled: () => isEnabled,
903
- isMetamaskExtensionInstalled: () => isMetamaskExtensionInstalled,
904
- isSecure: () => isSecure
905
- });
906
- module.exports = __toCommonJS(index_node_exports);
907
-
908
- // src/multichain/index.ts
909
- var import_analytics = require("@metamask/analytics");
910
- var import_mobile_wallet_protocol_core2 = require("@metamask/mobile-wallet-protocol-core");
911
- var import_mobile_wallet_protocol_dapp_client = require("@metamask/mobile-wallet-protocol-dapp-client");
912
- var import_multichain_api_client3 = require("@metamask/multichain-api-client");
913
-
914
- // src/config/index.ts
915
- var MWP_RELAY_URL = "wss://mm-sdk-relay.api.cx.metamask.io/connection/websocket";
916
- var METAMASK_CONNECT_BASE_URL = "https://metamask.app.link/connect";
917
- var METAMASK_DEEPLINK_BASE = "metamask://connect";
918
-
919
- // src/multichain/index.ts
920
- init_domain();
921
- init_logger();
922
- init_multichain();
923
- init_platform();
924
-
925
- // src/multichain/rpc/requestRouter.ts
926
- init_domain();
927
-
928
- // src/multichain/utils/index.ts
929
- var import_pako = require("pako");
930
- var import_utils = require("@metamask/utils");
931
- init_domain();
932
- function base64Encode(str) {
933
- if (typeof btoa !== "undefined") {
934
- return btoa(str);
935
- } else if (typeof Buffer !== "undefined") {
936
- return Buffer.from(str).toString("base64");
937
- }
938
- throw new Error("No base64 encoding method available");
939
- }
940
- function compressString(str) {
941
- const compressed = (0, import_pako.deflate)(str);
942
- const binaryString = String.fromCharCode.apply(null, Array.from(compressed));
943
- return base64Encode(binaryString);
944
- }
945
- function getDappId(dapp) {
946
- var _a, _b;
947
- if (typeof window === "undefined" || typeof window.location === "undefined") {
948
- return (_b = (_a = dapp == null ? void 0 : dapp.name) != null ? _a : dapp == null ? void 0 : dapp.url) != null ? _b : "N/A";
949
- }
950
- return window.location.hostname;
951
- }
952
- function openDeeplink(options, deeplink, universalLink) {
953
- const { mobile } = options;
954
- const useDeeplink = mobile && mobile.useDeeplink !== void 0 ? mobile.useDeeplink : true;
955
- if (useDeeplink) {
956
- if (typeof window !== "undefined") {
957
- window.location.href = deeplink;
958
- }
959
- } else if (typeof document !== "undefined") {
960
- const link = document.createElement("a");
961
- link.href = universalLink;
962
- link.target = "_self";
963
- link.rel = "noreferrer noopener";
964
- link.click();
965
- }
966
- }
967
- function getOptionalScopes(scopes) {
968
- return scopes.reduce(
969
- (prev, scope) => __spreadProps(__spreadValues({}, prev), {
970
- [scope]: {
971
- methods: [],
972
- notifications: [],
973
- accounts: []
974
- }
975
- }),
976
- {}
977
- );
978
- }
979
- var extractFavicon = () => {
980
- var _a;
981
- if (typeof document === "undefined") {
982
- return void 0;
983
- }
984
- let favicon;
985
- const nodeList = document.getElementsByTagName("link");
986
- for (let i = 0; i < nodeList.length; i++) {
987
- if (nodeList[i].getAttribute("rel") === "icon" || nodeList[i].getAttribute("rel") === "shortcut icon") {
988
- favicon = (_a = nodeList[i].getAttribute("href")) != null ? _a : void 0;
989
- }
990
- }
991
- return favicon;
992
- };
993
- function setupInfuraProvider(options) {
994
- var _a, _b;
995
- const infuraAPIKey = (_a = options.api) == null ? void 0 : _a.infuraAPIKey;
996
- if (!infuraAPIKey) {
997
- return options;
998
- }
999
- const urlsWithToken = getInfuraRpcUrls(infuraAPIKey);
1000
- if ((_b = options.api) == null ? void 0 : _b.readonlyRPCMap) {
1001
- options.api.readonlyRPCMap = __spreadValues(__spreadValues({}, options.api.readonlyRPCMap), urlsWithToken);
1002
- } else if (options.api) {
1003
- options.api.readonlyRPCMap = urlsWithToken;
1004
- }
1005
- return options;
1006
- }
1007
- function setupDappMetadata(options) {
1008
- var _a;
1009
- const platform = getPlatformType();
1010
- const isBrowser = platform === "web-desktop" /* DesktopWeb */ || platform === "web-mobile" /* MobileWeb */ || platform === "in-app-browser" /* MetaMaskMobileWebview */;
1011
- if (!((_a = options.dapp) == null ? void 0 : _a.url)) {
1012
- if (isBrowser) {
1013
- options.dapp = __spreadProps(__spreadValues({}, options.dapp), {
1014
- url: `${window.location.protocol}//${window.location.host}`
1015
- });
1016
- } else {
1017
- throw new Error("You must provide dapp url");
1018
- }
1019
- }
1020
- const BASE_64_ICON_MAX_LENGTH = 163400;
1021
- const urlPattern = /^(http|https):\/\/[^\s]*$/;
1022
- if (options.dapp) {
1023
- if ("iconUrl" in options.dapp) {
1024
- if (options.dapp.iconUrl && !urlPattern.test(options.dapp.iconUrl)) {
1025
- console.warn(
1026
- "Invalid dappMetadata.iconUrl: URL must start with http:// or https://"
1027
- );
1028
- options.dapp.iconUrl = void 0;
1029
- }
1030
- }
1031
- if ("base64Icon" in options.dapp) {
1032
- if (options.dapp.base64Icon && options.dapp.base64Icon.length > BASE_64_ICON_MAX_LENGTH) {
1033
- console.warn(
1034
- "Invalid dappMetadata.base64Icon: Base64-encoded icon string length must be less than 163400 characters"
1035
- );
1036
- options.dapp.base64Icon = void 0;
1037
- }
1038
- }
1039
- if (options.dapp.url && !urlPattern.test(options.dapp.url)) {
1040
- console.warn(
1041
- "Invalid dappMetadata.url: URL must start with http:// or https://"
1042
- );
1043
- }
1044
- const favicon = extractFavicon();
1045
- if (favicon && !("iconUrl" in options.dapp) && !("base64Icon" in options.dapp)) {
1046
- const faviconUrl = `${window.location.protocol}//${window.location.host}${favicon}`;
1047
- options.dapp.iconUrl = faviconUrl;
1048
- }
1049
- }
1050
- return options;
1051
- }
1052
- function isSameScopesAndAccounts(currentScopes, proposedScopes, walletSession, proposedCaipAccountIds) {
1053
- const isSameScopes = currentScopes.every((scope) => proposedScopes.includes(scope)) && proposedScopes.every((scope) => currentScopes.includes(scope));
1054
- if (!isSameScopes) {
1055
- return false;
1056
- }
1057
- const existingAccountIds = Object.values(
1058
- walletSession.sessionScopes
1059
- ).filter(({ accounts }) => Boolean(accounts)).flatMap(({ accounts }) => accounts != null ? accounts : []);
1060
- const allProposedAccountsIncluded = proposedCaipAccountIds.every(
1061
- (proposedAccountId) => existingAccountIds.includes(proposedAccountId)
1062
- );
1063
- return allProposedAccountsIncluded;
1064
- }
1065
- function getValidAccounts(caipAccountIds) {
1066
- return caipAccountIds.reduce(
1067
- (caipAccounts, caipAccountId) => {
1068
- try {
1069
- return [...caipAccounts, (0, import_utils.parseCaipAccountId)(caipAccountId)];
1070
- } catch (err) {
1071
- const stringifiedAccountId = JSON.stringify(caipAccountId);
1072
- console.error(`Invalid CAIP account ID: ${stringifiedAccountId}`, err);
1073
- return caipAccounts;
1074
- }
1075
- },
1076
- []
1077
- );
1078
- }
1079
- function addValidAccounts(optionalScopes, validAccounts) {
1080
- var _a;
1081
- if (!optionalScopes || !(validAccounts == null ? void 0 : validAccounts.length)) {
1082
- return optionalScopes;
1083
- }
1084
- const result = Object.fromEntries(
1085
- Object.entries(optionalScopes).map(([scope, scopeData]) => {
1086
- var _a2, _b, _c;
1087
- return [
1088
- scope,
1089
- {
1090
- methods: [...(_a2 = scopeData == null ? void 0 : scopeData.methods) != null ? _a2 : []],
1091
- notifications: [...(_b = scopeData == null ? void 0 : scopeData.notifications) != null ? _b : []],
1092
- accounts: [...(_c = scopeData == null ? void 0 : scopeData.accounts) != null ? _c : []]
1093
- }
1094
- ];
1095
- })
1096
- );
1097
- const accountsByChain = /* @__PURE__ */ new Map();
1098
- for (const account of validAccounts) {
1099
- const chainKey = `${account.chain.namespace}:${account.chain.reference}`;
1100
- const accountId = `${account.chainId}:${account.address}`;
1101
- if (!accountsByChain.has(chainKey)) {
1102
- accountsByChain.set(chainKey, []);
1103
- }
1104
- (_a = accountsByChain.get(chainKey)) == null ? void 0 : _a.push(accountId);
1105
- }
1106
- for (const [scopeKey, scopeData] of Object.entries(result)) {
1107
- if (!(scopeData == null ? void 0 : scopeData.accounts)) {
1108
- continue;
1109
- }
1110
- try {
1111
- const scope = scopeKey;
1112
- const scopeDetails = (0, import_utils.parseCaipChainId)(scope);
1113
- const chainKey = `${scopeDetails.namespace}:${scopeDetails.reference}`;
1114
- const matchingAccounts = accountsByChain.get(chainKey);
1115
- if (matchingAccounts) {
1116
- const existingAccounts = new Set(scopeData.accounts);
1117
- const newAccounts = matchingAccounts.filter(
1118
- (account) => !existingAccounts.has(account)
1119
- );
1120
- scopeData.accounts.push(...newAccounts);
1145
+ return (_a = this.storage.get(key)) != null ? _a : null;
1146
+ });
1121
1147
  }
1122
- } catch (error) {
1123
- console.error(`Invalid scope format: ${scopeKey}`, error);
1124
- }
1148
+ set(key, value) {
1149
+ return __async(this, null, function* () {
1150
+ this.storage.set(key, value);
1151
+ });
1152
+ }
1153
+ delete(key) {
1154
+ return __async(this, null, function* () {
1155
+ this.storage.delete(key);
1156
+ });
1157
+ }
1158
+ };
1125
1159
  }
1126
- return result;
1127
- }
1160
+ });
1161
+
1162
+ // src/index.node.ts
1163
+ var index_node_exports = {};
1164
+ __export(index_node_exports, {
1165
+ EventEmitter: () => EventEmitter,
1166
+ Modal: () => Modal,
1167
+ MultichainCore: () => MultichainCore,
1168
+ PlatformType: () => PlatformType,
1169
+ RPCHttpErr: () => RPCHttpErr,
1170
+ RPCInvokeMethodErr: () => RPCInvokeMethodErr,
1171
+ RPCReadonlyRequestErr: () => RPCReadonlyRequestErr,
1172
+ RPCReadonlyResponseErr: () => RPCReadonlyResponseErr,
1173
+ RPC_HANDLED_METHODS: () => RPC_HANDLED_METHODS,
1174
+ SDK_HANDLED_METHODS: () => SDK_HANDLED_METHODS,
1175
+ StoreAdapter: () => StoreAdapter,
1176
+ StoreClient: () => StoreClient,
1177
+ TransportType: () => TransportType,
1178
+ createLogger: () => createLogger,
1179
+ createMetamaskConnect: () => createMetamaskConnect,
1180
+ enableDebug: () => enableDebug,
1181
+ getInfuraRpcUrls: () => getInfuraRpcUrls,
1182
+ getPlatformType: () => getPlatformType,
1183
+ getTransportType: () => getTransportType,
1184
+ getVersion: () => getVersion,
1185
+ getWalletActionAnalyticsProperties: () => getWalletActionAnalyticsProperties,
1186
+ hasExtension: () => hasExtension,
1187
+ infuraRpcUrls: () => infuraRpcUrls,
1188
+ isEnabled: () => isEnabled,
1189
+ isMetamaskExtensionInstalled: () => isMetamaskExtensionInstalled,
1190
+ isRejectionError: () => isRejectionError,
1191
+ isSecure: () => isSecure
1192
+ });
1193
+ module.exports = __toCommonJS(index_node_exports);
1194
+
1195
+ // src/multichain/index.ts
1196
+ var import_analytics4 = require("@metamask/analytics");
1197
+ var import_mobile_wallet_protocol_core2 = require("@metamask/mobile-wallet-protocol-core");
1198
+ var import_mobile_wallet_protocol_dapp_client = require("@metamask/mobile-wallet-protocol-dapp-client");
1199
+ var import_multichain_api_client3 = require("@metamask/multichain-api-client");
1200
+
1201
+ // src/config/index.ts
1202
+ var MWP_RELAY_URL = "wss://mm-sdk-relay.api.cx.metamask.io/connection/websocket";
1203
+ var METAMASK_CONNECT_BASE_URL = "https://metamask.app.link/connect";
1204
+ var METAMASK_DEEPLINK_BASE = "metamask://connect";
1205
+
1206
+ // src/multichain/index.ts
1207
+ init_domain();
1208
+ init_analytics();
1209
+ init_logger();
1210
+ init_multichain();
1211
+ init_platform();
1128
1212
 
1129
1213
  // src/multichain/rpc/handlers/rpcClient.ts
1130
1214
  var import_cross_fetch = __toESM(require("cross-fetch"));
@@ -1143,6 +1227,7 @@ var RpcClient = class {
1143
1227
  }
1144
1228
  /**
1145
1229
  * Routes the request to a configured RPC node.
1230
+ * @param options - The invoke method options
1146
1231
  */
1147
1232
  request(options) {
1148
1233
  return __async(this, null, function* () {
@@ -1154,46 +1239,45 @@ var RpcClient = class {
1154
1239
  id: getNextRpcId()
1155
1240
  });
1156
1241
  const rpcEndpoint = this.getRpcEndpoint(options.scope);
1157
- const rpcRequest = yield this.fetch(rpcEndpoint, body, "POST", this.getHeaders(rpcEndpoint));
1242
+ const rpcRequest = yield this.fetchWithTimeout(rpcEndpoint, body, "POST", this.getHeaders(rpcEndpoint), 3e4);
1158
1243
  const response = yield this.parseResponse(rpcRequest);
1159
1244
  return response;
1160
1245
  });
1161
1246
  }
1162
1247
  getRpcEndpoint(scope) {
1163
- var _a, _b, _c, _d, _e;
1164
- let infuraAPIKey = (_b = (_a = this.config) == null ? void 0 : _a.api) == null ? void 0 : _b.infuraAPIKey;
1165
- let readonlyRPCMap = (_e = (_d = (_c = this.config) == null ? void 0 : _c.api) == null ? void 0 : _d.readonlyRPCMap) != null ? _e : {};
1166
- if (infuraAPIKey) {
1167
- const urlsWithToken = getInfuraRpcUrls(infuraAPIKey);
1168
- if (readonlyRPCMap) {
1169
- readonlyRPCMap = __spreadValues(__spreadValues({}, urlsWithToken), readonlyRPCMap);
1170
- } else {
1171
- readonlyRPCMap = urlsWithToken;
1172
- }
1173
- }
1174
- const rpcEndpoint = readonlyRPCMap[scope];
1248
+ var _a, _b, _c;
1249
+ const supportedNetworks = (_c = (_b = (_a = this.config) == null ? void 0 : _a.api) == null ? void 0 : _b.supportedNetworks) != null ? _c : {};
1250
+ const rpcEndpoint = supportedNetworks[scope];
1175
1251
  if (!rpcEndpoint) {
1176
1252
  throw new MissingRpcEndpointErr(`No RPC endpoint found for scope ${scope}`);
1177
1253
  }
1178
1254
  return rpcEndpoint;
1179
1255
  }
1180
- fetch(endpoint, body, method, headers) {
1256
+ fetchWithTimeout(endpoint, body, method, headers, timeout) {
1181
1257
  return __async(this, null, function* () {
1258
+ const controller = new AbortController();
1259
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
1182
1260
  try {
1183
1261
  const response = yield (0, import_cross_fetch.default)(endpoint, {
1184
1262
  method,
1185
1263
  headers,
1186
- body
1264
+ body,
1265
+ signal: controller.signal
1187
1266
  });
1267
+ clearTimeout(timeoutId);
1188
1268
  if (!response.ok) {
1189
1269
  throw new RPCHttpErr(endpoint, method, response.status);
1190
1270
  }
1191
1271
  return response;
1192
1272
  } catch (error) {
1273
+ clearTimeout(timeoutId);
1193
1274
  if (error instanceof RPCHttpErr) {
1194
1275
  throw error;
1195
1276
  }
1196
- throw new RPCReadonlyRequestErr(error.message);
1277
+ if (error instanceof Error && error.name === "AbortError") {
1278
+ throw new RPCReadonlyRequestErr(`Request timeout after ${timeout}ms`);
1279
+ }
1280
+ throw new RPCReadonlyRequestErr(error instanceof Error ? error.message : "Unknown error");
1197
1281
  }
1198
1282
  });
1199
1283
  }
@@ -1222,11 +1306,17 @@ var RpcClient = class {
1222
1306
  };
1223
1307
 
1224
1308
  // src/multichain/rpc/requestRouter.ts
1309
+ var import_analytics2 = require("@metamask/analytics");
1310
+ init_domain();
1311
+ init_utils();
1312
+ init_analytics();
1313
+ var _RequestRouter_instances, withAnalyticsTracking_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, trackWalletActionRejected_fn;
1225
1314
  var RequestRouter = class {
1226
1315
  constructor(transport, rpcClient, config) {
1227
1316
  this.transport = transport;
1228
1317
  this.rpcClient = rpcClient;
1229
1318
  this.config = config;
1319
+ __privateAdd(this, _RequestRouter_instances);
1230
1320
  }
1231
1321
  /**
1232
1322
  * The main entry point for invoking an RPC method.
@@ -1250,15 +1340,15 @@ var RequestRouter = class {
1250
1340
  */
1251
1341
  handleWithWallet(options) {
1252
1342
  return __async(this, null, function* () {
1253
- try {
1343
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1254
1344
  const request = this.transport.request({
1255
1345
  method: "wallet_invokeMethod",
1256
1346
  params: options
1257
1347
  });
1258
1348
  const { ui, mobile } = this.config;
1259
- const { preferDesktop = false } = ui != null ? ui : {};
1349
+ const { showInstallModal = false } = ui != null ? ui : {};
1260
1350
  const secure = isSecure();
1261
- const shouldOpenDeeplink = secure && !preferDesktop;
1351
+ const shouldOpenDeeplink = secure && !showInstallModal;
1262
1352
  if (shouldOpenDeeplink) {
1263
1353
  setTimeout(() => {
1264
1354
  if (mobile == null ? void 0 : mobile.preferredOpenLink) {
@@ -1273,9 +1363,7 @@ var RequestRouter = class {
1273
1363
  throw new RPCInvokeMethodErr(`RPC Request failed with code ${response.error.code}: ${response.error.message}`);
1274
1364
  }
1275
1365
  return response.result;
1276
- } catch (error) {
1277
- throw new RPCInvokeMethodErr(error.message);
1278
- }
1366
+ }));
1279
1367
  });
1280
1368
  }
1281
1369
  /**
@@ -1283,14 +1371,16 @@ var RequestRouter = class {
1283
1371
  */
1284
1372
  handleWithRpcNode(options) {
1285
1373
  return __async(this, null, function* () {
1286
- try {
1287
- return yield this.rpcClient.request(options);
1288
- } catch (error) {
1289
- if (error instanceof MissingRpcEndpointErr) {
1290
- return this.handleWithWallet(options);
1374
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1375
+ try {
1376
+ return yield this.rpcClient.request(options);
1377
+ } catch (error) {
1378
+ if (error instanceof MissingRpcEndpointErr) {
1379
+ return this.handleWithWallet(options);
1380
+ }
1381
+ throw error;
1291
1382
  }
1292
- throw error;
1293
- }
1383
+ }));
1294
1384
  });
1295
1385
  }
1296
1386
  /**
@@ -1303,11 +1393,62 @@ var RequestRouter = class {
1303
1393
  });
1304
1394
  }
1305
1395
  };
1396
+ _RequestRouter_instances = new WeakSet();
1397
+ withAnalyticsTracking_fn = function(options, execute) {
1398
+ return __async(this, null, function* () {
1399
+ var _a, _b, _c;
1400
+ if ((_a = this.config.analytics) == null ? void 0 : _a.enabled) {
1401
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRequested_fn).call(this, options);
1402
+ }
1403
+ try {
1404
+ const result = yield execute();
1405
+ if ((_b = this.config.analytics) == null ? void 0 : _b.enabled) {
1406
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionSucceeded_fn).call(this, options);
1407
+ }
1408
+ return result;
1409
+ } catch (error) {
1410
+ if ((_c = this.config.analytics) == null ? void 0 : _c.enabled) {
1411
+ const isRejection = isRejectionError(error);
1412
+ if (isRejection) {
1413
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRejected_fn).call(this, options);
1414
+ } else {
1415
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options);
1416
+ }
1417
+ }
1418
+ throw new RPCInvokeMethodErr(error.message);
1419
+ }
1420
+ });
1421
+ };
1422
+ trackWalletActionRequested_fn = function(options) {
1423
+ return __async(this, null, function* () {
1424
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1425
+ import_analytics2.analytics.track("mmconnect_wallet_action_requested", props);
1426
+ });
1427
+ };
1428
+ trackWalletActionSucceeded_fn = function(options) {
1429
+ return __async(this, null, function* () {
1430
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1431
+ import_analytics2.analytics.track("mmconnect_wallet_action_succeeded", props);
1432
+ });
1433
+ };
1434
+ trackWalletActionFailed_fn = function(options) {
1435
+ return __async(this, null, function* () {
1436
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1437
+ import_analytics2.analytics.track("mmconnect_wallet_action_failed", props);
1438
+ });
1439
+ };
1440
+ trackWalletActionRejected_fn = function(options) {
1441
+ return __async(this, null, function* () {
1442
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1443
+ import_analytics2.analytics.track("mmconnect_wallet_action_rejected", props);
1444
+ });
1445
+ };
1306
1446
 
1307
1447
  // src/multichain/transports/default/index.ts
1308
1448
  var import_multichain_api_client = require("@metamask/multichain-api-client");
1449
+ init_utils();
1309
1450
  var DEFAULT_REQUEST_TIMEOUT = 60 * 1e3;
1310
- var _notificationCallbacks, _transport, _defaultRequestOptions, _DefaultTransport_instances, notifyCallbacks_fn;
1451
+ var _notificationCallbacks, _transport, _defaultRequestOptions, _reqId, _pendingRequests, _handleResponseListener, _handleNotificationListener, _DefaultTransport_instances, notifyCallbacks_fn, isMetamaskProviderEvent_fn, handleResponse_fn, handleNotification_fn, setupMessageListener_fn;
1311
1452
  var DefaultTransport = class {
1312
1453
  constructor() {
1313
1454
  __privateAdd(this, _DefaultTransport_instances);
@@ -1316,10 +1457,52 @@ var DefaultTransport = class {
1316
1457
  __privateAdd(this, _defaultRequestOptions, {
1317
1458
  timeout: DEFAULT_REQUEST_TIMEOUT
1318
1459
  });
1460
+ // Use timestamp-based ID to avoid conflicts across disconnect/reconnect cycles
1461
+ __privateAdd(this, _reqId, Date.now());
1462
+ __privateAdd(this, _pendingRequests, /* @__PURE__ */ new Map());
1463
+ __privateAdd(this, _handleResponseListener);
1464
+ __privateAdd(this, _handleNotificationListener);
1465
+ }
1466
+ sendEip1193Message(payload, options) {
1467
+ return __async(this, null, function* () {
1468
+ __privateMethod(this, _DefaultTransport_instances, setupMessageListener_fn).call(this);
1469
+ __privateSet(this, _reqId, __privateGet(this, _reqId) + 1);
1470
+ const requestId = `${__privateGet(this, _reqId)}`;
1471
+ const request = __spreadValues({
1472
+ jsonrpc: "2.0",
1473
+ id: requestId
1474
+ }, payload);
1475
+ return new Promise((resolve, reject) => {
1476
+ var _a;
1477
+ const timeout = setTimeout(() => {
1478
+ __privateGet(this, _pendingRequests).delete(requestId);
1479
+ reject(new Error("Request timeout"));
1480
+ }, (_a = options == null ? void 0 : options.timeout) != null ? _a : __privateGet(this, _defaultRequestOptions).timeout);
1481
+ __privateGet(this, _pendingRequests).set(requestId, {
1482
+ resolve: (response) => {
1483
+ resolve(response);
1484
+ },
1485
+ reject,
1486
+ timeout
1487
+ });
1488
+ window.postMessage(
1489
+ {
1490
+ target: "metamask-contentscript",
1491
+ data: {
1492
+ name: "metamask-provider",
1493
+ data: request
1494
+ }
1495
+ },
1496
+ // eslint-disable-next-line no-restricted-globals
1497
+ location.origin
1498
+ );
1499
+ });
1500
+ });
1319
1501
  }
1320
1502
  connect(options) {
1321
1503
  return __async(this, null, function* () {
1322
1504
  var _a, _b, _c, _d, _e, _f, _g;
1505
+ __privateMethod(this, _DefaultTransport_instances, setupMessageListener_fn).call(this);
1323
1506
  yield __privateGet(this, _transport).connect();
1324
1507
  const sessionRequest = yield this.request(
1325
1508
  { method: "wallet_getSession" },
@@ -1329,7 +1512,7 @@ var DefaultTransport = class {
1329
1512
  throw new Error(sessionRequest.error.message);
1330
1513
  }
1331
1514
  let walletSession = sessionRequest.result;
1332
- if (walletSession && options) {
1515
+ if (walletSession && options && !options.forceRequest) {
1333
1516
  const currentScopes = Object.keys(
1334
1517
  (_a = walletSession == null ? void 0 : walletSession.sessionScopes) != null ? _a : {}
1335
1518
  );
@@ -1350,9 +1533,11 @@ var DefaultTransport = class {
1350
1533
  getOptionalScopes((_d = options == null ? void 0 : options.scopes) != null ? _d : []),
1351
1534
  getValidAccounts((_e = options == null ? void 0 : options.caipAccountIds) != null ? _e : [])
1352
1535
  );
1353
- const sessionRequest2 = { optionalScopes };
1536
+ const createSessionParams = {
1537
+ optionalScopes
1538
+ };
1354
1539
  const response = yield this.request(
1355
- { method: "wallet_createSession", params: sessionRequest2 },
1540
+ { method: "wallet_createSession", params: createSessionParams },
1356
1541
  __privateGet(this, _defaultRequestOptions)
1357
1542
  );
1358
1543
  if (response.error) {
@@ -1360,14 +1545,16 @@ var DefaultTransport = class {
1360
1545
  }
1361
1546
  walletSession = response.result;
1362
1547
  }
1363
- } else if (!walletSession) {
1548
+ } else if (!walletSession || (options == null ? void 0 : options.forceRequest)) {
1364
1549
  const optionalScopes = addValidAccounts(
1365
1550
  getOptionalScopes((_f = options == null ? void 0 : options.scopes) != null ? _f : []),
1366
1551
  getValidAccounts((_g = options == null ? void 0 : options.caipAccountIds) != null ? _g : [])
1367
1552
  );
1368
- const sessionRequest2 = { optionalScopes };
1553
+ const createSessionParams = {
1554
+ optionalScopes
1555
+ };
1369
1556
  const response = yield this.request(
1370
- { method: "wallet_createSession", params: sessionRequest2 },
1557
+ { method: "wallet_createSession", params: createSessionParams },
1371
1558
  __privateGet(this, _defaultRequestOptions)
1372
1559
  );
1373
1560
  if (response.error) {
@@ -1384,6 +1571,16 @@ var DefaultTransport = class {
1384
1571
  disconnect() {
1385
1572
  return __async(this, null, function* () {
1386
1573
  __privateGet(this, _notificationCallbacks).clear();
1574
+ yield this.request({ method: "wallet_revokeSession", params: {} });
1575
+ if (__privateGet(this, _handleResponseListener)) {
1576
+ window.removeEventListener("message", __privateGet(this, _handleResponseListener));
1577
+ __privateSet(this, _handleResponseListener, void 0);
1578
+ }
1579
+ for (const [, request] of __privateGet(this, _pendingRequests)) {
1580
+ clearTimeout(request.timeout);
1581
+ request.reject(new Error("Transport disconnected"));
1582
+ }
1583
+ __privateGet(this, _pendingRequests).clear();
1387
1584
  return __privateGet(this, _transport).disconnect();
1388
1585
  });
1389
1586
  }
@@ -1406,31 +1603,99 @@ var DefaultTransport = class {
1406
1603
  _notificationCallbacks = new WeakMap();
1407
1604
  _transport = new WeakMap();
1408
1605
  _defaultRequestOptions = new WeakMap();
1606
+ _reqId = new WeakMap();
1607
+ _pendingRequests = new WeakMap();
1608
+ _handleResponseListener = new WeakMap();
1609
+ _handleNotificationListener = new WeakMap();
1409
1610
  _DefaultTransport_instances = new WeakSet();
1410
1611
  notifyCallbacks_fn = function(data) {
1411
- for (const cb of __privateGet(this, _notificationCallbacks)) {
1612
+ for (const callback of __privateGet(this, _notificationCallbacks)) {
1412
1613
  try {
1413
- cb(data);
1414
- } catch (err) {
1415
- console.log("[WindowPostMessageTransport] notifyCallbacks error:", err);
1614
+ callback(data);
1615
+ } catch (error) {
1616
+ console.log(
1617
+ "[WindowPostMessageTransport] notifyCallbacks error:",
1618
+ error
1619
+ );
1620
+ }
1621
+ }
1622
+ };
1623
+ isMetamaskProviderEvent_fn = function(event) {
1624
+ var _a, _b;
1625
+ return ((_b = (_a = event == null ? void 0 : event.data) == null ? void 0 : _a.data) == null ? void 0 : _b.name) === "metamask-provider" && // eslint-disable-next-line no-restricted-globals
1626
+ event.origin === location.origin;
1627
+ };
1628
+ handleResponse_fn = function(event) {
1629
+ var _a, _b;
1630
+ if (!__privateMethod(this, _DefaultTransport_instances, isMetamaskProviderEvent_fn).call(this, event)) {
1631
+ return;
1632
+ }
1633
+ const responseData = (_b = (_a = event == null ? void 0 : event.data) == null ? void 0 : _a.data) == null ? void 0 : _b.data;
1634
+ if (typeof responseData === "object" && responseData !== null && "method" in responseData) {
1635
+ return;
1636
+ }
1637
+ if (typeof responseData === "object" && responseData !== null && "id" in responseData && ("result" in responseData || "error" in responseData)) {
1638
+ const responseId = String(responseData.id);
1639
+ const pendingRequest = __privateGet(this, _pendingRequests).get(responseId);
1640
+ if (pendingRequest) {
1641
+ clearTimeout(pendingRequest.timeout);
1642
+ __privateGet(this, _pendingRequests).delete(responseId);
1643
+ const response = responseData;
1644
+ if ("error" in response && response.error) {
1645
+ pendingRequest.reject(
1646
+ new Error(response.error.message || "Request failed")
1647
+ );
1648
+ } else {
1649
+ pendingRequest.resolve(response);
1650
+ }
1416
1651
  }
1417
1652
  }
1418
1653
  };
1654
+ handleNotification_fn = function(event) {
1655
+ var _a, _b;
1656
+ if (!__privateMethod(this, _DefaultTransport_instances, isMetamaskProviderEvent_fn).call(this, event)) {
1657
+ return;
1658
+ }
1659
+ const responseData = (_b = (_a = event == null ? void 0 : event.data) == null ? void 0 : _a.data) == null ? void 0 : _b.data;
1660
+ if (typeof responseData === "object" && responseData.method === "metamask_chainChanged" || responseData.method === "metamask_accountsChanged") {
1661
+ __privateMethod(this, _DefaultTransport_instances, notifyCallbacks_fn).call(this, responseData);
1662
+ }
1663
+ };
1664
+ setupMessageListener_fn = function() {
1665
+ if (__privateGet(this, _handleResponseListener)) {
1666
+ return;
1667
+ }
1668
+ __privateSet(this, _handleResponseListener, __privateMethod(this, _DefaultTransport_instances, handleResponse_fn).bind(this));
1669
+ __privateSet(this, _handleNotificationListener, __privateMethod(this, _DefaultTransport_instances, handleNotification_fn).bind(this));
1670
+ window.addEventListener("message", __privateGet(this, _handleResponseListener));
1671
+ window.addEventListener("message", __privateGet(this, _handleNotificationListener));
1672
+ };
1419
1673
 
1420
1674
  // src/multichain/transports/mwp/index.ts
1421
1675
  var import_mobile_wallet_protocol_core = require("@metamask/mobile-wallet-protocol-core");
1422
1676
  var import_multichain_api_client2 = require("@metamask/multichain-api-client");
1423
1677
  init_domain();
1678
+ init_utils();
1679
+
1680
+ // src/multichain/transports/constants.ts
1681
+ var MULTICHAIN_PROVIDER_STREAM_NAME = "metamask-multichain-provider";
1682
+
1683
+ // src/multichain/transports/mwp/index.ts
1424
1684
  var DEFAULT_REQUEST_TIMEOUT2 = 60 * 1e3;
1425
1685
  var CONNECTION_GRACE_PERIOD = 60 * 1e3;
1426
1686
  var DEFAULT_CONNECTION_TIMEOUT = DEFAULT_REQUEST_TIMEOUT2 + CONNECTION_GRACE_PERIOD;
1427
1687
  var SESSION_STORE_KEY = "cache_wallet_getSession";
1688
+ var ACCOUNTS_STORE_KEY = "cache_eth_accounts";
1689
+ var CHAIN_STORE_KEY = "cache_eth_chainId";
1428
1690
  var CACHED_METHOD_LIST = [
1429
1691
  "wallet_getSession",
1430
1692
  "wallet_createSession",
1431
1693
  "wallet_sessionChanged"
1432
1694
  ];
1433
- var CACHED_RESET_METHOD_LIST = ["wallet_revokeSession"];
1695
+ var CACHED_RESET_METHOD_LIST = [
1696
+ "wallet_revokeSession",
1697
+ "wallet_revokePermissions"
1698
+ ];
1434
1699
  var logger = createLogger("metamask-sdk:transport");
1435
1700
  var MWPTransport = class {
1436
1701
  constructor(dappClient, kvstore, options = {
@@ -1494,6 +1759,22 @@ var MWPTransport = class {
1494
1759
  this.pendingRequests.delete(messagePayload.id);
1495
1760
  }
1496
1761
  } else {
1762
+ if (message.data.method === "metamask_chainChanged") {
1763
+ this.kvstore.set(
1764
+ CHAIN_STORE_KEY,
1765
+ JSON.stringify(
1766
+ message.data.params.chainId
1767
+ )
1768
+ );
1769
+ }
1770
+ if (message.data.method === "metamask_accountsChanged") {
1771
+ this.kvstore.set(
1772
+ ACCOUNTS_STORE_KEY,
1773
+ JSON.stringify(
1774
+ message.data.params
1775
+ )
1776
+ );
1777
+ }
1497
1778
  this.notifyCallbacks(message.data);
1498
1779
  }
1499
1780
  }
@@ -1564,6 +1845,40 @@ var MWPTransport = class {
1564
1845
  }
1565
1846
  });
1566
1847
  }
1848
+ // TODO: Rename this
1849
+ sendEip1193Message(payload, options) {
1850
+ return __async(this, null, function* () {
1851
+ const request = __spreadValues({
1852
+ jsonrpc: "2.0",
1853
+ id: `${this.__reqId++}`
1854
+ }, payload);
1855
+ const cachedWalletSession = yield this.getCachedResponse(request);
1856
+ if (cachedWalletSession) {
1857
+ this.notifyCallbacks(cachedWalletSession);
1858
+ return cachedWalletSession;
1859
+ }
1860
+ return new Promise((resolve, reject) => {
1861
+ var _a;
1862
+ const timeout = setTimeout(() => {
1863
+ this.rejectRequest(request.id, new import_multichain_api_client2.TransportTimeoutError());
1864
+ }, (_a = options == null ? void 0 : options.timeout) != null ? _a : this.options.requestTimeout);
1865
+ this.pendingRequests.set(request.id, {
1866
+ request,
1867
+ method: request.method,
1868
+ resolve: (response) => __async(this, null, function* () {
1869
+ yield this.storeWalletSession(request, response);
1870
+ return resolve(response);
1871
+ }),
1872
+ reject,
1873
+ timeout
1874
+ });
1875
+ this.dappClient.sendRequest({
1876
+ name: "metamask-provider",
1877
+ data: request
1878
+ }).catch(reject);
1879
+ });
1880
+ });
1881
+ }
1567
1882
  connect(options) {
1568
1883
  return __async(this, null, function* () {
1569
1884
  const { dappClient, kvstore } = this;
@@ -1617,17 +1932,23 @@ var MWPTransport = class {
1617
1932
  if (messagePayload.error) {
1618
1933
  return rejectConnection(messagePayload.error);
1619
1934
  }
1620
- this.notifyCallbacks(message.data);
1621
1935
  yield this.storeWalletSession(
1622
1936
  request,
1623
1937
  messagePayload
1624
1938
  );
1939
+ this.notifyCallbacks(messagePayload);
1625
1940
  return resolveConnection();
1626
1941
  }
1627
1942
  }
1628
1943
  }
1629
1944
  }));
1630
- dappClient.connect({ mode: "trusted", initialPayload: request }).catch(rejectConnection);
1945
+ dappClient.connect({
1946
+ mode: "trusted",
1947
+ initialPayload: {
1948
+ name: MULTICHAIN_PROVIDER_STREAM_NAME,
1949
+ data: request
1950
+ }
1951
+ }).catch(rejectConnection);
1631
1952
  }
1632
1953
  );
1633
1954
  }
@@ -1654,6 +1975,9 @@ var MWPTransport = class {
1654
1975
  window.removeEventListener("focus", this.windowFocusHandler);
1655
1976
  this.windowFocusHandler = void 0;
1656
1977
  }
1978
+ this.kvstore.delete(SESSION_STORE_KEY);
1979
+ this.kvstore.delete(ACCOUNTS_STORE_KEY);
1980
+ this.kvstore.delete(CHAIN_STORE_KEY);
1657
1981
  return this.dappClient.disconnect();
1658
1982
  });
1659
1983
  }
@@ -1665,7 +1989,39 @@ var MWPTransport = class {
1665
1989
  isConnected() {
1666
1990
  return this.dappClient.state === "CONNECTED";
1667
1991
  }
1668
- fetchCachedWalletSession(request) {
1992
+ /**
1993
+ * Attempts to re-establish a connection via DappClient
1994
+ *
1995
+ * @returns Nothing
1996
+ */
1997
+ // TODO: We should re-evaluate adding this to the WebSocketTransport layer from `@metamask/mobile-wallet-protocol-core`
1998
+ // ticket: https://consensyssoftware.atlassian.net/browse/WAPI-862
1999
+ attemptResumeSession() {
2000
+ return __async(this, null, function* () {
2001
+ try {
2002
+ yield this.dappClient.reconnect();
2003
+ yield new Promise((resolve, reject) => {
2004
+ const timeout = setTimeout(() => {
2005
+ reject(new Error("Resume timeout"));
2006
+ }, 2e3);
2007
+ if (this.isConnected()) {
2008
+ clearTimeout(timeout);
2009
+ resolve();
2010
+ } else {
2011
+ this.dappClient.once("connected", () => {
2012
+ clearTimeout(timeout);
2013
+ resolve();
2014
+ });
2015
+ }
2016
+ });
2017
+ } catch (error) {
2018
+ return Promise.reject(
2019
+ new Error(`Failed to resume session: ${error.message}`)
2020
+ );
2021
+ }
2022
+ });
2023
+ }
2024
+ getCachedResponse(request) {
1669
2025
  return __async(this, null, function* () {
1670
2026
  var _a;
1671
2027
  if (request.method === "wallet_getSession") {
@@ -1676,6 +2032,27 @@ var MWPTransport = class {
1676
2032
  id: request.id,
1677
2033
  jsonrpc: "2.0",
1678
2034
  result: (_a = walletSession.params) != null ? _a : walletSession.result,
2035
+ // "what?... why walletSession.params?.."
2036
+ method: request.method
2037
+ };
2038
+ }
2039
+ } else if (request.method === "eth_accounts") {
2040
+ const ethAccounts = yield this.kvstore.get(ACCOUNTS_STORE_KEY);
2041
+ if (ethAccounts) {
2042
+ return {
2043
+ id: request.id,
2044
+ jsonrpc: "2.0",
2045
+ result: JSON.parse(ethAccounts),
2046
+ method: request.method
2047
+ };
2048
+ }
2049
+ } else if (request.method === "eth_chainId") {
2050
+ const ethChainId = yield this.kvstore.get(CHAIN_STORE_KEY);
2051
+ if (ethChainId) {
2052
+ return {
2053
+ id: request.id,
2054
+ jsonrpc: "2.0",
2055
+ result: JSON.parse(ethChainId),
1679
2056
  method: request.method
1680
2057
  };
1681
2058
  }
@@ -1686,8 +2063,17 @@ var MWPTransport = class {
1686
2063
  return __async(this, null, function* () {
1687
2064
  if (CACHED_METHOD_LIST.includes(request.method)) {
1688
2065
  yield this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
2066
+ } else if (request.method === "eth_accounts") {
2067
+ yield this.kvstore.set(
2068
+ ACCOUNTS_STORE_KEY,
2069
+ JSON.stringify(response.result)
2070
+ );
2071
+ } else if (request.method === "eth_chainId") {
2072
+ yield this.kvstore.set(CHAIN_STORE_KEY, JSON.stringify(response.result));
1689
2073
  } else if (CACHED_RESET_METHOD_LIST.includes(request.method)) {
1690
2074
  yield this.kvstore.delete(SESSION_STORE_KEY);
2075
+ yield this.kvstore.delete(ACCOUNTS_STORE_KEY);
2076
+ yield this.kvstore.delete(CHAIN_STORE_KEY);
1691
2077
  }
1692
2078
  });
1693
2079
  }
@@ -1697,11 +2083,14 @@ var MWPTransport = class {
1697
2083
  jsonrpc: "2.0",
1698
2084
  id: `${this.__reqId++}`
1699
2085
  }, payload);
1700
- const cachedWalletSession = yield this.fetchCachedWalletSession(request);
2086
+ const cachedWalletSession = yield this.getCachedResponse(request);
1701
2087
  if (cachedWalletSession) {
1702
2088
  this.notifyCallbacks(cachedWalletSession);
1703
2089
  return cachedWalletSession;
1704
2090
  }
2091
+ if (!this.isConnected()) {
2092
+ yield this.attemptResumeSession();
2093
+ }
1705
2094
  return new Promise((resolve, reject) => {
1706
2095
  var _a;
1707
2096
  const timeout = setTimeout(() => {
@@ -1711,15 +2100,16 @@ var MWPTransport = class {
1711
2100
  request,
1712
2101
  method: request.method,
1713
2102
  resolve: (response) => __async(this, null, function* () {
1714
- if (CACHED_METHOD_LIST.includes(request.method)) {
1715
- yield this.storeWalletSession(request, response);
1716
- }
2103
+ yield this.storeWalletSession(request, response);
1717
2104
  return resolve(response);
1718
2105
  }),
1719
2106
  reject,
1720
2107
  timeout
1721
2108
  });
1722
- this.dappClient.sendRequest(request).catch(reject);
2109
+ this.dappClient.sendRequest({
2110
+ name: MULTICHAIN_PROVIDER_STREAM_NAME,
2111
+ data: request
2112
+ }).catch(reject);
1723
2113
  });
1724
2114
  });
1725
2115
  }
@@ -1759,21 +2149,22 @@ var KeyManager = class {
1759
2149
  var keymanager = new KeyManager();
1760
2150
 
1761
2151
  // src/multichain/index.ts
2152
+ init_utils();
1762
2153
  var logger2 = createLogger("metamask-sdk:core");
1763
2154
  var MultichainSDK = class _MultichainSDK extends MultichainCore {
1764
2155
  constructor(options) {
1765
- var _a, _b, _c, _d, _e, _f;
1766
- const withInfuraRPCMethods = setupInfuraProvider(options);
1767
- const withDappMetadata = setupDappMetadata(withInfuraRPCMethods);
2156
+ var _a, _b, _c, _d, _e, _f, _g;
2157
+ const withDappMetadata = setupDappMetadata(options);
2158
+ const integrationType = ((_a = options.analytics) == null ? void 0 : _a.enabled) ? options.analytics.integrationType : "direct";
1768
2159
  const allOptions = __spreadProps(__spreadValues({}, withDappMetadata), {
1769
2160
  ui: __spreadProps(__spreadValues({}, withDappMetadata.ui), {
1770
- preferExtension: (_a = withDappMetadata.ui.preferExtension) != null ? _a : true,
1771
- preferDesktop: (_b = withDappMetadata.ui.preferDesktop) != null ? _b : false,
1772
- headless: (_c = withDappMetadata.ui.headless) != null ? _c : false
2161
+ preferExtension: (_b = withDappMetadata.ui.preferExtension) != null ? _b : true,
2162
+ showInstallModal: (_c = withDappMetadata.ui.showInstallModal) != null ? _c : false,
2163
+ headless: (_d = withDappMetadata.ui.headless) != null ? _d : false
1773
2164
  }),
1774
- analytics: __spreadProps(__spreadValues({}, (_d = options.analytics) != null ? _d : {}), {
1775
- enabled: (_f = (_e = options.analytics) == null ? void 0 : _e.enabled) != null ? _f : true,
1776
- integrationType: "unknown"
2165
+ analytics: __spreadProps(__spreadValues({}, (_e = options.analytics) != null ? _e : {}), {
2166
+ enabled: (_g = (_f = options.analytics) == null ? void 0 : _f.enabled) != null ? _g : true,
2167
+ integrationType
1777
2168
  })
1778
2169
  });
1779
2170
  super(allOptions);
@@ -1794,6 +2185,10 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1794
2185
  });
1795
2186
  }
1796
2187
  get provider() {
2188
+ if (!this.__provider && this.__transport) {
2189
+ this.__provider = (0, import_multichain_api_client3.getMultichainClient)({ transport: this.__transport });
2190
+ return this.__provider;
2191
+ }
1797
2192
  if (!this.__provider) {
1798
2193
  throw new Error("Provider not initialized, establish connection first");
1799
2194
  }
@@ -1814,6 +2209,9 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1814
2209
  get storage() {
1815
2210
  return this.options.storage;
1816
2211
  }
2212
+ get transportType() {
2213
+ return this.__transport instanceof MWPTransport ? "mwp" /* MWP */ : "browser" /* Browser */;
2214
+ }
1817
2215
  get sdkInfo() {
1818
2216
  var _a;
1819
2217
  return `Sdk/Javascript SdkVersion/${getVersion()} Platform/${getPlatformType()} dApp/${(_a = this.options.dapp.url) != null ? _a : this.options.dapp.name} dAppTitle/${this.options.dapp.name}`;
@@ -1850,12 +2248,12 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1850
2248
  const { integrationType } = (_b = this.options.analytics) != null ? _b : {
1851
2249
  integrationType: ""
1852
2250
  };
1853
- import_analytics.analytics.setGlobalProperty("sdk_version", version);
1854
- import_analytics.analytics.setGlobalProperty("dapp_id", dappId);
1855
- import_analytics.analytics.setGlobalProperty("anon_id", anonId);
1856
- import_analytics.analytics.setGlobalProperty("platform", platform);
1857
- import_analytics.analytics.setGlobalProperty("integration_type", integrationType);
1858
- import_analytics.analytics.enable();
2251
+ import_analytics4.analytics.setGlobalProperty("mmconnect_version", version);
2252
+ import_analytics4.analytics.setGlobalProperty("dapp_id", dappId);
2253
+ import_analytics4.analytics.setGlobalProperty("anon_id", anonId);
2254
+ import_analytics4.analytics.setGlobalProperty("platform", platform);
2255
+ import_analytics4.analytics.setGlobalProperty("integration_type", integrationType);
2256
+ import_analytics4.analytics.enable();
1859
2257
  });
1860
2258
  }
1861
2259
  onTransportNotification(payload) {
@@ -1868,13 +2266,11 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1868
2266
  }
1869
2267
  getStoredTransport() {
1870
2268
  return __async(this, null, function* () {
1871
- const { ui } = this.options;
1872
- const { preferExtension = true } = ui;
1873
2269
  const transportType = yield this.storage.getTransport();
1874
2270
  const hasExtensionInstalled = yield hasExtension();
1875
2271
  if (transportType) {
1876
2272
  if (transportType === "browser" /* Browser */) {
1877
- if (hasExtensionInstalled && preferExtension) {
2273
+ if (hasExtensionInstalled) {
1878
2274
  const apiTransport = new DefaultTransport();
1879
2275
  this.__transport = apiTransport;
1880
2276
  this.listener = apiTransport.onNotification(
@@ -1882,7 +2278,7 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1882
2278
  );
1883
2279
  return apiTransport;
1884
2280
  }
1885
- } else if (transportType === "mwp" /* MPW */) {
2281
+ } else if (transportType === "mwp" /* MWP */) {
1886
2282
  const { adapter: kvstore } = this.options.storage;
1887
2283
  const dappClient = yield this.createDappClient();
1888
2284
  const apiTransport = new MWPTransport(dappClient, kvstore);
@@ -1908,7 +2304,7 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1908
2304
  }
1909
2305
  this.state = "connected";
1910
2306
  if (this.transport instanceof MWPTransport) {
1911
- yield this.storage.setTransport("mwp" /* MPW */);
2307
+ yield this.storage.setTransport("mwp" /* MWP */);
1912
2308
  } else {
1913
2309
  yield this.storage.setTransport("browser" /* Browser */);
1914
2310
  }
@@ -1919,14 +2315,24 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1919
2315
  }
1920
2316
  init() {
1921
2317
  return __async(this, null, function* () {
1922
- var _a;
2318
+ var _a, _b;
1923
2319
  try {
1924
2320
  if (typeof window !== "undefined" && ((_a = window.mmsdk) == null ? void 0 : _a.isInitialized)) {
1925
2321
  logger2("MetaMaskSDK: init already initialized");
1926
2322
  } else {
1927
2323
  yield this.setupAnalytics();
1928
2324
  yield this.setupTransport();
1929
- import_analytics.analytics.track("sdk_initialized", {});
2325
+ if ((_b = this.options.analytics) == null ? void 0 : _b.enabled) {
2326
+ try {
2327
+ const baseProps = yield getBaseAnalyticsProperties(
2328
+ this.options,
2329
+ this.storage
2330
+ );
2331
+ import_analytics4.analytics.track("mmconnect_initialized", baseProps);
2332
+ } catch (error) {
2333
+ logger2("Error tracking initialized event", error);
2334
+ }
2335
+ }
1930
2336
  if (typeof window !== "undefined") {
1931
2337
  window.mmsdk = this;
1932
2338
  }
@@ -1968,7 +2374,7 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1968
2374
  this.listener = this.transport.onNotification(
1969
2375
  this.onTransportNotification.bind(this)
1970
2376
  );
1971
- yield this.storage.setTransport("mwp" /* MPW */);
2377
+ yield this.storage.setTransport("mwp" /* MWP */);
1972
2378
  });
1973
2379
  }
1974
2380
  onBeforeUnload() {
@@ -2024,7 +2430,7 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2024
2430
  this.options.ui.factory.unload();
2025
2431
  (_a2 = this.options.ui.factory.modal) == null ? void 0 : _a2.unmount();
2026
2432
  this.state = "connected";
2027
- return this.storage.setTransport("mwp" /* MPW */);
2433
+ return this.storage.setTransport("mwp" /* MWP */);
2028
2434
  }).catch((error) => {
2029
2435
  if (error instanceof import_mobile_wallet_protocol_core2.ProtocolError) {
2030
2436
  if (error.code !== import_mobile_wallet_protocol_core2.ErrorCode.REQUEST_EXPIRED) {
@@ -2040,7 +2446,7 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2040
2446
  }),
2041
2447
  (error) => __async(this, null, function* () {
2042
2448
  if (!error) {
2043
- yield this.storage.setTransport("mwp" /* MPW */);
2449
+ yield this.storage.setTransport("mwp" /* MWP */);
2044
2450
  resolve();
2045
2451
  } else {
2046
2452
  yield this.storage.removeTransport();
@@ -2128,52 +2534,128 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2128
2534
  }));
2129
2535
  });
2130
2536
  }
2131
- handleConnection(promise) {
2537
+ handleConnection(promise, scopes, transportType) {
2132
2538
  return __async(this, null, function* () {
2133
2539
  this.state = "connecting";
2134
- return promise.then(() => {
2540
+ return promise.then(() => __async(this, null, function* () {
2541
+ var _a;
2135
2542
  this.state = "connected";
2136
- }).catch((error) => {
2543
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2544
+ try {
2545
+ const baseProps = yield getBaseAnalyticsProperties(
2546
+ this.options,
2547
+ this.storage
2548
+ );
2549
+ import_analytics4.analytics.track("mmconnect_connection_established", __spreadProps(__spreadValues({}, baseProps), {
2550
+ transport_type: transportType,
2551
+ user_permissioned_chains: scopes
2552
+ }));
2553
+ } catch (error) {
2554
+ logger2("Error tracking connection_established event", error);
2555
+ }
2556
+ }
2557
+ })).catch((error) => __async(this, null, function* () {
2558
+ var _a;
2137
2559
  this.state = "disconnected";
2560
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2561
+ try {
2562
+ const baseProps = yield getBaseAnalyticsProperties(
2563
+ this.options,
2564
+ this.storage
2565
+ );
2566
+ const isRejection = isRejectionError(error);
2567
+ if (isRejection) {
2568
+ import_analytics4.analytics.track("mmconnect_connection_rejected", __spreadProps(__spreadValues({}, baseProps), {
2569
+ transport_type: transportType
2570
+ }));
2571
+ } else {
2572
+ import_analytics4.analytics.track("mmconnect_connection_failed", __spreadProps(__spreadValues({}, baseProps), {
2573
+ transport_type: transportType
2574
+ }));
2575
+ }
2576
+ } catch (e) {
2577
+ logger2("Error tracking connection failed/rejected event", error);
2578
+ }
2579
+ }
2138
2580
  return Promise.reject(error);
2139
- });
2581
+ }));
2140
2582
  });
2141
2583
  }
2142
- connect(scopes, caipAccountIds) {
2584
+ connect(scopes, caipAccountIds, forceRequest) {
2143
2585
  return __async(this, null, function* () {
2144
- var _a;
2586
+ var _a, _b;
2145
2587
  const { ui } = this.options;
2146
2588
  const platformType = getPlatformType();
2147
2589
  const isWeb = platformType === "in-app-browser" /* MetaMaskMobileWebview */ || platformType === "web-desktop" /* DesktopWeb */;
2148
- const { preferExtension = true, preferDesktop = false } = ui;
2590
+ const { preferExtension = true, showInstallModal = false } = ui;
2149
2591
  const secure = isSecure();
2150
2592
  const hasExtensionInstalled = yield hasExtension();
2151
- if (((_a = this.__transport) == null ? void 0 : _a.isConnected()) && !secure) {
2593
+ let transportType;
2594
+ if (platformType === "in-app-browser" /* MetaMaskMobileWebview */ || isWeb && hasExtensionInstalled && preferExtension) {
2595
+ transportType = "browser" /* Browser */;
2596
+ } else {
2597
+ transportType = "mwp" /* MWP */;
2598
+ }
2599
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2600
+ try {
2601
+ const baseProps = yield getBaseAnalyticsProperties(
2602
+ this.options,
2603
+ this.storage
2604
+ );
2605
+ const dappConfiguredChains = Object.keys(
2606
+ this.options.api.supportedNetworks
2607
+ );
2608
+ import_analytics4.analytics.track("mmconnect_connection_initiated", __spreadProps(__spreadValues({}, baseProps), {
2609
+ transport_type: transportType,
2610
+ dapp_configured_chains: dappConfiguredChains,
2611
+ dapp_requested_chains: scopes
2612
+ }));
2613
+ } catch (error) {
2614
+ logger2("Error tracking connection_initiated event", error);
2615
+ }
2616
+ }
2617
+ if (((_b = this.__transport) == null ? void 0 : _b.isConnected()) && !secure) {
2152
2618
  return this.handleConnection(
2153
- this.__transport.connect({ scopes, caipAccountIds }).then(() => {
2619
+ this.__transport.connect({ scopes, caipAccountIds, forceRequest }).then(() => {
2154
2620
  if (this.__transport instanceof MWPTransport) {
2155
- return this.storage.setTransport("mwp" /* MPW */);
2621
+ return this.storage.setTransport("mwp" /* MWP */);
2156
2622
  } else {
2157
2623
  return this.storage.setTransport("browser" /* Browser */);
2158
2624
  }
2159
- })
2625
+ }),
2626
+ scopes,
2627
+ transportType
2628
+ );
2629
+ }
2630
+ if (platformType === "in-app-browser" /* MetaMaskMobileWebview */) {
2631
+ const defaultTransport = yield this.setupDefaultTransport();
2632
+ return this.handleConnection(
2633
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2634
+ scopes,
2635
+ transportType
2160
2636
  );
2161
2637
  }
2162
2638
  if (isWeb && hasExtensionInstalled && preferExtension) {
2163
2639
  const defaultTransport = yield this.setupDefaultTransport();
2164
2640
  return this.handleConnection(
2165
- defaultTransport.connect({ scopes, caipAccountIds })
2641
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2642
+ scopes,
2643
+ transportType
2166
2644
  );
2167
2645
  }
2168
2646
  yield this.setupMWP();
2169
- const isDesktopPreferred = hasExtensionInstalled ? preferDesktop : !preferExtension || preferDesktop;
2170
- if (secure && !isDesktopPreferred) {
2647
+ const shouldShowInstallModal = hasExtensionInstalled ? showInstallModal : !preferExtension || showInstallModal;
2648
+ if (secure && !shouldShowInstallModal) {
2171
2649
  return this.handleConnection(
2172
- this.deeplinkConnect(scopes, caipAccountIds)
2650
+ this.deeplinkConnect(scopes, caipAccountIds),
2651
+ scopes,
2652
+ transportType
2173
2653
  );
2174
2654
  }
2175
2655
  return this.handleConnection(
2176
- this.showInstallModal(isDesktopPreferred, scopes, caipAccountIds)
2656
+ this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds),
2657
+ scopes,
2658
+ transportType
2177
2659
  );
2178
2660
  });
2179
2661
  }
@@ -2208,6 +2690,26 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2208
2690
  return requestRouter.invokeMethod(request);
2209
2691
  });
2210
2692
  }
2693
+ // DRY THIS WITH REQUEST ROUTER
2694
+ openDeeplinkIfNeeded() {
2695
+ const { ui, mobile } = this.options;
2696
+ const { showInstallModal = false } = ui != null ? ui : {};
2697
+ const secure = isSecure();
2698
+ const shouldOpenDeeplink = secure && !showInstallModal;
2699
+ if (shouldOpenDeeplink) {
2700
+ setTimeout(() => {
2701
+ if (mobile == null ? void 0 : mobile.preferredOpenLink) {
2702
+ mobile.preferredOpenLink(METAMASK_DEEPLINK_BASE, "_self");
2703
+ } else {
2704
+ openDeeplink(
2705
+ this.options,
2706
+ METAMASK_DEEPLINK_BASE,
2707
+ METAMASK_CONNECT_BASE_URL
2708
+ );
2709
+ }
2710
+ }, 10);
2711
+ }
2712
+ }
2211
2713
  };
2212
2714
 
2213
2715
  // src/store/index.ts
@@ -2393,25 +2895,34 @@ var Store = class extends StoreClient {
2393
2895
  var import_onboarding = __toESM(require("@metamask/onboarding"));
2394
2896
  init_domain();
2395
2897
  init_qr();
2898
+ init_utils();
2396
2899
  var __instance;
2397
2900
  function preload() {
2398
2901
  return __async(this, null, function* () {
2399
- __instance != null ? __instance : __instance = yield import(
2400
- // Use a non-literal specifier to avoid Vite static analysis of deep imports
2401
- // and gracefully handle absence of the Stencil loader in this package build.
2402
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2403
- // @ts-ignore
2404
- "@metamask/multichain-ui".concat("/dist/loader/index.js")
2405
- // Prefer ESM loader in browsers
2406
- ).then((loader) => __async(null, null, function* () {
2407
- if (typeof (loader == null ? void 0 : loader.defineCustomElements) === "function") {
2408
- loader.defineCustomElements();
2409
- }
2410
- return Promise.resolve(loader);
2411
- })).catch((error) => __async(null, null, function* () {
2412
- console.error(`Gracefully Failed to load modal customElements:`, error);
2413
- return Promise.resolve(void 0);
2414
- }));
2902
+ if (false) {
2903
+ __instance != null ? __instance : __instance = yield null.then((loader) => __async(null, null, function* () {
2904
+ if (typeof (loader == null ? void 0 : loader.defineCustomElements) === "function") {
2905
+ loader.defineCustomElements();
2906
+ }
2907
+ return Promise.resolve(loader);
2908
+ })).catch((error) => __async(null, null, function* () {
2909
+ console.error(`Gracefully Failed to load modal customElements:`, error);
2910
+ return Promise.resolve(void 0);
2911
+ }));
2912
+ } else {
2913
+ const dynamicImport = (0, eval)("import");
2914
+ __instance != null ? __instance : __instance = yield dynamicImport(
2915
+ "@metamask/multichain-ui/dist/loader/index.js"
2916
+ ).then((loader) => __async(null, null, function* () {
2917
+ if (typeof (loader == null ? void 0 : loader.defineCustomElements) === "function") {
2918
+ loader.defineCustomElements();
2919
+ }
2920
+ return Promise.resolve(loader);
2921
+ })).catch((error) => __async(null, null, function* () {
2922
+ console.error(`Gracefully Failed to load modal customElements:`, error);
2923
+ return Promise.resolve(void 0);
2924
+ }));
2925
+ }
2415
2926
  });
2416
2927
  }
2417
2928
  var ModalFactory = class {
@@ -2503,7 +3014,7 @@ var ModalFactory = class {
2503
3014
  onStartDesktopOnboarding() {
2504
3015
  new import_onboarding.default().startOnboarding();
2505
3016
  }
2506
- renderInstallModal(preferDesktop, createConnectionRequest, successCallback) {
3017
+ renderInstallModal(showInstallModal, createConnectionRequest, successCallback) {
2507
3018
  return __async(this, null, function* () {
2508
3019
  var _a;
2509
3020
  (_a = this.modal) == null ? void 0 : _a.unmount();
@@ -2516,7 +3027,7 @@ var ModalFactory = class {
2516
3027
  expiresIn: (connectionRequest.sessionRequest.expiresAt - Date.now()) / 1e3,
2517
3028
  connectionRequest,
2518
3029
  parentElement,
2519
- preferDesktop,
3030
+ showInstallModal,
2520
3031
  link: qrCodeLink,
2521
3032
  sdkVersion: getVersion(),
2522
3033
  generateQRCode: (request) => __async(this, null, function* () {
@@ -2594,10 +3105,12 @@ var createMetamaskConnect = (options) => __async(null, null, function* () {
2594
3105
  getPlatformType,
2595
3106
  getTransportType,
2596
3107
  getVersion,
3108
+ getWalletActionAnalyticsProperties,
2597
3109
  hasExtension,
2598
3110
  infuraRpcUrls,
2599
3111
  isEnabled,
2600
3112
  isMetamaskExtensionInstalled,
3113
+ isRejectionError,
2601
3114
  isSecure
2602
3115
  });
2603
3116
  //# sourceMappingURL=connect-multichain.js.map