@openzeppelin/ui-builder-adapter-evm 0.12.0 → 0.14.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.
@@ -1,10 +1,10 @@
1
1
  import { createPublicClient, http, isAddress, type Chain, type PublicClient } from 'viem';
2
2
 
3
3
  import type { ContractSchema, FunctionParameter } from '@openzeppelin/ui-builder-types';
4
- import { logger, userRpcConfigService } from '@openzeppelin/ui-builder-utils';
4
+ import { logger } from '@openzeppelin/ui-builder-utils';
5
5
 
6
6
  import { createAbiFunctionItem } from '../abi';
7
- import { resolveRpcUrl } from '../configuration';
7
+ import { getUserRpcUrl, resolveRpcUrl } from '../configuration';
8
8
  import { parseEvmInput } from '../transform';
9
9
  import type { TypedEvmNetworkConfig } from '../types';
10
10
  import type { WagmiWalletImplementation } from '../wallet/implementation/wagmi-implementation';
@@ -19,10 +19,8 @@ async function getPublicClientForQuery(
19
19
  walletImplementation: WagmiWalletImplementation,
20
20
  networkConfig: TypedEvmNetworkConfig
21
21
  ): Promise<PublicClient> {
22
- // First check if there's a custom RPC configuration
23
- const customRpcConfig = userRpcConfigService.getUserRpcConfig(networkConfig.id);
24
-
25
- if (customRpcConfig) {
22
+ // First check if there's a custom RPC configuration via generic service
23
+ if (getUserRpcUrl(networkConfig.id)) {
26
24
  // Always create a new client with custom RPC when configured
27
25
  const resolvedRpc = resolveRpcUrl(networkConfig);
28
26
  return createPublicClientWithRpc(networkConfig, resolvedRpc);
@@ -0,0 +1,68 @@
1
+ /**
2
+ * EVM Adapter: Vite Configuration Export
3
+ *
4
+ * This module exports Vite configuration fragments for the EVM adapter.
5
+ * Currently minimal, but provides a consistent interface for adapter-specific
6
+ * build requirements.
7
+ *
8
+ * USAGE:
9
+ * 1. In the main builder app: Import and merge into packages/builder/vite.config.ts
10
+ * 2. In exported apps: The export system injects these configs when EVM is used
11
+ *
12
+ * See: docs/ADAPTER_ARCHITECTURE.md § "Build-Time Requirements"
13
+ */
14
+
15
+ import type { UserConfig } from 'vite';
16
+
17
+ /**
18
+ * Returns the Vite configuration required for EVM adapter compatibility
19
+ *
20
+ * @returns Vite configuration object to be merged with your main vite.config
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // vite.config.ts
25
+ * import { getEvmViteConfig } from '@openzeppelin/ui-builder-adapter-evm/vite-config';
26
+ *
27
+ * export default defineConfig(({ mode }) => {
28
+ * const evmConfig = getEvmViteConfig();
29
+ *
30
+ * return {
31
+ * plugins: [
32
+ * react(),
33
+ * ...evmConfig.plugins,
34
+ * ],
35
+ * resolve: {
36
+ * dedupe: [
37
+ * ...evmConfig.resolve.dedupe,
38
+ * ],
39
+ * },
40
+ * };
41
+ * });
42
+ * ```
43
+ */
44
+ export function getEvmViteConfig(): UserConfig {
45
+ return {
46
+ // Currently no EVM-specific plugins required
47
+ plugins: [],
48
+
49
+ resolve: {
50
+ // Module Deduplication
51
+ // Ensure singleton instances of shared dependencies
52
+ dedupe: [
53
+ // EVM-specific dependencies that may need deduplication
54
+ 'viem',
55
+ 'wagmi',
56
+ '@wagmi/core',
57
+ ],
58
+ },
59
+
60
+ optimizeDeps: {
61
+ // Force Pre-Bundling (CommonJS → ESM conversion)
62
+ // Include wagmi and @wagmi/core to ensure they're properly resolved
63
+ // when the EVM adapter is dynamically imported in production builds
64
+ include: ['wagmi', '@wagmi/core', 'viem', '@tanstack/react-query'],
65
+ exclude: [],
66
+ },
67
+ };
68
+ }
@@ -23,6 +23,7 @@ import { http, PublicClient, WalletClient, type Chain } from 'viem';
23
23
  import type { Connector, UiKitConfiguration } from '@openzeppelin/ui-builder-types';
24
24
  import { appConfigService, logger } from '@openzeppelin/ui-builder-utils';
25
25
 
26
+ import { getUserRpcUrl } from '../../configuration/rpc';
26
27
  import { evmNetworks } from '../../networks';
27
28
  import { getWagmiConfigForRainbowKit } from '../rainbowkit';
28
29
  import { type WagmiConfigChains } from '../types';
@@ -176,16 +177,20 @@ export class WagmiWalletImplementation {
176
177
  let rpcUrlToUse: string | undefined = chainDefinition.rpcUrls.default?.http?.[0];
177
178
  const appNetworkIdString = viemChainIdToAppNetworkId[chainDefinition.id];
178
179
  if (appNetworkIdString) {
179
- const rpcOverrideSetting = appConfigService.getRpcEndpointOverride(appNetworkIdString);
180
- let httpRpcOverride: string | undefined;
181
- if (typeof rpcOverrideSetting === 'string') {
182
- httpRpcOverride = rpcOverrideSetting;
183
- } else if (typeof rpcOverrideSetting === 'object') {
184
- // Handle both RpcEndpointConfig and UserRpcProviderConfig
185
- if ('http' in rpcOverrideSetting && rpcOverrideSetting.http) {
186
- httpRpcOverride = rpcOverrideSetting.http;
187
- } else if ('url' in rpcOverrideSetting && rpcOverrideSetting.url) {
188
- httpRpcOverride = rpcOverrideSetting.url;
180
+ // Prefer user-configured RPC from generic service
181
+ let httpRpcOverride: string | undefined = getUserRpcUrl(appNetworkIdString);
182
+ // Fallback to AppConfigService override if no user config
183
+ if (!httpRpcOverride) {
184
+ const rpcOverrideSetting = appConfigService.getRpcEndpointOverride(appNetworkIdString);
185
+ if (typeof rpcOverrideSetting === 'string') {
186
+ httpRpcOverride = rpcOverrideSetting;
187
+ } else if (typeof rpcOverrideSetting === 'object') {
188
+ // Handle both RpcEndpointConfig and UserRpcProviderConfig
189
+ if ('http' in rpcOverrideSetting && rpcOverrideSetting.http) {
190
+ httpRpcOverride = rpcOverrideSetting.http;
191
+ } else if ('url' in rpcOverrideSetting && rpcOverrideSetting.url) {
192
+ httpRpcOverride = rpcOverrideSetting.url;
193
+ }
189
194
  }
190
195
  }
191
196
  if (httpRpcOverride) {
@@ -227,6 +232,12 @@ export class WagmiWalletImplementation {
227
232
  private getRpcOverrideForRainbowKit(
228
233
  networkId: string
229
234
  ): string | { http?: string; ws?: string } | undefined {
235
+ // Prefer user-configured RPC from generic service first
236
+ const userRpcUrl = getUserRpcUrl(networkId);
237
+ if (userRpcUrl) {
238
+ return { http: userRpcUrl };
239
+ }
240
+
230
241
  const rpcOverrideSetting = appConfigService.getRpcEndpointOverride(networkId);
231
242
 
232
243
  if (typeof rpcOverrideSetting === 'string') {
@@ -322,9 +333,8 @@ export class WagmiWalletImplementation {
322
333
  );
323
334
  }
324
335
 
325
- if (!this.defaultInstanceConfig) {
326
- this.defaultInstanceConfig = this.createDefaultConfig();
327
- }
336
+ // Always rebuild default config to reflect latest RPC overrides/user settings
337
+ this.defaultInstanceConfig = this.createDefaultConfig();
328
338
  return this.defaultInstanceConfig;
329
339
  }
330
340
 
@@ -6,39 +6,6 @@ import { logger } from '@openzeppelin/ui-builder-utils';
6
6
 
7
7
  import { type WagmiConfigChains } from '../types';
8
8
 
9
- // Cache to prevent duplicate config creation and WalletConnect double initialization
10
- const cacheInstanceId = Math.random().toString(36).substring(7);
11
- const configCache = new Map<string, Config>();
12
- logger.debug('rainbowkit/config-service', 'NEW configCache INSTANCE CREATED', cacheInstanceId);
13
-
14
- /**
15
- * Creates a cache key from the configuration to prevent duplicate config creation
16
- */
17
- function createConfigCacheKey(
18
- userFullNativeConfig: Record<string, unknown> | undefined | null,
19
- chains: readonly Chain[]
20
- ): string {
21
- const wagmiParamsContent = userFullNativeConfig?.wagmiParams;
22
- const chainIds = chains.map((c) => c.id).sort();
23
- const keyObject = {
24
- wagmiParams: wagmiParamsContent,
25
- chainIds: chainIds,
26
- };
27
- const configHash = JSON.stringify(keyObject);
28
- logger.debug(
29
- 'rainbowkit/config-service:createConfigCacheKey',
30
- 'Key generation input - userFullNativeConfig.wagmiParams:',
31
- wagmiParamsContent,
32
- 'Key generation input - chainIds:',
33
- chainIds,
34
- 'Generated Key Object for stringify:',
35
- keyObject,
36
- 'Generated Hash:',
37
- configHash
38
- );
39
- return configHash;
40
- }
41
-
42
9
  /**
43
10
  * Creates a Wagmi configuration for RainbowKit using getDefaultConfig
44
11
  *
@@ -58,39 +25,6 @@ export async function createRainbowKitWagmiConfig(
58
25
  getRpcEndpointOverride: (networkId: string) => string | { http?: string; ws?: string } | undefined
59
26
  ): Promise<Config | null> {
60
27
  try {
61
- const cacheKey = createConfigCacheKey(userFullNativeConfig, chains);
62
- logger.info(
63
- 'rainbowkit/config-service:createRainbowKitWagmiConfig',
64
- 'Attempting to get/create config. Cache Key:',
65
- cacheKey,
66
- 'Using cache instance ID:',
67
- cacheInstanceId
68
- );
69
-
70
- const cachedConfig = configCache.get(cacheKey);
71
-
72
- if (cachedConfig) {
73
- logger.info(
74
- 'rainbowkit/config-service:createRainbowKitWagmiConfig',
75
- 'CACHE HIT. Returning cached RainbowKit Wagmi config.',
76
- {
77
- cacheKey,
78
- cacheInstanceId,
79
- cachedConfigObjectId:
80
- typeof cachedConfig?.storage === 'object' && cachedConfig.storage !== null
81
- ? 'WagmiStorageObject'
82
- : String(cachedConfig?.storage),
83
- }
84
- );
85
- return cachedConfig;
86
- } else {
87
- logger.warn(
88
- 'rainbowkit/config-service:createRainbowKitWagmiConfig',
89
- 'CACHE MISS. Proceeding to create new RainbowKit Wagmi config.',
90
- { cacheKey, cacheSize: configCache.size, cacheInstanceId }
91
- );
92
- }
93
-
94
28
  const { getDefaultConfig } = await import('@rainbow-me/rainbowkit');
95
29
  if (!getDefaultConfig) {
96
30
  logger.error(
@@ -139,11 +73,12 @@ export async function createRainbowKitWagmiConfig(
139
73
  const rpcOverrideSetting = getRpcEndpointOverride(appNetworkIdString);
140
74
  let httpRpcOverride: string | undefined;
141
75
 
76
+ // Extract HTTP RPC URL from override setting
142
77
  if (typeof rpcOverrideSetting === 'string') {
143
78
  httpRpcOverride = rpcOverrideSetting;
144
- } else if (typeof rpcOverrideSetting === 'object') {
79
+ } else if (typeof rpcOverrideSetting === 'object' && rpcOverrideSetting) {
145
80
  // Handle both RpcEndpointConfig and UserRpcProviderConfig
146
- if (rpcOverrideSetting?.http) {
81
+ if ('http' in rpcOverrideSetting && rpcOverrideSetting.http) {
147
82
  httpRpcOverride = rpcOverrideSetting.http;
148
83
  } else if ('url' in rpcOverrideSetting && rpcOverrideSetting.url) {
149
84
  // Handle UserRpcProviderConfig
@@ -182,17 +117,6 @@ export async function createRainbowKitWagmiConfig(
182
117
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
183
118
  const config = getDefaultConfig(finalConfigOptions as any);
184
119
 
185
- configCache.set(cacheKey, config);
186
- logger.info(
187
- 'rainbowkit/config-service:createRainbowKitWagmiConfig',
188
- 'New config created and cached. Cache Size now:',
189
- configCache.size,
190
- {
191
- cacheKey,
192
- cacheInstanceId,
193
- }
194
- );
195
-
196
120
  logger.info(
197
121
  'rainbowkit/config-service',
198
122
  'Successfully created RainbowKit Wagmi config object.',