@metamask/connect-multichain 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/README.md +21 -19
  3. package/dist/browser/es/connect-multichain.d.mts +3 -0
  4. package/dist/browser/es/connect-multichain.mjs +134 -58
  5. package/dist/browser/es/connect-multichain.mjs.map +1 -1
  6. package/dist/browser/es/metafile-esm.json +1 -1
  7. package/dist/browser/iife/connect-multichain.d.ts +3 -0
  8. package/dist/browser/iife/connect-multichain.js +2737 -5000
  9. package/dist/browser/iife/connect-multichain.js.map +1 -1
  10. package/dist/browser/iife/metafile-iife.json +1 -1
  11. package/dist/browser/umd/connect-multichain.d.ts +3 -0
  12. package/dist/browser/umd/connect-multichain.js +132 -56
  13. package/dist/browser/umd/connect-multichain.js.map +1 -1
  14. package/dist/browser/umd/metafile-cjs.json +1 -1
  15. package/dist/node/cjs/connect-multichain.d.ts +3 -0
  16. package/dist/node/cjs/connect-multichain.js +132 -56
  17. package/dist/node/cjs/connect-multichain.js.map +1 -1
  18. package/dist/node/cjs/metafile-cjs.json +1 -1
  19. package/dist/node/es/connect-multichain.d.mts +3 -0
  20. package/dist/node/es/connect-multichain.mjs +134 -58
  21. package/dist/node/es/connect-multichain.mjs.map +1 -1
  22. package/dist/node/es/metafile-esm.json +1 -1
  23. package/dist/react-native/es/connect-multichain.d.mts +3 -0
  24. package/dist/react-native/es/connect-multichain.mjs +134 -58
  25. package/dist/react-native/es/connect-multichain.mjs.map +1 -1
  26. package/dist/react-native/es/metafile-esm.json +1 -1
  27. package/dist/src/domain/multichain/types.d.ts +3 -0
  28. package/dist/src/domain/multichain/types.d.ts.map +1 -1
  29. package/dist/src/multichain/index.d.ts.map +1 -1
  30. package/dist/src/multichain/index.js +65 -22
  31. package/dist/src/multichain/index.js.map +1 -1
  32. package/dist/src/multichain/transports/default/index.d.ts +1 -0
  33. package/dist/src/multichain/transports/default/index.d.ts.map +1 -1
  34. package/dist/src/multichain/transports/default/index.js +28 -32
  35. package/dist/src/multichain/transports/default/index.js.map +1 -1
  36. package/dist/src/multichain/transports/multichainApiClientWrapper/index.d.ts.map +1 -1
  37. package/dist/src/multichain/transports/multichainApiClientWrapper/index.js +0 -1
  38. package/dist/src/multichain/transports/multichainApiClientWrapper/index.js.map +1 -1
  39. package/dist/src/multichain/transports/mwp/KeyManager.d.ts +1 -0
  40. package/dist/src/multichain/transports/mwp/KeyManager.d.ts.map +1 -1
  41. package/dist/src/multichain/transports/mwp/KeyManager.js +4 -1
  42. package/dist/src/multichain/transports/mwp/KeyManager.js.map +1 -1
  43. package/dist/src/multichain/transports/mwp/index.d.ts +1 -0
  44. package/dist/src/multichain/transports/mwp/index.d.ts.map +1 -1
  45. package/dist/src/multichain/transports/mwp/index.js +17 -7
  46. package/dist/src/multichain/transports/mwp/index.js.map +1 -1
  47. package/dist/src/multichain/utils/index.d.ts.map +1 -1
  48. package/dist/src/multichain/utils/index.js +37 -0
  49. package/dist/src/multichain/utils/index.js.map +1 -1
  50. package/dist/types/connect-multichain.d.ts +3 -0
  51. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.8.0]
11
+
12
+ ### Added
13
+
14
+ - Enable `ConnectMultichain` to automatically handle `wallet_sessionChanged` events when MetaMask extension is detected (Desktop Chrome/Firefox, or Mobile In-App Browser) and `preferExtension: true` without needing the user to explicitly connect via `ConnectMultichain.connect()` ([#198](https://github.com/MetaMask/connect-monorepo/pull/198/))
15
+
16
+ ### Changed
17
+
18
+ - Bump `@metamask/mobile-wallet-protocol-core` to `^0.4.0` ([#201](https://github.com/MetaMask/connect-monorepo/pull/201))
19
+ - Bump `@metamask/mobile-wallet-protocol-dapp-client` to `^0.3.0` ([#201](https://github.com/MetaMask/connect-monorepo/pull/201))
20
+
21
+ ## [0.7.0]
22
+
23
+ ### Changed
24
+
25
+ - Correct README documentation across `connect-solana`, `connect-evm`, and `connect-multichain` to match actual API behaviour. ([#194](https://github.com/MetaMask/connect-monorepo/pull/194))
26
+ - Redact logs ([#191](https://github.com/MetaMask/connect-monorepo/pull/191]))
27
+ - Pin eciesjs to exact version 0.4.17 ([#188](https://github.com/MetaMask/connect-monorepo/pull/188))
28
+
29
+ ### Fixed
30
+
31
+ - Fix uncaught exception in `parseWalletError` when the wallet returns error codes outside the EIP-1193 provider range (1000–4999), such as standard JSON-RPC codes like `-32603` (Internal error). This prevented Solana request rejections from being handled gracefully. ([#189](https://github.com/MetaMask/connect-monorepo/pull/189))
32
+
10
33
  ## [0.6.0]
11
34
 
12
35
  ### Added
@@ -15,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
15
38
 
16
39
  ### Changed
17
40
 
41
+ - Normalize non-http(s) dapp URLs to valid https URLs on React Native to prevent RPC middleware crashes ([#190](https://github.com/MetaMask/connect-monorepo/pull/190))
18
42
  - **BREAKING** `createMultichainClient()` now returns a singleton. Any incoming constructor params on subsequent calls to `createMultichainClient()` will be applied to the existing singleton instance except for the `dapp`, `storage`, and `ui.factory` param options. ([#157](https://github.com/MetaMask/connect-monorepo/pull/157))
19
43
  - **BREAKING** `ConnectMultichain.openDeeplinkIfNeeded()` is renamed to `openSimpleDeeplinkIfNeeded()` ([#176](https://github.com/MetaMask/connect-monorepo/pull/176))
20
44
  - `ConnectMultichain.connect()` now throws an `'Existing connection is pending. Please check your MetaMask Mobile app to continue.'` error if there is already an pending connection attempt. Previously it would abort that ongoing connection in favor of a new one. ([#157](https://github.com/MetaMask/connect-monorepo/pull/157))
@@ -157,7 +181,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
157
181
 
158
182
  - Initial release
159
183
 
160
- [Unreleased]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.6.0...HEAD
184
+ [Unreleased]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.8.0...HEAD
185
+ [0.8.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.7.0...@metamask/connect-multichain@0.8.0
186
+ [0.7.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.6.0...@metamask/connect-multichain@0.7.0
161
187
  [0.6.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.5.3...@metamask/connect-multichain@0.6.0
162
188
  [0.5.3]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.5.2...@metamask/connect-multichain@0.5.3
163
189
  [0.5.2]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.5.1...@metamask/connect-multichain@0.5.2
package/README.md CHANGED
@@ -134,26 +134,28 @@ This package is written in TypeScript and includes full type definitions. No add
134
134
 
135
135
  Factory function to create a new Multichain SDK instance.
136
136
 
137
+ > **Singleton:** `createMultichainClient` returns a single shared instance per global context. Calling it a second time with different options will merge the new `api.supportedNetworks`, `ui.*`, `mobile.*`, `transport.extensionId`, and `debug` values into the existing instance rather than creating a new one. The `dapp` value is never overwritten on subsequent calls.
138
+
137
139
  #### Parameters
138
140
 
139
- | Option | Type | Required | Description |
140
- | --------------------------- | --------------------------------------------- | -------- | ---------------------------------------------- |
141
- | `dapp.name` | `string` | Yes | Name of your dApp |
142
- | `api.supportedNetworks` | `RpcUrlsMap` | Yes | Map of CAIP chain IDs to RPC URLs |
143
- | `dapp.url` | `string` | No | URL of your dApp |
144
- | `dapp.iconUrl` | `string` | No | Icon URL for your dApp |
145
- | `dapp.base64Icon` | `string` | No | Base64-encoded icon (alternative to iconUrl) |
146
- | `storage` | `StoreClient` | No | Custom storage adapter |
147
- | `ui.factory` | `BaseModalFactory` | No | Custom modal factory |
148
- | `ui.headless` | `boolean` | No | Run without UI (for custom QR implementations) |
149
- | `ui.preferExtension` | `boolean` | No | Prefer browser extension (default: true) |
150
- | `ui.showInstallModal` | `boolean` | No | Show installation modal |
151
- | `mobile.preferredOpenLink` | `(deeplink: string, target?: string) => void` | No | Custom deeplink handler |
152
- | `mobile.useDeeplink` | `boolean` | No | Use `metamask://` instead of universal links |
153
- | `analytics.integrationType` | `string` | No | Integration type for analytics |
154
- | `transport.extensionId` | `string` | No | Custom extension ID |
155
- | `transport.onNotification` | `(notification: unknown) => void` | No | Notification handler |
156
- | `debug` | `boolean` | No | Enable debug logging |
141
+ | Option | Type | Required | Description |
142
+ | --------------------------- | --------------------------------------------- | -------- | ----------------------------------------------------------------------------- |
143
+ | `dapp.name` | `string` | Yes | Name of your dApp |
144
+ | `api.supportedNetworks` | `RpcUrlsMap` | Yes | Map of [CAIP-2 chain IDs](https://chainagnostic.org/CAIPs/caip-2) to RPC URLs |
145
+ | `dapp.url` | `string` | No | URL of your dApp |
146
+ | `dapp.iconUrl` | `string` | No | Icon URL for your dApp |
147
+ | `dapp.base64Icon` | `string` | No | Base64-encoded icon (alternative to iconUrl) |
148
+ | `storage` | `StoreClient` | No | Custom storage adapter |
149
+ | `ui.factory` | `BaseModalFactory` | No | Custom modal factory |
150
+ | `ui.headless` | `boolean` | No | Run without UI (for custom QR implementations) |
151
+ | `ui.preferExtension` | `boolean` | No | Prefer browser extension (default: true) |
152
+ | `ui.showInstallModal` | `boolean` | No | Show installation modal |
153
+ | `mobile.preferredOpenLink` | `(deeplink: string, target?: string) => void` | No | Custom deeplink handler |
154
+ | `mobile.useDeeplink` | `boolean` | No | Use `metamask://` instead of universal links |
155
+ | `analytics.integrationType` | `string` | No | Integration type for analytics |
156
+ | `transport.extensionId` | `string` | No | Custom extension ID |
157
+ | `transport.onNotification` | `(notification: unknown) => void` | No | Notification handler |
158
+ | `debug` | `boolean` | No | Enable debug logging |
157
159
 
158
160
  #### Returns
159
161
 
@@ -347,7 +349,7 @@ Generates Infura RPC URLs for common networks keyed by CAIP Chain ID.
347
349
 
348
350
  **Returns**
349
351
 
350
- A map of hex chain IDs to Infura RPC URLs. See https://docs.metamask.io/services
352
+ A map of [CAIP-2 chain IDs](https://chainagnostic.org/CAIPs/caip-2) to Infura RPC URLs. See https://docs.metamask.io/services
351
353
 
352
354
  ```typescript
353
355
  import { getInfuraRpcUrls } from '@metamask/connect-multichain';
@@ -369,6 +369,8 @@ declare function hasExtension(): Promise<boolean>;
369
369
  type DappSettings = {
370
370
  name: string;
371
371
  url?: string;
372
+ /** The original non-http(s) URL before normalization on React Native platforms */
373
+ nativeScheme?: string;
372
374
  } & ({
373
375
  iconUrl?: string;
374
376
  } | {
@@ -453,6 +455,7 @@ type MergeableMultichainOptions = Omit<MultichainOptions, 'dapp' | 'analytics' |
453
455
  */
454
456
  type CreateMultichainFN = (options: MultiChainFNOptions) => Promise<MultichainCore>;
455
457
  type ExtendedTransport = Omit<Transport, 'connect'> & {
458
+ init: () => Promise<void>;
456
459
  connect: (props?: {
457
460
  scopes: Scope[];
458
461
  caipAccountIds: CaipAccountId[];
@@ -781,6 +781,21 @@ function getOptionalScopes(scopes) {
781
781
  {}
782
782
  );
783
783
  }
784
+ function normalizeNativeUrl(url) {
785
+ var _a3;
786
+ const httpPattern = /^https?:\/\//u;
787
+ if (httpPattern.test(url)) {
788
+ return void 0;
789
+ }
790
+ const schemeMatch = url.match(/^([^:]*):\/\//u);
791
+ const rawScheme = (_a3 = schemeMatch == null ? void 0 : schemeMatch[1]) != null ? _a3 : url;
792
+ const sanitized = rawScheme.toLowerCase().replace(/[^a-z0-9-]/gu, "-").replace(/^-+|-+$/gu, "");
793
+ const subdomain = (sanitized || "unknown").slice(0, 63).replace(/-+$/u, "");
794
+ return {
795
+ url: `https://${subdomain}.rn.dapp.local`,
796
+ nativeScheme: url
797
+ };
798
+ }
784
799
  function setupDappMetadata(options) {
785
800
  var _a3, _b;
786
801
  const platform = getPlatformType();
@@ -796,6 +811,18 @@ function setupDappMetadata(options) {
796
811
  if (!((_b = options.dapp) == null ? void 0 : _b.url)) {
797
812
  throw new Error("You must provide dapp url");
798
813
  }
814
+ if (platform === "react-native" /* ReactNative */ && options.dapp.url) {
815
+ const normalized = normalizeNativeUrl(options.dapp.url);
816
+ if (normalized) {
817
+ console.info(
818
+ `Normalizing dapp URL for React Native: "${options.dapp.url}" -> "${normalized.url}"`
819
+ );
820
+ options.dapp = __spreadProps(__spreadValues({}, options.dapp), {
821
+ url: normalized.url,
822
+ nativeScheme: normalized.nativeScheme
823
+ });
824
+ }
825
+ }
799
826
  const BASE_64_ICON_MAX_LENGTH = 163400;
800
827
  const urlPattern = /^(http|https):\/\/[^\s]*$/u;
801
828
  if (options.dapp) {
@@ -1561,7 +1588,7 @@ import {
1561
1588
  getDefaultTransport
1562
1589
  } from "@metamask/multichain-api-client";
1563
1590
  var DEFAULT_REQUEST_TIMEOUT = 60 * 1e3;
1564
- var _notificationCallbacks, _transport, _defaultRequestOptions, _pendingRequests, _handleResponseListener, _handleNotificationListener, _DefaultTransport_instances, notifyCallbacks_fn, isMetamaskProviderEvent_fn, handleResponse_fn, handleNotification_fn, setupMessageListener_fn;
1591
+ var _notificationCallbacks, _transport, _defaultRequestOptions, _pendingRequests, _handleResponseListener, _handleNotificationListener, _DefaultTransport_instances, notifyCallbacks_fn, isMetamaskProviderEvent_fn, handleResponse_fn, handleNotification_fn, setupMessageListener_fn, init_fn;
1565
1592
  var DefaultTransport = class {
1566
1593
  constructor() {
1567
1594
  __privateAdd(this, _DefaultTransport_instances);
@@ -1609,11 +1636,31 @@ var DefaultTransport = class {
1609
1636
  });
1610
1637
  });
1611
1638
  }
1639
+ init() {
1640
+ return __async(this, null, function* () {
1641
+ yield __privateMethod(this, _DefaultTransport_instances, init_fn).call(this);
1642
+ let walletSession = { sessionScopes: {} };
1643
+ try {
1644
+ const sessionRequest = yield this.request(
1645
+ { method: "wallet_getSession" },
1646
+ __privateGet(this, _defaultRequestOptions)
1647
+ );
1648
+ walletSession = sessionRequest.result;
1649
+ } catch (e) {
1650
+ console.error(
1651
+ "Failed to get wallet session during DefaultTransport init"
1652
+ );
1653
+ }
1654
+ __privateMethod(this, _DefaultTransport_instances, notifyCallbacks_fn).call(this, {
1655
+ method: "wallet_sessionChanged",
1656
+ params: walletSession
1657
+ });
1658
+ });
1659
+ }
1612
1660
  connect(options) {
1613
1661
  return __async(this, null, function* () {
1614
1662
  var _a3, _b, _c, _d, _e;
1615
- __privateMethod(this, _DefaultTransport_instances, setupMessageListener_fn).call(this);
1616
- yield __privateGet(this, _transport).connect();
1663
+ yield __privateMethod(this, _DefaultTransport_instances, init_fn).call(this);
1617
1664
  const sessionRequest = yield this.request(
1618
1665
  { method: "wallet_getSession" },
1619
1666
  __privateGet(this, _defaultRequestOptions)
@@ -1670,26 +1717,6 @@ var DefaultTransport = class {
1670
1717
  disconnect() {
1671
1718
  return __async(this, arguments, function* (scopes = []) {
1672
1719
  yield this.request({ method: "wallet_revokeSession", params: { scopes } });
1673
- const response = yield this.request({ method: "wallet_getSession" });
1674
- const { sessionScopes } = response.result;
1675
- if (Object.keys(sessionScopes).length > 0) {
1676
- return;
1677
- }
1678
- __privateGet(this, _notificationCallbacks).clear();
1679
- if (__privateGet(this, _handleResponseListener)) {
1680
- window.removeEventListener("message", __privateGet(this, _handleResponseListener));
1681
- __privateSet(this, _handleResponseListener, void 0);
1682
- }
1683
- if (__privateGet(this, _handleNotificationListener)) {
1684
- window.removeEventListener("message", __privateGet(this, _handleNotificationListener));
1685
- __privateSet(this, _handleNotificationListener, void 0);
1686
- }
1687
- for (const [, request] of __privateGet(this, _pendingRequests)) {
1688
- clearTimeout(request.timeout);
1689
- request.reject(new Error("Transport disconnected"));
1690
- }
1691
- __privateGet(this, _pendingRequests).clear();
1692
- yield __privateGet(this, _transport).disconnect();
1693
1720
  });
1694
1721
  }
1695
1722
  isConnected() {
@@ -1778,7 +1805,7 @@ handleNotification_fn = function(event) {
1778
1805
  return;
1779
1806
  }
1780
1807
  const responseData = (_b = (_a3 = event == null ? void 0 : event.data) == null ? void 0 : _a3.data) == null ? void 0 : _b.data;
1781
- if (typeof responseData === "object" && responseData.method === "metamask_chainChanged" || responseData.method === "metamask_accountsChanged") {
1808
+ if (typeof responseData === "object" && responseData !== null && (responseData.method === "metamask_chainChanged" || responseData.method === "metamask_accountsChanged")) {
1782
1809
  __privateMethod(this, _DefaultTransport_instances, notifyCallbacks_fn).call(this, responseData);
1783
1810
  }
1784
1811
  };
@@ -1791,6 +1818,12 @@ setupMessageListener_fn = function() {
1791
1818
  window.addEventListener("message", __privateGet(this, _handleResponseListener));
1792
1819
  window.addEventListener("message", __privateGet(this, _handleNotificationListener));
1793
1820
  };
1821
+ init_fn = function() {
1822
+ return __async(this, null, function* () {
1823
+ __privateMethod(this, _DefaultTransport_instances, setupMessageListener_fn).call(this);
1824
+ yield __privateGet(this, _transport).connect();
1825
+ });
1826
+ };
1794
1827
 
1795
1828
  // src/multichain/transports/multichainApiClientWrapper/index.ts
1796
1829
  init_utils2();
@@ -1878,7 +1911,6 @@ _notificationCallbacks2 = new WeakMap();
1878
1911
  _MultichainApiClientWrapperTransport_instances = new WeakSet();
1879
1912
  walletCreateSession_fn = function(request) {
1880
1913
  return __async(this, null, function* () {
1881
- console.log("\u{1F4DA} #walletCreateSession", request);
1882
1914
  const createSessionParams = request.params;
1883
1915
  const scopes = Object.keys(__spreadValues(__spreadValues({}, createSessionParams.optionalScopes), createSessionParams.requiredScopes));
1884
1916
  const scopeAccounts = [];
@@ -1959,7 +1991,7 @@ import { SessionStore } from "@metamask/mobile-wallet-protocol-core";
1959
1991
  import {
1960
1992
  TransportTimeoutError
1961
1993
  } from "@metamask/multichain-api-client";
1962
- import { providerErrors as providerErrors2, rpcErrors } from "@metamask/rpc-errors";
1994
+ import { JsonRpcError, providerErrors as providerErrors2, rpcErrors } from "@metamask/rpc-errors";
1963
1995
 
1964
1996
  // src/multichain/transports/constants.ts
1965
1997
  var MULTICHAIN_PROVIDER_STREAM_NAME = "metamask-multichain-provider";
@@ -2062,10 +2094,11 @@ var MWPTransport = class {
2062
2094
  parseWalletError(errorPayload) {
2063
2095
  const errorData = errorPayload;
2064
2096
  if (typeof errorData.code === "number" && typeof errorData.message === "string") {
2065
- return providerErrors2.custom({
2066
- code: errorData.code,
2067
- message: errorData.message
2068
- });
2097
+ const { code, message: message2 } = errorData;
2098
+ if (code >= 1e3 && code <= 4999) {
2099
+ return providerErrors2.custom({ code, message: message2 });
2100
+ }
2101
+ return new JsonRpcError(code, message2);
2069
2102
  }
2070
2103
  const message = errorPayload instanceof Error ? errorPayload.message : JSON.stringify(errorPayload);
2071
2104
  return rpcErrors.internal({ message });
@@ -2190,6 +2223,10 @@ var MWPTransport = class {
2190
2223
  }
2191
2224
  });
2192
2225
  }
2226
+ init() {
2227
+ return __async(this, null, function* () {
2228
+ });
2229
+ }
2193
2230
  // TODO: Rename this
2194
2231
  sendEip1193Message(payload, options) {
2195
2232
  return __async(this, null, function* () {
@@ -2229,7 +2266,11 @@ var MWPTransport = class {
2229
2266
  const { dappClient } = this;
2230
2267
  const session = yield this.getActiveSession();
2231
2268
  if (session) {
2232
- logger("active session found", session);
2269
+ logger("active session found", {
2270
+ id: session.id,
2271
+ channel: session.channel,
2272
+ expiresAt: session.expiresAt
2273
+ });
2233
2274
  }
2234
2275
  const storedSessionRequestBeforeConnectionAttempt = yield this.getStoredPendingSessionRequest();
2235
2276
  let timeout;
@@ -2538,7 +2579,7 @@ var MWPTransport = class {
2538
2579
  getActiveSession() {
2539
2580
  return __async(this, null, function* () {
2540
2581
  const { kvstore } = this;
2541
- const sessionStore = new SessionStore(kvstore);
2582
+ const sessionStore = yield SessionStore.create(kvstore);
2542
2583
  try {
2543
2584
  const [activeSession] = yield sessionStore.list();
2544
2585
  return activeSession;
@@ -2589,7 +2630,7 @@ var MWPTransport = class {
2589
2630
  };
2590
2631
 
2591
2632
  // src/multichain/transports/mwp/KeyManager.ts
2592
- import { decrypt, encrypt, PrivateKey } from "eciesjs";
2633
+ import { decrypt, encrypt, PrivateKey, PublicKey } from "eciesjs";
2593
2634
  var KeyManager = class {
2594
2635
  generateKeyPair() {
2595
2636
  const privateKey = new PrivateKey();
@@ -2612,6 +2653,9 @@ var KeyManager = class {
2612
2653
  return Buffer.from(decryptedBuffer).toString("utf8");
2613
2654
  });
2614
2655
  }
2656
+ validatePeerKey(key) {
2657
+ PublicKey.fromHex(Buffer.from(key).toString("hex"));
2658
+ }
2615
2659
  };
2616
2660
  var keymanager = new KeyManager();
2617
2661
 
@@ -2619,7 +2663,7 @@ var keymanager = new KeyManager();
2619
2663
  init_utils2();
2620
2664
  var logger2 = createLogger("metamask-sdk:core");
2621
2665
  var SINGLETON_KEY = "__METAMASK_CONNECT_MULTICHAIN_SINGLETON__";
2622
- var _a2, _provider, _providerTransportWrapper, _transport2, _dappClient, _beforeUnloadListener, _listener, _sdkInfo, _MetaMaskConnectMultichain_instances, setupAnalytics_fn, onTransportNotification_fn, getStoredTransport_fn, setupTransport_fn, init_fn, createDappClient_fn, setupMWP_fn, onBeforeUnload_fn, createBeforeUnloadListener_fn, renderInstallModalAsync_fn, showInstallModal_fn, headlessConnect_fn, setupDefaultTransport_fn, deeplinkConnect_fn, handleConnection_fn, getCaipSession_fn, openConnectDeeplinkIfNeeded_fn;
2666
+ var _a2, _provider, _providerTransportWrapper, _transport2, _dappClient, _beforeUnloadListener, _listener, _sdkInfo, _MetaMaskConnectMultichain_instances, setupAnalytics_fn, onTransportNotification_fn, getStoredTransport_fn, setupTransport_fn, init_fn2, createDappClient_fn, setupMWP_fn, onBeforeUnload_fn, createBeforeUnloadListener_fn, renderInstallModalAsync_fn, showInstallModal_fn, headlessConnect_fn, setupDefaultTransport_fn, deeplinkConnect_fn, handleConnection_fn, getCaipSession_fn, openConnectDeeplinkIfNeeded_fn;
2623
2667
  var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends MultichainCore {
2624
2668
  constructor(options) {
2625
2669
  var _a3, _b, _c, _d, _e, _f;
@@ -2657,6 +2701,9 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2657
2701
  }
2658
2702
  set status(value) {
2659
2703
  var _a3, _b;
2704
+ if (this._status === value) {
2705
+ return;
2706
+ }
2660
2707
  this._status = value;
2661
2708
  (_b = (_a3 = this.options.transport) == null ? void 0 : _a3.onNotification) == null ? void 0 : _b.call(_a3, {
2662
2709
  method: "stateChanged",
@@ -2712,7 +2759,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2712
2759
  if (isEnabled2) {
2713
2760
  enableDebug("metamask-sdk:core");
2714
2761
  }
2715
- yield __privateMethod(_a3 = instance, _MetaMaskConnectMultichain_instances, init_fn).call(_a3);
2762
+ yield __privateMethod(_a3 = instance, _MetaMaskConnectMultichain_instances, init_fn2).call(_a3);
2716
2763
  return instance;
2717
2764
  }))();
2718
2765
  globalObject[SINGLETON_KEY] = instancePromise;
@@ -2822,14 +2869,16 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2822
2869
  );
2823
2870
  yield (_a3 = __privateGet(this, _transport2)) == null ? void 0 : _a3.disconnect(scopes);
2824
2871
  if (remainingScopes.length === 0) {
2825
- yield (_b = __privateGet(this, _listener)) == null ? void 0 : _b.call(this);
2826
- (_c = __privateGet(this, _beforeUnloadListener)) == null ? void 0 : _c.call(this);
2827
2872
  yield this.storage.removeTransport();
2828
- __privateSet(this, _listener, void 0);
2829
- __privateSet(this, _beforeUnloadListener, void 0);
2830
- __privateSet(this, _transport2, void 0);
2831
- __privateGet(this, _providerTransportWrapper).clearTransportNotificationListener();
2832
- __privateSet(this, _dappClient, void 0);
2873
+ if (this.transportType !== "browser" /* Browser */) {
2874
+ yield (_b = __privateGet(this, _listener)) == null ? void 0 : _b.call(this);
2875
+ (_c = __privateGet(this, _beforeUnloadListener)) == null ? void 0 : _c.call(this);
2876
+ __privateSet(this, _listener, void 0);
2877
+ __privateSet(this, _beforeUnloadListener, void 0);
2878
+ __privateSet(this, _transport2, void 0);
2879
+ __privateGet(this, _providerTransportWrapper).clearTransportNotificationListener();
2880
+ __privateSet(this, _dappClient, void 0);
2881
+ }
2833
2882
  this.status = "disconnected";
2834
2883
  }
2835
2884
  });
@@ -2868,16 +2917,16 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2868
2917
  // without having to concern themselves with the current transport connection status.
2869
2918
  emitSessionChanged() {
2870
2919
  return __async(this, null, function* () {
2871
- var _a3;
2920
+ var _a3, _b;
2872
2921
  const emptySession = { sessionScopes: {} };
2873
- if (this.status !== "connected" && this.status !== "connecting") {
2922
+ if (!((_a3 = __privateGet(this, _transport2)) == null ? void 0 : _a3.isConnected())) {
2874
2923
  this.emit("wallet_sessionChanged", emptySession);
2875
2924
  return;
2876
2925
  }
2877
2926
  const response = yield this.transport.request({
2878
2927
  method: "wallet_getSession"
2879
2928
  });
2880
- this.emit("wallet_sessionChanged", (_a3 = response.result) != null ? _a3 : emptySession);
2929
+ this.emit("wallet_sessionChanged", (_b = response.result) != null ? _b : emptySession);
2881
2930
  });
2882
2931
  }
2883
2932
  };
@@ -2914,9 +2963,17 @@ setupAnalytics_fn = function() {
2914
2963
  };
2915
2964
  onTransportNotification_fn = function(payload) {
2916
2965
  return __async(this, null, function* () {
2917
- var _a3;
2966
+ var _a3, _b, _c;
2918
2967
  if (typeof payload === "object" && payload !== null && "method" in payload) {
2919
- this.emit(payload.method, (_a3 = payload.params) != null ? _a3 : payload.result);
2968
+ if (payload.method === "wallet_sessionChanged") {
2969
+ const sessionScopes = (_b = (_a3 = payload.params) == null ? void 0 : _a3.sessionScopes) != null ? _b : {};
2970
+ const hasScopes = Object.keys(sessionScopes).length > 0;
2971
+ if (this.status === "loaded" && !hasScopes) {
2972
+ return;
2973
+ }
2974
+ this.status = hasScopes ? "connected" : "disconnected";
2975
+ }
2976
+ this.emit(payload.method, (_c = payload.params) != null ? _c : payload.result);
2920
2977
  }
2921
2978
  });
2922
2979
  };
@@ -2954,6 +3011,7 @@ getStoredTransport_fn = function() {
2954
3011
  };
2955
3012
  setupTransport_fn = function() {
2956
3013
  return __async(this, null, function* () {
3014
+ var _a3;
2957
3015
  const transport = yield __privateMethod(this, _MetaMaskConnectMultichain_instances, getStoredTransport_fn).call(this);
2958
3016
  if (transport) {
2959
3017
  if (!this.transport.isConnected()) {
@@ -2968,10 +3026,20 @@ setupTransport_fn = function() {
2968
3026
  }
2969
3027
  } else {
2970
3028
  this.status = "loaded";
3029
+ const hasExtensionInstalled = yield hasExtension();
3030
+ const preferExtension = (_a3 = this.options.ui.preferExtension) != null ? _a3 : true;
3031
+ if (hasExtensionInstalled && preferExtension) {
3032
+ yield __privateMethod(this, _MetaMaskConnectMultichain_instances, setupDefaultTransport_fn).call(this, { persist: false });
3033
+ try {
3034
+ yield this.transport.init();
3035
+ } catch (error) {
3036
+ console.error("Passive init failed:", error);
3037
+ }
3038
+ }
2971
3039
  }
2972
3040
  });
2973
3041
  };
2974
- init_fn = function() {
3042
+ init_fn2 = function() {
2975
3043
  return __async(this, null, function* () {
2976
3044
  try {
2977
3045
  yield __privateMethod(this, _MetaMaskConnectMultichain_instances, setupAnalytics_fn).call(this);
@@ -2995,7 +3063,7 @@ init_fn = function() {
2995
3063
  createDappClient_fn = function() {
2996
3064
  return __async(this, null, function* () {
2997
3065
  const { adapter: kvstore } = this.options.storage;
2998
- const sessionstore = new SessionStore2(kvstore);
3066
+ const sessionstore = yield SessionStore2.create(kvstore);
2999
3067
  const websocket = (
3000
3068
  // eslint-disable-next-line no-negated-condition
3001
3069
  typeof window !== "undefined" ? WebSocket : (yield import("ws")).WebSocket
@@ -3172,9 +3240,13 @@ headlessConnect_fn = function(scopes, caipAccountIds, sessionProperties) {
3172
3240
  });
3173
3241
  };
3174
3242
  setupDefaultTransport_fn = function() {
3175
- return __async(this, null, function* () {
3176
- this.status = "connecting";
3177
- yield this.storage.setTransport("browser" /* Browser */);
3243
+ return __async(this, arguments, function* (options = { persist: true }) {
3244
+ if (__privateGet(this, _transport2) instanceof DefaultTransport) {
3245
+ return __privateGet(this, _transport2);
3246
+ }
3247
+ if (options == null ? void 0 : options.persist) {
3248
+ yield this.storage.setTransport("browser" /* Browser */);
3249
+ }
3178
3250
  const transport = new DefaultTransport();
3179
3251
  __privateSet(this, _listener, transport.onNotification(
3180
3252
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
@@ -3292,16 +3364,20 @@ handleConnection_fn = function(promise, scopes, transportType) {
3292
3364
  };
3293
3365
  getCaipSession_fn = function() {
3294
3366
  return __async(this, null, function* () {
3367
+ var _a3;
3295
3368
  let sessionData = {
3296
3369
  sessionScopes: {},
3297
3370
  sessionProperties: {}
3298
3371
  };
3299
- if (this.status === "connected") {
3300
- const response = yield this.transport.request({
3301
- method: "wallet_getSession"
3302
- });
3303
- if (response.result) {
3304
- sessionData = response.result;
3372
+ if ((_a3 = __privateGet(this, _transport2)) == null ? void 0 : _a3.isConnected()) {
3373
+ try {
3374
+ const response = yield this.transport.request({
3375
+ method: "wallet_getSession"
3376
+ });
3377
+ if (response.result) {
3378
+ sessionData = response.result;
3379
+ }
3380
+ } catch (e) {
3305
3381
  }
3306
3382
  }
3307
3383
  return sessionData;