add types and fix `useField` usage
This commit is contained in:
parent
cd77fba5b7
commit
e3a9945675
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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[]
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 : (
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 ? (
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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==
|
||||||
|
|
Loading…
Reference in New Issue