(Fix) Contract interaction ABI resets (#1394)
Co-authored-by: Daniel Sanchez <daniel.sanchez@gnosis.pm>
This commit is contained in:
parent
21ea1ad9dd
commit
5a41c3857d
|
@ -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 (
|
||||
<Row margin="sm">
|
||||
<Col>
|
||||
<TextareaField name="abi" placeholder="ABI*" text="ABI*" type="text" validate={mustBeValidABI} />
|
||||
<TextareaField name="abi" placeholder="ABI*" text="ABI*" type="text" validate={hasUsefulMethods} />
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
|
||||
export default ContractABI
|
||||
|
|
|
@ -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<ContractInteractionProps> = ({
|
|||
<Header onClose={onClose} subTitle="1 of 2" title="Contract Interaction" />
|
||||
<Hairline />
|
||||
<GnoForm
|
||||
decorators={[abiExtractor, ensResolver]}
|
||||
decorators={[ensResolver]}
|
||||
formMutators={formMutators}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
|
|
|
@ -2,9 +2,6 @@ import { FORM_ERROR, Mutator, SubmissionErrors } from 'final-form'
|
|||
import createDecorator from 'final-form-calculate'
|
||||
import { ContractSendMethod } from 'web3-eth-contract'
|
||||
|
||||
import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/components/forms/validator'
|
||||
import { getNetwork } from 'src/config'
|
||||
import { getConfiguredSource } from 'src/logic/contractInteraction/sources'
|
||||
import { AbiItemExtended } from 'src/logic/contractInteraction/sources/ABIService'
|
||||
import { getAddressFromENS, getWeb3 } from 'src/logic/wallets/getWeb3'
|
||||
import { TransactionReviewType } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review'
|
||||
|
@ -12,24 +9,6 @@ import { isValidEnsName } from 'src/logic/wallets/ethAddresses'
|
|||
|
||||
export const NO_CONTRACT = 'no contract'
|
||||
|
||||
export const abiExtractor = createDecorator({
|
||||
field: 'contractAddress',
|
||||
updates: {
|
||||
abi: async (contractAddress) => {
|
||||
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<string, Mutator<{ selectedMethod: { name: stri
|
|||
setCallResults: (args, state, utils) => {
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue