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", "react-app-rewired": "^2.1.6",
"truffle": "5.1.23", "truffle": "5.1.23",
"typescript": "~3.7.2", "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 { AbiItem } from 'web3-utils'
import { ABI, ExtendedABI } from './types'
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(',') const params = inputs.map((x) => x.type).join(',')
return `${name}(${params})` return `${name}(${params})`
} }
export const getSignatureHash = (signature) => { export const getSignatureHash = (signature: string): string => {
const web3 = getWeb3()
return web3.utils.keccak256(signature).toString() return web3.utils.keccak256(signature).toString()
} }
export const getMethodHash = (method) => { export const getMethodHash = (method: AbiItem): string => {
const signature = getMethodSignature(method) const signature = getMethodSignature(method)
return getSignatureHash(signature) return getSignatureHash(signature)
} }
export const getMethodSignatureAndSignatureHash = (method) => { export const getMethodSignatureAndSignatureHash = (
method: AbiItem,
): { methodSignature: string; signatureHash: string } => {
const methodSignature = getMethodSignature(method) const methodSignature = getMethodSignature(method)
const signatureHash = getSignatureHash(methodSignature) const signatureHash = getSignatureHash(methodSignature)
return { methodSignature, signatureHash } return { methodSignature, signatureHash }
} }
export const extractUsefulMethods = (abi: ABI): ExtendedABI => { export const extractUsefulMethods = (abi: AbiItem[]): AbiItemExtended[] => {
return abi return abi
.filter(({ constant, name, type }) => type === 'function' && !!name && typeof constant === 'boolean') .filter(({ constant, name, type }) => type === 'function' && !!name && typeof constant === 'boolean')
.map((method) => ({ .map(
(method): AbiItemExtended => ({
action: method.constant ? 'read' : 'write', action: method.constant ? 'read' : 'write',
...getMethodSignatureAndSignatureHash(method), ...getMethodSignatureAndSignatureHash(method),
...method, ...method,
})) }),
)
.sort(({ name: a }, { name: b }) => (a.toLowerCase() > b.toLowerCase() ? 1 : -1)) .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 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 classes = useStyles()
const { const {
input: { value: method }, input: { value: method },
} = useField('selectedMethod', { value: true }) } = useField('selectedMethod', { subscription: { value: true } })
const { modifiedSinceLastSubmit, submitError, submitting, valid, validating } = useFormState({ const { modifiedSinceLastSubmit, submitError, submitting, valid, validating } = useFormState({
subscription: { subscription: {
modifiedSinceLastSubmit: true, modifiedSinceLastSubmit: true,

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,11 @@
import { FORM_ERROR } from 'final-form' import { FORM_ERROR } from 'final-form'
import createDecorator from 'final-form-calculate' import createDecorator from 'final-form-calculate'
import { AbiItem } from 'web3-utils'
import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/components/forms/validator' import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/components/forms/validator'
import { getNetwork } from 'src/config' import { getNetwork } from 'src/config'
import { getConfiguredSource } from 'src/logic/contractInteraction/sources' import { getConfiguredSource } from 'src/logic/contractInteraction/sources'
import { AbiItemExtended } from 'src/logic/contractInteraction/sources/ABIService'
import { getWeb3 } from 'src/logic/wallets/getWeb3' import { getWeb3 } from 'src/logic/wallets/getWeb3'
export const NO_CONTRACT = 'no contract' export const NO_CONTRACT = 'no contract'
@ -60,7 +62,7 @@ export const handleSubmitError = (error, values) => {
return { [FORM_ERROR]: error.message } return { [FORM_ERROR]: error.message }
} }
export const createTxObject = (method, contractAddress, values) => { export const createTxObject = (method: AbiItem, contractAddress: string, values) => {
const web3 = getWeb3() const web3 = getWeb3()
const contract: any = new web3.eth.Contract([method], contractAddress) const contract: any = new web3.eth.Contract([method], contractAddress)
const { inputs, name } = method const { inputs, name } = method
@ -69,4 +71,4 @@ export const createTxObject = (method, contractAddress, values) => {
return contract.methods[name](...args) 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" underscore "1.9.1"
utf8 "3.0.0" 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" version "1.2.8"
resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.8.tgz#5321d91715cd4c0869005705a33c4c042a532b18" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.8.tgz#5321d91715cd4c0869005705a33c4c042a532b18"
integrity sha512-9SIVGFLajwlmo5joC4DGxuy2OeDkRCXVWT8JWcDQ+BayNVHyAWGvn0oGkQ0ys14Un0KK6bjjKoD0xYs4k+FaVw== integrity sha512-9SIVGFLajwlmo5joC4DGxuy2OeDkRCXVWT8JWcDQ+BayNVHyAWGvn0oGkQ0ys14Un0KK6bjjKoD0xYs4k+FaVw==