@metamask/connect-evm 0.4.0 → 0.5.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.
@@ -18,16 +18,18 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
18
18
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
19
19
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
20
20
  };
21
- var _MetamaskConnectEVM_instances, _MetamaskConnectEVM_core, _MetamaskConnectEVM_provider, _MetamaskConnectEVM_sessionScopes, _MetamaskConnectEVM_eventHandlers, _MetamaskConnectEVM_sessionChangedHandler, _MetamaskConnectEVM_displayUriHandler, _MetamaskConnectEVM_removeNotificationHandler, _MetamaskConnectEVM_getCoreOptions, _MetamaskConnectEVM_createInvokeOptions, _MetamaskConnectEVM_trackWalletActionRequested, _MetamaskConnectEVM_trackWalletActionSucceeded, _MetamaskConnectEVM_trackWalletActionFailed, _MetamaskConnectEVM_getSelectedChainId, _MetamaskConnectEVM_requestInterceptor, _MetamaskConnectEVM_clearConnectionState, _MetamaskConnectEVM_addEthereumChain, _MetamaskConnectEVM_request, _MetamaskConnectEVM_cacheChainId, _MetamaskConnectEVM_onChainChanged, _MetamaskConnectEVM_onAccountsChanged, _MetamaskConnectEVM_onConnect, _MetamaskConnectEVM_onDisconnect, _MetamaskConnectEVM_onDisplayUri, _MetamaskConnectEVM_attemptSessionRecovery;
21
+ var _MetamaskConnectEVM_instances, _MetamaskConnectEVM_core, _MetamaskConnectEVM_provider, _MetamaskConnectEVM_sessionScopes, _MetamaskConnectEVM_eventHandlers, _MetamaskConnectEVM_sessionChangedHandler, _MetamaskConnectEVM_displayUriHandler, _MetamaskConnectEVM_removeNotificationHandler, _MetamaskConnectEVM_status, _MetamaskConnectEVM_getCoreOptions, _MetamaskConnectEVM_createInvokeOptions, _MetamaskConnectEVM_trackWalletActionRequested, _MetamaskConnectEVM_trackWalletActionSucceeded, _MetamaskConnectEVM_trackWalletActionFailed, _MetamaskConnectEVM_getSelectedChainId, _MetamaskConnectEVM_requestInterceptor, _MetamaskConnectEVM_clearConnectionState, _MetamaskConnectEVM_addEthereumChain, _MetamaskConnectEVM_request, _MetamaskConnectEVM_cacheChainId, _MetamaskConnectEVM_onSessionChanged, _MetamaskConnectEVM_onChainChanged, _MetamaskConnectEVM_onAccountsChanged, _MetamaskConnectEVM_onConnect, _MetamaskConnectEVM_onDisconnect, _MetamaskConnectEVM_onDisplayUri;
22
+ /* eslint-disable no-restricted-syntax -- Private class properties use established patterns */
22
23
  import { analytics } from '@metamask/analytics';
24
+ import { parseScopeString } from '@metamask/chain-agnostic-permission';
23
25
  import { createMultichainClient, getWalletActionAnalyticsProperties, isRejectionError, TransportType, } from '@metamask/connect-multichain';
24
- import { numberToHex, hexToNumber, isHexString as isHex, } from '@metamask/utils';
26
+ import { hexToNumber } from '@metamask/utils';
25
27
  import { IGNORED_METHODS } from './constants';
26
28
  import { enableDebug, logger } from './logger';
27
29
  import { EIP1193Provider } from './provider';
28
- import { getPermittedEthChainIds } from './utils/caip';
30
+ import { getEthAccounts, getPermittedEthChainIds } from './utils/caip';
29
31
  import { isAccountsRequest, isAddChainRequest, isChainIdRequest, isConnectRequest, isSwitchChainRequest, validSupportedChainsUrls, } from './utils/type-guards';
30
- const DEFAULT_CHAIN_ID = 1;
32
+ const DEFAULT_CHAIN_ID = '0x1';
31
33
  const CHAIN_STORE_KEY = 'cache_eth_chainId';
32
34
  /**
33
35
  * The MetamaskConnectEVM class provides an EIP-1193 compatible interface for connecting
@@ -47,18 +49,20 @@ const CHAIN_STORE_KEY = 'cache_eth_chainId';
47
49
  *
48
50
  * @example
49
51
  * ```typescript
50
- * const sdk = await createEVMClient({
52
+ * const client = await createEVMClient({
51
53
  * dapp: { name: 'My DApp', url: 'https://mydapp.com' }
52
54
  * });
53
55
  *
54
- * await sdk.connect({ chainId: 1 });
55
- * const provider = await sdk.getProvider();
56
- * const accounts = await provider.request({ method: 'eth_accounts' });
56
+ * const { accounts, chainId } = await client.connect({ chainIds: [1, 137] }); // Connect to Ethereum Mainnet, and Polygon
57
+ *
58
+ * const provider = client.getProvider();
59
+ * const signedMessage = await provider.request({ method: 'personal_sign', params: ['0x0', accounts[0]] });
57
60
  * ```
58
61
  */
59
62
  export class MetamaskConnectEVM {
60
63
  /**
61
64
  * Creates a new MetamaskConnectEVM instance.
65
+ * Use the static `create()` method instead to ensure proper async initialization.
62
66
  *
63
67
  * @param options - The options for the MetamaskConnectEVM instance
64
68
  * @param options.core - The core instance of the Multichain SDK
@@ -80,6 +84,8 @@ export class MetamaskConnectEVM {
80
84
  _MetamaskConnectEVM_displayUriHandler.set(this, void 0);
81
85
  /** The clean-up function for the notification handler */
82
86
  _MetamaskConnectEVM_removeNotificationHandler.set(this, void 0);
87
+ /** The current connection status */
88
+ _MetamaskConnectEVM_status.set(this, 'disconnected');
83
89
  __classPrivateFieldSet(this, _MetamaskConnectEVM_core, core, "f");
84
90
  __classPrivateFieldSet(this, _MetamaskConnectEVM_provider, new EIP1193Provider(core, __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_requestInterceptor).bind(this)), "f");
85
91
  __classPrivateFieldSet(this, _MetamaskConnectEVM_eventHandlers, eventHandlers, "f");
@@ -89,87 +95,78 @@ export class MetamaskConnectEVM {
89
95
  *
90
96
  * @param session - The session data
91
97
  */
92
- __classPrivateFieldSet(this, _MetamaskConnectEVM_sessionChangedHandler, (session) => {
93
- var _a;
94
- logger('event: wallet_sessionChanged', session);
95
- __classPrivateFieldSet(this, _MetamaskConnectEVM_sessionScopes, (_a = session === null || session === void 0 ? void 0 : session.sessionScopes) !== null && _a !== void 0 ? _a : {}, "f");
96
- }, "f");
97
- __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").on('wallet_sessionChanged', __classPrivateFieldGet(this, _MetamaskConnectEVM_sessionChangedHandler, "f").bind(this));
98
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
99
+ __classPrivateFieldSet(this, _MetamaskConnectEVM_sessionChangedHandler, __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onSessionChanged).bind(this), "f");
100
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").on('wallet_sessionChanged', __classPrivateFieldGet(this, _MetamaskConnectEVM_sessionChangedHandler, "f"));
98
101
  /**
99
102
  * Handles the display_uri event.
100
103
  * Forwards the QR code URI to the provider for custom UI implementations.
101
104
  */
102
105
  __classPrivateFieldSet(this, _MetamaskConnectEVM_displayUriHandler, __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onDisplayUri).bind(this), "f");
103
106
  __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").on('display_uri', __classPrivateFieldGet(this, _MetamaskConnectEVM_displayUriHandler, "f"));
104
- // Attempt to set the permitted accounts if there's a valid previous session.
105
- // TODO (wenfix): does it make sense to catch here?
106
- __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_attemptSessionRecovery).call(this).catch((error) => {
107
- console.error('Error attempting session recovery', error);
108
- });
109
107
  logger('Connect/EVM constructor completed');
110
108
  }
109
+ /**
110
+ * Creates a fully initialized MetamaskConnectEVM instance.
111
+ * This is the recommended way to instantiate the class, as it ensures
112
+ * all async initialization (like session recovery) completes before
113
+ * the instance is returned.
114
+ *
115
+ * @param options - The options for the MetamaskConnectEVM instance
116
+ * @param options.core - The core instance of the Multichain SDK
117
+ * @param options.eventHandlers - Optional event handlers for EIP-1193 provider events
118
+ * @returns A promise that resolves with a fully initialized MetamaskConnectEVM instance
119
+ */
120
+ static create(options) {
121
+ return __awaiter(this, void 0, void 0, function* () {
122
+ const instance = new MetamaskConnectEVM(options);
123
+ yield __classPrivateFieldGet(instance, _MetamaskConnectEVM_core, "f").emitSessionChanged();
124
+ return instance;
125
+ });
126
+ }
111
127
  /**
112
128
  * Connects to the wallet with the specified chain ID and optional account.
113
129
  *
114
130
  * @param options - The connection options
115
- * @param options.account - Optional specific account to connect to
116
- * @param options.forceRequest - Wwhether to force a request regardless of an existing session
117
- * @param options.chainIds - Array of chain IDs to connect to
131
+ * @param [options.account] - Optional param to specify an account to connect to
132
+ * @param [options.forceRequest] - Optional param to force a connection request regardless of whether there is a pre-existing session
133
+ * @param [options.chainIds] - Array of chain IDs to connect to (defaults to ethereum mainnet if not provided)
118
134
  * @returns A promise that resolves with the connected accounts and chain ID
119
135
  */
120
136
  connect() {
121
- return __awaiter(this, arguments, void 0, function* ({ account, forceRequest, chainIds } = {
122
- chainIds: [DEFAULT_CHAIN_ID],
123
- }) {
124
- var _a, _b;
137
+ return __awaiter(this, arguments, void 0, function* ({ account, forceRequest, chainIds = [DEFAULT_CHAIN_ID], } = {}) {
138
+ var _a;
125
139
  logger('request: connect', { account });
126
140
  if (!chainIds || chainIds.length === 0) {
127
141
  throw new Error('chainIds must be an array of at least one chain ID');
128
142
  }
129
- const caipChainIds = Array.from(new Set((_a = chainIds.concat(DEFAULT_CHAIN_ID)) !== null && _a !== void 0 ? _a : [DEFAULT_CHAIN_ID])).map((id) => `eip155:${id}`);
143
+ const caipChainIds = Array.from(new Set((_a = chainIds.concat(DEFAULT_CHAIN_ID)) !== null && _a !== void 0 ? _a : [DEFAULT_CHAIN_ID])).map((id) => `eip155:${hexToNumber(id)}`);
130
144
  const caipAccountIds = account
131
145
  ? caipChainIds.map((caipChainId) => `${caipChainId}:${account}`)
132
146
  : [];
133
- yield __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").connect(caipChainIds, caipAccountIds, undefined, forceRequest);
134
- const hexPermittedChainIds = getPermittedEthChainIds(__classPrivateFieldGet(this, _MetamaskConnectEVM_sessionScopes, "f"));
135
- const initialAccounts = yield __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").transport.sendEip1193Message({ method: 'eth_accounts', params: [] });
136
- const chainId = yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_getSelectedChainId).call(this, hexPermittedChainIds);
137
- __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onConnect).call(this, {
138
- chainId,
139
- accounts: initialAccounts.result,
140
- });
141
- // Remove previous notification handler if it exists
142
- (_b = __classPrivateFieldGet(this, _MetamaskConnectEVM_removeNotificationHandler, "f")) === null || _b === void 0 ? void 0 : _b.call(this);
143
- __classPrivateFieldSet(this, _MetamaskConnectEVM_removeNotificationHandler, __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").transport.onNotification((notification) => {
144
- var _a;
145
- // @ts-expect-error TODO: address this
146
- if ((notification === null || notification === void 0 ? void 0 : notification.method) === 'metamask_accountsChanged') {
147
- // @ts-expect-error TODO: address this
148
- const accounts = notification === null || notification === void 0 ? void 0 : notification.params;
149
- logger('transport-event: accountsChanged', accounts);
150
- __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onAccountsChanged).call(this, accounts);
151
- }
152
- // @ts-expect-error TODO: address this
153
- if ((notification === null || notification === void 0 ? void 0 : notification.method) === 'metamask_chainChanged') {
154
- // @ts-expect-error TODO: address this
155
- const notificationChainId = Number((_a = notification === null || notification === void 0 ? void 0 : notification.params) === null || _a === void 0 ? void 0 : _a.chainId);
156
- logger('transport-event: chainChanged', notificationChainId);
157
- // Cache the chainId for persistence across page refreshes
158
- __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_cacheChainId).call(this, notificationChainId).catch((error) => {
159
- logger('Error caching chainId in notification handler', error);
147
+ __classPrivateFieldSet(this, _MetamaskConnectEVM_status, 'connecting', "f");
148
+ try {
149
+ // Wait for the wallet_sessionChanged event to fire and set the provider properties
150
+ const result = new Promise((resolve) => {
151
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").once('connect', ({ chainId, accounts }) => {
152
+ logger('fulfilled-request: connect', {
153
+ chainId,
154
+ accounts,
155
+ });
156
+ resolve({
157
+ accounts,
158
+ chainId: chainId,
159
+ });
160
160
  });
161
- __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onChainChanged).call(this, notificationChainId);
162
- }
163
- }), "f");
164
- logger('fulfilled-request: connect', {
165
- chainId: chainIds[0],
166
- accounts: __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").accounts,
167
- });
168
- // TODO: update required here since accounts and chainId are now promises
169
- return {
170
- accounts: __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").accounts,
171
- chainId: hexToNumber(chainId),
172
- };
161
+ });
162
+ yield __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").connect(caipChainIds, caipAccountIds, undefined, forceRequest);
163
+ return result;
164
+ }
165
+ catch (error) {
166
+ __classPrivateFieldSet(this, _MetamaskConnectEVM_status, 'disconnected', "f");
167
+ logger('Error connecting to wallet', error);
168
+ throw error;
169
+ }
173
170
  });
174
171
  }
175
172
  /**
@@ -177,7 +174,7 @@ export class MetamaskConnectEVM {
177
174
  *
178
175
  * @param options - The connection options
179
176
  * @param options.message - The message to sign after connecting
180
- * @param options.chainIds - Optional chain IDs to connect to (defaults to ethereum mainnet if not provided)
177
+ * @param [options.chainIds] - Optional hex chain IDs to connect to (defaults to ethereum mainnet if not provided)
181
178
  * @returns A promise that resolves with the signature
182
179
  * @throws Error if the selected account is not available after timeout
183
180
  */
@@ -205,9 +202,9 @@ export class MetamaskConnectEVM {
205
202
  * @param options - The options for connecting and invoking the method
206
203
  * @param options.method - The method name to invoke
207
204
  * @param options.params - The parameters to pass to the method, or a function that receives the account and returns params
208
- * @param options.chainIds - Optional chain IDs to connect to (defaults to ethereum mainnet if not provided)
209
- * @param options.account - Optional specific account to connect to
210
- * @param options.forceRequest - Whether to force a request regardless of an existing session
205
+ * @param [options.chainIds] - Optional hex chain IDs to connect to (defaults to ethereum mainnet if not provided)
206
+ * @param [options.account] - Optional specific account to connect to
207
+ * @param [options.forceRequest] - Whether to force a request regardless of an existing session
211
208
  * @returns A promise that resolves with the result of the method invocation
212
209
  * @throws Error if the selected account is not available after timeout (for methods that require an account)
213
210
  */
@@ -239,16 +236,22 @@ export class MetamaskConnectEVM {
239
236
  */
240
237
  disconnect() {
241
238
  return __awaiter(this, void 0, void 0, function* () {
239
+ var _a;
242
240
  logger('request: disconnect');
243
- yield __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").disconnect();
241
+ const sessionScopes = __classPrivateFieldGet(this, _MetamaskConnectEVM_sessionScopes, "f");
242
+ const eip155Scopes = Object.keys(sessionScopes).filter((scope) => {
243
+ const { namespace } = parseScopeString(scope);
244
+ return namespace === 'eip155';
245
+ });
246
+ yield __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").disconnect(eip155Scopes);
244
247
  __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onDisconnect).call(this);
245
248
  __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_clearConnectionState).call(this);
246
- __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").off('wallet_sessionChanged', __classPrivateFieldGet(this, _MetamaskConnectEVM_sessionChangedHandler, "f"));
247
- __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").off('display_uri', __classPrivateFieldGet(this, _MetamaskConnectEVM_displayUriHandler, "f"));
248
- if (__classPrivateFieldGet(this, _MetamaskConnectEVM_removeNotificationHandler, "f")) {
249
- __classPrivateFieldGet(this, _MetamaskConnectEVM_removeNotificationHandler, "f").call(this);
250
- __classPrivateFieldSet(this, _MetamaskConnectEVM_removeNotificationHandler, undefined, "f");
251
- }
249
+ // Note: We intentionally do NOT remove the display_uri and wallet_sessionChanged
250
+ // listeners here. These are instance-scoped listeners that should remain active
251
+ // for the lifetime of the SDK instance, allowing reconnection to work properly.
252
+ // Session-scoped listeners (like the notification handler below) are removed.
253
+ (_a = __classPrivateFieldGet(this, _MetamaskConnectEVM_removeNotificationHandler, "f")) === null || _a === void 0 ? void 0 : _a.call(this);
254
+ __classPrivateFieldSet(this, _MetamaskConnectEVM_removeNotificationHandler, undefined, "f");
252
255
  logger('fulfilled-request: disconnect');
253
256
  });
254
257
  }
@@ -257,25 +260,24 @@ export class MetamaskConnectEVM {
257
260
  *
258
261
  * @param options - The options for the switch chain request
259
262
  * @param options.chainId - The chain ID to switch to
260
- * @param options.chainConfiguration - The chain configuration to use in case the chain is not present by the wallet
261
- * @returns The result of the switch chain request
263
+ * @param [options.chainConfiguration] - The chain configuration to use in case the chain is not present by the wallet
264
+ * @returns A promise that resolves when the chain has been switched
262
265
  */
263
266
  switchChain(_a) {
264
267
  return __awaiter(this, arguments, void 0, function* ({ chainId, chainConfiguration, }) {
265
268
  const method = 'wallet_switchEthereumChain';
266
- const hexChainId = isHex(chainId) ? chainId : numberToHex(chainId);
267
- const scope = `eip155:${isHex(chainId) ? hexToNumber(chainId) : chainId}`;
268
- const params = [{ chainId: hexChainId }];
269
+ const scope = `eip155:${hexToNumber(chainId)}`;
270
+ const params = [{ chainId }];
269
271
  yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_trackWalletActionRequested).call(this, method, scope, params);
270
272
  // TODO (wenfix): better way to return here other than resolving.
271
- if (this.selectedChainId === hexChainId) {
273
+ if (this.selectedChainId === chainId) {
272
274
  return Promise.resolve();
273
275
  }
274
276
  const permittedChainIds = getPermittedEthChainIds(__classPrivateFieldGet(this, _MetamaskConnectEVM_sessionScopes, "f"));
275
- if (permittedChainIds.includes(hexChainId) &&
277
+ if (permittedChainIds.includes(chainId) &&
276
278
  __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").transportType === TransportType.MWP) {
277
- yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_cacheChainId).call(this, hexChainId);
278
- __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onChainChanged).call(this, hexChainId);
279
+ yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_cacheChainId).call(this, chainId);
280
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onChainChanged).call(this, chainId);
279
281
  yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_trackWalletActionSucceeded).call(this, method, scope, params);
280
282
  return Promise.resolve();
281
283
  }
@@ -293,10 +295,10 @@ export class MetamaskConnectEVM {
293
295
  yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_trackWalletActionSucceeded).call(this, method, scope, params);
294
296
  if (result.result === null) {
295
297
  // result is successful we eagerly call onChainChanged to update the provider's selected chain ID.
296
- yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_cacheChainId).call(this, hexChainId);
297
- __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onChainChanged).call(this, hexChainId);
298
+ yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_cacheChainId).call(this, chainId);
299
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onChainChanged).call(this, chainId);
298
300
  }
299
- return result;
301
+ return Promise.resolve();
300
302
  }
301
303
  catch (error) {
302
304
  yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_trackWalletActionFailed).call(this, method, scope, params, error);
@@ -366,7 +368,7 @@ export class MetamaskConnectEVM {
366
368
  return __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").status;
367
369
  }
368
370
  }
369
- _MetamaskConnectEVM_core = new WeakMap(), _MetamaskConnectEVM_provider = new WeakMap(), _MetamaskConnectEVM_sessionScopes = new WeakMap(), _MetamaskConnectEVM_eventHandlers = new WeakMap(), _MetamaskConnectEVM_sessionChangedHandler = new WeakMap(), _MetamaskConnectEVM_displayUriHandler = new WeakMap(), _MetamaskConnectEVM_removeNotificationHandler = new WeakMap(), _MetamaskConnectEVM_instances = new WeakSet(), _MetamaskConnectEVM_getCoreOptions = function _MetamaskConnectEVM_getCoreOptions() {
371
+ _MetamaskConnectEVM_core = new WeakMap(), _MetamaskConnectEVM_provider = new WeakMap(), _MetamaskConnectEVM_sessionScopes = new WeakMap(), _MetamaskConnectEVM_eventHandlers = new WeakMap(), _MetamaskConnectEVM_sessionChangedHandler = new WeakMap(), _MetamaskConnectEVM_displayUriHandler = new WeakMap(), _MetamaskConnectEVM_removeNotificationHandler = new WeakMap(), _MetamaskConnectEVM_status = new WeakMap(), _MetamaskConnectEVM_instances = new WeakSet(), _MetamaskConnectEVM_getCoreOptions = function _MetamaskConnectEVM_getCoreOptions() {
370
372
  return __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").options;
371
373
  }, _MetamaskConnectEVM_createInvokeOptions = function _MetamaskConnectEVM_createInvokeOptions(method, scope, params) {
372
374
  return {
@@ -435,6 +437,7 @@ _MetamaskConnectEVM_core = new WeakMap(), _MetamaskConnectEVM_provider = new Wea
435
437
  });
436
438
  }, _MetamaskConnectEVM_requestInterceptor = function _MetamaskConnectEVM_requestInterceptor(request) {
437
439
  return __awaiter(this, void 0, void 0, function* () {
440
+ var _a;
438
441
  logger(`Intercepting request for method: ${request.method}`);
439
442
  if (IGNORED_METHODS.includes(request.method)) {
440
443
  // TODO: replace with correct method unsupported provider error
@@ -469,7 +472,7 @@ _MetamaskConnectEVM_core = new WeakMap(), _MetamaskConnectEVM_provider = new Wea
469
472
  }
470
473
  if (isSwitchChainRequest(request)) {
471
474
  return this.switchChain({
472
- chainId: parseInt(request.params[0].chainId, 16),
475
+ chainId: request.params[0].chainId,
473
476
  });
474
477
  }
475
478
  if (isAddChainRequest(request)) {
@@ -477,10 +480,8 @@ _MetamaskConnectEVM_core = new WeakMap(), _MetamaskConnectEVM_provider = new Wea
477
480
  }
478
481
  if (isAccountsRequest(request)) {
479
482
  const { method } = request;
480
- const chainId = __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").selectedChainId
481
- ? hexToNumber(__classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").selectedChainId)
482
- : 1;
483
- const scope = `eip155:${chainId}`;
483
+ const decimalChainId = hexToNumber((_a = __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").selectedChainId) !== null && _a !== void 0 ? _a : '0x1');
484
+ const scope = `eip155:${decimalChainId}`;
484
485
  const params = [];
485
486
  yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_trackWalletActionRequested).call(this, method, scope, params);
486
487
  yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_trackWalletActionSucceeded).call(this, method, scope, params);
@@ -497,17 +498,17 @@ _MetamaskConnectEVM_core = new WeakMap(), _MetamaskConnectEVM_provider = new Wea
497
498
  __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").selectedChainId = undefined;
498
499
  }, _MetamaskConnectEVM_addEthereumChain = function _MetamaskConnectEVM_addEthereumChain(chainConfiguration) {
499
500
  return __awaiter(this, void 0, void 0, function* () {
500
- var _a;
501
501
  logger('addEthereumChain called', { chainConfiguration });
502
502
  const method = 'wallet_addEthereumChain';
503
503
  if (!chainConfiguration) {
504
504
  throw new Error('No chain configuration found.');
505
505
  }
506
506
  // Get chain ID from config or use current chain
507
- const chainId = chainConfiguration.chainId
508
- ? parseInt(chainConfiguration.chainId, 16)
509
- : hexToNumber((_a = __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").selectedChainId) !== null && _a !== void 0 ? _a : '0x1');
510
- const scope = `eip155:${chainId}`;
507
+ const chainId = chainConfiguration.chainId ||
508
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").selectedChainId ||
509
+ '0x1';
510
+ const decimalChainId = hexToNumber(chainId);
511
+ const scope = `eip155:${decimalChainId}`;
511
512
  const params = [chainConfiguration];
512
513
  yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_trackWalletActionRequested).call(this, method, scope, params);
513
514
  try {
@@ -533,89 +534,124 @@ _MetamaskConnectEVM_core = new WeakMap(), _MetamaskConnectEVM_provider = new Wea
533
534
  const result = __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").transport.sendEip1193Message(request);
534
535
  if (request.method === 'wallet_addEthereumChain' ||
535
536
  request.method === 'wallet_switchEthereumChain') {
536
- __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").openDeeplinkIfNeeded();
537
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").openSimpleDeeplinkIfNeeded();
537
538
  }
538
539
  return result;
539
540
  });
540
541
  }, _MetamaskConnectEVM_cacheChainId = function _MetamaskConnectEVM_cacheChainId(chainId) {
541
542
  return __awaiter(this, void 0, void 0, function* () {
542
543
  try {
543
- const hexChainId = isHex(chainId) ? chainId : numberToHex(chainId);
544
- yield __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").storage.adapter.set(CHAIN_STORE_KEY, JSON.stringify(hexChainId));
544
+ yield __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").storage.adapter.set(CHAIN_STORE_KEY, JSON.stringify(chainId));
545
545
  }
546
546
  catch (error) {
547
547
  logger('Error caching chainId', error);
548
548
  }
549
549
  });
550
+ }, _MetamaskConnectEVM_onSessionChanged = function _MetamaskConnectEVM_onSessionChanged(session) {
551
+ return __awaiter(this, void 0, void 0, function* () {
552
+ var _a;
553
+ logger('event: wallet_sessionChanged', session);
554
+ __classPrivateFieldSet(this, _MetamaskConnectEVM_sessionScopes, (_a = session === null || session === void 0 ? void 0 : session.sessionScopes) !== null && _a !== void 0 ? _a : {}, "f");
555
+ const hexPermittedChainIds = getPermittedEthChainIds(__classPrivateFieldGet(this, _MetamaskConnectEVM_sessionScopes, "f"));
556
+ if (hexPermittedChainIds.length === 0) {
557
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onDisconnect).call(this);
558
+ }
559
+ else {
560
+ let initialAccounts = [];
561
+ if (__classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").status === 'connected') {
562
+ const ethAccountsResponse = yield __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").transport.sendEip1193Message({
563
+ method: 'eth_accounts',
564
+ params: [],
565
+ });
566
+ initialAccounts = ethAccountsResponse.result;
567
+ }
568
+ else {
569
+ initialAccounts = getEthAccounts(__classPrivateFieldGet(this, _MetamaskConnectEVM_sessionScopes, "f"));
570
+ }
571
+ const chainId = yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_getSelectedChainId).call(this, hexPermittedChainIds);
572
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onConnect).call(this, {
573
+ chainId,
574
+ accounts: initialAccounts,
575
+ });
576
+ }
577
+ });
550
578
  }, _MetamaskConnectEVM_onChainChanged = function _MetamaskConnectEVM_onChainChanged(chainId) {
551
579
  var _a, _b;
552
- const hexChainId = isHex(chainId) ? chainId : numberToHex(chainId);
553
- if (hexChainId === __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").selectedChainId) {
580
+ if (chainId === __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").selectedChainId) {
554
581
  return;
555
582
  }
556
583
  logger('handler: chainChanged', { chainId });
557
584
  __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").selectedChainId = chainId;
558
- (_b = (_a = __classPrivateFieldGet(this, _MetamaskConnectEVM_eventHandlers, "f")) === null || _a === void 0 ? void 0 : _a.chainChanged) === null || _b === void 0 ? void 0 : _b.call(_a, hexChainId);
559
- __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").emit('chainChanged', hexChainId);
585
+ (_b = (_a = __classPrivateFieldGet(this, _MetamaskConnectEVM_eventHandlers, "f")) === null || _a === void 0 ? void 0 : _a.chainChanged) === null || _b === void 0 ? void 0 : _b.call(_a, chainId);
586
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").emit('chainChanged', chainId);
560
587
  }, _MetamaskConnectEVM_onAccountsChanged = function _MetamaskConnectEVM_onAccountsChanged(accounts) {
561
588
  var _a, _b;
589
+ const accountsUnchanged = accounts.length === __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").accounts.length &&
590
+ accounts.every((acct, idx) => acct === __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").accounts[idx]);
591
+ if (accountsUnchanged) {
592
+ return;
593
+ }
562
594
  logger('handler: accountsChanged', accounts);
563
595
  __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").accounts = accounts;
564
596
  __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").emit('accountsChanged', accounts);
565
597
  (_b = (_a = __classPrivateFieldGet(this, _MetamaskConnectEVM_eventHandlers, "f")) === null || _a === void 0 ? void 0 : _a.accountsChanged) === null || _b === void 0 ? void 0 : _b.call(_a, accounts);
566
598
  }, _MetamaskConnectEVM_onConnect = function _MetamaskConnectEVM_onConnect({ chainId, accounts, }) {
567
- var _a, _b;
599
+ var _a, _b, _c;
568
600
  logger('handler: connect', { chainId, accounts });
569
601
  const data = {
570
- chainId: isHex(chainId) ? chainId : numberToHex(chainId),
602
+ chainId,
571
603
  accounts,
572
604
  };
573
- __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").emit('connect', data);
574
- (_b = (_a = __classPrivateFieldGet(this, _MetamaskConnectEVM_eventHandlers, "f")) === null || _a === void 0 ? void 0 : _a.connect) === null || _b === void 0 ? void 0 : _b.call(_a, data);
605
+ if (__classPrivateFieldGet(this, _MetamaskConnectEVM_status, "f") !== 'connected') {
606
+ __classPrivateFieldSet(this, _MetamaskConnectEVM_status, 'connected', "f");
607
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").emit('connect', data);
608
+ (_b = (_a = __classPrivateFieldGet(this, _MetamaskConnectEVM_eventHandlers, "f")) === null || _a === void 0 ? void 0 : _a.connect) === null || _b === void 0 ? void 0 : _b.call(_a, data);
609
+ (_c = __classPrivateFieldGet(this, _MetamaskConnectEVM_removeNotificationHandler, "f")) === null || _c === void 0 ? void 0 : _c.call(this);
610
+ // TODO: Verify if #core.on('metamask_accountsChanged') and #core.on('metamask_chainChanged')
611
+ // would work here instead
612
+ __classPrivateFieldSet(this, _MetamaskConnectEVM_removeNotificationHandler, __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").transport.onNotification((notification) => {
613
+ var _a;
614
+ // @ts-expect-error TODO: address this
615
+ if ((notification === null || notification === void 0 ? void 0 : notification.method) === 'metamask_accountsChanged') {
616
+ // @ts-expect-error TODO: address this
617
+ const notificationAccounts = notification === null || notification === void 0 ? void 0 : notification.params;
618
+ logger('transport-event: accountsChanged', notificationAccounts);
619
+ // why are we not caching the accounts here?
620
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onAccountsChanged).call(this, notificationAccounts);
621
+ }
622
+ // @ts-expect-error TODO: address this
623
+ if ((notification === null || notification === void 0 ? void 0 : notification.method) === 'metamask_chainChanged') {
624
+ // @ts-expect-error TODO: address this
625
+ const notificationChainId = (_a = notification === null || notification === void 0 ? void 0 : notification.params) === null || _a === void 0 ? void 0 : _a.chainId;
626
+ logger('transport-event: chainChanged', notificationChainId);
627
+ // Cache the chainId for persistence across page refreshes
628
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_cacheChainId).call(this, notificationChainId).catch((error) => {
629
+ logger('Error caching chainId in notification handler', error);
630
+ });
631
+ __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onChainChanged).call(this, notificationChainId);
632
+ }
633
+ }), "f");
634
+ }
575
635
  __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onChainChanged).call(this, chainId);
576
636
  __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onAccountsChanged).call(this, accounts);
577
637
  }, _MetamaskConnectEVM_onDisconnect = function _MetamaskConnectEVM_onDisconnect() {
578
638
  var _a, _b;
639
+ if (__classPrivateFieldGet(this, _MetamaskConnectEVM_status, "f") === 'disconnected') {
640
+ return;
641
+ }
642
+ __classPrivateFieldSet(this, _MetamaskConnectEVM_status, 'disconnected', "f");
579
643
  logger('handler: disconnect');
580
644
  __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").emit('disconnect');
581
645
  (_b = (_a = __classPrivateFieldGet(this, _MetamaskConnectEVM_eventHandlers, "f")) === null || _a === void 0 ? void 0 : _a.disconnect) === null || _b === void 0 ? void 0 : _b.call(_a);
582
646
  __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onAccountsChanged).call(this, []);
583
647
  }, _MetamaskConnectEVM_onDisplayUri = function _MetamaskConnectEVM_onDisplayUri(uri) {
584
648
  var _a, _b;
649
+ if (__classPrivateFieldGet(this, _MetamaskConnectEVM_status, "f") !== 'connecting') {
650
+ return;
651
+ }
585
652
  logger('handler: display_uri', uri);
586
653
  __classPrivateFieldGet(this, _MetamaskConnectEVM_provider, "f").emit('display_uri', uri);
587
654
  (_b = (_a = __classPrivateFieldGet(this, _MetamaskConnectEVM_eventHandlers, "f")) === null || _a === void 0 ? void 0 : _a.displayUri) === null || _b === void 0 ? void 0 : _b.call(_a, uri);
588
- }, _MetamaskConnectEVM_attemptSessionRecovery = function _MetamaskConnectEVM_attemptSessionRecovery() {
589
- return __awaiter(this, void 0, void 0, function* () {
590
- // Skip session recovery if transport is not initialized yet.
591
- // Transport is only initialized when there's a stored session or after connect() is called.
592
- // Only attempt recovery if we're in a state where transport should be available.
593
- if (__classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").status !== 'connected' && __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").status !== 'connecting') {
594
- return;
595
- }
596
- try {
597
- const response = yield __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").transport.request({
598
- method: 'wallet_getSession',
599
- });
600
- const { sessionScopes } = response.result;
601
- __classPrivateFieldSet(this, _MetamaskConnectEVM_sessionScopes, sessionScopes, "f");
602
- const permittedChainIds = getPermittedEthChainIds(sessionScopes);
603
- // Instead of using the accounts we get back from calling `wallet_getSession`
604
- // we get permitted accounts from `eth_accounts` to make sure we have them ordered by last selected account
605
- // and correctly set the currently selected account for the dapp
606
- const permittedAccounts = yield __classPrivateFieldGet(this, _MetamaskConnectEVM_core, "f").transport.sendEip1193Message({ method: 'eth_accounts', params: [] });
607
- const chainId = yield __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_getSelectedChainId).call(this, permittedChainIds);
608
- if (permittedChainIds.length && permittedAccounts.result) {
609
- __classPrivateFieldGet(this, _MetamaskConnectEVM_instances, "m", _MetamaskConnectEVM_onConnect).call(this, {
610
- chainId,
611
- accounts: permittedAccounts.result,
612
- });
613
- }
614
- }
615
- catch (error) {
616
- console.error('Error attempting session recovery', error);
617
- }
618
- });
619
655
  };
620
656
  /**
621
657
  * Creates a new Metamask Connect/EVM instance
@@ -623,19 +659,27 @@ _MetamaskConnectEVM_core = new WeakMap(), _MetamaskConnectEVM_provider = new Wea
623
659
  * @param options - The options for the Metamask Connect/EVM layer
624
660
  * @param options.dapp - Dapp identification and branding settings
625
661
  * @param options.api - API configuration including read-only RPC map
626
- * @param options.api.supportedNetworks - A map of CAIP chain IDs to RPC URLs for read-only requests
627
- * @param options.ui - UI configuration options
628
- * @param options.ui.headless - Whether to run without UI
629
- * @param options.ui.preferExtension - Whether to prefer browser extension
630
- * @param options.ui.showInstallModal - Whether to render installation modal for desktop extension
631
- * @param options.eventEmitter - The event emitter to use for the Metamask Connect/EVM layer
632
- * @param options.eventHandlers - The event handlers to use for the Metamask Connect/EVM layer
633
- * @returns The Metamask Connect/EVM layer instance
662
+ * @param options.api.supportedNetworks - A map of hex chain IDs to RPC URLs for read-only requests
663
+ * @param [options.ui] - UI configuration options
664
+ * @param [options.ui.headless] - Whether to run without UI
665
+ * @param [options.ui.preferExtension] - Whether to prefer browser extension
666
+ * @param [options.ui.showInstallModal] - Whether to render installation modal for desktop extension
667
+ * @param [options.mobile] - Mobile configuration options
668
+ * @param [options.mobile.preferredOpenLink] - Custom handler for opening deeplinks (useful for React Native, etc.)
669
+ * @param [options.mobile.useDeeplink] - Whether to use native deeplinks instead of universal links
670
+ * @param [options.transport] - Transport configuration (e.g., extensionId, notification handler)
671
+ * @param [options.transport.extensionId] - Extension ID for browser extension transport
672
+ * @param [options.transport.onNotification] - Callback for receiving transport notifications
673
+ * @param [options.eventHandlers] - Event handlers for the Metamask Connect/EVM layer
674
+ * @param [options.debug] - Enable debug logging
675
+ * @returns The Metamask-Connect EVM client instance
634
676
  */
635
677
  export function createEVMClient(options) {
636
678
  return __awaiter(this, void 0, void 0, function* () {
637
679
  var _a;
638
- enableDebug(options.debug);
680
+ if (options.debug) {
681
+ enableDebug();
682
+ }
639
683
  logger('Creating Metamask Connect/EVM with options:', options);
640
684
  // Validate that supportedNetworks is provided and not empty
641
685
  if (!((_a = options.api) === null || _a === void 0 ? void 0 : _a.supportedNetworks) ||
@@ -643,11 +687,17 @@ export function createEVMClient(options) {
643
687
  throw new Error('supportedNetworks is required and must contain at least one chain configuration');
644
688
  }
645
689
  validSupportedChainsUrls(options.api.supportedNetworks, 'supportedNetworks');
690
+ const supportedNetworksCaipChainId = Object.entries(options.api.supportedNetworks).reduce((acc, [hexChainId, url]) => {
691
+ const decimalChainId = parseInt(hexChainId, 16);
692
+ const caip2ChainId = `eip155:${decimalChainId}`;
693
+ acc[caip2ChainId] = url;
694
+ return acc;
695
+ }, {});
646
696
  try {
647
697
  const core = yield createMultichainClient(Object.assign(Object.assign({}, options), { api: {
648
- supportedNetworks: options.api.supportedNetworks,
698
+ supportedNetworks: supportedNetworksCaipChainId,
649
699
  } }));
650
- return new MetamaskConnectEVM({
700
+ return MetamaskConnectEVM.create({
651
701
  core,
652
702
  eventHandlers: options.eventHandlers,
653
703
  supportedNetworks: options.api.supportedNetworks,