@metamask/connect-multichain 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +8 -1
  2. package/dist/browser/es/connect-multichain.d.mts +25 -1
  3. package/dist/browser/es/connect-multichain.mjs +437 -234
  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 +25 -1
  7. package/dist/browser/iife/connect-multichain.js +21353 -14490
  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 +25 -1
  11. package/dist/browser/umd/connect-multichain.js +434 -231
  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 +25 -1
  15. package/dist/node/cjs/connect-multichain.js +437 -232
  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 +25 -1
  19. package/dist/node/es/connect-multichain.mjs +438 -235
  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 +25 -1
  23. package/dist/react-native/es/connect-multichain.mjs +437 -234
  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/utils/index.d.ts +1 -0
  27. package/dist/src/domain/utils/index.d.ts.map +1 -1
  28. package/dist/src/domain/utils/index.js +1 -0
  29. package/dist/src/domain/utils/index.js.map +1 -1
  30. package/dist/src/multichain/index.d.ts.map +1 -1
  31. package/dist/src/multichain/index.js +73 -17
  32. package/dist/src/multichain/index.js.map +1 -1
  33. package/dist/src/multichain/rpc/requestRouter.d.ts +1 -0
  34. package/dist/src/multichain/rpc/requestRouter.d.ts.map +1 -1
  35. package/dist/src/multichain/rpc/requestRouter.js +69 -13
  36. package/dist/src/multichain/rpc/requestRouter.js.map +1 -1
  37. package/dist/src/multichain/utils/analytics.d.ts +39 -0
  38. package/dist/src/multichain/utils/analytics.d.ts.map +1 -0
  39. package/dist/src/multichain/utils/analytics.js +83 -0
  40. package/dist/src/multichain/utils/analytics.js.map +1 -0
  41. package/dist/types/connect-multichain.d.ts +25 -1
  42. package/package.json +2 -2
@@ -583,13 +583,265 @@ 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, _b;
607
+ if (typeof window === "undefined" || typeof window.location === "undefined") {
608
+ return (_b = (_a = dapp == null ? void 0 : dapp.name) != null ? _a : dapp == null ? void 0 : dapp.url) != null ? _b : "N/A";
609
+ }
610
+ return window.location.hostname;
611
+ }
612
+ function openDeeplink(options, deeplink, universalLink) {
613
+ const { mobile } = options;
614
+ const useDeeplink = mobile && mobile.useDeeplink !== void 0 ? mobile.useDeeplink : true;
615
+ if (useDeeplink) {
616
+ if (typeof window !== "undefined") {
617
+ window.location.href = deeplink;
618
+ }
619
+ } else if (typeof document !== "undefined") {
620
+ const link = document.createElement("a");
621
+ link.href = universalLink;
622
+ link.target = "_self";
623
+ link.rel = "noreferrer noopener";
624
+ link.click();
625
+ }
626
+ }
627
+ function getOptionalScopes(scopes) {
628
+ return scopes.reduce(
629
+ (prev, scope) => __spreadProps(__spreadValues({}, prev), {
630
+ [scope]: {
631
+ methods: [],
632
+ notifications: [],
633
+ accounts: []
634
+ }
635
+ }),
636
+ {}
637
+ );
638
+ }
639
+ function setupDappMetadata(options) {
640
+ var _a;
641
+ const platform = getPlatformType();
642
+ const isBrowser = platform === "web-desktop" /* DesktopWeb */ || platform === "web-mobile" /* MobileWeb */ || platform === "in-app-browser" /* MetaMaskMobileWebview */;
643
+ if (!((_a = options.dapp) == null ? void 0 : _a.url)) {
644
+ if (isBrowser) {
645
+ options.dapp = __spreadProps(__spreadValues({}, options.dapp), {
646
+ url: `${window.location.protocol}//${window.location.host}`
647
+ });
648
+ } else {
649
+ throw new Error("You must provide dapp url");
650
+ }
651
+ }
652
+ const BASE_64_ICON_MAX_LENGTH = 163400;
653
+ const urlPattern = /^(http|https):\/\/[^\s]*$/;
654
+ if (options.dapp) {
655
+ if ("iconUrl" in options.dapp) {
656
+ if (options.dapp.iconUrl && !urlPattern.test(options.dapp.iconUrl)) {
657
+ console.warn(
658
+ "Invalid dappMetadata.iconUrl: URL must start with http:// or https://"
659
+ );
660
+ options.dapp.iconUrl = void 0;
661
+ }
662
+ }
663
+ if ("base64Icon" in options.dapp) {
664
+ if (options.dapp.base64Icon && options.dapp.base64Icon.length > BASE_64_ICON_MAX_LENGTH) {
665
+ console.warn(
666
+ "Invalid dappMetadata.base64Icon: Base64-encoded icon string length must be less than 163400 characters"
667
+ );
668
+ options.dapp.base64Icon = void 0;
669
+ }
670
+ }
671
+ if (options.dapp.url && !urlPattern.test(options.dapp.url)) {
672
+ console.warn(
673
+ "Invalid dappMetadata.url: URL must start with http:// or https://"
674
+ );
675
+ }
676
+ const favicon = extractFavicon();
677
+ if (favicon && !("iconUrl" in options.dapp) && !("base64Icon" in options.dapp)) {
678
+ const faviconUrl = `${window.location.protocol}//${window.location.host}${favicon}`;
679
+ options.dapp.iconUrl = faviconUrl;
680
+ }
681
+ }
682
+ return options;
683
+ }
684
+ function isSameScopesAndAccounts(currentScopes, proposedScopes, walletSession, proposedCaipAccountIds) {
685
+ const isSameScopes = currentScopes.every((scope) => proposedScopes.includes(scope)) && proposedScopes.every((scope) => currentScopes.includes(scope));
686
+ if (!isSameScopes) {
687
+ return false;
688
+ }
689
+ const existingAccountIds = Object.values(
690
+ walletSession.sessionScopes
691
+ ).filter(({ accounts }) => Boolean(accounts)).flatMap(({ accounts }) => accounts != null ? accounts : []);
692
+ const allProposedAccountsIncluded = proposedCaipAccountIds.every(
693
+ (proposedAccountId) => existingAccountIds.includes(proposedAccountId)
694
+ );
695
+ return allProposedAccountsIncluded;
696
+ }
697
+ function getValidAccounts(caipAccountIds) {
698
+ return caipAccountIds.reduce(
699
+ (caipAccounts, caipAccountId) => {
700
+ try {
701
+ return [...caipAccounts, parseCaipAccountId(caipAccountId)];
702
+ } catch (err) {
703
+ const stringifiedAccountId = JSON.stringify(caipAccountId);
704
+ console.error(`Invalid CAIP account ID: ${stringifiedAccountId}`, err);
705
+ return caipAccounts;
706
+ }
707
+ },
708
+ []
709
+ );
710
+ }
711
+ function addValidAccounts(optionalScopes, validAccounts) {
712
+ var _a;
713
+ if (!optionalScopes || !(validAccounts == null ? void 0 : validAccounts.length)) {
714
+ return optionalScopes;
715
+ }
716
+ const result = Object.fromEntries(
717
+ Object.entries(optionalScopes).map(([scope, scopeData]) => {
718
+ var _a2, _b, _c;
719
+ return [
720
+ scope,
721
+ {
722
+ methods: [...(_a2 = scopeData == null ? void 0 : scopeData.methods) != null ? _a2 : []],
723
+ notifications: [...(_b = scopeData == null ? void 0 : scopeData.notifications) != null ? _b : []],
724
+ accounts: [...(_c = scopeData == null ? void 0 : scopeData.accounts) != null ? _c : []]
725
+ }
726
+ ];
727
+ })
728
+ );
729
+ const accountsByChain = /* @__PURE__ */ new Map();
730
+ for (const account of validAccounts) {
731
+ const chainKey = `${account.chain.namespace}:${account.chain.reference}`;
732
+ const accountId = `${account.chainId}:${account.address}`;
733
+ if (!accountsByChain.has(chainKey)) {
734
+ accountsByChain.set(chainKey, []);
735
+ }
736
+ (_a = accountsByChain.get(chainKey)) == null ? void 0 : _a.push(accountId);
737
+ }
738
+ for (const [scopeKey, scopeData] of Object.entries(result)) {
739
+ if (!(scopeData == null ? void 0 : scopeData.accounts)) {
740
+ continue;
741
+ }
742
+ try {
743
+ const scope = scopeKey;
744
+ const scopeDetails = parseCaipChainId(scope);
745
+ const chainKey = `${scopeDetails.namespace}:${scopeDetails.reference}`;
746
+ const matchingAccounts = accountsByChain.get(chainKey);
747
+ if (matchingAccounts) {
748
+ const existingAccounts = new Set(scopeData.accounts);
749
+ const newAccounts = matchingAccounts.filter(
750
+ (account) => !existingAccounts.has(account)
751
+ );
752
+ scopeData.accounts.push(...newAccounts);
753
+ }
754
+ } catch (error) {
755
+ console.error(`Invalid scope format: ${scopeKey}`, error);
756
+ }
757
+ }
758
+ return result;
759
+ }
760
+ var extractFavicon;
761
+ var init_utils = __esm({
762
+ "src/multichain/utils/index.ts"() {
763
+ "use strict";
764
+ init_domain();
765
+ extractFavicon = () => {
766
+ var _a;
767
+ if (typeof document === "undefined") {
768
+ return void 0;
769
+ }
770
+ let favicon;
771
+ const nodeList = document.getElementsByTagName("link");
772
+ for (let i = 0; i < nodeList.length; i++) {
773
+ if (nodeList[i].getAttribute("rel") === "icon" || nodeList[i].getAttribute("rel") === "shortcut icon") {
774
+ favicon = (_a = nodeList[i].getAttribute("href")) != null ? _a : void 0;
775
+ }
776
+ }
777
+ return favicon;
778
+ };
779
+ }
780
+ });
781
+
782
+ // src/multichain/utils/analytics.ts
783
+ function isRejectionError(error) {
784
+ var _a, _b;
785
+ if (typeof error !== "object" || error === null) {
786
+ return false;
787
+ }
788
+ const errorObj = error;
789
+ const errorCode = errorObj.code;
790
+ const errorMessage = (_b = (_a = errorObj.message) == null ? void 0 : _a.toLowerCase()) != null ? _b : "";
791
+ return errorCode === 4001 || // User rejected request (common EIP-1193 code)
792
+ errorCode === 4100 || // Unauthorized (common rejection code)
793
+ errorMessage.includes("reject") || errorMessage.includes("denied") || errorMessage.includes("cancel") || errorMessage.includes("user");
794
+ }
795
+ function getBaseAnalyticsProperties(options, storage) {
796
+ return __async(this, null, function* () {
797
+ var _a, _b;
798
+ const version = getVersion();
799
+ const dappId = getDappId(options.dapp);
800
+ const platform = getPlatformType();
801
+ const anonId = yield storage.getAnonId();
802
+ const integrationType = (_b = (_a = options.analytics) == null ? void 0 : _a.integrationType) != null ? _b : "unknown" /* UNKNOWN */;
803
+ return {
804
+ mmconnect_version: version,
805
+ dapp_id: dappId,
806
+ platform,
807
+ integration_type: integrationType,
808
+ anon_id: anonId
809
+ };
810
+ });
811
+ }
812
+ function getWalletActionAnalyticsProperties(options, storage, invokeOptions) {
813
+ return __async(this, null, function* () {
814
+ var _a, _b;
815
+ const version = getVersion();
816
+ const dappId = getDappId(options.dapp);
817
+ const anonId = yield storage.getAnonId();
818
+ const integrationType = (_b = (_a = options.analytics) == null ? void 0 : _a.integrationType) != null ? _b : "unknown";
819
+ return {
820
+ mmconnect_version: version,
821
+ dapp_id: dappId,
822
+ method: invokeOptions.request.method,
823
+ integration_type: integrationType,
824
+ caip_chain_id: invokeOptions.scope,
825
+ anon_id: anonId
826
+ };
827
+ });
828
+ }
829
+ var init_analytics = __esm({
830
+ "src/multichain/utils/analytics.ts"() {
831
+ "use strict";
832
+ init_utils();
833
+ init_domain();
834
+ }
835
+ });
836
+
586
837
  // src/domain/utils/index.ts
587
838
  function getVersion() {
588
839
  return "0.0.0";
589
840
  }
590
- var init_utils = __esm({
841
+ var init_utils2 = __esm({
591
842
  "src/domain/utils/index.ts"() {
592
843
  "use strict";
844
+ init_analytics();
593
845
  }
594
846
  });
595
847
 
@@ -604,7 +856,7 @@ var init_domain = __esm({
604
856
  init_platform();
605
857
  init_store();
606
858
  init_ui();
607
- init_utils();
859
+ init_utils2();
608
860
  }
609
861
  });
610
862
 
@@ -627,7 +879,7 @@ function shouldLogCountdown(remainingSeconds) {
627
879
  return remainingSeconds % 60 === 0;
628
880
  }
629
881
  }
630
- var init_utils2 = __esm({
882
+ var init_utils3 = __esm({
631
883
  "src/ui/modals/base/utils.ts"() {
632
884
  "use strict";
633
885
  }
@@ -639,7 +891,7 @@ var init_AbstractInstallModal = __esm({
639
891
  "src/ui/modals/base/AbstractInstallModal.ts"() {
640
892
  "use strict";
641
893
  init_domain();
642
- init_utils2();
894
+ init_utils3();
643
895
  logger3 = createLogger("metamask-sdk:ui");
644
896
  AbstractInstallModal = class extends Modal {
645
897
  constructor() {
@@ -830,7 +1082,7 @@ var init_rn2 = __esm({
830
1082
  });
831
1083
 
832
1084
  // src/multichain/index.ts
833
- import { analytics } from "@metamask/analytics";
1085
+ import { analytics as analytics2 } from "@metamask/analytics";
834
1086
  import {
835
1087
  ErrorCode,
836
1088
  ProtocolError,
@@ -849,6 +1101,7 @@ var METAMASK_DEEPLINK_BASE = "metamask://connect";
849
1101
 
850
1102
  // src/multichain/index.ts
851
1103
  init_domain();
1104
+ init_analytics();
852
1105
  init_logger();
853
1106
  init_multichain();
854
1107
  init_platform();
@@ -949,204 +1202,17 @@ var RpcClient = class {
949
1202
  };
950
1203
 
951
1204
  // src/multichain/rpc/requestRouter.ts
1205
+ import { analytics } from "@metamask/analytics";
952
1206
  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
1207
+ init_utils();
1208
+ init_analytics();
1209
+ var _RequestRouter_instances, withAnalyticsTracking_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, trackWalletActionRejected_fn;
1145
1210
  var RequestRouter = class {
1146
1211
  constructor(transport, rpcClient, config) {
1147
1212
  this.transport = transport;
1148
1213
  this.rpcClient = rpcClient;
1149
1214
  this.config = config;
1215
+ __privateAdd(this, _RequestRouter_instances);
1150
1216
  }
1151
1217
  /**
1152
1218
  * The main entry point for invoking an RPC method.
@@ -1170,7 +1236,7 @@ var RequestRouter = class {
1170
1236
  */
1171
1237
  handleWithWallet(options) {
1172
1238
  return __async(this, null, function* () {
1173
- try {
1239
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1174
1240
  const request = this.transport.request({
1175
1241
  method: "wallet_invokeMethod",
1176
1242
  params: options
@@ -1193,9 +1259,7 @@ var RequestRouter = class {
1193
1259
  throw new RPCInvokeMethodErr(`RPC Request failed with code ${response.error.code}: ${response.error.message}`);
1194
1260
  }
1195
1261
  return response.result;
1196
- } catch (error) {
1197
- throw new RPCInvokeMethodErr(error.message);
1198
- }
1262
+ }));
1199
1263
  });
1200
1264
  }
1201
1265
  /**
@@ -1203,14 +1267,16 @@ var RequestRouter = class {
1203
1267
  */
1204
1268
  handleWithRpcNode(options) {
1205
1269
  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);
1270
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1271
+ try {
1272
+ return yield this.rpcClient.request(options);
1273
+ } catch (error) {
1274
+ if (error instanceof MissingRpcEndpointErr) {
1275
+ return this.handleWithWallet(options);
1276
+ }
1277
+ throw error;
1211
1278
  }
1212
- throw error;
1213
- }
1279
+ }));
1214
1280
  });
1215
1281
  }
1216
1282
  /**
@@ -1223,8 +1289,59 @@ var RequestRouter = class {
1223
1289
  });
1224
1290
  }
1225
1291
  };
1292
+ _RequestRouter_instances = new WeakSet();
1293
+ withAnalyticsTracking_fn = function(options, execute) {
1294
+ return __async(this, null, function* () {
1295
+ var _a, _b, _c;
1296
+ if ((_a = this.config.analytics) == null ? void 0 : _a.enabled) {
1297
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRequested_fn).call(this, options);
1298
+ }
1299
+ try {
1300
+ const result = yield execute();
1301
+ if ((_b = this.config.analytics) == null ? void 0 : _b.enabled) {
1302
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionSucceeded_fn).call(this, options);
1303
+ }
1304
+ return result;
1305
+ } catch (error) {
1306
+ if ((_c = this.config.analytics) == null ? void 0 : _c.enabled) {
1307
+ const isRejection = isRejectionError(error);
1308
+ if (isRejection) {
1309
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRejected_fn).call(this, options);
1310
+ } else {
1311
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options);
1312
+ }
1313
+ }
1314
+ throw new RPCInvokeMethodErr(error.message);
1315
+ }
1316
+ });
1317
+ };
1318
+ trackWalletActionRequested_fn = function(options) {
1319
+ return __async(this, null, function* () {
1320
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1321
+ analytics.track("mmconnect_wallet_action_requested", props);
1322
+ });
1323
+ };
1324
+ trackWalletActionSucceeded_fn = function(options) {
1325
+ return __async(this, null, function* () {
1326
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1327
+ analytics.track("mmconnect_wallet_action_succeeded", props);
1328
+ });
1329
+ };
1330
+ trackWalletActionFailed_fn = function(options) {
1331
+ return __async(this, null, function* () {
1332
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1333
+ analytics.track("mmconnect_wallet_action_failed", props);
1334
+ });
1335
+ };
1336
+ trackWalletActionRejected_fn = function(options) {
1337
+ return __async(this, null, function* () {
1338
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1339
+ analytics.track("mmconnect_wallet_action_rejected", props);
1340
+ });
1341
+ };
1226
1342
 
1227
1343
  // src/multichain/transports/default/index.ts
1344
+ init_utils();
1228
1345
  import {
1229
1346
  getDefaultTransport
1230
1347
  } from "@metamask/multichain-api-client";
@@ -1454,6 +1571,7 @@ setupMessageListener_fn = function() {
1454
1571
 
1455
1572
  // src/multichain/transports/mwp/index.ts
1456
1573
  init_domain();
1574
+ init_utils();
1457
1575
  import { SessionStore } from "@metamask/mobile-wallet-protocol-core";
1458
1576
  import {
1459
1577
  TransportTimeoutError
@@ -1931,20 +2049,22 @@ var KeyManager = class {
1931
2049
  var keymanager = new KeyManager();
1932
2050
 
1933
2051
  // src/multichain/index.ts
2052
+ init_utils();
1934
2053
  var logger2 = createLogger("metamask-sdk:core");
1935
2054
  var MultichainSDK = class _MultichainSDK extends MultichainCore {
1936
2055
  constructor(options) {
1937
- var _a, _b, _c, _d, _e, _f;
2056
+ var _a, _b, _c, _d, _e, _f, _g;
1938
2057
  const withDappMetadata = setupDappMetadata(options);
2058
+ const integrationType = ((_a = options.analytics) == null ? void 0 : _a.enabled) ? options.analytics.integrationType : "direct";
1939
2059
  const allOptions = __spreadProps(__spreadValues({}, withDappMetadata), {
1940
2060
  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
2061
+ preferExtension: (_b = withDappMetadata.ui.preferExtension) != null ? _b : true,
2062
+ showInstallModal: (_c = withDappMetadata.ui.showInstallModal) != null ? _c : false,
2063
+ headless: (_d = withDappMetadata.ui.headless) != null ? _d : false
1944
2064
  }),
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"
2065
+ analytics: __spreadProps(__spreadValues({}, (_e = options.analytics) != null ? _e : {}), {
2066
+ enabled: (_g = (_f = options.analytics) == null ? void 0 : _f.enabled) != null ? _g : true,
2067
+ integrationType
1948
2068
  })
1949
2069
  });
1950
2070
  super(allOptions);
@@ -2028,12 +2148,12 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2028
2148
  const { integrationType } = (_b = this.options.analytics) != null ? _b : {
2029
2149
  integrationType: ""
2030
2150
  };
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();
2151
+ analytics2.setGlobalProperty("mmconnect_version", version);
2152
+ analytics2.setGlobalProperty("dapp_id", dappId);
2153
+ analytics2.setGlobalProperty("anon_id", anonId);
2154
+ analytics2.setGlobalProperty("platform", platform);
2155
+ analytics2.setGlobalProperty("integration_type", integrationType);
2156
+ analytics2.enable();
2037
2157
  });
2038
2158
  }
2039
2159
  onTransportNotification(payload) {
@@ -2095,14 +2215,24 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2095
2215
  }
2096
2216
  init() {
2097
2217
  return __async(this, null, function* () {
2098
- var _a;
2218
+ var _a, _b;
2099
2219
  try {
2100
2220
  if (typeof window !== "undefined" && ((_a = window.mmsdk) == null ? void 0 : _a.isInitialized)) {
2101
2221
  logger2("MetaMaskSDK: init already initialized");
2102
2222
  } else {
2103
2223
  yield this.setupAnalytics();
2104
2224
  yield this.setupTransport();
2105
- analytics.track("sdk_initialized", {});
2225
+ if ((_b = this.options.analytics) == null ? void 0 : _b.enabled) {
2226
+ try {
2227
+ const baseProps = yield getBaseAnalyticsProperties(
2228
+ this.options,
2229
+ this.storage
2230
+ );
2231
+ analytics2.track("mmconnect_initialized", baseProps);
2232
+ } catch (error) {
2233
+ logger2("Error tracking initialized event", error);
2234
+ }
2235
+ }
2106
2236
  if (typeof window !== "undefined") {
2107
2237
  window.mmsdk = this;
2108
2238
  }
@@ -2304,27 +2434,87 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2304
2434
  }));
2305
2435
  });
2306
2436
  }
2307
- handleConnection(promise) {
2437
+ handleConnection(promise, scopes, transportType) {
2308
2438
  return __async(this, null, function* () {
2309
2439
  this.state = "connecting";
2310
- return promise.then(() => {
2440
+ return promise.then(() => __async(this, null, function* () {
2441
+ var _a;
2311
2442
  this.state = "connected";
2312
- }).catch((error) => {
2443
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2444
+ try {
2445
+ const baseProps = yield getBaseAnalyticsProperties(
2446
+ this.options,
2447
+ this.storage
2448
+ );
2449
+ analytics2.track("mmconnect_connection_established", __spreadProps(__spreadValues({}, baseProps), {
2450
+ transport_type: transportType,
2451
+ user_permissioned_chains: scopes
2452
+ }));
2453
+ } catch (error) {
2454
+ logger2("Error tracking connection_established event", error);
2455
+ }
2456
+ }
2457
+ })).catch((error) => __async(this, null, function* () {
2458
+ var _a;
2313
2459
  this.state = "disconnected";
2460
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2461
+ try {
2462
+ const baseProps = yield getBaseAnalyticsProperties(
2463
+ this.options,
2464
+ this.storage
2465
+ );
2466
+ const isRejection = isRejectionError(error);
2467
+ if (isRejection) {
2468
+ analytics2.track("mmconnect_connection_rejected", __spreadProps(__spreadValues({}, baseProps), {
2469
+ transport_type: transportType
2470
+ }));
2471
+ } else {
2472
+ analytics2.track("mmconnect_connection_failed", __spreadProps(__spreadValues({}, baseProps), {
2473
+ transport_type: transportType
2474
+ }));
2475
+ }
2476
+ } catch (e) {
2477
+ logger2("Error tracking connection failed/rejected event", error);
2478
+ }
2479
+ }
2314
2480
  return Promise.reject(error);
2315
- });
2481
+ }));
2316
2482
  });
2317
2483
  }
2318
2484
  connect(scopes, caipAccountIds, forceRequest) {
2319
2485
  return __async(this, null, function* () {
2320
- var _a;
2486
+ var _a, _b;
2321
2487
  const { ui } = this.options;
2322
2488
  const platformType = getPlatformType();
2323
2489
  const isWeb = platformType === "in-app-browser" /* MetaMaskMobileWebview */ || platformType === "web-desktop" /* DesktopWeb */;
2324
2490
  const { preferExtension = true, showInstallModal = false } = ui;
2325
2491
  const secure = isSecure();
2326
2492
  const hasExtensionInstalled = yield hasExtension();
2327
- if (((_a = this.__transport) == null ? void 0 : _a.isConnected()) && !secure) {
2493
+ let transportType;
2494
+ if (platformType === "in-app-browser" /* MetaMaskMobileWebview */ || isWeb && hasExtensionInstalled && preferExtension) {
2495
+ transportType = "browser" /* Browser */;
2496
+ } else {
2497
+ transportType = "mwp" /* MWP */;
2498
+ }
2499
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2500
+ try {
2501
+ const baseProps = yield getBaseAnalyticsProperties(
2502
+ this.options,
2503
+ this.storage
2504
+ );
2505
+ const dappConfiguredChains = Object.keys(
2506
+ this.options.api.supportedNetworks
2507
+ );
2508
+ analytics2.track("mmconnect_connection_initiated", __spreadProps(__spreadValues({}, baseProps), {
2509
+ transport_type: transportType,
2510
+ dapp_configured_chains: dappConfiguredChains,
2511
+ dapp_requested_chains: scopes
2512
+ }));
2513
+ } catch (error) {
2514
+ logger2("Error tracking connection_initiated event", error);
2515
+ }
2516
+ }
2517
+ if (((_b = this.__transport) == null ? void 0 : _b.isConnected()) && !secure) {
2328
2518
  return this.handleConnection(
2329
2519
  this.__transport.connect({ scopes, caipAccountIds, forceRequest }).then(() => {
2330
2520
  if (this.__transport instanceof MWPTransport) {
@@ -2332,30 +2522,40 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2332
2522
  } else {
2333
2523
  return this.storage.setTransport("browser" /* Browser */);
2334
2524
  }
2335
- })
2525
+ }),
2526
+ scopes,
2527
+ transportType
2336
2528
  );
2337
2529
  }
2338
2530
  if (platformType === "in-app-browser" /* MetaMaskMobileWebview */) {
2339
2531
  const defaultTransport = yield this.setupDefaultTransport();
2340
2532
  return this.handleConnection(
2341
- defaultTransport.connect({ scopes, caipAccountIds, forceRequest })
2533
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2534
+ scopes,
2535
+ transportType
2342
2536
  );
2343
2537
  }
2344
2538
  if (isWeb && hasExtensionInstalled && preferExtension) {
2345
2539
  const defaultTransport = yield this.setupDefaultTransport();
2346
2540
  return this.handleConnection(
2347
- defaultTransport.connect({ scopes, caipAccountIds, forceRequest })
2541
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2542
+ scopes,
2543
+ transportType
2348
2544
  );
2349
2545
  }
2350
2546
  yield this.setupMWP();
2351
2547
  const shouldShowInstallModal = hasExtensionInstalled ? showInstallModal : !preferExtension || showInstallModal;
2352
2548
  if (secure && !shouldShowInstallModal) {
2353
2549
  return this.handleConnection(
2354
- this.deeplinkConnect(scopes, caipAccountIds)
2550
+ this.deeplinkConnect(scopes, caipAccountIds),
2551
+ scopes,
2552
+ transportType
2355
2553
  );
2356
2554
  }
2357
2555
  return this.handleConnection(
2358
- this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds)
2556
+ this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds),
2557
+ scopes,
2558
+ transportType
2359
2559
  );
2360
2560
  });
2361
2561
  }
@@ -2608,6 +2808,7 @@ function preloadQR() {
2608
2808
  }
2609
2809
 
2610
2810
  // src/ui/index.ts
2811
+ init_utils();
2611
2812
  var __instance;
2612
2813
  function preload() {
2613
2814
  return __async(this, null, function* () {
@@ -2816,10 +3017,12 @@ export {
2816
3017
  getPlatformType,
2817
3018
  getTransportType,
2818
3019
  getVersion,
3020
+ getWalletActionAnalyticsProperties,
2819
3021
  hasExtension,
2820
3022
  infuraRpcUrls,
2821
3023
  isEnabled,
2822
3024
  isMetamaskExtensionInstalled,
3025
+ isRejectionError,
2823
3026
  isSecure
2824
3027
  };
2825
3028
  //# sourceMappingURL=connect-multichain.mjs.map