@openzeppelin/ui-builder-adapter-evm 1.2.0 → 1.4.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 (105) hide show
  1. package/README.md +33 -18
  2. package/dist/index.cjs +4651 -4448
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +12 -226
  5. package/dist/index.d.ts +12 -226
  6. package/dist/index.js +4737 -4535
  7. package/dist/index.js.map +1 -1
  8. package/package.json +7 -6
  9. package/src/__tests__/adapter-parsing.test.ts +4 -3
  10. package/src/__tests__/getDefaultServiceConfig.test.ts +185 -0
  11. package/src/__tests__/mocks/mock-network-configs.ts +1 -1
  12. package/src/__tests__/provenanceLinks.test.ts +6 -4
  13. package/src/__tests__/providerSelection.test.ts +5 -4
  14. package/src/__tests__/timeouts.test.ts +5 -3
  15. package/src/__tests__/wallet-connect.test.ts +2 -2
  16. package/src/adapter.ts +61 -107
  17. package/src/configuration/execution.ts +1 -52
  18. package/src/configuration/index.ts +2 -3
  19. package/src/configuration/network-services.ts +47 -60
  20. package/src/index.ts +22 -13
  21. package/src/networks/index.ts +2 -1
  22. package/src/networks/mainnet.ts +1 -1
  23. package/src/networks/testnet.ts +1 -1
  24. package/src/query/adapter-query.ts +72 -0
  25. package/src/query/index.ts +2 -2
  26. package/src/transaction/components/useEvmRelayerOptions.ts +5 -3
  27. package/src/transaction/index.ts +1 -5
  28. package/src/types/artifacts.ts +5 -30
  29. package/src/types/providers.ts +7 -18
  30. package/src/wallet/components/EvmWalletUiRoot.tsx +1 -1
  31. package/src/wallet/evmUiKitManager.ts +26 -129
  32. package/src/wallet/hooks/index.ts +0 -1
  33. package/src/wallet/implementation/wagmi-implementation.ts +45 -577
  34. package/src/wallet/index.ts +2 -3
  35. package/src/wallet/rainbowkit/__tests__/export-service.test.ts +1 -2
  36. package/src/wallet/rainbowkit/componentFactory.ts +10 -8
  37. package/src/wallet/rainbowkit/components.tsx +16 -133
  38. package/src/wallet/rainbowkit/index.ts +27 -5
  39. package/src/wallet/utils/__tests__/uiKitService.test.ts +5 -1
  40. package/src/wallet/utils/connection.ts +8 -52
  41. package/src/wallet/utils/index.ts +0 -2
  42. package/src/wallet/utils/uiKitService.ts +7 -3
  43. package/src/wallet/utils/walletImplementationManager.ts +5 -4
  44. package/src/wallet/utils.ts +1 -65
  45. package/src/abi/__tests__/etherscan-v2.test.ts +0 -117
  46. package/src/abi/__tests__/transformer.test.ts +0 -342
  47. package/src/abi/comparison.ts +0 -389
  48. package/src/abi/etherscan-v2.ts +0 -243
  49. package/src/abi/etherscan.ts +0 -158
  50. package/src/abi/index.ts +0 -7
  51. package/src/abi/loader.ts +0 -415
  52. package/src/abi/sourcify.ts +0 -75
  53. package/src/abi/transformer.ts +0 -163
  54. package/src/abi/types.ts +0 -101
  55. package/src/configuration/__tests__/explorer.test.ts +0 -174
  56. package/src/configuration/__tests__/rpc.test.ts +0 -176
  57. package/src/configuration/explorer.ts +0 -243
  58. package/src/configuration/rpc.ts +0 -257
  59. package/src/mapping/__tests__/field-generator.test.ts +0 -137
  60. package/src/mapping/__tests__/type-mapper.test.ts +0 -139
  61. package/src/mapping/constants.ts +0 -57
  62. package/src/mapping/field-generator.ts +0 -115
  63. package/src/mapping/index.ts +0 -4
  64. package/src/mapping/type-mapper.ts +0 -80
  65. package/src/proxy/detection.ts +0 -465
  66. package/src/query/handler.ts +0 -227
  67. package/src/query/view-checker.ts +0 -10
  68. package/src/transaction/eoa.ts +0 -98
  69. package/src/transaction/execution-strategy.ts +0 -33
  70. package/src/transaction/formatter.ts +0 -101
  71. package/src/transaction/relayer.ts +0 -380
  72. package/src/transaction/sender.ts +0 -185
  73. package/src/transform/index.ts +0 -3
  74. package/src/transform/input-parser.ts +0 -177
  75. package/src/transform/output-formatter.ts +0 -64
  76. package/src/types/__tests__/artifacts.test.ts +0 -105
  77. package/src/types.ts +0 -92
  78. package/src/utils/__tests__/artifacts.test.ts +0 -81
  79. package/src/utils/artifacts.ts +0 -30
  80. package/src/utils/formatting.ts +0 -25
  81. package/src/utils/gas.ts +0 -17
  82. package/src/utils/index.ts +0 -6
  83. package/src/utils/json.ts +0 -19
  84. package/src/utils/validation.ts +0 -10
  85. package/src/validation/eoa.ts +0 -33
  86. package/src/validation/index.ts +0 -2
  87. package/src/validation/relayer.ts +0 -13
  88. package/src/wallet/__tests__/utils.test.ts +0 -149
  89. package/src/wallet/components/account/AccountDisplay.tsx +0 -52
  90. package/src/wallet/components/connect/ConnectButton.tsx +0 -125
  91. package/src/wallet/components/connect/ConnectorDialog.tsx +0 -140
  92. package/src/wallet/components/index.ts +0 -4
  93. package/src/wallet/components/network/NetworkSwitcher.tsx +0 -90
  94. package/src/wallet/context/index.ts +0 -1
  95. package/src/wallet/context/wagmi-context.tsx +0 -7
  96. package/src/wallet/hooks/useIsWagmiProviderInitialized.ts +0 -11
  97. package/src/wallet/rainbowkit/config-generator.ts +0 -56
  98. package/src/wallet/rainbowkit/config-service.ts +0 -169
  99. package/src/wallet/rainbowkit/export-service.ts +0 -18
  100. package/src/wallet/rainbowkit/rainbowkitAssetManager.ts +0 -74
  101. package/src/wallet/rainbowkit/types.ts +0 -74
  102. package/src/wallet/rainbowkit/utils.ts +0 -96
  103. package/src/wallet/services/configResolutionService.ts +0 -65
  104. package/src/wallet/utils/SafeWagmiComponent.tsx +0 -72
  105. package/src/wallet/utils/filterWalletComponents.ts +0 -89
@@ -1,599 +1,67 @@
1
1
  /**
2
- * Private Wagmi implementation for EVM wallet connection
2
+ * EVM Wagmi Wallet Implementation
3
3
  *
4
- * This file contains the internal implementation of Wagmi and Viem for wallet connection.
5
- * It's encapsulated within the EVM adapter and not exposed to the rest of the application.
4
+ * This file configures and exports the core WagmiWalletImplementation
5
+ * with EVM-specific settings.
6
6
  */
7
- import { injected, metaMask, safe, walletConnect } from '@wagmi/connectors';
8
7
  import {
9
- connect,
10
- createConfig,
11
- disconnect,
12
- getAccount,
13
- getPublicClient as getWagmiCorePublicClient,
14
- getWalletClient as getWagmiWalletClient,
15
- switchChain,
16
- watchAccount,
17
- type Config,
18
- type GetAccountReturnType,
19
- type CreateConnectorFn as WagmiCreateConnectorFn,
20
- } from '@wagmi/core';
21
- import { http, PublicClient, WalletClient, type Chain } from 'viem';
8
+ WagmiWalletImplementation as CoreWagmiWalletImplementation,
9
+ getWagmiConfigForRainbowKit,
10
+ type WagmiConfigChains,
11
+ type WagmiWalletConfig,
12
+ } from '@openzeppelin/ui-builder-adapter-evm-core';
13
+ import type { UiKitConfiguration } from '@openzeppelin/ui-types';
22
14
 
23
- import type { Connector, UiKitConfiguration } from '@openzeppelin/ui-types';
24
- import { appConfigService, logger } from '@openzeppelin/ui-utils';
25
-
26
- import { getUserRpcUrl } from '../../configuration/rpc';
27
15
  import { evmNetworks } from '../../networks';
28
- import { getWagmiConfigForRainbowKit } from '../rainbowkit';
29
- import { type WagmiConfigChains } from '../types';
30
-
31
- const LOG_SYSTEM = 'WagmiWalletImplementation'; // Define LOG_SYSTEM here
32
16
 
33
17
  /**
34
- * Generates the supported chains for Wagmi from the EVM network configurations.
18
+ * Generates the supported chains from EVM network configurations.
35
19
  * Only includes networks that have a viemChain property (ensuring wagmi compatibility).
36
- * This ensures that wagmi only supports networks that are defined in mainnet.ts and testnet.ts.
37
20
  */
38
- const getSupportedChainsFromNetworks = (): readonly Chain[] => {
39
- const chains = evmNetworks
40
- .filter((network) => network.viemChain) // Only include networks with viemChain
21
+ const getSupportedChainsFromNetworks = () => {
22
+ return evmNetworks
23
+ .filter((network) => network.viemChain)
41
24
  .map((network) => network.viemChain!)
42
- .filter((chain, index, self) => self.findIndex((c) => c.id === chain.id) === index); // Remove duplicates
43
-
44
- logger.info(
45
- LOG_SYSTEM,
46
- `Generated supported chains from network configurations: ${chains.length} chains`,
47
- chains.map((c) => ({ id: c.id, name: c.name }))
48
- );
49
-
50
- return chains;
25
+ .filter((chain, index, self) => self.findIndex((c) => c.id === chain.id) === index);
51
26
  };
52
27
 
53
28
  /**
54
- * Generates the mapping from Viem chain IDs to application network IDs.
55
- * This mapping is auto-generated from the EVM network configurations.
29
+ * The supported chains for EVM adapter.
56
30
  */
57
- const getChainIdToNetworkIdMapping = (): Record<number, string> => {
58
- const mapping = evmNetworks
59
- .filter((network) => network.viemChain) // Only include networks with viemChain
60
- .reduce(
61
- (acc, network) => {
62
- acc[network.chainId] = network.id;
63
- return acc;
64
- },
65
- {} as Record<number, string>
66
- );
67
-
68
- logger.info(
69
- LOG_SYSTEM,
70
- 'Generated chain ID to network ID mapping from network configurations:',
71
- mapping
72
- );
73
-
74
- return mapping;
75
- };
31
+ const defaultSupportedChains = getSupportedChainsFromNetworks();
76
32
 
77
33
  /**
78
- * The supported chains for Wagmi, dynamically generated from network configurations.
79
- * This ensures consistency between adapter networks and wagmi-supported networks.
80
- */
81
- const defaultSupportedChains: readonly Chain[] = getSupportedChainsFromNetworks();
82
-
83
- /**
84
- * Auto-generated mapping from Viem chain IDs to application network IDs.
85
- * This mapping is essential for AppConfigService to look up RPC URL overrides.
86
- * It's automatically synchronized with the networks defined in mainnet.ts and testnet.ts.
87
- */
88
- const viemChainIdToAppNetworkId: Record<number, string> = getChainIdToNetworkIdMapping();
89
-
90
- /**
91
- * Class responsible for encapsulating Wagmi core logic for wallet interactions.
92
- * This class should not be used directly by UI components. The EvmAdapter
93
- * exposes a standardized interface for wallet operations.
94
- * It manages Wagmi Config instances and provides methods for wallet actions.
34
+ * Create an EVM-configured WagmiWalletImplementation instance.
35
+ *
36
+ * @param walletConnectProjectId - Optional WalletConnect project ID
37
+ * @param initialUiKitConfig - Optional initial UI kit configuration
38
+ * @returns A configured WagmiWalletImplementation instance
95
39
  */
96
- export class WagmiWalletImplementation {
97
- private defaultInstanceConfig: Config | null = null;
98
- private activeWagmiConfig: Config | null = null; // To be set by EvmUiKitManager
99
- private unsubscribe?: ReturnType<typeof watchAccount>;
100
- private initialized: boolean = false;
101
- private walletConnectProjectId?: string;
102
- private rpcConfigUnsubscribe?: () => void;
103
-
104
- /**
105
- * Constructs the WagmiWalletImplementation.
106
- * Configuration for Wagmi is deferred until actually needed or set externally.
107
- * @param walletConnectProjectIdFromAppConfig - Optional WalletConnect Project ID from global app configuration.
108
- * @param initialUiKitConfig - Optional initial UI kit configuration, primarily for logging the anticipated kit.
109
- */
110
- constructor(
111
- walletConnectProjectIdFromAppConfig?: string,
112
- initialUiKitConfig?: UiKitConfiguration
113
- ) {
114
- this.walletConnectProjectId = walletConnectProjectIdFromAppConfig;
115
- logger.info(
116
- LOG_SYSTEM,
117
- 'Constructor called. Initial anticipated kitName:',
118
- initialUiKitConfig?.kitName
119
- );
120
- this.initialized = true;
121
- logger.info(
122
- LOG_SYSTEM,
123
- 'WagmiWalletImplementation instance initialized (Wagmi config creation deferred).'
124
- );
125
- // Subscribe to RPC configuration changes to invalidate cached config
126
- this.setupRpcConfigListener();
127
- // No config created here by default anymore.
128
- }
129
-
130
- /**
131
- * Sets up a listener for RPC configuration changes to invalidate the cached Wagmi config
132
- * when user changes RPC settings.
133
- */
134
- private setupRpcConfigListener(): void {
135
- // Import dynamically to avoid circular dependencies
136
- import('@openzeppelin/ui-utils')
137
- .then(({ userRpcConfigService }) => {
138
- // Subscribe to all RPC config changes
139
- this.rpcConfigUnsubscribe = userRpcConfigService.subscribe('*', (event) => {
140
- if (event.type === 'rpc-config-changed' || event.type === 'rpc-config-cleared') {
141
- logger.info(
142
- LOG_SYSTEM,
143
- `RPC config changed for network ${event.networkId}. Invalidating cached Wagmi config.`
144
- );
145
- // Invalidate the cached config to force recreation with new RPC settings
146
- this.defaultInstanceConfig = null;
147
- }
148
- });
149
- })
150
- .catch((error) => {
151
- logger.error(LOG_SYSTEM, 'Failed to setup RPC config listener:', error);
152
- });
153
- }
154
-
155
- /**
156
- * Cleanup method to unsubscribe from RPC config changes
157
- */
158
- public cleanup(): void {
159
- if (this.rpcConfigUnsubscribe) {
160
- this.rpcConfigUnsubscribe();
161
- this.rpcConfigUnsubscribe = undefined;
162
- }
163
- if (this.unsubscribe) {
164
- this.unsubscribe();
165
- this.unsubscribe = undefined;
166
- }
167
- }
168
-
169
- /**
170
- * Sets the externally determined, currently active WagmiConfig instance.
171
- * This is typically called by EvmUiKitManager after it has resolved the appropriate
172
- * config for the selected UI kit (e.g., RainbowKit's config or a default custom config).
173
- * @param config - The Wagmi Config object to set as active, or null to clear it.
174
- */
175
- public setActiveWagmiConfig(config: Config | null): void {
176
- logger.info(
177
- LOG_SYSTEM,
178
- 'setActiveWagmiConfig called with config:',
179
- config ? 'Valid Config' : 'Null'
180
- );
181
- this.activeWagmiConfig = config;
182
-
183
- // If the activeWagmiConfig instance has changed and there was an existing direct subscription
184
- // via onWalletConnectionChange, that subscription was bound to the *previous* config instance.
185
- // It might now be stale or not receive updates reflecting the new config context.
186
- // Consumers relying on onWalletConnectionChange for live updates across fundamental config changes
187
- // (e.g., switching UI kits or major network group changes affecting the config instance)
188
- // may need to re-invoke onWalletConnectionChange to get a new subscription bound to the new config.
189
- // UI components should primarily rely on useWalletState and derived hooks for reactivity,
190
- // which will naturally update with the new adapter/config context.
191
- if (this.unsubscribe) {
192
- logger.warn(
193
- LOG_SYSTEM,
194
- 'setActiveWagmiConfig: Active WagmiConfig instance has changed. Existing direct watchAccount subscription (via onWalletConnectionChange) may be stale and operating on an old config instance.'
195
- );
196
- }
197
- }
198
-
199
- /**
200
- * Creates a default WagmiConfig instance on demand.
201
- * This configuration includes standard connectors (injected, MetaMask, Safe)
202
- * and WalletConnect if a project ID is available.
203
- * Used as a fallback or for 'custom' UI kit mode.
204
- * @returns A Wagmi Config object.
205
- */
206
- private createDefaultConfig(): Config {
207
- const baseConnectors: WagmiCreateConnectorFn[] = [injected(), metaMask(), safe()];
208
- if (this.walletConnectProjectId?.trim()) {
209
- baseConnectors.push(walletConnect({ projectId: this.walletConnectProjectId }));
210
- logger.info(LOG_SYSTEM, 'WalletConnect connector added to DEFAULT config.');
211
- } else {
212
- logger.warn(
213
- LOG_SYSTEM,
214
- 'WalletConnect Project ID not provided; WC connector unavailable for DEFAULT config.'
215
- );
216
- }
217
- const transportsConfig = defaultSupportedChains.reduce(
218
- (acc, chainDefinition) => {
219
- let rpcUrlToUse: string | undefined = chainDefinition.rpcUrls.default?.http?.[0];
220
- const appNetworkIdString = viemChainIdToAppNetworkId[chainDefinition.id];
221
- if (appNetworkIdString) {
222
- // Prefer user-configured RPC from generic service
223
- let httpRpcOverride: string | undefined = getUserRpcUrl(appNetworkIdString);
224
- // Fallback to AppConfigService override if no user config
225
- if (!httpRpcOverride) {
226
- const rpcOverrideSetting = appConfigService.getRpcEndpointOverride(appNetworkIdString);
227
- if (typeof rpcOverrideSetting === 'string') {
228
- httpRpcOverride = rpcOverrideSetting;
229
- } else if (typeof rpcOverrideSetting === 'object') {
230
- // Handle both RpcEndpointConfig and UserRpcProviderConfig
231
- if ('http' in rpcOverrideSetting && rpcOverrideSetting.http) {
232
- httpRpcOverride = rpcOverrideSetting.http;
233
- } else if ('url' in rpcOverrideSetting && rpcOverrideSetting.url) {
234
- httpRpcOverride = rpcOverrideSetting.url;
235
- }
236
- }
237
- }
238
- if (httpRpcOverride) {
239
- logger.info(
240
- LOG_SYSTEM,
241
- `Using overridden RPC for chain ${chainDefinition.name} (default config): ${httpRpcOverride}`
242
- );
243
- rpcUrlToUse = httpRpcOverride;
244
- }
245
- }
246
- acc[chainDefinition.id] = http(rpcUrlToUse);
247
- return acc;
248
- },
249
- {} as Record<number, ReturnType<typeof http>>
250
- );
251
- try {
252
- const defaultConfig = createConfig({
253
- chains: defaultSupportedChains as unknown as WagmiConfigChains,
254
- connectors: baseConnectors,
255
- transports: transportsConfig,
256
- });
257
- logger.info(LOG_SYSTEM, 'Default Wagmi config created successfully on demand.');
258
- return defaultConfig;
259
- } catch (error) {
260
- logger.error(LOG_SYSTEM, 'Error creating default Wagmi config on demand:', error);
261
- return createConfig({
262
- chains: [defaultSupportedChains[0]] as unknown as WagmiConfigChains,
263
- connectors: [injected()],
264
- transports: { [defaultSupportedChains[0].id]: http() },
265
- });
266
- }
267
- }
268
-
269
- /**
270
- * Wrapper function to convert AppConfigService RPC overrides to the format expected by RainbowKit.
271
- * @param networkId - The network ID to get RPC override for
272
- * @returns RPC configuration in the format expected by RainbowKit
273
- */
274
- private getRpcOverrideForRainbowKit(
275
- networkId: string
276
- ): string | { http?: string; ws?: string } | undefined {
277
- // Prefer user-configured RPC from generic service first
278
- const userRpcUrl = getUserRpcUrl(networkId);
279
- if (userRpcUrl) {
280
- return { http: userRpcUrl };
281
- }
282
-
283
- const rpcOverrideSetting = appConfigService.getRpcEndpointOverride(networkId);
284
-
285
- if (typeof rpcOverrideSetting === 'string') {
286
- return rpcOverrideSetting;
287
- } else if (typeof rpcOverrideSetting === 'object' && rpcOverrideSetting !== null) {
288
- // Check for UserRpcProviderConfig first
289
- if ('url' in rpcOverrideSetting && typeof rpcOverrideSetting.url === 'string') {
290
- // It's a UserRpcProviderConfig - convert url to http
291
- return {
292
- http: rpcOverrideSetting.url,
293
- };
294
- } else if ('http' in rpcOverrideSetting || 'ws' in rpcOverrideSetting) {
295
- // It's an RpcEndpointConfig
296
- const config = rpcOverrideSetting as { http?: string; ws?: string };
297
- return {
298
- http: config.http,
299
- ws: config.ws,
300
- };
301
- }
302
- }
303
-
304
- return undefined;
305
- }
306
-
307
- /**
308
- * Retrieves or creates the WagmiConfig specifically for RainbowKit.
309
- * This delegates to `getWagmiConfigForRainbowKit` service which handles caching
310
- * and uses RainbowKit's `getDefaultConfig`.
311
- * @param currentAdapterUiKitConfig - The fully resolved UI kit configuration for the adapter.
312
- * @returns A Promise resolving to the RainbowKit-specific Wagmi Config object, or null if creation fails or not RainbowKit.
313
- */
314
- public async getConfigForRainbowKit(
315
- currentAdapterUiKitConfig: UiKitConfiguration
316
- ): Promise<Config | null> {
317
- if (!this.initialized) {
318
- logger.error(
319
- LOG_SYSTEM,
320
- 'getConfigForRainbowKit called before implementation initialization.'
321
- );
322
- return null;
323
- }
324
- if (currentAdapterUiKitConfig?.kitName !== 'rainbowkit') {
325
- logger.warn(
326
- LOG_SYSTEM,
327
- 'getConfigForRainbowKit called, but kitName is not rainbowkit. Returning null.'
328
- );
329
- return null;
330
- }
331
- logger.info(
332
- LOG_SYSTEM,
333
- 'getConfigForRainbowKit: Kit is RainbowKit. Proceeding to create/get config. CurrentAdapterUiKitConfig:',
334
- currentAdapterUiKitConfig
335
- );
336
- const rainbowKitWagmiConfig = await getWagmiConfigForRainbowKit(
337
- currentAdapterUiKitConfig,
338
- defaultSupportedChains as WagmiConfigChains,
339
- viemChainIdToAppNetworkId,
340
- this.getRpcOverrideForRainbowKit.bind(this)
341
- );
342
- if (rainbowKitWagmiConfig) {
343
- logger.info(LOG_SYSTEM, 'Returning RainbowKit-specific Wagmi config for provider.');
344
- return rainbowKitWagmiConfig;
345
- }
346
- logger.warn(LOG_SYSTEM, 'RainbowKit specific Wagmi config creation failed.');
347
- return null;
348
- }
349
-
350
- /**
351
- * Determines and returns the WagmiConfig to be used by EvmUiKitManager during its configuration process.
352
- * If RainbowKit is specified in the passed uiKitConfig, it attempts to get its specific config.
353
- * Otherwise, it falls back to creating/returning a default instance config.
354
- * @param uiKitConfig - The fully resolved UiKitConfiguration that the manager is currently processing.
355
- * @returns A Promise resolving to the determined Wagmi Config object.
356
- */
357
- public async getActiveConfigForManager(uiKitConfig: UiKitConfiguration): Promise<Config> {
358
- if (!this.initialized) {
359
- logger.error(
360
- LOG_SYSTEM,
361
- 'getActiveConfigForManager called before initialization! Creating fallback.'
362
- );
363
- return createConfig({
364
- chains: [defaultSupportedChains[0]] as unknown as WagmiConfigChains,
365
- transports: { [defaultSupportedChains[0].id]: http() },
366
- });
367
- }
368
-
369
- if (uiKitConfig?.kitName === 'rainbowkit') {
370
- const rkConfig = await this.getConfigForRainbowKit(uiKitConfig);
371
- if (rkConfig) return rkConfig;
372
- logger.warn(
373
- LOG_SYSTEM,
374
- 'getActiveConfigForManager: RainbowKit config failed, falling back to default.'
375
- );
376
- }
377
-
378
- // Reuse existing default config if available, only create if needed
379
- // This ensures wallet connection state is preserved across network switches
380
- // Config is automatically invalidated when RPC settings change via setupRpcConfigListener()
381
- if (!this.defaultInstanceConfig) {
382
- this.defaultInstanceConfig = this.createDefaultConfig();
383
- }
384
- return this.defaultInstanceConfig;
385
- }
386
-
387
- /**
388
- * @deprecated Prefer using methods that rely on the externally set `activeWagmiConfig`
389
- * or methods that determine contextually appropriate config like `getActiveConfigForManager` (for manager use)
390
- * or ensure `activeWagmiConfig` is set before calling wagmi actions.
391
- * This method returns the internally cached default config or the active one if set.
392
- * @returns The current default or active Wagmi Config object.
393
- */
394
- public getConfig(): Config {
395
- logger.warn(
396
- LOG_SYSTEM,
397
- 'getConfig() is deprecated. Internal calls should use activeWagmiConfig if set, or ensure default is created.'
398
- );
399
- if (this.activeWagmiConfig) return this.activeWagmiConfig;
400
- if (!this.defaultInstanceConfig) {
401
- this.defaultInstanceConfig = this.createDefaultConfig();
402
- }
403
- return this.defaultInstanceConfig!;
404
- }
405
-
406
- /**
407
- * Gets the current wallet connection status (isConnected, address, chainId, etc.).
408
- * This is a synchronous operation and uses the `activeWagmiConfig` if set by `EvmUiKitManager`,
409
- * otherwise falls back to the default instance config (created on demand).
410
- * For UI reactivity to connection changes, `onWalletConnectionChange` or derived hooks are preferred.
411
- * @returns The current account status from Wagmi.
412
- */
413
- public getWalletConnectionStatus(): GetAccountReturnType {
414
- logger.debug(LOG_SYSTEM, 'getWalletConnectionStatus called.');
415
- const configToUse =
416
- this.activeWagmiConfig ||
417
- this.defaultInstanceConfig ||
418
- (this.defaultInstanceConfig = this.createDefaultConfig());
419
- if (!configToUse) {
420
- logger.error(LOG_SYSTEM, 'No config available for getWalletConnectionStatus!');
421
- // Return a valid GetAccountReturnType for a disconnected state
422
- return {
423
- isConnected: false,
424
- isConnecting: false,
425
- isDisconnected: true,
426
- isReconnecting: false,
427
- status: 'disconnected',
428
- address: undefined,
429
- addresses: undefined,
430
- chainId: undefined,
431
- chain: undefined,
432
- connector: undefined,
433
- };
434
- }
435
- return getAccount(configToUse);
436
- }
437
-
438
- /**
439
- * Subscribes to account and connection status changes from Wagmi.
440
- * The subscription is bound to the `activeWagmiConfig` if available at the time of call,
441
- * otherwise to the default instance config. If `activeWagmiConfig` changes later,
442
- * this specific subscription might become stale (see warning in `setActiveWagmiConfig`).
443
- * @param callback - Function to call when connection status changes.
444
- * @returns A function to unsubscribe from the changes.
445
- */
446
- public onWalletConnectionChange(
447
- callback: (status: GetAccountReturnType, prevStatus: GetAccountReturnType) => void
448
- ): () => void {
449
- if (!this.initialized) {
450
- logger.warn(LOG_SYSTEM, 'onWalletConnectionChange called before initialization. No-op.');
451
- return () => {};
452
- }
453
- if (this.unsubscribe) {
454
- this.unsubscribe();
455
- logger.debug(LOG_SYSTEM, 'Previous watchAccount unsubscribed.');
456
- }
457
- const configToUse =
458
- this.activeWagmiConfig ||
459
- this.defaultInstanceConfig ||
460
- (this.defaultInstanceConfig = this.createDefaultConfig());
461
- if (!configToUse) {
462
- logger.error(
463
- LOG_SYSTEM,
464
- 'No config available for onWalletConnectionChange! Subscription not set.'
40
+ export function createEvmWalletImplementation(
41
+ walletConnectProjectId?: string,
42
+ initialUiKitConfig?: UiKitConfiguration
43
+ ): CoreWagmiWalletImplementation {
44
+ const config: WagmiWalletConfig = {
45
+ chains: defaultSupportedChains,
46
+ networkConfigs: evmNetworks,
47
+ walletConnectProjectId,
48
+ initialUiKitConfig,
49
+ logSystem: 'WagmiWalletImplementation',
50
+ };
51
+
52
+ const instance = new CoreWagmiWalletImplementation(config);
53
+
54
+ // Inject the RainbowKit config function
55
+ instance.setRainbowKitConfigFn(
56
+ async (uiKitConfiguration, chains, chainIdToNetworkIdMap, getRpcOverride) => {
57
+ return getWagmiConfigForRainbowKit(
58
+ uiKitConfiguration,
59
+ chains as WagmiConfigChains,
60
+ chainIdToNetworkIdMap,
61
+ getRpcOverride
465
62
  );
466
- return () => {};
467
63
  }
468
- this.unsubscribe = watchAccount(configToUse, { onChange: callback });
469
- logger.info(
470
- LOG_SYSTEM,
471
- 'watchAccount subscription established/re-established using config:',
472
- configToUse === this.activeWagmiConfig ? 'activeExternal' : 'defaultInstance'
473
- );
474
- return this.unsubscribe;
475
- }
476
-
477
- // Methods that perform actions should use the most current activeWagmiConfig
478
- /**
479
- * Gets the Viem Wallet Client for the currently connected account and chain, using the active Wagmi config.
480
- * @returns A Promise resolving to the Viem WalletClient or null if not connected or config not active.
481
- */
482
- public async getWalletClient(): Promise<WalletClient | null> {
483
- if (!this.initialized || !this.activeWagmiConfig) {
484
- logger.warn(
485
- LOG_SYSTEM,
486
- 'getWalletClient: Not initialized or no activeWagmiConfig. Returning null.'
487
- );
488
- return null;
489
- }
490
- const accountStatus = getAccount(this.activeWagmiConfig);
491
- if (!accountStatus.isConnected || !accountStatus.chainId || !accountStatus.address) return null;
492
- return getWagmiWalletClient(this.activeWagmiConfig, {
493
- chainId: accountStatus.chainId,
494
- account: accountStatus.address,
495
- });
496
- }
497
-
498
- /**
499
- * Gets the Viem Public Client for the currently connected chain, using the active Wagmi config.
500
- * Note: Direct public client retrieval from WagmiConfig is complex in v2. This is a placeholder.
501
- * Prefer using Wagmi actions like readContract, simulateContract which use the public client internally.
502
- * @returns A Promise resolving to the Viem PublicClient or null.
503
- */
504
- public async getPublicClient(): Promise<PublicClient | null> {
505
- if (!this.initialized || !this.activeWagmiConfig) {
506
- logger.warn(
507
- LOG_SYSTEM,
508
- 'getPublicClient: Not initialized or no activeWagmiConfig. Returning null.'
509
- );
510
- return null;
511
- }
512
-
513
- const accountStatus = getAccount(this.activeWagmiConfig); // Get current chain from the active config
514
- const currentChainId = accountStatus.chainId;
515
-
516
- if (!currentChainId) {
517
- logger.warn(
518
- LOG_SYSTEM,
519
- 'getPublicClient: No connected chainId available from accountStatus. Returning null.'
520
- );
521
- return null;
522
- }
523
-
524
- try {
525
- // Use the getPublicClient action from wagmi/core
526
- // It requires the config and optionally a chainId. If no chainId, it uses the config's primary/first chain.
527
- // It's better to be explicit with the current chainId.
528
- const publicClient = getWagmiCorePublicClient(this.activeWagmiConfig, {
529
- chainId: currentChainId,
530
- });
531
- if (publicClient) {
532
- logger.info(
533
- LOG_SYSTEM,
534
- `getPublicClient: Successfully retrieved public client for chainId ${currentChainId}.`
535
- );
536
- return publicClient;
537
- }
538
- logger.warn(
539
- LOG_SYSTEM,
540
- `getPublicClient: getWagmiCorePublicClient returned undefined/null for chainId ${currentChainId}.`
541
- );
542
- return null;
543
- } catch (error) {
544
- logger.error(LOG_SYSTEM, 'Error getting public client from wagmi/core:', error);
545
- return null;
546
- }
547
- }
548
-
549
- /**
550
- * Gets the list of available wallet connectors from the active Wagmi config.
551
- * @returns A Promise resolving to an array of available connectors.
552
- */
553
- public async getAvailableConnectors(): Promise<Connector[]> {
554
- if (!this.initialized || !this.activeWagmiConfig) return [];
555
- return this.activeWagmiConfig.connectors.map((co) => ({ id: co.uid, name: co.name }));
556
- }
557
-
558
- /**
559
- * Initiates the connection process for a specific connector using the active Wagmi config.
560
- * @param connectorId - The ID of the connector to use.
561
- * @returns A Promise with connection result including address and chainId if successful.
562
- */
563
- public async connect(
564
- connectorId: string
565
- ): Promise<{ connected: boolean; address?: string; chainId?: number; error?: string }> {
566
- if (!this.initialized || !this.activeWagmiConfig)
567
- throw new Error('Wallet not initialized or no active config');
568
- const connectorToUse = this.activeWagmiConfig.connectors.find(
569
- (cn) => cn.id === connectorId || cn.uid === connectorId
570
- );
571
- if (!connectorToUse) throw new Error(`Connector ${connectorId} not found`);
572
- const res = await connect(this.activeWagmiConfig, { connector: connectorToUse });
573
- return { connected: true, address: res.accounts[0], chainId: res.chainId };
574
- }
575
-
576
- /**
577
- * Disconnects the currently connected wallet using the active Wagmi config.
578
- * @returns A Promise with disconnection result.
579
- */
580
- public async disconnect(): Promise<{ disconnected: boolean; error?: string }> {
581
- if (!this.initialized || !this.activeWagmiConfig)
582
- return { disconnected: false, error: 'Wallet not initialized or no active config' };
583
- await disconnect(this.activeWagmiConfig);
584
- return { disconnected: true };
585
- }
586
-
587
- /**
588
- * Prompts the user to switch to the specified network using the active Wagmi config.
589
- * @param chainId - The target chain ID to switch to.
590
- * @returns A Promise that resolves if the switch is successful, or rejects with an error.
591
- */
592
- public async switchNetwork(chainId: number): Promise<void> {
593
- if (!this.initialized || !this.activeWagmiConfig)
594
- throw new Error('Wallet not initialized or no active config');
595
- await switchChain(this.activeWagmiConfig, { chainId });
596
- }
64
+ );
597
65
 
598
- // ... (rest of class, ensure all wagmi/core actions use this.activeWagmiConfig if available and appropriate)
66
+ return instance;
599
67
  }
@@ -1,9 +1,8 @@
1
1
  // Barrel file for wallet module
2
- export * from './components';
3
- export * from './context';
2
+ export { EvmWalletUiRoot } from './components/EvmWalletUiRoot';
4
3
  export * from './hooks';
5
4
  export * from './types';
6
5
  export * from './utils/index';
7
6
  // Export specific functions from utils.ts to avoid conflicts
8
- export { getResolvedWalletComponents, resolveAndInitializeKitConfig } from './utils';
7
+ export { getResolvedWalletComponents } from './utils';
9
8
  // Keep wagmi-implementation internal
@@ -1,9 +1,8 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
 
3
+ import { generateRainbowKitExportables } from '@openzeppelin/ui-builder-adapter-evm-core';
3
4
  import type { UiKitConfiguration } from '@openzeppelin/ui-types';
4
5
 
5
- import { generateRainbowKitExportables } from '../export-service';
6
-
7
6
  describe('RainbowKit Export Service', () => {
8
7
  describe('generateRainbowKitExportables', () => {
9
8
  it('should generate a valid RainbowKit config file with all properties', () => {