@openzeppelin/contracts-ui-builder-adapter-evm
Version:
EVM Adapter for Contracts UI Builder
459 lines (443 loc) • 15.6 kB
TypeScript
import { GetAccountReturnType } from '@wagmi/core';
import { Chain, Abi, TransactionReceipt } from 'viem';
import React$1 from 'react';
import { EvmNetworkConfig, ContractAdapter, UiKitConfiguration, FormValues, ContractSchema, ProxyInfo, FieldType, FunctionParameter, FormFieldType, ExecutionConfig, TransactionStatusUpdate, RelayerDetails, RelayerDetailsRich, ExecutionMethodDetail, ContractFunction, Connector, NativeConfigLoader, EcosystemReactUiProviderProps, EcosystemSpecificReactHooks, EcosystemWalletComponents, AvailableUiKit, UserRpcProviderConfig, UserExplorerConfig, AdapterConfig } from '@openzeppelin/contracts-ui-builder-types';
import { RainbowKitProvider, ConnectButton } from '@rainbow-me/rainbowkit';
import { Speed } from '@openzeppelin/relayer-sdk';
/**
* EVM-specific type definitions
*/
/**
* EVM-specific network configuration with properly typed viem chain
* This extends the base EvmNetworkConfig with the correct Chain type from viem
*/
interface TypedEvmNetworkConfig extends EvmNetworkConfig {
/**
* Viem Chain object for this EVM network.
* If provided, this will be used directly by Viem clients.
* If not provided, a fallback chain object will be created.
*/
viemChain?: Chain;
}
/**
* Defines the structure for parameters required to execute a contract write operation via viem.
*/
interface WriteContractParameters {
address: `0x${string}`;
abi: Abi;
functionName: string;
args: unknown[];
value?: bigint;
}
/**
* EVM-specific adapter implementation
*/
declare class EvmAdapter implements ContractAdapter {
readonly networkConfig: TypedEvmNetworkConfig;
readonly initialAppServiceKitName: UiKitConfiguration['kitName'];
constructor(networkConfig: TypedEvmNetworkConfig);
/**
* @inheritdoc
*/
loadContract(artifacts: FormValues): Promise<ContractSchema>;
/**
* @inheritdoc
*/
loadContractWithMetadata(artifacts: FormValues): Promise<{
schema: ContractSchema;
source: 'fetched' | 'manual';
contractDefinitionOriginal?: string;
metadata?: {
fetchedFrom?: string;
contractName?: string;
verificationStatus?: 'verified' | 'unverified' | 'unknown';
fetchTimestamp?: Date;
definitionHash?: string;
};
proxyInfo?: ProxyInfo;
}>;
/**
* @inheritdoc
*/
mapParameterTypeToFieldType(parameterType: string): FieldType;
/**
* @inheritdoc
*/
getCompatibleFieldTypes(parameterType: string): FieldType[];
/**
* @inheritdoc
*/
generateDefaultField<T extends FieldType = FieldType>(parameter: FunctionParameter): FormFieldType<T>;
/**
* @inheritdoc
*/
formatTransactionData(contractSchema: ContractSchema, functionId: string, submittedInputs: Record<string, unknown>, fields: FormFieldType[]): WriteContractParameters;
/**
* @inheritdoc
*/
signAndBroadcast(transactionData: unknown, executionConfig: ExecutionConfig, onStatusChange: (status: string, details: TransactionStatusUpdate) => void, runtimeApiKey?: string): Promise<{
txHash: string;
}>;
/**
* @inheritdoc
*/
getRelayers(serviceUrl: string, accessToken: string): Promise<RelayerDetails[]>;
/**
* @inheritdoc
*/
getRelayer(serviceUrl: string, accessToken: string, relayerId: string): Promise<RelayerDetailsRich>;
/**
* Returns a React component for configuring EVM-specific relayer transaction options.
* @returns The EVM relayer options component
*/
getRelayerOptionsComponent(): React$1.ComponentType<{
options: Record<string, unknown>;
onChange: (options: Record<string, unknown>) => void;
}> | undefined;
/**
* @inheritdoc
*/
getWritableFunctions(contractSchema: ContractSchema): ContractSchema['functions'];
/**
* @inheritdoc
*/
isValidAddress(address: string): boolean;
/**
* @inheritdoc
*/
getSupportedExecutionMethods(): Promise<ExecutionMethodDetail[]>;
/**
* @inheritdoc
*/
validateExecutionConfig(config: ExecutionConfig): Promise<true | string>;
/**
* @inheritdoc
*/
isViewFunction(functionDetails: ContractFunction): boolean;
/**
* @inheritdoc
*/
filterAutoQueryableFunctions(functions: ContractFunction[]): ContractFunction[];
/**
* @inheritdoc
*/
queryViewFunction(contractAddress: string, functionId: string, params?: unknown[], contractSchema?: ContractSchema): Promise<unknown>;
/**
* @inheritdoc
*/
formatFunctionResult(decodedValue: unknown, functionDetails: ContractFunction): string;
/**
* @inheritdoc
*/
supportsWalletConnection(): boolean;
/**
* @inheritdoc
*/
getAvailableConnectors(): Promise<Connector[]>;
/**
* @inheritdoc
*/
connectWallet(connectorId: string): Promise<{
connected: boolean;
address?: string;
error?: string;
}>;
/**
* @inheritdoc
*/
disconnectWallet(): Promise<{
disconnected: boolean;
error?: string;
}>;
/**
* @inheritdoc
*/
getWalletConnectionStatus(): {
isConnected: boolean;
address?: string;
chainId?: string;
};
/**
* @inheritdoc
*/
onWalletConnectionChange(callback: (account: GetAccountReturnType, prevAccount: GetAccountReturnType) => void): () => void;
/**
* @inheritdoc
*/
getExplorerUrl(address: string): string | null;
/**
* @inheritdoc
*/
getExplorerTxUrl?(txHash: string): string | null;
/**
* @inheritdoc
*/
waitForTransactionConfirmation(txHash: string): Promise<{
status: 'success' | 'error';
receipt?: TransactionReceipt;
error?: Error;
}>;
/**
* @inheritdoc
*/
configureUiKit(programmaticOverrides?: Partial<UiKitConfiguration>, options?: {
loadUiKitNativeConfig?: NativeConfigLoader;
}): Promise<void>;
/**
* @inheritdoc
*/
getEcosystemReactUiContextProvider(): React$1.ComponentType<EcosystemReactUiProviderProps> | undefined;
/**
* @inheritdoc
*/
getEcosystemReactHooks(): EcosystemSpecificReactHooks | undefined;
/**
* @inheritdoc
*/
getEcosystemWalletComponents(): EcosystemWalletComponents | undefined;
getAvailableUiKits(): Promise<AvailableUiKit[]>;
getExportableWalletConfigFiles(uiKitConfig?: UiKitConfiguration): Promise<Record<string, string>>;
/**
* @inheritdoc
*/
getContractDefinitionInputs(): FormFieldType[];
/**
* @inheritdoc
*/
validateRpcEndpoint(rpcConfig: UserRpcProviderConfig): Promise<boolean>;
/**
* @inheritdoc
*/
testRpcConnection(rpcConfig: UserRpcProviderConfig): Promise<{
success: boolean;
latency?: number;
error?: string;
}>;
/**
* @inheritdoc
*/
validateExplorerConfig(explorerConfig: UserExplorerConfig): Promise<boolean>;
/**
* @inheritdoc
*/
testExplorerConnection(explorerConfig: UserExplorerConfig): Promise<{
success: boolean;
latency?: number;
error?: string;
}>;
/**
* @inheritdoc
*/
compareContractDefinitions(storedSchema: string, freshSchema: string): Promise<{
identical: boolean;
differences: Array<{
type: 'added' | 'removed' | 'modified';
section: string;
name: string;
details: string;
impact: 'low' | 'medium' | 'high';
oldSignature?: string;
newSignature?: string;
}>;
severity: 'none' | 'minor' | 'major' | 'breaking';
summary: string;
}>;
/**
* @inheritdoc
*/
validateContractDefinition(definition: string): {
valid: boolean;
errors: string[];
warnings: string[];
};
/**
* @inheritdoc
*/
hashContractDefinition(definition: string): string;
}
/**
* Custom RainbowKit configuration types for enhanced UI control
*/
/**
* Re-export RainbowKit's native types for ConnectButton props
* This ensures we use the exact same types that RainbowKit expects,
* reducing maintenance burden and letting RainbowKit handle type validation
*/
/**
* Extract the `AppInfo` type from the RainbowKitProvider's props.
* This is the canonical way to get the type for the `appInfo` object.
*/
type AppInfo = React.ComponentProps<typeof RainbowKitProvider>['appInfo'];
/**
* Extract the props type from RainbowKit's ConnectButton component
* This gives us the exact same types that RainbowKit uses internally
*/
type RainbowKitConnectButtonProps = React.ComponentProps<typeof ConnectButton>;
/**
* Represents the props expected by the RainbowKitProvider component.
* It uses a nested `appInfo` object.
*/
interface RainbowKitProviderProps {
appInfo?: AppInfo;
[key: string]: unknown;
}
/**
* Represents the shape of the `kitConfig` object we use internally when the
* selected kit is RainbowKit. It has a flat structure for `appName` and `learnMoreUrl`
* for easier handling in our builder app, and can also contain pre-existing providerProps.
*/
type RainbowKitKitConfig = Partial<AppInfo> & {
providerProps?: RainbowKitProviderProps;
[key: string]: unknown;
};
/**
* Custom UI configuration that uses RainbowKit's native types
* This extends our configuration system while leveraging RainbowKit's own type definitions
*/
interface RainbowKitCustomizations {
/**
* Configuration for the RainbowKit ConnectButton component
* Uses RainbowKit's native prop types for type safety and compatibility
*/
connectButton?: Partial<RainbowKitConnectButtonProps>;
}
/**
* Type guard to check if an object contains RainbowKit customizations
*/
declare function isRainbowKitCustomizations(obj: unknown): obj is RainbowKitCustomizations;
/**
* Utility to extract RainbowKit customizations from a kit config
*/
declare function extractRainbowKitCustomizations(kitConfig: Record<string, unknown> | undefined): RainbowKitCustomizations | undefined;
declare const ethereumMainnet: TypedEvmNetworkConfig;
declare const arbitrumMainnet: TypedEvmNetworkConfig;
declare const polygonMainnet: TypedEvmNetworkConfig;
declare const polygonZkEvmMainnet: TypedEvmNetworkConfig;
declare const baseMainnet: TypedEvmNetworkConfig;
declare const bscMainnet: TypedEvmNetworkConfig;
declare const optimismMainnet: TypedEvmNetworkConfig;
declare const avalancheMainnet: TypedEvmNetworkConfig;
declare const zkSyncEraMainnet: TypedEvmNetworkConfig;
declare const scrollMainnet: TypedEvmNetworkConfig;
declare const lineaMainnet: TypedEvmNetworkConfig;
declare const ethereumSepolia: TypedEvmNetworkConfig;
declare const arbitrumSepolia: TypedEvmNetworkConfig;
declare const polygonAmoy: TypedEvmNetworkConfig;
declare const polygonZkEvmCardona: TypedEvmNetworkConfig;
declare const baseSepolia: TypedEvmNetworkConfig;
declare const bscTestnet: TypedEvmNetworkConfig;
declare const optimismSepolia: TypedEvmNetworkConfig;
declare const avalancheFuji: TypedEvmNetworkConfig;
declare const zksyncSepoliaTestnet: TypedEvmNetworkConfig;
declare const scrollSepolia: TypedEvmNetworkConfig;
declare const lineaSepolia: TypedEvmNetworkConfig;
declare const evmMainnetNetworks: TypedEvmNetworkConfig[];
declare const evmTestnetNetworks: TypedEvmNetworkConfig[];
declare const evmNetworks: TypedEvmNetworkConfig[];
/**
* Configuration for the EVM adapter
*
* This file defines the dependencies required by the EVM adapter
* when generating exported projects. It follows the AdapterConfig
* interface to provide a structured approach to dependency management.
*/
declare const evmAdapterConfig: AdapterConfig;
/**
* EVM-specific transaction options for the OpenZeppelin Relayer.
* These options map directly to the EvmTransactionRequest parameters in the SDK.
*/
interface EvmRelayerTransactionOptions {
speed?: Speed;
gasLimit?: number;
gasPrice?: number;
maxFeePerGas?: number;
maxPriorityFeePerGas?: number;
validUntil?: string;
}
/**
* EVM-specific ABI types for comparison and validation
* Uses viem's Abi type as the foundation for type safety
*/
/**
* Result of comparing two ABIs
*/
interface AbiComparisonResult {
/** Whether the ABIs are identical after normalization */
identical: boolean;
/** List of differences found between the ABIs */
differences: AbiDifference[];
/** Overall severity of the changes */
severity: 'none' | 'minor' | 'major' | 'breaking';
/** Human-readable summary of the comparison */
summary: string;
}
/**
* Represents a single difference between two ABIs
*/
interface AbiDifference {
/** Type of change */
type: 'added' | 'removed' | 'modified';
/** Which section of the ABI was affected */
section: 'function' | 'event' | 'constructor' | 'error' | 'fallback' | 'receive';
/** Name of the affected item (or type if no name) */
name: string;
/** Detailed description of the change */
details: string;
/** Impact level of this change */
impact: 'low' | 'medium' | 'high';
/** Signature before the change (for removed/modified) */
oldSignature?: string;
/** Signature after the change (for added/modified) */
newSignature?: string;
}
/**
* Result of validating an ABI structure
*/
interface AbiValidationResult {
/** Whether the ABI is structurally valid */
valid: boolean;
/** List of validation errors found */
errors: string[];
/** List of validation warnings */
warnings: string[];
/** Normalized ABI if validation passed */
normalizedAbi?: Abi;
}
/**
* ABI comparison service for EVM contracts
* Provides detailed analysis of differences between ABIs
*/
/**
* Service for comparing and validating EVM ABIs
*/
declare class AbiComparisonService {
/**
* Compares two ABIs and returns detailed difference analysis
*/
compareAbis(abi1: string, abi2: string): AbiComparisonResult;
/**
* Validates ABI structure and format
*/
validateAbi(abiString: string): AbiValidationResult;
/**
* Creates deterministic hash of ABI for quick comparison
*/
hashAbi(abiString: string): string;
/**
* Normalizes ABI for consistent comparison
*/
private normalizeAbi;
/**
* Finds detailed differences between two normalized ABIs
*/
private findDifferences;
private createAbiMap;
private generateItemKey;
private generateSignature;
private itemsEqual;
private calculateImpact;
private calculateSeverity;
private generateSummary;
}
declare const abiComparisonService: AbiComparisonService;
export { type AppInfo, EvmAdapter, type EvmRelayerTransactionOptions, type RainbowKitConnectButtonProps, type RainbowKitCustomizations, type RainbowKitKitConfig, type RainbowKitProviderProps, type TypedEvmNetworkConfig, type WriteContractParameters, abiComparisonService, arbitrumMainnet, arbitrumSepolia, avalancheFuji, avalancheMainnet, baseMainnet, baseSepolia, bscMainnet, bscTestnet, ethereumMainnet, ethereumSepolia, evmAdapterConfig, evmMainnetNetworks, evmNetworks, evmTestnetNetworks, extractRainbowKitCustomizations, isRainbowKitCustomizations, lineaMainnet, lineaSepolia, optimismMainnet, optimismSepolia, polygonAmoy, polygonMainnet, polygonZkEvmCardona, polygonZkEvmMainnet, scrollMainnet, scrollSepolia, zkSyncEraMainnet, zksyncSepoliaTestnet };