@metamask/connect-solana 0.8.1 → 1.1.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,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.1.0]
11
+
12
+ ### Changed
13
+
14
+ - `createSolanaClient()` now eagerly initializes the Solana wallet provider during creation. If the underlying multichain session already contains solana scopes, the provider's accounts are populated before the client is returned. ([#282](https://github.com/MetaMask/connect-monorepo/pull/282))
15
+ - `getWallet()` now returns the same wallet instance on every call instead of constructing a new one. ([#282](https://github.com/MetaMask/connect-monorepo/pull/282))
16
+
17
+ ## [1.0.0]
18
+
19
+ ### Changed
20
+
21
+ - **BREAKING** registerWallet() now registers the MetaMask Connect Solana Provider as `MetaMask` instead of `MetaMask Connect` ([#275](https://github.com/MetaMask/connect-monorepo/pull/275))
22
+ - Prefer the injected Solana provider by no longer announcing the MMC Solana provider if the injected Solana provider is detected ([#275](https://github.com/MetaMask/connect-monorepo/pull/275))
23
+
10
24
  ## [0.8.1]
11
25
 
12
26
  ### Changed
@@ -77,9 +91,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
91
 
78
92
  ### Added
79
93
 
80
- - Initial release
94
+ - Initial Release
81
95
 
82
- [Unreleased]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@0.8.1...HEAD
96
+ [Unreleased]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@1.1.0...HEAD
97
+ [1.1.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@1.0.0...@metamask/connect-solana@1.1.0
98
+ [1.0.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@0.8.1...@metamask/connect-solana@1.0.0
83
99
  [0.8.1]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@0.8.0...@metamask/connect-solana@0.8.1
84
100
  [0.8.0]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@0.7.1...@metamask/connect-solana@0.8.0
85
101
  [0.7.1]: https://github.com/MetaMask/connect-monorepo/compare/@metamask/connect-solana@0.7.0...@metamask/connect-solana@0.7.1
@@ -72,9 +72,24 @@ import {
72
72
  getWalletStandard,
73
73
  registerSolanaWalletStandard
74
74
  } from "@metamask/solana-wallet-standard";
75
+
76
+ // src/utils.ts
77
+ import {
78
+ createLogger,
79
+ enableDebug as debug
80
+ } from "@metamask/connect-multichain";
81
+ import { getWallets } from "@wallet-standard/app";
82
+ var namespace = "metamask-connect:solana";
83
+ var logger = createLogger(namespace, "93");
84
+ var isMetamaskExtensionRegistered = () => {
85
+ const wallets = getWallets();
86
+ return wallets.get().some((wallet) => wallet.name.toLowerCase().includes("metamask"));
87
+ };
88
+
89
+ // src/connect.ts
75
90
  function createSolanaClient(options) {
76
91
  return __async(this, null, function* () {
77
- var _a, _b, _c, _d;
92
+ var _a, _b, _c, _d, _e;
78
93
  const defaultNetworks = {
79
94
  mainnet: "https://api.mainnet-beta.solana.com"
80
95
  };
@@ -94,22 +109,53 @@ function createSolanaClient(options) {
94
109
  versions: {
95
110
  // typeof guard needed: Metro (React Native) bundles TS source directly,
96
111
  // bypassing the tsup build that substitutes __PACKAGE_VERSION__.
97
- "connect-solana": false ? "unknown" : "0.8.1"
112
+ "connect-solana": false ? "unknown" : "1.1.0"
98
113
  }
99
114
  });
100
115
  const client = core.provider;
101
- const walletName = "MetaMask Connect";
102
- if (!skipAutoRegister) {
116
+ const walletName = "MetaMask";
117
+ let hasRegisteredMmc = false;
118
+ let handledInitRegistration;
119
+ const initRegistrationHandledPromise = new Promise((resolve) => {
120
+ handledInitRegistration = resolve;
121
+ });
122
+ const registerWallet = () => __async(null, null, function* () {
123
+ if (hasRegisteredMmc) {
124
+ logger("MetaMask Connect is already registered. Skipping...");
125
+ return;
126
+ }
127
+ if (isMetamaskExtensionRegistered()) {
128
+ logger("MetaMask extension is already registered. Skipping...");
129
+ return;
130
+ }
103
131
  yield registerSolanaWalletStandard({ client, walletName });
132
+ hasRegisteredMmc = true;
133
+ });
134
+ if (skipAutoRegister) {
135
+ handledInitRegistration();
136
+ } else {
137
+ setTimeout(() => __async(null, null, function* () {
138
+ try {
139
+ yield registerWallet();
140
+ } finally {
141
+ handledInitRegistration();
142
+ }
143
+ }), 1e3);
144
+ }
145
+ const provider = getWalletStandard({ client, walletName });
146
+ const session = yield core.provider.getSession();
147
+ const hasSolanaScope = Object.keys((_e = session == null ? void 0 : session.sessionScopes) != null ? _e : {}).some(
148
+ (scope) => scope.startsWith("solana:")
149
+ );
150
+ if (hasSolanaScope) {
151
+ yield provider.features["standard:connect"].connect();
104
152
  }
105
153
  return {
106
154
  core,
107
- getWallet: () => getWalletStandard({ client, walletName }),
155
+ getWallet: () => provider,
108
156
  registerWallet: () => __async(null, null, function* () {
109
- if (!skipAutoRegister) {
110
- return;
111
- }
112
- yield registerSolanaWalletStandard({ client, walletName });
157
+ yield initRegistrationHandledPromise;
158
+ yield registerWallet();
113
159
  }),
114
160
  disconnect: () => __async(null, null, function* () {
115
161
  return yield core.disconnect(Object.values(SOLANA_CAIP_IDS));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts"],"sourcesContent":["import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ is an esbuild define convention */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\n\n// Value substitued by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const client = core.provider;\n\n const walletName = 'MetaMask Connect';\n\n if (!skipAutoRegister) {\n await registerSolanaWalletStandard({ client, walletName });\n }\n\n return {\n core,\n getWallet: () => getWalletStandard({ client, walletName }),\n registerWallet: async (): Promise<void> => {\n if (!skipAutoRegister) {\n return;\n }\n await registerSolanaWalletStandard({ client, walletName });\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,oBAAoB,kCAAkC;;;ACMxD,IAAM,kBAAiD;AAAA,EAC5D,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AACX;AAQO,SAAS,sBACd,UACwB;AACxB,SAAO,OAAO,QAAQ,QAAQ,EAAE;AAAA,IAC9B,CAAC,KAAK,CAAC,SAAS,MAAM,MAAM;AAC1B,YAAM,SAAS,gBAAgB,OAAwB;AACvD,UAAI,UAAU,QAAQ;AACpB,YAAI,MAAM,IAAI;AAAA,MAChB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AACF;;;ADfO,IAAM,mBAAmB,CAAC;AAAA,EAC/B;AAAA,EACA;AACF,MAG+B;AAC7B,QAAM,eAAe,SAAS;AAAA,IAC5B,CAAC,YAAY,gBAAgB,OAAO;AAAA,EACtC;AACA,QAAM,UAAU,2BAA2B;AAAA,IACzC;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,SAAS,OAAgC,CAAC,KAAK,YAAY;AAChE,UAAM,SAAS,gBAAgB,OAAO;AACtC,UAAM,SAAS,QAAQ,MAAM;AAC7B,QAAI,QAAQ;AACV,UAAI,OAAO,IAAI;AAAA,IACjB;AACA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AACP;;;AEtCA;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAmDP,SAAsB,mBACpB,SACuB;AAAA;AA7DzB;AA8DE,UAAM,kBAA2C;AAAA,MAC/C,SAAS;AAAA,IACX;AAEA,UAAM,oBAAmB,aAAQ,qBAAR,YAA4B;AAErD,UAAM,oBAAoB;AAAA,OACxB,mBAAQ,QAAR,mBAAa,sBAAb,YAAkC;AAAA,IACpC;AAEA,UAAM,OAAO,MAAM,uBAAuB;AAAA,MACxC,MAAM,QAAQ;AAAA,MACd,KAAK;AAAA,QACH;AAAA,MACF;AAAA,MACA,WAAW;AAAA;AAAA,QAET,mBAAiB,aAAQ,cAAR,mBAAmB,oBAAmB;AAAA,MACzD;AAAA,MACA,UAAU;AAAA;AAAA;AAAA,QAGR,kBACE,QACI,YACA;AAAA,MACR;AAAA,IACF,CAAC;AAED,UAAM,SAAS,KAAK;AAEpB,UAAM,aAAa;AAEnB,QAAI,CAAC,kBAAkB;AACrB,YAAM,6BAA6B,EAAE,QAAQ,WAAW,CAAC;AAAA,IAC3D;AAEA,WAAO;AAAA,MACL;AAAA,MACA,WAAW,MAAM,kBAAkB,EAAE,QAAQ,WAAW,CAAC;AAAA,MACzD,gBAAgB,MAA2B;AACzC,YAAI,CAAC,kBAAkB;AACrB;AAAA,QACF;AACA,cAAM,6BAA6B,EAAE,QAAQ,WAAW,CAAC;AAAA,MAC3D;AAAA,MACA,YAAY,MAAS;AACnB,qBAAM,KAAK,WAAW,OAAO,OAAO,eAAe,CAAY;AAAA;AAAA,IACnE;AAAA,EACF;AAAA;","names":[]}
1
+ {"version":3,"sources":["../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts","../../../src/utils.ts"],"sourcesContent":["import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ is an esbuild define convention */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\nimport { isMetamaskExtensionRegistered, logger } from './utils';\n\n// Value substitued by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const client = core.provider;\n\n const walletName = 'MetaMask';\n\n let hasRegisteredMmc = false;\n let handledInitRegistration!: () => void;\n const initRegistrationHandledPromise = new Promise<void>((resolve) => {\n handledInitRegistration = resolve;\n });\n\n const registerWallet = async (): Promise<void> => {\n if (hasRegisteredMmc) {\n logger('MetaMask Connect is already registered. Skipping...');\n return;\n }\n\n if (isMetamaskExtensionRegistered()) {\n logger('MetaMask extension is already registered. Skipping...');\n return;\n }\n\n await registerSolanaWalletStandard({ client, walletName });\n hasRegisteredMmc = true; // eslint-disable-line require-atomic-updates\n };\n\n if (skipAutoRegister) {\n handledInitRegistration();\n } else {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await registerWallet();\n } finally {\n handledInitRegistration();\n }\n }, 1000);\n }\n\n const provider = getWalletStandard({ client, walletName });\n const session = await core.provider.getSession();\n const hasSolanaScope = Object.keys(session?.sessionScopes ?? {}).some(\n (scope) => scope.startsWith('solana:'),\n );\n if (hasSolanaScope) {\n // This will resolve without needing to prompt the user as we know solana scopes are already granted\n await provider.features['standard:connect'].connect();\n }\n\n return {\n core,\n getWallet: () => provider,\n registerWallet: async (): Promise<void> => {\n await initRegistrationHandledPromise;\n await registerWallet();\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n","import {\n createLogger,\n enableDebug as debug,\n} from '@metamask/connect-multichain';\nimport { getWallets } from '@wallet-standard/app';\n\nconst namespace = 'metamask-connect:solana';\n\n// @ts-expect-error logger needs to be typed properly\nexport const logger = createLogger(namespace, '93');\n\nexport const enableDebug = (): void => {\n // @ts-expect-error logger needs to be typed properly\n debug(namespace);\n};\n\n/**\n * Check if MetaMask extension is registered on Solana wallet-standard registry\n *\n * @returns True if extension is registered, false otherwise\n */\nexport const isMetamaskExtensionRegistered = (): boolean => {\n const wallets = getWallets();\n\n return wallets\n .get()\n .some((wallet) => wallet.name.toLowerCase().includes('metamask'));\n};\n"],"mappings":"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","names":[]}
@@ -91,11 +91,23 @@ var getInfuraRpcUrls = ({
91
91
  };
92
92
 
93
93
  // src/connect.ts
94
- var import_connect_multichain2 = require("@metamask/connect-multichain");
94
+ var import_connect_multichain3 = require("@metamask/connect-multichain");
95
95
  var import_solana_wallet_standard = require("@metamask/solana-wallet-standard");
96
+
97
+ // src/utils.ts
98
+ var import_connect_multichain2 = require("@metamask/connect-multichain");
99
+ var import_app = require("@wallet-standard/app");
100
+ var namespace = "metamask-connect:solana";
101
+ var logger = (0, import_connect_multichain2.createLogger)(namespace, "93");
102
+ var isMetamaskExtensionRegistered = () => {
103
+ const wallets = (0, import_app.getWallets)();
104
+ return wallets.get().some((wallet) => wallet.name.toLowerCase().includes("metamask"));
105
+ };
106
+
107
+ // src/connect.ts
96
108
  function createSolanaClient(options) {
97
109
  return __async(this, null, function* () {
98
- var _a, _b, _c, _d;
110
+ var _a, _b, _c, _d, _e;
99
111
  const defaultNetworks = {
100
112
  mainnet: "https://api.mainnet-beta.solana.com"
101
113
  };
@@ -103,7 +115,7 @@ function createSolanaClient(options) {
103
115
  const supportedNetworks = convertNetworksToCAIP(
104
116
  (_c = (_b = options.api) == null ? void 0 : _b.supportedNetworks) != null ? _c : defaultNetworks
105
117
  );
106
- const core = yield (0, import_connect_multichain2.createMultichainClient)({
118
+ const core = yield (0, import_connect_multichain3.createMultichainClient)({
107
119
  dapp: options.dapp,
108
120
  api: {
109
121
  supportedNetworks
@@ -115,22 +127,53 @@ function createSolanaClient(options) {
115
127
  versions: {
116
128
  // typeof guard needed: Metro (React Native) bundles TS source directly,
117
129
  // bypassing the tsup build that substitutes __PACKAGE_VERSION__.
118
- "connect-solana": false ? "unknown" : "0.8.1"
130
+ "connect-solana": false ? "unknown" : "1.1.0"
119
131
  }
120
132
  });
121
133
  const client = core.provider;
122
- const walletName = "MetaMask Connect";
123
- if (!skipAutoRegister) {
134
+ const walletName = "MetaMask";
135
+ let hasRegisteredMmc = false;
136
+ let handledInitRegistration;
137
+ const initRegistrationHandledPromise = new Promise((resolve) => {
138
+ handledInitRegistration = resolve;
139
+ });
140
+ const registerWallet = () => __async(null, null, function* () {
141
+ if (hasRegisteredMmc) {
142
+ logger("MetaMask Connect is already registered. Skipping...");
143
+ return;
144
+ }
145
+ if (isMetamaskExtensionRegistered()) {
146
+ logger("MetaMask extension is already registered. Skipping...");
147
+ return;
148
+ }
124
149
  yield (0, import_solana_wallet_standard.registerSolanaWalletStandard)({ client, walletName });
150
+ hasRegisteredMmc = true;
151
+ });
152
+ if (skipAutoRegister) {
153
+ handledInitRegistration();
154
+ } else {
155
+ setTimeout(() => __async(null, null, function* () {
156
+ try {
157
+ yield registerWallet();
158
+ } finally {
159
+ handledInitRegistration();
160
+ }
161
+ }), 1e3);
162
+ }
163
+ const provider = (0, import_solana_wallet_standard.getWalletStandard)({ client, walletName });
164
+ const session = yield core.provider.getSession();
165
+ const hasSolanaScope = Object.keys((_e = session == null ? void 0 : session.sessionScopes) != null ? _e : {}).some(
166
+ (scope) => scope.startsWith("solana:")
167
+ );
168
+ if (hasSolanaScope) {
169
+ yield provider.features["standard:connect"].connect();
125
170
  }
126
171
  return {
127
172
  core,
128
- getWallet: () => (0, import_solana_wallet_standard.getWalletStandard)({ client, walletName }),
173
+ getWallet: () => provider,
129
174
  registerWallet: () => __async(null, null, function* () {
130
- if (!skipAutoRegister) {
131
- return;
132
- }
133
- yield (0, import_solana_wallet_standard.registerSolanaWalletStandard)({ client, walletName });
175
+ yield initRegistrationHandledPromise;
176
+ yield registerWallet();
134
177
  }),
135
178
  disconnect: () => __async(null, null, function* () {
136
179
  return yield core.disconnect(Object.values(SOLANA_CAIP_IDS));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/index.ts","../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts"],"sourcesContent":["export { getInfuraRpcUrls } from './infura';\nexport { createSolanaClient } from './connect';\nexport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaNetwork,\n SolanaSupportedNetworks,\n} from './types';\n","import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ is an esbuild define convention */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\n\n// Value substitued by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const client = core.provider;\n\n const walletName = 'MetaMask Connect';\n\n if (!skipAutoRegister) {\n await registerSolanaWalletStandard({ client, walletName });\n }\n\n return {\n core,\n getWallet: () => getWalletStandard({ client, walletName }),\n registerWallet: async (): Promise<void> => {\n if (!skipAutoRegister) {\n return;\n }\n await registerSolanaWalletStandard({ client, walletName });\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,gCAA+D;;;ACMxD,IAAM,kBAAiD;AAAA,EAC5D,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AACX;AAQO,SAAS,sBACd,UACwB;AACxB,SAAO,OAAO,QAAQ,QAAQ,EAAE;AAAA,IAC9B,CAAC,KAAK,CAAC,SAAS,MAAM,MAAM;AAC1B,YAAM,SAAS,gBAAgB,OAAwB;AACvD,UAAI,UAAU,QAAQ;AACpB,YAAI,MAAM,IAAI;AAAA,MAChB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AACF;;;ADfO,IAAM,mBAAmB,CAAC;AAAA,EAC/B;AAAA,EACA;AACF,MAG+B;AAC7B,QAAM,eAAe,SAAS;AAAA,IAC5B,CAAC,YAAY,gBAAgB,OAAO;AAAA,EACtC;AACA,QAAM,cAAU,0BAAAA,kBAA2B;AAAA,IACzC;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,SAAS,OAAgC,CAAC,KAAK,YAAY;AAChE,UAAM,SAAS,gBAAgB,OAAO;AACtC,UAAM,SAAS,QAAQ,MAAM;AAC7B,QAAI,QAAQ;AACV,UAAI,OAAO,IAAI;AAAA,IACjB;AACA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AACP;;;AEtCA,IAAAC,6BAGO;AACP,oCAGO;AAmDP,SAAsB,mBACpB,SACuB;AAAA;AA7DzB;AA8DE,UAAM,kBAA2C;AAAA,MAC/C,SAAS;AAAA,IACX;AAEA,UAAM,oBAAmB,aAAQ,qBAAR,YAA4B;AAErD,UAAM,oBAAoB;AAAA,OACxB,mBAAQ,QAAR,mBAAa,sBAAb,YAAkC;AAAA,IACpC;AAEA,UAAM,OAAO,UAAM,mDAAuB;AAAA,MACxC,MAAM,QAAQ;AAAA,MACd,KAAK;AAAA,QACH;AAAA,MACF;AAAA,MACA,WAAW;AAAA;AAAA,QAET,mBAAiB,aAAQ,cAAR,mBAAmB,oBAAmB;AAAA,MACzD;AAAA,MACA,UAAU;AAAA;AAAA;AAAA,QAGR,kBACE,QACI,YACA;AAAA,MACR;AAAA,IACF,CAAC;AAED,UAAM,SAAS,KAAK;AAEpB,UAAM,aAAa;AAEnB,QAAI,CAAC,kBAAkB;AACrB,gBAAM,4DAA6B,EAAE,QAAQ,WAAW,CAAC;AAAA,IAC3D;AAEA,WAAO;AAAA,MACL;AAAA,MACA,WAAW,UAAM,iDAAkB,EAAE,QAAQ,WAAW,CAAC;AAAA,MACzD,gBAAgB,MAA2B;AACzC,YAAI,CAAC,kBAAkB;AACrB;AAAA,QACF;AACA,kBAAM,4DAA6B,EAAE,QAAQ,WAAW,CAAC;AAAA,MAC3D;AAAA,MACA,YAAY,MAAS;AACnB,qBAAM,KAAK,WAAW,OAAO,OAAO,eAAe,CAAY;AAAA;AAAA,IACnE;AAAA,EACF;AAAA;","names":["getInfuraRpcUrlsMultichain","import_connect_multichain"]}
1
+ {"version":3,"sources":["../../../src/index.ts","../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts","../../../src/utils.ts"],"sourcesContent":["export { getInfuraRpcUrls } from './infura';\nexport { createSolanaClient } from './connect';\nexport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaNetwork,\n SolanaSupportedNetworks,\n} from './types';\n","import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ is an esbuild define convention */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\nimport { isMetamaskExtensionRegistered, logger } from './utils';\n\n// Value substitued by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const client = core.provider;\n\n const walletName = 'MetaMask';\n\n let hasRegisteredMmc = false;\n let handledInitRegistration!: () => void;\n const initRegistrationHandledPromise = new Promise<void>((resolve) => {\n handledInitRegistration = resolve;\n });\n\n const registerWallet = async (): Promise<void> => {\n if (hasRegisteredMmc) {\n logger('MetaMask Connect is already registered. Skipping...');\n return;\n }\n\n if (isMetamaskExtensionRegistered()) {\n logger('MetaMask extension is already registered. Skipping...');\n return;\n }\n\n await registerSolanaWalletStandard({ client, walletName });\n hasRegisteredMmc = true; // eslint-disable-line require-atomic-updates\n };\n\n if (skipAutoRegister) {\n handledInitRegistration();\n } else {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await registerWallet();\n } finally {\n handledInitRegistration();\n }\n }, 1000);\n }\n\n const provider = getWalletStandard({ client, walletName });\n const session = await core.provider.getSession();\n const hasSolanaScope = Object.keys(session?.sessionScopes ?? {}).some(\n (scope) => scope.startsWith('solana:'),\n );\n if (hasSolanaScope) {\n // This will resolve without needing to prompt the user as we know solana scopes are already granted\n await provider.features['standard:connect'].connect();\n }\n\n return {\n core,\n getWallet: () => provider,\n registerWallet: async (): Promise<void> => {\n await initRegistrationHandledPromise;\n await registerWallet();\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n","import {\n createLogger,\n enableDebug as debug,\n} from '@metamask/connect-multichain';\nimport { getWallets } from '@wallet-standard/app';\n\nconst namespace = 'metamask-connect:solana';\n\n// @ts-expect-error logger needs to be typed properly\nexport const logger = createLogger(namespace, '93');\n\nexport const enableDebug = (): void => {\n // @ts-expect-error logger needs to be typed properly\n debug(namespace);\n};\n\n/**\n * Check if MetaMask extension is registered on Solana wallet-standard registry\n *\n * @returns True if extension is registered, false otherwise\n */\nexport const isMetamaskExtensionRegistered = (): boolean => {\n const wallets = getWallets();\n\n return wallets\n .get()\n .some((wallet) => wallet.name.toLowerCase().includes('metamask'));\n};\n"],"mappings":"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","names":["getInfuraRpcUrlsMultichain","import_connect_multichain","import_connect_multichain"]}
@@ -72,9 +72,24 @@ import {
72
72
  getWalletStandard,
73
73
  registerSolanaWalletStandard
74
74
  } from "@metamask/solana-wallet-standard";
75
+
76
+ // src/utils.ts
77
+ import {
78
+ createLogger,
79
+ enableDebug as debug
80
+ } from "@metamask/connect-multichain";
81
+ import { getWallets } from "@wallet-standard/app";
82
+ var namespace = "metamask-connect:solana";
83
+ var logger = createLogger(namespace, "93");
84
+ var isMetamaskExtensionRegistered = () => {
85
+ const wallets = getWallets();
86
+ return wallets.get().some((wallet) => wallet.name.toLowerCase().includes("metamask"));
87
+ };
88
+
89
+ // src/connect.ts
75
90
  function createSolanaClient(options) {
76
91
  return __async(this, null, function* () {
77
- var _a, _b, _c, _d;
92
+ var _a, _b, _c, _d, _e;
78
93
  const defaultNetworks = {
79
94
  mainnet: "https://api.mainnet-beta.solana.com"
80
95
  };
@@ -94,22 +109,53 @@ function createSolanaClient(options) {
94
109
  versions: {
95
110
  // typeof guard needed: Metro (React Native) bundles TS source directly,
96
111
  // bypassing the tsup build that substitutes __PACKAGE_VERSION__.
97
- "connect-solana": false ? "unknown" : "0.8.1"
112
+ "connect-solana": false ? "unknown" : "1.1.0"
98
113
  }
99
114
  });
100
115
  const client = core.provider;
101
- const walletName = "MetaMask Connect";
102
- if (!skipAutoRegister) {
116
+ const walletName = "MetaMask";
117
+ let hasRegisteredMmc = false;
118
+ let handledInitRegistration;
119
+ const initRegistrationHandledPromise = new Promise((resolve) => {
120
+ handledInitRegistration = resolve;
121
+ });
122
+ const registerWallet = () => __async(null, null, function* () {
123
+ if (hasRegisteredMmc) {
124
+ logger("MetaMask Connect is already registered. Skipping...");
125
+ return;
126
+ }
127
+ if (isMetamaskExtensionRegistered()) {
128
+ logger("MetaMask extension is already registered. Skipping...");
129
+ return;
130
+ }
103
131
  yield registerSolanaWalletStandard({ client, walletName });
132
+ hasRegisteredMmc = true;
133
+ });
134
+ if (skipAutoRegister) {
135
+ handledInitRegistration();
136
+ } else {
137
+ setTimeout(() => __async(null, null, function* () {
138
+ try {
139
+ yield registerWallet();
140
+ } finally {
141
+ handledInitRegistration();
142
+ }
143
+ }), 1e3);
144
+ }
145
+ const provider = getWalletStandard({ client, walletName });
146
+ const session = yield core.provider.getSession();
147
+ const hasSolanaScope = Object.keys((_e = session == null ? void 0 : session.sessionScopes) != null ? _e : {}).some(
148
+ (scope) => scope.startsWith("solana:")
149
+ );
150
+ if (hasSolanaScope) {
151
+ yield provider.features["standard:connect"].connect();
104
152
  }
105
153
  return {
106
154
  core,
107
- getWallet: () => getWalletStandard({ client, walletName }),
155
+ getWallet: () => provider,
108
156
  registerWallet: () => __async(null, null, function* () {
109
- if (!skipAutoRegister) {
110
- return;
111
- }
112
- yield registerSolanaWalletStandard({ client, walletName });
157
+ yield initRegistrationHandledPromise;
158
+ yield registerWallet();
113
159
  }),
114
160
  disconnect: () => __async(null, null, function* () {
115
161
  return yield core.disconnect(Object.values(SOLANA_CAIP_IDS));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts"],"sourcesContent":["import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ is an esbuild define convention */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\n\n// Value substitued by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const client = core.provider;\n\n const walletName = 'MetaMask Connect';\n\n if (!skipAutoRegister) {\n await registerSolanaWalletStandard({ client, walletName });\n }\n\n return {\n core,\n getWallet: () => getWalletStandard({ client, walletName }),\n registerWallet: async (): Promise<void> => {\n if (!skipAutoRegister) {\n return;\n }\n await registerSolanaWalletStandard({ client, walletName });\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,oBAAoB,kCAAkC;;;ACMxD,IAAM,kBAAiD;AAAA,EAC5D,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AACX;AAQO,SAAS,sBACd,UACwB;AACxB,SAAO,OAAO,QAAQ,QAAQ,EAAE;AAAA,IAC9B,CAAC,KAAK,CAAC,SAAS,MAAM,MAAM;AAC1B,YAAM,SAAS,gBAAgB,OAAwB;AACvD,UAAI,UAAU,QAAQ;AACpB,YAAI,MAAM,IAAI;AAAA,MAChB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AACF;;;ADfO,IAAM,mBAAmB,CAAC;AAAA,EAC/B;AAAA,EACA;AACF,MAG+B;AAC7B,QAAM,eAAe,SAAS;AAAA,IAC5B,CAAC,YAAY,gBAAgB,OAAO;AAAA,EACtC;AACA,QAAM,UAAU,2BAA2B;AAAA,IACzC;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,SAAS,OAAgC,CAAC,KAAK,YAAY;AAChE,UAAM,SAAS,gBAAgB,OAAO;AACtC,UAAM,SAAS,QAAQ,MAAM;AAC7B,QAAI,QAAQ;AACV,UAAI,OAAO,IAAI;AAAA,IACjB;AACA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AACP;;;AEtCA;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAmDP,SAAsB,mBACpB,SACuB;AAAA;AA7DzB;AA8DE,UAAM,kBAA2C;AAAA,MAC/C,SAAS;AAAA,IACX;AAEA,UAAM,oBAAmB,aAAQ,qBAAR,YAA4B;AAErD,UAAM,oBAAoB;AAAA,OACxB,mBAAQ,QAAR,mBAAa,sBAAb,YAAkC;AAAA,IACpC;AAEA,UAAM,OAAO,MAAM,uBAAuB;AAAA,MACxC,MAAM,QAAQ;AAAA,MACd,KAAK;AAAA,QACH;AAAA,MACF;AAAA,MACA,WAAW;AAAA;AAAA,QAET,mBAAiB,aAAQ,cAAR,mBAAmB,oBAAmB;AAAA,MACzD;AAAA,MACA,UAAU;AAAA;AAAA;AAAA,QAGR,kBACE,QACI,YACA;AAAA,MACR;AAAA,IACF,CAAC;AAED,UAAM,SAAS,KAAK;AAEpB,UAAM,aAAa;AAEnB,QAAI,CAAC,kBAAkB;AACrB,YAAM,6BAA6B,EAAE,QAAQ,WAAW,CAAC;AAAA,IAC3D;AAEA,WAAO;AAAA,MACL;AAAA,MACA,WAAW,MAAM,kBAAkB,EAAE,QAAQ,WAAW,CAAC;AAAA,MACzD,gBAAgB,MAA2B;AACzC,YAAI,CAAC,kBAAkB;AACrB;AAAA,QACF;AACA,cAAM,6BAA6B,EAAE,QAAQ,WAAW,CAAC;AAAA,MAC3D;AAAA,MACA,YAAY,MAAS;AACnB,qBAAM,KAAK,WAAW,OAAO,OAAO,eAAe,CAAY;AAAA;AAAA,IACnE;AAAA,EACF;AAAA;","names":[]}
1
+ {"version":3,"sources":["../../../src/infura.ts","../../../src/networks.ts","../../../src/connect.ts","../../../src/utils.ts"],"sourcesContent":["import { getInfuraRpcUrls as getInfuraRpcUrlsMultichain } from '@metamask/connect-multichain';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport { SOLANA_CAIP_IDS } from './networks';\nimport type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * Generates Infura RPC URLs for Solana networks keyed by Solana network name.\n *\n * The returned map is intended for `createSolanaClient({ api: { supportedNetworks } })`.\n *\n * @param options - The options for generating Solana Infura RPC URLs\n * @param options.infuraApiKey - The Infura API key\n * @param options.networks - Solana networks to include in the returned map\n * @returns A map of Solana network names to Infura RPC URLs\n */\nexport const getInfuraRpcUrls = ({\n infuraApiKey,\n networks,\n}: {\n infuraApiKey: string;\n networks: SolanaNetwork[];\n}): SolanaSupportedNetworks => {\n const caipChainIds = networks.map(\n (network) => SOLANA_CAIP_IDS[network] as CaipChainId,\n );\n const caipMap = getInfuraRpcUrlsMultichain({\n infuraApiKey,\n caipChainIds,\n });\n\n return networks.reduce<SolanaSupportedNetworks>((acc, network) => {\n const caipId = SOLANA_CAIP_IDS[network] as CaipChainId;\n const rpcUrl = caipMap[caipId];\n if (rpcUrl) {\n acc[network] = rpcUrl;\n }\n return acc;\n }, {});\n};\n","import type { SolanaNetwork, SolanaSupportedNetworks } from './types';\n\n/**\n * CAIP-2 chain IDs for Solana networks.\n * The reference is the first 32 characters of the Base58-encoded genesis hash.\n */\nexport const SOLANA_CAIP_IDS: Record<SolanaNetwork, string> = {\n mainnet: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n devnet: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n testnet: 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',\n};\n\n/**\n * Converts a record of network names to RPC URLs into a record of CAIP IDs to RPC URLs.\n *\n * @param networks - A record of network names to RPC URLs\n * @returns A record of CAIP IDs to RPC URLs\n */\nexport function convertNetworksToCAIP(\n networks: SolanaSupportedNetworks,\n): Record<string, string> {\n return Object.entries(networks).reduce<Record<string, string>>(\n (acc, [network, rpcUrl]) => {\n const caipId = SOLANA_CAIP_IDS[network as SolanaNetwork];\n if (caipId && rpcUrl) {\n acc[caipId] = rpcUrl;\n }\n return acc;\n },\n {},\n );\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- __PACKAGE_VERSION__ is an esbuild define convention */\nimport {\n createMultichainClient,\n type Scope,\n} from '@metamask/connect-multichain';\nimport {\n getWalletStandard,\n registerSolanaWalletStandard,\n} from '@metamask/solana-wallet-standard';\n\nimport { convertNetworksToCAIP, SOLANA_CAIP_IDS } from './networks';\nimport type {\n SolanaClient,\n SolanaConnectOptions,\n SolanaSupportedNetworks,\n} from './types';\nimport { isMetamaskExtensionRegistered, logger } from './utils';\n\n// Value substitued by tsup at build time\ndeclare const __PACKAGE_VERSION__: string | undefined;\n\n/**\n * Creates a new Solana client for connecting to MetaMask via wallet-standard.\n *\n * This function initializes the MultichainSDK and provides methods to get or register\n * a wallet-standard compatible wallet. The wallet handles session creation internally\n * when users connect through the Solana wallet adapter UI.\n *\n * @param options - Configuration options for the Solana client\n * @param options.dapp - Dapp identification and branding settings\n * @param options.api - Optional API configuration with supported networks\n * @param options.api.supportedNetworks - Record mapping network names (mainnet, devnet, testnet) to RPC URLs\n * @param [options.analytics] - Analytics configuration\n * @param [options.analytics.integrationType] - Integration type for analytics (defaults to 'direct')\n * @param options.debug - Enable debug logging\n * @param options.skipAutoRegister - Skip auto-registering the wallet during creation (defaults to false)\n * @returns A promise that resolves to the Solana client instance\n *\n * @example\n * ```typescript\n * import { createSolanaClient } from '@metamask/connect-solana';\n *\n * // Wallet is auto-registered and ready to use\n * const client = await createSolanaClient({\n * dapp: {\n * name: 'My Solana DApp',\n * url: 'https://mydapp.com',\n * },\n * api: {\n * supportedNetworks: {\n * mainnet: 'https://api.mainnet-beta.solana.com',\n * devnet: 'https://api.devnet.solana.com',\n * },\n * },\n * });\n *\n * // Get the wallet instance directly\n * const wallet = client.getWallet();\n * ```\n */\nexport async function createSolanaClient(\n options: SolanaConnectOptions,\n): Promise<SolanaClient> {\n const defaultNetworks: SolanaSupportedNetworks = {\n mainnet: 'https://api.mainnet-beta.solana.com',\n };\n\n const skipAutoRegister = options.skipAutoRegister ?? false;\n\n const supportedNetworks = convertNetworksToCAIP(\n options.api?.supportedNetworks ?? defaultNetworks,\n );\n\n const core = await createMultichainClient({\n dapp: options.dapp,\n api: {\n supportedNetworks,\n },\n analytics: {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n integrationType: options.analytics?.integrationType || 'direct',\n },\n versions: {\n // typeof guard needed: Metro (React Native) bundles TS source directly,\n // bypassing the tsup build that substitutes __PACKAGE_VERSION__.\n 'connect-solana':\n typeof __PACKAGE_VERSION__ === 'undefined'\n ? 'unknown'\n : __PACKAGE_VERSION__,\n },\n });\n\n const client = core.provider;\n\n const walletName = 'MetaMask';\n\n let hasRegisteredMmc = false;\n let handledInitRegistration!: () => void;\n const initRegistrationHandledPromise = new Promise<void>((resolve) => {\n handledInitRegistration = resolve;\n });\n\n const registerWallet = async (): Promise<void> => {\n if (hasRegisteredMmc) {\n logger('MetaMask Connect is already registered. Skipping...');\n return;\n }\n\n if (isMetamaskExtensionRegistered()) {\n logger('MetaMask extension is already registered. Skipping...');\n return;\n }\n\n await registerSolanaWalletStandard({ client, walletName });\n hasRegisteredMmc = true; // eslint-disable-line require-atomic-updates\n };\n\n if (skipAutoRegister) {\n handledInitRegistration();\n } else {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await registerWallet();\n } finally {\n handledInitRegistration();\n }\n }, 1000);\n }\n\n const provider = getWalletStandard({ client, walletName });\n const session = await core.provider.getSession();\n const hasSolanaScope = Object.keys(session?.sessionScopes ?? {}).some(\n (scope) => scope.startsWith('solana:'),\n );\n if (hasSolanaScope) {\n // This will resolve without needing to prompt the user as we know solana scopes are already granted\n await provider.features['standard:connect'].connect();\n }\n\n return {\n core,\n getWallet: () => provider,\n registerWallet: async (): Promise<void> => {\n await initRegistrationHandledPromise;\n await registerWallet();\n },\n disconnect: async () =>\n await core.disconnect(Object.values(SOLANA_CAIP_IDS) as Scope[]),\n };\n}\n","import {\n createLogger,\n enableDebug as debug,\n} from '@metamask/connect-multichain';\nimport { getWallets } from '@wallet-standard/app';\n\nconst namespace = 'metamask-connect:solana';\n\n// @ts-expect-error logger needs to be typed properly\nexport const logger = createLogger(namespace, '93');\n\nexport const enableDebug = (): void => {\n // @ts-expect-error logger needs to be typed properly\n debug(namespace);\n};\n\n/**\n * Check if MetaMask extension is registered on Solana wallet-standard registry\n *\n * @returns True if extension is registered, false otherwise\n */\nexport const isMetamaskExtensionRegistered = (): boolean => {\n const wallets = getWallets();\n\n return wallets\n .get()\n .some((wallet) => wallet.name.toLowerCase().includes('metamask'));\n};\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/connect-solana",
3
- "version": "0.8.1",
3
+ "version": "1.1.0",
4
4
  "description": "Solana Layer for MetaMask Connect",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -58,8 +58,9 @@
58
58
  "test:watch": "vitest watch"
59
59
  },
60
60
  "dependencies": {
61
- "@metamask/connect-multichain": "^0.12.1",
61
+ "@metamask/connect-multichain": "^0.13.0",
62
62
  "@metamask/solana-wallet-standard": "^0.6.0",
63
+ "@wallet-standard/app": "~1.1.0",
63
64
  "@wallet-standard/base": "^1.1.0"
64
65
  },
65
66
  "devDependencies": {