send tx for changing threshold, validation wip

This commit is contained in:
mmv 2019-06-18 16:25:55 +04:00
parent 8ec1d6f528
commit 72c8611cc5
6 changed files with 118 additions and 72 deletions

View File

@ -124,7 +124,6 @@
"postcss-simple-vars": "^5.0.2", "postcss-simple-vars": "^5.0.2",
"pre-commit": "^1.2.2", "pre-commit": "^1.2.2",
"prettier-eslint-cli": "5.0.0", "prettier-eslint-cli": "5.0.0",
"react-testing-library": "8.0.1",
"run-with-testrpc": "0.3.1", "run-with-testrpc": "0.3.1",
"storybook-host": "^5.0.3", "storybook-host": "^5.0.3",
"storybook-router": "^0.3.3", "storybook-router": "^0.3.3",

View File

@ -70,4 +70,12 @@ export const inLimit = (limit: number, base: number, baseText: string, symbol: s
return `Should not exceed ${max} ${symbol} (amount to reach ${baseText})` return `Should not exceed ${max} ${symbol} (amount to reach ${baseText})`
} }
export const differentFrom = (diffValue: string) => (value: string) => {
if (value === diffValue.toString()) {
return `Value should be different than ${value}`
}
return undefined
}
export const noErrorsOn = (name: string, errors: Object) => errors[name] === undefined export const noErrorsOn = (name: string, errors: Object) => errors[name] === undefined

View File

@ -7,7 +7,7 @@ import IconButton from '@material-ui/core/IconButton'
import SelectField from '~/components/forms/SelectField' import SelectField from '~/components/forms/SelectField'
import MenuItem from '@material-ui/core/MenuItem' import MenuItem from '@material-ui/core/MenuItem'
import { import {
composeValidators, minValue, mustBeInteger, required, composeValidators, minValue, mustBeInteger, required, differentFrom,
} from '~/components/forms/validator' } from '~/components/forms/validator'
import Field from '~/components/forms/Field' import Field from '~/components/forms/Field'
import GnoForm from '~/components/forms/GnoForm' import GnoForm from '~/components/forms/GnoForm'
@ -33,10 +33,11 @@ const THRESHOLD_FIELD_NAME = 'threshold'
const ChangeThreshold = ({ const ChangeThreshold = ({
onClose, owners, threshold, classes, onChangeThreshold, onClose, owners, threshold, classes, onChangeThreshold,
}: Props) => { }: Props) => {
const handleSubmit = (values) => { const handleSubmit = async (values) => {
const newThreshold = values[THRESHOLD_FIELD_NAME] const newThreshold = values[THRESHOLD_FIELD_NAME]
onChangeThreshold(newThreshold) await onChangeThreshold(newThreshold)
onClose()
} }
return ( return (
@ -50,10 +51,10 @@ const ChangeThreshold = ({
</IconButton> </IconButton>
</Row> </Row>
<Hairline /> <Hairline />
<Block className={classes.modalContent}> <GnoForm onSubmit={handleSubmit} initialValues={{ threshold: threshold.toString() }}>
<GnoForm onSubmit={handleSubmit} initialValues={{ threshold: threshold.toString() }}> {() => (
{() => ( <React.Fragment>
<React.Fragment> <Block className={classes.modalContent}>
<Row> <Row>
<Paragraph> <Paragraph>
Every transaction outside any specified daily limits, needs to be confirmed by all specified owners. Every transaction outside any specified daily limits, needs to be confirmed by all specified owners.
@ -70,7 +71,7 @@ const ChangeThreshold = ({
<Field <Field
name={THRESHOLD_FIELD_NAME} name={THRESHOLD_FIELD_NAME}
component={SelectField} component={SelectField}
validate={composeValidators(required, mustBeInteger, minValue(1))} validate={composeValidators(required, mustBeInteger, minValue(1), differentFrom(threshold))}
data-testid="threshold-select-input" data-testid="threshold-select-input"
> >
{[...Array(Number(owners.size))].map((x, index) => ( {[...Array(Number(owners.size))].map((x, index) => (
@ -90,19 +91,19 @@ owner(s)
</Paragraph> </Paragraph>
</Col> </Col>
</Row> </Row>
</React.Fragment> </Block>
)} <Hairline style={{ position: 'absolute', bottom: 85 }} />
</GnoForm> <Row align="center" className={classes.buttonRow}>
</Block> <Button className={classes.button} minWidth={140} onClick={onClose}>
<Hairline style={{ position: 'absolute', bottom: 85 }} /> BACK
<Row align="center" className={classes.buttonRow}> </Button>
<Button className={classes.button} minWidth={140} onClick={onClose}> <Button type="submit" color="primary" className={classes.button} minWidth={140} variant="contained">
BACK CHANGE
</Button> </Button>
<Button color="primary" className={classes.button} minWidth={140} onClick={onClose} variant="contained"> </Row>
CHANGE </React.Fragment>
</Button> )}
</Row> </GnoForm>
</React.Fragment> </React.Fragment>
) )
} }

View File

@ -2,6 +2,7 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import { withStyles } from '@material-ui/core/styles' import { withStyles } from '@material-ui/core/styles'
import { List } from 'immutable' import { List } from 'immutable'
import { SharedSnackbarConsumer } from '~/components/SharedSnackBar'
import Heading from '~/components/layout/Heading' import Heading from '~/components/layout/Heading'
import Button from '~/components/layout/Button' import Button from '~/components/layout/Button'
import Bold from '~/components/layout/Bold' import Bold from '~/components/layout/Bold'
@ -32,56 +33,65 @@ const ThresholdSettings = ({
setModalOpen(prevOpen => !prevOpen) setModalOpen(prevOpen => !prevOpen)
} }
const onChangeThreshold = async (newThreshold) => {
const safeInstance = await getGnosisSafeInstanceAt(safeAddress)
const data = safeInstance.contract.changeThreshold(newThreshold).encodeABI()
createTransaction(safeInstance, safeAddress, 0, ZERO_ADDRESS)
}
return ( return (
<React.Fragment> <React.Fragment>
<Block className={classes.container}> <SharedSnackbarConsumer>
<Heading tag="h3">Required confirmations</Heading> {({ openSnackbar }) => {
<Paragraph> const onChangeThreshold = async (newThreshold) => {
Any transaction over any daily limit const safeInstance = await getGnosisSafeInstanceAt(safeAddress)
<br /> const txData = safeInstance.contract.methods.changeThreshold(newThreshold).encodeABI()
{' '}
requires the confirmation of: createTransaction(safeAddress, safeAddress, 0, txData, openSnackbar)
</Paragraph> }
<Paragraph size="xxl" className={classes.ownersText}>
<Bold>{threshold}</Bold> return (
{' '} <>
out of <Block className={classes.container}>
<Bold>{owners.size}</Bold> <Heading tag="h3">Required confirmations</Heading>
{' '} <Paragraph>
owners Any transaction over any daily limit
</Paragraph> <br />
<Row align="center" className={classes.buttonRow}> {' '}
<Button requires the confirmation of:
color="primary" </Paragraph>
minWidth={120} <Paragraph size="xxl" className={classes.ownersText}>
className={classes.modifyBtn} <Bold>{threshold}</Bold>
onClick={toggleModal} {' '}
variant="contained" out of
> {' '}
Modify <Bold>{owners.size}</Bold>
</Button> {' '}
</Row> owners
</Block> </Paragraph>
<Modal <Row align="center" className={classes.buttonRow}>
title="Change Required Confirmations" <Button
description="Change Required Confirmations Form" color="primary"
handleClose={toggleModal} minWidth={120}
open={isModalOpen} className={classes.modifyBtn}
> onClick={toggleModal}
<ChangeThreshold variant="contained"
onClose={toggleModal} >
owners={owners} Modify
threshold={threshold} </Button>
onChangeThreshold={onChangeThreshold} </Row>
/> </Block>
</Modal> <Modal
title="Change Required Confirmations"
description="Change Required Confirmations Form"
handleClose={toggleModal}
open={isModalOpen}
>
<ChangeThreshold
onClose={toggleModal}
owners={owners}
threshold={threshold}
onChangeThreshold={onChangeThreshold}
/>
</Modal>
</>
)
}}
</SharedSnackbarConsumer>
</React.Fragment> </React.Fragment>
) )
} }

View File

@ -25,7 +25,6 @@ const createTransaction = (
const nonce = await safeInstance.nonce() const nonce = await safeInstance.nonce()
const isExecution = threshold.toNumber() === 1 const isExecution = threshold.toNumber() === 1
let txHash let txHash
if (isExecution) { if (isExecution) {
openSnackbar('Transaction has been submitted', 'success') openSnackbar('Transaction has been submitted', 'success')

View File

@ -1613,6 +1613,11 @@
dependencies: dependencies:
uuid "^3.1.0" uuid "^3.1.0"
"@sheerun/mutationobserver-shim@^0.3.2":
version "0.3.2"
resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b"
integrity sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q==
"@storybook/addon-actions@5.1.8": "@storybook/addon-actions@5.1.8":
version "5.1.8" version "5.1.8"
resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.1.8.tgz#98d6aff42fb7fa7477b4db6cf21da3ede18ede0d" resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.1.8.tgz#98d6aff42fb7fa7477b4db6cf21da3ede18ede0d"
@ -2081,6 +2086,25 @@
"@svgr/plugin-svgo" "^4.2.0" "@svgr/plugin-svgo" "^4.2.0"
loader-utils "^1.2.3" loader-utils "^1.2.3"
"@testing-library/dom@^5.0.0":
version "5.2.0"
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-5.2.0.tgz#450bd09f93ddd8865eec98fc5e81fceb2bccdf9c"
integrity sha512-nFaZes/bzDfMqwZpQXdiPyj3WXU16FYf5k5NCFu/qJM4JdRJLHEtSRYtrETmk7nCf+qLVoHCqRduGi/4KE83Gw==
dependencies:
"@babel/runtime" "^7.4.5"
"@sheerun/mutationobserver-shim" "^0.3.2"
aria-query "3.0.0"
pretty-format "^24.8.0"
wait-for-expect "^1.2.0"
"@testing-library/react@^8.0.1":
version "8.0.1"
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-8.0.1.tgz#91c254adf855b13de50020613cb5d3915f9f7875"
integrity sha512-N/1pJfhEnNYkGyxuw4xbp03evaS0z/CT8o0QgTfJqGlukAcU15xf9uU1w03NHKZJcU69nOCBAoAkXHtHzYwMbg==
dependencies:
"@babel/runtime" "^7.4.5"
"@testing-library/dom" "^5.0.0"
"@types/babel__core@^7.1.0": "@types/babel__core@^7.1.0":
version "7.1.2" version "7.1.2"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.2.tgz#608c74f55928033fce18b99b213c16be4b3d114f" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.2.tgz#608c74f55928033fce18b99b213c16be4b3d114f"
@ -2729,7 +2753,7 @@ argparse@^1.0.7:
dependencies: dependencies:
sprintf-js "~1.0.2" sprintf-js "~1.0.2"
aria-query@^3.0.0: aria-query@3.0.0, aria-query@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc"
integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w= integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=
@ -16760,6 +16784,11 @@ w3c-hr-time@^1.0.1:
dependencies: dependencies:
browser-process-hrtime "^0.1.2" browser-process-hrtime "^0.1.2"
wait-for-expect@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-1.2.0.tgz#fdab6a26e87d2039101db88bff3d8158e5c3e13f"
integrity sha512-EJhKpA+5UHixduMBEGhTFuLuVgQBKWxkFbefOdj2bbk2/OpA5Opsc4aUTGmF+qJ+v3kTGxDRNYwKaT4j6g5n8Q==
walker@^1.0.7, walker@~1.0.5: walker@^1.0.7, walker@~1.0.5:
version "1.0.7" version "1.0.7"
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"