WA-232 Add Token component
This commit is contained in:
parent
bca38c8c07
commit
c86aee108c
|
@ -0,0 +1,17 @@
|
|||
// @flow
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import * as React from 'react'
|
||||
import { List } from 'immutable'
|
||||
import styles from '~/components/layout/PageFrame/index.scss'
|
||||
import AddTokenForm from './index'
|
||||
|
||||
const FrameDecorator = story => (
|
||||
<div className={styles.frame} style={{ textAlign: 'center' }}>
|
||||
{ story() }
|
||||
</div>
|
||||
)
|
||||
storiesOf('Components', module)
|
||||
.addDecorator(FrameDecorator)
|
||||
.add('AddTokenForm', () => (
|
||||
<AddTokenForm tokens={List([]).toArray()} safeAddress="" />
|
||||
))
|
|
@ -0,0 +1,33 @@
|
|||
// @flow
|
||||
import * as React from 'react'
|
||||
import Field from '~/components/forms/Field'
|
||||
import TextField from '~/components/forms/TextField'
|
||||
import { composeValidators, required, mustBeEthereumAddress, uniqueAddress } from '~/components/forms/validator'
|
||||
import Block from '~/components/layout/Block'
|
||||
import Heading from '~/components/layout/Heading'
|
||||
|
||||
type Props = {
|
||||
addresses: string[],
|
||||
}
|
||||
|
||||
export const TOKEN_PARAM = 'tokenAddress'
|
||||
|
||||
const FirstPage = ({ addresses }: Props) => () => (
|
||||
<Block margin="md">
|
||||
<Heading tag="h2" margin="lg">
|
||||
Add Custom ERC20 Token
|
||||
</Heading>
|
||||
<Block margin="md">
|
||||
<Field
|
||||
name={TOKEN_PARAM}
|
||||
component={TextField}
|
||||
type="text"
|
||||
validate={composeValidators(required, mustBeEthereumAddress, uniqueAddress(addresses))}
|
||||
placeholder="ERC20 Token Address*"
|
||||
text="ERC20 Token Address"
|
||||
/>
|
||||
</Block>
|
||||
</Block>
|
||||
)
|
||||
|
||||
export default FirstPage
|
|
@ -0,0 +1,45 @@
|
|||
// @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 Heading from '~/components/layout/Heading'
|
||||
import Paragraph from '~/components/layout/Paragraph'
|
||||
import { TOKEN_PARAM } from '~/routes/tokens/component/AddToken/FirstPage'
|
||||
import { LOGO_URL_PARAM, NAME_PARAM, SYMBOL_PARAM, DECIMALS_PARAM } from '~/routes/tokens/component/AddToken/SecondPage'
|
||||
|
||||
type FormProps = {
|
||||
values: Object,
|
||||
submitting: boolean,
|
||||
}
|
||||
|
||||
const spinnerStyle = {
|
||||
minHeight: '50px',
|
||||
}
|
||||
|
||||
const Review = () => ({ values, submitting }: FormProps) => (
|
||||
<Block>
|
||||
<Heading tag="h2">Review ERC20 Token operation</Heading>
|
||||
<Paragraph align="left">
|
||||
<Bold>Token address: </Bold> {values[TOKEN_PARAM]}
|
||||
</Paragraph>
|
||||
<Paragraph align="left">
|
||||
<Bold>Token name: </Bold> {values[NAME_PARAM]}
|
||||
</Paragraph>
|
||||
<Paragraph align="left">
|
||||
<Bold>Token symbol: </Bold> {values[SYMBOL_PARAM]}
|
||||
</Paragraph>
|
||||
<Paragraph align="left">
|
||||
<Bold>Token decimals: </Bold> {values[DECIMALS_PARAM]}
|
||||
</Paragraph>
|
||||
<Paragraph align="left">
|
||||
<Bold>Token logo: </Bold> {values[LOGO_URL_PARAM]}
|
||||
</Paragraph>
|
||||
<Block style={spinnerStyle}>
|
||||
{ submitting && <CircularProgress size={50} /> }
|
||||
</Block>
|
||||
</Block>
|
||||
)
|
||||
|
||||
|
||||
export default Review
|
|
@ -0,0 +1,62 @@
|
|||
// @flow
|
||||
import * as React from 'react'
|
||||
import Field from '~/components/forms/Field'
|
||||
import TextField from '~/components/forms/TextField'
|
||||
import { composeValidators, required, mustBeInteger, mustBeUrl } from '~/components/forms/validator'
|
||||
import Block from '~/components/layout/Block'
|
||||
import Heading from '~/components/layout/Heading'
|
||||
|
||||
export const NAME_PARAM = 'tokenName'
|
||||
export const SYMBOL_PARAM = 'tokenSymbol'
|
||||
export const DECIMALS_PARAM = 'tokenDecimals'
|
||||
export const LOGO_URL_PARAM = 'tokenLogo'
|
||||
|
||||
const SecondPage = () => () => (
|
||||
<Block margin="md">
|
||||
<Heading tag="h2" margin="lg">
|
||||
Complete Custom Token information
|
||||
</Heading>
|
||||
<Block margin="md">
|
||||
<Field
|
||||
name={NAME_PARAM}
|
||||
component={TextField}
|
||||
type="text"
|
||||
validate={required}
|
||||
placeholder="ERC20 Token Name*"
|
||||
text="ERC20 Token Name"
|
||||
/>
|
||||
</Block>
|
||||
<Block margin="md">
|
||||
<Field
|
||||
name={SYMBOL_PARAM}
|
||||
component={TextField}
|
||||
type="text"
|
||||
validate={required}
|
||||
placeholder="ERC20 Token Symbol*"
|
||||
text="ERC20 Token Symbol"
|
||||
/>
|
||||
</Block>
|
||||
<Block margin="md">
|
||||
<Field
|
||||
name={DECIMALS_PARAM}
|
||||
component={TextField}
|
||||
type="text"
|
||||
validate={composeValidators(required, mustBeInteger)}
|
||||
placeholder="ERC20 Token Decimals*"
|
||||
text="ERC20 Token Decimals"
|
||||
/>
|
||||
</Block>
|
||||
<Block margin="md">
|
||||
<Field
|
||||
name={LOGO_URL_PARAM}
|
||||
component={TextField}
|
||||
type="text"
|
||||
validate={composeValidators(required, mustBeUrl)}
|
||||
placeholder="ERC20 Token Logo url*"
|
||||
text="ERC20 Token Logo"
|
||||
/>
|
||||
</Block>
|
||||
</Block>
|
||||
)
|
||||
|
||||
export default SecondPage
|
|
@ -0,0 +1,89 @@
|
|||
// @flow
|
||||
import * as React from 'react'
|
||||
import Stepper from '~/components/Stepper'
|
||||
import SecondPage, { SYMBOL_PARAM, DECIMALS_PARAM, NAME_PARAM } from '~/routes/tokens/component/AddToken/SecondPage'
|
||||
import { getHumanFriendlyToken } from '~/routes/tokens/store/actions/fetchTokens'
|
||||
import { TOKEN_PARAM } from '~/routes/tokens/component/AddToken/FirstPage'
|
||||
import Review from './Review'
|
||||
import FirstPage from './FirstPage'
|
||||
|
||||
export const getSteps = () => [
|
||||
'Fill Add Token Form', 'Check optional attributes', 'Review Information',
|
||||
]
|
||||
|
||||
type Props = {
|
||||
tokens: string[],
|
||||
safeAddress: string,
|
||||
}
|
||||
|
||||
type State = {
|
||||
done: boolean,
|
||||
}
|
||||
|
||||
export const ADD_TOKEN_RESET_BUTTON_TEXT = 'RESET'
|
||||
|
||||
export const addToken = async (values: Object) => Promise.reject(values)
|
||||
|
||||
class AddToken extends React.Component<Props, State> {
|
||||
state = {
|
||||
done: false,
|
||||
}
|
||||
|
||||
onAddToken = async (values: Object) => {
|
||||
// eslint-disable-next-line
|
||||
console.log("onAddToken...")
|
||||
// eslint-disable-next-line
|
||||
console.log(values)
|
||||
}
|
||||
|
||||
onReset = () => {
|
||||
this.setState({ done: false })
|
||||
}
|
||||
|
||||
fetchInitialPropsSecondPage = async (values: Object) => {
|
||||
const tokenAddress = values[TOKEN_PARAM]
|
||||
const erc20Token = await getHumanFriendlyToken()
|
||||
const instance = await erc20Token.at(tokenAddress)
|
||||
|
||||
const name = await instance.name()
|
||||
const symbol = await instance.symbol()
|
||||
const decimals = await instance.decimals()
|
||||
|
||||
return ({
|
||||
[SYMBOL_PARAM]: symbol,
|
||||
[DECIMALS_PARAM]: `${decimals}`,
|
||||
[NAME_PARAM]: name,
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { tokens, safeAddress } = this.props
|
||||
const { done } = this.state
|
||||
const steps = getSteps()
|
||||
const finishedButton = <Stepper.FinishButton title={ADD_TOKEN_RESET_BUTTON_TEXT} />
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Stepper
|
||||
finishedTransaction={done}
|
||||
finishedButton={finishedButton}
|
||||
onSubmit={this.onAddToken}
|
||||
steps={steps}
|
||||
onReset={this.onReset}
|
||||
>
|
||||
<Stepper.Page addresses={tokens} prepareNextInitialProps={this.fetchInitialPropsSecondPage}>
|
||||
{ FirstPage }
|
||||
</Stepper.Page>
|
||||
<Stepper.Page safeAddress={safeAddress}>
|
||||
{ SecondPage }
|
||||
</Stepper.Page>
|
||||
<Stepper.Page>
|
||||
{ Review }
|
||||
</Stepper.Page>
|
||||
</Stepper>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default AddToken
|
Loading…
Reference in New Issue