@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,140 +0,0 @@
1
- import React, { useEffect, useState } from 'react';
2
-
3
- import {
4
- Button,
5
- Dialog,
6
- DialogContent,
7
- DialogDescription,
8
- DialogHeader,
9
- DialogTitle,
10
- } from '@openzeppelin/ui-components';
11
- import { useDerivedAccountStatus, useDerivedConnectStatus } from '@openzeppelin/ui-react';
12
- import type { Connector } from '@openzeppelin/ui-types';
13
-
14
- import { isConfigEnabled, useUiKitConfig } from '../../hooks/useUiKitConfig';
15
- import { SafeWagmiComponent } from '../../utils/SafeWagmiComponent';
16
-
17
- /**
18
- * Dialog component for selecting a wallet connector
19
- */
20
- interface ConnectorDialogProps {
21
- open: boolean;
22
- onOpenChange: (open: boolean) => void;
23
- }
24
-
25
- export const ConnectorDialog: React.FC<ConnectorDialogProps> = ({ open, onOpenChange }) => {
26
- // Prepare fallback dialog content
27
- const unavailableContent = (
28
- <Dialog open={open} onOpenChange={onOpenChange}>
29
- <DialogContent className="sm:max-w-[425px]">
30
- <DialogHeader>
31
- <DialogTitle>Wallet Connection Unavailable</DialogTitle>
32
- <DialogDescription>
33
- The wallet connection system is not properly initialized.
34
- </DialogDescription>
35
- </DialogHeader>
36
- </DialogContent>
37
- </Dialog>
38
- );
39
-
40
- // Only render wagmi-dependent part when provider is initialized
41
- return (
42
- <SafeWagmiComponent fallback={unavailableContent}>
43
- <ConnectorDialogContent open={open} onOpenChange={onOpenChange} />
44
- </SafeWagmiComponent>
45
- );
46
- };
47
-
48
- // Inner content that uses wagmi hooks
49
- const ConnectorDialogContent: React.FC<ConnectorDialogProps> = ({ open, onOpenChange }) => {
50
- const {
51
- connect,
52
- connectors,
53
- error: connectError,
54
- isConnecting,
55
- pendingConnector,
56
- } = useDerivedConnectStatus();
57
- const { isConnected } = useDerivedAccountStatus();
58
- const [connectingId, setConnectingId] = useState<string | null>(null);
59
-
60
- // Get the complete config to log it
61
- const fullConfig = useUiKitConfig();
62
- const showInjectedConnector = isConfigEnabled('showInjectedConnector');
63
-
64
- // Log the configuration to debug
65
- useEffect(() => {}, [fullConfig, showInjectedConnector, isConnecting, pendingConnector]);
66
-
67
- // Track connection attempts for dialog closure
68
- useEffect(() => {
69
- // If we're connected and there was a connection attempt, close the dialog
70
- if (isConnected && connectingId) {
71
- onOpenChange(false);
72
- setConnectingId(null);
73
- }
74
- }, [isConnected, connectingId, onOpenChange]);
75
-
76
- // If connect function itself is not available (e.g., adapter doesn't provide useConnect facade hook)
77
- if (!connect) {
78
- return (
79
- <Dialog open={open} onOpenChange={onOpenChange}>
80
- <DialogContent className="sm:max-w-[425px]">
81
- <DialogHeader>
82
- <DialogTitle>Error</DialogTitle>
83
- </DialogHeader>
84
- <p>Wallet connection function is not available.</p>
85
- </DialogContent>
86
- </Dialog>
87
- );
88
- }
89
-
90
- const handleConnectorSelect = (selectedConnector: Connector) => {
91
- setConnectingId(selectedConnector.id);
92
- connect({ connector: selectedConnector });
93
- };
94
-
95
- // Filter out the injected connector if showInjectedConnector is false
96
- const filteredConnectors = connectors.filter((connector: Connector) => {
97
- const isInjected = connector.id === 'injected';
98
- return !(isInjected && !showInjectedConnector);
99
- });
100
-
101
- return (
102
- <Dialog open={open} onOpenChange={onOpenChange}>
103
- <DialogContent className="sm:max-w-[425px]">
104
- <DialogHeader>
105
- <DialogTitle>Connect Wallet</DialogTitle>
106
- <DialogDescription>
107
- Select a wallet provider to connect with this application.
108
- </DialogDescription>
109
- </DialogHeader>
110
-
111
- <div className="grid gap-4 py-4">
112
- {filteredConnectors.length === 0 ? (
113
- <p className="text-center text-muted-foreground">No wallet connectors available.</p>
114
- ) : (
115
- filteredConnectors.map((connector: Connector) => (
116
- <Button
117
- key={connector.id}
118
- onClick={() => handleConnectorSelect(connector)}
119
- disabled={isConnecting && connectingId === connector.id}
120
- variant="outline"
121
- className="flex justify-between items-center w-full py-6"
122
- >
123
- <span>{connector.name}</span>
124
- {isConnecting && connectingId === connector.id && (
125
- <span className="ml-2 text-xs">Connecting...</span>
126
- )}
127
- </Button>
128
- ))
129
- )}
130
- </div>
131
-
132
- {connectError && (
133
- <p className="text-sm text-red-500 mt-1">
134
- {connectError.message || 'Error connecting wallet'}
135
- </p>
136
- )}
137
- </DialogContent>
138
- </Dialog>
139
- );
140
- };
@@ -1,4 +0,0 @@
1
- // Export all wallet UI components
2
- export { CustomConnectButton } from './connect/ConnectButton';
3
- export { CustomAccountDisplay } from './account/AccountDisplay';
4
- export { CustomNetworkSwitcher } from './network/NetworkSwitcher';
@@ -1,90 +0,0 @@
1
- import { Loader2 } from 'lucide-react';
2
- import type { Chain } from 'viem';
3
- import React from 'react';
4
-
5
- import {
6
- Select,
7
- SelectContent,
8
- SelectItem,
9
- SelectTrigger,
10
- SelectValue,
11
- } from '@openzeppelin/ui-components';
12
- import {
13
- useDerivedAccountStatus,
14
- useDerivedChainInfo,
15
- useDerivedSwitchChainStatus,
16
- } from '@openzeppelin/ui-react';
17
- import type { BaseComponentProps } from '@openzeppelin/ui-types';
18
- import { cn } from '@openzeppelin/ui-utils';
19
-
20
- import { SafeWagmiComponent } from '../../utils/SafeWagmiComponent';
21
-
22
- /**
23
- * A component that displays the current network and allows switching to other networks.
24
- * Uses the chainId and switchChain hooks from wagmi.
25
- */
26
- export const CustomNetworkSwitcher: React.FC<BaseComponentProps> = ({ className }) => {
27
- // Use the SafeWagmiComponent with null fallback
28
- return (
29
- <SafeWagmiComponent fallback={null}>
30
- <NetworkSwitcherContent className={className} />
31
- </SafeWagmiComponent>
32
- );
33
- };
34
-
35
- // Inner component that uses wagmi hooks
36
- const NetworkSwitcherContent: React.FC<{ className?: string }> = ({ className }) => {
37
- const { isConnected } = useDerivedAccountStatus();
38
- const { currentChainId, availableChains: unknownChains } = useDerivedChainInfo();
39
- const { switchChain, isSwitching: isPending, error } = useDerivedSwitchChainStatus();
40
-
41
- // Cast to Chain[] for use within this EVM-specific component
42
- const typedAvailableChains = unknownChains as Chain[];
43
-
44
- if (!isConnected || !switchChain || typedAvailableChains.length === 0) {
45
- return null;
46
- }
47
-
48
- const handleNetworkChange = (chainId: number) => {
49
- if (chainId !== currentChainId) {
50
- switchChain({ chainId });
51
- }
52
- };
53
-
54
- const currentChain = typedAvailableChains.find((chain) => chain.id === currentChainId);
55
- const currentChainName = currentChain?.name || 'Network';
56
-
57
- return (
58
- <div className={cn('flex items-center', className)}>
59
- <Select
60
- value={currentChainId?.toString() ?? ''}
61
- onValueChange={(value: string) => handleNetworkChange(Number(value))}
62
- disabled={isPending || typedAvailableChains.length === 0}
63
- >
64
- <SelectTrigger className="h-8 text-xs px-2 min-w-[90px] max-w-[120px]">
65
- <SelectValue placeholder="Network">{currentChainName}</SelectValue>
66
- </SelectTrigger>
67
- <SelectContent
68
- position="popper"
69
- sideOffset={5}
70
- align="start"
71
- className="w-auto min-w-[160px] max-h-[300px]"
72
- >
73
- {typedAvailableChains.map((chain) => (
74
- <SelectItem key={chain.id} value={chain.id.toString()} className="text-xs py-1.5">
75
- {chain.name}
76
- </SelectItem>
77
- ))}
78
- </SelectContent>
79
- </Select>
80
-
81
- {isPending && (
82
- <span className="text-xs text-muted-foreground ml-2">
83
- <Loader2 className="h-3 w-3 animate-spin" />
84
- </span>
85
- )}
86
-
87
- {error && <span className="text-xs text-red-500 ml-2">!</span>}
88
- </div>
89
- );
90
- };
@@ -1 +0,0 @@
1
- export * from './wagmi-context';
@@ -1,7 +0,0 @@
1
- import { createContext } from 'react';
2
-
3
- /**
4
- * Context to track Wagmi provider initialization status
5
- * Used by components to safely render when the provider is ready
6
- */
7
- export const WagmiProviderInitializedContext = createContext<boolean>(false);
@@ -1,11 +0,0 @@
1
- import { useContext } from 'react';
2
-
3
- import { WagmiProviderInitializedContext } from '../context/wagmi-context';
4
-
5
- /**
6
- * Hook to check if WagmiProvider is ready
7
- * @returns boolean indicating if the provider is initialized
8
- */
9
- export const useIsWagmiProviderInitialized = (): boolean => {
10
- return useContext(WagmiProviderInitializedContext);
11
- };
@@ -1,56 +0,0 @@
1
- import { UiKitConfiguration } from '@openzeppelin/ui-types';
2
-
3
- /**
4
- * Generates the content for a `rainbowkit.config.ts` file for an exported project.
5
- * It merges the user-provided configuration with the necessary boilerplate to ensure
6
- * the config is valid for RainbowKit's `getDefaultConfig`.
7
- *
8
- * @param userConfig - The user-provided configuration from the builder app.
9
- * @returns A string containing the formatted TypeScript code for the config file.
10
- */
11
- export function generateRainbowKitConfigFile(userConfig: UiKitConfiguration['kitConfig']): string {
12
- const config = (userConfig || {}) as Record<string, unknown>;
13
- const appName = (config.appName as string) || 'My RainbowKit App';
14
- const learnMoreUrl = (config.learnMoreUrl as string) || 'https://openzeppelin.com';
15
- // We provide a default projectId as it's required by RainbowKit for WalletConnect.
16
- const projectId = (config.projectId as string) || 'YOUR_PROJECT_ID';
17
-
18
- // Build the appInfo part conditionally
19
- const appInfoLines = [`appName: '${appName}'`];
20
- if (learnMoreUrl) {
21
- appInfoLines.push(`learnMoreUrl: '${learnMoreUrl}'`);
22
- }
23
- const appInfoContent = appInfoLines.join(',\n ');
24
-
25
- const fileContent = `// RainbowKit configuration for your exported application
26
- // This file is used ONLY in the exported app, not in the builder app preview
27
-
28
- // Uncomment imports as needed:
29
- // import { darkTheme, lightTheme } from '@rainbow-me/rainbowkit';
30
-
31
- const rainbowKitAppConfig = {
32
- wagmiParams: {
33
- appName: '${appName}',
34
- projectId: '${projectId}', // Get yours at https://cloud.walletconnect.com
35
-
36
- // Additional options:
37
- // ssr: true,
38
- // wallets: [...],
39
- },
40
- providerProps: {
41
- appInfo: {
42
- ${appInfoContent}
43
- },
44
-
45
- // UI customization - all features work in exported apps:
46
- // theme: darkTheme(),
47
- // modalSize: 'compact',
48
- // showRecentTransactions: true,
49
- // coolMode: true,
50
- },
51
- };
52
-
53
- export default rainbowKitAppConfig;`;
54
-
55
- return fileContent;
56
- }
@@ -1,169 +0,0 @@
1
- import { Config, http } from '@wagmi/core';
2
- import { type Chain } from 'viem';
3
-
4
- import type { UiKitConfiguration } from '@openzeppelin/ui-types';
5
- import { logger } from '@openzeppelin/ui-utils';
6
-
7
- import { type WagmiConfigChains } from '../types';
8
-
9
- /**
10
- * Creates a Wagmi configuration for RainbowKit using getDefaultConfig
11
- *
12
- * @param userFullNativeConfig The full native configuration object. This object IS the result of merging
13
- * AppConfigService settings, user's native rainbowkit.config.ts, and programmatic overrides.
14
- * It is expected to contain a `wagmiParams` object for RainbowKit's getDefaultConfig
15
- * and potentially a `providerProps` object for RainbowKitProvider.
16
- * @param chains Array of viem Chain objects - will be safely cast to wagmi's expected chain type
17
- * @param chainIdToNetworkIdMap Mapping of chain IDs to network IDs for RPC override lookups
18
- * @param getRpcEndpointOverride Function to get RPC endpoint overrides
19
- * @returns Wagmi configuration for RainbowKit or null if creation fails
20
- */
21
- export async function createRainbowKitWagmiConfig(
22
- userFullNativeConfig: Record<string, unknown> | undefined | null, // This is the fully resolved kitConfig
23
- chains: readonly Chain[],
24
- chainIdToNetworkIdMap: Record<number, string>,
25
- getRpcEndpointOverride: (networkId: string) => string | { http?: string; ws?: string } | undefined
26
- ): Promise<Config | null> {
27
- try {
28
- const { getDefaultConfig } = await import('@rainbow-me/rainbowkit');
29
- if (!getDefaultConfig) {
30
- logger.error(
31
- 'rainbowkit/config-service',
32
- 'Failed to import getDefaultConfig from RainbowKit'
33
- );
34
- return null;
35
- }
36
-
37
- // userFullNativeConfig *is* the kitConfig here. Its wagmiParams are what we need.
38
- const wagmiParams = userFullNativeConfig?.wagmiParams as Record<string, unknown> | undefined;
39
-
40
- if (!wagmiParams) {
41
- logger.warn(
42
- 'rainbowkit/config-service',
43
- 'Resolved kitConfig does not contain a `wagmiParams` object. Cannot create RainbowKit Wagmi config.'
44
- );
45
- return null;
46
- }
47
-
48
- // Ensure essential appName and projectId are present in user's wagmiParams
49
- if (typeof wagmiParams.appName !== 'string' || !wagmiParams.appName) {
50
- logger.warn(
51
- 'rainbowkit/config-service',
52
- 'kitConfig.wagmiParams is missing or has invalid `appName`.'
53
- );
54
- return null;
55
- }
56
- if (typeof wagmiParams.projectId !== 'string' || !wagmiParams.projectId) {
57
- logger.warn(
58
- 'rainbowkit/config-service',
59
- 'kitConfig.wagmiParams is missing or has invalid `projectId`.'
60
- );
61
- return null;
62
- }
63
-
64
- // Build transport configuration with RPC overrides as needed.
65
- // This iterates over the adapter-determined chains and creates a transport
66
- // for each, applying any RPC overrides specified via AppConfigService.
67
- const transportsConfig = chains.reduce(
68
- (acc, chainDefinition) => {
69
- let rpcUrlToUse: string | undefined = chainDefinition.rpcUrls.default?.http?.[0];
70
- const appNetworkIdString = chainIdToNetworkIdMap[chainDefinition.id];
71
-
72
- if (appNetworkIdString) {
73
- const rpcOverrideSetting = getRpcEndpointOverride(appNetworkIdString);
74
- let httpRpcOverride: string | undefined;
75
-
76
- // Extract HTTP RPC URL from override setting
77
- if (typeof rpcOverrideSetting === 'string') {
78
- httpRpcOverride = rpcOverrideSetting;
79
- } else if (typeof rpcOverrideSetting === 'object' && rpcOverrideSetting) {
80
- // Handle both RpcEndpointConfig and UserRpcProviderConfig
81
- if ('http' in rpcOverrideSetting && rpcOverrideSetting.http) {
82
- httpRpcOverride = rpcOverrideSetting.http;
83
- } else if ('url' in rpcOverrideSetting && rpcOverrideSetting.url) {
84
- // Handle UserRpcProviderConfig
85
- httpRpcOverride = rpcOverrideSetting.url as string;
86
- }
87
- }
88
-
89
- if (httpRpcOverride) {
90
- logger.info(
91
- 'rainbowkit/config-service',
92
- `Using overridden RPC for chain ${chainDefinition.name}: ${httpRpcOverride}`
93
- );
94
- rpcUrlToUse = httpRpcOverride;
95
- }
96
- }
97
-
98
- acc[chainDefinition.id] = http(rpcUrlToUse);
99
- return acc;
100
- },
101
- {} as Record<number, ReturnType<typeof http>>
102
- );
103
-
104
- // Spread all user-provided wagmiParams, then override chains and transports
105
- const finalConfigOptions = {
106
- ...wagmiParams, // User's native params (appName, projectId, wallets, ssr, etc.)
107
- chains: chains as WagmiConfigChains, // Adapter controls this
108
- transports: transportsConfig, // Adapter controls this
109
- };
110
-
111
- // The `wallets` property from user config is of type `unknown` on our side if accessed directly from wagmiParams.
112
- // RainbowKit's `getDefaultConfig` expects a specific `WalletList` type for `wallets`.
113
- // By spreading `wagmiParams`, we pass whatever structure the user provided.
114
- // We use `eslint-disable-next-line @typescript-eslint/no-explicit-any` here to pass through
115
- // the user-provided structure directly, relying on RainbowKit to perform its own validation or type checking internally.
116
- // This aligns with our principle of not mimicking complex third-party types for pass-through configuration.
117
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
- const config = getDefaultConfig(finalConfigOptions as any);
119
-
120
- logger.info(
121
- 'rainbowkit/config-service',
122
- 'Successfully created RainbowKit Wagmi config object.',
123
- config
124
- );
125
- return config;
126
- } catch (error) {
127
- logger.error('rainbowkit/config-service', 'Error creating RainbowKit Wagmi config:', error);
128
- return null;
129
- }
130
- }
131
-
132
- /**
133
- * Gets the Wagmi configuration for RainbowKit based on the global UI kit settings.
134
- * This function is intended to be called by WagmiWalletImplementation.
135
- *
136
- * @param uiKitConfiguration The UI kit configuration object from EvmUiKitManager (contains the resolved kitConfig).
137
- * @param chains Array of viem Chain objects to use with RainbowKit
138
- * @param chainIdToNetworkIdMap Mapping of chain IDs to network IDs for RPC override lookups
139
- * @param getRpcEndpointOverride Function to get RPC endpoint overrides
140
- * @returns The wagmi Config object or null if invalid or not RainbowKit
141
- */
142
- export async function getWagmiConfigForRainbowKit(
143
- uiKitConfiguration: UiKitConfiguration | undefined,
144
- chains: readonly Chain[],
145
- chainIdToNetworkIdMap: Record<number, string>,
146
- getRpcEndpointOverride: (networkId: string) => string | { http?: string; ws?: string } | undefined
147
- ): Promise<Config | null> {
148
- if (
149
- !uiKitConfiguration ||
150
- uiKitConfiguration.kitName !== 'rainbowkit' ||
151
- !uiKitConfiguration.kitConfig // kitConfig is the fully resolved config here
152
- ) {
153
- logger.debug(
154
- 'rainbowkit/config-service',
155
- 'Not configured for RainbowKit or kitConfig (resolved native + programmatic) is missing.'
156
- );
157
- return null;
158
- }
159
-
160
- // userFullNativeConfig for createRainbowKitWagmiConfig IS uiKitConfiguration.kitConfig
161
- const resolvedKitConfig = uiKitConfiguration.kitConfig as Record<string, unknown>;
162
-
163
- return createRainbowKitWagmiConfig(
164
- resolvedKitConfig, // Pass the resolved kitConfig
165
- chains,
166
- chainIdToNetworkIdMap,
167
- getRpcEndpointOverride
168
- );
169
- }
@@ -1,18 +0,0 @@
1
- import type { UiKitConfiguration } from '@openzeppelin/ui-types';
2
-
3
- import { generateRainbowKitConfigFile } from './config-generator';
4
-
5
- /**
6
- * Generates the specific configuration file for RainbowKit during project export.
7
- *
8
- * @param uiKitConfig The full UI kit configuration object from the builder.
9
- * @returns A record containing the file path and its generated content.
10
- */
11
- export function generateRainbowKitExportables(
12
- uiKitConfig: UiKitConfiguration
13
- ): Record<string, string> {
14
- const filePath = 'src/config/wallet/rainbowkit.config.ts';
15
- const content = uiKitConfig.customCode || generateRainbowKitConfigFile(uiKitConfig.kitConfig);
16
-
17
- return { [filePath]: content };
18
- }
@@ -1,74 +0,0 @@
1
- import type React from 'react';
2
-
3
- import { logger } from '@openzeppelin/ui-utils';
4
-
5
- export interface RainbowKitAssets {
6
- ProviderComponent: React.ComponentType<React.PropsWithChildren<unknown>> | null;
7
- cssLoaded: boolean;
8
- }
9
-
10
- let loadedAssets: RainbowKitAssets | null = null;
11
-
12
- // Promises to ensure assets are loaded only once
13
- let providerPromise: Promise<React.ComponentType<React.PropsWithChildren<unknown>> | null> | null =
14
- null;
15
- let cssPromise: Promise<boolean> | null = null;
16
-
17
- /**
18
- * Ensures RainbowKit provider component and CSS are loaded.
19
- * Loads them dynamically only once and caches the result.
20
- * @returns A promise resolving to an object containing the ProviderComponent and cssLoaded status.
21
- */
22
- export async function ensureRainbowKitAssetsLoaded(): Promise<RainbowKitAssets> {
23
- if (loadedAssets) {
24
- logger.debug('RainbowKitAssetManager', 'Assets already loaded, returning cached.');
25
- return loadedAssets;
26
- }
27
-
28
- if (!providerPromise) {
29
- providerPromise = import('@rainbow-me/rainbowkit')
30
- .then((module) => {
31
- const component = module.RainbowKitProvider as React.ComponentType<
32
- React.PropsWithChildren<unknown>
33
- >;
34
- logger.info('RainbowKitAssetManager', 'RainbowKitProvider module loaded.');
35
- return component;
36
- })
37
- .catch((err) => {
38
- logger.error('RainbowKitAssetManager', 'Failed to load RainbowKitProvider module:', err);
39
- return null; // Resolve with null on error to allow Promise.all to complete
40
- });
41
- }
42
-
43
- if (!cssPromise) {
44
- cssPromise = import('@rainbow-me/rainbowkit/styles.css')
45
- .then(() => {
46
- logger.info('RainbowKitAssetManager', 'RainbowKit CSS loaded successfully.');
47
- return true;
48
- })
49
- .catch((err) => {
50
- logger.error('RainbowKitAssetManager', 'Failed to load RainbowKit CSS:', err);
51
- return false; // Resolve with false on error
52
- });
53
- }
54
-
55
- try {
56
- const [ProviderComponent, cssLoadedSuccess] = await Promise.all([providerPromise, cssPromise]);
57
-
58
- loadedAssets = { ProviderComponent, cssLoaded: cssLoadedSuccess };
59
- if (!ProviderComponent || !cssLoadedSuccess) {
60
- logger.warn(
61
- 'RainbowKitAssetManager',
62
- 'One or more RainbowKit assets failed to load.',
63
- loadedAssets
64
- );
65
- // Potentially throw here if assets are critical, or let caller decide based on null/false
66
- }
67
- return loadedAssets;
68
- } catch (error) {
69
- // This catch is for Promise.all failing, though individual catches should handle module errors.
70
- logger.error('RainbowKitAssetManager', 'Error in Promise.all for asset loading:', error);
71
- loadedAssets = { ProviderComponent: null, cssLoaded: false }; // Ensure loadedAssets is set
72
- return loadedAssets;
73
- }
74
- }
@@ -1,74 +0,0 @@
1
- /**
2
- * Custom RainbowKit configuration types for enhanced UI control
3
- */
4
- /**
5
- * Re-export RainbowKit's native types for ConnectButton props
6
- * This ensures we use the exact same types that RainbowKit expects,
7
- * reducing maintenance burden and letting RainbowKit handle type validation
8
- */
9
- // Import RainbowKit's native ConnectButton types
10
- import type { ConnectButton, RainbowKitProvider } from '@rainbow-me/rainbowkit';
11
-
12
- /**
13
- * Extract the `AppInfo` type from the RainbowKitProvider's props.
14
- * This is the canonical way to get the type for the `appInfo` object.
15
- */
16
- export type AppInfo = React.ComponentProps<typeof RainbowKitProvider>['appInfo'];
17
-
18
- /**
19
- * Extract the props type from RainbowKit's ConnectButton component
20
- * This gives us the exact same types that RainbowKit uses internally
21
- */
22
- export type RainbowKitConnectButtonProps = React.ComponentProps<typeof ConnectButton>;
23
-
24
- /**
25
- * Represents the props expected by the RainbowKitProvider component.
26
- * It uses a nested `appInfo` object.
27
- */
28
- export interface RainbowKitProviderProps {
29
- appInfo?: AppInfo;
30
- [key: string]: unknown;
31
- }
32
-
33
- /**
34
- * Represents the shape of the `kitConfig` object we use internally when the
35
- * selected kit is RainbowKit. It has a flat structure for `appName` and `learnMoreUrl`
36
- * for easier handling in our builder app, and can also contain pre-existing providerProps.
37
- */
38
- export type RainbowKitKitConfig = Partial<AppInfo> & {
39
- providerProps?: RainbowKitProviderProps;
40
- [key: string]: unknown;
41
- };
42
-
43
- /**
44
- * Custom UI configuration that uses RainbowKit's native types
45
- * This extends our configuration system while leveraging RainbowKit's own type definitions
46
- */
47
- export interface RainbowKitCustomizations {
48
- /**
49
- * Configuration for the RainbowKit ConnectButton component
50
- * Uses RainbowKit's native prop types for type safety and compatibility
51
- */
52
- connectButton?: Partial<RainbowKitConnectButtonProps>;
53
- }
54
-
55
- /**
56
- * Type guard to check if an object contains RainbowKit customizations
57
- */
58
- export function isRainbowKitCustomizations(obj: unknown): obj is RainbowKitCustomizations {
59
- return typeof obj === 'object' && obj !== null && 'connectButton' in obj;
60
- }
61
-
62
- /**
63
- * Utility to extract RainbowKit customizations from a kit config
64
- */
65
- export function extractRainbowKitCustomizations(
66
- kitConfig: Record<string, unknown> | undefined
67
- ): RainbowKitCustomizations | undefined {
68
- if (!kitConfig || !kitConfig.customizations) {
69
- return undefined;
70
- }
71
-
72
- const customizations = kitConfig.customizations;
73
- return isRainbowKitCustomizations(customizations) ? customizations : undefined;
74
- }