TxForm.js 5.47 KiB
Newer Older
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
//
// SPDX-License-Identifier: MIT

import React, { Component } from 'react';
import { FormField, Header } from 'light-ui';
import { fromWei, toWei } from '@parity/api/lib/util/wei';
import { inject, observer } from 'mobx-react';
Amaury Martiny's avatar
Amaury Martiny committed
import { Link } from 'react-router-dom';
import TokenBalance from '../../Tokens/TokensList/TokenBalance';
import withBalance from '../../utils/withBalance';
Amaury Martiny's avatar
Amaury Martiny committed
const MAX_GAS_PRICE = 40; // In Gwei
const MIN_GAS_PRICE = 3; // Safelow gas price from GasStation, in Gwei

@inject('sendStore')
@withBalance(({ sendStore: { token } }) => token)
@observer
class Send extends Component {
Amaury Martiny's avatar
Amaury Martiny committed
  componentDidMount () {
    this.props.sendStore.estimateGas();
  }
  getMaxAmount = () => {
    const {
      balance,
      sendStore: { estimated, tx }
    } = this.props;

    // TODO this in sendStore as @computed?
    return balance && estimated
      ? +fromWei(
        toWei(balance).minus(
          estimated.multipliedBy(toWei(tx.gasPrice, 'shannon'))
        )
      )
      : 0.01;
  };

  handleChangeAmount = ({ target: { value } }) =>
Amaury Martiny's avatar
Amaury Martiny committed
    this.props.sendStore.setTxAmount(value);
Amaury Martiny's avatar
Amaury Martiny committed
  handleChangeGasPrice = ({ target: { value } }) =>
Amaury Martiny's avatar
Amaury Martiny committed
    this.props.sendStore.setTxGasPrice(value);
Amaury Martiny's avatar
Amaury Martiny committed
  handleChangeTo = ({ target: { value } }) => {
Amaury Martiny's avatar
Amaury Martiny committed
    const { sendStore } = this.props;
    sendStore.setTxTo(value);
    // Estimate the gas to this address, if we're sending ETH.
    if (sendStore.tokenAddress === 'ETH') {
      sendStore.estimateGas();
    }
Amaury Martiny's avatar
Amaury Martiny committed
  };
  handleMax = () => this.props.sendStore.setTxAmount(this.getMaxAmount());

  handleSubmit = e => {
    e.preventDefault();
Amaury Martiny's avatar
Amaury Martiny committed
    const { history, sendStore } = this.props;

    // Post a request to the transaction. There is a next step to sign this
    // request.
Amaury Martiny's avatar
Amaury Martiny committed
    sendStore.send();

    history.push('/send/signer');
  };

  render () {
    const {
      sendStore: { token, tx }
    } = this.props;

    return (
Amaury Martiny's avatar
Amaury Martiny committed
      <div>
        <Header
          left={
Amaury Martiny's avatar
Amaury Martiny committed
            <Link to='/tokens' className='icon -close'>
              Close
            </Link>
          }
          title={<h1>Send {token.name}</h1>}
        />

Amaury Martiny's avatar
Amaury Martiny committed
        <div className='window_content'>
          <div className='box -padded'>
            <TokenBalance
              decimals={6}
              drawers={[
                <form
                  className='send-form'
                  key='txForm'
                  onSubmit={this.handleSubmit}
                >
Amaury Martiny's avatar
Amaury Martiny committed
                  <fieldset className='form_fields'>
                    <FormField
                      input={
                        <div>
                          <input
                            className='form_field_amount'
                            max={this.getMaxAmount()}
                            min={0}
                            onChange={this.handleChangeAmount}
                            placeholder='1.00'
                            required
                            step={10 ** -token.decimals}
                            type='number'
Amaury Martiny's avatar
Amaury Martiny committed
                            value={tx.amount}
                          />
                          <nav className='form-field_nav'>
                            <button
                              className='button -utility'
                              onClick={this.handleMax}
                              type='button'
                            >
                              Max
                            </button>
                          </nav>
                        </div>
                      }
                      label='Amount'
                    />

                    <FormField
                      input={
Amaury Martiny's avatar
Amaury Martiny committed
                        <input
                          className='-sm'
                          onChange={this.handleChangeTo}
Amaury Martiny's avatar
Amaury Martiny committed
                          pattern='^0x[a-fA-F0-9]{40}$'
                          placeholder='0x...'
                          required
Amaury Martiny's avatar
Amaury Martiny committed
                          title='Invalid Ethereum address'
                          type='text'
Amaury Martiny's avatar
Amaury Martiny committed
                          value={tx.to}
                        />
                      }
                      label='To'
                    />

                    <FormField
                      className='-range'
                      input={
                        <div>
                          <input
                            max={MAX_GAS_PRICE}
                            min={MIN_GAS_PRICE}
                            onChange={this.handleChangeGasPrice}
                            required
                            step={0.5}
                            type='range'
Amaury Martiny's avatar
Amaury Martiny committed
                            value={tx.gasPrice}
                          />
                          <nav className='range-nav'>
                            <span className='range-nav_label'>Cheap</span>
                            <span className='range-nav_value'>
                              {tx.gasPrice} Gwei
                            </span>
                            <span className='range-nav_label'>Fast</span>
                          </nav>
                        </div>
                      }
                      label='Gas'
                    />
Amaury Martiny's avatar
Amaury Martiny committed
                  </fieldset>
                  <nav className='form-nav'>
                    <button className='button'>Send</button>
                  </nav>
                </form>
              ]}
              onClick={null}
              token={token}
            />
Amaury Martiny's avatar
Amaury Martiny committed
          </div>
        </div>
      </div>
    );
  }
}

export default Send;