@metamask/connect-multichain 0.8.0 → 0.10.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 (58) hide show
  1. package/CHANGELOG.md +32 -1
  2. package/README.md +38 -25
  3. package/dist/browser/es/connect-multichain.d.mts +31 -8
  4. package/dist/browser/es/connect-multichain.mjs +87 -68
  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 +31 -8
  8. package/dist/browser/iife/connect-multichain.js +100 -84
  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 +31 -8
  12. package/dist/browser/umd/connect-multichain.js +87 -68
  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 +31 -8
  16. package/dist/node/cjs/connect-multichain.js +87 -67
  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 +31 -8
  20. package/dist/node/es/connect-multichain.mjs +87 -67
  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 +31 -8
  24. package/dist/react-native/es/connect-multichain.mjs +87 -67
  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/api/infura.d.ts +13 -1
  28. package/dist/src/domain/multichain/api/infura.d.ts.map +1 -1
  29. package/dist/src/domain/multichain/api/infura.js +17 -5
  30. package/dist/src/domain/multichain/api/infura.js.map +1 -1
  31. package/dist/src/domain/multichain/index.d.ts +1 -1
  32. package/dist/src/domain/multichain/index.d.ts.map +1 -1
  33. package/dist/src/domain/multichain/index.js +3 -3
  34. package/dist/src/domain/multichain/index.js.map +1 -1
  35. package/dist/src/domain/multichain/types.d.ts +12 -1
  36. package/dist/src/domain/multichain/types.d.ts.map +1 -1
  37. package/dist/src/multichain/index.d.ts.map +1 -1
  38. package/dist/src/multichain/index.js +24 -17
  39. package/dist/src/multichain/index.js.map +1 -1
  40. package/dist/src/multichain/rpc/requestRouter.d.ts +3 -2
  41. package/dist/src/multichain/rpc/requestRouter.d.ts.map +1 -1
  42. package/dist/src/multichain/rpc/requestRouter.js +14 -15
  43. package/dist/src/multichain/rpc/requestRouter.js.map +1 -1
  44. package/dist/src/multichain/transports/default/index.d.ts.map +1 -1
  45. package/dist/src/multichain/transports/default/index.js +7 -1
  46. package/dist/src/multichain/transports/default/index.js.map +1 -1
  47. package/dist/src/multichain/utils/analytics.d.ts +6 -6
  48. package/dist/src/multichain/utils/analytics.d.ts.map +1 -1
  49. package/dist/src/multichain/utils/analytics.js +8 -12
  50. package/dist/src/multichain/utils/analytics.js.map +1 -1
  51. package/dist/src/ui/ModalFactory.d.ts.map +1 -1
  52. package/dist/src/ui/ModalFactory.js +1 -3
  53. package/dist/src/ui/ModalFactory.js.map +1 -1
  54. package/dist/src/ui/modals/web/install.d.ts.map +1 -1
  55. package/dist/src/ui/modals/web/install.js +0 -1
  56. package/dist/src/ui/modals/web/install.js.map +1 -1
  57. package/dist/types/connect-multichain.d.ts +31 -8
  58. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -7,6 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.10.0]
11
+
12
+ ### Changed
13
+
14
+ - **BREAKING** `getInfuraRpcUrls` now accepts a single options object `{ infuraApiKey, caipChainIds? }` instead of a positional `infuraApiKey` string. The optional `caipChainIds` parameter filters the output to only the specified CAIP-2 chain IDs ([#211](https://github.com/MetaMask/connect-monorepo/pull/211))
15
+ - use merged integration types in analytics ([#223](https://github.com/MetaMask/connect-monorepo/pull/223))
16
+
17
+ ### Fixed
18
+
19
+ - fix: Fix react-native-playground consumption of **PACKAGE_VERSION** build-time constant in connect packages ([#221](https://github.com/MetaMask/connect-monorepo/pull/221))
20
+
21
+ ## [0.9.0]
22
+
23
+ ### Added
24
+
25
+ - Add `versions` constructor option to `createMultichainClient` so chain-specific packages (`connect-evm`, `connect-solana`) can report their version in analytics events. Versions are merged into the singleton on each call, following the same pattern as `api.supportedNetworks`. ([#206](https://github.com/MetaMask/connect-monorepo/pull/206))
26
+
27
+ ### Changed
28
+
29
+ - **BREAKING** `mmconnect_versions` analytics property is now a `Record<string, string>` keyed by package name instead of a plain version string ([#206](https://github.com/MetaMask/connect-monorepo/pull/206))
30
+
31
+ ### Removed
32
+
33
+ - Stop passing `sdkVersion` to install and OTP modals ([#212](https://github.com/MetaMask/connect-monorepo/pull/212))
34
+
35
+ ### Fixed
36
+
37
+ - Fix a bug where wallet_sessionChanged events were failing to propagate to the `ConnectMultichain` instance when the `DefaultTransport` is using the `WindowPostMessageTransport`. This was affecting Firefox, both iOS and Android in-app browsers ([#204](https://github.com/MetaMask/connect-monorepo/pull/204))
38
+
10
39
  ## [0.8.0]
11
40
 
12
41
  ### Added
@@ -181,7 +210,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
181
210
 
182
211
  - Initial release
183
212
 
184
- [Unreleased]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.8.0...HEAD
213
+ [Unreleased]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.10.0...HEAD
214
+ [0.10.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.9.0...@metamask/connect-multichain@0.10.0
215
+ [0.9.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.8.0...@metamask/connect-multichain@0.9.0
185
216
  [0.8.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.7.0...@metamask/connect-multichain@0.8.0
186
217
  [0.7.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.6.0...@metamask/connect-multichain@0.7.0
187
218
  [0.6.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-multichain@0.5.3...@metamask/connect-multichain@0.6.0
package/README.md CHANGED
@@ -32,7 +32,7 @@ const client = await createMultichainClient({
32
32
  api: {
33
33
  supportedNetworks: {
34
34
  // use the `getInfuraRpcUrls` helper to generate a map of Infura RPC endpoints
35
- ...getInfuraRpcUrls(INFURA_API_KEY),
35
+ ...getInfuraRpcUrls({ infuraApiKey: INFURA_API_KEY }),
36
36
  // or specify your own CAIP Chain ID to rpc endpoint mapping
37
37
  'eip155:1': 'https://mainnet.example.io/rpc',
38
38
  'eip155:137': 'https://polygon-mainnet.example.io/rpc',
@@ -134,28 +134,29 @@ 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.
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`, `versions`, `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
138
 
139
139
  #### Parameters
140
140
 
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 |
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
+ | `versions` | `Partial<ConnectVersions>` | No | Internal: set automatically by `createEVMClient` / `createSolanaClient`. Consumers do not need to provide this. |
159
+ | `debug` | `boolean` | No | Enable debug logging |
159
160
 
160
161
  #### Returns
161
162
 
@@ -337,15 +338,16 @@ Emits an event to all registered handlers.
337
338
 
338
339
  ### Utilities
339
340
 
340
- #### `getInfuraRpcUrls(infuraApiKey)`
341
+ #### `getInfuraRpcUrls(options)`
341
342
 
342
343
  Generates Infura RPC URLs for common networks keyed by CAIP Chain ID.
343
344
 
344
345
  **Parameters**
345
346
 
346
- | Name | Type | Required | Description |
347
- | -------------- | -------- | -------- | ------------------- |
348
- | `infuraApiKey` | `string` | Yes | Your Infura API key |
347
+ | Name | Type | Required | Description |
348
+ | -------------- | --------------- | -------- | ------------------------------------- |
349
+ | `infuraApiKey` | `string` | Yes | Your Infura API key |
350
+ | `caipChainIds` | `CaipChainId[]` | No | CAIP-2 chain IDs to filter the output |
349
351
 
350
352
  **Returns**
351
353
 
@@ -354,13 +356,24 @@ A map of [CAIP-2 chain IDs](https://chainagnostic.org/CAIPs/caip-2) to Infura RP
354
356
  ```typescript
355
357
  import { getInfuraRpcUrls } from '@metamask/connect-multichain';
356
358
 
357
- const rpcUrls = getInfuraRpcUrls('YOUR_INFURA_KEY');
359
+ // Get all supported Infura RPC URLs
360
+ const rpcUrls = getInfuraRpcUrls({ infuraApiKey: 'YOUR_INFURA_KEY' });
358
361
  // {
359
362
  // 'eip155:1': 'https://mainnet.infura.io/v3/YOUR_KEY',
360
363
  // 'eip155:137': 'https://polygon-mainnet.infura.io/v3/YOUR_KEY',
361
364
  // 'eip155:11155111': 'https://sepolia.infura.io/v3/YOUR_KEY',
362
365
  // ...
363
366
  // }
367
+
368
+ // Filter to specific chains
369
+ const filtered = getInfuraRpcUrls({
370
+ infuraApiKey: 'YOUR_INFURA_KEY',
371
+ caipChainIds: ['eip155:1', 'eip155:137'],
372
+ });
373
+ // {
374
+ // 'eip155:1': 'https://mainnet.infura.io/v3/YOUR_KEY',
375
+ // 'eip155:137': 'https://polygon-mainnet.infura.io/v3/YOUR_KEY',
376
+ // }
364
377
  ```
365
378
 
366
379
  ---
@@ -1,7 +1,7 @@
1
1
  import debug from 'debug';
2
2
  import { SessionData, Transport, SessionProperties, TransportRequest, TransportResponse, MultichainApiClient } from '@metamask/multichain-api-client';
3
3
  export { SessionData } from '@metamask/multichain-api-client';
4
- import { CaipAccountId, Json } from '@metamask/utils';
4
+ import { CaipAccountId, CaipChainId, Json } from '@metamask/utils';
5
5
  import { SessionRequest, Session } from '@metamask/mobile-wallet-protocol-core';
6
6
  import { Components } from '@metamask/multichain-ui';
7
7
 
@@ -386,6 +386,14 @@ type ConnectionRequest = {
386
386
  };
387
387
  };
388
388
  };
389
+ /**
390
+ * Package versions keyed by connect package name.
391
+ * connect-multichain is always present; chain-specific packages
392
+ * appear only when their client is instantiated.
393
+ */
394
+ type ConnectVersions = {
395
+ 'connect-multichain': string;
396
+ } & Partial<Record<'connect-evm' | 'connect-solana', string>>;
389
397
  /**
390
398
  * Constructor options for creating a Multichain SDK instance.
391
399
  *
@@ -431,6 +439,8 @@ type MultichainOptions = {
431
439
  };
432
440
  /** Enable debug logging */
433
441
  debug?: boolean;
442
+ /** Package versions contributed by chain-specific clients (merged on each createMultichainClient call) */
443
+ versions?: Partial<ConnectVersions>;
434
444
  };
435
445
  type MultiChainFNOptions = Omit<MultichainOptions, 'storage' | 'ui'> & {
436
446
  ui?: Omit<MultichainOptions['ui'], 'factory'>;
@@ -441,11 +451,12 @@ type MultiChainFNOptions = Omit<MultichainOptions, 'storage' | 'ui'> & {
441
451
  * Options that can be merged/overwritten when createMultichainClient is called
442
452
  * with an existing singleton.
443
453
  */
444
- type MergeableMultichainOptions = Omit<MultichainOptions, 'dapp' | 'analytics' | 'storage' | 'api' | 'ui' | 'transport'> & {
454
+ type MergeableMultichainOptions = Omit<MultichainOptions, 'dapp' | 'analytics' | 'storage' | 'api' | 'ui' | 'transport' | 'versions'> & {
445
455
  api?: MultichainOptions['api'];
446
456
  ui?: Pick<MultichainOptions['ui'], 'headless' | 'preferExtension' | 'showInstallModal'>;
447
457
  transport?: Pick<NonNullable<MultichainOptions['transport']>, 'extensionId'>;
448
458
  debug?: boolean;
459
+ versions?: Partial<ConnectVersions>;
449
460
  };
450
461
  /**
451
462
  * Complete options for Multichain SDK configuration.
@@ -474,7 +485,18 @@ declare const infuraRpcUrls: RpcUrlsMap;
474
485
  declare const RPC_HANDLED_METHODS: Set<string>;
475
486
  declare const SDK_HANDLED_METHODS: Set<string>;
476
487
 
477
- declare function getInfuraRpcUrls(infuraAPIKey: string): RpcUrlsMap;
488
+ /**
489
+ * Generates Infura RPC URLs for common networks keyed by CAIP Chain ID.
490
+ *
491
+ * @param options - The options for generating Infura RPC URLs
492
+ * @param options.infuraApiKey - The Infura API key
493
+ * @param options.caipChainIds - Optional CAIP-2 chain IDs to filter the output
494
+ * @returns A map of CAIP-2 chain IDs to Infura RPC URLs
495
+ */
496
+ declare function getInfuraRpcUrls({ infuraApiKey, caipChainIds, }: {
497
+ infuraApiKey: string;
498
+ caipChainIds?: CaipChainId[];
499
+ }): RpcUrlsMap;
478
500
 
479
501
  type ConnectionStatus = 'pending' | 'loaded' | 'disconnected' | 'connected' | 'connecting';
480
502
  declare enum TransportType {
@@ -519,7 +541,7 @@ declare abstract class MultichainCore extends EventEmitter<SDKEvents> {
519
541
  constructor(options: MultichainOptions);
520
542
  /**
521
543
  * Merges the given options into the current instance options.
522
- * Only the mergeable keys are updated (api.supportedNetworks, ui.*, mobile.*, transport.extensionId, debug).
544
+ * Only the mergeable keys are updated (api.supportedNetworks, versions, ui.*, mobile.*, transport.extensionId, debug).
523
545
  * The main thing to note is that the value for `dapp` is not merged as it does not make sense for
524
546
  * subsequent calls to `createMultichainClient` to have a different `dapp` value.
525
547
  * Used when createMultichainClient is called with an existing singleton.
@@ -658,15 +680,16 @@ declare function isRejectionError(error: unknown): boolean;
658
680
  * @param options - Multichain options containing dapp and analytics config
659
681
  * @param storage - Storage client for getting anonymous ID
660
682
  * @param invokeOptions - The invoke method options containing method and scope
683
+ * @param transportType - The transport type to use for the analytics event
661
684
  * @returns Wallet action analytics properties
662
685
  */
663
- declare function getWalletActionAnalyticsProperties(options: MultichainOptions, storage: StoreClient, invokeOptions: InvokeMethodOptions): Promise<{
664
- mmconnect_version: string;
686
+ declare function getWalletActionAnalyticsProperties(options: MultichainOptions, storage: StoreClient, invokeOptions: InvokeMethodOptions, transportType: TransportType): Promise<{
687
+ mmconnect_versions: Record<string, string>;
665
688
  dapp_id: string;
666
689
  method: string;
667
- integration_type: string;
668
690
  caip_chain_id: string;
669
691
  anon_id: string;
692
+ transport_type: TransportType;
670
693
  }>;
671
694
 
672
695
  /**
@@ -678,4 +701,4 @@ declare function getVersion(): string;
678
701
 
679
702
  declare const createMultichainClient: CreateMultichainFN;
680
703
 
681
- export { type ConnectionRequest, type ConnectionStatus, type CreateMultichainFN, type DappSettings, type DataType, type DomainErrorCodes, type Enumerate, type ErrorCodeRange, type ErrorCodes, EventEmitter, type EventTypes, type ExtendedTransport, type InstallWidgetProps, type InvokeMethodOptions, type LoggerNameSpaces, type MergeableMultichainOptions, Modal, type ModalFactoryConnectOptions, type ModalFactoryOptions, MultichainCore, type MultichainOptions, type NotificationCallback, type OTPCode, type OTPCodeWidgetProps, PlatformType, type QRLink, type RPCAPI, type RPCErrorCodes, RPCHttpErr, RPCInvokeMethodErr, RPCReadonlyRequestErr, RPCReadonlyResponseErr, type RPCResponse, RPC_HANDLED_METHODS, type RpcMethod, type RpcUrlsMap, type SDKEvents, SDK_HANDLED_METHODS, type Scope, type StorageErrorCodes, StoreAdapter, StoreClient, type StoreOptions, TransportType, createLogger, createMultichainClient, enableDebug, getInfuraRpcUrls, getPlatformType, getTransportType, getVersion, getWalletActionAnalyticsProperties, hasExtension, infuraRpcUrls, isEnabled, isMetamaskExtensionInstalled, isRejectionError, isSecure };
704
+ export { type ConnectVersions, type ConnectionRequest, type ConnectionStatus, type CreateMultichainFN, type DappSettings, type DataType, type DomainErrorCodes, type Enumerate, type ErrorCodeRange, type ErrorCodes, EventEmitter, type EventTypes, type ExtendedTransport, type InstallWidgetProps, type InvokeMethodOptions, type LoggerNameSpaces, type MergeableMultichainOptions, Modal, type ModalFactoryConnectOptions, type ModalFactoryOptions, MultichainCore, type MultichainOptions, type NotificationCallback, type OTPCode, type OTPCodeWidgetProps, PlatformType, type QRLink, type RPCAPI, type RPCErrorCodes, RPCHttpErr, RPCInvokeMethodErr, RPCReadonlyRequestErr, RPCReadonlyResponseErr, type RPCResponse, RPC_HANDLED_METHODS, type RpcMethod, type RpcUrlsMap, type SDKEvents, SDK_HANDLED_METHODS, type Scope, type StorageErrorCodes, StoreAdapter, StoreClient, type StoreOptions, TransportType, createLogger, createMultichainClient, enableDebug, getInfuraRpcUrls, getPlatformType, getTransportType, getVersion, getWalletActionAnalyticsProperties, hasExtension, infuraRpcUrls, isEnabled, isMetamaskExtensionInstalled, isRejectionError, isSecure };
@@ -356,10 +356,16 @@ var init_constants = __esm({
356
356
  });
357
357
 
358
358
  // src/domain/multichain/api/infura.ts
359
- function getInfuraRpcUrls(infuraAPIKey) {
360
- return Object.keys(infuraRpcUrls).reduce((acc, key) => {
361
- const typedKey = key;
362
- acc[typedKey] = `${infuraRpcUrls[typedKey]}${infuraAPIKey}`;
359
+ function getInfuraRpcUrls({
360
+ infuraApiKey,
361
+ caipChainIds
362
+ }) {
363
+ const keys = caipChainIds && caipChainIds.length > 0 ? caipChainIds : Object.keys(infuraRpcUrls);
364
+ return keys.reduce((acc, key) => {
365
+ const baseUrl = infuraRpcUrls[key];
366
+ if (baseUrl) {
367
+ acc[key] = `${baseUrl}${infuraApiKey}`;
368
+ }
363
369
  return acc;
364
370
  }, {});
365
371
  }
@@ -401,7 +407,7 @@ var init_multichain = __esm({
401
407
  }
402
408
  /**
403
409
  * Merges the given options into the current instance options.
404
- * Only the mergeable keys are updated (api.supportedNetworks, ui.*, mobile.*, transport.extensionId, debug).
410
+ * Only the mergeable keys are updated (api.supportedNetworks, versions, ui.*, mobile.*, transport.extensionId, debug).
405
411
  * The main thing to note is that the value for `dapp` is not merged as it does not make sense for
406
412
  * subsequent calls to `createMultichainClient` to have a different `dapp` value.
407
413
  * Used when createMultichainClient is called with an existing singleton.
@@ -409,22 +415,23 @@ var init_multichain = __esm({
409
415
  * @param partial - Options to merge/overwrite onto the current instance
410
416
  */
411
417
  mergeOptions(partial) {
412
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
418
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
413
419
  const opts = this.options;
414
420
  this.options = __spreadProps(__spreadValues({}, opts), {
415
421
  api: __spreadProps(__spreadValues({}, opts.api), {
416
422
  supportedNetworks: __spreadValues(__spreadValues({}, opts.api.supportedNetworks), (_b = (_a3 = partial.api) == null ? void 0 : _a3.supportedNetworks) != null ? _b : {})
417
423
  }),
424
+ versions: __spreadValues(__spreadValues({}, opts.versions), (_c = partial.versions) != null ? _c : {}),
418
425
  ui: __spreadProps(__spreadValues({}, opts.ui), {
419
- headless: (_d = (_c = partial.ui) == null ? void 0 : _c.headless) != null ? _d : opts.ui.headless,
420
- preferExtension: (_f = (_e = partial.ui) == null ? void 0 : _e.preferExtension) != null ? _f : opts.ui.preferExtension,
421
- showInstallModal: (_h = (_g = partial.ui) == null ? void 0 : _g.showInstallModal) != null ? _h : opts.ui.showInstallModal
426
+ headless: (_e = (_d = partial.ui) == null ? void 0 : _d.headless) != null ? _e : opts.ui.headless,
427
+ preferExtension: (_g = (_f = partial.ui) == null ? void 0 : _f.preferExtension) != null ? _g : opts.ui.preferExtension,
428
+ showInstallModal: (_i = (_h = partial.ui) == null ? void 0 : _h.showInstallModal) != null ? _i : opts.ui.showInstallModal
422
429
  }),
423
- mobile: __spreadValues(__spreadValues({}, opts.mobile), (_i = partial.mobile) != null ? _i : {}),
424
- transport: __spreadProps(__spreadValues({}, (_j = opts.transport) != null ? _j : {}), {
425
- extensionId: (_m = (_k = partial.transport) == null ? void 0 : _k.extensionId) != null ? _m : (_l = opts.transport) == null ? void 0 : _l.extensionId
430
+ mobile: __spreadValues(__spreadValues({}, opts.mobile), (_j = partial.mobile) != null ? _j : {}),
431
+ transport: __spreadProps(__spreadValues({}, (_k = opts.transport) != null ? _k : {}), {
432
+ extensionId: (_n = (_l = partial.transport) == null ? void 0 : _l.extensionId) != null ? _n : (_m = opts.transport) == null ? void 0 : _m.extensionId
426
433
  }),
427
- debug: (_n = partial.debug) != null ? _n : opts.debug
434
+ debug: (_o = partial.debug) != null ? _o : opts.debug
428
435
  });
429
436
  }
430
437
  };
@@ -626,35 +633,30 @@ function isRejectionError(error) {
626
633
  }
627
634
  function getBaseAnalyticsProperties(options, storage) {
628
635
  return __async(this, null, function* () {
629
- var _a3, _b;
630
- const version = getVersion();
636
+ var _a3;
631
637
  const dappId = getDappId(options.dapp);
632
638
  const platform = getPlatformType();
633
639
  const anonId = yield storage.getAnonId();
634
- const integrationType = (_b = (_a3 = options.analytics) == null ? void 0 : _a3.integrationType) != null ? _b : "unknown" /* UNKNOWN */;
635
640
  return {
636
- mmconnect_version: version,
641
+ mmconnect_versions: (_a3 = options.versions) != null ? _a3 : {},
637
642
  dapp_id: dappId,
638
643
  platform,
639
- integration_type: integrationType,
640
644
  anon_id: anonId
641
645
  };
642
646
  });
643
647
  }
644
- function getWalletActionAnalyticsProperties(options, storage, invokeOptions) {
648
+ function getWalletActionAnalyticsProperties(options, storage, invokeOptions, transportType) {
645
649
  return __async(this, null, function* () {
646
- var _a3, _b;
647
- const version = getVersion();
650
+ var _a3;
648
651
  const dappId = getDappId(options.dapp);
649
652
  const anonId = yield storage.getAnonId();
650
- const integrationType = (_b = (_a3 = options.analytics) == null ? void 0 : _a3.integrationType) != null ? _b : "unknown";
651
653
  return {
652
- mmconnect_version: version,
654
+ mmconnect_versions: (_a3 = options.versions) != null ? _a3 : {},
653
655
  dapp_id: dappId,
654
656
  method: invokeOptions.request.method,
655
- integration_type: integrationType,
656
657
  caip_chain_id: invokeOptions.scope,
657
- anon_id: anonId
658
+ anon_id: anonId,
659
+ transport_type: transportType
658
660
  };
659
661
  });
660
662
  }
@@ -1093,7 +1095,6 @@ var init_install = __esm({
1093
1095
  "mm-install-modal"
1094
1096
  );
1095
1097
  modal.showInstallModal = options.showInstallModal;
1096
- modal.sdkVersion = options.sdkVersion;
1097
1098
  modal.addEventListener("close", (ev) => {
1098
1099
  const { detail } = ev;
1099
1100
  options.onClose(detail == null ? void 0 : detail.shouldTerminate);
@@ -1420,10 +1421,11 @@ init_utils2();
1420
1421
  init_analytics();
1421
1422
  var _RequestRouter_instances, withAnalyticsTracking_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, trackWalletActionRejected_fn;
1422
1423
  var RequestRouter = class {
1423
- constructor(transport, rpcClient, config) {
1424
+ constructor(transport, rpcClient, config, transportType) {
1424
1425
  this.transport = transport;
1425
1426
  this.rpcClient = rpcClient;
1426
1427
  this.config = config;
1428
+ this.transportType = transportType;
1427
1429
  __privateAdd(this, _RequestRouter_instances);
1428
1430
  }
1429
1431
  /**
@@ -1493,16 +1495,14 @@ var RequestRouter = class {
1493
1495
  */
1494
1496
  handleWithRpcNode(options) {
1495
1497
  return __async(this, null, function* () {
1496
- return __privateMethod(this, _RequestRouter_instances, withAnalyticsTracking_fn).call(this, options, () => __async(this, null, function* () {
1497
- try {
1498
- return yield this.rpcClient.request(options);
1499
- } catch (error) {
1500
- if (error instanceof MissingRpcEndpointErr) {
1501
- return this.handleWithWallet(options);
1502
- }
1503
- throw error;
1498
+ try {
1499
+ return yield this.rpcClient.request(options);
1500
+ } catch (error) {
1501
+ if (error instanceof MissingRpcEndpointErr) {
1502
+ return this.handleWithWallet(options);
1504
1503
  }
1505
- }));
1504
+ throw error;
1505
+ }
1506
1506
  });
1507
1507
  }
1508
1508
  /**
@@ -1546,7 +1546,8 @@ trackWalletActionRequested_fn = function(options) {
1546
1546
  const props = yield getWalletActionAnalyticsProperties(
1547
1547
  this.config,
1548
1548
  this.config.storage,
1549
- options
1549
+ options,
1550
+ this.transportType
1550
1551
  );
1551
1552
  analytics.track("mmconnect_wallet_action_requested", props);
1552
1553
  });
@@ -1556,7 +1557,8 @@ trackWalletActionSucceeded_fn = function(options) {
1556
1557
  const props = yield getWalletActionAnalyticsProperties(
1557
1558
  this.config,
1558
1559
  this.config.storage,
1559
- options
1560
+ options,
1561
+ this.transportType
1560
1562
  );
1561
1563
  analytics.track("mmconnect_wallet_action_succeeded", props);
1562
1564
  });
@@ -1566,7 +1568,8 @@ trackWalletActionFailed_fn = function(options) {
1566
1568
  const props = yield getWalletActionAnalyticsProperties(
1567
1569
  this.config,
1568
1570
  this.config.storage,
1569
- options
1571
+ options,
1572
+ this.transportType
1570
1573
  );
1571
1574
  analytics.track("mmconnect_wallet_action_failed", props);
1572
1575
  });
@@ -1576,7 +1579,8 @@ trackWalletActionRejected_fn = function(options) {
1576
1579
  const props = yield getWalletActionAnalyticsProperties(
1577
1580
  this.config,
1578
1581
  this.config.storage,
1579
- options
1582
+ options,
1583
+ this.transportType
1580
1584
  );
1581
1585
  analytics.track("mmconnect_wallet_action_rejected", props);
1582
1586
  });
@@ -1821,7 +1825,9 @@ setupMessageListener_fn = function() {
1821
1825
  init_fn = function() {
1822
1826
  return __async(this, null, function* () {
1823
1827
  __privateMethod(this, _DefaultTransport_instances, setupMessageListener_fn).call(this);
1824
- yield __privateGet(this, _transport).connect();
1828
+ if (!__privateGet(this, _transport).isConnected()) {
1829
+ yield __privateGet(this, _transport).connect();
1830
+ }
1825
1831
  });
1826
1832
  };
1827
1833
 
@@ -2668,16 +2674,21 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2668
2674
  constructor(options) {
2669
2675
  var _a3, _b, _c, _d, _e, _f;
2670
2676
  const withDappMetadata = setupDappMetadata(options);
2671
- const integrationType = (_b = (_a3 = options.analytics) == null ? void 0 : _a3.integrationType) != null ? _b : "direct";
2677
+ const integrationType = ((_a3 = options.analytics) == null ? void 0 : _a3.integrationType) || "direct";
2672
2678
  const allOptions = __spreadProps(__spreadValues({}, withDappMetadata), {
2673
2679
  ui: __spreadProps(__spreadValues({}, withDappMetadata.ui), {
2674
- preferExtension: (_c = withDappMetadata.ui.preferExtension) != null ? _c : true,
2675
- showInstallModal: (_d = withDappMetadata.ui.showInstallModal) != null ? _d : false,
2676
- headless: (_e = withDappMetadata.ui.headless) != null ? _e : false
2680
+ preferExtension: (_b = withDappMetadata.ui.preferExtension) != null ? _b : true,
2681
+ showInstallModal: (_c = withDappMetadata.ui.showInstallModal) != null ? _c : false,
2682
+ headless: (_d = withDappMetadata.ui.headless) != null ? _d : false
2677
2683
  }),
2678
- analytics: __spreadProps(__spreadValues({}, (_f = options.analytics) != null ? _f : {}), {
2684
+ analytics: __spreadProps(__spreadValues({}, (_e = options.analytics) != null ? _e : {}), {
2679
2685
  integrationType
2680
- })
2686
+ }),
2687
+ versions: __spreadValues({
2688
+ // typeof guard needed: Metro (React Native) bundles TS source directly,
2689
+ // bypassing the tsup build that substitutes __PACKAGE_VERSION__.
2690
+ "connect-multichain": false ? "unknown" : "0.10.0"
2691
+ }, (_f = options.versions) != null ? _f : {})
2681
2692
  });
2682
2693
  super(allOptions);
2683
2694
  __privateAdd(this, _MetaMaskConnectMultichain_instances);
@@ -2734,23 +2745,33 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2734
2745
  // Creates a singleton instance of MetaMaskConnectMultichain.
2735
2746
  // If the singleton already exists, it merges the incoming options with the
2736
2747
  // existing singleton options for the following keys: `api.supportedNetworks`,
2737
- // `ui.*`, `mobile.*`, `transport.extensionId`, `debug`. Take note that the
2738
- // value for `dapp` is not merged as it does not make sense for subsequent calls to
2739
- // `createMultichainClient` to have a different `dapp` value.
2748
+ // `versions`, `ui.*`, `mobile.*`, `transport.extensionId`, `debug`. Take note
2749
+ // that the value for `dapp` is not merged as it does not make sense for
2750
+ // subsequent calls to `createMultichainClient` to have a different `dapp` value.
2740
2751
  static create(options) {
2741
2752
  return __async(this, null, function* () {
2753
+ var _a3, _b;
2742
2754
  const globalObject = getGlobalObject();
2743
2755
  const existing = globalObject[SINGLETON_KEY];
2744
2756
  if (existing) {
2745
2757
  const instance = yield existing;
2746
2758
  instance.mergeOptions(options);
2759
+ analytics2.setGlobalProperty(
2760
+ "mmconnect_versions",
2761
+ (_a3 = instance.options.versions) != null ? _a3 : {}
2762
+ );
2763
+ if ((_b = options.analytics) == null ? void 0 : _b.integrationType) {
2764
+ analytics2.setGlobalProperty("integration_types", [
2765
+ options.analytics.integrationType
2766
+ ]);
2767
+ }
2747
2768
  if (options.debug) {
2748
2769
  enableDebug("metamask-sdk:*");
2749
2770
  }
2750
2771
  return instance;
2751
2772
  }
2752
2773
  const instancePromise = (() => __async(null, null, function* () {
2753
- var _a3;
2774
+ var _a4;
2754
2775
  const instance = new _MetaMaskConnectMultichain(options);
2755
2776
  const isEnabled2 = yield isEnabled(
2756
2777
  "metamask-sdk:core",
@@ -2759,7 +2780,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2759
2780
  if (isEnabled2) {
2760
2781
  enableDebug("metamask-sdk:core");
2761
2782
  }
2762
- yield __privateMethod(_a3 = instance, _MetaMaskConnectMultichain_instances, init_fn2).call(_a3);
2783
+ yield __privateMethod(_a4 = instance, _MetaMaskConnectMultichain_instances, init_fn2).call(_a4);
2763
2784
  return instance;
2764
2785
  }))();
2765
2786
  globalObject[SINGLETON_KEY] = instancePromise;
@@ -2887,7 +2908,12 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2887
2908
  return __async(this, null, function* () {
2888
2909
  const { transport, options } = this;
2889
2910
  const rpcClient = new RpcClient(options, __privateGet(this, _sdkInfo));
2890
- const requestRouter = new RequestRouter(transport, rpcClient, options);
2911
+ const requestRouter = new RequestRouter(
2912
+ transport,
2913
+ rpcClient,
2914
+ options,
2915
+ this.transportType
2916
+ );
2891
2917
  return requestRouter.invokeMethod(request);
2892
2918
  });
2893
2919
  }
@@ -2940,24 +2966,28 @@ _sdkInfo = new WeakMap();
2940
2966
  _MetaMaskConnectMultichain_instances = new WeakSet();
2941
2967
  setupAnalytics_fn = function() {
2942
2968
  return __async(this, null, function* () {
2943
- var _a3;
2969
+ var _a3, _b;
2944
2970
  const platform = getPlatformType();
2945
2971
  const isBrowser = platform === "in-app-browser" /* MetaMaskMobileWebview */ || platform === "web-desktop" /* DesktopWeb */ || platform === "web-mobile" /* MobileWeb */;
2946
2972
  const isReactNative2 = platform === "react-native" /* ReactNative */;
2947
2973
  if (!isBrowser && !isReactNative2) {
2948
2974
  return;
2949
2975
  }
2950
- const version = getVersion();
2951
2976
  const dappId = getDappId(this.options.dapp);
2952
2977
  const anonId = yield this.storage.getAnonId();
2953
2978
  const { integrationType } = (_a3 = this.options.analytics) != null ? _a3 : {
2954
2979
  integrationType: ""
2955
2980
  };
2956
- analytics2.setGlobalProperty("mmconnect_version", version);
2981
+ analytics2.setGlobalProperty(
2982
+ "mmconnect_versions",
2983
+ (_b = this.options.versions) != null ? _b : {}
2984
+ );
2957
2985
  analytics2.setGlobalProperty("dapp_id", dappId);
2958
2986
  analytics2.setGlobalProperty("anon_id", anonId);
2959
2987
  analytics2.setGlobalProperty("platform", platform);
2960
- analytics2.setGlobalProperty("integration_type", integrationType);
2988
+ if (integrationType) {
2989
+ analytics2.setGlobalProperty("integration_types", [integrationType]);
2990
+ }
2961
2991
  analytics2.enable();
2962
2992
  });
2963
2993
  };
@@ -3044,15 +3074,6 @@ init_fn2 = function() {
3044
3074
  try {
3045
3075
  yield __privateMethod(this, _MetaMaskConnectMultichain_instances, setupAnalytics_fn).call(this);
3046
3076
  yield __privateMethod(this, _MetaMaskConnectMultichain_instances, setupTransport_fn).call(this);
3047
- try {
3048
- const baseProps = yield getBaseAnalyticsProperties(
3049
- this.options,
3050
- this.storage
3051
- );
3052
- analytics2.track("mmconnect_initialized", baseProps);
3053
- } catch (error) {
3054
- logger2("Error tracking initialized event", error);
3055
- }
3056
3077
  } catch (error) {
3057
3078
  yield this.storage.removeTransport();
3058
3079
  this.status = "pending";
@@ -3706,7 +3727,6 @@ var BaseModalFactory = class {
3706
3727
  parentElement,
3707
3728
  showInstallModal,
3708
3729
  link: qrCodeLink,
3709
- sdkVersion: getVersion(),
3710
3730
  generateQRCode: (request) => __async(this, null, function* () {
3711
3731
  var _a4;
3712
3732
  const newLink = this.createConnectionDeeplink(request);
@@ -3732,7 +3752,6 @@ var BaseModalFactory = class {
3732
3752
  const otpCode = yield createOTPCode();
3733
3753
  const modal = new this.options.OTPCodeModal({
3734
3754
  parentElement: container,
3735
- sdkVersion: getVersion(),
3736
3755
  otpCode,
3737
3756
  onClose: this.onCloseModal.bind(this),
3738
3757
  createOTPCode,