Newer
Older
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
//
import React, { Component } from 'react';
import debounce from 'lodash/debounce';
import { FormField, Header } from 'fether-ui';
import { fromWei, toWei } from '@parity/api/lib/util/wei';
import { inject, observer } from 'mobx-react';
import { isAddress } from '@parity/api/lib/util/address';
import ReactTooltip from 'react-tooltip';
import TokenBalance from '../../Tokens/TokensList/TokenBalance';
import withBalance from '../../utils/withBalance';
const MAX_GAS_PRICE = 40; // In Gwei
const MIN_GAS_PRICE = 3; // Safelow gas price from GasStation, in Gwei
@inject('sendStore', 'tokensStore')
@withBalance(
({ sendStore: { tokenAddress }, tokensStore }) =>
tokensStore.tokens[tokenAddress]
)
@observer
class Send extends Component {
state = {
amount: '', // In Ether or in token
gasPrice: 4, // in Gwei
to: '',
estimating: false, // Currently estimating gasPrice
...this.props.sendStore.tx
};
static getDerivedStateFromProps (nextProps, prevState) {
sendStore: { estimated }
} = nextProps;
return {
maxAmount:
balance && estimated
? +fromWei(
toWei(balance).minus(
estimated.mul(toWei(prevState.gasPrice, 'shannon'))
)
)
: 0.01
};
}
componentDidMount () {
this.handleEstimateGasPrice();
estimateGas = debounce(
() =>
this.props.sendStore
.estimateGas()
.then(() => this.setState({ estimating: false }))
.catch(() => this.setState({ estimating: false })),
1000
);
handleChangeAmount = ({ target: { value } }) =>
this.setState({ amount: value }, this.handleEstimateGasPrice);
handleChangeGasPrice = ({ target: { value } }) =>
this.setState({ gasPrice: value }, this.handleEstimateGasPrice);
this.setState({ to: value }, this.handleEstimateGasPrice);
};
handleEstimateGasPrice = () => {
if (this.hasError()) {
return;
}
const { amount, gasPrice, to } = this.state;
this.props.sendStore.setTx({ amount, gasPrice, to });
this.setState({ estimating: true }, this.estimateGas);
handleMax = () =>
this.setState(
{ amount: this.state.maxAmount },
this.handleEstimateGasPrice
);
handleSubmit = event => {
event.preventDefault();
const { history } = this.props;
history.push('/send/signer');
};
/**
* Get form errors.
*
* TODO Use a React form library to do this?
*/
const { amount, maxAmount, to } = this.state;
if (!amount || isNaN(amount)) {
return 'Please enter a valid amount';
}
if (amount < 0) {
return 'Please enter a positive amount ';
}
if (amount > maxAmount) {
return "You don't have enough balance";
}
if (!isAddress(to)) {
return 'Please enter a valid Ethereum address';
}
return null;
};
const { amount, estimating, gasPrice, maxAmount, to } = this.state;
const token = tokensStore.tokens[tokenAddress];
<Link to='/tokens' className='icon -close'>
Close
</Link>
}
title={<h1>Send {token.name}</h1>}
/>
<div className='window_content'>
<div className='box -padded'>
drawers={[
<form
className='send-form'
key='txForm'
onSubmit={this.handleSubmit}
>
<FormField
input={
<div>
<input
className='form_field_amount'
<button
className='button -utility'
onClick={this.handleMax}
Max
</button>
</nav>
</div>
}
label='Amount'
/>
<FormField
input={
className='-sm'
onChange={this.handleChangeTo}
/>
}
label='To'
/>
<FormField
className='-range'
input={
<div>
<input
max={MAX_GAS_PRICE}
min={MIN_GAS_PRICE}
onChange={this.handleChangeGasPrice}
required
/>
<nav className='range-nav'>
<span className='range-nav_label'>Cheap</span>
<span className='range-nav_value'>
</span>
<span className='range-nav_label'>Fast</span>
</nav>
</div>
}
label='Gas'
/>
<button disabled={error || estimating} className='button'>
{estimating ? 'Checking...' : 'Send'}
]}
onClick={null}
token={token}
/>
<ReactTooltip
effect='solid'
event='mouseover'
eventOff='mouseout'
place='top'
/>
</div>
);
}
}
export default Send;