From 9376a0b282890b2608533a29bb421a01e61dd822 Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Fri, 22 Mar 2019 14:21:06 +0100
Subject: [PATCH 01/14] Show parity/light.js's logs too

---
 packages/fether-react/src/index.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/fether-react/src/index.js b/packages/fether-react/src/index.js
index 3fa6a6b30..0c9d0eb03 100644
--- a/packages/fether-react/src/index.js
+++ b/packages/fether-react/src/index.js
@@ -16,7 +16,7 @@ import rootStore from './stores';
 import './index.css';
 
 // Show debug logs
-window.localStorage.debug = 'fether*'; // https://github.com/visionmedia/debug#browser-support
+window.localStorage.debug = 'fether*,@parity*'; // https://github.com/visionmedia/debug#browser-support
 
 // Set recompose to use RxJS
 // https://github.com/acdlite/recompose/blob/master/docs/API.md#setobservableconfig

From c6d3bbdbe751b7475ed7051c85a54056997b95e5 Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Fri, 22 Mar 2019 14:21:24 +0100
Subject: [PATCH 02/14] Remove txCount from withAccount

---
 packages/fether-react/src/utils/withAccount.js | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/packages/fether-react/src/utils/withAccount.js b/packages/fether-react/src/utils/withAccount.js
index 5d9f8dc3b..99ff17908 100644
--- a/packages/fether-react/src/utils/withAccount.js
+++ b/packages/fether-react/src/utils/withAccount.js
@@ -6,24 +6,14 @@
 import React from 'react';
 import { withRouter } from 'react-router-dom';
 import { compose, mapProps } from 'recompose';
-import { startWith } from 'rxjs/operators';
-import light from '@parity/light.js-react';
-import { transactionCountOf$ } from '@parity/light.js';
 
 import withAccountsInfo from '../utils/withAccountsInfo';
 
 const WithAccount = compose(
   withRouter,
   withAccountsInfo,
-  light({
-    transactionCount: props =>
-      transactionCountOf$(props.match.params.accountAddress).pipe(
-        startWith(undefined)
-      )
-  }),
   mapProps(
     ({
-      transactionCount,
       match: {
         params: { accountAddress }
       },
@@ -33,8 +23,7 @@ const WithAccount = compose(
       account: {
         address: accountAddress,
         name: accountsInfo[accountAddress].name,
-        type: accountsInfo[accountAddress].type,
-        transactionCount
+        type: accountsInfo[accountAddress].type
       },
       ...otherProps
     })

From 06a2714b7d68fb72fca0dd56f4505bc37ac1438c Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Fri, 22 Mar 2019 14:22:47 +0100
Subject: [PATCH 03/14] withBalance shows component immeidately

---
 packages/fether-react/src/utils/withBalance.js | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/packages/fether-react/src/utils/withBalance.js b/packages/fether-react/src/utils/withBalance.js
index 5bb56439f..b92af8ec8 100644
--- a/packages/fether-react/src/utils/withBalance.js
+++ b/packages/fether-react/src/utils/withBalance.js
@@ -9,19 +9,25 @@ import branch from 'recompose/branch';
 import compose from 'recompose/compose';
 import { fromWei } from '@parity/api/lib/util/wei';
 import light from '@parity/light.js-react';
-import { map } from 'rxjs/operators';
+import { map, startWith } from 'rxjs/operators';
 import withProps from 'recompose/withProps';
 
 export const withErc20Balance = light({
   erc20Balance: ({ token, account: { address } }) =>
     makeContract(token.address, abi)
       .balanceOf$(address)
-      .pipe(map(value => value && value.div(10 ** token.decimals)))
+      .pipe(
+        map(value => value && value.div(10 ** token.decimals)),
+        startWith(undefined)
+      )
 });
 
 export const withEthBalance = light({
   ethBalance: ({ account: { address } }) =>
-    balanceOf$(address).pipe(map(value => value && fromWei(value)))
+    balanceOf$(address).pipe(
+      map(value => value && fromWei(value)),
+      startWith(undefined)
+    )
 });
 
 /**

From ff8cba5d414ec5894b397e1a8736aad901af896c Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Fri, 22 Mar 2019 16:36:34 +0100
Subject: [PATCH 04/14] Play around

---
 .../fether-react/src/Send/TxForm/TxForm.js    | 101 ++++++++++++------
 1 file changed, 66 insertions(+), 35 deletions(-)

diff --git a/packages/fether-react/src/Send/TxForm/TxForm.js b/packages/fether-react/src/Send/TxForm/TxForm.js
index 0169f9e11..12ce434a7 100644
--- a/packages/fether-react/src/Send/TxForm/TxForm.js
+++ b/packages/fether-react/src/Send/TxForm/TxForm.js
@@ -4,10 +4,10 @@
 // SPDX-License-Identifier: BSD-3-Clause
 
 import React, { Component } from 'react';
+import { balanceOf$, chainId$, transactionCountOf$ } from '@parity/light.js';
 import BigNumber from 'bignumber.js';
 import { Clickable, Form as FetherForm, Header } from 'fether-ui';
 import createDecorator from 'final-form-calculate';
-import { chainId$ } from '@parity/light.js';
 import debounce from 'debounce-promise';
 import { Field, Form } from 'react-final-form';
 import { fromWei, toWei } from '@parity/api/lib/util/wei';
@@ -15,6 +15,7 @@ import { inject, observer } from 'mobx-react';
 import { isAddress } from '@parity/api/lib/util/address';
 import light from '@parity/light.js-react';
 import { Link } from 'react-router-dom';
+import { map, startWith, delay, tap } from 'rxjs/operators';
 import { OnChange } from 'react-final-form-listeners';
 import { withProps } from 'recompose';
 
@@ -23,13 +24,14 @@ import RequireHealthOverlay from '../../RequireHealthOverlay';
 import TokenBalance from '../../Tokens/TokensList/TokenBalance';
 import TxDetails from './TxDetails';
 import withAccount from '../../utils/withAccount';
-import withBalance, { withEthBalance } from '../../utils/withBalance';
+import withBalance from '../../utils/withBalance';
 import withTokens from '../../utils/withTokens';
 
 const DEFAULT_AMOUNT_MAX_CHARS = 9;
 const MEDIUM_AMOUNT_MAX_CHARS = 14;
 const MAX_GAS_PRICE = 40; // In Gwei
 const MIN_GAS_PRICE = 3; // Safelow gas price from GasStation, in Gwei
+const MINUS_ONE = new BigNumber(-1);
 
 @inject('parityStore', 'sendStore')
 @withTokens
@@ -38,10 +40,18 @@ const MIN_GAS_PRICE = 3; // Safelow gas price from GasStation, in Gwei
 }))
 @withAccount
 @light({
-  chainId: () => chainId$()
+  chainId: () => chainId$().pipe(startWith(undefined)), // Start with `undefined` not to block UI
+  transactionCount: ({ account: { address } }) =>
+    transactionCountOf$(address).pipe(
+      delay(5000),
+      tap(a => console.log('GOT transactionCountOf', a.toString())),
+      // Start with some value not to block UI, needs to be a truthy value to
+      // taken into account by final-form
+      startWith(undefined)
+    )
 })
 @withBalance // Balance of current token (can be ETH)
-@withEthBalance // ETH balance
+@withEthBalance
 @observer
 class TxForm extends Component {
   state = {
@@ -130,14 +140,13 @@ class TxForm extends Component {
 
   handleSubmit = values => {
     const {
-      account: { address, type, transactionCount },
-      chainId,
+      account: { address, type },
       history,
       sendStore,
       token
     } = this.props;
 
-    sendStore.setTx({ ...values, chainId, token, transactionCount });
+    sendStore.setTx({ ...values, token });
 
     if (type === 'signer') {
       history.push(`/send/${token.address}/from/${address}/txqrcode`);
@@ -184,12 +193,19 @@ class TxForm extends Component {
   render () {
     const {
       account: { address, type },
+      chainId,
+      ethBalance,
       sendStore: { tx },
-      token
+      token,
+      transactionCount
     } = this.props;
 
     const { showDetails } = this.state;
 
+    if (!ethBalance || !chainId || !transactionCount) {
+      return null;
+    }
+
     return (
       <div>
         <Header
@@ -208,12 +224,22 @@ class TxForm extends Component {
                 decimals={6}
                 drawers={[
                   <Form
+                    decorators={[this.decorator]}
+                    initialValues={{
+                      chainId,
+                      ethBalance,
+                      from: address,
+                      gasPrice: 4,
+                      transactionCount,
+                      ...tx
+                    }}
+                    keepDirtyOnReinitialize
                     key='txForm'
-                    initialValues={{ from: address, gasPrice: 4, ...tx }}
+                    mutators={{
+                      recalculateMax: this.recalculateMax
+                    }}
                     onSubmit={this.handleSubmit}
                     validate={this.validateForm}
-                    decorators={[this.decorator]}
-                    mutators={{ recalculateMax: this.recalculateMax }}
                     render={({
                       handleSubmit,
                       valid,
@@ -335,6 +361,9 @@ class TxForm extends Component {
     );
   }
 
+  /**
+   * Prevalidate form on user's input. These validations are sync.
+   */
   preValidate = values => {
     const { balance, token } = this.props;
 
@@ -384,47 +413,47 @@ class TxForm extends Component {
    * the tx.
    */
   validateForm = debounce(values => {
+    console.log('CALLING validateForm', values);
     if (!values) {
       return;
     }
 
     try {
-      const {
-        account: { address, transactionCount },
-        chainId,
-        ethBalance,
-        token
-      } = this.props;
-
-      if (!chainId) {
-        throw new Error('chaindId is required for an EthereumTx');
-      }
+      const { token } = this.props;
+      const { chainId, ethBalance, transactionCount } = values;
 
-      if (!address) {
-        throw new Error('address of an account is required');
-      }
+      const preValidation = this.preValidate(values);
 
-      if (!transactionCount) {
-        throw new Error('transactionCount is required for an EthereumTx');
+      // preValidate return an error if a field isn't valid
+      if (preValidation !== true) {
+        console.log('prevalidation did not pass');
+        return preValidation;
       }
 
-      if (!token || !token.address || !token.decimals) {
-        throw new Error('token information is required for an EthereumTx');
+      // The 3 values below (`chainId`, `ethBalance`, and `transactionCount`)
+      // come from props, and are passed into `values` via the form's
+      // initialValues. As such, they don't have visible fields, so putting an
+      // error here just means we're keeping the form state as not valid.
+      if (!chainId) {
+        console.log('chainId did not pass');
+        return { chainId: 'Fetching chainId' };
       }
 
       if (!ethBalance) {
-        throw new Error('No "ethBalance"');
+        console.log('ethBalance did not pass');
+        return { ethBalance: 'Fetching ethBalance' };
       }
 
-      const preValidation = this.preValidate(values);
-
-      // preValidate return an error if a field isn't valid
-      if (preValidation !== true) {
-        return preValidation;
+      if (!transactionCount) {
+        console.log('transactionCount did not pass', transactionCount);
+        return {
+          transactionCount: 'Fetching transactionCount'
+        };
       }
 
       if (values.gas && values.gas.eq(-1)) {
-        return { amount: 'Unable to estimate gas...' };
+        console.log('values.gas did not pass', values.gas);
+        return {};
       }
 
       // If the gas hasn't been calculated yet, then we don't show any errors,
@@ -443,6 +472,8 @@ class TxForm extends Component {
           ? { amount: 'ETH balance too low to pay for gas' }
           : { amount: "You don't have enough ETH balance" };
       }
+
+      console.log('passed');
     } catch (err) {
       console.error(err);
       return {

From 53bac8fb09a267ff0b989bcb95dbb03115aec0ad Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Fri, 22 Mar 2019 17:07:53 +0100
Subject: [PATCH 05/14] Make it work

---
 .../fether-react/src/Send/TxForm/TxForm.js    | 41 ++++++++-----------
 1 file changed, 16 insertions(+), 25 deletions(-)

diff --git a/packages/fether-react/src/Send/TxForm/TxForm.js b/packages/fether-react/src/Send/TxForm/TxForm.js
index 12ce434a7..2b6a198c1 100644
--- a/packages/fether-react/src/Send/TxForm/TxForm.js
+++ b/packages/fether-react/src/Send/TxForm/TxForm.js
@@ -4,8 +4,8 @@
 // SPDX-License-Identifier: BSD-3-Clause
 
 import React, { Component } from 'react';
-import { balanceOf$, chainId$, transactionCountOf$ } from '@parity/light.js';
 import BigNumber from 'bignumber.js';
+import { chainId$, transactionCountOf$ } from '@parity/light.js';
 import { Clickable, Form as FetherForm, Header } from 'fether-ui';
 import createDecorator from 'final-form-calculate';
 import debounce from 'debounce-promise';
@@ -24,14 +24,13 @@ import RequireHealthOverlay from '../../RequireHealthOverlay';
 import TokenBalance from '../../Tokens/TokensList/TokenBalance';
 import TxDetails from './TxDetails';
 import withAccount from '../../utils/withAccount';
-import withBalance from '../../utils/withBalance';
+import withBalance, { withEthBalance } from '../../utils/withBalance';
 import withTokens from '../../utils/withTokens';
 
 const DEFAULT_AMOUNT_MAX_CHARS = 9;
 const MEDIUM_AMOUNT_MAX_CHARS = 14;
 const MAX_GAS_PRICE = 40; // In Gwei
 const MIN_GAS_PRICE = 3; // Safelow gas price from GasStation, in Gwei
-const MINUS_ONE = new BigNumber(-1);
 
 @inject('parityStore', 'sendStore')
 @withTokens
@@ -40,15 +39,14 @@ const MINUS_ONE = new BigNumber(-1);
 }))
 @withAccount
 @light({
-  chainId: () => chainId$().pipe(startWith(undefined)), // Start with `undefined` not to block UI
+  // We need to wait for 3 values that might take time:
+  // - ethBalance: to check that we have enough to send amount+fees
+  // - chainId & transactionCount: needed to construct the tx
+  // For the three of them, we add the `startWith()` operator so that the UI is
+  // not blocked while waiting for their first response.
+  chainId: () => chainId$().pipe(startWith(undefined)),
   transactionCount: ({ account: { address } }) =>
-    transactionCountOf$(address).pipe(
-      delay(5000),
-      tap(a => console.log('GOT transactionCountOf', a.toString())),
-      // Start with some value not to block UI, needs to be a truthy value to
-      // taken into account by final-form
-      startWith(undefined)
-    )
+    transactionCountOf$(address).pipe(startWith(undefined))
 })
 @withBalance // Balance of current token (can be ETH)
 @withEthBalance
@@ -75,7 +73,6 @@ class TxForm extends Component {
               parityStore.api
             );
           } catch (error) {
-            console.error(error);
             return new BigNumber(-1);
           }
         }
@@ -202,10 +199,6 @@ class TxForm extends Component {
 
     const { showDetails } = this.state;
 
-    if (!ethBalance || !chainId || !transactionCount) {
-      return null;
-    }
-
     return (
       <div>
         <Header
@@ -233,7 +226,7 @@ class TxForm extends Component {
                       transactionCount,
                       ...tx
                     }}
-                    keepDirtyOnReinitialize
+                    keepDirtyOnReinitialize // Don't erase other fields when we get new initialValues
                     key='txForm'
                     mutators={{
                       recalculateMax: this.recalculateMax
@@ -249,6 +242,12 @@ class TxForm extends Component {
                     }) => (
                       <form className='send-form' onSubmit={handleSubmit}>
                         <fieldset className='form_fields'>
+                          {/* Unfortunately, we need to set these hidden fields
+                              for the 3 values that come from props. */}
+                          <Field name='chainId' render={() => null} />
+                          <Field name='ethBalance' render={() => null} />
+                          <Field name='transactionCount' render={() => null} />
+
                           <Field
                             as='textarea'
                             autoFocus
@@ -413,7 +412,6 @@ class TxForm extends Component {
    * the tx.
    */
   validateForm = debounce(values => {
-    console.log('CALLING validateForm', values);
     if (!values) {
       return;
     }
@@ -426,7 +424,6 @@ class TxForm extends Component {
 
       // preValidate return an error if a field isn't valid
       if (preValidation !== true) {
-        console.log('prevalidation did not pass');
         return preValidation;
       }
 
@@ -435,24 +432,20 @@ class TxForm extends Component {
       // initialValues. As such, they don't have visible fields, so putting an
       // error here just means we're keeping the form state as not valid.
       if (!chainId) {
-        console.log('chainId did not pass');
         return { chainId: 'Fetching chainId' };
       }
 
       if (!ethBalance) {
-        console.log('ethBalance did not pass');
         return { ethBalance: 'Fetching ethBalance' };
       }
 
       if (!transactionCount) {
-        console.log('transactionCount did not pass', transactionCount);
         return {
           transactionCount: 'Fetching transactionCount'
         };
       }
 
       if (values.gas && values.gas.eq(-1)) {
-        console.log('values.gas did not pass', values.gas);
         return {};
       }
 
@@ -472,8 +465,6 @@ class TxForm extends Component {
           ? { amount: 'ETH balance too low to pay for gas' }
           : { amount: "You don't have enough ETH balance" };
       }
-
-      console.log('passed');
     } catch (err) {
       console.error(err);
       return {

From 6e0ec18e3c8ceb297c0f6f6a725b042f4b38d0da Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Fri, 22 Mar 2019 17:11:20 +0100
Subject: [PATCH 06/14] Cleaner code

---
 packages/fether-react/src/Send/TxForm/TxForm.js | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/packages/fether-react/src/Send/TxForm/TxForm.js b/packages/fether-react/src/Send/TxForm/TxForm.js
index 2b6a198c1..74616aff8 100644
--- a/packages/fether-react/src/Send/TxForm/TxForm.js
+++ b/packages/fether-react/src/Send/TxForm/TxForm.js
@@ -15,7 +15,7 @@ import { inject, observer } from 'mobx-react';
 import { isAddress } from '@parity/api/lib/util/address';
 import light from '@parity/light.js-react';
 import { Link } from 'react-router-dom';
-import { map, startWith, delay, tap } from 'rxjs/operators';
+import { startWith } from 'rxjs/operators';
 import { OnChange } from 'react-final-form-listeners';
 import { withProps } from 'recompose';
 
@@ -49,7 +49,7 @@ const MIN_GAS_PRICE = 3; // Safelow gas price from GasStation, in Gwei
     transactionCountOf$(address).pipe(startWith(undefined))
 })
 @withBalance // Balance of current token (can be ETH)
-@withEthBalance
+@withEthBalance // ETH balance
 @observer
 class TxForm extends Component {
   state = {
@@ -243,7 +243,8 @@ class TxForm extends Component {
                       <form className='send-form' onSubmit={handleSubmit}>
                         <fieldset className='form_fields'>
                           {/* Unfortunately, we need to set these hidden fields
-                              for the 3 values that come from props. */}
+                              for the 3 values that come from props, even
+                              though they are already set in initialValues. */}
                           <Field name='chainId' render={() => null} />
                           <Field name='ethBalance' render={() => null} />
                           <Field name='transactionCount' render={() => null} />
@@ -418,7 +419,6 @@ class TxForm extends Component {
 
     try {
       const { token } = this.props;
-      const { chainId, ethBalance, transactionCount } = values;
 
       const preValidation = this.preValidate(values);
 
@@ -431,15 +431,15 @@ class TxForm extends Component {
       // come from props, and are passed into `values` via the form's
       // initialValues. As such, they don't have visible fields, so putting an
       // error here just means we're keeping the form state as not valid.
-      if (!chainId) {
+      if (!values.chainId) {
         return { chainId: 'Fetching chainId' };
       }
 
-      if (!ethBalance) {
+      if (!values.ethBalance) {
         return { ethBalance: 'Fetching ethBalance' };
       }
 
-      if (!transactionCount) {
+      if (!values.transactionCount) {
         return {
           transactionCount: 'Fetching transactionCount'
         };
@@ -459,7 +459,7 @@ class TxForm extends Component {
       if (
         this.estimatedTxFee(values)
           .plus(token.address === 'ETH' ? toWei(values.amount) : 0)
-          .gt(toWei(ethBalance))
+          .gt(toWei(values.ethBalance))
       ) {
         return token.address !== 'ETH'
           ? { amount: 'ETH balance too low to pay for gas' }

From a8e72cd3792c83f17afac220a7fd3e30085382df Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Fri, 22 Mar 2019 17:14:17 +0100
Subject: [PATCH 07/14] Remove 'Loading account tokens...' modal

---
 .../TokensList/TokenBalance/TokenBalance.js   |  9 -------
 .../src/Tokens/TokensList/TokensList.js       | 25 +------------------
 2 files changed, 1 insertion(+), 33 deletions(-)

diff --git a/packages/fether-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js b/packages/fether-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js
index df613ac77..256dfc099 100644
--- a/packages/fether-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js
+++ b/packages/fether-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js
@@ -18,18 +18,9 @@ import withBalance from '../../../utils/withBalance';
 @inject('sendStore')
 class TokenBalance extends Component {
   static propTypes = {
-    hideLoadingAccountTokensModal: PropTypes.func,
     token: PropTypes.object
   };
 
-  componentDidMount () {
-    const { hideLoadingAccountTokensModal } = this.props;
-
-    if (hideLoadingAccountTokensModal) {
-      hideLoadingAccountTokensModal();
-    }
-  }
-
   handleClick = () => {
     const {
       account: { address },
diff --git a/packages/fether-react/src/Tokens/TokensList/TokensList.js b/packages/fether-react/src/Tokens/TokensList/TokensList.js
index 2190d1748..f9f29359a 100644
--- a/packages/fether-react/src/Tokens/TokensList/TokensList.js
+++ b/packages/fether-react/src/Tokens/TokensList/TokensList.js
@@ -4,37 +4,19 @@
 // SPDX-License-Identifier: BSD-3-Clause
 
 import React, { Component } from 'react';
-import { Modal } from 'fether-ui';
 import RequireHealthOverlay from '../../RequireHealthOverlay';
 import TokenBalance from './TokenBalance';
 import withTokens from '../../utils/withTokens';
-import loading from '../../assets/img/icons/loading.svg';
 
 @withTokens
 class TokensList extends Component {
-  state = {
-    isLoadingAccountTokens: true
-  };
-
-  hideLoadingAccountTokensModal = () => {
-    this.setState({ isLoadingAccountTokens: false });
-  };
-
   render () {
     const { tokensArray } = this.props;
-    const { isLoadingAccountTokens } = this.state;
     // Show empty token placeholder if tokens have not been loaded yet
     const shownArray = tokensArray.length ? tokensArray : [{}];
 
     return (
       <RequireHealthOverlay require='sync'>
-        <Modal
-          description='Please wait...'
-          fullscreen={false}
-          icon={loading}
-          title='Loading account tokens...'
-          visible={isLoadingAccountTokens}
-        />
         <div className='window_content'>
           <div className='box -scroller'>
             <ul className='list -padded'>
@@ -43,12 +25,7 @@ class TokensList extends Component {
                 index // With empty tokens, the token.address is not defined, so we prefix with index
               ) => (
                 <li key={`${index}-${token.address}`}>
-                  <TokenBalance
-                    hideLoadingAccountTokensModal={
-                      this.hideLoadingAccountTokensModal
-                    }
-                    token={token}
-                  />
+                  <TokenBalance token={token} />
                 </li>
               ))}
             </ul>

From 7862560c29d2361d15908615b5b1d2c090d3a28b Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Fri, 22 Mar 2019 17:15:00 +0100
Subject: [PATCH 08/14] Re-order import

---
 packages/fether-react/src/Send/TxForm/TxForm.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/fether-react/src/Send/TxForm/TxForm.js b/packages/fether-react/src/Send/TxForm/TxForm.js
index 74616aff8..9c7891c08 100644
--- a/packages/fether-react/src/Send/TxForm/TxForm.js
+++ b/packages/fether-react/src/Send/TxForm/TxForm.js
@@ -15,8 +15,8 @@ import { inject, observer } from 'mobx-react';
 import { isAddress } from '@parity/api/lib/util/address';
 import light from '@parity/light.js-react';
 import { Link } from 'react-router-dom';
-import { startWith } from 'rxjs/operators';
 import { OnChange } from 'react-final-form-listeners';
+import { startWith } from 'rxjs/operators';
 import { withProps } from 'recompose';
 
 import { estimateGas } from '../../utils/transaction';

From 9fe045058a6ad2e5c353d0f0a0d475407563ec27 Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Fri, 22 Mar 2019 17:15:52 +0100
Subject: [PATCH 09/14] Optimize code

---
 packages/fether-react/src/Send/TxForm/TxForm.js | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/packages/fether-react/src/Send/TxForm/TxForm.js b/packages/fether-react/src/Send/TxForm/TxForm.js
index 9c7891c08..1bcd2d8a5 100644
--- a/packages/fether-react/src/Send/TxForm/TxForm.js
+++ b/packages/fether-react/src/Send/TxForm/TxForm.js
@@ -245,9 +245,12 @@ class TxForm extends Component {
                           {/* Unfortunately, we need to set these hidden fields
                               for the 3 values that come from props, even
                               though they are already set in initialValues. */}
-                          <Field name='chainId' render={() => null} />
-                          <Field name='ethBalance' render={() => null} />
-                          <Field name='transactionCount' render={() => null} />
+                          <Field name='chainId' render={this.renderNull} />
+                          <Field name='ethBalance' render={this.renderNull} />
+                          <Field
+                            name='transactionCount'
+                            render={this.renderNull}
+                          />
 
                           <Field
                             as='textarea'
@@ -361,6 +364,8 @@ class TxForm extends Component {
     );
   }
 
+  renderNull = this.renderNull;
+
   /**
    * Prevalidate form on user's input. These validations are sync.
    */

From 66597ab10d51267a4e299e6c0bf3122ff560cea9 Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Fri, 22 Mar 2019 17:16:53 +0100
Subject: [PATCH 10/14] Fix regression

---
 packages/fether-react/src/Send/TxForm/TxForm.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/fether-react/src/Send/TxForm/TxForm.js b/packages/fether-react/src/Send/TxForm/TxForm.js
index 1bcd2d8a5..87a11e2dd 100644
--- a/packages/fether-react/src/Send/TxForm/TxForm.js
+++ b/packages/fether-react/src/Send/TxForm/TxForm.js
@@ -451,7 +451,7 @@ class TxForm extends Component {
       }
 
       if (values.gas && values.gas.eq(-1)) {
-        return {};
+        return { amount: 'Unable to estimate gas...' };
       }
 
       // If the gas hasn't been calculated yet, then we don't show any errors,

From ec47ea644a5cb5efb1a883a4b8987be789e54a48 Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Fri, 22 Mar 2019 17:21:18 +0100
Subject: [PATCH 11/14] Fix typo

---
 packages/fether-react/src/Send/TxForm/TxForm.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/fether-react/src/Send/TxForm/TxForm.js b/packages/fether-react/src/Send/TxForm/TxForm.js
index 87a11e2dd..60a8b5e46 100644
--- a/packages/fether-react/src/Send/TxForm/TxForm.js
+++ b/packages/fether-react/src/Send/TxForm/TxForm.js
@@ -364,7 +364,7 @@ class TxForm extends Component {
     );
   }
 
-  renderNull = this.renderNull;
+  renderNull = () => null;
 
   /**
    * Prevalidate form on user's input. These validations are sync.

From 814a625d1cfe13a3c5d46ef3e1451e5294aee608 Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Sun, 24 Mar 2019 23:25:07 +0100
Subject: [PATCH 12/14] Luke's grumbles

---
 packages/fether-react/src/Send/TxForm/TxForm.js | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/packages/fether-react/src/Send/TxForm/TxForm.js b/packages/fether-react/src/Send/TxForm/TxForm.js
index 60a8b5e46..005255bd0 100644
--- a/packages/fether-react/src/Send/TxForm/TxForm.js
+++ b/packages/fether-react/src/Send/TxForm/TxForm.js
@@ -434,28 +434,24 @@ class TxForm extends Component {
 
       // The 3 values below (`chainId`, `ethBalance`, and `transactionCount`)
       // come from props, and are passed into `values` via the form's
-      // initialValues. As such, they don't have visible fields, so putting an
-      // error here just means we're keeping the form state as not valid.
+      // initialValues. As such, they don't have visible fields, so we put
+      // their errors in the `amount` field arbitrarily.
       if (!values.chainId) {
-        return { chainId: 'Fetching chainId' };
+        return { amount: 'Fetching chain ID' };
       }
 
       if (!values.ethBalance) {
-        return { ethBalance: 'Fetching ethBalance' };
+        return { amount: 'Fetching Ether balance' };
       }
 
       if (!values.transactionCount) {
-        return {
-          transactionCount: 'Fetching transactionCount'
-        };
+        return { amount: 'Fetching transaction count for nonce' };
       }
 
       if (values.gas && values.gas.eq(-1)) {
         return { amount: 'Unable to estimate gas...' };
       }
 
-      // If the gas hasn't been calculated yet, then we don't show any errors,
-      // just wait a bit more
       if (!this.isEstimatedTxFee(values)) {
         return { amount: 'Estimating gas...' };
       }

From 6e5f772103ae32c142c7bde6c25c8e8ee9471b90 Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Mon, 25 Mar 2019 09:59:40 +0100
Subject: [PATCH 13/14] Put "checking..." when fetching async values

---
 .../fether-react/src/Send/TxForm/TxForm.js    | 31 ++++++++++++++-----
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/packages/fether-react/src/Send/TxForm/TxForm.js b/packages/fether-react/src/Send/TxForm/TxForm.js
index 005255bd0..3150275db 100644
--- a/packages/fether-react/src/Send/TxForm/TxForm.js
+++ b/packages/fether-react/src/Send/TxForm/TxForm.js
@@ -20,6 +20,7 @@ import { startWith } from 'rxjs/operators';
 import { withProps } from 'recompose';
 
 import { estimateGas } from '../../utils/transaction';
+import Debug from '../../utils/debug';
 import RequireHealthOverlay from '../../RequireHealthOverlay';
 import TokenBalance from '../../Tokens/TokensList/TokenBalance';
 import TxDetails from './TxDetails';
@@ -32,6 +33,8 @@ const MEDIUM_AMOUNT_MAX_CHARS = 14;
 const MAX_GAS_PRICE = 40; // In Gwei
 const MIN_GAS_PRICE = 3; // Safelow gas price from GasStation, in Gwei
 
+const debug = Debug('TxForm');
+
 @inject('parityStore', 'sendStore')
 @withTokens
 @withProps(({ match: { params: { tokenAddress } }, tokens }) => ({
@@ -234,6 +237,7 @@ class TxForm extends Component {
                     onSubmit={this.handleSubmit}
                     validate={this.validateForm}
                     render={({
+                      errors,
                       handleSubmit,
                       valid,
                       validating,
@@ -343,7 +347,11 @@ class TxForm extends Component {
                             disabled={!valid || validating}
                             className='button'
                           >
-                            {validating
+                            {validating ||
+                            errors.chainId ||
+                            errors.ethBalance ||
+                            errors.gas ||
+                            errors.transactionCount
                               ? 'Checking...'
                               : type === 'signer'
                                 ? 'Scan'
@@ -434,26 +442,31 @@ class TxForm extends Component {
 
       // The 3 values below (`chainId`, `ethBalance`, and `transactionCount`)
       // come from props, and are passed into `values` via the form's
-      // initialValues. As such, they don't have visible fields, so we put
-      // their errors in the `amount` field arbitrarily.
+      // initialValues. As such, they don't have visible fields, so these
+      // errors won't actually be shown on the UI.
       if (!values.chainId) {
-        return { amount: 'Fetching chain ID' };
+        debug('Fetching chain ID');
+        return { chainId: 'Fetching chain ID' };
       }
 
       if (!values.ethBalance) {
-        return { amount: 'Fetching Ether balance' };
+        debug('Fetching Ether balance');
+        return { ethBalance: 'Fetching Ether balance' };
       }
 
       if (!values.transactionCount) {
-        return { amount: 'Fetching transaction count for nonce' };
+        debug('Fetching transaction count for nonce');
+        return { transactionCount: 'Fetching transaction count for nonce' };
       }
 
       if (values.gas && values.gas.eq(-1)) {
-        return { amount: 'Unable to estimate gas...' };
+        debug('Unable to estimate gas...');
+        return { gas: 'Unable to estimate gas...' };
       }
 
       if (!this.isEstimatedTxFee(values)) {
-        return { amount: 'Estimating gas...' };
+        debug('Estimating gas...');
+        return { gas: 'Estimating gas...' };
       }
 
       // Verify that `gas + (eth amount if sending eth) <= ethBalance`
@@ -466,6 +479,8 @@ class TxForm extends Component {
           ? { amount: 'ETH balance too low to pay for gas' }
           : { amount: "You don't have enough ETH balance" };
       }
+
+      debug('Transaction seems valid');
     } catch (err) {
       console.error(err);
       return {

From 041148eafc712e5f0e017b3514c42e65db274fe5 Mon Sep 17 00:00:00 2001
From: Amaury Martiny <amaury.martiny@protonmail.com>
Date: Mon, 25 Mar 2019 10:02:14 +0100
Subject: [PATCH 14/14] Show gas error on amount field

---
 packages/fether-react/src/Send/TxForm/TxForm.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/packages/fether-react/src/Send/TxForm/TxForm.js b/packages/fether-react/src/Send/TxForm/TxForm.js
index 3150275db..a825084a2 100644
--- a/packages/fether-react/src/Send/TxForm/TxForm.js
+++ b/packages/fether-react/src/Send/TxForm/TxForm.js
@@ -461,7 +461,8 @@ class TxForm extends Component {
 
       if (values.gas && values.gas.eq(-1)) {
         debug('Unable to estimate gas...');
-        return { gas: 'Unable to estimate gas...' };
+        // Show this error on the `amount` field
+        return { amount: 'Unable to estimate gas...' };
       }
 
       if (!this.isEstimatedTxFee(values)) {
