From 6206ebc994a2cf76b90ac426218d6ed18b74a072 Mon Sep 17 00:00:00 2001
From: Fabio Berger <me@fabioberger.com>
Date: Sun, 28 Jan 2018 16:19:55 +0100
Subject: Implement just-in-time loading of token balances & allowances

---
 packages/website/ts/components/eth_wrappers.tsx | 86 +++++++++++++++++++++----
 1 file changed, 75 insertions(+), 11 deletions(-)

(limited to 'packages/website/ts/components/eth_wrappers.tsx')

diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx
index d074ec787..460a6cae3 100644
--- a/packages/website/ts/components/eth_wrappers.tsx
+++ b/packages/website/ts/components/eth_wrappers.tsx
@@ -41,12 +41,14 @@ interface EthWrappersProps {
     blockchain: Blockchain;
     dispatcher: Dispatcher;
     tokenByAddress: TokenByAddress;
-    tokenStateByAddress: TokenStateByAddress;
     userAddress: string;
     userEtherBalance: BigNumber;
+    lastForceTokenStateRefetch: number;
 }
 
 interface EthWrappersState {
+    ethTokenState: TokenState;
+    isWethStateLoaded: boolean;
     outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded;
     outdatedWETHStateByAddress: OutdatedWETHStateByAddress;
 }
@@ -67,18 +69,31 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
         this.state = {
             outdatedWETHAddressToIsStateLoaded,
             outdatedWETHStateByAddress,
+            isWethStateLoaded: false,
+            ethTokenState: {
+                balance: new BigNumber(0),
+                allowance: new BigNumber(0),
+            },
         };
     }
+    public componentWillReceiveProps(nextProps: EthWrappersProps) {
+        if (
+            nextProps.userAddress !== this.props.userAddress ||
+            nextProps.networkId !== this.props.networkId ||
+            nextProps.lastForceTokenStateRefetch !== this.props.lastForceTokenStateRefetch
+        ) {
+            // tslint:disable-next-line:no-floating-promises
+            this._fetchWETHStateAsync();
+        }
+    }
     public componentDidMount() {
         window.scrollTo(0, 0);
         // tslint:disable-next-line:no-floating-promises
-        this._fetchOutdatedWETHStateAsync();
+        this._fetchWETHStateAsync();
     }
     public render() {
-        const tokens = _.values(this.props.tokenByAddress);
-        const etherToken = _.find(tokens, { symbol: 'WETH' });
-        const etherTokenState = this.props.tokenStateByAddress[etherToken.address];
-        const wethBalance = ZeroEx.toUnitAmount(etherTokenState.balance, constants.DECIMAL_PLACES_ETH);
+        const etherToken = this._getEthToken();
+        const wethBalance = ZeroEx.toUnitAmount(this.state.ethTokenState.balance, constants.DECIMAL_PLACES_ETH);
         const isBidirectional = true;
         const etherscanUrl = utils.getEtherScanLinkIfExists(
             etherToken.address,
@@ -136,10 +151,14 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
                                     </TableRowColumn>
                                     <TableRowColumn>
                                         <EthWethConversionButton
+                                            refetchEthTokenStateAsync={this._refetchEthTokenStateAsync.bind(this)}
+                                            lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
+                                            userAddress={this.props.userAddress}
+                                            networkId={this.props.networkId}
                                             isOutdatedWrappedEther={false}
                                             direction={Side.Deposit}
                                             ethToken={etherToken}
-                                            ethTokenState={etherTokenState}
+                                            ethTokenState={this.state.ethTokenState}
                                             dispatcher={this.props.dispatcher}
                                             blockchain={this.props.blockchain}
                                             userEtherBalance={this.props.userEtherBalance}
@@ -150,13 +169,24 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
                                     <TableRowColumn className="py1">
                                         {this._renderTokenLink(tokenLabel, etherscanUrl)}
                                     </TableRowColumn>
-                                    <TableRowColumn>{wethBalance.toFixed(PRECISION)} WETH</TableRowColumn>
+                                    <TableRowColumn>
+                                        {this.state.isWethStateLoaded ? (
+                                            `${wethBalance.toFixed(PRECISION)} WETH`
+                                        ) : (
+                                            <i className="zmdi zmdi-spinner zmdi-hc-spin" />
+                                        )}
+                                    </TableRowColumn>
                                     <TableRowColumn>
                                         <EthWethConversionButton
+                                            refetchEthTokenStateAsync={this._refetchEthTokenStateAsync.bind(this)}
+                                            lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
+                                            userAddress={this.props.userAddress}
+                                            networkId={this.props.networkId}
                                             isOutdatedWrappedEther={false}
                                             direction={Side.Receive}
+                                            isDisabled={!this.state.isWethStateLoaded}
                                             ethToken={etherToken}
-                                            ethTokenState={etherTokenState}
+                                            ethTokenState={this.state.ethTokenState}
                                             dispatcher={this.props.dispatcher}
                                             blockchain={this.props.blockchain}
                                             userEtherBalance={this.props.userEtherBalance}
@@ -190,7 +220,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
                                 </TableRow>
                             </TableHeader>
                             <TableBody displayRowCheckbox={false}>
-                                {this._renderOutdatedWeths(etherToken, etherTokenState)}
+                                {this._renderOutdatedWeths(etherToken, this.state.ethTokenState)}
                             </TableBody>
                         </Table>
                     </div>
@@ -269,6 +299,10 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
                         </TableRowColumn>
                         <TableRowColumn>
                             <EthWethConversionButton
+                                refetchEthTokenStateAsync={this._refetchEthTokenStateAsync.bind(this)}
+                                lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
+                                userAddress={this.props.userAddress}
+                                networkId={this.props.networkId}
                                 isDisabled={!isStateLoaded}
                                 isOutdatedWrappedEther={true}
                                 direction={Side.Receive}
@@ -338,7 +372,14 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
             },
         });
     }
-    private async _fetchOutdatedWETHStateAsync() {
+    private async _fetchWETHStateAsync() {
+        const tokens = _.values(this.props.tokenByAddress);
+        const wethToken = _.find(tokens, token => token.symbol === 'WETH');
+        const [wethBalance, wethAllowance] = await this.props.blockchain.getTokenBalanceAndAllowanceAsync(
+            this.props.userAddress,
+            wethToken.address,
+        );
+
         const outdatedWETHAddresses = this._getOutdatedWETHAddresses();
         const outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded = {};
         const outdatedWETHStateByAddress: OutdatedWETHStateByAddress = {};
@@ -356,6 +397,11 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
         this.setState({
             outdatedWETHStateByAddress,
             outdatedWETHAddressToIsStateLoaded,
+            ethTokenState: {
+                balance: wethBalance,
+                allowance: wethAllowance,
+            },
+            isWethStateLoaded: true,
         });
     }
     private _getOutdatedWETHAddresses(): string[] {
@@ -371,4 +417,22 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
         );
         return outdatedWETHAddresses;
     }
+    private _getEthToken() {
+        const tokens = _.values(this.props.tokenByAddress);
+        const etherToken = _.find(tokens, { symbol: 'WETH' });
+        return etherToken;
+    }
+    private async _refetchEthTokenStateAsync() {
+        const etherToken = this._getEthToken();
+        const [balance, allowance] = await this.props.blockchain.getTokenBalanceAndAllowanceAsync(
+            this.props.userAddress,
+            etherToken.address,
+        );
+        this.setState({
+            ethTokenState: {
+                balance,
+                allowance,
+            },
+        });
+    }
 } // tslint:disable:max-file-line-count
-- 
cgit 


From e219772b2a25712f41fb819be36917d3b889201f Mon Sep 17 00:00:00 2001
From: Fabio Berger <me@fabioberger.com>
Date: Tue, 30 Jan 2018 20:12:32 +0100
Subject: Fix all setState calls after unmounted errors. Decided to create our
 own flag rather then using a cancellablePromise since there was little to be
 gained from this alternative

---
 packages/website/ts/components/eth_wrappers.tsx | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

(limited to 'packages/website/ts/components/eth_wrappers.tsx')

diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx
index 460a6cae3..90d2c0514 100644
--- a/packages/website/ts/components/eth_wrappers.tsx
+++ b/packages/website/ts/components/eth_wrappers.tsx
@@ -54,8 +54,10 @@ interface EthWrappersState {
 }
 
 export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersState> {
+    private _isUnmounted: boolean;
     constructor(props: EthWrappersProps) {
         super(props);
+        this._isUnmounted = false;
         const outdatedWETHAddresses = this._getOutdatedWETHAddresses();
         const outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded = {};
         const outdatedWETHStateByAddress: OutdatedWETHStateByAddress = {};
@@ -91,6 +93,9 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
         // tslint:disable-next-line:no-floating-promises
         this._fetchWETHStateAsync();
     }
+    public componentWillUnmount() {
+        this._isUnmounted = true;
+    }
     public render() {
         const etherToken = this._getEthToken();
         const wethBalance = ZeroEx.toUnitAmount(this.state.ethTokenState.balance, constants.DECIMAL_PLACES_ETH);
@@ -394,15 +399,17 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
             };
             outdatedWETHAddressToIsStateLoaded[address] = true;
         }
-        this.setState({
-            outdatedWETHStateByAddress,
-            outdatedWETHAddressToIsStateLoaded,
-            ethTokenState: {
-                balance: wethBalance,
-                allowance: wethAllowance,
-            },
-            isWethStateLoaded: true,
-        });
+        if (!this._isUnmounted) {
+            this.setState({
+                outdatedWETHStateByAddress,
+                outdatedWETHAddressToIsStateLoaded,
+                ethTokenState: {
+                    balance: wethBalance,
+                    allowance: wethAllowance,
+                },
+                isWethStateLoaded: true,
+            });
+        }
     }
     private _getOutdatedWETHAddresses(): string[] {
         const outdatedWETHAddresses = _.compact(
-- 
cgit 


From 16ea0348a9776c99bf50013fca65deb2ba2d698e Mon Sep 17 00:00:00 2001
From: Fabio Berger <me@fabioberger.com>
Date: Tue, 30 Jan 2018 20:45:09 +0100
Subject: Fix linter errors

---
 packages/website/ts/components/eth_wrappers.tsx | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'packages/website/ts/components/eth_wrappers.tsx')

diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx
index 90d2c0514..db1ceecb5 100644
--- a/packages/website/ts/components/eth_wrappers.tsx
+++ b/packages/website/ts/components/eth_wrappers.tsx
@@ -16,7 +16,6 @@ import {
     Token,
     TokenByAddress,
     TokenState,
-    TokenStateByAddress,
 } from 'ts/types';
 import { colors } from 'ts/utils/colors';
 import { configs } from 'ts/utils/configs';
@@ -163,7 +162,6 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
                                             isOutdatedWrappedEther={false}
                                             direction={Side.Deposit}
                                             ethToken={etherToken}
-                                            ethTokenState={this.state.ethTokenState}
                                             dispatcher={this.props.dispatcher}
                                             blockchain={this.props.blockchain}
                                             userEtherBalance={this.props.userEtherBalance}
@@ -191,7 +189,6 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
                                             direction={Side.Receive}
                                             isDisabled={!this.state.isWethStateLoaded}
                                             ethToken={etherToken}
-                                            ethTokenState={this.state.ethTokenState}
                                             dispatcher={this.props.dispatcher}
                                             blockchain={this.props.blockchain}
                                             userEtherBalance={this.props.userEtherBalance}
-- 
cgit 

