@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
@@ -604,13 +604,261 @@ var init_ui = __esm({
604
604
  }
605
605
  });
606
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;
623
+ return (_a = dapp.url) != null ? _a : dapp.name;
624
+ }
625
+ function openDeeplink(options, deeplink, universalLink) {
626
+ const { mobile } = options;
627
+ const useDeeplink = mobile && mobile.useDeeplink !== void 0 ? mobile.useDeeplink : true;
628
+ if (useDeeplink) {
629
+ if (typeof window !== "undefined") {
630
+ window.location.href = deeplink;
631
+ }
632
+ } else if (typeof document !== "undefined") {
633
+ const link = document.createElement("a");
634
+ link.href = universalLink;
635
+ link.target = "_self";
636
+ link.rel = "noreferrer noopener";
637
+ link.click();
638
+ }
639
+ }
640
+ function getOptionalScopes(scopes) {
641
+ return scopes.reduce(
642
+ (prev, scope) => __spreadProps(__spreadValues({}, prev), {
643
+ [scope]: {
644
+ methods: [],
645
+ notifications: [],
646
+ accounts: []
647
+ }
648
+ }),
649
+ {}
650
+ );
651
+ }
652
+ function setupDappMetadata(options) {
653
+ var _a, _b;
654
+ const platform = getPlatformType();
655
+ const isBrowser = platform === "web-desktop" /* DesktopWeb */ || platform === "web-mobile" /* MobileWeb */ || platform === "in-app-browser" /* MetaMaskMobileWebview */;
656
+ if (!((_a = options.dapp) == null ? void 0 : _a.name)) {
657
+ throw new Error("You must provide dapp name");
658
+ }
659
+ if (isBrowser) {
660
+ options.dapp = __spreadProps(__spreadValues({}, options.dapp), {
661
+ url: `${window.location.protocol}//${window.location.host}`
662
+ });
663
+ }
664
+ if (!((_b = options.dapp) == null ? void 0 : _b.url)) {
665
+ throw new Error("You must provide dapp url");
666
+ }
667
+ const BASE_64_ICON_MAX_LENGTH = 163400;
668
+ const urlPattern = /^(http|https):\/\/[^\s]*$/;
669
+ if (options.dapp) {
670
+ if ("iconUrl" in options.dapp) {
671
+ if (options.dapp.iconUrl && !urlPattern.test(options.dapp.iconUrl)) {
672
+ console.warn(
673
+ "Invalid dappMetadata.iconUrl: URL must start with http:// or https://"
674
+ );
675
+ options.dapp.iconUrl = void 0;
676
+ }
677
+ }
678
+ if ("base64Icon" in options.dapp) {
679
+ if (options.dapp.base64Icon && options.dapp.base64Icon.length > BASE_64_ICON_MAX_LENGTH) {
680
+ console.warn(
681
+ "Invalid dappMetadata.base64Icon: Base64-encoded icon string length must be less than 163400 characters"
682
+ );
683
+ options.dapp.base64Icon = void 0;
684
+ }
685
+ }
686
+ if (options.dapp.url && !urlPattern.test(options.dapp.url)) {
687
+ console.warn(
688
+ "Invalid dappMetadata.url: URL must start with http:// or https://"
689
+ );
690
+ }
691
+ const favicon = extractFavicon();
692
+ if (favicon && !("iconUrl" in options.dapp) && !("base64Icon" in options.dapp)) {
693
+ const faviconUrl = `${window.location.protocol}//${window.location.host}${favicon}`;
694
+ options.dapp.iconUrl = faviconUrl;
695
+ }
696
+ }
697
+ return options;
698
+ }
699
+ function isSameScopesAndAccounts(currentScopes, proposedScopes, walletSession, proposedCaipAccountIds) {
700
+ const isSameScopes = currentScopes.every((scope) => proposedScopes.includes(scope)) && proposedScopes.every((scope) => currentScopes.includes(scope));
701
+ if (!isSameScopes) {
702
+ return false;
703
+ }
704
+ const existingAccountIds = Object.values(
705
+ walletSession.sessionScopes
706
+ ).filter(({ accounts }) => Boolean(accounts)).flatMap(({ accounts }) => accounts != null ? accounts : []);
707
+ const allProposedAccountsIncluded = proposedCaipAccountIds.every(
708
+ (proposedAccountId) => existingAccountIds.includes(proposedAccountId)
709
+ );
710
+ return allProposedAccountsIncluded;
711
+ }
712
+ function getValidAccounts(caipAccountIds) {
713
+ return caipAccountIds.reduce(
714
+ (caipAccounts, caipAccountId) => {
715
+ try {
716
+ return [...caipAccounts, (0, import_utils.parseCaipAccountId)(caipAccountId)];
717
+ } catch (err) {
718
+ const stringifiedAccountId = JSON.stringify(caipAccountId);
719
+ console.error(`Invalid CAIP account ID: ${stringifiedAccountId}`, err);
720
+ return caipAccounts;
721
+ }
722
+ },
723
+ []
724
+ );
725
+ }
726
+ function addValidAccounts(optionalScopes, validAccounts) {
727
+ var _a;
728
+ if (!optionalScopes || !(validAccounts == null ? void 0 : validAccounts.length)) {
729
+ return optionalScopes;
730
+ }
731
+ const result = Object.fromEntries(
732
+ Object.entries(optionalScopes).map(([scope, scopeData]) => {
733
+ var _a2, _b, _c;
734
+ return [
735
+ scope,
736
+ {
737
+ methods: [...(_a2 = scopeData == null ? void 0 : scopeData.methods) != null ? _a2 : []],
738
+ notifications: [...(_b = scopeData == null ? void 0 : scopeData.notifications) != null ? _b : []],
739
+ accounts: [...(_c = scopeData == null ? void 0 : scopeData.accounts) != null ? _c : []]
740
+ }
741
+ ];
742
+ })
743
+ );
744
+ const accountsByChain = /* @__PURE__ */ new Map();
745
+ for (const account of validAccounts) {
746
+ const chainKey = `${account.chain.namespace}:${account.chain.reference}`;
747
+ const accountId = `${account.chainId}:${account.address}`;
748
+ if (!accountsByChain.has(chainKey)) {
749
+ accountsByChain.set(chainKey, []);
750
+ }
751
+ (_a = accountsByChain.get(chainKey)) == null ? void 0 : _a.push(accountId);
752
+ }
753
+ for (const [scopeKey, scopeData] of Object.entries(result)) {
754
+ if (!(scopeData == null ? void 0 : scopeData.accounts)) {
755
+ continue;
756
+ }
757
+ try {
758
+ const scope = scopeKey;
759
+ const scopeDetails = (0, import_utils.parseCaipChainId)(scope);
760
+ const chainKey = `${scopeDetails.namespace}:${scopeDetails.reference}`;
761
+ const matchingAccounts = accountsByChain.get(chainKey);
762
+ if (matchingAccounts) {
763
+ const existingAccounts = new Set(scopeData.accounts);
764
+ const newAccounts = matchingAccounts.filter(
765
+ (account) => !existingAccounts.has(account)
766
+ );
767
+ scopeData.accounts.push(...newAccounts);
768
+ }
769
+ } catch (error) {
770
+ console.error(`Invalid scope format: ${scopeKey}`, error);
771
+ }
772
+ }
773
+ return result;
774
+ }
775
+ var import_pako, import_utils, extractFavicon;
776
+ var init_utils = __esm({
777
+ "src/multichain/utils/index.ts"() {
778
+ "use strict";
779
+ import_pako = require("pako");
780
+ import_utils = require("@metamask/utils");
781
+ init_domain();
782
+ extractFavicon = () => {
783
+ var _a;
784
+ if (typeof document === "undefined") {
785
+ return void 0;
786
+ }
787
+ let favicon;
788
+ const nodeList = document.getElementsByTagName("link");
789
+ for (let i = 0; i < nodeList.length; i++) {
790
+ if (nodeList[i].getAttribute("rel") === "icon" || nodeList[i].getAttribute("rel") === "shortcut icon") {
791
+ favicon = (_a = nodeList[i].getAttribute("href")) != null ? _a : void 0;
792
+ }
793
+ }
794
+ return favicon;
795
+ };
796
+ }
797
+ });
798
+
799
+ // src/multichain/utils/analytics.ts
800
+ function isRejectionError(error) {
801
+ var _a, _b;
802
+ if (typeof error !== "object" || error === null) {
803
+ return false;
804
+ }
805
+ const errorObj = error;
806
+ const errorCode = errorObj.code;
807
+ const errorMessage = (_b = (_a = errorObj.message) == null ? void 0 : _a.toLowerCase()) != null ? _b : "";
808
+ return errorCode === 4001 || // User rejected request (common EIP-1193 code)
809
+ errorCode === 4100 || // Unauthorized (common rejection code)
810
+ errorMessage.includes("reject") || errorMessage.includes("denied") || errorMessage.includes("cancel") || errorMessage.includes("user");
811
+ }
812
+ function getBaseAnalyticsProperties(options, storage) {
813
+ return __async(this, null, function* () {
814
+ var _a, _b;
815
+ const version = getVersion();
816
+ const dappId = getDappId(options.dapp);
817
+ const platform = getPlatformType();
818
+ const anonId = yield storage.getAnonId();
819
+ const integrationType = (_b = (_a = options.analytics) == null ? void 0 : _a.integrationType) != null ? _b : "unknown" /* UNKNOWN */;
820
+ return {
821
+ mmconnect_version: version,
822
+ dapp_id: dappId,
823
+ platform,
824
+ integration_type: integrationType,
825
+ anon_id: anonId
826
+ };
827
+ });
828
+ }
829
+ function getWalletActionAnalyticsProperties(options, storage, invokeOptions) {
830
+ return __async(this, null, function* () {
831
+ var _a, _b;
832
+ const version = getVersion();
833
+ const dappId = getDappId(options.dapp);
834
+ const anonId = yield storage.getAnonId();
835
+ const integrationType = (_b = (_a = options.analytics) == null ? void 0 : _a.integrationType) != null ? _b : "unknown";
836
+ return {
837
+ mmconnect_version: version,
838
+ dapp_id: dappId,
839
+ method: invokeOptions.request.method,
840
+ integration_type: integrationType,
841
+ caip_chain_id: invokeOptions.scope,
842
+ anon_id: anonId
843
+ };
844
+ });
845
+ }
846
+ var init_analytics = __esm({
847
+ "src/multichain/utils/analytics.ts"() {
848
+ "use strict";
849
+ init_utils();
850
+ init_domain();
851
+ }
852
+ });
853
+
607
854
  // src/domain/utils/index.ts
608
855
  function getVersion() {
609
856
  return "0.0.0";
610
857
  }
611
- var init_utils = __esm({
858
+ var init_utils2 = __esm({
612
859
  "src/domain/utils/index.ts"() {
613
860
  "use strict";
861
+ init_analytics();
614
862
  }
615
863
  });
616
864
 
@@ -625,7 +873,7 @@ var init_domain = __esm({
625
873
  init_platform();
626
874
  init_store();
627
875
  init_ui();
628
- init_utils();
876
+ init_utils2();
629
877
  }
630
878
  });
631
879
 
@@ -672,7 +920,7 @@ function shouldLogCountdown(remainingSeconds) {
672
920
  return remainingSeconds % 60 === 0;
673
921
  }
674
922
  }
675
- var init_utils2 = __esm({
923
+ var init_utils3 = __esm({
676
924
  "src/ui/modals/base/utils.ts"() {
677
925
  "use strict";
678
926
  }
@@ -684,7 +932,7 @@ var init_AbstractInstallModal = __esm({
684
932
  "src/ui/modals/base/AbstractInstallModal.ts"() {
685
933
  "use strict";
686
934
  init_domain();
687
- init_utils2();
935
+ init_utils3();
688
936
  logger3 = createLogger("metamask-sdk:ui");
689
937
  AbstractInstallModal = class extends Modal {
690
938
  constructor() {
@@ -778,7 +1026,7 @@ var init_install = __esm({
778
1026
  init_domain();
779
1027
  init_qr();
780
1028
  init_AbstractInstallModal();
781
- init_utils2();
1029
+ init_utils3();
782
1030
  logger4 = createLogger("metamask-sdk:ui");
783
1031
  InstallModal = class extends AbstractInstallModal {
784
1032
  displayQRWithCountdown(qrCodeLink, expiresInMs) {
@@ -933,16 +1181,18 @@ __export(index_node_exports, {
933
1181
  getPlatformType: () => getPlatformType,
934
1182
  getTransportType: () => getTransportType,
935
1183
  getVersion: () => getVersion,
1184
+ getWalletActionAnalyticsProperties: () => getWalletActionAnalyticsProperties,
936
1185
  hasExtension: () => hasExtension,
937
1186
  infuraRpcUrls: () => infuraRpcUrls,
938
1187
  isEnabled: () => isEnabled,
939
1188
  isMetamaskExtensionInstalled: () => isMetamaskExtensionInstalled,
1189
+ isRejectionError: () => isRejectionError,
940
1190
  isSecure: () => isSecure
941
1191
  });
942
1192
  module.exports = __toCommonJS(index_node_exports);
943
1193
 
944
1194
  // src/multichain/index.ts
945
- var import_analytics = require("@metamask/analytics");
1195
+ var import_analytics4 = require("@metamask/analytics");
946
1196
  var import_mobile_wallet_protocol_core2 = require("@metamask/mobile-wallet-protocol-core");
947
1197
  var import_mobile_wallet_protocol_dapp_client = require("@metamask/mobile-wallet-protocol-dapp-client");
948
1198
  var import_multichain_api_client3 = require("@metamask/multichain-api-client");
@@ -954,6 +1204,7 @@ var METAMASK_DEEPLINK_BASE = "metamask://connect";
954
1204
 
955
1205
  // src/multichain/index.ts
956
1206
  init_domain();
1207
+ init_analytics();
957
1208
  init_logger();
958
1209
  init_multichain();
959
1210
  init_platform();
@@ -1054,201 +1305,17 @@ var RpcClient = class {
1054
1305
  };
1055
1306
 
1056
1307
  // src/multichain/rpc/requestRouter.ts
1308
+ var import_analytics2 = require("@metamask/analytics");
1057
1309
  init_domain();
1058
-
1059
- // src/multichain/utils/index.ts
1060
- var import_pako = require("pako");
1061
- var import_utils = require("@metamask/utils");
1062
- init_domain();
1063
- function base64Encode(str) {
1064
- if (typeof btoa !== "undefined") {
1065
- return btoa(str);
1066
- } else if (typeof Buffer !== "undefined") {
1067
- return Buffer.from(str).toString("base64");
1068
- }
1069
- throw new Error("No base64 encoding method available");
1070
- }
1071
- function compressString(str) {
1072
- const compressed = (0, import_pako.deflate)(str);
1073
- const binaryString = String.fromCharCode.apply(null, Array.from(compressed));
1074
- return base64Encode(binaryString);
1075
- }
1076
- function getDappId(dapp) {
1077
- var _a, _b;
1078
- if (typeof window === "undefined" || typeof window.location === "undefined") {
1079
- return (_b = (_a = dapp == null ? void 0 : dapp.name) != null ? _a : dapp == null ? void 0 : dapp.url) != null ? _b : "N/A";
1080
- }
1081
- return window.location.hostname;
1082
- }
1083
- function openDeeplink(options, deeplink, universalLink) {
1084
- const { mobile } = options;
1085
- const useDeeplink = mobile && mobile.useDeeplink !== void 0 ? mobile.useDeeplink : true;
1086
- if (useDeeplink) {
1087
- if (typeof window !== "undefined") {
1088
- window.location.href = deeplink;
1089
- }
1090
- } else if (typeof document !== "undefined") {
1091
- const link = document.createElement("a");
1092
- link.href = universalLink;
1093
- link.target = "_self";
1094
- link.rel = "noreferrer noopener";
1095
- link.click();
1096
- }
1097
- }
1098
- function getOptionalScopes(scopes) {
1099
- return scopes.reduce(
1100
- (prev, scope) => __spreadProps(__spreadValues({}, prev), {
1101
- [scope]: {
1102
- methods: [],
1103
- notifications: [],
1104
- accounts: []
1105
- }
1106
- }),
1107
- {}
1108
- );
1109
- }
1110
- var extractFavicon = () => {
1111
- var _a;
1112
- if (typeof document === "undefined") {
1113
- return void 0;
1114
- }
1115
- let favicon;
1116
- const nodeList = document.getElementsByTagName("link");
1117
- for (let i = 0; i < nodeList.length; i++) {
1118
- if (nodeList[i].getAttribute("rel") === "icon" || nodeList[i].getAttribute("rel") === "shortcut icon") {
1119
- favicon = (_a = nodeList[i].getAttribute("href")) != null ? _a : void 0;
1120
- }
1121
- }
1122
- return favicon;
1123
- };
1124
- function setupDappMetadata(options) {
1125
- var _a;
1126
- const platform = getPlatformType();
1127
- const isBrowser = platform === "web-desktop" /* DesktopWeb */ || platform === "web-mobile" /* MobileWeb */ || platform === "in-app-browser" /* MetaMaskMobileWebview */;
1128
- if (!((_a = options.dapp) == null ? void 0 : _a.url)) {
1129
- if (isBrowser) {
1130
- options.dapp = __spreadProps(__spreadValues({}, options.dapp), {
1131
- url: `${window.location.protocol}//${window.location.host}`
1132
- });
1133
- } else {
1134
- throw new Error("You must provide dapp url");
1135
- }
1136
- }
1137
- const BASE_64_ICON_MAX_LENGTH = 163400;
1138
- const urlPattern = /^(http|https):\/\/[^\s]*$/;
1139
- if (options.dapp) {
1140
- if ("iconUrl" in options.dapp) {
1141
- if (options.dapp.iconUrl && !urlPattern.test(options.dapp.iconUrl)) {
1142
- console.warn(
1143
- "Invalid dappMetadata.iconUrl: URL must start with http:// or https://"
1144
- );
1145
- options.dapp.iconUrl = void 0;
1146
- }
1147
- }
1148
- if ("base64Icon" in options.dapp) {
1149
- if (options.dapp.base64Icon && options.dapp.base64Icon.length > BASE_64_ICON_MAX_LENGTH) {
1150
- console.warn(
1151
- "Invalid dappMetadata.base64Icon: Base64-encoded icon string length must be less than 163400 characters"
1152
- );
1153
- options.dapp.base64Icon = void 0;
1154
- }
1155
- }
1156
- if (options.dapp.url && !urlPattern.test(options.dapp.url)) {
1157
- console.warn(
1158
- "Invalid dappMetadata.url: URL must start with http:// or https://"
1159
- );
1160
- }
1161
- const favicon = extractFavicon();
1162
- if (favicon && !("iconUrl" in options.dapp) && !("base64Icon" in options.dapp)) {
1163
- const faviconUrl = `${window.location.protocol}//${window.location.host}${favicon}`;
1164
- options.dapp.iconUrl = faviconUrl;
1165
- }
1166
- }
1167
- return options;
1168
- }
1169
- function isSameScopesAndAccounts(currentScopes, proposedScopes, walletSession, proposedCaipAccountIds) {
1170
- const isSameScopes = currentScopes.every((scope) => proposedScopes.includes(scope)) && proposedScopes.every((scope) => currentScopes.includes(scope));
1171
- if (!isSameScopes) {
1172
- return false;
1173
- }
1174
- const existingAccountIds = Object.values(
1175
- walletSession.sessionScopes
1176
- ).filter(({ accounts }) => Boolean(accounts)).flatMap(({ accounts }) => accounts != null ? accounts : []);
1177
- const allProposedAccountsIncluded = proposedCaipAccountIds.every(
1178
- (proposedAccountId) => existingAccountIds.includes(proposedAccountId)
1179
- );
1180
- return allProposedAccountsIncluded;
1181
- }
1182
- function getValidAccounts(caipAccountIds) {
1183
- return caipAccountIds.reduce(
1184
- (caipAccounts, caipAccountId) => {
1185
- try {
1186
- return [...caipAccounts, (0, import_utils.parseCaipAccountId)(caipAccountId)];
1187
- } catch (err) {
1188
- const stringifiedAccountId = JSON.stringify(caipAccountId);
1189
- console.error(`Invalid CAIP account ID: ${stringifiedAccountId}`, err);
1190
- return caipAccounts;
1191
- }
1192
- },
1193
- []
1194
- );
1195
- }
1196
- function addValidAccounts(optionalScopes, validAccounts) {
1197
- var _a;
1198
- if (!optionalScopes || !(validAccounts == null ? void 0 : validAccounts.length)) {
1199
- return optionalScopes;
1200
- }
1201
- const result = Object.fromEntries(
1202
- Object.entries(optionalScopes).map(([scope, scopeData]) => {
1203
- var _a2, _b, _c;
1204
- return [
1205
- scope,
1206
- {
1207
- methods: [...(_a2 = scopeData == null ? void 0 : scopeData.methods) != null ? _a2 : []],
1208
- notifications: [...(_b = scopeData == null ? void 0 : scopeData.notifications) != null ? _b : []],
1209
- accounts: [...(_c = scopeData == null ? void 0 : scopeData.accounts) != null ? _c : []]
1210
- }
1211
- ];
1212
- })
1213
- );
1214
- const accountsByChain = /* @__PURE__ */ new Map();
1215
- for (const account of validAccounts) {
1216
- const chainKey = `${account.chain.namespace}:${account.chain.reference}`;
1217
- const accountId = `${account.chainId}:${account.address}`;
1218
- if (!accountsByChain.has(chainKey)) {
1219
- accountsByChain.set(chainKey, []);
1220
- }
1221
- (_a = accountsByChain.get(chainKey)) == null ? void 0 : _a.push(accountId);
1222
- }
1223
- for (const [scopeKey, scopeData] of Object.entries(result)) {
1224
- if (!(scopeData == null ? void 0 : scopeData.accounts)) {
1225
- continue;
1226
- }
1227
- try {
1228
- const scope = scopeKey;
1229
- const scopeDetails = (0, import_utils.parseCaipChainId)(scope);
1230
- const chainKey = `${scopeDetails.namespace}:${scopeDetails.reference}`;
1231
- const matchingAccounts = accountsByChain.get(chainKey);
1232
- if (matchingAccounts) {
1233
- const existingAccounts = new Set(scopeData.accounts);
1234
- const newAccounts = matchingAccounts.filter(
1235
- (account) => !existingAccounts.has(account)
1236
- );
1237
- scopeData.accounts.push(...newAccounts);
1238
- }
1239
- } catch (error) {
1240
- console.error(`Invalid scope format: ${scopeKey}`, error);
1241
- }
1242
- }
1243
- return result;
1244
- }
1245
-
1246
- // src/multichain/rpc/requestRouter.ts
1310
+ init_utils();
1311
+ init_analytics();
1312
+ var _RequestRouter_instances, withAnalyticsTracking_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, trackWalletActionRejected_fn;
1247
1313
  var RequestRouter = class {
1248
1314
  constructor(transport, rpcClient, config) {
1249
1315
  this.transport = transport;
1250
1316
  this.rpcClient = rpcClient;
1251
1317
  this.config = config;
1318
+ __privateAdd(this, _RequestRouter_instances);
1252
1319
  }
1253
1320
  /**
1254
1321
  * The main entry point for invoking an RPC method.
@@ -1272,7 +1339,7 @@ var RequestRouter = class {
1272
1339
  */
1273
1340
  handleWithWallet(options) {
1274
1341
  return __async(this, null, function* () {
1275
- try {
1342
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1276
1343
  const request = this.transport.request({
1277
1344
  method: "wallet_invokeMethod",
1278
1345
  params: options
@@ -1295,9 +1362,7 @@ var RequestRouter = class {
1295
1362
  throw new RPCInvokeMethodErr(`RPC Request failed with code ${response.error.code}: ${response.error.message}`);
1296
1363
  }
1297
1364
  return response.result;
1298
- } catch (error) {
1299
- throw new RPCInvokeMethodErr(error.message);
1300
- }
1365
+ }));
1301
1366
  });
1302
1367
  }
1303
1368
  /**
@@ -1305,14 +1370,16 @@ var RequestRouter = class {
1305
1370
  */
1306
1371
  handleWithRpcNode(options) {
1307
1372
  return __async(this, null, function* () {
1308
- try {
1309
- return yield this.rpcClient.request(options);
1310
- } catch (error) {
1311
- if (error instanceof MissingRpcEndpointErr) {
1312
- return this.handleWithWallet(options);
1373
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1374
+ try {
1375
+ return yield this.rpcClient.request(options);
1376
+ } catch (error) {
1377
+ if (error instanceof MissingRpcEndpointErr) {
1378
+ return this.handleWithWallet(options);
1379
+ }
1380
+ throw error;
1313
1381
  }
1314
- throw error;
1315
- }
1382
+ }));
1316
1383
  });
1317
1384
  }
1318
1385
  /**
@@ -1325,9 +1392,60 @@ var RequestRouter = class {
1325
1392
  });
1326
1393
  }
1327
1394
  };
1395
+ _RequestRouter_instances = new WeakSet();
1396
+ withAnalyticsTracking_fn = function(options, execute) {
1397
+ return __async(this, null, function* () {
1398
+ var _a, _b, _c;
1399
+ if ((_a = this.config.analytics) == null ? void 0 : _a.enabled) {
1400
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRequested_fn).call(this, options);
1401
+ }
1402
+ try {
1403
+ const result = yield execute();
1404
+ if ((_b = this.config.analytics) == null ? void 0 : _b.enabled) {
1405
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionSucceeded_fn).call(this, options);
1406
+ }
1407
+ return result;
1408
+ } catch (error) {
1409
+ if ((_c = this.config.analytics) == null ? void 0 : _c.enabled) {
1410
+ const isRejection = isRejectionError(error);
1411
+ if (isRejection) {
1412
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRejected_fn).call(this, options);
1413
+ } else {
1414
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options);
1415
+ }
1416
+ }
1417
+ throw new RPCInvokeMethodErr(error.message);
1418
+ }
1419
+ });
1420
+ };
1421
+ trackWalletActionRequested_fn = function(options) {
1422
+ return __async(this, null, function* () {
1423
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1424
+ import_analytics2.analytics.track("mmconnect_wallet_action_requested", props);
1425
+ });
1426
+ };
1427
+ trackWalletActionSucceeded_fn = function(options) {
1428
+ return __async(this, null, function* () {
1429
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1430
+ import_analytics2.analytics.track("mmconnect_wallet_action_succeeded", props);
1431
+ });
1432
+ };
1433
+ trackWalletActionFailed_fn = function(options) {
1434
+ return __async(this, null, function* () {
1435
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1436
+ import_analytics2.analytics.track("mmconnect_wallet_action_failed", props);
1437
+ });
1438
+ };
1439
+ trackWalletActionRejected_fn = function(options) {
1440
+ return __async(this, null, function* () {
1441
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1442
+ import_analytics2.analytics.track("mmconnect_wallet_action_rejected", props);
1443
+ });
1444
+ };
1328
1445
 
1329
1446
  // src/multichain/transports/default/index.ts
1330
1447
  var import_multichain_api_client = require("@metamask/multichain-api-client");
1448
+ init_utils();
1331
1449
  var DEFAULT_REQUEST_TIMEOUT = 60 * 1e3;
1332
1450
  var _notificationCallbacks, _transport, _defaultRequestOptions, _reqId, _pendingRequests, _handleResponseListener, _handleNotificationListener, _DefaultTransport_instances, notifyCallbacks_fn, isMetamaskProviderEvent_fn, handleResponse_fn, handleNotification_fn, setupMessageListener_fn;
1333
1451
  var DefaultTransport = class {
@@ -1556,6 +1674,7 @@ setupMessageListener_fn = function() {
1556
1674
  var import_mobile_wallet_protocol_core = require("@metamask/mobile-wallet-protocol-core");
1557
1675
  var import_multichain_api_client2 = require("@metamask/multichain-api-client");
1558
1676
  init_domain();
1677
+ init_utils();
1559
1678
 
1560
1679
  // src/multichain/transports/constants.ts
1561
1680
  var MULTICHAIN_PROVIDER_STREAM_NAME = "metamask-multichain-provider";
@@ -2029,20 +2148,22 @@ var KeyManager = class {
2029
2148
  var keymanager = new KeyManager();
2030
2149
 
2031
2150
  // src/multichain/index.ts
2151
+ init_utils();
2032
2152
  var logger2 = createLogger("metamask-sdk:core");
2033
2153
  var MultichainSDK = class _MultichainSDK extends MultichainCore {
2034
2154
  constructor(options) {
2035
- var _a, _b, _c, _d, _e, _f;
2155
+ var _a, _b, _c, _d, _e, _f, _g;
2036
2156
  const withDappMetadata = setupDappMetadata(options);
2157
+ const integrationType = ((_a = options.analytics) == null ? void 0 : _a.enabled) ? options.analytics.integrationType : "direct";
2037
2158
  const allOptions = __spreadProps(__spreadValues({}, withDappMetadata), {
2038
2159
  ui: __spreadProps(__spreadValues({}, withDappMetadata.ui), {
2039
- preferExtension: (_a = withDappMetadata.ui.preferExtension) != null ? _a : true,
2040
- showInstallModal: (_b = withDappMetadata.ui.showInstallModal) != null ? _b : false,
2041
- headless: (_c = withDappMetadata.ui.headless) != null ? _c : false
2160
+ preferExtension: (_b = withDappMetadata.ui.preferExtension) != null ? _b : true,
2161
+ showInstallModal: (_c = withDappMetadata.ui.showInstallModal) != null ? _c : false,
2162
+ headless: (_d = withDappMetadata.ui.headless) != null ? _d : false
2042
2163
  }),
2043
- analytics: __spreadProps(__spreadValues({}, (_d = options.analytics) != null ? _d : {}), {
2044
- enabled: (_f = (_e = options.analytics) == null ? void 0 : _e.enabled) != null ? _f : true,
2045
- integrationType: "unknown"
2164
+ analytics: __spreadProps(__spreadValues({}, (_e = options.analytics) != null ? _e : {}), {
2165
+ enabled: (_g = (_f = options.analytics) == null ? void 0 : _f.enabled) != null ? _g : true,
2166
+ integrationType
2046
2167
  })
2047
2168
  });
2048
2169
  super(allOptions);
@@ -2126,12 +2247,12 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2126
2247
  const { integrationType } = (_b = this.options.analytics) != null ? _b : {
2127
2248
  integrationType: ""
2128
2249
  };
2129
- import_analytics.analytics.setGlobalProperty("sdk_version", version);
2130
- import_analytics.analytics.setGlobalProperty("dapp_id", dappId);
2131
- import_analytics.analytics.setGlobalProperty("anon_id", anonId);
2132
- import_analytics.analytics.setGlobalProperty("platform", platform);
2133
- import_analytics.analytics.setGlobalProperty("integration_type", integrationType);
2134
- import_analytics.analytics.enable();
2250
+ import_analytics4.analytics.setGlobalProperty("mmconnect_version", version);
2251
+ import_analytics4.analytics.setGlobalProperty("dapp_id", dappId);
2252
+ import_analytics4.analytics.setGlobalProperty("anon_id", anonId);
2253
+ import_analytics4.analytics.setGlobalProperty("platform", platform);
2254
+ import_analytics4.analytics.setGlobalProperty("integration_type", integrationType);
2255
+ import_analytics4.analytics.enable();
2135
2256
  });
2136
2257
  }
2137
2258
  onTransportNotification(payload) {
@@ -2193,14 +2314,24 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2193
2314
  }
2194
2315
  init() {
2195
2316
  return __async(this, null, function* () {
2196
- var _a;
2317
+ var _a, _b;
2197
2318
  try {
2198
2319
  if (typeof window !== "undefined" && ((_a = window.mmsdk) == null ? void 0 : _a.isInitialized)) {
2199
2320
  logger2("MetaMaskSDK: init already initialized");
2200
2321
  } else {
2201
2322
  yield this.setupAnalytics();
2202
2323
  yield this.setupTransport();
2203
- import_analytics.analytics.track("sdk_initialized", {});
2324
+ if ((_b = this.options.analytics) == null ? void 0 : _b.enabled) {
2325
+ try {
2326
+ const baseProps = yield getBaseAnalyticsProperties(
2327
+ this.options,
2328
+ this.storage
2329
+ );
2330
+ import_analytics4.analytics.track("mmconnect_initialized", baseProps);
2331
+ } catch (error) {
2332
+ logger2("Error tracking initialized event", error);
2333
+ }
2334
+ }
2204
2335
  if (typeof window !== "undefined") {
2205
2336
  window.mmsdk = this;
2206
2337
  }
@@ -2379,17 +2510,6 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2379
2510
  }
2380
2511
  }
2381
2512
  );
2382
- } else {
2383
- timeout = setTimeout(() => {
2384
- var _a;
2385
- const deeplink = this.options.ui.factory.createDeeplink();
2386
- const universalLink = this.options.ui.factory.createUniversalLink();
2387
- if ((_a = this.options.mobile) == null ? void 0 : _a.preferredOpenLink) {
2388
- this.options.mobile.preferredOpenLink(deeplink, "_self");
2389
- } else {
2390
- openDeeplink(this.options, deeplink, universalLink);
2391
- }
2392
- }, 250);
2393
2513
  }
2394
2514
  this.transport.connect({ scopes, caipAccountIds }).then(resolve).catch((error) => {
2395
2515
  this.storage.removeTransport();
@@ -2402,27 +2522,87 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2402
2522
  }));
2403
2523
  });
2404
2524
  }
2405
- handleConnection(promise) {
2525
+ handleConnection(promise, scopes, transportType) {
2406
2526
  return __async(this, null, function* () {
2407
2527
  this.state = "connecting";
2408
- return promise.then(() => {
2528
+ return promise.then(() => __async(this, null, function* () {
2529
+ var _a;
2409
2530
  this.state = "connected";
2410
- }).catch((error) => {
2531
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2532
+ try {
2533
+ const baseProps = yield getBaseAnalyticsProperties(
2534
+ this.options,
2535
+ this.storage
2536
+ );
2537
+ import_analytics4.analytics.track("mmconnect_connection_established", __spreadProps(__spreadValues({}, baseProps), {
2538
+ transport_type: transportType,
2539
+ user_permissioned_chains: scopes
2540
+ }));
2541
+ } catch (error) {
2542
+ logger2("Error tracking connection_established event", error);
2543
+ }
2544
+ }
2545
+ })).catch((error) => __async(this, null, function* () {
2546
+ var _a;
2411
2547
  this.state = "disconnected";
2548
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2549
+ try {
2550
+ const baseProps = yield getBaseAnalyticsProperties(
2551
+ this.options,
2552
+ this.storage
2553
+ );
2554
+ const isRejection = isRejectionError(error);
2555
+ if (isRejection) {
2556
+ import_analytics4.analytics.track("mmconnect_connection_rejected", __spreadProps(__spreadValues({}, baseProps), {
2557
+ transport_type: transportType
2558
+ }));
2559
+ } else {
2560
+ import_analytics4.analytics.track("mmconnect_connection_failed", __spreadProps(__spreadValues({}, baseProps), {
2561
+ transport_type: transportType
2562
+ }));
2563
+ }
2564
+ } catch (e) {
2565
+ logger2("Error tracking connection failed/rejected event", error);
2566
+ }
2567
+ }
2412
2568
  return Promise.reject(error);
2413
- });
2569
+ }));
2414
2570
  });
2415
2571
  }
2416
2572
  connect(scopes, caipAccountIds, forceRequest) {
2417
2573
  return __async(this, null, function* () {
2418
- var _a;
2574
+ var _a, _b;
2419
2575
  const { ui } = this.options;
2420
2576
  const platformType = getPlatformType();
2421
2577
  const isWeb = platformType === "in-app-browser" /* MetaMaskMobileWebview */ || platformType === "web-desktop" /* DesktopWeb */;
2422
2578
  const { preferExtension = true, showInstallModal = false } = ui;
2423
2579
  const secure = isSecure();
2424
2580
  const hasExtensionInstalled = yield hasExtension();
2425
- if (((_a = this.__transport) == null ? void 0 : _a.isConnected()) && !secure) {
2581
+ let transportType;
2582
+ if (platformType === "in-app-browser" /* MetaMaskMobileWebview */ || isWeb && hasExtensionInstalled && preferExtension) {
2583
+ transportType = "browser" /* Browser */;
2584
+ } else {
2585
+ transportType = "mwp" /* MWP */;
2586
+ }
2587
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2588
+ try {
2589
+ const baseProps = yield getBaseAnalyticsProperties(
2590
+ this.options,
2591
+ this.storage
2592
+ );
2593
+ const dappConfiguredChains = Object.keys(
2594
+ this.options.api.supportedNetworks
2595
+ );
2596
+ import_analytics4.analytics.track("mmconnect_connection_initiated", __spreadProps(__spreadValues({}, baseProps), {
2597
+ transport_type: transportType,
2598
+ dapp_configured_chains: dappConfiguredChains,
2599
+ dapp_requested_chains: scopes
2600
+ }));
2601
+ } catch (error) {
2602
+ logger2("Error tracking connection_initiated event", error);
2603
+ }
2604
+ }
2605
+ if (((_b = this.__transport) == null ? void 0 : _b.isConnected()) && !secure) {
2426
2606
  return this.handleConnection(
2427
2607
  this.__transport.connect({ scopes, caipAccountIds, forceRequest }).then(() => {
2428
2608
  if (this.__transport instanceof MWPTransport) {
@@ -2430,30 +2610,40 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2430
2610
  } else {
2431
2611
  return this.storage.setTransport("browser" /* Browser */);
2432
2612
  }
2433
- })
2613
+ }),
2614
+ scopes,
2615
+ transportType
2434
2616
  );
2435
2617
  }
2436
2618
  if (platformType === "in-app-browser" /* MetaMaskMobileWebview */) {
2437
2619
  const defaultTransport = yield this.setupDefaultTransport();
2438
2620
  return this.handleConnection(
2439
- defaultTransport.connect({ scopes, caipAccountIds, forceRequest })
2621
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2622
+ scopes,
2623
+ transportType
2440
2624
  );
2441
2625
  }
2442
2626
  if (isWeb && hasExtensionInstalled && preferExtension) {
2443
2627
  const defaultTransport = yield this.setupDefaultTransport();
2444
2628
  return this.handleConnection(
2445
- defaultTransport.connect({ scopes, caipAccountIds, forceRequest })
2629
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2630
+ scopes,
2631
+ transportType
2446
2632
  );
2447
2633
  }
2448
2634
  yield this.setupMWP();
2449
2635
  const shouldShowInstallModal = hasExtensionInstalled ? showInstallModal : !preferExtension || showInstallModal;
2450
2636
  if (secure && !shouldShowInstallModal) {
2451
2637
  return this.handleConnection(
2452
- this.deeplinkConnect(scopes, caipAccountIds)
2638
+ this.deeplinkConnect(scopes, caipAccountIds),
2639
+ scopes,
2640
+ transportType
2453
2641
  );
2454
2642
  }
2455
2643
  return this.handleConnection(
2456
- this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds)
2644
+ this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds),
2645
+ scopes,
2646
+ transportType
2457
2647
  );
2458
2648
  });
2459
2649
  }
@@ -2693,6 +2883,7 @@ var Store = class extends StoreClient {
2693
2883
  var import_onboarding = __toESM(require("@metamask/onboarding"));
2694
2884
  init_domain();
2695
2885
  init_qr();
2886
+ init_utils();
2696
2887
  var __instance;
2697
2888
  function preload() {
2698
2889
  return __async(this, null, function* () {
@@ -2785,7 +2976,7 @@ var ModalFactory = class {
2785
2976
  }
2786
2977
  createDeeplink(connectionRequest) {
2787
2978
  if (!connectionRequest) {
2788
- return `${METAMASK_DEEPLINK_BASE}`;
2979
+ throw new Error("createDeeplink can only be called with a connection request");
2789
2980
  }
2790
2981
  const json = JSON.stringify(connectionRequest);
2791
2982
  const compressed = compressString(json);
@@ -2902,10 +3093,12 @@ var createMetamaskConnect = (options) => __async(null, null, function* () {
2902
3093
  getPlatformType,
2903
3094
  getTransportType,
2904
3095
  getVersion,
3096
+ getWalletActionAnalyticsProperties,
2905
3097
  hasExtension,
2906
3098
  infuraRpcUrls,
2907
3099
  isEnabled,
2908
3100
  isMetamaskExtensionInstalled,
3101
+ isRejectionError,
2909
3102
  isSecure
2910
3103
  });
2911
3104
  //# sourceMappingURL=connect-multichain.js.map