Removing daily limit from open route
This commit is contained in:
parent
78618b5a26
commit
471417da0b
|
@ -1,57 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from 'react'
|
|
||||||
import CircularProgress from '@material-ui/core/CircularProgress'
|
|
||||||
import Block from '~/components/layout/Block'
|
|
||||||
import Bold from '~/components/layout/Bold'
|
|
||||||
import Col from '~/components/layout/Col'
|
|
||||||
import OpenPaper from '~/components/Stepper/OpenPaper'
|
|
||||||
import Paragraph from '~/components/layout/Paragraph'
|
|
||||||
import Pre from '~/components/layout/Pre'
|
|
||||||
import Row from '~/components/layout/Row'
|
|
||||||
|
|
||||||
type FormProps = {
|
|
||||||
submitting: boolean,
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
address: string,
|
|
||||||
tx: Object,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DEPLOYED_COMPONENT_ID = 'deployedSafeComponent'
|
|
||||||
|
|
||||||
const Deployment = ({ address, tx }: Props) => (
|
|
||||||
<Block className={DEPLOYED_COMPONENT_ID}>
|
|
||||||
<Paragraph><Bold>Deployed safe to: </Bold>{address}</Paragraph>
|
|
||||||
<Pre>
|
|
||||||
{JSON.stringify(tx, null, 2) }
|
|
||||||
</Pre>
|
|
||||||
</Block>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default ({ address, tx }: Props) => (controls: React$Node, { submitting }: FormProps) => {
|
|
||||||
const txFinished = !!address
|
|
||||||
|
|
||||||
return (
|
|
||||||
<OpenPaper controls={controls}>
|
|
||||||
{ !txFinished &&
|
|
||||||
<React.Fragment>
|
|
||||||
<Paragraph align="center" size="lg">
|
|
||||||
You are about to create a Safe for keeping your funds more secure.
|
|
||||||
</Paragraph>
|
|
||||||
<Paragraph align="center" size="lg">
|
|
||||||
Remember to check you have enough funds in your wallet.
|
|
||||||
</Paragraph>
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
|
||||||
<Row>
|
|
||||||
<Col xs={12} center={submitting ? 'xs' : undefined} margin="lg">
|
|
||||||
{ submitting
|
|
||||||
? <CircularProgress size={50} />
|
|
||||||
: txFinished && <Deployment address={address} tx={tx} />
|
|
||||||
}
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</OpenPaper>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from 'react'
|
|
||||||
import Field from '~/components/forms/Field'
|
|
||||||
import TextField from '~/components/forms/TextField'
|
|
||||||
import { composeValidators, minValue, mustBeInteger, required } from '~/components/forms/validator'
|
|
||||||
import Block from '~/components/layout/Block'
|
|
||||||
import { FIELD_CONFIRMATIONS } from '~/routes/open/components/fields'
|
|
||||||
|
|
||||||
const Confirmations = () => (
|
|
||||||
<Block margin="md">
|
|
||||||
<Field
|
|
||||||
name={FIELD_CONFIRMATIONS}
|
|
||||||
component={TextField}
|
|
||||||
type="text"
|
|
||||||
validate={composeValidators(
|
|
||||||
required,
|
|
||||||
mustBeInteger,
|
|
||||||
minValue(1),
|
|
||||||
)}
|
|
||||||
placeholder="Required confirmations*"
|
|
||||||
text="Required confirmations"
|
|
||||||
/>
|
|
||||||
</Block>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default Confirmations
|
|
|
@ -1,74 +0,0 @@
|
||||||
// @flow
|
|
||||||
import TextField from '~/components/forms/TextField'
|
|
||||||
import * as React from 'react'
|
|
||||||
import * as TestUtils from 'react-dom/test-utils'
|
|
||||||
import Layout from '~/routes/open/components/Layout'
|
|
||||||
import { FIELD_CONFIRMATIONS, FIELD_OWNERS } from '~/routes/open/components/fields'
|
|
||||||
import { getProviderInfo } from '~/logic/wallets/getWeb3'
|
|
||||||
import Wrapper from '~/test/utils/Wrapper'
|
|
||||||
import { CONFIRMATIONS_ERROR } from '~/routes/open/components/SafeForm'
|
|
||||||
|
|
||||||
const onSubmitMock = async (): Promise<void> => {}
|
|
||||||
|
|
||||||
describe('React DOM TESTS > Create Safe form', () => {
|
|
||||||
let open
|
|
||||||
let fieldOwners
|
|
||||||
let fieldConfirmations
|
|
||||||
beforeEach(async () => {
|
|
||||||
// init app web3 instance
|
|
||||||
await getProviderInfo()
|
|
||||||
|
|
||||||
open = TestUtils.renderIntoDocument((
|
|
||||||
<Wrapper>
|
|
||||||
<Layout
|
|
||||||
network="rinkeby"
|
|
||||||
provider="METAMASK"
|
|
||||||
userAccount="foo"
|
|
||||||
safeAddress=""
|
|
||||||
safeTx=""
|
|
||||||
onCallSafeContractSubmit={onSubmitMock}
|
|
||||||
/>
|
|
||||||
</Wrapper>
|
|
||||||
))
|
|
||||||
|
|
||||||
const inputs = TestUtils.scryRenderedDOMComponentsWithTag(open, 'input')
|
|
||||||
const indexOwners = 1
|
|
||||||
const indexConfirmations = 2
|
|
||||||
fieldOwners = inputs[indexOwners]
|
|
||||||
fieldConfirmations = inputs[indexConfirmations]
|
|
||||||
|
|
||||||
expect(fieldOwners.name).toEqual(FIELD_OWNERS)
|
|
||||||
expect(fieldConfirmations.name).toEqual(FIELD_CONFIRMATIONS)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not allow to continue if confirmations are higher than owners', async () => {
|
|
||||||
// GIVEN
|
|
||||||
TestUtils.Simulate.change(fieldOwners, { target: { value: '1' } })
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
TestUtils.Simulate.change(fieldConfirmations, { target: { value: '2' } })
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
const muiFields = TestUtils.scryRenderedComponentsWithType(open, TextField)
|
|
||||||
expect(6).toEqual(muiFields.length)
|
|
||||||
const confirmationsField = muiFields[4]
|
|
||||||
|
|
||||||
expect(confirmationsField.props.meta.valid).toBe(false)
|
|
||||||
expect(confirmationsField.props.meta.error).toBe(CONFIRMATIONS_ERROR)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should raise error when confirmations are 012 and number of owners are 2', async () => {
|
|
||||||
// GIVEN
|
|
||||||
TestUtils.Simulate.change(fieldOwners, { target: { value: '2' } })
|
|
||||||
// WHEN
|
|
||||||
TestUtils.Simulate.change(fieldConfirmations, { target: { value: '014' } })
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
const muiFields = TestUtils.scryRenderedComponentsWithType(open, TextField)
|
|
||||||
expect(8).toEqual(muiFields.length)
|
|
||||||
const confirmationsField = muiFields[6]
|
|
||||||
|
|
||||||
expect(confirmationsField.props.meta.valid).toBe(false)
|
|
||||||
expect(confirmationsField.props.meta.error).toBe(CONFIRMATIONS_ERROR)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,22 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from 'react'
|
|
||||||
import Field from '~/components/forms/Field'
|
|
||||||
import TextField from '~/components/forms/TextField'
|
|
||||||
import { composeValidators, mustBeFloat, required, minValue } from '~/components/forms/validator'
|
|
||||||
import Block from '~/components/layout/Block'
|
|
||||||
import { FIELD_DAILY_LIMIT } from '~/routes/open/components/fields'
|
|
||||||
|
|
||||||
const DailyLimit = () => (
|
|
||||||
<Block margin="md">
|
|
||||||
<Field
|
|
||||||
name={FIELD_DAILY_LIMIT}
|
|
||||||
component={TextField}
|
|
||||||
type="text"
|
|
||||||
validate={composeValidators(required, mustBeFloat, minValue(0))}
|
|
||||||
placeholder="Daily Limit*"
|
|
||||||
text="Daily Limit"
|
|
||||||
/>
|
|
||||||
</Block>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default DailyLimit
|
|
|
@ -1,84 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from 'react'
|
|
||||||
import Field from '~/components/forms/Field'
|
|
||||||
import TextField from '~/components/forms/TextField'
|
|
||||||
import {
|
|
||||||
composeValidators,
|
|
||||||
minValue,
|
|
||||||
maxValue,
|
|
||||||
mustBeInteger,
|
|
||||||
mustBeEthereumAddress,
|
|
||||||
required,
|
|
||||||
uniqueAddress,
|
|
||||||
} from '~/components/forms/validator'
|
|
||||||
import Block from '~/components/layout/Block'
|
|
||||||
import Col from '~/components/layout/Col'
|
|
||||||
import Heading from '~/components/layout/Heading'
|
|
||||||
import Row from '~/components/layout/Row'
|
|
||||||
import Paragraph from '~/components/layout/Paragraph'
|
|
||||||
import { FIELD_OWNERS, getOwnerNameBy, getOwnerAddressBy } from '~/routes/open/components/fields'
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
numOwners: number,
|
|
||||||
otherAccounts: string[],
|
|
||||||
}
|
|
||||||
|
|
||||||
const MAX_NUMBER_OWNERS = 50
|
|
||||||
|
|
||||||
const getAddressValidators = (addresses: string[], position: number) => {
|
|
||||||
const copy = addresses.slice()
|
|
||||||
copy.splice(position, 1)
|
|
||||||
|
|
||||||
return composeValidators(required, mustBeEthereumAddress, uniqueAddress(copy))
|
|
||||||
}
|
|
||||||
|
|
||||||
const Owners = (props: Props) => {
|
|
||||||
const { numOwners, otherAccounts } = props
|
|
||||||
const validNumber = numOwners && Number.isInteger(Number(numOwners))
|
|
||||||
const renderOwners = validNumber && Number(numOwners) <= MAX_NUMBER_OWNERS
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Block margin="md">
|
|
||||||
<Heading tag="h3">Owners</Heading>
|
|
||||||
<Block margin="sm">
|
|
||||||
<Field
|
|
||||||
name={FIELD_OWNERS}
|
|
||||||
component={TextField}
|
|
||||||
type="text"
|
|
||||||
validate={composeValidators(required, mustBeInteger, maxValue(MAX_NUMBER_OWNERS), minValue(1))}
|
|
||||||
placeholder="Number of owners*"
|
|
||||||
text="Number of owners"
|
|
||||||
/>
|
|
||||||
</Block>
|
|
||||||
{ renderOwners && [...Array(Number(numOwners))].map((x, index) => (
|
|
||||||
<Row key={`owner${(index)}`}>
|
|
||||||
<Col xs={11} xsOffset={1} layout="column" margin="md">
|
|
||||||
<Paragraph weight="bold">Owner Nº {index + 1}</Paragraph>
|
|
||||||
<Block margin="sm">
|
|
||||||
<Field
|
|
||||||
name={getOwnerNameBy(index)}
|
|
||||||
component={TextField}
|
|
||||||
type="text"
|
|
||||||
validate={required}
|
|
||||||
placeholder="Owner Name*"
|
|
||||||
text="Owner Name"
|
|
||||||
/>
|
|
||||||
</Block>
|
|
||||||
<Block margin="sm">
|
|
||||||
<Field
|
|
||||||
name={getOwnerAddressBy(index)}
|
|
||||||
component={TextField}
|
|
||||||
type="text"
|
|
||||||
validate={getAddressValidators(otherAccounts, index)}
|
|
||||||
placeholder="Owner Address*"
|
|
||||||
text="Owner Address"
|
|
||||||
/>
|
|
||||||
</Block>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
)) }
|
|
||||||
</Block>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Owners
|
|
|
@ -1,61 +0,0 @@
|
||||||
// @flow
|
|
||||||
import TextField from '~/components/forms/TextField'
|
|
||||||
import * as React from 'react'
|
|
||||||
import * as TestUtils from 'react-dom/test-utils'
|
|
||||||
import GnoForm from '~/components/forms/GnoForm'
|
|
||||||
import { FIELD_OWNERS } from '~/routes/open/components/fields'
|
|
||||||
import { getAccountsFrom } from '~/routes/open/utils/safeDataExtractor'
|
|
||||||
import { getProviderInfo } from '~/logic/wallets/getWeb3'
|
|
||||||
import Wrapper from '~/test/utils/Wrapper'
|
|
||||||
import { ADDRESS_REPEATED_ERROR } from '~/components/forms/validator'
|
|
||||||
import Owners from './index'
|
|
||||||
|
|
||||||
const onSubmitMock = () => {}
|
|
||||||
const childrenMock = () => {}
|
|
||||||
|
|
||||||
describe('React DOM TESTS > Create Safe form', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
// init app web3 instance
|
|
||||||
await getProviderInfo()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not allow to continue if owners addresses are duplicated', async () => {
|
|
||||||
// GIVEN
|
|
||||||
const open = TestUtils.renderIntoDocument((
|
|
||||||
<Wrapper>
|
|
||||||
<GnoForm
|
|
||||||
onSubmit={onSubmitMock}
|
|
||||||
padding={15}
|
|
||||||
render={({ values }) => (
|
|
||||||
<Owners
|
|
||||||
numOwners={values.owners}
|
|
||||||
otherAccounts={getAccountsFrom(values)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{childrenMock}
|
|
||||||
</GnoForm>
|
|
||||||
</Wrapper>
|
|
||||||
))
|
|
||||||
|
|
||||||
let inputs = TestUtils.scryRenderedDOMComponentsWithTag(open, 'input')
|
|
||||||
const fieldOwners = inputs[0]
|
|
||||||
expect(fieldOwners.name).toEqual(FIELD_OWNERS)
|
|
||||||
TestUtils.Simulate.change(fieldOwners, { target: { value: '2' } })
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
inputs = TestUtils.scryRenderedDOMComponentsWithTag(open, 'input')
|
|
||||||
const firstOwnerAddress = inputs[2]
|
|
||||||
TestUtils.Simulate.change(firstOwnerAddress, { target: { value: '0xC21aC257Db500a87c65Daa980432F216A719bA30' } })
|
|
||||||
const secondOwnerAddress = inputs[4]
|
|
||||||
TestUtils.Simulate.change(secondOwnerAddress, { target: { value: '0xC21aC257Db500a87c65Daa980432F216A719bA30' } })
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
const muiFields = TestUtils.scryRenderedComponentsWithType(open, TextField)
|
|
||||||
expect(5).toEqual(muiFields.length)
|
|
||||||
const secondAddressField = muiFields[4]
|
|
||||||
|
|
||||||
expect(secondAddressField.props.meta.valid).toBe(false)
|
|
||||||
expect(secondAddressField.props.meta.error).toBe(ADDRESS_REPEATED_ERROR)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,29 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from 'react'
|
|
||||||
import OpenPaper from '~/components/Stepper/OpenPaper'
|
|
||||||
import { getAccountsFrom } from '~/routes/open/utils/safeDataExtractor'
|
|
||||||
import Owners from './Owners'
|
|
||||||
import Confirmations from './Confirmations'
|
|
||||||
import DailyLimit from './DailyLimit'
|
|
||||||
|
|
||||||
export const CONFIRMATIONS_ERROR = 'Number of confirmations can not be higher than the number of owners'
|
|
||||||
|
|
||||||
export const safeFieldsValidation = (values: Object) => {
|
|
||||||
const errors = {}
|
|
||||||
|
|
||||||
if (Number.parseInt(values.owners, 10) < Number.parseInt(values.confirmations, 10)) {
|
|
||||||
errors.confirmations = CONFIRMATIONS_ERROR
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors
|
|
||||||
}
|
|
||||||
|
|
||||||
const SafeRestPage = () => (controls: React$Node, { values }: Object) => (
|
|
||||||
<OpenPaper controls={controls}>
|
|
||||||
<Owners numOwners={values.owners} otherAccounts={getAccountsFrom(values)} />
|
|
||||||
<Confirmations />
|
|
||||||
<DailyLimit />
|
|
||||||
</OpenPaper>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default SafeRestPage
|
|
|
@ -1,6 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
export const getDailyLimitFrom = (values: Object): number => Number(values.limit)
|
|
||||||
|
|
||||||
export const getAccountsFrom = (values: Object): string[] => {
|
export const getAccountsFrom = (values: Object): string[] => {
|
||||||
const accounts = Object.keys(values).sort().filter(key => /^owner\d+Address$/.test(key))
|
const accounts = Object.keys(values).sort().filter(key => /^owner\d+Address$/.test(key))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue