diff --git a/apps/contract-verification/src/app/AppContext.tsx b/apps/contract-verification/src/app/AppContext.tsx index e0def0e176..a730ca5e65 100644 --- a/apps/contract-verification/src/app/AppContext.tsx +++ b/apps/contract-verification/src/app/AppContext.tsx @@ -1,18 +1,15 @@ import React from 'react' -import { ThemeType } from './types' -import { Chain, SubmittedContracts } from './types/VerificationTypes' +import type { ThemeType, Chain, SubmittedContracts, ContractVerificationSettings } from './types' import { CompilerAbstract } from '@remix-project/remix-solidity' -import { AbstractVerifier } from './Verifiers/AbstractVerifier' // Define the type for the context type AppContextType = { themeType: ThemeType setThemeType: (themeType: ThemeType) => void + settings: ContractVerificationSettings + setSettings: React.Dispatch> chains: Chain[] compilationOutput: { [key: string]: CompilerAbstract } | undefined - targetFileName: string | undefined - verifiers: AbstractVerifier[] - setVerifiers: React.Dispatch> submittedContracts: SubmittedContracts setSubmittedContracts: React.Dispatch> } @@ -23,11 +20,10 @@ const defaultContextValue: AppContextType = { setThemeType: (themeType: ThemeType) => { console.log('Calling Set Theme Type') }, + settings: { chains: {} }, + setSettings: () => {}, chains: [], compilationOutput: undefined, - targetFileName: undefined, - verifiers: [], - setVerifiers: (verifiers: AbstractVerifier[]) => {}, submittedContracts: {}, setSubmittedContracts: (submittedContracts: SubmittedContracts) => {}, } diff --git a/apps/contract-verification/src/app/Receipts/SourcifyReceipt.tsx b/apps/contract-verification/src/app/Receipts/SourcifyReceipt.tsx index 96bfa8e751..063c73d5bf 100644 --- a/apps/contract-verification/src/app/Receipts/SourcifyReceipt.tsx +++ b/apps/contract-verification/src/app/Receipts/SourcifyReceipt.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react' import { SourcifyVerifier } from '../Verifiers/SourcifyVerifier' -// import { SourcifyVerificationStatus } from '../types/VerificationTypes' +// import { SourcifyVerificationStatus } from '../types' import { ReceiptProps } from './props' // A receipt is something to be rendered diff --git a/apps/contract-verification/src/app/Verifiers/AbstractVerifier.ts b/apps/contract-verification/src/app/Verifiers/AbstractVerifier.ts index a7db33316b..29d79d2732 100644 --- a/apps/contract-verification/src/app/Verifiers/AbstractVerifier.ts +++ b/apps/contract-verification/src/app/Verifiers/AbstractVerifier.ts @@ -1,5 +1,5 @@ import { CompilerAbstract } from '@remix-project/remix-solidity' -import { LookupResponse, SubmittedContract, VerificationResponse, VerificationStatus } from '../types/VerificationTypes' +import type { LookupResponse, SubmittedContract, VerificationResponse, VerificationStatus } from '../types' export interface AbstractVerifier { checkVerificationStatus?(receiptId: string): Promise diff --git a/apps/contract-verification/src/app/Verifiers/EtherscanVerifier.ts b/apps/contract-verification/src/app/Verifiers/EtherscanVerifier.ts index 44fd4ca536..2a5e222dab 100644 --- a/apps/contract-verification/src/app/Verifiers/EtherscanVerifier.ts +++ b/apps/contract-verification/src/app/Verifiers/EtherscanVerifier.ts @@ -1,6 +1,6 @@ import { CompilerAbstract } from '@remix-project/remix-solidity' import { AbstractVerifier } from './AbstractVerifier' -import { LookupResponse, SubmittedContract, VerificationResponse, VerificationStatus } from '../types/VerificationTypes' +import type { LookupResponse, SubmittedContract, VerificationResponse, VerificationStatus } from '../types' interface EtherscanVerificationRequest { chainId?: string diff --git a/apps/contract-verification/src/app/Verifiers/SourcifyVerifier.ts b/apps/contract-verification/src/app/Verifiers/SourcifyVerifier.ts index 91938760b3..c5a73dbaaf 100644 --- a/apps/contract-verification/src/app/Verifiers/SourcifyVerifier.ts +++ b/apps/contract-verification/src/app/Verifiers/SourcifyVerifier.ts @@ -1,6 +1,6 @@ import { CompilerAbstract, SourcesCode } from '@remix-project/remix-solidity' import { AbstractVerifier } from './AbstractVerifier' -import { LookupResponse, SubmittedContract, VerificationResponse, VerificationStatus } from '../types/VerificationTypes' +import type { LookupResponse, SubmittedContract, VerificationResponse, VerificationStatus } from '../types' interface SourcifyVerificationRequest { address: string diff --git a/apps/contract-verification/src/app/Verifiers/index.ts b/apps/contract-verification/src/app/Verifiers/index.ts index 65a0169afb..e2376589f5 100644 --- a/apps/contract-verification/src/app/Verifiers/index.ts +++ b/apps/contract-verification/src/app/Verifiers/index.ts @@ -1,4 +1,4 @@ -import { VerifierIdentifier, VerifierSettings } from '../types/VerificationTypes' +import type { VerifierIdentifier, VerifierSettings } from '../types' import { AbstractVerifier } from './AbstractVerifier' import { BlockscoutVerifier } from './BlockscoutVerifier' import { EtherscanVerifier } from './EtherscanVerifier' diff --git a/apps/contract-verification/src/app/app.tsx b/apps/contract-verification/src/app/app.tsx index 5cf44fc82c..ad5cea424b 100644 --- a/apps/contract-verification/src/app/app.tsx +++ b/apps/contract-verification/src/app/app.tsx @@ -1,35 +1,26 @@ -import React, { useState, useEffect, useRef } from 'react' +import { useState, useEffect } from 'react' import { ContractVerificationPluginClient } from './ContractVerificationPluginClient' import { AppContext } from './AppContext' import DisplayRoutes from './routes' -import { ThemeType } from './types' +import { ContractVerificationSettings, ThemeType, Chain, SubmittedContracts } from './types' import './App.css' -import { Chain, SubmittedContracts } from './types/VerificationTypes' import { CompilerAbstract } from '@remix-project/remix-solidity' -import { SourcifyVerifier } from './Verifiers/SourcifyVerifier' -import { EtherscanVerifier } from './Verifiers/EtherscanVerifier' -import { AbstractVerifier } from './Verifiers/AbstractVerifier' -import { ContractDropdownSelection } from './components/ContractDropdown' +import { useLocalStorage } from './hooks/useLocalStorage' const plugin = new ContractVerificationPluginClient() const App = () => { const [themeType, setThemeType] = useState('dark') + const [settings, setSettings] = useLocalStorage('contract-verification:settings', { chains: {} }) + const [submittedContracts, setSubmittedContracts] = useLocalStorage('contract-verification:submitted-contracts', {}) // TODO: Types for chains const [chains, setChains] = useState([]) // State to hold the chains data - const [targetFileName, setTargetFileName] = useState('') const [compilationOutput, setCompilationOutput] = useState<{ [key: string]: CompilerAbstract } | undefined>() - const [verifiers, setVerifiers] = useState([]) - const [submittedContracts, setSubmittedContracts] = useState({}) useEffect(() => { - // const sourcifyVerifier = new SourcifyVerifier('http://sourcify.dev/server/', 'Sourcify') - const sourcifyVerifier = new SourcifyVerifier('http://localhost:5555/', 'todo') - const etherscanVerifier = new EtherscanVerifier('https://api.etherscan.io', 'todo', 'API_KEY') - setVerifiers([sourcifyVerifier, etherscanVerifier]) // TODO: Fix 'compilationFinished' event types. The interface is outdated at https://github.com/ethereum/remix-plugin/blob/master/packages/api/src/lib/compiler/api.ts. It does not include data, input, or version. See the current parameters: https://github.com/ethereum/remix-project/blob/9f6c5be882453a555055f07171701459e4ae88a4/libs/remix-solidity/src/compiler/compiler.ts#L189 // Fetch compiler artefacts initially @@ -61,7 +52,7 @@ const App = () => { }, []) return ( - + ) diff --git a/apps/contract-verification/src/app/components/AccordionReceipt.tsx b/apps/contract-verification/src/app/components/AccordionReceipt.tsx index 9b29c00a4b..1d09db6605 100644 --- a/apps/contract-verification/src/app/components/AccordionReceipt.tsx +++ b/apps/contract-verification/src/app/components/AccordionReceipt.tsx @@ -1,5 +1,5 @@ import React, { useMemo } from 'react' -import { SubmittedContract, SubmittedProxyContract, isContract, isProxy } from '../types/VerificationTypes' +import { SubmittedContract, SubmittedProxyContract, isContract, isProxy } from '../types' import { shortenAddress, CustomTooltip } from '@remix-ui/helper' import { AppContext } from '../AppContext' diff --git a/apps/contract-verification/src/app/components/SearchableChainDropdown.tsx b/apps/contract-verification/src/app/components/SearchableChainDropdown.tsx index 1c8542f307..2afe0e0da0 100644 --- a/apps/contract-verification/src/app/components/SearchableChainDropdown.tsx +++ b/apps/contract-verification/src/app/components/SearchableChainDropdown.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef, useMemo } from 'react' import Fuse from 'fuse.js' -import { Chain } from '../types/VerificationTypes' +import type { Chain } from '../types' import { AppContext } from '../AppContext' interface DropdownProps { diff --git a/apps/contract-verification/src/app/hooks/useLocalStorage.tsx b/apps/contract-verification/src/app/hooks/useLocalStorage.tsx index 3d66b7bcf4..9007c1a8b4 100644 --- a/apps/contract-verification/src/app/hooks/useLocalStorage.tsx +++ b/apps/contract-verification/src/app/hooks/useLocalStorage.tsx @@ -1,9 +1,9 @@ import { useState } from 'react' -export function useLocalStorage(key: string, initialValue: any) { +export function useLocalStorage(key: string, initialValue: T): [T, (value: T) => void] { // State to store our value // Pass initial state function to useState so logic is only executed once - const [storedValue, setStoredValue] = useState(() => { + const [storedValue, setStoredValue] = useState(() => { try { // Get from local storage by key const item = window.localStorage.getItem(key) @@ -18,14 +18,12 @@ export function useLocalStorage(key: string, initialValue: any) { // Return a wrapped version of useState's setter function that ... // ... persists the new value to localStorage. - const setValue = (value: any) => { + const setValue = (value: T) => { try { - // Allow value to be a function so we have same API as useState - const valueToStore = value instanceof Function ? value(storedValue) : value // Save state - setStoredValue(valueToStore) + setStoredValue(value) // Save to local storage - window.localStorage.setItem(key, JSON.stringify(valueToStore)) + window.localStorage.setItem(key, JSON.stringify(value)) } catch (error) { // A more advanced implementation would handle the error case console.error(error) diff --git a/apps/contract-verification/src/app/types/SettingsTypes.ts b/apps/contract-verification/src/app/types/SettingsTypes.ts new file mode 100644 index 0000000000..9bb660aaf8 --- /dev/null +++ b/apps/contract-verification/src/app/types/SettingsTypes.ts @@ -0,0 +1,19 @@ +import { VerifierIdentifier } from './VerificationTypes' + +export interface VerifierSettings { + apiUrl: string + explorerUrl?: string + apiKey?: string +} + +export type SettingsForVerifier = Record + +export interface ChainSettings { + verifiers: SettingsForVerifier +} + +export type SettingsForChains = Record + +export interface ContractVerificationSettings { + chains: SettingsForChains +} diff --git a/apps/contract-verification/src/app/types/VerificationTypes.ts b/apps/contract-verification/src/app/types/VerificationTypes.ts index 4d8887e726..d437bf3d31 100644 --- a/apps/contract-verification/src/app/types/VerificationTypes.ts +++ b/apps/contract-verification/src/app/types/VerificationTypes.ts @@ -19,12 +19,6 @@ export interface Chain { export type VerifierIdentifier = 'Sourcify' | 'Etherscan' | 'Blockscout' -export interface VerifierSettings { - apiUrl: string - explorerUrl?: string - apiKey?: string -} - export interface VerifierInfo { name: VerifierIdentifier apiUrl: string diff --git a/apps/contract-verification/src/app/types/index.ts b/apps/contract-verification/src/app/types/index.ts index 0143b906b4..6b783cddab 100644 --- a/apps/contract-verification/src/app/types/index.ts +++ b/apps/contract-verification/src/app/types/index.ts @@ -1 +1,3 @@ export * from './ThemeType' +export * from './SettingsTypes' +export * from './VerificationTypes' diff --git a/apps/contract-verification/src/app/views/LookupView.tsx b/apps/contract-verification/src/app/views/LookupView.tsx index ab9c448623..8a640db1a6 100644 --- a/apps/contract-verification/src/app/views/LookupView.tsx +++ b/apps/contract-verification/src/app/views/LookupView.tsx @@ -1,6 +1,6 @@ import { useState } from 'react' import { SearchableChainDropdown, ContractAddressInput } from '../components' -import { Chain } from '../types/VerificationTypes' +import type { Chain } from '../types' export const LookupView = () => { const [selectedChain, setSelectedChain] = useState() diff --git a/apps/contract-verification/src/app/views/ReceiptsView.tsx b/apps/contract-verification/src/app/views/ReceiptsView.tsx index 98de6acc9a..9352ef30bd 100644 --- a/apps/contract-verification/src/app/views/ReceiptsView.tsx +++ b/apps/contract-verification/src/app/views/ReceiptsView.tsx @@ -1,6 +1,6 @@ import example from './example.js' import { AccordionReceipt } from '../components/AccordionReceipt' -import { SubmittedContracts } from '../types/VerificationTypes' +import type { SubmittedContracts } from '../types' export const ReceiptsView = () => { const submittedContracts = example as unknown as SubmittedContracts diff --git a/apps/contract-verification/src/app/views/SettingsView.tsx b/apps/contract-verification/src/app/views/SettingsView.tsx index ab68a6b323..d17a5fd758 100644 --- a/apps/contract-verification/src/app/views/SettingsView.tsx +++ b/apps/contract-verification/src/app/views/SettingsView.tsx @@ -1,6 +1,6 @@ import { useState } from 'react' import { SearchableChainDropdown, ConfigInput } from '../components' -import { Chain } from '../types/VerificationTypes' +import type { Chain } from '../types' export const SettingsView = () => { const [selectedChain, setSelectedChain] = useState() diff --git a/apps/contract-verification/src/app/views/VerifyView.tsx b/apps/contract-verification/src/app/views/VerifyView.tsx index f4999605a3..8b61be992d 100644 --- a/apps/contract-verification/src/app/views/VerifyView.tsx +++ b/apps/contract-verification/src/app/views/VerifyView.tsx @@ -2,22 +2,29 @@ import React, { useEffect, useState } from 'react' import { AppContext } from '../AppContext' import { SearchableChainDropdown, ContractDropdown, ContractAddressInput } from '../components' -import { Chain, SubmittedContract, VerificationReceipt, VerifierInfo } from '../types/VerificationTypes' +import type { Chain, SubmittedContract, VerificationReceipt, VerifierInfo } from '../types' import { SourcifyVerifier } from '../Verifiers/SourcifyVerifier' import { EtherscanVerifier } from '../Verifiers/EtherscanVerifier' import { useNavigate } from 'react-router-dom' import { ConstructorArguments } from '../components/ConstructorArguments' -import { getVerifier } from '../Verifiers' +import { AbstractVerifier, getVerifier } from '../Verifiers' import { ContractDropdownSelection } from '../components/ContractDropdown' export const VerifyView = () => { - const { compilationOutput, verifiers, setVerifiers, setSubmittedContracts } = React.useContext(AppContext) + const { compilationOutput, setSubmittedContracts } = React.useContext(AppContext) const [contractAddress, setContractAddress] = useState('') const [selectedChain, setSelectedChain] = useState() const [abiEncodedConstructorArgs, setAbiEncodedConstructorArgs] = React.useState('') const [selectedContract, setSelectedContract] = useState() const navigate = useNavigate() + // TODO + const [verifiers, setVerifiers] = useState([]) // Placeholder, to be derived from settings + // const sourcifyVerifier = new SourcifyVerifier('http://sourcify.dev/server/', 'Sourcify') + const sourcifyVerifier = new SourcifyVerifier('http://localhost:5555/', 'todo') + const etherscanVerifier = new EtherscanVerifier('https://api.etherscan.io', 'todo', 'API_KEY') + setVerifiers([sourcifyVerifier, etherscanVerifier]) + useEffect(() => { console.log('Selected chain changed', selectedChain) }, [selectedChain])