@metamask/connect-evm 0.1.1 → 0.2.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.0]
11
+
12
+ ### Added
13
+
14
+ - Add `display_uri` event support for custom QR code UI implementations ([#130](https://github.com/MetaMask/connect-monorepo/pull/130))
15
+ - `display_uri` event on `EIP1193Provider` emitted when QR code link is available
16
+ - `displayUri` callback in `EventHandlers` for event-based subscriptions
17
+ - Forwarded from `@metamask/connect-multichain` core to EIP-1193 provider layer
18
+ - Add `mobile.preferredOpenLink` option support for React Native deeplink handling in wagmi connector ([#118](https://github.com/MetaMask/connect-monorepo/pull/118))
19
+ - Allows React Native apps to use `Linking.openURL()` instead of `window.location.href` for opening MetaMask deeplinks
20
+ - Required for wagmi connector usage in React Native environments
21
+ - Add legacy compatibility methods to `EIP1193Provider` for broader ecosystem compatibility ([#102](https://github.com/MetaMask/connect-monorepo/pull/102))
22
+ - `chainId` getter (alias for `selectedChainId`)
23
+ - `sendAsync()` for callback/promise-based JSON-RPC requests
24
+ - `send()` for callback-based JSON-RPC requests
25
+
26
+ ### Changed
27
+
28
+ - **BREAKING** Rename `createMetamaskConnectEVM` to `createEVMClient` for a cleaner naming convention ([#114](https://github.com/MetaMask/connect-monorepo/pull/114))
29
+
30
+ ### Removed
31
+
32
+ - Revert: Fix local state not correctly being reset when establishing a new connection when there is an existing active session ([#119](https://github.com/MetaMask/connect-monorepo/pull/119))
33
+
34
+ ### Fixed
35
+
36
+ - Fix selected chainId incorrectly reverting to Ethereum Mainnet after page refresh by caching the selected chainId and retrieving it from storage instead of assuming the first permitted chain is selected ([#113](https://github.com/MetaMask/connect-monorepo/pull/113))
37
+ - Update `#attemptSessionRecovery()` to check to state before attempting recovery ([#107](https://github.com/MetaMask/connect-monorepo/pull/107))
38
+ - Bind all public methods in `EIP1193Provider` constructor to ensure stable `this` context when methods are extracted or passed as callbacks ([#102](https://github.com/MetaMask/connect-monorepo/pull/102))
39
+
40
+ ## [0.1.2]
41
+
42
+ ### Added
43
+
44
+ - **BREAKING** Replace `chainId` property on `connect` method with `chainIds` to support for connecting to multiple chains ([#77](https://github.com/MetaMask/connect-monorepo/pull/77))
45
+
46
+ ### Changed
47
+
48
+ - Bump `@metamask/connect-multichain` removing `enable` flag from `analytics` ([#92](https://github.com/MetaMask/connect-monorepo/pull/92))
49
+ - **BREAKING** Change `connectWithMessage()` to expect param object with `message` and optional `chainIds` property ([#82](https://github.com/MetaMask/connect-monorepo/pull/82))
50
+ - `message` should be the value that the user will prompted to sign with their selected account after connecting. `message` is required.
51
+ - `chainIds` should be an array of chainIds that the wallet will prompt the user to grant permisson for. `chainIds` is optional.
52
+
53
+ ### Fixed
54
+
55
+ - Fix duplicate `onNotification` listener ([#81](https://github.com/MetaMask/connect-monorepo/pull/81))
56
+ - Fixed `addEthereumChain` not being prompted on mobile native browsers after a switch chain failure ([#79](https://github.com/MetaMask/connect-monorepo/pull/79))
57
+ - Fix local state not correctly being reset when establishing a new connection when there is an existing active session ([#88](https://github.com/MetaMask/connect-monorepo/pull/88))
58
+
10
59
  ## [0.1.1]
11
60
 
12
61
  ### Fixed
@@ -21,6 +70,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
21
70
 
22
71
  - Initial release ([#58](https://github.com/MetaMask/connect-monorepo/pull/58))
23
72
 
24
- [Unreleased]: https://github.com/MetaMask/metamask-connect-monorepo/compare/@metamask/connect-evm@0.1.1...HEAD
25
- [0.1.1]: https://github.com/MetaMask/metamask-connect-monorepo/compare/@metamask/connect-evm@0.1.0...@metamask/connect-evm@0.1.1
26
- [0.1.0]: https://github.com/MetaMask/metamask-connect-monorepo/releases/tag/@metamask/connect-evm@0.1.0
73
+ [Unreleased]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-evm@0.2.0...HEAD
74
+ [0.2.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-evm@0.1.2...@metamask/connect-evm@0.2.0
75
+ [0.1.2]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-evm@0.1.1...@metamask/connect-evm@0.1.2
76
+ [0.1.1]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-evm@0.1.0...@metamask/connect-evm@0.1.1
77
+ [0.1.0]: https://github.com/MetaMask/connect-monorepo/releases/tag/@metamask/connect-evm@0.1.0
package/README.md CHANGED
@@ -8,6 +8,7 @@
8
8
 
9
9
  - **EIP-1193 Provider Interface** - Seamless integration with existing dapp code using the standard Ethereum provider interface
10
10
  - **Cross-Platform Support** - Works with browser extensions and mobile applications
11
+ - **React Native Support** - Native mobile deeplink handling via `preferredOpenLink` option
11
12
 
12
13
  ## Installation
13
14
 
@@ -24,10 +25,10 @@ npm install @metamask/connect-evm
24
25
  ## Quick Start
25
26
 
26
27
  ```typescript
27
- import { createMetamaskConnectEVM } from '@metamask/connect-evm';
28
+ import { createEVMClient } from '@metamask/connect-evm';
28
29
 
29
30
  // Create an SDK instance
30
- const sdk = await createMetamaskConnectEVM({
31
+ const sdk = await createEVMClient({
31
32
  dapp: {
32
33
  name: 'My DApp',
33
34
  url: 'https://mydapp.com',
@@ -51,9 +52,9 @@ const accounts = await provider.request({
51
52
  ### Basic Connection
52
53
 
53
54
  ```typescript
54
- import { createMetamaskConnectEVM } from '@metamask/connect-evm';
55
+ import { createEVMClient } from '@metamask/connect-evm';
55
56
 
56
- const sdk = await createMetamaskConnectEVM({
57
+ const sdk = await createEVMClient({
57
58
  dapp: {
58
59
  name: 'My DApp',
59
60
  url: 'https://mydapp.com',
@@ -70,6 +71,37 @@ await sdk.connect({ chainId: 137 }); // Polygon
70
71
  await sdk.connect({ chainId: 1, account: '0x...' });
71
72
  ```
72
73
 
74
+ ### React Native Support
75
+
76
+ When using `@metamask/connect-evm` in React Native, the standard browser deeplink mechanism (`window.location.href`) doesn't work. Instead, you can provide a custom `preferredOpenLink` function via the `mobile` option to handle deeplinks using React Native's `Linking` API.
77
+
78
+ ```typescript
79
+ import { Linking } from 'react-native';
80
+ import { createEVMClient } from '@metamask/connect-evm';
81
+
82
+ const sdk = await createEVMClient({
83
+ dapp: {
84
+ name: 'My React Native DApp',
85
+ url: 'https://mydapp.com',
86
+ },
87
+ api: {
88
+ supportedNetworks: {
89
+ 'eip155:1': 'https://mainnet.infura.io/v3/YOUR_KEY',
90
+ },
91
+ },
92
+ // React Native: use Linking.openURL for deeplinks
93
+ mobile: {
94
+ preferredOpenLink: (deeplink: string) => {
95
+ Linking.openURL(deeplink).catch((err) => {
96
+ console.error('Failed to open deeplink:', err);
97
+ });
98
+ },
99
+ },
100
+ } as any); // Note: mobile option is passed through to connect-multichain
101
+ ```
102
+
103
+ The `mobile.preferredOpenLink` option is checked before falling back to browser-based deeplink methods, making it the recommended approach for React Native applications.
104
+
73
105
  ### Using the Provider Directly
74
106
 
75
107
  ```typescript
@@ -101,7 +133,7 @@ const result = await provider.request({
101
133
 
102
134
  ## Examples
103
135
 
104
- Check out the [playground examples](../../playground/legacy-evm-react-vite-playground) for a complete React implementation.
136
+ Check out the [playground examples](../../playground/browser-playground) for a complete React implementation.
105
137
 
106
138
  ## TypeScript
107
139
 
@@ -127,7 +159,7 @@ yarn workspace @metamask/connect-evm run test
127
159
 
128
160
  ## Contributing
129
161
 
130
- This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/metamask-connect-monorepo#readme).
162
+ This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/connect-monorepo#readme).
131
163
 
132
164
  ## License
133
165
 
@@ -52,7 +52,7 @@ import { getInfuraRpcUrls } from "@metamask/connect-multichain";
52
52
  // src/connect.ts
53
53
  import { analytics } from "@metamask/analytics";
54
54
  import {
55
- createMetamaskConnect,
55
+ createMultichainClient,
56
56
  getWalletActionAnalyticsProperties,
57
57
  isRejectionError,
58
58
  TransportType
@@ -117,6 +117,15 @@ var EIP1193Provider = class extends EventEmitter {
117
117
  __privateAdd(this, _selectedChainId);
118
118
  __privateSet(this, _core, core);
119
119
  __privateSet(this, _requestInterceptor, interceptor);
120
+ this.request = this.request.bind(this);
121
+ this.sendAsync = this.sendAsync.bind(this);
122
+ this.send = this.send.bind(this);
123
+ this.on = this.on.bind(this);
124
+ this.off = this.off.bind(this);
125
+ this.emit = this.emit.bind(this);
126
+ this.once = this.once.bind(this);
127
+ this.removeListener = this.removeListener.bind(this);
128
+ this.listenerCount = this.listenerCount.bind(this);
120
129
  }
121
130
  /**
122
131
  * Performs a EIP-1193 request.
@@ -175,6 +184,74 @@ var EIP1193Provider = class extends EventEmitter {
175
184
  }
176
185
  __privateSet(this, _selectedChainId, hexChainId);
177
186
  }
187
+ // ==========================================
188
+ // Legacy compatibility methods
189
+ // ==========================================
190
+ /**
191
+ * Alias for selectedChainId for legacy compatibility.
192
+ * Many dApps expect a `chainId` property on the provider.
193
+ */
194
+ get chainId() {
195
+ return this.selectedChainId;
196
+ }
197
+ /**
198
+ * Legacy method for sending JSON-RPC requests.
199
+ * @deprecated Use `request` instead. This method is provided for backwards compatibility.
200
+ * @param request - The JSON-RPC request object
201
+ * @param callback - Optional callback function. If provided, the method returns void.
202
+ * @returns A promise resolving to the JSON-RPC response, or void if a callback is provided.
203
+ */
204
+ sendAsync(request, callback) {
205
+ return __async(this, null, function* () {
206
+ var _a;
207
+ const id = (_a = request.id) != null ? _a : 1;
208
+ const promise = this.request({
209
+ method: request.method,
210
+ params: request.params
211
+ }).then(
212
+ (result) => ({
213
+ id,
214
+ jsonrpc: "2.0",
215
+ result
216
+ })
217
+ ).catch(
218
+ (error) => {
219
+ var _a2, _b;
220
+ return {
221
+ id,
222
+ jsonrpc: "2.0",
223
+ error: {
224
+ code: (_a2 = error.code) != null ? _a2 : -32603,
225
+ message: (_b = error.message) != null ? _b : "Internal error",
226
+ data: error.data
227
+ }
228
+ };
229
+ }
230
+ );
231
+ if (callback) {
232
+ promise.then((response) => {
233
+ if (response.error) {
234
+ callback(new Error(response.error.message), response);
235
+ } else {
236
+ callback(null, response);
237
+ }
238
+ }).catch((error) => {
239
+ callback(error, null);
240
+ });
241
+ return;
242
+ }
243
+ return promise;
244
+ });
245
+ }
246
+ /**
247
+ * Legacy method for sending JSON-RPC requests synchronously (callback-based).
248
+ * @deprecated Use `request` instead. This method is provided for backwards compatibility.
249
+ * @param request - The JSON-RPC request object
250
+ * @param callback - The callback function to receive the response
251
+ */
252
+ send(request, callback) {
253
+ this.sendAsync(request, callback);
254
+ }
178
255
  };
179
256
  _core = new WeakMap();
180
257
  _requestInterceptor = new WeakMap();
@@ -228,7 +305,8 @@ ${invalidUrls.join("\n")}`
228
305
 
229
306
  // src/connect.ts
230
307
  var DEFAULT_CHAIN_ID = 1;
231
- var _core2, _provider, _sessionScopes, _eventHandlers, _sessionChangedHandler, _MetamaskConnectEVM_instances, getCoreOptions_fn, createInvokeOptions_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, requestInterceptor_fn, clearConnectionState_fn, addEthereumChain_fn, request_fn, onChainChanged_fn, onAccountsChanged_fn, onConnect_fn, onDisconnect_fn, attemptSessionRecovery_fn;
308
+ var CHAIN_STORE_KEY = "cache_eth_chainId";
309
+ var _core2, _provider, _sessionScopes, _eventHandlers, _sessionChangedHandler, _displayUriHandler, _removeNotificationHandler, _MetamaskConnectEVM_instances, getCoreOptions_fn, createInvokeOptions_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, getSelectedChainId_fn, requestInterceptor_fn, clearConnectionState_fn, addEthereumChain_fn, request_fn, cacheChainId_fn, onChainChanged_fn, onAccountsChanged_fn, onConnect_fn, onDisconnect_fn, onDisplayUri_fn, attemptSessionRecovery_fn;
232
310
  var MetamaskConnectEVM = class {
233
311
  /**
234
312
  * Creates a new MetamaskConnectEVM instance.
@@ -249,6 +327,10 @@ var MetamaskConnectEVM = class {
249
327
  __privateAdd(this, _eventHandlers);
250
328
  /** The handler for the wallet_sessionChanged event */
251
329
  __privateAdd(this, _sessionChangedHandler);
330
+ /** The handler for the display_uri event */
331
+ __privateAdd(this, _displayUriHandler);
332
+ /** The clean-up function for the notification handler */
333
+ __privateAdd(this, _removeNotificationHandler);
252
334
  __privateSet(this, _core2, core);
253
335
  __privateSet(this, _provider, new EIP1193Provider(
254
336
  core,
@@ -264,6 +346,8 @@ var MetamaskConnectEVM = class {
264
346
  "wallet_sessionChanged",
265
347
  __privateGet(this, _sessionChangedHandler).bind(this)
266
348
  );
349
+ __privateSet(this, _displayUriHandler, __privateMethod(this, _MetamaskConnectEVM_instances, onDisplayUri_fn).bind(this));
350
+ __privateGet(this, _core2).on("display_uri", __privateGet(this, _displayUriHandler));
267
351
  __privateMethod(this, _MetamaskConnectEVM_instances, attemptSessionRecovery_fn).call(this).catch((error) => {
268
352
  console.error("Error attempting session recovery", error);
269
353
  });
@@ -273,62 +357,84 @@ var MetamaskConnectEVM = class {
273
357
  * Connects to the wallet with the specified chain ID and optional account.
274
358
  *
275
359
  * @param options - The connection options
276
- * @param options.chainId - The chain ID to connect to (defaults to 1 for mainnet)
277
360
  * @param options.account - Optional specific account to connect to
278
361
  * @param options.forceRequest - Wwhether to force a request regardless of an existing session
362
+ * @param options.chainIds - Array of chain IDs to connect to
279
363
  * @returns A promise that resolves with the connected accounts and chain ID
280
364
  */
281
365
  connect() {
282
- return __async(this, arguments, function* ({
283
- chainId,
284
- account,
285
- forceRequest
286
- } = { chainId: DEFAULT_CHAIN_ID }) {
287
- logger("request: connect", { chainId, account });
288
- const caipChainId = chainId ? [`eip155:${chainId}`] : [];
289
- const caipAccountId = chainId && account ? [`eip155:${chainId}:${account}`] : [];
290
- yield __privateGet(this, _core2).connect(caipChainId, caipAccountId, forceRequest);
366
+ return __async(this, arguments, function* ({ account, forceRequest, chainIds } = {
367
+ chainIds: [DEFAULT_CHAIN_ID]
368
+ }) {
369
+ var _a, _b;
370
+ logger("request: connect", { account });
371
+ if (!chainIds || chainIds.length === 0) {
372
+ throw new Error("chainIds must be an array of at least one chain ID");
373
+ }
374
+ const caipChainIds = Array.from(
375
+ new Set((_a = chainIds.concat(DEFAULT_CHAIN_ID)) != null ? _a : [DEFAULT_CHAIN_ID])
376
+ ).map((id) => `eip155:${id}`);
377
+ const caipAccountIds = account ? caipChainIds.map((caipChainId) => `${caipChainId}:${account}`) : [];
378
+ yield __privateGet(this, _core2).connect(
379
+ caipChainIds,
380
+ caipAccountIds,
381
+ {},
382
+ forceRequest
383
+ );
291
384
  const hexPermittedChainIds = getPermittedEthChainIds(__privateGet(this, _sessionScopes));
292
- const initialChainId = hexPermittedChainIds[0];
293
385
  const initialAccounts = yield __privateGet(this, _core2).transport.sendEip1193Message({ method: "eth_accounts", params: [] });
386
+ const chainId = yield __privateMethod(this, _MetamaskConnectEVM_instances, getSelectedChainId_fn).call(this, hexPermittedChainIds);
294
387
  __privateMethod(this, _MetamaskConnectEVM_instances, onConnect_fn).call(this, {
295
- chainId: initialChainId,
388
+ chainId,
296
389
  accounts: initialAccounts.result
297
390
  });
298
- __privateGet(this, _core2).transport.onNotification((notification) => {
299
- var _a;
300
- if ((notification == null ? void 0 : notification.method) === "metamask_accountsChanged") {
301
- const accounts = notification == null ? void 0 : notification.params;
302
- logger("transport-event: accountsChanged", accounts);
303
- __privateMethod(this, _MetamaskConnectEVM_instances, onAccountsChanged_fn).call(this, accounts);
391
+ (_b = __privateGet(this, _removeNotificationHandler)) == null ? void 0 : _b.call(this);
392
+ __privateSet(this, _removeNotificationHandler, __privateGet(this, _core2).transport.onNotification(
393
+ (notification) => {
394
+ var _a2;
395
+ if ((notification == null ? void 0 : notification.method) === "metamask_accountsChanged") {
396
+ const accounts = notification == null ? void 0 : notification.params;
397
+ logger("transport-event: accountsChanged", accounts);
398
+ __privateMethod(this, _MetamaskConnectEVM_instances, onAccountsChanged_fn).call(this, accounts);
399
+ }
400
+ if ((notification == null ? void 0 : notification.method) === "metamask_chainChanged") {
401
+ const notificationChainId = Number((_a2 = notification == null ? void 0 : notification.params) == null ? void 0 : _a2.chainId);
402
+ logger("transport-event: chainChanged", notificationChainId);
403
+ __privateMethod(this, _MetamaskConnectEVM_instances, cacheChainId_fn).call(this, notificationChainId).catch((error) => {
404
+ logger("Error caching chainId in notification handler", error);
405
+ });
406
+ __privateMethod(this, _MetamaskConnectEVM_instances, onChainChanged_fn).call(this, notificationChainId);
407
+ }
304
408
  }
305
- if ((notification == null ? void 0 : notification.method) === "metamask_chainChanged") {
306
- const notificationChainId = Number((_a = notification == null ? void 0 : notification.params) == null ? void 0 : _a.chainId);
307
- logger("transport-event: chainChanged", notificationChainId);
308
- __privateMethod(this, _MetamaskConnectEVM_instances, onChainChanged_fn).call(this, notificationChainId);
309
- }
310
- });
409
+ ));
311
410
  logger("fulfilled-request: connect", {
312
- chainId,
411
+ chainId: chainIds[0],
313
412
  accounts: __privateGet(this, _provider).accounts
314
413
  });
315
414
  return {
316
415
  accounts: __privateGet(this, _provider).accounts,
317
- chainId: hexToNumber2(initialChainId)
416
+ chainId: hexToNumber2(chainId)
318
417
  };
319
418
  });
320
419
  }
321
420
  /**
322
421
  * Connects to the wallet and signs a message using personal_sign.
323
422
  *
324
- * @param message - The message to sign
423
+ * @param options - The connection options
424
+ * @param options.message - The message to sign after connecting
425
+ * @param options.chainIds - Optional chain IDs to connect to (defaults to ethereum mainnet if not provided)
325
426
  * @returns A promise that resolves with the signature
326
427
  * @throws Error if the selected account is not available after timeout
327
428
  */
328
- connectAndSign(message) {
329
- return __async(this, null, function* () {
429
+ connectAndSign(_0) {
430
+ return __async(this, arguments, function* ({
431
+ message,
432
+ chainIds
433
+ }) {
330
434
  var _a, _b;
331
- const { accounts, chainId } = yield this.connect();
435
+ const { accounts, chainId } = yield this.connect({
436
+ chainIds: chainIds != null ? chainIds : [DEFAULT_CHAIN_ID]
437
+ });
332
438
  const result = yield __privateGet(this, _provider).request({
333
439
  method: "personal_sign",
334
440
  params: [accounts[0], message]
@@ -347,7 +453,7 @@ var MetamaskConnectEVM = class {
347
453
  * @param options - The options for connecting and invoking the method
348
454
  * @param options.method - The method name to invoke
349
455
  * @param options.params - The parameters to pass to the method, or a function that receives the account and returns params
350
- * @param options.chainId - Optional chain ID to connect to (defaults to mainnet)
456
+ * @param options.chainIds - Optional chain IDs to connect to (defaults to ethereum mainnet if not provided)
351
457
  * @param options.account - Optional specific account to connect to
352
458
  * @param options.forceRequest - Whether to force a request regardless of an existing session
353
459
  * @returns A promise that resolves with the result of the method invocation
@@ -357,13 +463,13 @@ var MetamaskConnectEVM = class {
357
463
  return __async(this, arguments, function* ({
358
464
  method,
359
465
  params,
360
- chainId,
466
+ chainIds,
361
467
  account,
362
468
  forceRequest
363
469
  }) {
364
470
  var _a, _b;
365
471
  const { accounts: connectedAccounts, chainId: connectedChainId } = yield this.connect({
366
- chainId: chainId != null ? chainId : DEFAULT_CHAIN_ID,
472
+ chainIds: chainIds != null ? chainIds : [DEFAULT_CHAIN_ID],
367
473
  account,
368
474
  forceRequest
369
475
  });
@@ -392,6 +498,11 @@ var MetamaskConnectEVM = class {
392
498
  __privateMethod(this, _MetamaskConnectEVM_instances, onDisconnect_fn).call(this);
393
499
  __privateMethod(this, _MetamaskConnectEVM_instances, clearConnectionState_fn).call(this);
394
500
  __privateGet(this, _core2).off("wallet_sessionChanged", __privateGet(this, _sessionChangedHandler));
501
+ __privateGet(this, _core2).off("display_uri", __privateGet(this, _displayUriHandler));
502
+ if (__privateGet(this, _removeNotificationHandler)) {
503
+ __privateGet(this, _removeNotificationHandler).call(this);
504
+ __privateSet(this, _removeNotificationHandler, void 0);
505
+ }
395
506
  logger("fulfilled-request: disconnect");
396
507
  });
397
508
  }
@@ -418,6 +529,7 @@ var MetamaskConnectEVM = class {
418
529
  }
419
530
  const permittedChainIds = getPermittedEthChainIds(__privateGet(this, _sessionScopes));
420
531
  if (permittedChainIds.includes(hexChainId) && __privateGet(this, _core2).transportType === TransportType.MWP) {
532
+ yield __privateMethod(this, _MetamaskConnectEVM_instances, cacheChainId_fn).call(this, hexChainId);
421
533
  __privateMethod(this, _MetamaskConnectEVM_instances, onChainChanged_fn).call(this, hexChainId);
422
534
  yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionSucceeded_fn).call(this, method, scope, params);
423
535
  return Promise.resolve();
@@ -427,8 +539,13 @@ var MetamaskConnectEVM = class {
427
539
  method: "wallet_switchEthereumChain",
428
540
  params
429
541
  });
542
+ const resultWithError = result;
543
+ if (resultWithError == null ? void 0 : resultWithError.error) {
544
+ throw new Error(resultWithError.error.message);
545
+ }
430
546
  yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionSucceeded_fn).call(this, method, scope, params);
431
547
  if (result.result === null) {
548
+ yield __privateMethod(this, _MetamaskConnectEVM_instances, cacheChainId_fn).call(this, hexChainId);
432
549
  __privateMethod(this, _MetamaskConnectEVM_instances, onChainChanged_fn).call(this, hexChainId);
433
550
  }
434
551
  return result;
@@ -496,6 +613,8 @@ _provider = new WeakMap();
496
613
  _sessionScopes = new WeakMap();
497
614
  _eventHandlers = new WeakMap();
498
615
  _sessionChangedHandler = new WeakMap();
616
+ _displayUriHandler = new WeakMap();
617
+ _removeNotificationHandler = new WeakMap();
499
618
  _MetamaskConnectEVM_instances = new WeakSet();
500
619
  /**
501
620
  * Gets the core options for analytics checks.
@@ -521,11 +640,7 @@ createInvokeOptions_fn = function(method, scope, params) {
521
640
  };
522
641
  trackWalletActionRequested_fn = function(method, scope, params) {
523
642
  return __async(this, null, function* () {
524
- var _a;
525
643
  const coreOptions = __privateMethod(this, _MetamaskConnectEVM_instances, getCoreOptions_fn).call(this);
526
- if (!((_a = coreOptions.analytics) == null ? void 0 : _a.enabled)) {
527
- return;
528
- }
529
644
  try {
530
645
  const invokeOptions = __privateMethod(this, _MetamaskConnectEVM_instances, createInvokeOptions_fn).call(this, method, scope, params);
531
646
  const props = yield getWalletActionAnalyticsProperties(
@@ -541,11 +656,7 @@ trackWalletActionRequested_fn = function(method, scope, params) {
541
656
  };
542
657
  trackWalletActionSucceeded_fn = function(method, scope, params) {
543
658
  return __async(this, null, function* () {
544
- var _a;
545
659
  const coreOptions = __privateMethod(this, _MetamaskConnectEVM_instances, getCoreOptions_fn).call(this);
546
- if (!((_a = coreOptions.analytics) == null ? void 0 : _a.enabled)) {
547
- return;
548
- }
549
660
  try {
550
661
  const invokeOptions = __privateMethod(this, _MetamaskConnectEVM_instances, createInvokeOptions_fn).call(this, method, scope, params);
551
662
  const props = yield getWalletActionAnalyticsProperties(
@@ -561,11 +672,7 @@ trackWalletActionSucceeded_fn = function(method, scope, params) {
561
672
  };
562
673
  trackWalletActionFailed_fn = function(method, scope, params, error) {
563
674
  return __async(this, null, function* () {
564
- var _a;
565
675
  const coreOptions = __privateMethod(this, _MetamaskConnectEVM_instances, getCoreOptions_fn).call(this);
566
- if (!((_a = coreOptions.analytics) == null ? void 0 : _a.enabled)) {
567
- return;
568
- }
569
676
  try {
570
677
  const invokeOptions = __privateMethod(this, _MetamaskConnectEVM_instances, createInvokeOptions_fn).call(this, method, scope, params);
571
678
  const props = yield getWalletActionAnalyticsProperties(
@@ -584,6 +691,22 @@ trackWalletActionFailed_fn = function(method, scope, params, error) {
584
691
  }
585
692
  });
586
693
  };
694
+ getSelectedChainId_fn = function(permittedChainIds) {
695
+ return __async(this, null, function* () {
696
+ try {
697
+ const cachedChainId = yield __privateGet(this, _core2).storage.adapter.get(CHAIN_STORE_KEY);
698
+ if (cachedChainId) {
699
+ const chainId = JSON.parse(cachedChainId);
700
+ if (permittedChainIds.includes(chainId)) {
701
+ return chainId;
702
+ }
703
+ }
704
+ } catch (error) {
705
+ logger("Error retrieving cached chainId", error);
706
+ }
707
+ return permittedChainIds[0];
708
+ });
709
+ };
587
710
  requestInterceptor_fn = function(request) {
588
711
  return __async(this, null, function* () {
589
712
  logger(`Intercepting request for method: ${request.method}`);
@@ -600,12 +723,12 @@ requestInterceptor_fn = function(request) {
600
723
  if (isConnectRequest(request)) {
601
724
  const shouldForceConnectionRequest = request.method === "wallet_requestPermissions";
602
725
  const { method, params } = request;
603
- const chainId = DEFAULT_CHAIN_ID;
604
- const scope = `eip155:${chainId}`;
726
+ const initiallySelectedChainId = DEFAULT_CHAIN_ID;
727
+ const scope = `eip155:${initiallySelectedChainId}`;
605
728
  yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionRequested_fn).call(this, method, scope, params);
606
729
  try {
607
730
  const result = yield this.connect({
608
- chainId,
731
+ chainIds: [initiallySelectedChainId],
609
732
  forceRequest: shouldForceConnectionRequest
610
733
  });
611
734
  yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionSucceeded_fn).call(this, method, scope, params);
@@ -656,10 +779,14 @@ addEthereumChain_fn = function(chainConfiguration) {
656
779
  const params = [chainConfiguration];
657
780
  yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionRequested_fn).call(this, method, scope, params);
658
781
  try {
659
- yield __privateMethod(this, _MetamaskConnectEVM_instances, request_fn).call(this, {
782
+ const result = yield __privateMethod(this, _MetamaskConnectEVM_instances, request_fn).call(this, {
660
783
  method: "wallet_addEthereumChain",
661
784
  params
662
785
  });
786
+ if (result.result === null) {
787
+ yield __privateMethod(this, _MetamaskConnectEVM_instances, cacheChainId_fn).call(this, chainId);
788
+ __privateMethod(this, _MetamaskConnectEVM_instances, onChainChanged_fn).call(this, chainId);
789
+ }
663
790
  yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionSucceeded_fn).call(this, method, scope, params);
664
791
  } catch (error) {
665
792
  yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionFailed_fn).call(this, method, scope, params, error);
@@ -677,6 +804,19 @@ request_fn = function(request) {
677
804
  return result;
678
805
  });
679
806
  };
807
+ cacheChainId_fn = function(chainId) {
808
+ return __async(this, null, function* () {
809
+ try {
810
+ const hexChainId = isHex(chainId) ? chainId : numberToHex2(chainId);
811
+ yield __privateGet(this, _core2).storage.adapter.set(
812
+ CHAIN_STORE_KEY,
813
+ JSON.stringify(hexChainId)
814
+ );
815
+ } catch (error) {
816
+ logger("Error caching chainId", error);
817
+ }
818
+ });
819
+ };
680
820
  /**
681
821
  * Handles chain change events and updates the provider's selected chain ID.
682
822
  *
@@ -738,8 +878,23 @@ onDisconnect_fn = function() {
738
878
  (_b = (_a = __privateGet(this, _eventHandlers)) == null ? void 0 : _a.disconnect) == null ? void 0 : _b.call(_a);
739
879
  __privateMethod(this, _MetamaskConnectEVM_instances, onAccountsChanged_fn).call(this, []);
740
880
  };
881
+ /**
882
+ * Handles display_uri events and emits them to the provider.
883
+ * This allows consumers to display their own custom QR code UI.
884
+ *
885
+ * @param uri - The deeplink URI to be displayed as a QR code
886
+ */
887
+ onDisplayUri_fn = function(uri) {
888
+ var _a, _b;
889
+ logger("handler: display_uri", uri);
890
+ __privateGet(this, _provider).emit("display_uri", uri);
891
+ (_b = (_a = __privateGet(this, _eventHandlers)) == null ? void 0 : _a.displayUri) == null ? void 0 : _b.call(_a, uri);
892
+ };
741
893
  attemptSessionRecovery_fn = function() {
742
894
  return __async(this, null, function* () {
895
+ if (__privateGet(this, _core2).status !== "connected" && __privateGet(this, _core2).status !== "connecting") {
896
+ return;
897
+ }
743
898
  try {
744
899
  const response = yield __privateGet(this, _core2).transport.request({
745
900
  method: "wallet_getSession"
@@ -747,13 +902,11 @@ attemptSessionRecovery_fn = function() {
747
902
  const { sessionScopes } = response.result;
748
903
  __privateSet(this, _sessionScopes, sessionScopes);
749
904
  const permittedChainIds = getPermittedEthChainIds(sessionScopes);
750
- const permittedAccounts = yield __privateGet(this, _core2).transport.sendEip1193Message({
751
- method: "eth_accounts",
752
- params: []
753
- });
905
+ const permittedAccounts = yield __privateGet(this, _core2).transport.sendEip1193Message({ method: "eth_accounts", params: [] });
906
+ const chainId = yield __privateMethod(this, _MetamaskConnectEVM_instances, getSelectedChainId_fn).call(this, permittedChainIds);
754
907
  if (permittedChainIds.length && permittedAccounts.result) {
755
908
  __privateMethod(this, _MetamaskConnectEVM_instances, onConnect_fn).call(this, {
756
- chainId: permittedChainIds[0],
909
+ chainId,
757
910
  accounts: permittedAccounts.result
758
911
  });
759
912
  }
@@ -762,7 +915,7 @@ attemptSessionRecovery_fn = function() {
762
915
  }
763
916
  });
764
917
  };
765
- function createMetamaskConnectEVM(options) {
918
+ function createEVMClient(options) {
766
919
  return __async(this, null, function* () {
767
920
  var _a;
768
921
  enableDebug(options.debug);
@@ -774,7 +927,7 @@ function createMetamaskConnectEVM(options) {
774
927
  }
775
928
  validSupportedChainsUrls(options.api.supportedNetworks, "supportedNetworks");
776
929
  try {
777
- const core = yield createMetamaskConnect(__spreadProps(__spreadValues({}, options), {
930
+ const core = yield createMultichainClient(__spreadProps(__spreadValues({}, options), {
778
931
  api: {
779
932
  supportedNetworks: options.api.supportedNetworks
780
933
  }
@@ -791,7 +944,7 @@ function createMetamaskConnectEVM(options) {
791
944
  });
792
945
  }
793
946
  export {
794
- createMetamaskConnectEVM,
947
+ createEVMClient,
795
948
  getInfuraRpcUrls
796
949
  };
797
950
  //# sourceMappingURL=connect-evm.mjs.map