@metamask/connect-multichain 0.2.0 → 0.3.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 (50) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/dist/browser/es/connect-multichain.d.mts +26 -2
  3. package/dist/browser/es/connect-multichain.mjs +437 -246
  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 +26 -2
  7. package/dist/browser/iife/connect-multichain.js +21359 -14508
  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 +26 -2
  11. package/dist/browser/umd/connect-multichain.js +434 -243
  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 +26 -2
  15. package/dist/node/cjs/connect-multichain.js +437 -244
  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 +26 -2
  19. package/dist/node/es/connect-multichain.mjs +438 -247
  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 +26 -2
  23. package/dist/react-native/es/connect-multichain.mjs +437 -246
  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/multichain/types.d.ts +1 -1
  27. package/dist/src/domain/multichain/types.d.ts.map +1 -1
  28. package/dist/src/domain/utils/index.d.ts +1 -0
  29. package/dist/src/domain/utils/index.d.ts.map +1 -1
  30. package/dist/src/domain/utils/index.js +1 -0
  31. package/dist/src/domain/utils/index.js.map +1 -1
  32. package/dist/src/multichain/index.d.ts.map +1 -1
  33. package/dist/src/multichain/index.js +73 -30
  34. package/dist/src/multichain/index.js.map +1 -1
  35. package/dist/src/multichain/rpc/requestRouter.d.ts +1 -0
  36. package/dist/src/multichain/rpc/requestRouter.d.ts.map +1 -1
  37. package/dist/src/multichain/rpc/requestRouter.js +69 -13
  38. package/dist/src/multichain/rpc/requestRouter.js.map +1 -1
  39. package/dist/src/multichain/utils/analytics.d.ts +39 -0
  40. package/dist/src/multichain/utils/analytics.d.ts.map +1 -0
  41. package/dist/src/multichain/utils/analytics.js +83 -0
  42. package/dist/src/multichain/utils/analytics.js.map +1 -0
  43. package/dist/src/multichain/utils/index.d.ts +1 -1
  44. package/dist/src/multichain/utils/index.d.ts.map +1 -1
  45. package/dist/src/multichain/utils/index.js +11 -14
  46. package/dist/src/multichain/utils/index.js.map +1 -1
  47. package/dist/src/ui/index.js +1 -1
  48. package/dist/src/ui/index.js.map +1 -1
  49. package/dist/types/connect-multichain.d.ts +26 -2
  50. package/package.json +2 -2
@@ -583,13 +583,264 @@ var init_ui = __esm({
583
583
  }
584
584
  });
585
585
 
586
+ // src/multichain/utils/index.ts
587
+ import { deflate } from "pako";
588
+ import {
589
+ parseCaipAccountId,
590
+ parseCaipChainId
591
+ } from "@metamask/utils";
592
+ function base64Encode(str) {
593
+ if (typeof btoa !== "undefined") {
594
+ return btoa(str);
595
+ } else if (typeof Buffer !== "undefined") {
596
+ return Buffer.from(str).toString("base64");
597
+ }
598
+ throw new Error("No base64 encoding method available");
599
+ }
600
+ function compressString(str) {
601
+ const compressed = deflate(str);
602
+ const binaryString = String.fromCharCode.apply(null, Array.from(compressed));
603
+ return base64Encode(binaryString);
604
+ }
605
+ function getDappId(dapp) {
606
+ var _a;
607
+ return (_a = dapp.url) != null ? _a : dapp.name;
608
+ }
609
+ function openDeeplink(options, deeplink, universalLink) {
610
+ const { mobile } = options;
611
+ const useDeeplink = mobile && mobile.useDeeplink !== void 0 ? mobile.useDeeplink : true;
612
+ if (useDeeplink) {
613
+ if (typeof window !== "undefined") {
614
+ window.location.href = deeplink;
615
+ }
616
+ } else if (typeof document !== "undefined") {
617
+ const link = document.createElement("a");
618
+ link.href = universalLink;
619
+ link.target = "_self";
620
+ link.rel = "noreferrer noopener";
621
+ link.click();
622
+ }
623
+ }
624
+ function getOptionalScopes(scopes) {
625
+ return scopes.reduce(
626
+ (prev, scope) => __spreadProps(__spreadValues({}, prev), {
627
+ [scope]: {
628
+ methods: [],
629
+ notifications: [],
630
+ accounts: []
631
+ }
632
+ }),
633
+ {}
634
+ );
635
+ }
636
+ function setupDappMetadata(options) {
637
+ var _a, _b;
638
+ const platform = getPlatformType();
639
+ const isBrowser = platform === "web-desktop" /* DesktopWeb */ || platform === "web-mobile" /* MobileWeb */ || platform === "in-app-browser" /* MetaMaskMobileWebview */;
640
+ if (!((_a = options.dapp) == null ? void 0 : _a.name)) {
641
+ throw new Error("You must provide dapp name");
642
+ }
643
+ if (isBrowser) {
644
+ options.dapp = __spreadProps(__spreadValues({}, options.dapp), {
645
+ url: `${window.location.protocol}//${window.location.host}`
646
+ });
647
+ }
648
+ if (!((_b = options.dapp) == null ? void 0 : _b.url)) {
649
+ throw new Error("You must provide dapp url");
650
+ }
651
+ const BASE_64_ICON_MAX_LENGTH = 163400;
652
+ const urlPattern = /^(http|https):\/\/[^\s]*$/;
653
+ if (options.dapp) {
654
+ if ("iconUrl" in options.dapp) {
655
+ if (options.dapp.iconUrl && !urlPattern.test(options.dapp.iconUrl)) {
656
+ console.warn(
657
+ "Invalid dappMetadata.iconUrl: URL must start with http:// or https://"
658
+ );
659
+ options.dapp.iconUrl = void 0;
660
+ }
661
+ }
662
+ if ("base64Icon" in options.dapp) {
663
+ if (options.dapp.base64Icon && options.dapp.base64Icon.length > BASE_64_ICON_MAX_LENGTH) {
664
+ console.warn(
665
+ "Invalid dappMetadata.base64Icon: Base64-encoded icon string length must be less than 163400 characters"
666
+ );
667
+ options.dapp.base64Icon = void 0;
668
+ }
669
+ }
670
+ if (options.dapp.url && !urlPattern.test(options.dapp.url)) {
671
+ console.warn(
672
+ "Invalid dappMetadata.url: URL must start with http:// or https://"
673
+ );
674
+ }
675
+ const favicon = extractFavicon();
676
+ if (favicon && !("iconUrl" in options.dapp) && !("base64Icon" in options.dapp)) {
677
+ const faviconUrl = `${window.location.protocol}//${window.location.host}${favicon}`;
678
+ options.dapp.iconUrl = faviconUrl;
679
+ }
680
+ }
681
+ return options;
682
+ }
683
+ function isSameScopesAndAccounts(currentScopes, proposedScopes, walletSession, proposedCaipAccountIds) {
684
+ const isSameScopes = currentScopes.every((scope) => proposedScopes.includes(scope)) && proposedScopes.every((scope) => currentScopes.includes(scope));
685
+ if (!isSameScopes) {
686
+ return false;
687
+ }
688
+ const existingAccountIds = Object.values(
689
+ walletSession.sessionScopes
690
+ ).filter(({ accounts }) => Boolean(accounts)).flatMap(({ accounts }) => accounts != null ? accounts : []);
691
+ const allProposedAccountsIncluded = proposedCaipAccountIds.every(
692
+ (proposedAccountId) => existingAccountIds.includes(proposedAccountId)
693
+ );
694
+ return allProposedAccountsIncluded;
695
+ }
696
+ function getValidAccounts(caipAccountIds) {
697
+ return caipAccountIds.reduce(
698
+ (caipAccounts, caipAccountId) => {
699
+ try {
700
+ return [...caipAccounts, parseCaipAccountId(caipAccountId)];
701
+ } catch (err) {
702
+ const stringifiedAccountId = JSON.stringify(caipAccountId);
703
+ console.error(`Invalid CAIP account ID: ${stringifiedAccountId}`, err);
704
+ return caipAccounts;
705
+ }
706
+ },
707
+ []
708
+ );
709
+ }
710
+ function addValidAccounts(optionalScopes, validAccounts) {
711
+ var _a;
712
+ if (!optionalScopes || !(validAccounts == null ? void 0 : validAccounts.length)) {
713
+ return optionalScopes;
714
+ }
715
+ const result = Object.fromEntries(
716
+ Object.entries(optionalScopes).map(([scope, scopeData]) => {
717
+ var _a2, _b, _c;
718
+ return [
719
+ scope,
720
+ {
721
+ methods: [...(_a2 = scopeData == null ? void 0 : scopeData.methods) != null ? _a2 : []],
722
+ notifications: [...(_b = scopeData == null ? void 0 : scopeData.notifications) != null ? _b : []],
723
+ accounts: [...(_c = scopeData == null ? void 0 : scopeData.accounts) != null ? _c : []]
724
+ }
725
+ ];
726
+ })
727
+ );
728
+ const accountsByChain = /* @__PURE__ */ new Map();
729
+ for (const account of validAccounts) {
730
+ const chainKey = `${account.chain.namespace}:${account.chain.reference}`;
731
+ const accountId = `${account.chainId}:${account.address}`;
732
+ if (!accountsByChain.has(chainKey)) {
733
+ accountsByChain.set(chainKey, []);
734
+ }
735
+ (_a = accountsByChain.get(chainKey)) == null ? void 0 : _a.push(accountId);
736
+ }
737
+ for (const [scopeKey, scopeData] of Object.entries(result)) {
738
+ if (!(scopeData == null ? void 0 : scopeData.accounts)) {
739
+ continue;
740
+ }
741
+ try {
742
+ const scope = scopeKey;
743
+ const scopeDetails = parseCaipChainId(scope);
744
+ const chainKey = `${scopeDetails.namespace}:${scopeDetails.reference}`;
745
+ const matchingAccounts = accountsByChain.get(chainKey);
746
+ if (matchingAccounts) {
747
+ const existingAccounts = new Set(scopeData.accounts);
748
+ const newAccounts = matchingAccounts.filter(
749
+ (account) => !existingAccounts.has(account)
750
+ );
751
+ scopeData.accounts.push(...newAccounts);
752
+ }
753
+ } catch (error) {
754
+ console.error(`Invalid scope format: ${scopeKey}`, error);
755
+ }
756
+ }
757
+ return result;
758
+ }
759
+ var extractFavicon;
760
+ var init_utils = __esm({
761
+ "src/multichain/utils/index.ts"() {
762
+ "use strict";
763
+ init_domain();
764
+ extractFavicon = () => {
765
+ var _a;
766
+ if (typeof document === "undefined") {
767
+ return void 0;
768
+ }
769
+ let favicon;
770
+ const nodeList = document.getElementsByTagName("link");
771
+ for (let i = 0; i < nodeList.length; i++) {
772
+ if (nodeList[i].getAttribute("rel") === "icon" || nodeList[i].getAttribute("rel") === "shortcut icon") {
773
+ favicon = (_a = nodeList[i].getAttribute("href")) != null ? _a : void 0;
774
+ }
775
+ }
776
+ return favicon;
777
+ };
778
+ }
779
+ });
780
+
781
+ // src/multichain/utils/analytics.ts
782
+ function isRejectionError(error) {
783
+ var _a, _b;
784
+ if (typeof error !== "object" || error === null) {
785
+ return false;
786
+ }
787
+ const errorObj = error;
788
+ const errorCode = errorObj.code;
789
+ const errorMessage = (_b = (_a = errorObj.message) == null ? void 0 : _a.toLowerCase()) != null ? _b : "";
790
+ return errorCode === 4001 || // User rejected request (common EIP-1193 code)
791
+ errorCode === 4100 || // Unauthorized (common rejection code)
792
+ errorMessage.includes("reject") || errorMessage.includes("denied") || errorMessage.includes("cancel") || errorMessage.includes("user");
793
+ }
794
+ function getBaseAnalyticsProperties(options, storage) {
795
+ return __async(this, null, function* () {
796
+ var _a, _b;
797
+ const version = getVersion();
798
+ const dappId = getDappId(options.dapp);
799
+ const platform = getPlatformType();
800
+ const anonId = yield storage.getAnonId();
801
+ const integrationType = (_b = (_a = options.analytics) == null ? void 0 : _a.integrationType) != null ? _b : "unknown" /* UNKNOWN */;
802
+ return {
803
+ mmconnect_version: version,
804
+ dapp_id: dappId,
805
+ platform,
806
+ integration_type: integrationType,
807
+ anon_id: anonId
808
+ };
809
+ });
810
+ }
811
+ function getWalletActionAnalyticsProperties(options, storage, invokeOptions) {
812
+ return __async(this, null, function* () {
813
+ var _a, _b;
814
+ const version = getVersion();
815
+ const dappId = getDappId(options.dapp);
816
+ const anonId = yield storage.getAnonId();
817
+ const integrationType = (_b = (_a = options.analytics) == null ? void 0 : _a.integrationType) != null ? _b : "unknown";
818
+ return {
819
+ mmconnect_version: version,
820
+ dapp_id: dappId,
821
+ method: invokeOptions.request.method,
822
+ integration_type: integrationType,
823
+ caip_chain_id: invokeOptions.scope,
824
+ anon_id: anonId
825
+ };
826
+ });
827
+ }
828
+ var init_analytics = __esm({
829
+ "src/multichain/utils/analytics.ts"() {
830
+ "use strict";
831
+ init_utils();
832
+ init_domain();
833
+ }
834
+ });
835
+
586
836
  // src/domain/utils/index.ts
587
837
  function getVersion() {
588
838
  return "0.0.0";
589
839
  }
590
- var init_utils = __esm({
840
+ var init_utils2 = __esm({
591
841
  "src/domain/utils/index.ts"() {
592
842
  "use strict";
843
+ init_analytics();
593
844
  }
594
845
  });
595
846
 
@@ -604,7 +855,7 @@ var init_domain = __esm({
604
855
  init_platform();
605
856
  init_store();
606
857
  init_ui();
607
- init_utils();
858
+ init_utils2();
608
859
  }
609
860
  });
610
861
 
@@ -651,7 +902,7 @@ function shouldLogCountdown(remainingSeconds) {
651
902
  return remainingSeconds % 60 === 0;
652
903
  }
653
904
  }
654
- var init_utils2 = __esm({
905
+ var init_utils3 = __esm({
655
906
  "src/ui/modals/base/utils.ts"() {
656
907
  "use strict";
657
908
  }
@@ -663,7 +914,7 @@ var init_AbstractInstallModal = __esm({
663
914
  "src/ui/modals/base/AbstractInstallModal.ts"() {
664
915
  "use strict";
665
916
  init_domain();
666
- init_utils2();
917
+ init_utils3();
667
918
  logger3 = createLogger("metamask-sdk:ui");
668
919
  AbstractInstallModal = class extends Modal {
669
920
  constructor() {
@@ -757,7 +1008,7 @@ var init_install = __esm({
757
1008
  init_domain();
758
1009
  init_qr();
759
1010
  init_AbstractInstallModal();
760
- init_utils2();
1011
+ init_utils3();
761
1012
  logger4 = createLogger("metamask-sdk:ui");
762
1013
  InstallModal = class extends AbstractInstallModal {
763
1014
  displayQRWithCountdown(qrCodeLink, expiresInMs) {
@@ -890,7 +1141,7 @@ var init_node2 = __esm({
890
1141
  });
891
1142
 
892
1143
  // src/multichain/index.ts
893
- import { analytics } from "@metamask/analytics";
1144
+ import { analytics as analytics2 } from "@metamask/analytics";
894
1145
  import {
895
1146
  ErrorCode,
896
1147
  ProtocolError,
@@ -909,6 +1160,7 @@ var METAMASK_DEEPLINK_BASE = "metamask://connect";
909
1160
 
910
1161
  // src/multichain/index.ts
911
1162
  init_domain();
1163
+ init_analytics();
912
1164
  init_logger();
913
1165
  init_multichain();
914
1166
  init_platform();
@@ -1009,204 +1261,17 @@ var RpcClient = class {
1009
1261
  };
1010
1262
 
1011
1263
  // src/multichain/rpc/requestRouter.ts
1264
+ import { analytics } from "@metamask/analytics";
1012
1265
  init_domain();
1013
-
1014
- // src/multichain/utils/index.ts
1015
- init_domain();
1016
- import { deflate } from "pako";
1017
- import {
1018
- parseCaipAccountId,
1019
- parseCaipChainId
1020
- } from "@metamask/utils";
1021
- function base64Encode(str) {
1022
- if (typeof btoa !== "undefined") {
1023
- return btoa(str);
1024
- } else if (typeof Buffer !== "undefined") {
1025
- return Buffer.from(str).toString("base64");
1026
- }
1027
- throw new Error("No base64 encoding method available");
1028
- }
1029
- function compressString(str) {
1030
- const compressed = deflate(str);
1031
- const binaryString = String.fromCharCode.apply(null, Array.from(compressed));
1032
- return base64Encode(binaryString);
1033
- }
1034
- function getDappId(dapp) {
1035
- var _a, _b;
1036
- if (typeof window === "undefined" || typeof window.location === "undefined") {
1037
- return (_b = (_a = dapp == null ? void 0 : dapp.name) != null ? _a : dapp == null ? void 0 : dapp.url) != null ? _b : "N/A";
1038
- }
1039
- return window.location.hostname;
1040
- }
1041
- function openDeeplink(options, deeplink, universalLink) {
1042
- const { mobile } = options;
1043
- const useDeeplink = mobile && mobile.useDeeplink !== void 0 ? mobile.useDeeplink : true;
1044
- if (useDeeplink) {
1045
- if (typeof window !== "undefined") {
1046
- window.location.href = deeplink;
1047
- }
1048
- } else if (typeof document !== "undefined") {
1049
- const link = document.createElement("a");
1050
- link.href = universalLink;
1051
- link.target = "_self";
1052
- link.rel = "noreferrer noopener";
1053
- link.click();
1054
- }
1055
- }
1056
- function getOptionalScopes(scopes) {
1057
- return scopes.reduce(
1058
- (prev, scope) => __spreadProps(__spreadValues({}, prev), {
1059
- [scope]: {
1060
- methods: [],
1061
- notifications: [],
1062
- accounts: []
1063
- }
1064
- }),
1065
- {}
1066
- );
1067
- }
1068
- var extractFavicon = () => {
1069
- var _a;
1070
- if (typeof document === "undefined") {
1071
- return void 0;
1072
- }
1073
- let favicon;
1074
- const nodeList = document.getElementsByTagName("link");
1075
- for (let i = 0; i < nodeList.length; i++) {
1076
- if (nodeList[i].getAttribute("rel") === "icon" || nodeList[i].getAttribute("rel") === "shortcut icon") {
1077
- favicon = (_a = nodeList[i].getAttribute("href")) != null ? _a : void 0;
1078
- }
1079
- }
1080
- return favicon;
1081
- };
1082
- function setupDappMetadata(options) {
1083
- var _a;
1084
- const platform = getPlatformType();
1085
- const isBrowser = platform === "web-desktop" /* DesktopWeb */ || platform === "web-mobile" /* MobileWeb */ || platform === "in-app-browser" /* MetaMaskMobileWebview */;
1086
- if (!((_a = options.dapp) == null ? void 0 : _a.url)) {
1087
- if (isBrowser) {
1088
- options.dapp = __spreadProps(__spreadValues({}, options.dapp), {
1089
- url: `${window.location.protocol}//${window.location.host}`
1090
- });
1091
- } else {
1092
- throw new Error("You must provide dapp url");
1093
- }
1094
- }
1095
- const BASE_64_ICON_MAX_LENGTH = 163400;
1096
- const urlPattern = /^(http|https):\/\/[^\s]*$/;
1097
- if (options.dapp) {
1098
- if ("iconUrl" in options.dapp) {
1099
- if (options.dapp.iconUrl && !urlPattern.test(options.dapp.iconUrl)) {
1100
- console.warn(
1101
- "Invalid dappMetadata.iconUrl: URL must start with http:// or https://"
1102
- );
1103
- options.dapp.iconUrl = void 0;
1104
- }
1105
- }
1106
- if ("base64Icon" in options.dapp) {
1107
- if (options.dapp.base64Icon && options.dapp.base64Icon.length > BASE_64_ICON_MAX_LENGTH) {
1108
- console.warn(
1109
- "Invalid dappMetadata.base64Icon: Base64-encoded icon string length must be less than 163400 characters"
1110
- );
1111
- options.dapp.base64Icon = void 0;
1112
- }
1113
- }
1114
- if (options.dapp.url && !urlPattern.test(options.dapp.url)) {
1115
- console.warn(
1116
- "Invalid dappMetadata.url: URL must start with http:// or https://"
1117
- );
1118
- }
1119
- const favicon = extractFavicon();
1120
- if (favicon && !("iconUrl" in options.dapp) && !("base64Icon" in options.dapp)) {
1121
- const faviconUrl = `${window.location.protocol}//${window.location.host}${favicon}`;
1122
- options.dapp.iconUrl = faviconUrl;
1123
- }
1124
- }
1125
- return options;
1126
- }
1127
- function isSameScopesAndAccounts(currentScopes, proposedScopes, walletSession, proposedCaipAccountIds) {
1128
- const isSameScopes = currentScopes.every((scope) => proposedScopes.includes(scope)) && proposedScopes.every((scope) => currentScopes.includes(scope));
1129
- if (!isSameScopes) {
1130
- return false;
1131
- }
1132
- const existingAccountIds = Object.values(
1133
- walletSession.sessionScopes
1134
- ).filter(({ accounts }) => Boolean(accounts)).flatMap(({ accounts }) => accounts != null ? accounts : []);
1135
- const allProposedAccountsIncluded = proposedCaipAccountIds.every(
1136
- (proposedAccountId) => existingAccountIds.includes(proposedAccountId)
1137
- );
1138
- return allProposedAccountsIncluded;
1139
- }
1140
- function getValidAccounts(caipAccountIds) {
1141
- return caipAccountIds.reduce(
1142
- (caipAccounts, caipAccountId) => {
1143
- try {
1144
- return [...caipAccounts, parseCaipAccountId(caipAccountId)];
1145
- } catch (err) {
1146
- const stringifiedAccountId = JSON.stringify(caipAccountId);
1147
- console.error(`Invalid CAIP account ID: ${stringifiedAccountId}`, err);
1148
- return caipAccounts;
1149
- }
1150
- },
1151
- []
1152
- );
1153
- }
1154
- function addValidAccounts(optionalScopes, validAccounts) {
1155
- var _a;
1156
- if (!optionalScopes || !(validAccounts == null ? void 0 : validAccounts.length)) {
1157
- return optionalScopes;
1158
- }
1159
- const result = Object.fromEntries(
1160
- Object.entries(optionalScopes).map(([scope, scopeData]) => {
1161
- var _a2, _b, _c;
1162
- return [
1163
- scope,
1164
- {
1165
- methods: [...(_a2 = scopeData == null ? void 0 : scopeData.methods) != null ? _a2 : []],
1166
- notifications: [...(_b = scopeData == null ? void 0 : scopeData.notifications) != null ? _b : []],
1167
- accounts: [...(_c = scopeData == null ? void 0 : scopeData.accounts) != null ? _c : []]
1168
- }
1169
- ];
1170
- })
1171
- );
1172
- const accountsByChain = /* @__PURE__ */ new Map();
1173
- for (const account of validAccounts) {
1174
- const chainKey = `${account.chain.namespace}:${account.chain.reference}`;
1175
- const accountId = `${account.chainId}:${account.address}`;
1176
- if (!accountsByChain.has(chainKey)) {
1177
- accountsByChain.set(chainKey, []);
1178
- }
1179
- (_a = accountsByChain.get(chainKey)) == null ? void 0 : _a.push(accountId);
1180
- }
1181
- for (const [scopeKey, scopeData] of Object.entries(result)) {
1182
- if (!(scopeData == null ? void 0 : scopeData.accounts)) {
1183
- continue;
1184
- }
1185
- try {
1186
- const scope = scopeKey;
1187
- const scopeDetails = parseCaipChainId(scope);
1188
- const chainKey = `${scopeDetails.namespace}:${scopeDetails.reference}`;
1189
- const matchingAccounts = accountsByChain.get(chainKey);
1190
- if (matchingAccounts) {
1191
- const existingAccounts = new Set(scopeData.accounts);
1192
- const newAccounts = matchingAccounts.filter(
1193
- (account) => !existingAccounts.has(account)
1194
- );
1195
- scopeData.accounts.push(...newAccounts);
1196
- }
1197
- } catch (error) {
1198
- console.error(`Invalid scope format: ${scopeKey}`, error);
1199
- }
1200
- }
1201
- return result;
1202
- }
1203
-
1204
- // src/multichain/rpc/requestRouter.ts
1266
+ init_utils();
1267
+ init_analytics();
1268
+ var _RequestRouter_instances, withAnalyticsTracking_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, trackWalletActionRejected_fn;
1205
1269
  var RequestRouter = class {
1206
1270
  constructor(transport, rpcClient, config) {
1207
1271
  this.transport = transport;
1208
1272
  this.rpcClient = rpcClient;
1209
1273
  this.config = config;
1274
+ __privateAdd(this, _RequestRouter_instances);
1210
1275
  }
1211
1276
  /**
1212
1277
  * The main entry point for invoking an RPC method.
@@ -1230,7 +1295,7 @@ var RequestRouter = class {
1230
1295
  */
1231
1296
  handleWithWallet(options) {
1232
1297
  return __async(this, null, function* () {
1233
- try {
1298
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1234
1299
  const request = this.transport.request({
1235
1300
  method: "wallet_invokeMethod",
1236
1301
  params: options
@@ -1253,9 +1318,7 @@ var RequestRouter = class {
1253
1318
  throw new RPCInvokeMethodErr(`RPC Request failed with code ${response.error.code}: ${response.error.message}`);
1254
1319
  }
1255
1320
  return response.result;
1256
- } catch (error) {
1257
- throw new RPCInvokeMethodErr(error.message);
1258
- }
1321
+ }));
1259
1322
  });
1260
1323
  }
1261
1324
  /**
@@ -1263,14 +1326,16 @@ var RequestRouter = class {
1263
1326
  */
1264
1327
  handleWithRpcNode(options) {
1265
1328
  return __async(this, null, function* () {
1266
- try {
1267
- return yield this.rpcClient.request(options);
1268
- } catch (error) {
1269
- if (error instanceof MissingRpcEndpointErr) {
1270
- return this.handleWithWallet(options);
1329
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1330
+ try {
1331
+ return yield this.rpcClient.request(options);
1332
+ } catch (error) {
1333
+ if (error instanceof MissingRpcEndpointErr) {
1334
+ return this.handleWithWallet(options);
1335
+ }
1336
+ throw error;
1271
1337
  }
1272
- throw error;
1273
- }
1338
+ }));
1274
1339
  });
1275
1340
  }
1276
1341
  /**
@@ -1283,8 +1348,59 @@ var RequestRouter = class {
1283
1348
  });
1284
1349
  }
1285
1350
  };
1351
+ _RequestRouter_instances = new WeakSet();
1352
+ withAnalyticsTracking_fn = function(options, execute) {
1353
+ return __async(this, null, function* () {
1354
+ var _a, _b, _c;
1355
+ if ((_a = this.config.analytics) == null ? void 0 : _a.enabled) {
1356
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRequested_fn).call(this, options);
1357
+ }
1358
+ try {
1359
+ const result = yield execute();
1360
+ if ((_b = this.config.analytics) == null ? void 0 : _b.enabled) {
1361
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionSucceeded_fn).call(this, options);
1362
+ }
1363
+ return result;
1364
+ } catch (error) {
1365
+ if ((_c = this.config.analytics) == null ? void 0 : _c.enabled) {
1366
+ const isRejection = isRejectionError(error);
1367
+ if (isRejection) {
1368
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRejected_fn).call(this, options);
1369
+ } else {
1370
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options);
1371
+ }
1372
+ }
1373
+ throw new RPCInvokeMethodErr(error.message);
1374
+ }
1375
+ });
1376
+ };
1377
+ trackWalletActionRequested_fn = function(options) {
1378
+ return __async(this, null, function* () {
1379
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1380
+ analytics.track("mmconnect_wallet_action_requested", props);
1381
+ });
1382
+ };
1383
+ trackWalletActionSucceeded_fn = function(options) {
1384
+ return __async(this, null, function* () {
1385
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1386
+ analytics.track("mmconnect_wallet_action_succeeded", props);
1387
+ });
1388
+ };
1389
+ trackWalletActionFailed_fn = function(options) {
1390
+ return __async(this, null, function* () {
1391
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1392
+ analytics.track("mmconnect_wallet_action_failed", props);
1393
+ });
1394
+ };
1395
+ trackWalletActionRejected_fn = function(options) {
1396
+ return __async(this, null, function* () {
1397
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1398
+ analytics.track("mmconnect_wallet_action_rejected", props);
1399
+ });
1400
+ };
1286
1401
 
1287
1402
  // src/multichain/transports/default/index.ts
1403
+ init_utils();
1288
1404
  import {
1289
1405
  getDefaultTransport
1290
1406
  } from "@metamask/multichain-api-client";
@@ -1514,6 +1630,7 @@ setupMessageListener_fn = function() {
1514
1630
 
1515
1631
  // src/multichain/transports/mwp/index.ts
1516
1632
  init_domain();
1633
+ init_utils();
1517
1634
  import { SessionStore } from "@metamask/mobile-wallet-protocol-core";
1518
1635
  import {
1519
1636
  TransportTimeoutError
@@ -1991,20 +2108,22 @@ var KeyManager = class {
1991
2108
  var keymanager = new KeyManager();
1992
2109
 
1993
2110
  // src/multichain/index.ts
2111
+ init_utils();
1994
2112
  var logger2 = createLogger("metamask-sdk:core");
1995
2113
  var MultichainSDK = class _MultichainSDK extends MultichainCore {
1996
2114
  constructor(options) {
1997
- var _a, _b, _c, _d, _e, _f;
2115
+ var _a, _b, _c, _d, _e, _f, _g;
1998
2116
  const withDappMetadata = setupDappMetadata(options);
2117
+ const integrationType = ((_a = options.analytics) == null ? void 0 : _a.enabled) ? options.analytics.integrationType : "direct";
1999
2118
  const allOptions = __spreadProps(__spreadValues({}, withDappMetadata), {
2000
2119
  ui: __spreadProps(__spreadValues({}, withDappMetadata.ui), {
2001
- preferExtension: (_a = withDappMetadata.ui.preferExtension) != null ? _a : true,
2002
- showInstallModal: (_b = withDappMetadata.ui.showInstallModal) != null ? _b : false,
2003
- headless: (_c = withDappMetadata.ui.headless) != null ? _c : false
2120
+ preferExtension: (_b = withDappMetadata.ui.preferExtension) != null ? _b : true,
2121
+ showInstallModal: (_c = withDappMetadata.ui.showInstallModal) != null ? _c : false,
2122
+ headless: (_d = withDappMetadata.ui.headless) != null ? _d : false
2004
2123
  }),
2005
- analytics: __spreadProps(__spreadValues({}, (_d = options.analytics) != null ? _d : {}), {
2006
- enabled: (_f = (_e = options.analytics) == null ? void 0 : _e.enabled) != null ? _f : true,
2007
- integrationType: "unknown"
2124
+ analytics: __spreadProps(__spreadValues({}, (_e = options.analytics) != null ? _e : {}), {
2125
+ enabled: (_g = (_f = options.analytics) == null ? void 0 : _f.enabled) != null ? _g : true,
2126
+ integrationType
2008
2127
  })
2009
2128
  });
2010
2129
  super(allOptions);
@@ -2088,12 +2207,12 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2088
2207
  const { integrationType } = (_b = this.options.analytics) != null ? _b : {
2089
2208
  integrationType: ""
2090
2209
  };
2091
- analytics.setGlobalProperty("sdk_version", version);
2092
- analytics.setGlobalProperty("dapp_id", dappId);
2093
- analytics.setGlobalProperty("anon_id", anonId);
2094
- analytics.setGlobalProperty("platform", platform);
2095
- analytics.setGlobalProperty("integration_type", integrationType);
2096
- analytics.enable();
2210
+ analytics2.setGlobalProperty("mmconnect_version", version);
2211
+ analytics2.setGlobalProperty("dapp_id", dappId);
2212
+ analytics2.setGlobalProperty("anon_id", anonId);
2213
+ analytics2.setGlobalProperty("platform", platform);
2214
+ analytics2.setGlobalProperty("integration_type", integrationType);
2215
+ analytics2.enable();
2097
2216
  });
2098
2217
  }
2099
2218
  onTransportNotification(payload) {
@@ -2155,14 +2274,24 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2155
2274
  }
2156
2275
  init() {
2157
2276
  return __async(this, null, function* () {
2158
- var _a;
2277
+ var _a, _b;
2159
2278
  try {
2160
2279
  if (typeof window !== "undefined" && ((_a = window.mmsdk) == null ? void 0 : _a.isInitialized)) {
2161
2280
  logger2("MetaMaskSDK: init already initialized");
2162
2281
  } else {
2163
2282
  yield this.setupAnalytics();
2164
2283
  yield this.setupTransport();
2165
- analytics.track("sdk_initialized", {});
2284
+ if ((_b = this.options.analytics) == null ? void 0 : _b.enabled) {
2285
+ try {
2286
+ const baseProps = yield getBaseAnalyticsProperties(
2287
+ this.options,
2288
+ this.storage
2289
+ );
2290
+ analytics2.track("mmconnect_initialized", baseProps);
2291
+ } catch (error) {
2292
+ logger2("Error tracking initialized event", error);
2293
+ }
2294
+ }
2166
2295
  if (typeof window !== "undefined") {
2167
2296
  window.mmsdk = this;
2168
2297
  }
@@ -2341,17 +2470,6 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2341
2470
  }
2342
2471
  }
2343
2472
  );
2344
- } else {
2345
- timeout = setTimeout(() => {
2346
- var _a;
2347
- const deeplink = this.options.ui.factory.createDeeplink();
2348
- const universalLink = this.options.ui.factory.createUniversalLink();
2349
- if ((_a = this.options.mobile) == null ? void 0 : _a.preferredOpenLink) {
2350
- this.options.mobile.preferredOpenLink(deeplink, "_self");
2351
- } else {
2352
- openDeeplink(this.options, deeplink, universalLink);
2353
- }
2354
- }, 250);
2355
2473
  }
2356
2474
  this.transport.connect({ scopes, caipAccountIds }).then(resolve).catch((error) => {
2357
2475
  this.storage.removeTransport();
@@ -2364,27 +2482,87 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2364
2482
  }));
2365
2483
  });
2366
2484
  }
2367
- handleConnection(promise) {
2485
+ handleConnection(promise, scopes, transportType) {
2368
2486
  return __async(this, null, function* () {
2369
2487
  this.state = "connecting";
2370
- return promise.then(() => {
2488
+ return promise.then(() => __async(this, null, function* () {
2489
+ var _a;
2371
2490
  this.state = "connected";
2372
- }).catch((error) => {
2491
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2492
+ try {
2493
+ const baseProps = yield getBaseAnalyticsProperties(
2494
+ this.options,
2495
+ this.storage
2496
+ );
2497
+ analytics2.track("mmconnect_connection_established", __spreadProps(__spreadValues({}, baseProps), {
2498
+ transport_type: transportType,
2499
+ user_permissioned_chains: scopes
2500
+ }));
2501
+ } catch (error) {
2502
+ logger2("Error tracking connection_established event", error);
2503
+ }
2504
+ }
2505
+ })).catch((error) => __async(this, null, function* () {
2506
+ var _a;
2373
2507
  this.state = "disconnected";
2508
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2509
+ try {
2510
+ const baseProps = yield getBaseAnalyticsProperties(
2511
+ this.options,
2512
+ this.storage
2513
+ );
2514
+ const isRejection = isRejectionError(error);
2515
+ if (isRejection) {
2516
+ analytics2.track("mmconnect_connection_rejected", __spreadProps(__spreadValues({}, baseProps), {
2517
+ transport_type: transportType
2518
+ }));
2519
+ } else {
2520
+ analytics2.track("mmconnect_connection_failed", __spreadProps(__spreadValues({}, baseProps), {
2521
+ transport_type: transportType
2522
+ }));
2523
+ }
2524
+ } catch (e) {
2525
+ logger2("Error tracking connection failed/rejected event", error);
2526
+ }
2527
+ }
2374
2528
  return Promise.reject(error);
2375
- });
2529
+ }));
2376
2530
  });
2377
2531
  }
2378
2532
  connect(scopes, caipAccountIds, forceRequest) {
2379
2533
  return __async(this, null, function* () {
2380
- var _a;
2534
+ var _a, _b;
2381
2535
  const { ui } = this.options;
2382
2536
  const platformType = getPlatformType();
2383
2537
  const isWeb = platformType === "in-app-browser" /* MetaMaskMobileWebview */ || platformType === "web-desktop" /* DesktopWeb */;
2384
2538
  const { preferExtension = true, showInstallModal = false } = ui;
2385
2539
  const secure = isSecure();
2386
2540
  const hasExtensionInstalled = yield hasExtension();
2387
- if (((_a = this.__transport) == null ? void 0 : _a.isConnected()) && !secure) {
2541
+ let transportType;
2542
+ if (platformType === "in-app-browser" /* MetaMaskMobileWebview */ || isWeb && hasExtensionInstalled && preferExtension) {
2543
+ transportType = "browser" /* Browser */;
2544
+ } else {
2545
+ transportType = "mwp" /* MWP */;
2546
+ }
2547
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2548
+ try {
2549
+ const baseProps = yield getBaseAnalyticsProperties(
2550
+ this.options,
2551
+ this.storage
2552
+ );
2553
+ const dappConfiguredChains = Object.keys(
2554
+ this.options.api.supportedNetworks
2555
+ );
2556
+ analytics2.track("mmconnect_connection_initiated", __spreadProps(__spreadValues({}, baseProps), {
2557
+ transport_type: transportType,
2558
+ dapp_configured_chains: dappConfiguredChains,
2559
+ dapp_requested_chains: scopes
2560
+ }));
2561
+ } catch (error) {
2562
+ logger2("Error tracking connection_initiated event", error);
2563
+ }
2564
+ }
2565
+ if (((_b = this.__transport) == null ? void 0 : _b.isConnected()) && !secure) {
2388
2566
  return this.handleConnection(
2389
2567
  this.__transport.connect({ scopes, caipAccountIds, forceRequest }).then(() => {
2390
2568
  if (this.__transport instanceof MWPTransport) {
@@ -2392,30 +2570,40 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2392
2570
  } else {
2393
2571
  return this.storage.setTransport("browser" /* Browser */);
2394
2572
  }
2395
- })
2573
+ }),
2574
+ scopes,
2575
+ transportType
2396
2576
  );
2397
2577
  }
2398
2578
  if (platformType === "in-app-browser" /* MetaMaskMobileWebview */) {
2399
2579
  const defaultTransport = yield this.setupDefaultTransport();
2400
2580
  return this.handleConnection(
2401
- defaultTransport.connect({ scopes, caipAccountIds, forceRequest })
2581
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2582
+ scopes,
2583
+ transportType
2402
2584
  );
2403
2585
  }
2404
2586
  if (isWeb && hasExtensionInstalled && preferExtension) {
2405
2587
  const defaultTransport = yield this.setupDefaultTransport();
2406
2588
  return this.handleConnection(
2407
- defaultTransport.connect({ scopes, caipAccountIds, forceRequest })
2589
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2590
+ scopes,
2591
+ transportType
2408
2592
  );
2409
2593
  }
2410
2594
  yield this.setupMWP();
2411
2595
  const shouldShowInstallModal = hasExtensionInstalled ? showInstallModal : !preferExtension || showInstallModal;
2412
2596
  if (secure && !shouldShowInstallModal) {
2413
2597
  return this.handleConnection(
2414
- this.deeplinkConnect(scopes, caipAccountIds)
2598
+ this.deeplinkConnect(scopes, caipAccountIds),
2599
+ scopes,
2600
+ transportType
2415
2601
  );
2416
2602
  }
2417
2603
  return this.handleConnection(
2418
- this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds)
2604
+ this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds),
2605
+ scopes,
2606
+ transportType
2419
2607
  );
2420
2608
  });
2421
2609
  }
@@ -2655,6 +2843,7 @@ var Store = class extends StoreClient {
2655
2843
  import MetaMaskOnboarding from "@metamask/onboarding";
2656
2844
  init_domain();
2657
2845
  init_qr();
2846
+ init_utils();
2658
2847
  var __instance;
2659
2848
  function preload() {
2660
2849
  return __async(this, null, function* () {
@@ -2747,7 +2936,7 @@ var ModalFactory = class {
2747
2936
  }
2748
2937
  createDeeplink(connectionRequest) {
2749
2938
  if (!connectionRequest) {
2750
- return `${METAMASK_DEEPLINK_BASE}`;
2939
+ throw new Error("createDeeplink can only be called with a connection request");
2751
2940
  }
2752
2941
  const json = JSON.stringify(connectionRequest);
2753
2942
  const compressed = compressString(json);
@@ -2863,10 +3052,12 @@ export {
2863
3052
  getPlatformType,
2864
3053
  getTransportType,
2865
3054
  getVersion,
3055
+ getWalletActionAnalyticsProperties,
2866
3056
  hasExtension,
2867
3057
  infuraRpcUrls,
2868
3058
  isEnabled,
2869
3059
  isMetamaskExtensionInstalled,
3060
+ isRejectionError,
2870
3061
  isSecure
2871
3062
  };
2872
3063
  //# sourceMappingURL=connect-multichain.mjs.map