OasisDEX/oasis-react

View on GitHub
src/containers/OasisTokenTransfer.jsx

Summary

Maintainability
A
1 hr
Test Coverage
D
63%
import React, { PureComponent } from "react";
import { PropTypes } from "prop-types";
// import ImmutablePropTypes from 'react-immutable-proptypes';

import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import OasisTokenSelectWrapper from "./OasisTokenSelect";
import TokenTransferFormWrapper from "./TokenTransferForm";
import OasisTokenBalanceSummary from "./OasisTokenBalanceSummary";
import OasisWidgetFrame from "../containers/OasisWidgetFrame";
import styles from "./OasisTokenTransfer.scss"

import transfersReducer from "../store/reducers/transfers";
import transfers from "../store/selectors/transfers";
import {
  TX__GROUP__TRANSFERS,
  TX_STATUS_AWAITING_CONFIRMATION,
  TX_STATUS_AWAITING_USER_ACCEPTANCE,
  TX_STATUS_CANCELLED_BY_USER,
  TX_STATUS_CONFIRMED,
  TX_STATUS_REJECTED
} from "../store/reducers/transactions";
import { formatAmount } from "../utils/tokens/pair";
import textStyles from "../styles/modules/_typography.scss";
import CSSModules from "react-css-modules/dist/index";
import { OasisTransactionStatusWrapperInfoBox } from "./OasisTransactionStatusInfoBox";

const propTypes = PropTypes && {
  actions: PropTypes.object.isRequired,
  selectedToken: PropTypes.string
};

export class OasisTokenTransferWrapper extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {};
    this.componentIsUnmounted = false;
    this.makeTransfer = this.makeTransfer.bind(this);
    this.onFormChange = this.onFormChange.bind(this);
  }

  async makeTransfer() {
    this.setState(
      {
        disableTransferButton: true,
        txStatus: false,
        txStartTimestamp: undefined
      },
      () =>
        this.props.actions.makeTransfer({
          onStart: this.onTransactionStart.bind(this),
          onCancelCleanup: this.onTransactionCancelledByUser.bind(this),
          onPending: this.onTransactionPending.bind(this),
          onCompleted: this.onTransactionCompleted.bind(this),
          onRejected: this.onTransactionRejected.bind(this)
        })
    );
  }

  onTransactionStart() {
    this.setState({
      txStatus: TX_STATUS_AWAITING_USER_ACCEPTANCE,
      disableForm: true
    });
  }

  onTransactionCancelledByUser() {
    this.setState({ disableTransferButton: false });
    this.setState({
      txStatus: TX_STATUS_CANCELLED_BY_USER,
      disableForm: false
    });
  }
  onTransactionPending({ txStartTimestamp }) {
    this.setState({
      txStatus: TX_STATUS_AWAITING_CONFIRMATION,
      txStartTimestamp
    });
  }

  onTransactionCompleted() {
    this.setState({
      txStatus: TX_STATUS_CONFIRMED,
      disableForm: false
    });
    this.props.actions.resetTransferForm();
  }

  onTransactionRejected({ txHash }) {
    this.setState({
      txStatus: TX_STATUS_REJECTED,
      txHash,
      disableForm: false
    });
  }

  shouldDisableForm() {
    const { disableForm } = this.state;
    return disableForm;
  }

  selectedToken() {
    return (
      <OasisTokenSelectWrapper
        onChange={() => this.props.actions.resetTransferForm()}
        disabled={this.shouldDisableForm()}
        name={"tokenTransfer"}
      />
    );
  }

  static transferInfo({ transferFormValues: { tokenAmount }, selectedToken }) {
    return (
      <div>
        Transfer
        <strong className={textStyles.spaceBoth}>
          {formatAmount(tokenAmount, false, null, 5)} {selectedToken}
        </strong>
      </div>
    );
  }

  renderTransactionStatus() {
    const { selectedToken, transferFormValues } = this.props;
    const { txStatus, txStartTimestamp } = this.state;
    if (transferFormValues && transferFormValues.tokenAmount) {
      this.transferFormValues = Object.create(transferFormValues);
    }
    return (
      this.transferFormValues && (
        <OasisTransactionStatusWrapperInfoBox
          txStatus={txStatus}
          infoText={OasisTokenTransferWrapper.transferInfo({
            selectedToken,
            transferFormValues: this.transferFormValues
          })}
          localStatus={txStatus}
          txTimestamp={txStartTimestamp}
          txType={TX__GROUP__TRANSFERS}
        />
      )
    );
  }

  onFormChange() {
    if (this.componentIsUnmounted === false) {
      this.setState({
        txStatus: undefined,
        txStartTimestamp: undefined
      });
    }
  }

  render() {
    const { txStatus } = this.state;
    const { selectedToken } = this.props;
    return (
      <OasisWidgetFrame
        className={styles.frame}
        heading="Transfer"
        spaceForContent={true}
        headingChildren={this.selectedToken()}
      >
        <OasisTokenBalanceSummary
          summary="Wallet"
          token={selectedToken}
          decimalPlaces={5}
          className={styles.tokenBalanceSummaryShorter}
        />
        <TokenTransferFormWrapper
          txStatus={txStatus}
          onFormChange={this.onFormChange}
          disabled={this.shouldDisableForm()}
          onSubmit={this.makeTransfer}
          transferState={this.renderTransactionStatus()}
        />
      </OasisWidgetFrame>
    );
  }

  componentWillUnmount() {
    this.componentIsUnmounted = true;
  }

}

export function mapStateToProps(state) {
  return {
    selectedToken: transfers.selectedToken(state),
    transferFormValues: transfers.getMakeTransferFormValues(state)
  };
}

export function mapDispatchToProps(dispatch) {
  const actions = {
    makeTransfer: transfersReducer.actions.makeTransferEpic,
    resetTransferForm: transfersReducer.actions.resetTransferForm
  };
  return { actions: bindActionCreators(actions, dispatch) };
}

OasisTokenTransferWrapper.propTypes = propTypes;
OasisTokenTransferWrapper.displayName = "OasisTokenTransfer";
export default connect(mapStateToProps, mapDispatchToProps)(
  CSSModules(OasisTokenTransferWrapper, { textStyles, styles }, { allowMultiple: true })
);