@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.
- package/README.md +33 -18
- package/dist/index.cjs +4651 -4448
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -226
- package/dist/index.d.ts +12 -226
- package/dist/index.js +4737 -4535
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
- package/src/__tests__/adapter-parsing.test.ts +4 -3
- package/src/__tests__/getDefaultServiceConfig.test.ts +185 -0
- package/src/__tests__/mocks/mock-network-configs.ts +1 -1
- package/src/__tests__/provenanceLinks.test.ts +6 -4
- package/src/__tests__/providerSelection.test.ts +5 -4
- package/src/__tests__/timeouts.test.ts +5 -3
- package/src/__tests__/wallet-connect.test.ts +2 -2
- package/src/adapter.ts +61 -107
- package/src/configuration/execution.ts +1 -52
- package/src/configuration/index.ts +2 -3
- package/src/configuration/network-services.ts +47 -60
- package/src/index.ts +22 -13
- package/src/networks/index.ts +2 -1
- package/src/networks/mainnet.ts +1 -1
- package/src/networks/testnet.ts +1 -1
- package/src/query/adapter-query.ts +72 -0
- package/src/query/index.ts +2 -2
- package/src/transaction/components/useEvmRelayerOptions.ts +5 -3
- package/src/transaction/index.ts +1 -5
- package/src/types/artifacts.ts +5 -30
- package/src/types/providers.ts +7 -18
- package/src/wallet/components/EvmWalletUiRoot.tsx +1 -1
- package/src/wallet/evmUiKitManager.ts +26 -129
- package/src/wallet/hooks/index.ts +0 -1
- package/src/wallet/implementation/wagmi-implementation.ts +45 -577
- package/src/wallet/index.ts +2 -3
- package/src/wallet/rainbowkit/__tests__/export-service.test.ts +1 -2
- package/src/wallet/rainbowkit/componentFactory.ts +10 -8
- package/src/wallet/rainbowkit/components.tsx +16 -133
- package/src/wallet/rainbowkit/index.ts +27 -5
- package/src/wallet/utils/__tests__/uiKitService.test.ts +5 -1
- package/src/wallet/utils/connection.ts +8 -52
- package/src/wallet/utils/index.ts +0 -2
- package/src/wallet/utils/uiKitService.ts +7 -3
- package/src/wallet/utils/walletImplementationManager.ts +5 -4
- package/src/wallet/utils.ts +1 -65
- package/src/abi/__tests__/etherscan-v2.test.ts +0 -117
- package/src/abi/__tests__/transformer.test.ts +0 -342
- package/src/abi/comparison.ts +0 -389
- package/src/abi/etherscan-v2.ts +0 -243
- package/src/abi/etherscan.ts +0 -158
- package/src/abi/index.ts +0 -7
- package/src/abi/loader.ts +0 -415
- package/src/abi/sourcify.ts +0 -75
- package/src/abi/transformer.ts +0 -163
- package/src/abi/types.ts +0 -101
- package/src/configuration/__tests__/explorer.test.ts +0 -174
- package/src/configuration/__tests__/rpc.test.ts +0 -176
- package/src/configuration/explorer.ts +0 -243
- package/src/configuration/rpc.ts +0 -257
- package/src/mapping/__tests__/field-generator.test.ts +0 -137
- package/src/mapping/__tests__/type-mapper.test.ts +0 -139
- package/src/mapping/constants.ts +0 -57
- package/src/mapping/field-generator.ts +0 -115
- package/src/mapping/index.ts +0 -4
- package/src/mapping/type-mapper.ts +0 -80
- package/src/proxy/detection.ts +0 -465
- package/src/query/handler.ts +0 -227
- package/src/query/view-checker.ts +0 -10
- package/src/transaction/eoa.ts +0 -98
- package/src/transaction/execution-strategy.ts +0 -33
- package/src/transaction/formatter.ts +0 -101
- package/src/transaction/relayer.ts +0 -380
- package/src/transaction/sender.ts +0 -185
- package/src/transform/index.ts +0 -3
- package/src/transform/input-parser.ts +0 -177
- package/src/transform/output-formatter.ts +0 -64
- package/src/types/__tests__/artifacts.test.ts +0 -105
- package/src/types.ts +0 -92
- package/src/utils/__tests__/artifacts.test.ts +0 -81
- package/src/utils/artifacts.ts +0 -30
- package/src/utils/formatting.ts +0 -25
- package/src/utils/gas.ts +0 -17
- package/src/utils/index.ts +0 -6
- package/src/utils/json.ts +0 -19
- package/src/utils/validation.ts +0 -10
- package/src/validation/eoa.ts +0 -33
- package/src/validation/index.ts +0 -2
- package/src/validation/relayer.ts +0 -13
- package/src/wallet/__tests__/utils.test.ts +0 -149
- package/src/wallet/components/account/AccountDisplay.tsx +0 -52
- package/src/wallet/components/connect/ConnectButton.tsx +0 -125
- package/src/wallet/components/connect/ConnectorDialog.tsx +0 -140
- package/src/wallet/components/index.ts +0 -4
- package/src/wallet/components/network/NetworkSwitcher.tsx +0 -90
- package/src/wallet/context/index.ts +0 -1
- package/src/wallet/context/wagmi-context.tsx +0 -7
- package/src/wallet/hooks/useIsWagmiProviderInitialized.ts +0 -11
- package/src/wallet/rainbowkit/config-generator.ts +0 -56
- package/src/wallet/rainbowkit/config-service.ts +0 -169
- package/src/wallet/rainbowkit/export-service.ts +0 -18
- package/src/wallet/rainbowkit/rainbowkitAssetManager.ts +0 -74
- package/src/wallet/rainbowkit/types.ts +0 -74
- package/src/wallet/rainbowkit/utils.ts +0 -96
- package/src/wallet/services/configResolutionService.ts +0 -65
- package/src/wallet/utils/SafeWagmiComponent.tsx +0 -72
- 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,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,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
|
-
}
|