From 0f8e6b395eb2260bbb03da9de35505a7a91c5c7b Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 20 Jul 2018 10:44:59 -0700 Subject: WIP for allowance toggle redesign working --- .../components/inputs/allowance_state_toggle.tsx | 102 +++++++++++++++++++-- .../ts/components/ui/allowance_state_view.tsx | 2 - packages/website/ts/components/wallet/wallet.tsx | 10 +- .../ts/containers/inputs/allowance_state_toggle.ts | 20 +++- 4 files changed, 118 insertions(+), 16 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/components/inputs/allowance_state_toggle.tsx b/packages/website/ts/components/inputs/allowance_state_toggle.tsx index bf661dee8..495efd806 100644 --- a/packages/website/ts/components/inputs/allowance_state_toggle.tsx +++ b/packages/website/ts/components/inputs/allowance_state_toggle.tsx @@ -1,36 +1,82 @@ -import { colors } from '@0xproject/react-shared'; +import { BigNumber, logUtils } from '@0xproject/utils'; +import * as _ from 'lodash'; import * as React from 'react'; -import { AllowanceStateView, AllowanceState } from 'ts/components/ui/allowance_state_view'; -import { Token, TokenState } from 'ts/types'; -import { Container } from 'ts/components/ui/container'; import ReactTooltip = require('react-tooltip'); +import { Blockchain } from 'ts/blockchain'; +import { AllowanceState, AllowanceStateView } from 'ts/components/ui/allowance_state_view'; +import { Container } from 'ts/components/ui/container'; +import { Dispatcher } from 'ts/redux/dispatcher'; +import { BalanceErrs, Token, TokenState } from 'ts/types'; +import { analytics } from 'ts/utils/analytics'; +import { errorReporter } from 'ts/utils/error_reporter'; +import { utils } from 'ts/utils/utils'; export interface AllowanceStateToggleProps { + networkId: number; + blockchain: Blockchain; + dispatcher: Dispatcher; token: Token; tokenState: TokenState; + userAddress: string; + onErrorOccurred?: (errType: BalanceErrs) => void; + refetchTokenStateAsync: () => Promise; } export interface AllowanceStateToggleState { allowanceState: AllowanceState; + prevAllowance: BigNumber; } -const flip = () => Math.random() < 0.5; +const DEFAULT_ALLOWANCE_AMOUNT_IN_BASE_UNITS = new BigNumber(2).pow(256).minus(1); export class AllowanceStateToggle extends React.Component { - public state = { - allowanceState: flip() ? AllowanceState.Loading : AllowanceState.Locked, + public static defaultProps = { + onErrorOccurred: _.noop.bind(_), }; + private static _getAllowanceStateFromAllowance(allowance?: BigNumber): AllowanceState { + if (_.isUndefined(allowance)) { + return AllowanceState.Loading; + } + if (allowance.gt(0)) { + return AllowanceState.Unlocked; + } + return AllowanceState.Locked; + } + constructor(props: AllowanceStateToggleProps) { + super(props); + const allowance = props.tokenState.allowance; + this.state = { + allowanceState: AllowanceState.Loading, + prevAllowance: allowance, + }; + } + public render(): React.ReactNode { const tooltipId = `tooltip-id-${this.props.token.symbol}`; return ( {this._getTooltipContent()} -
+
); } + public componentWillReceiveProps(nextProps: AllowanceStateToggleProps): void { + if (!nextProps.tokenState.allowance.eq(this.state.prevAllowance)) { + const allowance = nextProps.tokenState.allowance; + this.setState({ + prevAllowance: allowance, + allowanceState: AllowanceStateToggle._getAllowanceStateFromAllowance(allowance), + }); + } + } private _getTooltipContent(): React.ReactNode { const symbol = this.props.token.symbol; switch (this.state.allowanceState) { @@ -53,4 +99,44 @@ export class AllowanceStateToggle extends React.Component { + if (this.props.userAddress === '') { + this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); + return; + } + + this.setState({ + allowanceState: AllowanceState.Loading, + }); + + let newAllowanceAmountInBaseUnits = new BigNumber(0); + if (!this._isAllowanceSet()) { + newAllowanceAmountInBaseUnits = DEFAULT_ALLOWANCE_AMOUNT_IN_BASE_UNITS; + } + const logData = { + tokenSymbol: this.props.token.symbol, + newAllowance: newAllowanceAmountInBaseUnits.toNumber(), + }; + try { + await this.props.blockchain.setProxyAllowanceAsync(this.props.token, newAllowanceAmountInBaseUnits); + analytics.track('Set Allowances Success', logData); + await this.props.refetchTokenStateAsync(); + } catch (err) { + analytics.track('Set Allowance Failure', logData); + this.setState({ + allowanceState: AllowanceStateToggle._getAllowanceStateFromAllowance(this.state.prevAllowance), + }); + const errMsg = `${err}`; + if (utils.didUserDenyWeb3Request(errMsg)) { + return; + } + logUtils.log(`Unexpected error encountered: ${err}`); + logUtils.log(err.stack); + this.props.onErrorOccurred(BalanceErrs.allowanceSettingFailed); + errorReporter.report(err); + } + } + private _isAllowanceSet(): boolean { + return !this.props.tokenState.allowance.eq(0); + } } diff --git a/packages/website/ts/components/ui/allowance_state_view.tsx b/packages/website/ts/components/ui/allowance_state_view.tsx index eecf88c34..6b20d37eb 100644 --- a/packages/website/ts/components/ui/allowance_state_view.tsx +++ b/packages/website/ts/components/ui/allowance_state_view.tsx @@ -1,7 +1,5 @@ -import { colors } from '@0xproject/react-shared'; import CircularProgress from 'material-ui/CircularProgress'; import * as React from 'react'; -import { styled } from 'ts/style/theme'; export enum AllowanceState { Locked, diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 32c56ef14..2cba993c4 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -28,7 +28,6 @@ import { NullTokenRow } from 'ts/components/wallet/null_token_row'; import { PlaceHolder } from 'ts/components/wallet/placeholder'; import { StandardIconRow } from 'ts/components/wallet/standard_icon_row'; import { WrapEtherItem } from 'ts/components/wallet/wrap_ether_item'; -import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle'; import { AllowanceStateToggle } from 'ts/containers/inputs/allowance_state_toggle'; import { Dispatcher } from 'ts/redux/dispatcher'; import { colors } from 'ts/style/colors'; @@ -422,7 +421,14 @@ export class Wallet extends React.Component { // refetchTokenStateAsync={async () => this.props.refetchTokenStateAsync(config.token.address)} // /> // ); - return ; + return ( + this.props.refetchTokenStateAsync(config.token.address)} + /> + ); } private _renderAmount( amount: BigNumber, diff --git a/packages/website/ts/containers/inputs/allowance_state_toggle.ts b/packages/website/ts/containers/inputs/allowance_state_toggle.ts index cdda5ecf0..d6ff11f84 100644 --- a/packages/website/ts/containers/inputs/allowance_state_toggle.ts +++ b/packages/website/ts/containers/inputs/allowance_state_toggle.ts @@ -9,21 +9,33 @@ import { AllowanceStateToggle as AllowanceStateToggleComponent } from 'ts/compon import { Dispatcher } from 'ts/redux/dispatcher'; interface AllowanceStateToggleProps { + blockchain: Blockchain; + onErrorOccurred?: (errType: BalanceErrs) => void; token: Token; tokenState: TokenState; + isDisabled?: boolean; + refetchTokenStateAsync: () => Promise; } -interface ConnectedState {} +interface ConnectedState { + networkId: number; + userAddress: string; +} interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, _ownProps: AllowanceStateToggleProps): ConnectedState => ({}); +const mapStateToProps = (state: State, _ownProps: AllowanceStateToggleProps): ConnectedState => ({ + networkId: state.networkId, + userAddress: state.userAddress, +}); -// const mapDispatchTopProps = (dispatch: Dispatch): ConnectedDispatch => ({}); +const mapDispatchTopProps = (dispatch: Dispatch): ConnectedDispatch => ({ + dispatcher: new Dispatcher(dispatch), +}); export const AllowanceStateToggle: React.ComponentClass = connect( mapStateToProps, - // mapDispatchTopProps, + mapDispatchTopProps, )(AllowanceStateToggleComponent); -- cgit v1.2.3