import { ZeroEx } from '0x.js'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import * as React from 'react'; import { Link } from 'react-router-dom'; import { Blockchain } from 'ts/blockchain'; import { BalanceBoundedInput } from 'ts/components/inputs/balance_bounded_input'; import { InputErrMsg, Token, ValidatedBigNumberCallback, WebsitePaths } from 'ts/types'; import { colors } from 'ts/utils/colors'; interface TokenAmountInputProps { userAddress: string; networkId: number; blockchain: Blockchain; token: Token; label?: string; amount?: BigNumber; shouldShowIncompleteErrs: boolean; shouldCheckBalance: boolean; shouldCheckAllowance: boolean; onChange: ValidatedBigNumberCallback; onVisitBalancesPageClick?: () => void; lastForceTokenStateRefetch: number; } interface TokenAmountInputState { balance: BigNumber; allowance: BigNumber; isBalanceAndAllowanceLoaded: boolean; } export class TokenAmountInput extends React.Component { private _isUnmounted: boolean; constructor(props: TokenAmountInputProps) { super(props); this._isUnmounted = false; const defaultAmount = new BigNumber(0); this.state = { balance: defaultAmount, allowance: defaultAmount, isBalanceAndAllowanceLoaded: false, }; } public componentWillMount() { // tslint:disable-next-line:no-floating-promises this._fetchBalanceAndAllowanceAsync(this.props.token.address, this.props.userAddress); } public componentWillUnmount() { this._isUnmounted = true; } public componentWillReceiveProps(nextProps: TokenAmountInputProps) { if ( nextProps.userAddress !== this.props.userAddress || nextProps.networkId !== this.props.networkId || nextProps.token.address !== this.props.token.address || nextProps.lastForceTokenStateRefetch !== this.props.lastForceTokenStateRefetch ) { // tslint:disable-next-line:no-floating-promises this._fetchBalanceAndAllowanceAsync(nextProps.token.address, nextProps.userAddress); } } public render() { const amount = this.props.amount ? ZeroEx.toUnitAmount(this.props.amount, this.props.token.decimals) : undefined; const hasLabel = !_.isUndefined(this.props.label); return (
{this.props.token.symbol}
); } private _onChange(isValid: boolean, amount?: BigNumber) { let baseUnitAmount; if (!_.isUndefined(amount)) { baseUnitAmount = ZeroEx.toBaseUnitAmount(amount, this.props.token.decimals); } this.props.onChange(isValid, baseUnitAmount); } private _validate(amount: BigNumber): InputErrMsg { if (this.props.shouldCheckAllowance && amount.gt(this.state.allowance)) { return ( Insufficient allowance.{' '} Set allowance ); } else { return undefined; } } private async _fetchBalanceAndAllowanceAsync(tokenAddress: string, userAddress: string) { this.setState({ isBalanceAndAllowanceLoaded: false, }); const [balance, allowance] = await this.props.blockchain.getTokenBalanceAndAllowanceAsync( userAddress, tokenAddress, ); if (!this._isUnmounted) { this.setState({ balance, allowance, isBalanceAndAllowanceLoaded: true, }); } } }