add types and fix `useField` usage

This commit is contained in:
fernandomg 2020-06-03 11:43:58 -03:00
parent cd77fba5b7
commit e3a9945675
10 changed files with 41 additions and 53 deletions

View File

@ -235,6 +235,7 @@
"react-app-rewired": "^2.1.6",
"truffle": "5.1.23",
"typescript": "~3.7.2",
"wait-on": "5.0.0"
"wait-on": "5.0.0",
"web3-utils": "^1.2.8"
}
}

View File

@ -1,38 +1,48 @@
import { getWeb3 } from 'src/logic/wallets/getWeb3'
import { ABI, ExtendedABI } from './types'
import { AbiItem } from 'web3-utils'
export const getMethodSignature = ({ inputs, name }) => {
import { web3ReadOnly as web3 } from 'src/logic/wallets/getWeb3'
export interface AbiItemExtended extends AbiItem {
action: string
methodSignature: string
signatureHash: string
}
export const getMethodSignature = ({ inputs, name }: AbiItem) => {
const params = inputs.map((x) => x.type).join(',')
return `${name}(${params})`
}
export const getSignatureHash = (signature) => {
const web3 = getWeb3()
export const getSignatureHash = (signature: string): string => {
return web3.utils.keccak256(signature).toString()
}
export const getMethodHash = (method) => {
export const getMethodHash = (method: AbiItem): string => {
const signature = getMethodSignature(method)
return getSignatureHash(signature)
}
export const getMethodSignatureAndSignatureHash = (method) => {
export const getMethodSignatureAndSignatureHash = (
method: AbiItem,
): { methodSignature: string; signatureHash: string } => {
const methodSignature = getMethodSignature(method)
const signatureHash = getSignatureHash(methodSignature)
return { methodSignature, signatureHash }
}
export const extractUsefulMethods = (abi: ABI): ExtendedABI => {
export const extractUsefulMethods = (abi: AbiItem[]): AbiItemExtended[] => {
return abi
.filter(({ constant, name, type }) => type === 'function' && !!name && typeof constant === 'boolean')
.map((method) => ({
.map(
(method): AbiItemExtended => ({
action: method.constant ? 'read' : 'write',
...getMethodSignatureAndSignatureHash(method),
...method,
}))
}),
)
.sort(({ name: a }, { name: b }) => (a.toLowerCase() > b.toLowerCase() ? 1 : -1))
}
export const isPayable = (method) => {
export const isPayable = (method: AbiItem | AbiItemExtended): boolean => {
return method.payable
}

View File

@ -1,25 +0,0 @@
export interface InterfaceParams {
internalType: string
name: string
type: string
}
export interface MethodInterface {
constant: boolean
inputs: InterfaceParams[]
name: string
outputs: InterfaceParams[]
payable: boolean
stateMutability: string
type: string
}
export interface ExtendedContractInterface extends MethodInterface {
action: string
methodSignature: string
signatureHash: string
}
export type ABI = MethodInterface[]
export type ExtendedABI = ExtendedContractInterface[]

View File

@ -17,7 +17,7 @@ const Buttons = ({ onClose }: ButtonProps) => {
const classes = useStyles()
const {
input: { value: method },
} = useField('selectedMethod', { value: true })
} = useField('selectedMethod', { subscription: { value: true } })
const { modifiedSinceLastSubmit, submitError, submitting, valid, validating } = useFormState({
subscription: {
modifiedSinceLastSubmit: true,

View File

@ -25,7 +25,7 @@ const EthValue = ({ onSetMax }: EthValueProps) => {
const { ethBalance } = useSelector(safeSelector)
const {
input: { value: method },
} = useField('selectedMethod', { value: true })
} = useField('selectedMethod', { subscription: { value: true } })
const disabled = !isPayable(method)
return disabled ? null : (

View File

@ -8,6 +8,7 @@ import SearchIcon from '@material-ui/icons/Search'
import classNames from 'classnames'
import React from 'react'
import { useField, useFormState } from 'react-final-form'
import { AbiItem } from 'web3-utils'
import Col from 'src/components/layout/Col'
import Row from 'src/components/layout/Row'
@ -16,12 +17,11 @@ import CheckIcon from 'src/routes/safe/components/CurrencyDropdown/img/check.svg
import { useDropdownStyles } from 'src/routes/safe/components/CurrencyDropdown/style'
import { DropdownListTheme } from 'src/theme/mui'
import { extractUsefulMethods } from 'src/logic/contractInteraction/sources/ABIService'
import { MethodInterface } from 'src/logic/contractInteraction/sources/ABIService/types'
const MENU_WIDTH = '452px'
interface MethodsDropdownProps {
onChange: (method: MethodInterface) => void
onChange: (method: AbiItem) => void
}
const MethodsDropdown = ({ onChange }: MethodsDropdownProps) => {
@ -29,7 +29,7 @@ const MethodsDropdown = ({ onChange }: MethodsDropdownProps) => {
const {
input: { value: abi },
meta: { valid },
} = useField('abi', { value: true, valid: true } as any)
} = useField('abi', { subscription: { value: true, valid: true } })
const {
initialValues: { selectedMethod: selectedMethodByDefault },
} = useFormState({ subscription: { initialValues: true } })
@ -61,7 +61,7 @@ const MethodsDropdown = ({ onChange }: MethodsDropdownProps) => {
setAnchorEl(null)
}
const onMethodSelectedChanged = (chosenMethod: MethodInterface) => {
const onMethodSelectedChanged = (chosenMethod: AbiItem) => {
setSelectedMethod(chosenMethod)
onChange(chosenMethod)
handleClose()

View File

@ -10,10 +10,10 @@ import Row from 'src/components/layout/Row'
const RenderInputParams = () => {
const {
meta: { valid: validABI },
} = useField('abi', { value: true })
} = useField('abi', { subscription: { valid: true, value: true } })
const {
input: { value: method },
}: any = useField('selectedMethod', { value: true })
}: any = useField('selectedMethod', { subscription: { value: true } })
const renderInputs = validABI && !!method && method.inputs.length
return !renderInputs

View File

@ -9,10 +9,10 @@ import Row from 'src/components/layout/Row'
const RenderOutputParams = () => {
const {
input: { value: method },
}: any = useField('selectedMethod', { value: true })
}: any = useField('selectedMethod', { subscription: { value: true } })
const {
input: { value: results },
}: any = useField('callResults', { value: true })
}: any = useField('callResults', { subscription: { value: true } })
const multipleResults = !!method && method.outputs.length > 1
return results ? (

View File

@ -1,9 +1,11 @@
import { FORM_ERROR } from 'final-form'
import createDecorator from 'final-form-calculate'
import { AbiItem } from 'web3-utils'
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 { getWeb3 } from 'src/logic/wallets/getWeb3'
export const NO_CONTRACT = 'no contract'
@ -60,7 +62,7 @@ export const handleSubmitError = (error, values) => {
return { [FORM_ERROR]: error.message }
}
export const createTxObject = (method, contractAddress, values) => {
export const createTxObject = (method: AbiItem, contractAddress: string, values) => {
const web3 = getWeb3()
const contract: any = new web3.eth.Contract([method], contractAddress)
const { inputs, name } = method
@ -69,4 +71,4 @@ export const createTxObject = (method, contractAddress, values) => {
return contract.methods[name](...args)
}
export const isReadMethod = (method: any) => method && method.action === 'read'
export const isReadMethod = (method: AbiItemExtended): boolean => method && method.action === 'read'

View File

@ -17146,7 +17146,7 @@ web3-utils@1.2.1:
underscore "1.9.1"
utf8 "3.0.0"
web3-utils@1.2.8, web3-utils@^1.2.7:
web3-utils@1.2.8, web3-utils@^1.2.7, web3-utils@^1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.8.tgz#5321d91715cd4c0869005705a33c4c042a532b18"
integrity sha512-9SIVGFLajwlmo5joC4DGxuy2OeDkRCXVWT8JWcDQ+BayNVHyAWGvn0oGkQ0ys14Un0KK6bjjKoD0xYs4k+FaVw==