@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
 
@@ -627,7 +878,7 @@ function shouldLogCountdown(remainingSeconds) {
627
878
  return remainingSeconds % 60 === 0;
628
879
  }
629
880
  }
630
- var init_utils2 = __esm({
881
+ var init_utils3 = __esm({
631
882
  "src/ui/modals/base/utils.ts"() {
632
883
  "use strict";
633
884
  }
@@ -639,7 +890,7 @@ var init_AbstractInstallModal = __esm({
639
890
  "src/ui/modals/base/AbstractInstallModal.ts"() {
640
891
  "use strict";
641
892
  init_domain();
642
- init_utils2();
893
+ init_utils3();
643
894
  logger3 = createLogger("metamask-sdk:ui");
644
895
  AbstractInstallModal = class extends Modal {
645
896
  constructor() {
@@ -830,7 +1081,7 @@ var init_rn2 = __esm({
830
1081
  });
831
1082
 
832
1083
  // src/multichain/index.ts
833
- import { analytics } from "@metamask/analytics";
1084
+ import { analytics as analytics2 } from "@metamask/analytics";
834
1085
  import {
835
1086
  ErrorCode,
836
1087
  ProtocolError,
@@ -849,6 +1100,7 @@ var METAMASK_DEEPLINK_BASE = "metamask://connect";
849
1100
 
850
1101
  // src/multichain/index.ts
851
1102
  init_domain();
1103
+ init_analytics();
852
1104
  init_logger();
853
1105
  init_multichain();
854
1106
  init_platform();
@@ -949,204 +1201,17 @@ var RpcClient = class {
949
1201
  };
950
1202
 
951
1203
  // src/multichain/rpc/requestRouter.ts
1204
+ import { analytics } from "@metamask/analytics";
952
1205
  init_domain();
953
-
954
- // src/multichain/utils/index.ts
955
- init_domain();
956
- import { deflate } from "pako";
957
- import {
958
- parseCaipAccountId,
959
- parseCaipChainId
960
- } from "@metamask/utils";
961
- function base64Encode(str) {
962
- if (typeof btoa !== "undefined") {
963
- return btoa(str);
964
- } else if (typeof Buffer !== "undefined") {
965
- return Buffer.from(str).toString("base64");
966
- }
967
- throw new Error("No base64 encoding method available");
968
- }
969
- function compressString(str) {
970
- const compressed = deflate(str);
971
- const binaryString = String.fromCharCode.apply(null, Array.from(compressed));
972
- return base64Encode(binaryString);
973
- }
974
- function getDappId(dapp) {
975
- var _a, _b;
976
- if (typeof window === "undefined" || typeof window.location === "undefined") {
977
- return (_b = (_a = dapp == null ? void 0 : dapp.name) != null ? _a : dapp == null ? void 0 : dapp.url) != null ? _b : "N/A";
978
- }
979
- return window.location.hostname;
980
- }
981
- function openDeeplink(options, deeplink, universalLink) {
982
- const { mobile } = options;
983
- const useDeeplink = mobile && mobile.useDeeplink !== void 0 ? mobile.useDeeplink : true;
984
- if (useDeeplink) {
985
- if (typeof window !== "undefined") {
986
- window.location.href = deeplink;
987
- }
988
- } else if (typeof document !== "undefined") {
989
- const link = document.createElement("a");
990
- link.href = universalLink;
991
- link.target = "_self";
992
- link.rel = "noreferrer noopener";
993
- link.click();
994
- }
995
- }
996
- function getOptionalScopes(scopes) {
997
- return scopes.reduce(
998
- (prev, scope) => __spreadProps(__spreadValues({}, prev), {
999
- [scope]: {
1000
- methods: [],
1001
- notifications: [],
1002
- accounts: []
1003
- }
1004
- }),
1005
- {}
1006
- );
1007
- }
1008
- var extractFavicon = () => {
1009
- var _a;
1010
- if (typeof document === "undefined") {
1011
- return void 0;
1012
- }
1013
- let favicon;
1014
- const nodeList = document.getElementsByTagName("link");
1015
- for (let i = 0; i < nodeList.length; i++) {
1016
- if (nodeList[i].getAttribute("rel") === "icon" || nodeList[i].getAttribute("rel") === "shortcut icon") {
1017
- favicon = (_a = nodeList[i].getAttribute("href")) != null ? _a : void 0;
1018
- }
1019
- }
1020
- return favicon;
1021
- };
1022
- function setupDappMetadata(options) {
1023
- var _a;
1024
- const platform = getPlatformType();
1025
- const isBrowser = platform === "web-desktop" /* DesktopWeb */ || platform === "web-mobile" /* MobileWeb */ || platform === "in-app-browser" /* MetaMaskMobileWebview */;
1026
- if (!((_a = options.dapp) == null ? void 0 : _a.url)) {
1027
- if (isBrowser) {
1028
- options.dapp = __spreadProps(__spreadValues({}, options.dapp), {
1029
- url: `${window.location.protocol}//${window.location.host}`
1030
- });
1031
- } else {
1032
- throw new Error("You must provide dapp url");
1033
- }
1034
- }
1035
- const BASE_64_ICON_MAX_LENGTH = 163400;
1036
- const urlPattern = /^(http|https):\/\/[^\s]*$/;
1037
- if (options.dapp) {
1038
- if ("iconUrl" in options.dapp) {
1039
- if (options.dapp.iconUrl && !urlPattern.test(options.dapp.iconUrl)) {
1040
- console.warn(
1041
- "Invalid dappMetadata.iconUrl: URL must start with http:// or https://"
1042
- );
1043
- options.dapp.iconUrl = void 0;
1044
- }
1045
- }
1046
- if ("base64Icon" in options.dapp) {
1047
- if (options.dapp.base64Icon && options.dapp.base64Icon.length > BASE_64_ICON_MAX_LENGTH) {
1048
- console.warn(
1049
- "Invalid dappMetadata.base64Icon: Base64-encoded icon string length must be less than 163400 characters"
1050
- );
1051
- options.dapp.base64Icon = void 0;
1052
- }
1053
- }
1054
- if (options.dapp.url && !urlPattern.test(options.dapp.url)) {
1055
- console.warn(
1056
- "Invalid dappMetadata.url: URL must start with http:// or https://"
1057
- );
1058
- }
1059
- const favicon = extractFavicon();
1060
- if (favicon && !("iconUrl" in options.dapp) && !("base64Icon" in options.dapp)) {
1061
- const faviconUrl = `${window.location.protocol}//${window.location.host}${favicon}`;
1062
- options.dapp.iconUrl = faviconUrl;
1063
- }
1064
- }
1065
- return options;
1066
- }
1067
- function isSameScopesAndAccounts(currentScopes, proposedScopes, walletSession, proposedCaipAccountIds) {
1068
- const isSameScopes = currentScopes.every((scope) => proposedScopes.includes(scope)) && proposedScopes.every((scope) => currentScopes.includes(scope));
1069
- if (!isSameScopes) {
1070
- return false;
1071
- }
1072
- const existingAccountIds = Object.values(
1073
- walletSession.sessionScopes
1074
- ).filter(({ accounts }) => Boolean(accounts)).flatMap(({ accounts }) => accounts != null ? accounts : []);
1075
- const allProposedAccountsIncluded = proposedCaipAccountIds.every(
1076
- (proposedAccountId) => existingAccountIds.includes(proposedAccountId)
1077
- );
1078
- return allProposedAccountsIncluded;
1079
- }
1080
- function getValidAccounts(caipAccountIds) {
1081
- return caipAccountIds.reduce(
1082
- (caipAccounts, caipAccountId) => {
1083
- try {
1084
- return [...caipAccounts, parseCaipAccountId(caipAccountId)];
1085
- } catch (err) {
1086
- const stringifiedAccountId = JSON.stringify(caipAccountId);
1087
- console.error(`Invalid CAIP account ID: ${stringifiedAccountId}`, err);
1088
- return caipAccounts;
1089
- }
1090
- },
1091
- []
1092
- );
1093
- }
1094
- function addValidAccounts(optionalScopes, validAccounts) {
1095
- var _a;
1096
- if (!optionalScopes || !(validAccounts == null ? void 0 : validAccounts.length)) {
1097
- return optionalScopes;
1098
- }
1099
- const result = Object.fromEntries(
1100
- Object.entries(optionalScopes).map(([scope, scopeData]) => {
1101
- var _a2, _b, _c;
1102
- return [
1103
- scope,
1104
- {
1105
- methods: [...(_a2 = scopeData == null ? void 0 : scopeData.methods) != null ? _a2 : []],
1106
- notifications: [...(_b = scopeData == null ? void 0 : scopeData.notifications) != null ? _b : []],
1107
- accounts: [...(_c = scopeData == null ? void 0 : scopeData.accounts) != null ? _c : []]
1108
- }
1109
- ];
1110
- })
1111
- );
1112
- const accountsByChain = /* @__PURE__ */ new Map();
1113
- for (const account of validAccounts) {
1114
- const chainKey = `${account.chain.namespace}:${account.chain.reference}`;
1115
- const accountId = `${account.chainId}:${account.address}`;
1116
- if (!accountsByChain.has(chainKey)) {
1117
- accountsByChain.set(chainKey, []);
1118
- }
1119
- (_a = accountsByChain.get(chainKey)) == null ? void 0 : _a.push(accountId);
1120
- }
1121
- for (const [scopeKey, scopeData] of Object.entries(result)) {
1122
- if (!(scopeData == null ? void 0 : scopeData.accounts)) {
1123
- continue;
1124
- }
1125
- try {
1126
- const scope = scopeKey;
1127
- const scopeDetails = parseCaipChainId(scope);
1128
- const chainKey = `${scopeDetails.namespace}:${scopeDetails.reference}`;
1129
- const matchingAccounts = accountsByChain.get(chainKey);
1130
- if (matchingAccounts) {
1131
- const existingAccounts = new Set(scopeData.accounts);
1132
- const newAccounts = matchingAccounts.filter(
1133
- (account) => !existingAccounts.has(account)
1134
- );
1135
- scopeData.accounts.push(...newAccounts);
1136
- }
1137
- } catch (error) {
1138
- console.error(`Invalid scope format: ${scopeKey}`, error);
1139
- }
1140
- }
1141
- return result;
1142
- }
1143
-
1144
- // src/multichain/rpc/requestRouter.ts
1206
+ init_utils();
1207
+ init_analytics();
1208
+ var _RequestRouter_instances, withAnalyticsTracking_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, trackWalletActionRejected_fn;
1145
1209
  var RequestRouter = class {
1146
1210
  constructor(transport, rpcClient, config) {
1147
1211
  this.transport = transport;
1148
1212
  this.rpcClient = rpcClient;
1149
1213
  this.config = config;
1214
+ __privateAdd(this, _RequestRouter_instances);
1150
1215
  }
1151
1216
  /**
1152
1217
  * The main entry point for invoking an RPC method.
@@ -1170,7 +1235,7 @@ var RequestRouter = class {
1170
1235
  */
1171
1236
  handleWithWallet(options) {
1172
1237
  return __async(this, null, function* () {
1173
- try {
1238
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1174
1239
  const request = this.transport.request({
1175
1240
  method: "wallet_invokeMethod",
1176
1241
  params: options
@@ -1193,9 +1258,7 @@ var RequestRouter = class {
1193
1258
  throw new RPCInvokeMethodErr(`RPC Request failed with code ${response.error.code}: ${response.error.message}`);
1194
1259
  }
1195
1260
  return response.result;
1196
- } catch (error) {
1197
- throw new RPCInvokeMethodErr(error.message);
1198
- }
1261
+ }));
1199
1262
  });
1200
1263
  }
1201
1264
  /**
@@ -1203,14 +1266,16 @@ var RequestRouter = class {
1203
1266
  */
1204
1267
  handleWithRpcNode(options) {
1205
1268
  return __async(this, null, function* () {
1206
- try {
1207
- return yield this.rpcClient.request(options);
1208
- } catch (error) {
1209
- if (error instanceof MissingRpcEndpointErr) {
1210
- return this.handleWithWallet(options);
1269
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1270
+ try {
1271
+ return yield this.rpcClient.request(options);
1272
+ } catch (error) {
1273
+ if (error instanceof MissingRpcEndpointErr) {
1274
+ return this.handleWithWallet(options);
1275
+ }
1276
+ throw error;
1211
1277
  }
1212
- throw error;
1213
- }
1278
+ }));
1214
1279
  });
1215
1280
  }
1216
1281
  /**
@@ -1223,8 +1288,59 @@ var RequestRouter = class {
1223
1288
  });
1224
1289
  }
1225
1290
  };
1291
+ _RequestRouter_instances = new WeakSet();
1292
+ withAnalyticsTracking_fn = function(options, execute) {
1293
+ return __async(this, null, function* () {
1294
+ var _a, _b, _c;
1295
+ if ((_a = this.config.analytics) == null ? void 0 : _a.enabled) {
1296
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRequested_fn).call(this, options);
1297
+ }
1298
+ try {
1299
+ const result = yield execute();
1300
+ if ((_b = this.config.analytics) == null ? void 0 : _b.enabled) {
1301
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionSucceeded_fn).call(this, options);
1302
+ }
1303
+ return result;
1304
+ } catch (error) {
1305
+ if ((_c = this.config.analytics) == null ? void 0 : _c.enabled) {
1306
+ const isRejection = isRejectionError(error);
1307
+ if (isRejection) {
1308
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRejected_fn).call(this, options);
1309
+ } else {
1310
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options);
1311
+ }
1312
+ }
1313
+ throw new RPCInvokeMethodErr(error.message);
1314
+ }
1315
+ });
1316
+ };
1317
+ trackWalletActionRequested_fn = function(options) {
1318
+ return __async(this, null, function* () {
1319
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1320
+ analytics.track("mmconnect_wallet_action_requested", props);
1321
+ });
1322
+ };
1323
+ trackWalletActionSucceeded_fn = function(options) {
1324
+ return __async(this, null, function* () {
1325
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1326
+ analytics.track("mmconnect_wallet_action_succeeded", props);
1327
+ });
1328
+ };
1329
+ trackWalletActionFailed_fn = function(options) {
1330
+ return __async(this, null, function* () {
1331
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1332
+ analytics.track("mmconnect_wallet_action_failed", props);
1333
+ });
1334
+ };
1335
+ trackWalletActionRejected_fn = function(options) {
1336
+ return __async(this, null, function* () {
1337
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1338
+ analytics.track("mmconnect_wallet_action_rejected", props);
1339
+ });
1340
+ };
1226
1341
 
1227
1342
  // src/multichain/transports/default/index.ts
1343
+ init_utils();
1228
1344
  import {
1229
1345
  getDefaultTransport
1230
1346
  } from "@metamask/multichain-api-client";
@@ -1454,6 +1570,7 @@ setupMessageListener_fn = function() {
1454
1570
 
1455
1571
  // src/multichain/transports/mwp/index.ts
1456
1572
  init_domain();
1573
+ init_utils();
1457
1574
  import { SessionStore } from "@metamask/mobile-wallet-protocol-core";
1458
1575
  import {
1459
1576
  TransportTimeoutError
@@ -1931,20 +2048,22 @@ var KeyManager = class {
1931
2048
  var keymanager = new KeyManager();
1932
2049
 
1933
2050
  // src/multichain/index.ts
2051
+ init_utils();
1934
2052
  var logger2 = createLogger("metamask-sdk:core");
1935
2053
  var MultichainSDK = class _MultichainSDK extends MultichainCore {
1936
2054
  constructor(options) {
1937
- var _a, _b, _c, _d, _e, _f;
2055
+ var _a, _b, _c, _d, _e, _f, _g;
1938
2056
  const withDappMetadata = setupDappMetadata(options);
2057
+ const integrationType = ((_a = options.analytics) == null ? void 0 : _a.enabled) ? options.analytics.integrationType : "direct";
1939
2058
  const allOptions = __spreadProps(__spreadValues({}, withDappMetadata), {
1940
2059
  ui: __spreadProps(__spreadValues({}, withDappMetadata.ui), {
1941
- preferExtension: (_a = withDappMetadata.ui.preferExtension) != null ? _a : true,
1942
- showInstallModal: (_b = withDappMetadata.ui.showInstallModal) != null ? _b : false,
1943
- headless: (_c = withDappMetadata.ui.headless) != null ? _c : false
2060
+ preferExtension: (_b = withDappMetadata.ui.preferExtension) != null ? _b : true,
2061
+ showInstallModal: (_c = withDappMetadata.ui.showInstallModal) != null ? _c : false,
2062
+ headless: (_d = withDappMetadata.ui.headless) != null ? _d : false
1944
2063
  }),
1945
- analytics: __spreadProps(__spreadValues({}, (_d = options.analytics) != null ? _d : {}), {
1946
- enabled: (_f = (_e = options.analytics) == null ? void 0 : _e.enabled) != null ? _f : true,
1947
- integrationType: "unknown"
2064
+ analytics: __spreadProps(__spreadValues({}, (_e = options.analytics) != null ? _e : {}), {
2065
+ enabled: (_g = (_f = options.analytics) == null ? void 0 : _f.enabled) != null ? _g : true,
2066
+ integrationType
1948
2067
  })
1949
2068
  });
1950
2069
  super(allOptions);
@@ -2028,12 +2147,12 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2028
2147
  const { integrationType } = (_b = this.options.analytics) != null ? _b : {
2029
2148
  integrationType: ""
2030
2149
  };
2031
- analytics.setGlobalProperty("sdk_version", version);
2032
- analytics.setGlobalProperty("dapp_id", dappId);
2033
- analytics.setGlobalProperty("anon_id", anonId);
2034
- analytics.setGlobalProperty("platform", platform);
2035
- analytics.setGlobalProperty("integration_type", integrationType);
2036
- analytics.enable();
2150
+ analytics2.setGlobalProperty("mmconnect_version", version);
2151
+ analytics2.setGlobalProperty("dapp_id", dappId);
2152
+ analytics2.setGlobalProperty("anon_id", anonId);
2153
+ analytics2.setGlobalProperty("platform", platform);
2154
+ analytics2.setGlobalProperty("integration_type", integrationType);
2155
+ analytics2.enable();
2037
2156
  });
2038
2157
  }
2039
2158
  onTransportNotification(payload) {
@@ -2095,14 +2214,24 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2095
2214
  }
2096
2215
  init() {
2097
2216
  return __async(this, null, function* () {
2098
- var _a;
2217
+ var _a, _b;
2099
2218
  try {
2100
2219
  if (typeof window !== "undefined" && ((_a = window.mmsdk) == null ? void 0 : _a.isInitialized)) {
2101
2220
  logger2("MetaMaskSDK: init already initialized");
2102
2221
  } else {
2103
2222
  yield this.setupAnalytics();
2104
2223
  yield this.setupTransport();
2105
- analytics.track("sdk_initialized", {});
2224
+ if ((_b = this.options.analytics) == null ? void 0 : _b.enabled) {
2225
+ try {
2226
+ const baseProps = yield getBaseAnalyticsProperties(
2227
+ this.options,
2228
+ this.storage
2229
+ );
2230
+ analytics2.track("mmconnect_initialized", baseProps);
2231
+ } catch (error) {
2232
+ logger2("Error tracking initialized event", error);
2233
+ }
2234
+ }
2106
2235
  if (typeof window !== "undefined") {
2107
2236
  window.mmsdk = this;
2108
2237
  }
@@ -2281,17 +2410,6 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2281
2410
  }
2282
2411
  }
2283
2412
  );
2284
- } else {
2285
- timeout = setTimeout(() => {
2286
- var _a;
2287
- const deeplink = this.options.ui.factory.createDeeplink();
2288
- const universalLink = this.options.ui.factory.createUniversalLink();
2289
- if ((_a = this.options.mobile) == null ? void 0 : _a.preferredOpenLink) {
2290
- this.options.mobile.preferredOpenLink(deeplink, "_self");
2291
- } else {
2292
- openDeeplink(this.options, deeplink, universalLink);
2293
- }
2294
- }, 250);
2295
2413
  }
2296
2414
  this.transport.connect({ scopes, caipAccountIds }).then(resolve).catch((error) => {
2297
2415
  this.storage.removeTransport();
@@ -2304,27 +2422,87 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2304
2422
  }));
2305
2423
  });
2306
2424
  }
2307
- handleConnection(promise) {
2425
+ handleConnection(promise, scopes, transportType) {
2308
2426
  return __async(this, null, function* () {
2309
2427
  this.state = "connecting";
2310
- return promise.then(() => {
2428
+ return promise.then(() => __async(this, null, function* () {
2429
+ var _a;
2311
2430
  this.state = "connected";
2312
- }).catch((error) => {
2431
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2432
+ try {
2433
+ const baseProps = yield getBaseAnalyticsProperties(
2434
+ this.options,
2435
+ this.storage
2436
+ );
2437
+ analytics2.track("mmconnect_connection_established", __spreadProps(__spreadValues({}, baseProps), {
2438
+ transport_type: transportType,
2439
+ user_permissioned_chains: scopes
2440
+ }));
2441
+ } catch (error) {
2442
+ logger2("Error tracking connection_established event", error);
2443
+ }
2444
+ }
2445
+ })).catch((error) => __async(this, null, function* () {
2446
+ var _a;
2313
2447
  this.state = "disconnected";
2448
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2449
+ try {
2450
+ const baseProps = yield getBaseAnalyticsProperties(
2451
+ this.options,
2452
+ this.storage
2453
+ );
2454
+ const isRejection = isRejectionError(error);
2455
+ if (isRejection) {
2456
+ analytics2.track("mmconnect_connection_rejected", __spreadProps(__spreadValues({}, baseProps), {
2457
+ transport_type: transportType
2458
+ }));
2459
+ } else {
2460
+ analytics2.track("mmconnect_connection_failed", __spreadProps(__spreadValues({}, baseProps), {
2461
+ transport_type: transportType
2462
+ }));
2463
+ }
2464
+ } catch (e) {
2465
+ logger2("Error tracking connection failed/rejected event", error);
2466
+ }
2467
+ }
2314
2468
  return Promise.reject(error);
2315
- });
2469
+ }));
2316
2470
  });
2317
2471
  }
2318
2472
  connect(scopes, caipAccountIds, forceRequest) {
2319
2473
  return __async(this, null, function* () {
2320
- var _a;
2474
+ var _a, _b;
2321
2475
  const { ui } = this.options;
2322
2476
  const platformType = getPlatformType();
2323
2477
  const isWeb = platformType === "in-app-browser" /* MetaMaskMobileWebview */ || platformType === "web-desktop" /* DesktopWeb */;
2324
2478
  const { preferExtension = true, showInstallModal = false } = ui;
2325
2479
  const secure = isSecure();
2326
2480
  const hasExtensionInstalled = yield hasExtension();
2327
- if (((_a = this.__transport) == null ? void 0 : _a.isConnected()) && !secure) {
2481
+ let transportType;
2482
+ if (platformType === "in-app-browser" /* MetaMaskMobileWebview */ || isWeb && hasExtensionInstalled && preferExtension) {
2483
+ transportType = "browser" /* Browser */;
2484
+ } else {
2485
+ transportType = "mwp" /* MWP */;
2486
+ }
2487
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2488
+ try {
2489
+ const baseProps = yield getBaseAnalyticsProperties(
2490
+ this.options,
2491
+ this.storage
2492
+ );
2493
+ const dappConfiguredChains = Object.keys(
2494
+ this.options.api.supportedNetworks
2495
+ );
2496
+ analytics2.track("mmconnect_connection_initiated", __spreadProps(__spreadValues({}, baseProps), {
2497
+ transport_type: transportType,
2498
+ dapp_configured_chains: dappConfiguredChains,
2499
+ dapp_requested_chains: scopes
2500
+ }));
2501
+ } catch (error) {
2502
+ logger2("Error tracking connection_initiated event", error);
2503
+ }
2504
+ }
2505
+ if (((_b = this.__transport) == null ? void 0 : _b.isConnected()) && !secure) {
2328
2506
  return this.handleConnection(
2329
2507
  this.__transport.connect({ scopes, caipAccountIds, forceRequest }).then(() => {
2330
2508
  if (this.__transport instanceof MWPTransport) {
@@ -2332,30 +2510,40 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2332
2510
  } else {
2333
2511
  return this.storage.setTransport("browser" /* Browser */);
2334
2512
  }
2335
- })
2513
+ }),
2514
+ scopes,
2515
+ transportType
2336
2516
  );
2337
2517
  }
2338
2518
  if (platformType === "in-app-browser" /* MetaMaskMobileWebview */) {
2339
2519
  const defaultTransport = yield this.setupDefaultTransport();
2340
2520
  return this.handleConnection(
2341
- defaultTransport.connect({ scopes, caipAccountIds, forceRequest })
2521
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2522
+ scopes,
2523
+ transportType
2342
2524
  );
2343
2525
  }
2344
2526
  if (isWeb && hasExtensionInstalled && preferExtension) {
2345
2527
  const defaultTransport = yield this.setupDefaultTransport();
2346
2528
  return this.handleConnection(
2347
- defaultTransport.connect({ scopes, caipAccountIds, forceRequest })
2529
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2530
+ scopes,
2531
+ transportType
2348
2532
  );
2349
2533
  }
2350
2534
  yield this.setupMWP();
2351
2535
  const shouldShowInstallModal = hasExtensionInstalled ? showInstallModal : !preferExtension || showInstallModal;
2352
2536
  if (secure && !shouldShowInstallModal) {
2353
2537
  return this.handleConnection(
2354
- this.deeplinkConnect(scopes, caipAccountIds)
2538
+ this.deeplinkConnect(scopes, caipAccountIds),
2539
+ scopes,
2540
+ transportType
2355
2541
  );
2356
2542
  }
2357
2543
  return this.handleConnection(
2358
- this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds)
2544
+ this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds),
2545
+ scopes,
2546
+ transportType
2359
2547
  );
2360
2548
  });
2361
2549
  }
@@ -2608,6 +2796,7 @@ function preloadQR() {
2608
2796
  }
2609
2797
 
2610
2798
  // src/ui/index.ts
2799
+ init_utils();
2611
2800
  var __instance;
2612
2801
  function preload() {
2613
2802
  return __async(this, null, function* () {
@@ -2700,7 +2889,7 @@ var ModalFactory = class {
2700
2889
  }
2701
2890
  createDeeplink(connectionRequest) {
2702
2891
  if (!connectionRequest) {
2703
- return `${METAMASK_DEEPLINK_BASE}`;
2892
+ throw new Error("createDeeplink can only be called with a connection request");
2704
2893
  }
2705
2894
  const json = JSON.stringify(connectionRequest);
2706
2895
  const compressed = compressString(json);
@@ -2816,10 +3005,12 @@ export {
2816
3005
  getPlatformType,
2817
3006
  getTransportType,
2818
3007
  getVersion,
3008
+ getWalletActionAnalyticsProperties,
2819
3009
  hasExtension,
2820
3010
  infuraRpcUrls,
2821
3011
  isEnabled,
2822
3012
  isMetamaskExtensionInstalled,
3013
+ isRejectionError,
2823
3014
  isSecure
2824
3015
  };
2825
3016
  //# sourceMappingURL=connect-multichain.mjs.map