From 61bea0ec750aaee6767785fc9f3aac9927fa2fea Mon Sep 17 00:00:00 2001 From: Tien Nam Dao Date: Mon, 21 Nov 2022 16:18:23 +0700 Subject: [PATCH] fix: update API evmVersion + solidityCompiler --- .tikici.yaml | 4 +- api/api_list.ts | 4 +- components/FormItem/index.tsx | 1 + .../ContractFlattenedVerify.tsx | 22 ++++---- .../VerifyContract/hook/useEvmVersion.ts | 20 +++++++ .../hook/useSolidityCompiler.ts | 20 +++++++ pages/_app.tsx | 2 - types/address.d.ts | 9 ++- views/transactions/DecodeInput.tsx | 17 +++--- views/transactions/Log.tsx | 56 +++++++++++-------- views/transactions/TransactionTabs.tsx | 2 +- 11 files changed, 105 insertions(+), 52 deletions(-) create mode 100644 components/VerifyContract/hook/useEvmVersion.ts create mode 100644 components/VerifyContract/hook/useSolidityCompiler.ts diff --git a/.tikici.yaml b/.tikici.yaml index 521b4811..24698fef 100644 --- a/.tikici.yaml +++ b/.tikici.yaml @@ -83,7 +83,7 @@ deployment_config: port: '3000' envFrom: - secretRef: - name: env-explorer-fe + name: explorer-fe optional: false replicaCount: 1 prod: @@ -95,6 +95,6 @@ deployment_config: port: '3000' envFrom: - secretRef: - name: env-explorer-fe + name: explorer-fe optional: false replicaCount: 1 diff --git a/api/api_list.ts b/api/api_list.ts index 65c88cf1..75d9e69b 100644 --- a/api/api_list.ts +++ b/api/api_list.ts @@ -47,7 +47,9 @@ const API_LIST = { CONTRACT_CODE: 'evm_/api/v1?module=contract&action=getsourcecode', VERIFY_CONTRACT: 'https://blockscout.astranaut.dev/verify_smart_contract/contract_verifications', - CHECK_VERIFY_STATUS: 'evm_/api/v1?module=contract&action=checkverifystatus' + CHECK_VERIFY_STATUS: 'evm_/api/v1?module=contract&action=checkverifystatus', + GET_EVM_VERSION: 'evm_/api/v1/evm-versions', + GET_SOLIDITY_COMPILER: 'evm_/api/v1/compiler-versions?compiler=solc' } export default API_LIST diff --git a/components/FormItem/index.tsx b/components/FormItem/index.tsx index 4770d1de..d0107dfa 100644 --- a/components/FormItem/index.tsx +++ b/components/FormItem/index.tsx @@ -83,6 +83,7 @@ const FormItem = ({ label, type, inputProps }: Props) => { data-for={data?.id} onChange={value => props.onSelect(value)} options={data.items} + defaultInputValue={data.currentValue} {...props} /> ) diff --git a/components/VerifyContract/ContractFlattenedVerify.tsx b/components/VerifyContract/ContractFlattenedVerify.tsx index 734526a7..53489f43 100644 --- a/components/VerifyContract/ContractFlattenedVerify.tsx +++ b/components/VerifyContract/ContractFlattenedVerify.tsx @@ -11,6 +11,8 @@ import { useEffect, useRef, useState } from 'react' import AddressDisplay from './AddressDisplay' import Header from './Header' import useContractVerifyStatus from './hook/useContractVerifyStatus' +import useEvmVersion from './hook/useEvmVersion' +import useSolidityCompiler from './hook/useSolidityCompiler' import styles from './style.module.scss' interface Props { @@ -24,7 +26,7 @@ const ContractFlattenedVerify = ({ address, onClose, onSuccess }: Props) => { const [contractName, setContractName] = useState('') const [hasNightlyBuild, setHasNightlyBuild] = useState(true) const [compiler, setCompiler] = useState(undefined) - const [evmVersion, setEvmVersion] = useState(undefined) + const [evmVersion, setEvmVersion] = useState('default') const [hasOptimization, setOptimization] = useState(true) const [optimizeRun, setOptimizeRun] = useState(200) const [solidityCode, setSolidityCode] = useState('') @@ -33,6 +35,8 @@ const ContractFlattenedVerify = ({ address, onClose, onSuccess }: Props) => { const [guid, setGuid] = useState(undefined) const [libs, setLib] = useState([]) + const versions = useEvmVersion() + const solidityCompilers = useSolidityCompiler() const isValidated = useContractVerifyStatus(guid) const addLibraryItem = () => { @@ -51,7 +55,7 @@ const ContractFlattenedVerify = ({ address, onClose, onSuccess }: Props) => { setContractName('') setHasNightlyBuild(true) setCompiler(undefined) - setEvmVersion(undefined) + setEvmVersion('default') setOptimization(true) setOptimizeRun(200) setSolidityCode('') @@ -64,8 +68,8 @@ const ContractFlattenedVerify = ({ address, onClose, onSuccess }: Props) => { 'smart_contract[address_hash]': address, 'smart_contract[name]': contractName, 'smart_contract[nightly_builds]': hasNightlyBuild, - 'smart_contract[compiler_version]': 'v0.8.4+commit.c7e474f2', // compiler, - 'smart_contract[evm_version]': 'default', // evmVersion, + 'smart_contract[compiler_version]': compiler, + 'smart_contract[evm_version]': evmVersion, 'smart_contract[optimization]': hasOptimization, 'smart_contract[optimization_runs]': optimizeRun, 'smart_contract[contract_source_code]': solidityCode, @@ -161,10 +165,7 @@ const ContractFlattenedVerify = ({ address, onClose, onSuccess }: Props) => { }, data: { currentValue: compiler, - items: [ - { label: 'Yes', value: 'yes' }, - { label: 'No', value: 'no' } - ], + items: solidityCompilers.map(v => ({ label: v, value: v })), id: 'verify-compiler', tooltip: `The compiler version is specified in pragma solidity X.X.X. Use the compiler version rather than the nightly build. If using the Solidity compiler, run solc —version to check.` } as FormSelectData @@ -180,10 +181,7 @@ const ContractFlattenedVerify = ({ address, onClose, onSuccess }: Props) => { }, data: { currentValue: evmVersion, - items: [ - { label: 'Yes', value: 'yes' }, - { label: 'No', value: 'no' } - ], + items: versions.map(v => ({ label: v, value: v })), id: 'verify-evm-version', tooltip: 'The EVM version the contract is written for. If the bytecode does not match the version, we try to verify using the latest EVM version. EVM version details.' diff --git a/components/VerifyContract/hook/useEvmVersion.ts b/components/VerifyContract/hook/useEvmVersion.ts new file mode 100644 index 00000000..13945e81 --- /dev/null +++ b/components/VerifyContract/hook/useEvmVersion.ts @@ -0,0 +1,20 @@ +import API_LIST from 'api/api_list' +import { useEffect, useState } from 'react' +import useSWRImmutable from 'swr/immutable' + +const useEvmVersion = (): string[] => { + const [evmVersions, setEvmVersions] = useState([]) + const _fetchCondition = () => { + return [API_LIST.GET_EVM_VERSION] + } + const { data } = useSWRImmutable(_fetchCondition()) + + useEffect(() => { + if (data && data?.result) { + setEvmVersions(data?.result?.versions) + } + }, [data]) + return evmVersions || [] +} + +export default useEvmVersion diff --git a/components/VerifyContract/hook/useSolidityCompiler.ts b/components/VerifyContract/hook/useSolidityCompiler.ts new file mode 100644 index 00000000..edb4c1fb --- /dev/null +++ b/components/VerifyContract/hook/useSolidityCompiler.ts @@ -0,0 +1,20 @@ +import API_LIST from 'api/api_list' +import { useEffect, useState } from 'react' +import useSWRImmutable from 'swr/immutable' + +const useSolidityCompiler = (): string[] => { + const [evmVersions, setEvmVersions] = useState([]) + const _fetchCondition = () => { + return [API_LIST.GET_SOLIDITY_COMPILER] + } + const { data } = useSWRImmutable(_fetchCondition()) + + useEffect(() => { + if (data && data?.result) { + setEvmVersions(data?.result?.versions) + } + }, [data]) + return evmVersions || [] +} + +export default useSolidityCompiler diff --git a/pages/_app.tsx b/pages/_app.tsx index 77f65c03..64af475e 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -18,8 +18,6 @@ import '../prism-theme/dark.scss' import store, { persistor } from '../store' import '../styles.css' -console.log(process.env) - dayjs.locale('en') export function reportWebVitals(metric: NextWebVitalsMetric) { diff --git a/types/address.d.ts b/types/address.d.ts index ee6571d3..db7420ba 100644 --- a/types/address.d.ts +++ b/types/address.d.ts @@ -17,7 +17,14 @@ interface AbiResponse { interface HashAbiResponse { message: string result: { - abi: any + abi: { + inputs: [] + name: string + outputs: any + stateMutability: any + type: any + } + verified: boolean } status: string } diff --git a/views/transactions/DecodeInput.tsx b/views/transactions/DecodeInput.tsx index 0ae5cf36..c45839a3 100644 --- a/views/transactions/DecodeInput.tsx +++ b/views/transactions/DecodeInput.tsx @@ -40,27 +40,24 @@ export default function DecodeInput({ dataInput, address, evmHash }: DecodeInput router.reload() } - const getAbi = async (address: string): Promise<{ abi: AbiItem[]; hasAbi: boolean }> => { - const addressAbiRes = await evmApi.get(`${API_LIST.ABI}${address}`) - if (addressAbiRes.data.message === 'OK') { - return { abi: JSON.parse(addressAbiRes?.data?.result), hasAbi: true } - } + const getAbi = async (address: string): Promise<{ abi: AbiItem[]; hasVerified: boolean }> => { // datainput from hash if (evmHash) { const hashAbiRes = await evmApi.get(`${API_LIST.HASH_ABI}${evmHash}`) + if (hashAbiRes.data.message === 'OK') { - return { abi: [hashAbiRes?.data?.result?.abi], hasAbi: false } + return { abi: [hashAbiRes?.data?.result?.abi], hasVerified: hashAbiRes?.data?.result?.verified } } } - return { abi: undefined, hasAbi: false } + return { abi: undefined, hasVerified: false } } useEffect(() => { async function data() { if (!isEmpty(dataInput)) { let items: LogElementProps[] = [] - const { abi, hasAbi } = await getAbi(address) + const { abi, hasVerified } = await getAbi(address) const item: LogElementProps = { address: address, data: '', @@ -71,8 +68,8 @@ export default function DecodeInput({ dataInput, address, evmHash }: DecodeInput items.push(item) item.methodId = evmMethodId(dataInput) - item.verified = hasAbi - item.useDraftAbiToDecode = !hasAbi && !!abi + item.verified = hasVerified + item.useDraftAbiToDecode = !hasVerified && !!abi if (Array.isArray(abi)) { abiDecoder.addABI(abi) diff --git a/views/transactions/Log.tsx b/views/transactions/Log.tsx index e8f01936..a91f61f1 100644 --- a/views/transactions/Log.tsx +++ b/views/transactions/Log.tsx @@ -4,7 +4,7 @@ import API_LIST from 'api/api_list' import { EventDecode } from 'components/Card/CardInfo/Components/Decode' import RowLoader from 'components/Loader/RowLoader' import Empty from 'components/Typography/Empty' -import { isEmpty } from 'lodash' +import { isEmpty, isUndefined } from 'lodash' import { useEffect, useState } from 'react' import { evmMethodId } from 'utils/evm' import { AbiItem } from 'web3-utils' @@ -15,30 +15,30 @@ interface AbiItemDecode extends AbiItem { type LogProps = { logs: EvmLog[] + evmHash: string display: boolean } -export default function Log({ logs, display }: LogProps) { +export default function Log({ logs, display, evmHash }: LogProps) { const [load, setLoad] = useState(false) const [items, setItems] = useState() - // no display and no load - if (!display && !load) { - return null - } - const getAbi = async (address: string): Promise => { - const res = await evmApi.get(`${API_LIST.ABI}${address}`) - if (res.data.message === 'OK') { - return JSON.parse(res?.data?.result) + if (evmHash) { + const hashAbiRes = await evmApi.get(`${API_LIST.HASH_ABI}${evmHash}`) + + if (hashAbiRes.data.message === 'OK') { + return [hashAbiRes?.data?.result?.abi] + } } + return undefined } useEffect(() => { async function data() { if (!isEmpty(logs)) { - const items: LogElementProps[] = [] + let items: LogElementProps[] = [] for (let log of logs) { const abi = await getAbi(log.address) const item: LogElementProps = { @@ -50,20 +50,24 @@ export default function Log({ logs, display }: LogProps) { item.verified = true abiDecoder.addABI(abi) const logObj = abiDecoder.decodeLogs([log])[0] as AbiItemDecode - const name = logObj.name - const interfaceItem = abi.find(item => item.name === name) - const params = interfaceItem.inputs - const call = `${interfaceItem.name}(${interfaceItem.inputs - .map(input => `${input.type} ${input.indexed ? 'indexed' : ''} ${input.name}`) - .join(', ')})` - item.call = call - for (let para of params) { - const input = logObj?.events.find(input => input.name === para.name) - if (input) { - input.indexed = para.indexed + if (!isUndefined(logObj)) { + const name = logObj.name + const interfaceItem = abi.find(item => item.name === name) + const params = interfaceItem.inputs + const call = `${interfaceItem.name}(${interfaceItem.inputs + .map(input => `${input.type} ${input.indexed ? 'indexed' : ''} ${input.name}`) + .join(', ')})` + item.call = call + for (let para of params) { + const input = logObj?.events.find(input => input.name === para.name) + if (input) { + input.indexed = para.indexed + } } + item.methodParams = logObj.events } - item.methodParams = logObj.events + } else { + items = [] } } setItems(items) @@ -72,6 +76,12 @@ export default function Log({ logs, display }: LogProps) { } data() }, [logs]) + + // no display and no load + if (!display && !load) { + return null + } + return (
{!load ? ( diff --git a/views/transactions/TransactionTabs.tsx b/views/transactions/TransactionTabs.tsx index 67083416..7971c839 100644 --- a/views/transactions/TransactionTabs.tsx +++ b/views/transactions/TransactionTabs.tsx @@ -54,7 +54,7 @@ export default function TransactionTabs({ { title: 'Raw Trace', id: 'trace' } ] const contents = { - logs: , + logs: , trace: }