@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() {
@@ -922,7 +1174,7 @@ var init_web2 = __esm({
922
1174
  });
923
1175
 
924
1176
  // src/multichain/index.ts
925
- import { analytics } from "@metamask/analytics";
1177
+ import { analytics as analytics2 } from "@metamask/analytics";
926
1178
  import {
927
1179
  ErrorCode,
928
1180
  ProtocolError,
@@ -941,6 +1193,7 @@ var METAMASK_DEEPLINK_BASE = "metamask://connect";
941
1193
 
942
1194
  // src/multichain/index.ts
943
1195
  init_domain();
1196
+ init_analytics();
944
1197
  init_logger();
945
1198
  init_multichain();
946
1199
  init_platform();
@@ -1041,204 +1294,17 @@ var RpcClient = class {
1041
1294
  };
1042
1295
 
1043
1296
  // src/multichain/rpc/requestRouter.ts
1297
+ import { analytics } from "@metamask/analytics";
1044
1298
  init_domain();
1045
-
1046
- // src/multichain/utils/index.ts
1047
- init_domain();
1048
- import { deflate } from "pako";
1049
- import {
1050
- parseCaipAccountId,
1051
- parseCaipChainId
1052
- } from "@metamask/utils";
1053
- function base64Encode(str) {
1054
- if (typeof btoa !== "undefined") {
1055
- return btoa(str);
1056
- } else if (typeof Buffer !== "undefined") {
1057
- return Buffer.from(str).toString("base64");
1058
- }
1059
- throw new Error("No base64 encoding method available");
1060
- }
1061
- function compressString(str) {
1062
- const compressed = deflate(str);
1063
- const binaryString = String.fromCharCode.apply(null, Array.from(compressed));
1064
- return base64Encode(binaryString);
1065
- }
1066
- function getDappId(dapp) {
1067
- var _a, _b;
1068
- if (typeof window === "undefined" || typeof window.location === "undefined") {
1069
- return (_b = (_a = dapp == null ? void 0 : dapp.name) != null ? _a : dapp == null ? void 0 : dapp.url) != null ? _b : "N/A";
1070
- }
1071
- return window.location.hostname;
1072
- }
1073
- function openDeeplink(options, deeplink, universalLink) {
1074
- const { mobile } = options;
1075
- const useDeeplink = mobile && mobile.useDeeplink !== void 0 ? mobile.useDeeplink : true;
1076
- if (useDeeplink) {
1077
- if (typeof window !== "undefined") {
1078
- window.location.href = deeplink;
1079
- }
1080
- } else if (typeof document !== "undefined") {
1081
- const link = document.createElement("a");
1082
- link.href = universalLink;
1083
- link.target = "_self";
1084
- link.rel = "noreferrer noopener";
1085
- link.click();
1086
- }
1087
- }
1088
- function getOptionalScopes(scopes) {
1089
- return scopes.reduce(
1090
- (prev, scope) => __spreadProps(__spreadValues({}, prev), {
1091
- [scope]: {
1092
- methods: [],
1093
- notifications: [],
1094
- accounts: []
1095
- }
1096
- }),
1097
- {}
1098
- );
1099
- }
1100
- var extractFavicon = () => {
1101
- var _a;
1102
- if (typeof document === "undefined") {
1103
- return void 0;
1104
- }
1105
- let favicon;
1106
- const nodeList = document.getElementsByTagName("link");
1107
- for (let i = 0; i < nodeList.length; i++) {
1108
- if (nodeList[i].getAttribute("rel") === "icon" || nodeList[i].getAttribute("rel") === "shortcut icon") {
1109
- favicon = (_a = nodeList[i].getAttribute("href")) != null ? _a : void 0;
1110
- }
1111
- }
1112
- return favicon;
1113
- };
1114
- function setupDappMetadata(options) {
1115
- var _a;
1116
- const platform = getPlatformType();
1117
- const isBrowser = platform === "web-desktop" /* DesktopWeb */ || platform === "web-mobile" /* MobileWeb */ || platform === "in-app-browser" /* MetaMaskMobileWebview */;
1118
- if (!((_a = options.dapp) == null ? void 0 : _a.url)) {
1119
- if (isBrowser) {
1120
- options.dapp = __spreadProps(__spreadValues({}, options.dapp), {
1121
- url: `${window.location.protocol}//${window.location.host}`
1122
- });
1123
- } else {
1124
- throw new Error("You must provide dapp url");
1125
- }
1126
- }
1127
- const BASE_64_ICON_MAX_LENGTH = 163400;
1128
- const urlPattern = /^(http|https):\/\/[^\s]*$/;
1129
- if (options.dapp) {
1130
- if ("iconUrl" in options.dapp) {
1131
- if (options.dapp.iconUrl && !urlPattern.test(options.dapp.iconUrl)) {
1132
- console.warn(
1133
- "Invalid dappMetadata.iconUrl: URL must start with http:// or https://"
1134
- );
1135
- options.dapp.iconUrl = void 0;
1136
- }
1137
- }
1138
- if ("base64Icon" in options.dapp) {
1139
- if (options.dapp.base64Icon && options.dapp.base64Icon.length > BASE_64_ICON_MAX_LENGTH) {
1140
- console.warn(
1141
- "Invalid dappMetadata.base64Icon: Base64-encoded icon string length must be less than 163400 characters"
1142
- );
1143
- options.dapp.base64Icon = void 0;
1144
- }
1145
- }
1146
- if (options.dapp.url && !urlPattern.test(options.dapp.url)) {
1147
- console.warn(
1148
- "Invalid dappMetadata.url: URL must start with http:// or https://"
1149
- );
1150
- }
1151
- const favicon = extractFavicon();
1152
- if (favicon && !("iconUrl" in options.dapp) && !("base64Icon" in options.dapp)) {
1153
- const faviconUrl = `${window.location.protocol}//${window.location.host}${favicon}`;
1154
- options.dapp.iconUrl = faviconUrl;
1155
- }
1156
- }
1157
- return options;
1158
- }
1159
- function isSameScopesAndAccounts(currentScopes, proposedScopes, walletSession, proposedCaipAccountIds) {
1160
- const isSameScopes = currentScopes.every((scope) => proposedScopes.includes(scope)) && proposedScopes.every((scope) => currentScopes.includes(scope));
1161
- if (!isSameScopes) {
1162
- return false;
1163
- }
1164
- const existingAccountIds = Object.values(
1165
- walletSession.sessionScopes
1166
- ).filter(({ accounts }) => Boolean(accounts)).flatMap(({ accounts }) => accounts != null ? accounts : []);
1167
- const allProposedAccountsIncluded = proposedCaipAccountIds.every(
1168
- (proposedAccountId) => existingAccountIds.includes(proposedAccountId)
1169
- );
1170
- return allProposedAccountsIncluded;
1171
- }
1172
- function getValidAccounts(caipAccountIds) {
1173
- return caipAccountIds.reduce(
1174
- (caipAccounts, caipAccountId) => {
1175
- try {
1176
- return [...caipAccounts, parseCaipAccountId(caipAccountId)];
1177
- } catch (err) {
1178
- const stringifiedAccountId = JSON.stringify(caipAccountId);
1179
- console.error(`Invalid CAIP account ID: ${stringifiedAccountId}`, err);
1180
- return caipAccounts;
1181
- }
1182
- },
1183
- []
1184
- );
1185
- }
1186
- function addValidAccounts(optionalScopes, validAccounts) {
1187
- var _a;
1188
- if (!optionalScopes || !(validAccounts == null ? void 0 : validAccounts.length)) {
1189
- return optionalScopes;
1190
- }
1191
- const result = Object.fromEntries(
1192
- Object.entries(optionalScopes).map(([scope, scopeData]) => {
1193
- var _a2, _b, _c;
1194
- return [
1195
- scope,
1196
- {
1197
- methods: [...(_a2 = scopeData == null ? void 0 : scopeData.methods) != null ? _a2 : []],
1198
- notifications: [...(_b = scopeData == null ? void 0 : scopeData.notifications) != null ? _b : []],
1199
- accounts: [...(_c = scopeData == null ? void 0 : scopeData.accounts) != null ? _c : []]
1200
- }
1201
- ];
1202
- })
1203
- );
1204
- const accountsByChain = /* @__PURE__ */ new Map();
1205
- for (const account of validAccounts) {
1206
- const chainKey = `${account.chain.namespace}:${account.chain.reference}`;
1207
- const accountId = `${account.chainId}:${account.address}`;
1208
- if (!accountsByChain.has(chainKey)) {
1209
- accountsByChain.set(chainKey, []);
1210
- }
1211
- (_a = accountsByChain.get(chainKey)) == null ? void 0 : _a.push(accountId);
1212
- }
1213
- for (const [scopeKey, scopeData] of Object.entries(result)) {
1214
- if (!(scopeData == null ? void 0 : scopeData.accounts)) {
1215
- continue;
1216
- }
1217
- try {
1218
- const scope = scopeKey;
1219
- const scopeDetails = parseCaipChainId(scope);
1220
- const chainKey = `${scopeDetails.namespace}:${scopeDetails.reference}`;
1221
- const matchingAccounts = accountsByChain.get(chainKey);
1222
- if (matchingAccounts) {
1223
- const existingAccounts = new Set(scopeData.accounts);
1224
- const newAccounts = matchingAccounts.filter(
1225
- (account) => !existingAccounts.has(account)
1226
- );
1227
- scopeData.accounts.push(...newAccounts);
1228
- }
1229
- } catch (error) {
1230
- console.error(`Invalid scope format: ${scopeKey}`, error);
1231
- }
1232
- }
1233
- return result;
1234
- }
1235
-
1236
- // src/multichain/rpc/requestRouter.ts
1299
+ init_utils();
1300
+ init_analytics();
1301
+ var _RequestRouter_instances, withAnalyticsTracking_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, trackWalletActionRejected_fn;
1237
1302
  var RequestRouter = class {
1238
1303
  constructor(transport, rpcClient, config) {
1239
1304
  this.transport = transport;
1240
1305
  this.rpcClient = rpcClient;
1241
1306
  this.config = config;
1307
+ __privateAdd(this, _RequestRouter_instances);
1242
1308
  }
1243
1309
  /**
1244
1310
  * The main entry point for invoking an RPC method.
@@ -1262,7 +1328,7 @@ var RequestRouter = class {
1262
1328
  */
1263
1329
  handleWithWallet(options) {
1264
1330
  return __async(this, null, function* () {
1265
- try {
1331
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1266
1332
  const request = this.transport.request({
1267
1333
  method: "wallet_invokeMethod",
1268
1334
  params: options
@@ -1285,9 +1351,7 @@ var RequestRouter = class {
1285
1351
  throw new RPCInvokeMethodErr(`RPC Request failed with code ${response.error.code}: ${response.error.message}`);
1286
1352
  }
1287
1353
  return response.result;
1288
- } catch (error) {
1289
- throw new RPCInvokeMethodErr(error.message);
1290
- }
1354
+ }));
1291
1355
  });
1292
1356
  }
1293
1357
  /**
@@ -1295,14 +1359,16 @@ var RequestRouter = class {
1295
1359
  */
1296
1360
  handleWithRpcNode(options) {
1297
1361
  return __async(this, null, function* () {
1298
- try {
1299
- return yield this.rpcClient.request(options);
1300
- } catch (error) {
1301
- if (error instanceof MissingRpcEndpointErr) {
1302
- return this.handleWithWallet(options);
1362
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1363
+ try {
1364
+ return yield this.rpcClient.request(options);
1365
+ } catch (error) {
1366
+ if (error instanceof MissingRpcEndpointErr) {
1367
+ return this.handleWithWallet(options);
1368
+ }
1369
+ throw error;
1303
1370
  }
1304
- throw error;
1305
- }
1371
+ }));
1306
1372
  });
1307
1373
  }
1308
1374
  /**
@@ -1315,8 +1381,59 @@ var RequestRouter = class {
1315
1381
  });
1316
1382
  }
1317
1383
  };
1384
+ _RequestRouter_instances = new WeakSet();
1385
+ withAnalyticsTracking_fn = function(options, execute) {
1386
+ return __async(this, null, function* () {
1387
+ var _a, _b, _c;
1388
+ if ((_a = this.config.analytics) == null ? void 0 : _a.enabled) {
1389
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRequested_fn).call(this, options);
1390
+ }
1391
+ try {
1392
+ const result = yield execute();
1393
+ if ((_b = this.config.analytics) == null ? void 0 : _b.enabled) {
1394
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionSucceeded_fn).call(this, options);
1395
+ }
1396
+ return result;
1397
+ } catch (error) {
1398
+ if ((_c = this.config.analytics) == null ? void 0 : _c.enabled) {
1399
+ const isRejection = isRejectionError(error);
1400
+ if (isRejection) {
1401
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRejected_fn).call(this, options);
1402
+ } else {
1403
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options);
1404
+ }
1405
+ }
1406
+ throw new RPCInvokeMethodErr(error.message);
1407
+ }
1408
+ });
1409
+ };
1410
+ trackWalletActionRequested_fn = function(options) {
1411
+ return __async(this, null, function* () {
1412
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1413
+ analytics.track("mmconnect_wallet_action_requested", props);
1414
+ });
1415
+ };
1416
+ trackWalletActionSucceeded_fn = function(options) {
1417
+ return __async(this, null, function* () {
1418
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1419
+ analytics.track("mmconnect_wallet_action_succeeded", props);
1420
+ });
1421
+ };
1422
+ trackWalletActionFailed_fn = function(options) {
1423
+ return __async(this, null, function* () {
1424
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1425
+ analytics.track("mmconnect_wallet_action_failed", props);
1426
+ });
1427
+ };
1428
+ trackWalletActionRejected_fn = function(options) {
1429
+ return __async(this, null, function* () {
1430
+ const props = yield getWalletActionAnalyticsProperties(this.config, this.config.storage, options);
1431
+ analytics.track("mmconnect_wallet_action_rejected", props);
1432
+ });
1433
+ };
1318
1434
 
1319
1435
  // src/multichain/transports/default/index.ts
1436
+ init_utils();
1320
1437
  import {
1321
1438
  getDefaultTransport
1322
1439
  } from "@metamask/multichain-api-client";
@@ -1546,6 +1663,7 @@ setupMessageListener_fn = function() {
1546
1663
 
1547
1664
  // src/multichain/transports/mwp/index.ts
1548
1665
  init_domain();
1666
+ init_utils();
1549
1667
  import { SessionStore } from "@metamask/mobile-wallet-protocol-core";
1550
1668
  import {
1551
1669
  TransportTimeoutError
@@ -2023,20 +2141,22 @@ var KeyManager = class {
2023
2141
  var keymanager = new KeyManager();
2024
2142
 
2025
2143
  // src/multichain/index.ts
2144
+ init_utils();
2026
2145
  var logger2 = createLogger("metamask-sdk:core");
2027
2146
  var MultichainSDK = class _MultichainSDK extends MultichainCore {
2028
2147
  constructor(options) {
2029
- var _a, _b, _c, _d, _e, _f;
2148
+ var _a, _b, _c, _d, _e, _f, _g;
2030
2149
  const withDappMetadata = setupDappMetadata(options);
2150
+ const integrationType = ((_a = options.analytics) == null ? void 0 : _a.enabled) ? options.analytics.integrationType : "direct";
2031
2151
  const allOptions = __spreadProps(__spreadValues({}, withDappMetadata), {
2032
2152
  ui: __spreadProps(__spreadValues({}, withDappMetadata.ui), {
2033
- preferExtension: (_a = withDappMetadata.ui.preferExtension) != null ? _a : true,
2034
- showInstallModal: (_b = withDappMetadata.ui.showInstallModal) != null ? _b : false,
2035
- headless: (_c = withDappMetadata.ui.headless) != null ? _c : false
2153
+ preferExtension: (_b = withDappMetadata.ui.preferExtension) != null ? _b : true,
2154
+ showInstallModal: (_c = withDappMetadata.ui.showInstallModal) != null ? _c : false,
2155
+ headless: (_d = withDappMetadata.ui.headless) != null ? _d : false
2036
2156
  }),
2037
- analytics: __spreadProps(__spreadValues({}, (_d = options.analytics) != null ? _d : {}), {
2038
- enabled: (_f = (_e = options.analytics) == null ? void 0 : _e.enabled) != null ? _f : true,
2039
- integrationType: "unknown"
2157
+ analytics: __spreadProps(__spreadValues({}, (_e = options.analytics) != null ? _e : {}), {
2158
+ enabled: (_g = (_f = options.analytics) == null ? void 0 : _f.enabled) != null ? _g : true,
2159
+ integrationType
2040
2160
  })
2041
2161
  });
2042
2162
  super(allOptions);
@@ -2120,12 +2240,12 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2120
2240
  const { integrationType } = (_b = this.options.analytics) != null ? _b : {
2121
2241
  integrationType: ""
2122
2242
  };
2123
- analytics.setGlobalProperty("sdk_version", version);
2124
- analytics.setGlobalProperty("dapp_id", dappId);
2125
- analytics.setGlobalProperty("anon_id", anonId);
2126
- analytics.setGlobalProperty("platform", platform);
2127
- analytics.setGlobalProperty("integration_type", integrationType);
2128
- analytics.enable();
2243
+ analytics2.setGlobalProperty("mmconnect_version", version);
2244
+ analytics2.setGlobalProperty("dapp_id", dappId);
2245
+ analytics2.setGlobalProperty("anon_id", anonId);
2246
+ analytics2.setGlobalProperty("platform", platform);
2247
+ analytics2.setGlobalProperty("integration_type", integrationType);
2248
+ analytics2.enable();
2129
2249
  });
2130
2250
  }
2131
2251
  onTransportNotification(payload) {
@@ -2187,14 +2307,24 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2187
2307
  }
2188
2308
  init() {
2189
2309
  return __async(this, null, function* () {
2190
- var _a;
2310
+ var _a, _b;
2191
2311
  try {
2192
2312
  if (typeof window !== "undefined" && ((_a = window.mmsdk) == null ? void 0 : _a.isInitialized)) {
2193
2313
  logger2("MetaMaskSDK: init already initialized");
2194
2314
  } else {
2195
2315
  yield this.setupAnalytics();
2196
2316
  yield this.setupTransport();
2197
- analytics.track("sdk_initialized", {});
2317
+ if ((_b = this.options.analytics) == null ? void 0 : _b.enabled) {
2318
+ try {
2319
+ const baseProps = yield getBaseAnalyticsProperties(
2320
+ this.options,
2321
+ this.storage
2322
+ );
2323
+ analytics2.track("mmconnect_initialized", baseProps);
2324
+ } catch (error) {
2325
+ logger2("Error tracking initialized event", error);
2326
+ }
2327
+ }
2198
2328
  if (typeof window !== "undefined") {
2199
2329
  window.mmsdk = this;
2200
2330
  }
@@ -2396,27 +2526,87 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2396
2526
  }));
2397
2527
  });
2398
2528
  }
2399
- handleConnection(promise) {
2529
+ handleConnection(promise, scopes, transportType) {
2400
2530
  return __async(this, null, function* () {
2401
2531
  this.state = "connecting";
2402
- return promise.then(() => {
2532
+ return promise.then(() => __async(this, null, function* () {
2533
+ var _a;
2403
2534
  this.state = "connected";
2404
- }).catch((error) => {
2535
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2536
+ try {
2537
+ const baseProps = yield getBaseAnalyticsProperties(
2538
+ this.options,
2539
+ this.storage
2540
+ );
2541
+ analytics2.track("mmconnect_connection_established", __spreadProps(__spreadValues({}, baseProps), {
2542
+ transport_type: transportType,
2543
+ user_permissioned_chains: scopes
2544
+ }));
2545
+ } catch (error) {
2546
+ logger2("Error tracking connection_established event", error);
2547
+ }
2548
+ }
2549
+ })).catch((error) => __async(this, null, function* () {
2550
+ var _a;
2405
2551
  this.state = "disconnected";
2552
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2553
+ try {
2554
+ const baseProps = yield getBaseAnalyticsProperties(
2555
+ this.options,
2556
+ this.storage
2557
+ );
2558
+ const isRejection = isRejectionError(error);
2559
+ if (isRejection) {
2560
+ analytics2.track("mmconnect_connection_rejected", __spreadProps(__spreadValues({}, baseProps), {
2561
+ transport_type: transportType
2562
+ }));
2563
+ } else {
2564
+ analytics2.track("mmconnect_connection_failed", __spreadProps(__spreadValues({}, baseProps), {
2565
+ transport_type: transportType
2566
+ }));
2567
+ }
2568
+ } catch (e) {
2569
+ logger2("Error tracking connection failed/rejected event", error);
2570
+ }
2571
+ }
2406
2572
  return Promise.reject(error);
2407
- });
2573
+ }));
2408
2574
  });
2409
2575
  }
2410
2576
  connect(scopes, caipAccountIds, forceRequest) {
2411
2577
  return __async(this, null, function* () {
2412
- var _a;
2578
+ var _a, _b;
2413
2579
  const { ui } = this.options;
2414
2580
  const platformType = getPlatformType();
2415
2581
  const isWeb = platformType === "in-app-browser" /* MetaMaskMobileWebview */ || platformType === "web-desktop" /* DesktopWeb */;
2416
2582
  const { preferExtension = true, showInstallModal = false } = ui;
2417
2583
  const secure = isSecure();
2418
2584
  const hasExtensionInstalled = yield hasExtension();
2419
- if (((_a = this.__transport) == null ? void 0 : _a.isConnected()) && !secure) {
2585
+ let transportType;
2586
+ if (platformType === "in-app-browser" /* MetaMaskMobileWebview */ || isWeb && hasExtensionInstalled && preferExtension) {
2587
+ transportType = "browser" /* Browser */;
2588
+ } else {
2589
+ transportType = "mwp" /* MWP */;
2590
+ }
2591
+ if ((_a = this.options.analytics) == null ? void 0 : _a.enabled) {
2592
+ try {
2593
+ const baseProps = yield getBaseAnalyticsProperties(
2594
+ this.options,
2595
+ this.storage
2596
+ );
2597
+ const dappConfiguredChains = Object.keys(
2598
+ this.options.api.supportedNetworks
2599
+ );
2600
+ analytics2.track("mmconnect_connection_initiated", __spreadProps(__spreadValues({}, baseProps), {
2601
+ transport_type: transportType,
2602
+ dapp_configured_chains: dappConfiguredChains,
2603
+ dapp_requested_chains: scopes
2604
+ }));
2605
+ } catch (error) {
2606
+ logger2("Error tracking connection_initiated event", error);
2607
+ }
2608
+ }
2609
+ if (((_b = this.__transport) == null ? void 0 : _b.isConnected()) && !secure) {
2420
2610
  return this.handleConnection(
2421
2611
  this.__transport.connect({ scopes, caipAccountIds, forceRequest }).then(() => {
2422
2612
  if (this.__transport instanceof MWPTransport) {
@@ -2424,30 +2614,40 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2424
2614
  } else {
2425
2615
  return this.storage.setTransport("browser" /* Browser */);
2426
2616
  }
2427
- })
2617
+ }),
2618
+ scopes,
2619
+ transportType
2428
2620
  );
2429
2621
  }
2430
2622
  if (platformType === "in-app-browser" /* MetaMaskMobileWebview */) {
2431
2623
  const defaultTransport = yield this.setupDefaultTransport();
2432
2624
  return this.handleConnection(
2433
- defaultTransport.connect({ scopes, caipAccountIds, forceRequest })
2625
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2626
+ scopes,
2627
+ transportType
2434
2628
  );
2435
2629
  }
2436
2630
  if (isWeb && hasExtensionInstalled && preferExtension) {
2437
2631
  const defaultTransport = yield this.setupDefaultTransport();
2438
2632
  return this.handleConnection(
2439
- defaultTransport.connect({ scopes, caipAccountIds, forceRequest })
2633
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2634
+ scopes,
2635
+ transportType
2440
2636
  );
2441
2637
  }
2442
2638
  yield this.setupMWP();
2443
2639
  const shouldShowInstallModal = hasExtensionInstalled ? showInstallModal : !preferExtension || showInstallModal;
2444
2640
  if (secure && !shouldShowInstallModal) {
2445
2641
  return this.handleConnection(
2446
- this.deeplinkConnect(scopes, caipAccountIds)
2642
+ this.deeplinkConnect(scopes, caipAccountIds),
2643
+ scopes,
2644
+ transportType
2447
2645
  );
2448
2646
  }
2449
2647
  return this.handleConnection(
2450
- this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds)
2648
+ this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds),
2649
+ scopes,
2650
+ transportType
2451
2651
  );
2452
2652
  });
2453
2653
  }
@@ -2700,6 +2900,7 @@ function preloadQR() {
2700
2900
  }
2701
2901
 
2702
2902
  // src/ui/index.ts
2903
+ init_utils();
2703
2904
  var __instance;
2704
2905
  function preload() {
2705
2906
  return __async(this, null, function* () {
@@ -2908,10 +3109,12 @@ export {
2908
3109
  getPlatformType,
2909
3110
  getTransportType,
2910
3111
  getVersion,
3112
+ getWalletActionAnalyticsProperties,
2911
3113
  hasExtension,
2912
3114
  infuraRpcUrls,
2913
3115
  isEnabled,
2914
3116
  isMetamaskExtensionInstalled,
3117
+ isRejectionError,
2915
3118
  isSecure
2916
3119
  };
2917
3120
  //# sourceMappingURL=connect-multichain.mjs.map