From 5a41c3857de30d82da18a709d31e5282c45149e0 Mon Sep 17 00:00:00 2001 From: Fernando Date: Mon, 5 Oct 2020 12:13:19 -0300 Subject: [PATCH] (Fix) Contract interaction ABI resets (#1394) Co-authored-by: Daniel Sanchez --- .../ContractInteraction/ContractABI/index.tsx | 52 ++++++++++++++++--- .../screens/ContractInteraction/index.tsx | 4 +- .../ContractInteraction/utils/index.ts | 28 ++-------- 3 files changed, 51 insertions(+), 33 deletions(-) diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ContractABI/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ContractABI/index.tsx index fe47ee3f..57168b16 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ContractABI/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ContractABI/index.tsx @@ -1,13 +1,17 @@ import React from 'react' +import { useField, useForm } from 'react-final-form' import TextareaField from 'src/components/forms/TextareaField' +import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/components/forms/validator' import Col from 'src/components/layout/Col' import Row from 'src/components/layout/Row' +import { getNetwork } from 'src/config' +import { getConfiguredSource } from 'src/logic/contractInteraction/sources' import { extractUsefulMethods } from 'src/logic/contractInteraction/sources/ABIService' export const NO_DATA = 'no data' -const mustBeValidABI = (abi: string): undefined | string => { +const hasUsefulMethods = (abi: string): undefined | string => { try { const parsedABI = extractUsefulMethods(JSON.parse(abi)) @@ -19,12 +23,44 @@ const mustBeValidABI = (abi: string): undefined | string => { } } -const ContractABI = () => ( - - - - - -) +const ContractABI = (): React.ReactElement => { + const { + input: { value: contractAddress }, + } = useField('contractAddress', { subscription: { value: true } }) + const { mutators } = useForm() + const setAbiValue = React.useRef(mutators.setAbiValue) + + React.useEffect(() => { + const validateAndSetAbi = async () => { + const isEthereumAddress = mustBeEthereumAddress(contractAddress) === undefined + const isEthereumContractAddress = (await mustBeEthereumContractAddress(contractAddress)) === undefined + + if (isEthereumAddress && isEthereumContractAddress) { + const network = getNetwork() + const source = getConfiguredSource() + const abi = await source.getContractABI(contractAddress, network) + const isValidABI = hasUsefulMethods(abi) === undefined + + // this check may help in scenarios where the user first pastes the ABI, + // and then sets a Proxy contract that has no useful methods + if (isValidABI) { + setAbiValue.current(abi) + } + } + } + + if (contractAddress) { + validateAndSetAbi() + } + }, [contractAddress]) + + return ( + + + + + + ) +} export default ContractABI diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx index 31d28b3f..a9a305ce 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx @@ -19,7 +19,7 @@ import Header from './Header' import MethodsDropdown from './MethodsDropdown' import RenderInputParams from './RenderInputParams' import RenderOutputParams from './RenderOutputParams' -import { abiExtractor, createTxObject, formMutators, handleSubmitError, isReadMethod, ensResolver } from './utils' +import { createTxObject, formMutators, handleSubmitError, isReadMethod, ensResolver } from './utils' import { TransactionReviewType } from './Review' const useStyles = makeStyles(styles) @@ -92,7 +92,7 @@ const ContractInteraction: React.FC = ({
{ - if ( - !contractAddress || - mustBeEthereumAddress(contractAddress) || - (await mustBeEthereumContractAddress(contractAddress)) - ) { - return - } - const network = getNetwork() - const source = getConfiguredSource() - return source.getContractABI(contractAddress, network) - }, - }, -}) - export const ensResolver = createDecorator({ field: 'contractAddress', updates: { @@ -40,12 +19,12 @@ export const ensResolver = createDecorator({ if (resolvedAddress) { return resolvedAddress } + + return contractAddress } catch (e) { console.error(e.message) return contractAddress } - - return contractAddress }, }, }) @@ -71,6 +50,9 @@ export const formMutators: Record { utils.changeValue(state, 'callResults', () => args[0]) }, + setAbiValue: (args, state, utils) => { + utils.changeValue(state, 'abi', () => args[0]) + }, } export const isAddress = (type: string): boolean => type.indexOf('address') === 0