Fix value bug + preserve values when changing switch

This commit is contained in:
Mati Dastugue 2020-06-18 20:14:53 -03:00
parent 473977723b
commit 45ca501c60
5 changed files with 41 additions and 32 deletions

View File

@ -30,7 +30,7 @@ export const required = (value?: string) => {
export const mustBeInteger = (value: string) => export const mustBeInteger = (value: string) =>
!Number.isInteger(Number(value)) || value.includes('.') ? 'Must be an integer' : undefined !Number.isInteger(Number(value)) || value.includes('.') ? 'Must be an integer' : undefined
export const mustBeFloat = (value: string) => (value && Number.isNaN(Number(value)) ? 'Must be a number' : undefined) export const mustBeFloat = (value: string) => (value && Number.isNaN(Number(value)) ? 'Must be a number' : undefined)
export const greaterThan = (min: number | string) => (value: string) => { export const greaterThan = (min: number | string) => (value: string) => {
if (Number.isNaN(Number(value)) || Number.parseFloat(value) > Number(min)) { if (Number.isNaN(Number(value)) || Number.parseFloat(value) > Number(min)) {

View File

@ -59,14 +59,14 @@ const SendModal = ({ activeScreenType, isOpen, onClose, recipientAddress, select
setTx(txInfo) setTx(txInfo)
} }
const handleContractInteractionCreation = (contractInteractionInfo) => { const handleContractInteractionCreation = (contractInteractionInfo, submit) => {
setTx(contractInteractionInfo) setTx(contractInteractionInfo)
setActiveScreen('contractInteractionReview') if (submit) setActiveScreen('contractInteractionReview')
} }
const handleCustomTxCreation = (customTxInfo) => { const handleCustomTxCreation = (customTxInfo, submit) => {
setActiveScreen('reviewCustomTx')
setTx(customTxInfo) setTx(customTxInfo)
if (submit) setActiveScreen('reviewCustomTx')
} }
const handleSendCollectible = (txInfo) => { const handleSendCollectible = (txInfo) => {
@ -128,7 +128,7 @@ const SendModal = ({ activeScreenType, isOpen, onClose, recipientAddress, select
switchMethod={handleSwitchMethod} switchMethod={handleSwitchMethod}
onClose={onClose} onClose={onClose}
onNext={handleCustomTxCreation} onNext={handleCustomTxCreation}
recipientAddress={recipientAddress} contractAddress={recipientAddress}
/> />
)} )}
{activeScreen === 'reviewCustomTx' && ( {activeScreen === 'reviewCustomTx' && (

View File

@ -33,7 +33,7 @@ import { sm } from 'src/theme/variables'
type Props = { type Props = {
onClose: () => void onClose: () => void
onPrev: () => void onPrev: () => void
tx: { recipientAddress?: string; data?: string; value?: string } tx: { contractAddress?: string; data?: string; value?: string }
} }
const useStyles = makeStyles(styles) const useStyles = makeStyles(styles)
@ -52,7 +52,7 @@ const ReviewCustomTx = ({ onClose, onPrev, tx }: Props) => {
const { fromWei, toBN } = getWeb3().utils const { fromWei, toBN } = getWeb3().utils
const txData = tx.data ? tx.data.trim() : '' const txData = tx.data ? tx.data.trim() : ''
const estimatedGasCosts = await estimateTxGasCosts(safeAddress, tx.recipientAddress, txData) const estimatedGasCosts = await estimateTxGasCosts(safeAddress, tx.contractAddress, txData)
const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether')
const formattedGasCosts = formatAmount(gasCostsAsEth) const formattedGasCosts = formatAmount(gasCostsAsEth)
@ -66,11 +66,11 @@ const ReviewCustomTx = ({ onClose, onPrev, tx }: Props) => {
return () => { return () => {
isCurrent = false isCurrent = false
} }
}, [safeAddress, tx.data, tx.recipientAddress]) }, [safeAddress, tx.data, tx.contractAddress])
const submitTx = async () => { const submitTx = async () => {
const web3 = getWeb3() const web3 = getWeb3()
const txRecipient = tx.recipientAddress const txRecipient = tx.contractAddress
const txData = tx.data ? tx.data.trim() : '' const txData = tx.data ? tx.data.trim() : ''
const txValue = tx.value ? web3.utils.toWei(tx.value, 'ether') : '0' const txValue = tx.value ? web3.utils.toWei(tx.value, 'ether') : '0'
@ -118,15 +118,15 @@ const ReviewCustomTx = ({ onClose, onPrev, tx }: Props) => {
</Row> </Row>
<Row align="center" margin="md"> <Row align="center" margin="md">
<Col xs={1}> <Col xs={1}>
<Identicon address={tx.recipientAddress} diameter={32} /> <Identicon address={tx.contractAddress} diameter={32} />
</Col> </Col>
<Col layout="column" xs={11}> <Col layout="column" xs={11}>
<Block justify="left"> <Block justify="left">
<Paragraph noMargin weight="bolder"> <Paragraph noMargin weight="bolder">
{tx.recipientAddress} {tx.contractAddress}
</Paragraph> </Paragraph>
<CopyBtn content={tx.recipientAddress} /> <CopyBtn content={tx.contractAddress} />
<EtherscanBtn type="address" value={tx.recipientAddress} /> <EtherscanBtn type="address" value={tx.contractAddress} />
</Block> </Block>
</Col> </Col>
</Row> </Row>

View File

@ -19,7 +19,7 @@ import Field from 'src/components/forms/Field'
import GnoForm from 'src/components/forms/GnoForm' import GnoForm from 'src/components/forms/GnoForm'
import TextField from 'src/components/forms/TextField' import TextField from 'src/components/forms/TextField'
import TextareaField from 'src/components/forms/TextareaField' import TextareaField from 'src/components/forms/TextareaField'
import { composeValidators, maxValue, mustBeFloat } from 'src/components/forms/validator' import { composeValidators, maxValue, mustBeFloat, greaterThan } from 'src/components/forms/validator'
import Block from 'src/components/layout/Block' import Block from 'src/components/layout/Block'
import Button from 'src/components/layout/Button' import Button from 'src/components/layout/Button'
import ButtonLink from 'src/components/layout/ButtonLink' import ButtonLink from 'src/components/layout/ButtonLink'
@ -34,12 +34,12 @@ import { safeSelector } from 'src/routes/safe/store/selectors'
import { sm } from 'src/theme/variables' import { sm } from 'src/theme/variables'
type Props = { type Props = {
initialValues: { contractAddress?: string; recipientAddress?: string } initialValues: { contractAddress?: string }
onClose: () => void onClose: () => void
onNext: (any) => void onNext: (any, submit: boolean) => void
isABI: boolean isABI: boolean
switchMethod: () => void switchMethod: () => void
recipientAddress: string contractAddress: string
} }
const useStyles = makeStyles(styles) const useStyles = makeStyles(styles)
@ -48,7 +48,7 @@ const SendCustomTx: React.FC<Props> = ({
initialValues, initialValues,
onClose, onClose,
onNext, onNext,
recipientAddress, contractAddress,
switchMethod, switchMethod,
isABI, isABI,
}: Props) => { }: Props) => {
@ -56,7 +56,7 @@ const SendCustomTx: React.FC<Props> = ({
const { ethBalance } = useSelector(safeSelector) const { ethBalance } = useSelector(safeSelector)
const [qrModalOpen, setQrModalOpen] = useState<boolean>(false) const [qrModalOpen, setQrModalOpen] = useState<boolean>(false)
const [selectedEntry, setSelectedEntry] = useState<{ address?: string; name?: string } | null>({ const [selectedEntry, setSelectedEntry] = useState<{ address?: string; name?: string } | null>({
address: recipientAddress || initialValues.recipientAddress, address: contractAddress || initialValues.contractAddress,
name: '', name: '',
}) })
const [pristine, setPristine] = useState<boolean>(true) const [pristine, setPristine] = useState<boolean>(true)
@ -68,9 +68,14 @@ const SendCustomTx: React.FC<Props> = ({
} }
}, [selectedEntry, pristine]) }, [selectedEntry, pristine])
const handleSubmit = (values: any) => { const saveForm = async (values) => {
await handleSubmit(values, false)
switchMethod()
}
const handleSubmit = (values: any, submit = true) => {
if (values.data || values.value) { if (values.data || values.value) {
onNext(values) onNext(values, submit)
} }
} }
@ -87,7 +92,7 @@ const SendCustomTx: React.FC<Props> = ({
utils.changeValue(state, 'value', () => ethBalance) utils.changeValue(state, 'value', () => ethBalance)
}, },
setRecipient: (args, state, utils) => { setRecipient: (args, state, utils) => {
utils.changeValue(state, 'recipientAddress', () => args[0]) utils.changeValue(state, 'contractAddress', () => args[0])
}, },
} }
@ -106,7 +111,6 @@ const SendCustomTx: React.FC<Props> = ({
<GnoForm formMutators={formMutators} initialValues={initialValues} onSubmit={handleSubmit}> <GnoForm formMutators={formMutators} initialValues={initialValues} onSubmit={handleSubmit}>
{(...args) => { {(...args) => {
const mutators = args[3] const mutators = args[3]
let shouldDisableSubmitButton = !isValidAddress let shouldDisableSubmitButton = !isValidAddress
if (selectedEntry) { if (selectedEntry) {
shouldDisableSubmitButton = !selectedEntry.address shouldDisableSubmitButton = !selectedEntry.address
@ -228,7 +232,7 @@ const SendCustomTx: React.FC<Props> = ({
placeholder="Value*" placeholder="Value*"
text="Value*" text="Value*"
type="text" type="text"
validate={composeValidators(mustBeFloat, maxValue(ethBalance))} validate={composeValidators(mustBeFloat, maxValue(ethBalance), greaterThan(0))}
/> />
</Col> </Col>
</Row> </Row>
@ -244,7 +248,7 @@ const SendCustomTx: React.FC<Props> = ({
</Row> </Row>
<Paragraph color="disabled" noMargin size="md" style={{ letterSpacing: '-0.5px' }}> <Paragraph color="disabled" noMargin size="md" style={{ letterSpacing: '-0.5px' }}>
Use custom data (hex encoded) Use custom data (hex encoded)
<Switch checked={!isABI} onChange={switchMethod} /> <Switch onChange={() => saveForm(args[2].values)} checked={!isABI} />
</Paragraph> </Paragraph>
</Block> </Block>
<Hairline /> <Hairline />

View File

@ -37,7 +37,7 @@ export interface ContractInteractionProps {
isABI: boolean isABI: boolean
onClose: () => void onClose: () => void
switchMethod: () => void switchMethod: () => void
onNext: (tx: CreatedTx) => void onNext: (tx: CreatedTx, submit: boolean) => void
} }
const ContractInteraction: React.FC<ContractInteractionProps> = ({ const ContractInteraction: React.FC<ContractInteractionProps> = ({
@ -58,13 +58,18 @@ const ContractInteraction: React.FC<ContractInteractionProps> = ({
} }
}, [contractAddress, initialValues.contractAddress]) }, [contractAddress, initialValues.contractAddress])
const handleSubmit = async ({ contractAddress, selectedMethod, value, ...values }) => { const saveForm = async (values) => {
await handleSubmit(values, false)
switchMethod()
}
const handleSubmit = async ({ contractAddress, selectedMethod, value, ...values }, submit = true) => {
if (value || (contractAddress && selectedMethod)) { if (value || (contractAddress && selectedMethod)) {
try { try {
const txObject = createTxObject(selectedMethod, contractAddress, values) const txObject = createTxObject(selectedMethod, contractAddress, values)
const data = txObject.encodeABI() const data = txObject.encodeABI()
if (isReadMethod(selectedMethod)) { if (isReadMethod(selectedMethod) && submit) {
const result = await txObject.call({ from: safeAddress }) const result = await txObject.call({ from: safeAddress })
setCallResults(result) setCallResults(result)
@ -72,7 +77,7 @@ const ContractInteraction: React.FC<ContractInteractionProps> = ({
return return
} }
onNext({ ...values, contractAddress, data, selectedMethod, value }) onNext({ ...values, contractAddress, data, selectedMethod, value }, submit)
} catch (error) { } catch (error) {
return handleSubmitError(error, values) return handleSubmitError(error, values)
} }
@ -88,7 +93,7 @@ const ContractInteraction: React.FC<ContractInteractionProps> = ({
formMutators={formMutators} formMutators={formMutators}
initialValues={initialValues} initialValues={initialValues}
onSubmit={handleSubmit} onSubmit={handleSubmit}
subscription={{ submitting: true, pristine: true }} subscription={{ submitting: true, pristine: true, values: true }}
> >
{(submitting, validating, rest, mutators) => { {(submitting, validating, rest, mutators) => {
setCallResults = mutators.setCallResults setCallResults = mutators.setCallResults
@ -111,7 +116,7 @@ const ContractInteraction: React.FC<ContractInteractionProps> = ({
<FormErrorMessage /> <FormErrorMessage />
<Paragraph color="disabled" noMargin size="md" style={{ letterSpacing: '-0.5px' }}> <Paragraph color="disabled" noMargin size="md" style={{ letterSpacing: '-0.5px' }}>
Use custom data (hex encoded) Use custom data (hex encoded)
<Switch checked={!isABI} onChange={switchMethod} /> <Switch checked={!isABI} onChange={() => saveForm(rest.values)} />
</Paragraph> </Paragraph>
</Block> </Block>
<Hairline /> <Hairline />