From ed995df5b77a4498711b7274c01f2b2914a40f79 Mon Sep 17 00:00:00 2001 From: fernandomg Date: Mon, 1 Jun 2020 23:38:27 -0300 Subject: [PATCH] simplify call/review buttons - unify handleSubmit - use `.call` to identify a failing tx --- .../ContractInteraction/Buttons/index.tsx | 57 +++++-------------- .../screens/ContractInteraction/index.tsx | 30 ++++++---- .../ContractInteraction/utils/index.ts | 14 +++++ 3 files changed, 46 insertions(+), 55 deletions(-) diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Buttons/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Buttons/index.tsx index 3b587995..3350981c 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Buttons/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Buttons/index.tsx @@ -5,70 +5,41 @@ import { useField, useFormState } from 'react-final-form' import Button from 'src/components/layout/Button' import Row from 'src/components/layout/Row' import { styles } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/style' -import { createTxObject } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils' +import { isReadMethod } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils' const useStyles = makeStyles(styles as any) -const Buttons = ({ onCallSubmit, onClose }) => { +const Buttons = ({ onClose }) => { const classes = useStyles() const { input: { value: method }, } = useField('selectedMethod', { value: true }) - const { - input: { value: contractAddress }, - } = useField('contractAddress', { valid: true } as any) - const { modifiedSinceLastSubmit, submitError, submitting, valid, validating, values } = useFormState({ + const { modifiedSinceLastSubmit, submitError, submitting, valid, validating } = useFormState({ subscription: { modifiedSinceLastSubmit: true, submitError: true, submitting: true, valid: true, - values: true, validating: true, }, }) - const handleCallSubmit = async () => { - const results = await createTxObject(method, contractAddress, values).call() - onCallSubmit(results) - } - return ( - {method && (method as any).action === 'read' ? ( - - ) : ( - - )} + ) } 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 de34ffc0..2c945a0d 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx @@ -1,12 +1,13 @@ import { makeStyles } from '@material-ui/core/styles' -import { FORM_ERROR } from 'final-form' import React from 'react' +import { useSelector } from 'react-redux' import { styles } from './style' import GnoForm from 'src/components/forms/GnoForm' import Block from 'src/components/layout/Block' import Hairline from 'src/components/layout/Hairline' import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo' +import { safeSelector } from 'src/routes/safe/store/selectors' import Buttons from './Buttons' import ContractABI from './ContractABI' import EthAddressInput from './EthAddressInput' @@ -17,12 +18,14 @@ import Header from './Header' import MethodsDropdown from './MethodsDropdown' import RenderInputParams from './RenderInputParams' import RenderOutputParams from './RenderOutputParams' -import { abiExtractor, createTxObject, formMutators } from './utils' +import { abiExtractor, createTxObject, formMutators, handleSubmitError, isReadMethod } from './utils' const useStyles = makeStyles(styles as any) const ContractInteraction = ({ contractAddress, initialValues, onClose, onNext }) => { const classes = useStyles() + const { address: safeAddress = '' } = useSelector(safeSelector) + let setCallResults React.useMemo(() => { if (contractAddress) { @@ -35,17 +38,18 @@ const ContractInteraction = ({ contractAddress, initialValues, onClose, onNext } try { const txObject = createTxObject(selectedMethod, contractAddress, values) const data = txObject.encodeABI() - await txObject.estimateGas() - onNext({ contractAddress, data, selectedMethod, value, ...values }) - } catch (e) { - for (const key in values) { - if (values.hasOwnProperty(key) && values[key] === e.value) { - return { [key]: e.reason } - } + const result = await txObject.call({ from: safeAddress }) + + if (isReadMethod(selectedMethod)) { + setCallResults(result) + + // this was a read method, so we won't go to the 'review' screen + return } - // .estimateGas() failed - return { [FORM_ERROR]: e.message } + onNext({ contractAddress, data, selectedMethod, value, ...values }) + } catch (error) { + return handleSubmitError(error, values) } } } @@ -62,6 +66,8 @@ const ContractInteraction = ({ contractAddress, initialValues, onClose, onNext } subscription={{ submitting: true, pristine: true }} > {(submitting, validating, rest, mutators) => { + setCallResults = mutators.setCallResults + return ( <> @@ -80,7 +86,7 @@ const ContractInteraction = ({ contractAddress, initialValues, onClose, onNext } - + ) }} diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts index 4fa20b0d..2c961591 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts @@ -1,3 +1,4 @@ +import { FORM_ERROR } from 'final-form' import createDecorator from 'final-form-calculate' import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/components/forms/validator' @@ -48,6 +49,17 @@ export const formMutators = { }, } +export const handleSubmitError = (error, values) => { + for (const key in values) { + if (values.hasOwnProperty(key) && values[key] === error.value) { + return { [key]: error.reason } + } + } + + // .call() failed and we're logging a generic error + return { [FORM_ERROR]: error.message } +} + export const createTxObject = (method, contractAddress, values) => { const web3 = getWeb3() const contract: any = new web3.eth.Contract([method], contractAddress) @@ -56,3 +68,5 @@ export const createTxObject = (method, contractAddress, values) => { return contract.methods[name](...args) } + +export const isReadMethod = (method: any) => method && method.action === 'read'