@metamask/connect-multichain 0.1.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 (83) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/dist/browser/es/connect-multichain.d.mts +67 -13
  3. package/dist/browser/es/connect-multichain.mjs +895 -384
  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 +67 -13
  7. package/dist/browser/iife/connect-multichain.js +21636 -14459
  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 +67 -13
  11. package/dist/browser/umd/connect-multichain.js +893 -382
  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 +67 -13
  15. package/dist/node/cjs/connect-multichain.js +898 -385
  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 +67 -13
  19. package/dist/node/es/connect-multichain.mjs +898 -387
  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 +67 -13
  23. package/dist/react-native/es/connect-multichain.mjs +897 -386
  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/events/index.d.ts +26 -0
  27. package/dist/src/domain/events/index.d.ts.map +1 -1
  28. package/dist/src/domain/events/index.js +35 -0
  29. package/dist/src/domain/events/index.js.map +1 -1
  30. package/dist/src/domain/multichain/index.d.ts +7 -5
  31. package/dist/src/domain/multichain/index.d.ts.map +1 -1
  32. package/dist/src/domain/multichain/index.js +2 -2
  33. package/dist/src/domain/multichain/index.js.map +1 -1
  34. package/dist/src/domain/multichain/types.d.ts +9 -7
  35. package/dist/src/domain/multichain/types.d.ts.map +1 -1
  36. package/dist/src/domain/platform/index.js +3 -3
  37. package/dist/src/domain/platform/index.js.map +1 -1
  38. package/dist/src/domain/ui/factory.d.ts +1 -1
  39. package/dist/src/domain/ui/factory.d.ts.map +1 -1
  40. package/dist/src/domain/utils/index.d.ts +1 -0
  41. package/dist/src/domain/utils/index.d.ts.map +1 -1
  42. package/dist/src/domain/utils/index.js +1 -0
  43. package/dist/src/domain/utils/index.js.map +1 -1
  44. package/dist/src/multichain/index.d.ts +5 -2
  45. package/dist/src/multichain/index.d.ts.map +1 -1
  46. package/dist/src/multichain/index.js +124 -38
  47. package/dist/src/multichain/index.js.map +1 -1
  48. package/dist/src/multichain/rpc/handlers/rpcClient.d.ts +2 -1
  49. package/dist/src/multichain/rpc/handlers/rpcClient.d.ts.map +1 -1
  50. package/dist/src/multichain/rpc/handlers/rpcClient.js +16 -17
  51. package/dist/src/multichain/rpc/handlers/rpcClient.js.map +1 -1
  52. package/dist/src/multichain/rpc/requestRouter.d.ts +1 -0
  53. package/dist/src/multichain/rpc/requestRouter.d.ts.map +1 -1
  54. package/dist/src/multichain/rpc/requestRouter.js +71 -15
  55. package/dist/src/multichain/rpc/requestRouter.js.map +1 -1
  56. package/dist/src/multichain/transports/constants.d.ts +3 -0
  57. package/dist/src/multichain/transports/constants.d.ts.map +1 -0
  58. package/dist/src/multichain/transports/constants.js +3 -0
  59. package/dist/src/multichain/transports/constants.js.map +1 -0
  60. package/dist/src/multichain/transports/default/index.d.ts +4 -0
  61. package/dist/src/multichain/transports/default/index.d.ts.map +1 -1
  62. package/dist/src/multichain/transports/default/index.js +137 -13
  63. package/dist/src/multichain/transports/default/index.js.map +1 -1
  64. package/dist/src/multichain/transports/mwp/index.d.ts +10 -1
  65. package/dist/src/multichain/transports/mwp/index.d.ts.map +1 -1
  66. package/dist/src/multichain/transports/mwp/index.js +138 -10
  67. package/dist/src/multichain/transports/mwp/index.js.map +1 -1
  68. package/dist/src/multichain/utils/analytics.d.ts +39 -0
  69. package/dist/src/multichain/utils/analytics.d.ts.map +1 -0
  70. package/dist/src/multichain/utils/analytics.js +83 -0
  71. package/dist/src/multichain/utils/analytics.js.map +1 -0
  72. package/dist/src/multichain/utils/index.d.ts +0 -1
  73. package/dist/src/multichain/utils/index.d.ts.map +1 -1
  74. package/dist/src/multichain/utils/index.js +1 -16
  75. package/dist/src/multichain/utils/index.js.map +1 -1
  76. package/dist/src/ui/index.d.ts +1 -1
  77. package/dist/src/ui/index.d.ts.map +1 -1
  78. package/dist/src/ui/index.js +35 -19
  79. package/dist/src/ui/index.js.map +1 -1
  80. package/dist/src/ui/modals/web/install.js +1 -1
  81. package/dist/src/ui/modals/web/install.js.map +1 -1
  82. package/dist/types/connect-multichain.d.ts +67 -13
  83. package/package.json +12 -9
@@ -32,6 +32,7 @@ var __export = (target, all) => {
32
32
  var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
33
33
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
34
34
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
35
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
35
36
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
36
37
  var __async = (__this, __arguments, generator) => {
37
38
  return new Promise((resolve, reject) => {
@@ -176,6 +177,41 @@ var init_events = __esm({
176
177
  off(eventName, handler) {
177
178
  __privateGet(this, _emitter).off(eventName, handler);
178
179
  }
180
+ /**
181
+ * Removes a specific event handler for the specified event.
182
+ * Added for compatibility as some libraries use this method name.
183
+ *
184
+ * @template TEventName - The name of the event to remove the handler from (must be a key of TEvents)
185
+ * @param eventName - The name of the event to remove the handler from
186
+ * @param handler - The specific handler function to remove
187
+ */
188
+ removeListener(eventName, handler) {
189
+ __privateGet(this, _emitter).off(eventName, handler);
190
+ }
191
+ /**
192
+ * Registers an event handler for the specified event that will only be called once.
193
+ *
194
+ * @template TEventName - The name of the event to listen for (must be a key of TEvents)
195
+ * @param eventName - The name of the event to listen for
196
+ * @param handler - The function to call when the event is emitted (only once)
197
+ * @returns A function to remove the listener
198
+ */
199
+ once(eventName, handler) {
200
+ __privateGet(this, _emitter).once(eventName, handler);
201
+ return () => {
202
+ this.off(eventName, handler);
203
+ };
204
+ }
205
+ /**
206
+ * Returns the number of listeners registered for the specified event.
207
+ *
208
+ * @template TEventName - The name of the event to count listeners for (must be a key of TEvents)
209
+ * @param eventName - The name of the event to count listeners for
210
+ * @returns The number of listeners registered for the event
211
+ */
212
+ listenerCount(eventName) {
213
+ return __privateGet(this, _emitter).listenerCount(eventName);
214
+ }
179
215
  };
180
216
  _emitter = new WeakMap();
181
217
  }
@@ -340,7 +376,7 @@ function getTransportType(type) {
340
376
  case "browser":
341
377
  return "browser" /* Browser */;
342
378
  case "mwp":
343
- return "mwp" /* MPW */;
379
+ return "mwp" /* MWP */;
344
380
  default:
345
381
  return "unknown" /* UNKNOWN */;
346
382
  }
@@ -354,7 +390,7 @@ var init_multichain = __esm({
354
390
  init_infura();
355
391
  TransportType = /* @__PURE__ */ ((TransportType2) => {
356
392
  TransportType2["Browser"] = "browser";
357
- TransportType2["MPW"] = "mwp";
393
+ TransportType2["MWP"] = "mwp";
358
394
  TransportType2["UNKNOWN"] = "unknown";
359
395
  return TransportType2;
360
396
  })(TransportType || {});
@@ -368,7 +404,7 @@ var init_multichain = __esm({
368
404
  });
369
405
 
370
406
  // src/domain/platform/index.ts
371
- import { parse } from "bowser";
407
+ import Bowser from "bowser";
372
408
  function isNotBrowser() {
373
409
  var _a;
374
410
  if (typeof window === "undefined") {
@@ -397,7 +433,7 @@ function isMetaMaskMobileWebView() {
397
433
  }
398
434
  function isMobile() {
399
435
  var _a, _b;
400
- const browser = parse(window.navigator.userAgent);
436
+ const browser = Bowser.parse(window.navigator.userAgent);
401
437
  return ((_a = browser == null ? void 0 : browser.platform) == null ? void 0 : _a.type) === "mobile" || ((_b = browser == null ? void 0 : browser.platform) == null ? void 0 : _b.type) === "tablet";
402
438
  }
403
439
  function getPlatformType() {
@@ -462,8 +498,8 @@ var init_platform = __esm({
462
498
  window.removeEventListener("eip6963:announceProvider", handler);
463
499
  const hasMetaMask = providers.some(
464
500
  (provider) => {
465
- var _a;
466
- return ((_a = provider == null ? void 0 : provider.info) == null ? void 0 : _a.rdns) === "io.metamask";
501
+ var _a, _b;
502
+ return (_b = (_a = provider == null ? void 0 : provider.info) == null ? void 0 : _a.rdns) == null ? void 0 : _b.startsWith("io.metamask");
467
503
  }
468
504
  );
469
505
  resolve(hasMetaMask);
@@ -547,13 +583,265 @@ var init_ui = __esm({
547
583
  }
548
584
  });
549
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
+
550
837
  // src/domain/utils/index.ts
551
838
  function getVersion() {
552
839
  return "0.0.0";
553
840
  }
554
- var init_utils = __esm({
841
+ var init_utils2 = __esm({
555
842
  "src/domain/utils/index.ts"() {
556
843
  "use strict";
844
+ init_analytics();
557
845
  }
558
846
  });
559
847
 
@@ -568,7 +856,7 @@ var init_domain = __esm({
568
856
  init_platform();
569
857
  init_store();
570
858
  init_ui();
571
- init_utils();
859
+ init_utils2();
572
860
  }
573
861
  });
574
862
 
@@ -591,7 +879,7 @@ function shouldLogCountdown(remainingSeconds) {
591
879
  return remainingSeconds % 60 === 0;
592
880
  }
593
881
  }
594
- var init_utils2 = __esm({
882
+ var init_utils3 = __esm({
595
883
  "src/ui/modals/base/utils.ts"() {
596
884
  "use strict";
597
885
  }
@@ -603,7 +891,7 @@ var init_AbstractInstallModal = __esm({
603
891
  "src/ui/modals/base/AbstractInstallModal.ts"() {
604
892
  "use strict";
605
893
  init_domain();
606
- init_utils2();
894
+ init_utils3();
607
895
  logger3 = createLogger("metamask-sdk:ui");
608
896
  AbstractInstallModal = class extends Modal {
609
897
  constructor() {
@@ -704,7 +992,7 @@ var init_install = __esm({
704
992
  const modal = document.createElement(
705
993
  "mm-install-modal"
706
994
  );
707
- modal.preferDesktop = options.preferDesktop;
995
+ modal.showInstallModal = options.showInstallModal;
708
996
  modal.sdkVersion = options.sdkVersion;
709
997
  modal.addEventListener("close", (ev) => {
710
998
  const { detail } = ev;
@@ -848,273 +1136,67 @@ var init_web2 = __esm({
848
1136
  return __async(this, null, function* () {
849
1137
  const { storeName } = this;
850
1138
  const db = yield this.dbPromise;
851
- return new Promise((resolve, reject) => {
852
- try {
853
- const tx = db.transaction(storeName, "readwrite");
854
- const store = tx.objectStore(storeName);
855
- const request = store.put(value, key);
856
- request.onerror = () => reject(new Error("Failed to set value in IndexedDB."));
857
- request.onsuccess = () => resolve();
858
- } catch (error) {
859
- reject(error);
860
- }
861
- });
862
- });
863
- }
864
- delete(key) {
865
- return __async(this, null, function* () {
866
- const { storeName } = this;
867
- const db = yield this.dbPromise;
868
- return new Promise((resolve, reject) => {
869
- try {
870
- const tx = db.transaction(storeName, "readwrite");
871
- const store = tx.objectStore(storeName);
872
- const request = store.delete(key);
873
- request.onerror = () => reject(new Error("Failed to delete value from IndexedDB."));
874
- request.onsuccess = () => resolve();
875
- } catch (error) {
876
- reject(error);
877
- }
878
- });
879
- });
880
- }
881
- };
882
- _StoreAdapterWeb.stores = ["sdk-kv-store", "key-value-pairs"];
883
- _StoreAdapterWeb.DB_NAME = "mmsdk";
884
- StoreAdapterWeb = _StoreAdapterWeb;
885
- }
886
- });
887
-
888
- // src/multichain/index.ts
889
- import { analytics } from "@metamask/analytics";
890
- import {
891
- ErrorCode,
892
- ProtocolError,
893
- SessionStore as SessionStore2,
894
- WebSocketTransport
895
- } from "@metamask/mobile-wallet-protocol-core";
896
- import { DappClient } from "@metamask/mobile-wallet-protocol-dapp-client";
897
- import {
898
- getMultichainClient
899
- } from "@metamask/multichain-api-client";
900
-
901
- // src/config/index.ts
902
- var MWP_RELAY_URL = "wss://mm-sdk-relay.api.cx.metamask.io/connection/websocket";
903
- var METAMASK_CONNECT_BASE_URL = "https://metamask.app.link/connect";
904
- var METAMASK_DEEPLINK_BASE = "metamask://connect";
905
-
906
- // src/multichain/index.ts
907
- init_domain();
908
- init_logger();
909
- init_multichain();
910
- init_platform();
911
-
912
- // src/multichain/rpc/requestRouter.ts
913
- init_domain();
914
-
915
- // src/multichain/utils/index.ts
916
- init_domain();
917
- import { deflate } from "pako";
918
- import {
919
- parseCaipAccountId,
920
- parseCaipChainId
921
- } from "@metamask/utils";
922
- function base64Encode(str) {
923
- if (typeof btoa !== "undefined") {
924
- return btoa(str);
925
- } else if (typeof Buffer !== "undefined") {
926
- return Buffer.from(str).toString("base64");
927
- }
928
- throw new Error("No base64 encoding method available");
929
- }
930
- function compressString(str) {
931
- const compressed = deflate(str);
932
- const binaryString = String.fromCharCode.apply(null, Array.from(compressed));
933
- return base64Encode(binaryString);
934
- }
935
- function getDappId(dapp) {
936
- var _a, _b;
937
- if (typeof window === "undefined" || typeof window.location === "undefined") {
938
- return (_b = (_a = dapp == null ? void 0 : dapp.name) != null ? _a : dapp == null ? void 0 : dapp.url) != null ? _b : "N/A";
939
- }
940
- return window.location.hostname;
941
- }
942
- function openDeeplink(options, deeplink, universalLink) {
943
- const { mobile } = options;
944
- const useDeeplink = mobile && mobile.useDeeplink !== void 0 ? mobile.useDeeplink : true;
945
- if (useDeeplink) {
946
- if (typeof window !== "undefined") {
947
- window.location.href = deeplink;
948
- }
949
- } else if (typeof document !== "undefined") {
950
- const link = document.createElement("a");
951
- link.href = universalLink;
952
- link.target = "_self";
953
- link.rel = "noreferrer noopener";
954
- link.click();
955
- }
956
- }
957
- function getOptionalScopes(scopes) {
958
- return scopes.reduce(
959
- (prev, scope) => __spreadProps(__spreadValues({}, prev), {
960
- [scope]: {
961
- methods: [],
962
- notifications: [],
963
- accounts: []
964
- }
965
- }),
966
- {}
967
- );
968
- }
969
- var extractFavicon = () => {
970
- var _a;
971
- if (typeof document === "undefined") {
972
- return void 0;
973
- }
974
- let favicon;
975
- const nodeList = document.getElementsByTagName("link");
976
- for (let i = 0; i < nodeList.length; i++) {
977
- if (nodeList[i].getAttribute("rel") === "icon" || nodeList[i].getAttribute("rel") === "shortcut icon") {
978
- favicon = (_a = nodeList[i].getAttribute("href")) != null ? _a : void 0;
979
- }
980
- }
981
- return favicon;
982
- };
983
- function setupInfuraProvider(options) {
984
- var _a, _b;
985
- const infuraAPIKey = (_a = options.api) == null ? void 0 : _a.infuraAPIKey;
986
- if (!infuraAPIKey) {
987
- return options;
988
- }
989
- const urlsWithToken = getInfuraRpcUrls(infuraAPIKey);
990
- if ((_b = options.api) == null ? void 0 : _b.readonlyRPCMap) {
991
- options.api.readonlyRPCMap = __spreadValues(__spreadValues({}, options.api.readonlyRPCMap), urlsWithToken);
992
- } else if (options.api) {
993
- options.api.readonlyRPCMap = urlsWithToken;
994
- }
995
- return options;
996
- }
997
- function setupDappMetadata(options) {
998
- var _a;
999
- const platform = getPlatformType();
1000
- const isBrowser = platform === "web-desktop" /* DesktopWeb */ || platform === "web-mobile" /* MobileWeb */ || platform === "in-app-browser" /* MetaMaskMobileWebview */;
1001
- if (!((_a = options.dapp) == null ? void 0 : _a.url)) {
1002
- if (isBrowser) {
1003
- options.dapp = __spreadProps(__spreadValues({}, options.dapp), {
1004
- url: `${window.location.protocol}//${window.location.host}`
1005
- });
1006
- } else {
1007
- throw new Error("You must provide dapp url");
1008
- }
1009
- }
1010
- const BASE_64_ICON_MAX_LENGTH = 163400;
1011
- const urlPattern = /^(http|https):\/\/[^\s]*$/;
1012
- if (options.dapp) {
1013
- if ("iconUrl" in options.dapp) {
1014
- if (options.dapp.iconUrl && !urlPattern.test(options.dapp.iconUrl)) {
1015
- console.warn(
1016
- "Invalid dappMetadata.iconUrl: URL must start with http:// or https://"
1017
- );
1018
- options.dapp.iconUrl = void 0;
1019
- }
1020
- }
1021
- if ("base64Icon" in options.dapp) {
1022
- if (options.dapp.base64Icon && options.dapp.base64Icon.length > BASE_64_ICON_MAX_LENGTH) {
1023
- console.warn(
1024
- "Invalid dappMetadata.base64Icon: Base64-encoded icon string length must be less than 163400 characters"
1025
- );
1026
- options.dapp.base64Icon = void 0;
1027
- }
1028
- }
1029
- if (options.dapp.url && !urlPattern.test(options.dapp.url)) {
1030
- console.warn(
1031
- "Invalid dappMetadata.url: URL must start with http:// or https://"
1032
- );
1033
- }
1034
- const favicon = extractFavicon();
1035
- if (favicon && !("iconUrl" in options.dapp) && !("base64Icon" in options.dapp)) {
1036
- const faviconUrl = `${window.location.protocol}//${window.location.host}${favicon}`;
1037
- options.dapp.iconUrl = faviconUrl;
1038
- }
1039
- }
1040
- return options;
1041
- }
1042
- function isSameScopesAndAccounts(currentScopes, proposedScopes, walletSession, proposedCaipAccountIds) {
1043
- const isSameScopes = currentScopes.every((scope) => proposedScopes.includes(scope)) && proposedScopes.every((scope) => currentScopes.includes(scope));
1044
- if (!isSameScopes) {
1045
- return false;
1046
- }
1047
- const existingAccountIds = Object.values(
1048
- walletSession.sessionScopes
1049
- ).filter(({ accounts }) => Boolean(accounts)).flatMap(({ accounts }) => accounts != null ? accounts : []);
1050
- const allProposedAccountsIncluded = proposedCaipAccountIds.every(
1051
- (proposedAccountId) => existingAccountIds.includes(proposedAccountId)
1052
- );
1053
- return allProposedAccountsIncluded;
1054
- }
1055
- function getValidAccounts(caipAccountIds) {
1056
- return caipAccountIds.reduce(
1057
- (caipAccounts, caipAccountId) => {
1058
- try {
1059
- return [...caipAccounts, parseCaipAccountId(caipAccountId)];
1060
- } catch (err) {
1061
- const stringifiedAccountId = JSON.stringify(caipAccountId);
1062
- console.error(`Invalid CAIP account ID: ${stringifiedAccountId}`, err);
1063
- return caipAccounts;
1064
- }
1065
- },
1066
- []
1067
- );
1068
- }
1069
- function addValidAccounts(optionalScopes, validAccounts) {
1070
- var _a;
1071
- if (!optionalScopes || !(validAccounts == null ? void 0 : validAccounts.length)) {
1072
- return optionalScopes;
1073
- }
1074
- const result = Object.fromEntries(
1075
- Object.entries(optionalScopes).map(([scope, scopeData]) => {
1076
- var _a2, _b, _c;
1077
- return [
1078
- scope,
1079
- {
1080
- methods: [...(_a2 = scopeData == null ? void 0 : scopeData.methods) != null ? _a2 : []],
1081
- notifications: [...(_b = scopeData == null ? void 0 : scopeData.notifications) != null ? _b : []],
1082
- accounts: [...(_c = scopeData == null ? void 0 : scopeData.accounts) != null ? _c : []]
1083
- }
1084
- ];
1085
- })
1086
- );
1087
- const accountsByChain = /* @__PURE__ */ new Map();
1088
- for (const account of validAccounts) {
1089
- const chainKey = `${account.chain.namespace}:${account.chain.reference}`;
1090
- const accountId = `${account.chainId}:${account.address}`;
1091
- if (!accountsByChain.has(chainKey)) {
1092
- accountsByChain.set(chainKey, []);
1093
- }
1094
- (_a = accountsByChain.get(chainKey)) == null ? void 0 : _a.push(accountId);
1095
- }
1096
- for (const [scopeKey, scopeData] of Object.entries(result)) {
1097
- if (!(scopeData == null ? void 0 : scopeData.accounts)) {
1098
- continue;
1099
- }
1100
- try {
1101
- const scope = scopeKey;
1102
- const scopeDetails = parseCaipChainId(scope);
1103
- const chainKey = `${scopeDetails.namespace}:${scopeDetails.reference}`;
1104
- const matchingAccounts = accountsByChain.get(chainKey);
1105
- if (matchingAccounts) {
1106
- const existingAccounts = new Set(scopeData.accounts);
1107
- const newAccounts = matchingAccounts.filter(
1108
- (account) => !existingAccounts.has(account)
1109
- );
1110
- scopeData.accounts.push(...newAccounts);
1139
+ return new Promise((resolve, reject) => {
1140
+ try {
1141
+ const tx = db.transaction(storeName, "readwrite");
1142
+ const store = tx.objectStore(storeName);
1143
+ const request = store.put(value, key);
1144
+ request.onerror = () => reject(new Error("Failed to set value in IndexedDB."));
1145
+ request.onsuccess = () => resolve();
1146
+ } catch (error) {
1147
+ reject(error);
1148
+ }
1149
+ });
1150
+ });
1111
1151
  }
1112
- } catch (error) {
1113
- console.error(`Invalid scope format: ${scopeKey}`, error);
1114
- }
1152
+ delete(key) {
1153
+ return __async(this, null, function* () {
1154
+ const { storeName } = this;
1155
+ const db = yield this.dbPromise;
1156
+ return new Promise((resolve, reject) => {
1157
+ try {
1158
+ const tx = db.transaction(storeName, "readwrite");
1159
+ const store = tx.objectStore(storeName);
1160
+ const request = store.delete(key);
1161
+ request.onerror = () => reject(new Error("Failed to delete value from IndexedDB."));
1162
+ request.onsuccess = () => resolve();
1163
+ } catch (error) {
1164
+ reject(error);
1165
+ }
1166
+ });
1167
+ });
1168
+ }
1169
+ };
1170
+ _StoreAdapterWeb.stores = ["sdk-kv-store", "key-value-pairs"];
1171
+ _StoreAdapterWeb.DB_NAME = "mmsdk";
1172
+ StoreAdapterWeb = _StoreAdapterWeb;
1115
1173
  }
1116
- return result;
1117
- }
1174
+ });
1175
+
1176
+ // src/multichain/index.ts
1177
+ import { analytics as analytics2 } from "@metamask/analytics";
1178
+ import {
1179
+ ErrorCode,
1180
+ ProtocolError,
1181
+ SessionStore as SessionStore2,
1182
+ WebSocketTransport
1183
+ } from "@metamask/mobile-wallet-protocol-core";
1184
+ import { DappClient } from "@metamask/mobile-wallet-protocol-dapp-client";
1185
+ import {
1186
+ getMultichainClient
1187
+ } from "@metamask/multichain-api-client";
1188
+
1189
+ // src/config/index.ts
1190
+ var MWP_RELAY_URL = "wss://mm-sdk-relay.api.cx.metamask.io/connection/websocket";
1191
+ var METAMASK_CONNECT_BASE_URL = "https://metamask.app.link/connect";
1192
+ var METAMASK_DEEPLINK_BASE = "metamask://connect";
1193
+
1194
+ // src/multichain/index.ts
1195
+ init_domain();
1196
+ init_analytics();
1197
+ init_logger();
1198
+ init_multichain();
1199
+ init_platform();
1118
1200
 
1119
1201
  // src/multichain/rpc/handlers/rpcClient.ts
1120
1202
  init_domain();
@@ -1133,6 +1215,7 @@ var RpcClient = class {
1133
1215
  }
1134
1216
  /**
1135
1217
  * Routes the request to a configured RPC node.
1218
+ * @param options - The invoke method options
1136
1219
  */
1137
1220
  request(options) {
1138
1221
  return __async(this, null, function* () {
@@ -1144,46 +1227,45 @@ var RpcClient = class {
1144
1227
  id: getNextRpcId()
1145
1228
  });
1146
1229
  const rpcEndpoint = this.getRpcEndpoint(options.scope);
1147
- const rpcRequest = yield this.fetch(rpcEndpoint, body, "POST", this.getHeaders(rpcEndpoint));
1230
+ const rpcRequest = yield this.fetchWithTimeout(rpcEndpoint, body, "POST", this.getHeaders(rpcEndpoint), 3e4);
1148
1231
  const response = yield this.parseResponse(rpcRequest);
1149
1232
  return response;
1150
1233
  });
1151
1234
  }
1152
1235
  getRpcEndpoint(scope) {
1153
- var _a, _b, _c, _d, _e;
1154
- let infuraAPIKey = (_b = (_a = this.config) == null ? void 0 : _a.api) == null ? void 0 : _b.infuraAPIKey;
1155
- let readonlyRPCMap = (_e = (_d = (_c = this.config) == null ? void 0 : _c.api) == null ? void 0 : _d.readonlyRPCMap) != null ? _e : {};
1156
- if (infuraAPIKey) {
1157
- const urlsWithToken = getInfuraRpcUrls(infuraAPIKey);
1158
- if (readonlyRPCMap) {
1159
- readonlyRPCMap = __spreadValues(__spreadValues({}, urlsWithToken), readonlyRPCMap);
1160
- } else {
1161
- readonlyRPCMap = urlsWithToken;
1162
- }
1163
- }
1164
- const rpcEndpoint = readonlyRPCMap[scope];
1236
+ var _a, _b, _c;
1237
+ const supportedNetworks = (_c = (_b = (_a = this.config) == null ? void 0 : _a.api) == null ? void 0 : _b.supportedNetworks) != null ? _c : {};
1238
+ const rpcEndpoint = supportedNetworks[scope];
1165
1239
  if (!rpcEndpoint) {
1166
1240
  throw new MissingRpcEndpointErr(`No RPC endpoint found for scope ${scope}`);
1167
1241
  }
1168
1242
  return rpcEndpoint;
1169
1243
  }
1170
- fetch(endpoint, body, method, headers) {
1244
+ fetchWithTimeout(endpoint, body, method, headers, timeout) {
1171
1245
  return __async(this, null, function* () {
1246
+ const controller = new AbortController();
1247
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
1172
1248
  try {
1173
1249
  const response = yield fetch(endpoint, {
1174
1250
  method,
1175
1251
  headers,
1176
- body
1252
+ body,
1253
+ signal: controller.signal
1177
1254
  });
1255
+ clearTimeout(timeoutId);
1178
1256
  if (!response.ok) {
1179
1257
  throw new RPCHttpErr(endpoint, method, response.status);
1180
1258
  }
1181
1259
  return response;
1182
1260
  } catch (error) {
1261
+ clearTimeout(timeoutId);
1183
1262
  if (error instanceof RPCHttpErr) {
1184
1263
  throw error;
1185
1264
  }
1186
- throw new RPCReadonlyRequestErr(error.message);
1265
+ if (error instanceof Error && error.name === "AbortError") {
1266
+ throw new RPCReadonlyRequestErr(`Request timeout after ${timeout}ms`);
1267
+ }
1268
+ throw new RPCReadonlyRequestErr(error instanceof Error ? error.message : "Unknown error");
1187
1269
  }
1188
1270
  });
1189
1271
  }
@@ -1212,11 +1294,17 @@ var RpcClient = class {
1212
1294
  };
1213
1295
 
1214
1296
  // src/multichain/rpc/requestRouter.ts
1297
+ import { analytics } from "@metamask/analytics";
1298
+ init_domain();
1299
+ init_utils();
1300
+ init_analytics();
1301
+ var _RequestRouter_instances, withAnalyticsTracking_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, trackWalletActionRejected_fn;
1215
1302
  var RequestRouter = class {
1216
1303
  constructor(transport, rpcClient, config) {
1217
1304
  this.transport = transport;
1218
1305
  this.rpcClient = rpcClient;
1219
1306
  this.config = config;
1307
+ __privateAdd(this, _RequestRouter_instances);
1220
1308
  }
1221
1309
  /**
1222
1310
  * The main entry point for invoking an RPC method.
@@ -1240,15 +1328,15 @@ var RequestRouter = class {
1240
1328
  */
1241
1329
  handleWithWallet(options) {
1242
1330
  return __async(this, null, function* () {
1243
- try {
1331
+ return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1244
1332
  const request = this.transport.request({
1245
1333
  method: "wallet_invokeMethod",
1246
1334
  params: options
1247
1335
  });
1248
1336
  const { ui, mobile } = this.config;
1249
- const { preferDesktop = false } = ui != null ? ui : {};
1337
+ const { showInstallModal = false } = ui != null ? ui : {};
1250
1338
  const secure = isSecure();
1251
- const shouldOpenDeeplink = secure && !preferDesktop;
1339
+ const shouldOpenDeeplink = secure && !showInstallModal;
1252
1340
  if (shouldOpenDeeplink) {
1253
1341
  setTimeout(() => {
1254
1342
  if (mobile == null ? void 0 : mobile.preferredOpenLink) {
@@ -1263,9 +1351,7 @@ var RequestRouter = class {
1263
1351
  throw new RPCInvokeMethodErr(`RPC Request failed with code ${response.error.code}: ${response.error.message}`);
1264
1352
  }
1265
1353
  return response.result;
1266
- } catch (error) {
1267
- throw new RPCInvokeMethodErr(error.message);
1268
- }
1354
+ }));
1269
1355
  });
1270
1356
  }
1271
1357
  /**
@@ -1273,14 +1359,16 @@ var RequestRouter = class {
1273
1359
  */
1274
1360
  handleWithRpcNode(options) {
1275
1361
  return __async(this, null, function* () {
1276
- try {
1277
- return yield this.rpcClient.request(options);
1278
- } catch (error) {
1279
- if (error instanceof MissingRpcEndpointErr) {
1280
- 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;
1281
1370
  }
1282
- throw error;
1283
- }
1371
+ }));
1284
1372
  });
1285
1373
  }
1286
1374
  /**
@@ -1293,13 +1381,64 @@ var RequestRouter = class {
1293
1381
  });
1294
1382
  }
1295
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
+ };
1296
1434
 
1297
1435
  // src/multichain/transports/default/index.ts
1436
+ init_utils();
1298
1437
  import {
1299
1438
  getDefaultTransport
1300
1439
  } from "@metamask/multichain-api-client";
1301
1440
  var DEFAULT_REQUEST_TIMEOUT = 60 * 1e3;
1302
- var _notificationCallbacks, _transport, _defaultRequestOptions, _DefaultTransport_instances, notifyCallbacks_fn;
1441
+ var _notificationCallbacks, _transport, _defaultRequestOptions, _reqId, _pendingRequests, _handleResponseListener, _handleNotificationListener, _DefaultTransport_instances, notifyCallbacks_fn, isMetamaskProviderEvent_fn, handleResponse_fn, handleNotification_fn, setupMessageListener_fn;
1303
1442
  var DefaultTransport = class {
1304
1443
  constructor() {
1305
1444
  __privateAdd(this, _DefaultTransport_instances);
@@ -1308,10 +1447,52 @@ var DefaultTransport = class {
1308
1447
  __privateAdd(this, _defaultRequestOptions, {
1309
1448
  timeout: DEFAULT_REQUEST_TIMEOUT
1310
1449
  });
1450
+ // Use timestamp-based ID to avoid conflicts across disconnect/reconnect cycles
1451
+ __privateAdd(this, _reqId, Date.now());
1452
+ __privateAdd(this, _pendingRequests, /* @__PURE__ */ new Map());
1453
+ __privateAdd(this, _handleResponseListener);
1454
+ __privateAdd(this, _handleNotificationListener);
1455
+ }
1456
+ sendEip1193Message(payload, options) {
1457
+ return __async(this, null, function* () {
1458
+ __privateMethod(this, _DefaultTransport_instances, setupMessageListener_fn).call(this);
1459
+ __privateSet(this, _reqId, __privateGet(this, _reqId) + 1);
1460
+ const requestId = `${__privateGet(this, _reqId)}`;
1461
+ const request = __spreadValues({
1462
+ jsonrpc: "2.0",
1463
+ id: requestId
1464
+ }, payload);
1465
+ return new Promise((resolve, reject) => {
1466
+ var _a;
1467
+ const timeout = setTimeout(() => {
1468
+ __privateGet(this, _pendingRequests).delete(requestId);
1469
+ reject(new Error("Request timeout"));
1470
+ }, (_a = options == null ? void 0 : options.timeout) != null ? _a : __privateGet(this, _defaultRequestOptions).timeout);
1471
+ __privateGet(this, _pendingRequests).set(requestId, {
1472
+ resolve: (response) => {
1473
+ resolve(response);
1474
+ },
1475
+ reject,
1476
+ timeout
1477
+ });
1478
+ window.postMessage(
1479
+ {
1480
+ target: "metamask-contentscript",
1481
+ data: {
1482
+ name: "metamask-provider",
1483
+ data: request
1484
+ }
1485
+ },
1486
+ // eslint-disable-next-line no-restricted-globals
1487
+ location.origin
1488
+ );
1489
+ });
1490
+ });
1311
1491
  }
1312
1492
  connect(options) {
1313
1493
  return __async(this, null, function* () {
1314
1494
  var _a, _b, _c, _d, _e, _f, _g;
1495
+ __privateMethod(this, _DefaultTransport_instances, setupMessageListener_fn).call(this);
1315
1496
  yield __privateGet(this, _transport).connect();
1316
1497
  const sessionRequest = yield this.request(
1317
1498
  { method: "wallet_getSession" },
@@ -1321,7 +1502,7 @@ var DefaultTransport = class {
1321
1502
  throw new Error(sessionRequest.error.message);
1322
1503
  }
1323
1504
  let walletSession = sessionRequest.result;
1324
- if (walletSession && options) {
1505
+ if (walletSession && options && !options.forceRequest) {
1325
1506
  const currentScopes = Object.keys(
1326
1507
  (_a = walletSession == null ? void 0 : walletSession.sessionScopes) != null ? _a : {}
1327
1508
  );
@@ -1342,9 +1523,11 @@ var DefaultTransport = class {
1342
1523
  getOptionalScopes((_d = options == null ? void 0 : options.scopes) != null ? _d : []),
1343
1524
  getValidAccounts((_e = options == null ? void 0 : options.caipAccountIds) != null ? _e : [])
1344
1525
  );
1345
- const sessionRequest2 = { optionalScopes };
1526
+ const createSessionParams = {
1527
+ optionalScopes
1528
+ };
1346
1529
  const response = yield this.request(
1347
- { method: "wallet_createSession", params: sessionRequest2 },
1530
+ { method: "wallet_createSession", params: createSessionParams },
1348
1531
  __privateGet(this, _defaultRequestOptions)
1349
1532
  );
1350
1533
  if (response.error) {
@@ -1352,14 +1535,16 @@ var DefaultTransport = class {
1352
1535
  }
1353
1536
  walletSession = response.result;
1354
1537
  }
1355
- } else if (!walletSession) {
1538
+ } else if (!walletSession || (options == null ? void 0 : options.forceRequest)) {
1356
1539
  const optionalScopes = addValidAccounts(
1357
1540
  getOptionalScopes((_f = options == null ? void 0 : options.scopes) != null ? _f : []),
1358
1541
  getValidAccounts((_g = options == null ? void 0 : options.caipAccountIds) != null ? _g : [])
1359
1542
  );
1360
- const sessionRequest2 = { optionalScopes };
1543
+ const createSessionParams = {
1544
+ optionalScopes
1545
+ };
1361
1546
  const response = yield this.request(
1362
- { method: "wallet_createSession", params: sessionRequest2 },
1547
+ { method: "wallet_createSession", params: createSessionParams },
1363
1548
  __privateGet(this, _defaultRequestOptions)
1364
1549
  );
1365
1550
  if (response.error) {
@@ -1376,6 +1561,16 @@ var DefaultTransport = class {
1376
1561
  disconnect() {
1377
1562
  return __async(this, null, function* () {
1378
1563
  __privateGet(this, _notificationCallbacks).clear();
1564
+ yield this.request({ method: "wallet_revokeSession", params: {} });
1565
+ if (__privateGet(this, _handleResponseListener)) {
1566
+ window.removeEventListener("message", __privateGet(this, _handleResponseListener));
1567
+ __privateSet(this, _handleResponseListener, void 0);
1568
+ }
1569
+ for (const [, request] of __privateGet(this, _pendingRequests)) {
1570
+ clearTimeout(request.timeout);
1571
+ request.reject(new Error("Transport disconnected"));
1572
+ }
1573
+ __privateGet(this, _pendingRequests).clear();
1379
1574
  return __privateGet(this, _transport).disconnect();
1380
1575
  });
1381
1576
  }
@@ -1398,33 +1593,101 @@ var DefaultTransport = class {
1398
1593
  _notificationCallbacks = new WeakMap();
1399
1594
  _transport = new WeakMap();
1400
1595
  _defaultRequestOptions = new WeakMap();
1596
+ _reqId = new WeakMap();
1597
+ _pendingRequests = new WeakMap();
1598
+ _handleResponseListener = new WeakMap();
1599
+ _handleNotificationListener = new WeakMap();
1401
1600
  _DefaultTransport_instances = new WeakSet();
1402
1601
  notifyCallbacks_fn = function(data) {
1403
- for (const cb of __privateGet(this, _notificationCallbacks)) {
1602
+ for (const callback of __privateGet(this, _notificationCallbacks)) {
1404
1603
  try {
1405
- cb(data);
1406
- } catch (err) {
1407
- console.log("[WindowPostMessageTransport] notifyCallbacks error:", err);
1604
+ callback(data);
1605
+ } catch (error) {
1606
+ console.log(
1607
+ "[WindowPostMessageTransport] notifyCallbacks error:",
1608
+ error
1609
+ );
1610
+ }
1611
+ }
1612
+ };
1613
+ isMetamaskProviderEvent_fn = function(event) {
1614
+ var _a, _b;
1615
+ return ((_b = (_a = event == null ? void 0 : event.data) == null ? void 0 : _a.data) == null ? void 0 : _b.name) === "metamask-provider" && // eslint-disable-next-line no-restricted-globals
1616
+ event.origin === location.origin;
1617
+ };
1618
+ handleResponse_fn = function(event) {
1619
+ var _a, _b;
1620
+ if (!__privateMethod(this, _DefaultTransport_instances, isMetamaskProviderEvent_fn).call(this, event)) {
1621
+ return;
1622
+ }
1623
+ const responseData = (_b = (_a = event == null ? void 0 : event.data) == null ? void 0 : _a.data) == null ? void 0 : _b.data;
1624
+ if (typeof responseData === "object" && responseData !== null && "method" in responseData) {
1625
+ return;
1626
+ }
1627
+ if (typeof responseData === "object" && responseData !== null && "id" in responseData && ("result" in responseData || "error" in responseData)) {
1628
+ const responseId = String(responseData.id);
1629
+ const pendingRequest = __privateGet(this, _pendingRequests).get(responseId);
1630
+ if (pendingRequest) {
1631
+ clearTimeout(pendingRequest.timeout);
1632
+ __privateGet(this, _pendingRequests).delete(responseId);
1633
+ const response = responseData;
1634
+ if ("error" in response && response.error) {
1635
+ pendingRequest.reject(
1636
+ new Error(response.error.message || "Request failed")
1637
+ );
1638
+ } else {
1639
+ pendingRequest.resolve(response);
1640
+ }
1408
1641
  }
1409
1642
  }
1410
1643
  };
1644
+ handleNotification_fn = function(event) {
1645
+ var _a, _b;
1646
+ if (!__privateMethod(this, _DefaultTransport_instances, isMetamaskProviderEvent_fn).call(this, event)) {
1647
+ return;
1648
+ }
1649
+ const responseData = (_b = (_a = event == null ? void 0 : event.data) == null ? void 0 : _a.data) == null ? void 0 : _b.data;
1650
+ if (typeof responseData === "object" && responseData.method === "metamask_chainChanged" || responseData.method === "metamask_accountsChanged") {
1651
+ __privateMethod(this, _DefaultTransport_instances, notifyCallbacks_fn).call(this, responseData);
1652
+ }
1653
+ };
1654
+ setupMessageListener_fn = function() {
1655
+ if (__privateGet(this, _handleResponseListener)) {
1656
+ return;
1657
+ }
1658
+ __privateSet(this, _handleResponseListener, __privateMethod(this, _DefaultTransport_instances, handleResponse_fn).bind(this));
1659
+ __privateSet(this, _handleNotificationListener, __privateMethod(this, _DefaultTransport_instances, handleNotification_fn).bind(this));
1660
+ window.addEventListener("message", __privateGet(this, _handleResponseListener));
1661
+ window.addEventListener("message", __privateGet(this, _handleNotificationListener));
1662
+ };
1411
1663
 
1412
1664
  // src/multichain/transports/mwp/index.ts
1413
1665
  init_domain();
1666
+ init_utils();
1414
1667
  import { SessionStore } from "@metamask/mobile-wallet-protocol-core";
1415
1668
  import {
1416
1669
  TransportTimeoutError
1417
1670
  } from "@metamask/multichain-api-client";
1671
+
1672
+ // src/multichain/transports/constants.ts
1673
+ var MULTICHAIN_PROVIDER_STREAM_NAME = "metamask-multichain-provider";
1674
+
1675
+ // src/multichain/transports/mwp/index.ts
1418
1676
  var DEFAULT_REQUEST_TIMEOUT2 = 60 * 1e3;
1419
1677
  var CONNECTION_GRACE_PERIOD = 60 * 1e3;
1420
1678
  var DEFAULT_CONNECTION_TIMEOUT = DEFAULT_REQUEST_TIMEOUT2 + CONNECTION_GRACE_PERIOD;
1421
1679
  var SESSION_STORE_KEY = "cache_wallet_getSession";
1680
+ var ACCOUNTS_STORE_KEY = "cache_eth_accounts";
1681
+ var CHAIN_STORE_KEY = "cache_eth_chainId";
1422
1682
  var CACHED_METHOD_LIST = [
1423
1683
  "wallet_getSession",
1424
1684
  "wallet_createSession",
1425
1685
  "wallet_sessionChanged"
1426
1686
  ];
1427
- var CACHED_RESET_METHOD_LIST = ["wallet_revokeSession"];
1687
+ var CACHED_RESET_METHOD_LIST = [
1688
+ "wallet_revokeSession",
1689
+ "wallet_revokePermissions"
1690
+ ];
1428
1691
  var logger = createLogger("metamask-sdk:transport");
1429
1692
  var MWPTransport = class {
1430
1693
  constructor(dappClient, kvstore, options = {
@@ -1488,6 +1751,22 @@ var MWPTransport = class {
1488
1751
  this.pendingRequests.delete(messagePayload.id);
1489
1752
  }
1490
1753
  } else {
1754
+ if (message.data.method === "metamask_chainChanged") {
1755
+ this.kvstore.set(
1756
+ CHAIN_STORE_KEY,
1757
+ JSON.stringify(
1758
+ message.data.params.chainId
1759
+ )
1760
+ );
1761
+ }
1762
+ if (message.data.method === "metamask_accountsChanged") {
1763
+ this.kvstore.set(
1764
+ ACCOUNTS_STORE_KEY,
1765
+ JSON.stringify(
1766
+ message.data.params
1767
+ )
1768
+ );
1769
+ }
1491
1770
  this.notifyCallbacks(message.data);
1492
1771
  }
1493
1772
  }
@@ -1558,6 +1837,40 @@ var MWPTransport = class {
1558
1837
  }
1559
1838
  });
1560
1839
  }
1840
+ // TODO: Rename this
1841
+ sendEip1193Message(payload, options) {
1842
+ return __async(this, null, function* () {
1843
+ const request = __spreadValues({
1844
+ jsonrpc: "2.0",
1845
+ id: `${this.__reqId++}`
1846
+ }, payload);
1847
+ const cachedWalletSession = yield this.getCachedResponse(request);
1848
+ if (cachedWalletSession) {
1849
+ this.notifyCallbacks(cachedWalletSession);
1850
+ return cachedWalletSession;
1851
+ }
1852
+ return new Promise((resolve, reject) => {
1853
+ var _a;
1854
+ const timeout = setTimeout(() => {
1855
+ this.rejectRequest(request.id, new TransportTimeoutError());
1856
+ }, (_a = options == null ? void 0 : options.timeout) != null ? _a : this.options.requestTimeout);
1857
+ this.pendingRequests.set(request.id, {
1858
+ request,
1859
+ method: request.method,
1860
+ resolve: (response) => __async(this, null, function* () {
1861
+ yield this.storeWalletSession(request, response);
1862
+ return resolve(response);
1863
+ }),
1864
+ reject,
1865
+ timeout
1866
+ });
1867
+ this.dappClient.sendRequest({
1868
+ name: "metamask-provider",
1869
+ data: request
1870
+ }).catch(reject);
1871
+ });
1872
+ });
1873
+ }
1561
1874
  connect(options) {
1562
1875
  return __async(this, null, function* () {
1563
1876
  const { dappClient, kvstore } = this;
@@ -1611,17 +1924,23 @@ var MWPTransport = class {
1611
1924
  if (messagePayload.error) {
1612
1925
  return rejectConnection(messagePayload.error);
1613
1926
  }
1614
- this.notifyCallbacks(message.data);
1615
1927
  yield this.storeWalletSession(
1616
1928
  request,
1617
1929
  messagePayload
1618
1930
  );
1931
+ this.notifyCallbacks(messagePayload);
1619
1932
  return resolveConnection();
1620
1933
  }
1621
1934
  }
1622
1935
  }
1623
1936
  }));
1624
- dappClient.connect({ mode: "trusted", initialPayload: request }).catch(rejectConnection);
1937
+ dappClient.connect({
1938
+ mode: "trusted",
1939
+ initialPayload: {
1940
+ name: MULTICHAIN_PROVIDER_STREAM_NAME,
1941
+ data: request
1942
+ }
1943
+ }).catch(rejectConnection);
1625
1944
  }
1626
1945
  );
1627
1946
  }
@@ -1648,6 +1967,9 @@ var MWPTransport = class {
1648
1967
  window.removeEventListener("focus", this.windowFocusHandler);
1649
1968
  this.windowFocusHandler = void 0;
1650
1969
  }
1970
+ this.kvstore.delete(SESSION_STORE_KEY);
1971
+ this.kvstore.delete(ACCOUNTS_STORE_KEY);
1972
+ this.kvstore.delete(CHAIN_STORE_KEY);
1651
1973
  return this.dappClient.disconnect();
1652
1974
  });
1653
1975
  }
@@ -1659,7 +1981,39 @@ var MWPTransport = class {
1659
1981
  isConnected() {
1660
1982
  return this.dappClient.state === "CONNECTED";
1661
1983
  }
1662
- fetchCachedWalletSession(request) {
1984
+ /**
1985
+ * Attempts to re-establish a connection via DappClient
1986
+ *
1987
+ * @returns Nothing
1988
+ */
1989
+ // TODO: We should re-evaluate adding this to the WebSocketTransport layer from `@metamask/mobile-wallet-protocol-core`
1990
+ // ticket: https://consensyssoftware.atlassian.net/browse/WAPI-862
1991
+ attemptResumeSession() {
1992
+ return __async(this, null, function* () {
1993
+ try {
1994
+ yield this.dappClient.reconnect();
1995
+ yield new Promise((resolve, reject) => {
1996
+ const timeout = setTimeout(() => {
1997
+ reject(new Error("Resume timeout"));
1998
+ }, 2e3);
1999
+ if (this.isConnected()) {
2000
+ clearTimeout(timeout);
2001
+ resolve();
2002
+ } else {
2003
+ this.dappClient.once("connected", () => {
2004
+ clearTimeout(timeout);
2005
+ resolve();
2006
+ });
2007
+ }
2008
+ });
2009
+ } catch (error) {
2010
+ return Promise.reject(
2011
+ new Error(`Failed to resume session: ${error.message}`)
2012
+ );
2013
+ }
2014
+ });
2015
+ }
2016
+ getCachedResponse(request) {
1663
2017
  return __async(this, null, function* () {
1664
2018
  var _a;
1665
2019
  if (request.method === "wallet_getSession") {
@@ -1670,6 +2024,27 @@ var MWPTransport = class {
1670
2024
  id: request.id,
1671
2025
  jsonrpc: "2.0",
1672
2026
  result: (_a = walletSession.params) != null ? _a : walletSession.result,
2027
+ // "what?... why walletSession.params?.."
2028
+ method: request.method
2029
+ };
2030
+ }
2031
+ } else if (request.method === "eth_accounts") {
2032
+ const ethAccounts = yield this.kvstore.get(ACCOUNTS_STORE_KEY);
2033
+ if (ethAccounts) {
2034
+ return {
2035
+ id: request.id,
2036
+ jsonrpc: "2.0",
2037
+ result: JSON.parse(ethAccounts),
2038
+ method: request.method
2039
+ };
2040
+ }
2041
+ } else if (request.method === "eth_chainId") {
2042
+ const ethChainId = yield this.kvstore.get(CHAIN_STORE_KEY);
2043
+ if (ethChainId) {
2044
+ return {
2045
+ id: request.id,
2046
+ jsonrpc: "2.0",
2047
+ result: JSON.parse(ethChainId),
1673
2048
  method: request.method
1674
2049
  };
1675
2050
  }
@@ -1680,8 +2055,17 @@ var MWPTransport = class {
1680
2055
  return __async(this, null, function* () {
1681
2056
  if (CACHED_METHOD_LIST.includes(request.method)) {
1682
2057
  yield this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
2058
+ } else if (request.method === "eth_accounts") {
2059
+ yield this.kvstore.set(
2060
+ ACCOUNTS_STORE_KEY,
2061
+ JSON.stringify(response.result)
2062
+ );
2063
+ } else if (request.method === "eth_chainId") {
2064
+ yield this.kvstore.set(CHAIN_STORE_KEY, JSON.stringify(response.result));
1683
2065
  } else if (CACHED_RESET_METHOD_LIST.includes(request.method)) {
1684
2066
  yield this.kvstore.delete(SESSION_STORE_KEY);
2067
+ yield this.kvstore.delete(ACCOUNTS_STORE_KEY);
2068
+ yield this.kvstore.delete(CHAIN_STORE_KEY);
1685
2069
  }
1686
2070
  });
1687
2071
  }
@@ -1691,11 +2075,14 @@ var MWPTransport = class {
1691
2075
  jsonrpc: "2.0",
1692
2076
  id: `${this.__reqId++}`
1693
2077
  }, payload);
1694
- const cachedWalletSession = yield this.fetchCachedWalletSession(request);
2078
+ const cachedWalletSession = yield this.getCachedResponse(request);
1695
2079
  if (cachedWalletSession) {
1696
2080
  this.notifyCallbacks(cachedWalletSession);
1697
2081
  return cachedWalletSession;
1698
2082
  }
2083
+ if (!this.isConnected()) {
2084
+ yield this.attemptResumeSession();
2085
+ }
1699
2086
  return new Promise((resolve, reject) => {
1700
2087
  var _a;
1701
2088
  const timeout = setTimeout(() => {
@@ -1705,15 +2092,16 @@ var MWPTransport = class {
1705
2092
  request,
1706
2093
  method: request.method,
1707
2094
  resolve: (response) => __async(this, null, function* () {
1708
- if (CACHED_METHOD_LIST.includes(request.method)) {
1709
- yield this.storeWalletSession(request, response);
1710
- }
2095
+ yield this.storeWalletSession(request, response);
1711
2096
  return resolve(response);
1712
2097
  }),
1713
2098
  reject,
1714
2099
  timeout
1715
2100
  });
1716
- this.dappClient.sendRequest(request).catch(reject);
2101
+ this.dappClient.sendRequest({
2102
+ name: MULTICHAIN_PROVIDER_STREAM_NAME,
2103
+ data: request
2104
+ }).catch(reject);
1717
2105
  });
1718
2106
  });
1719
2107
  }
@@ -1753,21 +2141,22 @@ var KeyManager = class {
1753
2141
  var keymanager = new KeyManager();
1754
2142
 
1755
2143
  // src/multichain/index.ts
2144
+ init_utils();
1756
2145
  var logger2 = createLogger("metamask-sdk:core");
1757
2146
  var MultichainSDK = class _MultichainSDK extends MultichainCore {
1758
2147
  constructor(options) {
1759
- var _a, _b, _c, _d, _e, _f;
1760
- const withInfuraRPCMethods = setupInfuraProvider(options);
1761
- const withDappMetadata = setupDappMetadata(withInfuraRPCMethods);
2148
+ var _a, _b, _c, _d, _e, _f, _g;
2149
+ const withDappMetadata = setupDappMetadata(options);
2150
+ const integrationType = ((_a = options.analytics) == null ? void 0 : _a.enabled) ? options.analytics.integrationType : "direct";
1762
2151
  const allOptions = __spreadProps(__spreadValues({}, withDappMetadata), {
1763
2152
  ui: __spreadProps(__spreadValues({}, withDappMetadata.ui), {
1764
- preferExtension: (_a = withDappMetadata.ui.preferExtension) != null ? _a : true,
1765
- preferDesktop: (_b = withDappMetadata.ui.preferDesktop) != null ? _b : false,
1766
- 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
1767
2156
  }),
1768
- analytics: __spreadProps(__spreadValues({}, (_d = options.analytics) != null ? _d : {}), {
1769
- enabled: (_f = (_e = options.analytics) == null ? void 0 : _e.enabled) != null ? _f : true,
1770
- 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
1771
2160
  })
1772
2161
  });
1773
2162
  super(allOptions);
@@ -1788,6 +2177,10 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1788
2177
  });
1789
2178
  }
1790
2179
  get provider() {
2180
+ if (!this.__provider && this.__transport) {
2181
+ this.__provider = getMultichainClient({ transport: this.__transport });
2182
+ return this.__provider;
2183
+ }
1791
2184
  if (!this.__provider) {
1792
2185
  throw new Error("Provider not initialized, establish connection first");
1793
2186
  }
@@ -1808,6 +2201,9 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1808
2201
  get storage() {
1809
2202
  return this.options.storage;
1810
2203
  }
2204
+ get transportType() {
2205
+ return this.__transport instanceof MWPTransport ? "mwp" /* MWP */ : "browser" /* Browser */;
2206
+ }
1811
2207
  get sdkInfo() {
1812
2208
  var _a;
1813
2209
  return `Sdk/Javascript SdkVersion/${getVersion()} Platform/${getPlatformType()} dApp/${(_a = this.options.dapp.url) != null ? _a : this.options.dapp.name} dAppTitle/${this.options.dapp.name}`;
@@ -1844,12 +2240,12 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1844
2240
  const { integrationType } = (_b = this.options.analytics) != null ? _b : {
1845
2241
  integrationType: ""
1846
2242
  };
1847
- analytics.setGlobalProperty("sdk_version", version);
1848
- analytics.setGlobalProperty("dapp_id", dappId);
1849
- analytics.setGlobalProperty("anon_id", anonId);
1850
- analytics.setGlobalProperty("platform", platform);
1851
- analytics.setGlobalProperty("integration_type", integrationType);
1852
- 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();
1853
2249
  });
1854
2250
  }
1855
2251
  onTransportNotification(payload) {
@@ -1862,13 +2258,11 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1862
2258
  }
1863
2259
  getStoredTransport() {
1864
2260
  return __async(this, null, function* () {
1865
- const { ui } = this.options;
1866
- const { preferExtension = true } = ui;
1867
2261
  const transportType = yield this.storage.getTransport();
1868
2262
  const hasExtensionInstalled = yield hasExtension();
1869
2263
  if (transportType) {
1870
2264
  if (transportType === "browser" /* Browser */) {
1871
- if (hasExtensionInstalled && preferExtension) {
2265
+ if (hasExtensionInstalled) {
1872
2266
  const apiTransport = new DefaultTransport();
1873
2267
  this.__transport = apiTransport;
1874
2268
  this.listener = apiTransport.onNotification(
@@ -1876,7 +2270,7 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1876
2270
  );
1877
2271
  return apiTransport;
1878
2272
  }
1879
- } else if (transportType === "mwp" /* MPW */) {
2273
+ } else if (transportType === "mwp" /* MWP */) {
1880
2274
  const { adapter: kvstore } = this.options.storage;
1881
2275
  const dappClient = yield this.createDappClient();
1882
2276
  const apiTransport = new MWPTransport(dappClient, kvstore);
@@ -1902,7 +2296,7 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1902
2296
  }
1903
2297
  this.state = "connected";
1904
2298
  if (this.transport instanceof MWPTransport) {
1905
- yield this.storage.setTransport("mwp" /* MPW */);
2299
+ yield this.storage.setTransport("mwp" /* MWP */);
1906
2300
  } else {
1907
2301
  yield this.storage.setTransport("browser" /* Browser */);
1908
2302
  }
@@ -1913,14 +2307,24 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1913
2307
  }
1914
2308
  init() {
1915
2309
  return __async(this, null, function* () {
1916
- var _a;
2310
+ var _a, _b;
1917
2311
  try {
1918
2312
  if (typeof window !== "undefined" && ((_a = window.mmsdk) == null ? void 0 : _a.isInitialized)) {
1919
2313
  logger2("MetaMaskSDK: init already initialized");
1920
2314
  } else {
1921
2315
  yield this.setupAnalytics();
1922
2316
  yield this.setupTransport();
1923
- 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
+ }
1924
2328
  if (typeof window !== "undefined") {
1925
2329
  window.mmsdk = this;
1926
2330
  }
@@ -1962,7 +2366,7 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
1962
2366
  this.listener = this.transport.onNotification(
1963
2367
  this.onTransportNotification.bind(this)
1964
2368
  );
1965
- yield this.storage.setTransport("mwp" /* MPW */);
2369
+ yield this.storage.setTransport("mwp" /* MWP */);
1966
2370
  });
1967
2371
  }
1968
2372
  onBeforeUnload() {
@@ -2018,7 +2422,7 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2018
2422
  this.options.ui.factory.unload();
2019
2423
  (_a2 = this.options.ui.factory.modal) == null ? void 0 : _a2.unmount();
2020
2424
  this.state = "connected";
2021
- return this.storage.setTransport("mwp" /* MPW */);
2425
+ return this.storage.setTransport("mwp" /* MWP */);
2022
2426
  }).catch((error) => {
2023
2427
  if (error instanceof ProtocolError) {
2024
2428
  if (error.code !== ErrorCode.REQUEST_EXPIRED) {
@@ -2034,7 +2438,7 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2034
2438
  }),
2035
2439
  (error) => __async(this, null, function* () {
2036
2440
  if (!error) {
2037
- yield this.storage.setTransport("mwp" /* MPW */);
2441
+ yield this.storage.setTransport("mwp" /* MWP */);
2038
2442
  resolve();
2039
2443
  } else {
2040
2444
  yield this.storage.removeTransport();
@@ -2122,52 +2526,128 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2122
2526
  }));
2123
2527
  });
2124
2528
  }
2125
- handleConnection(promise) {
2529
+ handleConnection(promise, scopes, transportType) {
2126
2530
  return __async(this, null, function* () {
2127
2531
  this.state = "connecting";
2128
- return promise.then(() => {
2532
+ return promise.then(() => __async(this, null, function* () {
2533
+ var _a;
2129
2534
  this.state = "connected";
2130
- }).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;
2131
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
+ }
2132
2572
  return Promise.reject(error);
2133
- });
2573
+ }));
2134
2574
  });
2135
2575
  }
2136
- connect(scopes, caipAccountIds) {
2576
+ connect(scopes, caipAccountIds, forceRequest) {
2137
2577
  return __async(this, null, function* () {
2138
- var _a;
2578
+ var _a, _b;
2139
2579
  const { ui } = this.options;
2140
2580
  const platformType = getPlatformType();
2141
2581
  const isWeb = platformType === "in-app-browser" /* MetaMaskMobileWebview */ || platformType === "web-desktop" /* DesktopWeb */;
2142
- const { preferExtension = true, preferDesktop = false } = ui;
2582
+ const { preferExtension = true, showInstallModal = false } = ui;
2143
2583
  const secure = isSecure();
2144
2584
  const hasExtensionInstalled = yield hasExtension();
2145
- 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) {
2146
2610
  return this.handleConnection(
2147
- this.__transport.connect({ scopes, caipAccountIds }).then(() => {
2611
+ this.__transport.connect({ scopes, caipAccountIds, forceRequest }).then(() => {
2148
2612
  if (this.__transport instanceof MWPTransport) {
2149
- return this.storage.setTransport("mwp" /* MPW */);
2613
+ return this.storage.setTransport("mwp" /* MWP */);
2150
2614
  } else {
2151
2615
  return this.storage.setTransport("browser" /* Browser */);
2152
2616
  }
2153
- })
2617
+ }),
2618
+ scopes,
2619
+ transportType
2620
+ );
2621
+ }
2622
+ if (platformType === "in-app-browser" /* MetaMaskMobileWebview */) {
2623
+ const defaultTransport = yield this.setupDefaultTransport();
2624
+ return this.handleConnection(
2625
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2626
+ scopes,
2627
+ transportType
2154
2628
  );
2155
2629
  }
2156
2630
  if (isWeb && hasExtensionInstalled && preferExtension) {
2157
2631
  const defaultTransport = yield this.setupDefaultTransport();
2158
2632
  return this.handleConnection(
2159
- defaultTransport.connect({ scopes, caipAccountIds })
2633
+ defaultTransport.connect({ scopes, caipAccountIds, forceRequest }),
2634
+ scopes,
2635
+ transportType
2160
2636
  );
2161
2637
  }
2162
2638
  yield this.setupMWP();
2163
- const isDesktopPreferred = hasExtensionInstalled ? preferDesktop : !preferExtension || preferDesktop;
2164
- if (secure && !isDesktopPreferred) {
2639
+ const shouldShowInstallModal = hasExtensionInstalled ? showInstallModal : !preferExtension || showInstallModal;
2640
+ if (secure && !shouldShowInstallModal) {
2165
2641
  return this.handleConnection(
2166
- this.deeplinkConnect(scopes, caipAccountIds)
2642
+ this.deeplinkConnect(scopes, caipAccountIds),
2643
+ scopes,
2644
+ transportType
2167
2645
  );
2168
2646
  }
2169
2647
  return this.handleConnection(
2170
- this.showInstallModal(isDesktopPreferred, scopes, caipAccountIds)
2648
+ this.showInstallModal(shouldShowInstallModal, scopes, caipAccountIds),
2649
+ scopes,
2650
+ transportType
2171
2651
  );
2172
2652
  });
2173
2653
  }
@@ -2202,6 +2682,26 @@ var MultichainSDK = class _MultichainSDK extends MultichainCore {
2202
2682
  return requestRouter.invokeMethod(request);
2203
2683
  });
2204
2684
  }
2685
+ // DRY THIS WITH REQUEST ROUTER
2686
+ openDeeplinkIfNeeded() {
2687
+ const { ui, mobile } = this.options;
2688
+ const { showInstallModal = false } = ui != null ? ui : {};
2689
+ const secure = isSecure();
2690
+ const shouldOpenDeeplink = secure && !showInstallModal;
2691
+ if (shouldOpenDeeplink) {
2692
+ setTimeout(() => {
2693
+ if (mobile == null ? void 0 : mobile.preferredOpenLink) {
2694
+ mobile.preferredOpenLink(METAMASK_DEEPLINK_BASE, "_self");
2695
+ } else {
2696
+ openDeeplink(
2697
+ this.options,
2698
+ METAMASK_DEEPLINK_BASE,
2699
+ METAMASK_CONNECT_BASE_URL
2700
+ );
2701
+ }
2702
+ }, 10);
2703
+ }
2704
+ }
2205
2705
  };
2206
2706
 
2207
2707
  // src/store/index.ts
@@ -2400,25 +2900,34 @@ function preloadQR() {
2400
2900
  }
2401
2901
 
2402
2902
  // src/ui/index.ts
2903
+ init_utils();
2403
2904
  var __instance;
2404
2905
  function preload() {
2405
2906
  return __async(this, null, function* () {
2406
- __instance != null ? __instance : __instance = yield import(
2407
- // Use a non-literal specifier to avoid Vite static analysis of deep imports
2408
- // and gracefully handle absence of the Stencil loader in this package build.
2409
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2410
- // @ts-ignore
2411
- "@metamask/multichain-ui".concat("/dist/loader/index.js")
2412
- // Prefer ESM loader in browsers
2413
- ).then((loader) => __async(null, null, function* () {
2414
- if (typeof (loader == null ? void 0 : loader.defineCustomElements) === "function") {
2415
- loader.defineCustomElements();
2416
- }
2417
- return Promise.resolve(loader);
2418
- })).catch((error) => __async(null, null, function* () {
2419
- console.error(`Gracefully Failed to load modal customElements:`, error);
2420
- return Promise.resolve(void 0);
2421
- }));
2907
+ if (true) {
2908
+ __instance != null ? __instance : __instance = yield import("@metamask/multichain-ui/dist/loader/index.js").then((loader) => __async(null, null, function* () {
2909
+ if (typeof (loader == null ? void 0 : loader.defineCustomElements) === "function") {
2910
+ loader.defineCustomElements();
2911
+ }
2912
+ return Promise.resolve(loader);
2913
+ })).catch((error) => __async(null, null, function* () {
2914
+ console.error(`Gracefully Failed to load modal customElements:`, error);
2915
+ return Promise.resolve(void 0);
2916
+ }));
2917
+ } else {
2918
+ const dynamicImport = (0, eval)("import");
2919
+ __instance != null ? __instance : __instance = yield dynamicImport(
2920
+ "@metamask/multichain-ui/dist/loader/index.js"
2921
+ ).then((loader) => __async(null, null, function* () {
2922
+ if (typeof (loader == null ? void 0 : loader.defineCustomElements) === "function") {
2923
+ loader.defineCustomElements();
2924
+ }
2925
+ return Promise.resolve(loader);
2926
+ })).catch((error) => __async(null, null, function* () {
2927
+ console.error(`Gracefully Failed to load modal customElements:`, error);
2928
+ return Promise.resolve(void 0);
2929
+ }));
2930
+ }
2422
2931
  });
2423
2932
  }
2424
2933
  var ModalFactory = class {
@@ -2510,7 +3019,7 @@ var ModalFactory = class {
2510
3019
  onStartDesktopOnboarding() {
2511
3020
  new MetaMaskOnboarding().startOnboarding();
2512
3021
  }
2513
- renderInstallModal(preferDesktop, createConnectionRequest, successCallback) {
3022
+ renderInstallModal(showInstallModal, createConnectionRequest, successCallback) {
2514
3023
  return __async(this, null, function* () {
2515
3024
  var _a;
2516
3025
  (_a = this.modal) == null ? void 0 : _a.unmount();
@@ -2523,7 +3032,7 @@ var ModalFactory = class {
2523
3032
  expiresIn: (connectionRequest.sessionRequest.expiresAt - Date.now()) / 1e3,
2524
3033
  connectionRequest,
2525
3034
  parentElement,
2526
- preferDesktop,
3035
+ showInstallModal,
2527
3036
  link: qrCodeLink,
2528
3037
  sdkVersion: getVersion(),
2529
3038
  generateQRCode: (request) => __async(this, null, function* () {
@@ -2600,10 +3109,12 @@ export {
2600
3109
  getPlatformType,
2601
3110
  getTransportType,
2602
3111
  getVersion,
3112
+ getWalletActionAnalyticsProperties,
2603
3113
  hasExtension,
2604
3114
  infuraRpcUrls,
2605
3115
  isEnabled,
2606
3116
  isMetamaskExtensionInstalled,
3117
+ isRejectionError,
2607
3118
  isSecure
2608
3119
  };
2609
3120
  //# sourceMappingURL=connect-multichain.mjs.map