diff --git a/src/views/Wallet/views/AccountSend/components/Advanced/index.js b/src/views/Wallet/views/AccountSend/components/Advanced/index.js
new file mode 100644
index 00000000..dd9d44e6
--- /dev/null
+++ b/src/views/Wallet/views/AccountSend/components/Advanced/index.js
@@ -0,0 +1,221 @@
+/* @flow */
+
+import React from 'react';
+import styled from 'styled-components';
+import colors from 'config/colors';
+
+import Input from 'components/inputs/Input';
+import Textarea from 'components/Textarea';
+import Tooltip from 'components/Tooltip';
+import Icon from 'components/Icon';
+import Link from 'components/Link';
+import ICONS from 'config/icons';
+
+import type { Props } from '../../Container';
+
+// duplicates from ../../Container
+const InputRow = styled.div`
+ margin-bottom: 20px;
+`;
+// duplicates end
+
+const InputLabelWrapper = styled.div`
+ display: flex;
+ align-items: center;
+`;
+
+const GreenSpan = styled.span`
+ color: ${colors.GREEN_PRIMARY};
+`;
+
+const AdvancedSettingsWrapper = styled.div`
+ padding: 20px 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+
+ border-top: 1px solid ${colors.DIVIDER};
+`;
+
+const GasInputRow = styled(InputRow)`
+ width: 100%;
+ display: flex;
+`;
+
+const GasInput = styled(Input)`
+ &:first-child {
+ padding-right: 20px;
+ }
+`;
+
+const StyledTextarea = styled(Textarea)`
+ margin-bottom: 20px;
+ height: 80px;
+`;
+
+const AdvancedSettingsSendButtonWrapper = styled.div`
+ width: 100%;
+ display: flex;
+ justify-content: flex-end;
+`;
+
+const getGasLimitInputState = (gasLimitErrors: string, gasLimitWarnings: string): string => {
+ let state = '';
+ if (gasLimitWarnings && !gasLimitErrors) {
+ state = 'warning';
+ }
+ if (gasLimitErrors) {
+ state = 'error';
+ }
+ return state;
+};
+
+const getGasPriceInputState = (gasPriceErrors: string, gasPriceWarnings: string): string => {
+ let state = '';
+ if (gasPriceWarnings && !gasPriceErrors) {
+ state = 'warning';
+ }
+ if (gasPriceErrors) {
+ state = 'error';
+ }
+ return state;
+};
+
+// stateless component
+const AdvancedForm = (props: Props) => {
+ const {
+ network,
+ } = props.selectedAccount;
+ if (!network) return null;
+ const {
+ networkSymbol,
+ currency,
+ recommendedGasPrice,
+ errors,
+ warnings,
+ infos,
+ data,
+ gasLimit,
+ gasPrice,
+ } = props.sendForm;
+ const {
+ onGasLimitChange,
+ onGasPriceChange,
+ onDataChange,
+ } = props.sendFormActions;
+
+ let gasLimitTooltipCurrency: string;
+ let gasLimitTooltipValue: string;
+ if (networkSymbol !== currency) {
+ gasLimitTooltipCurrency = 'tokens';
+ gasLimitTooltipValue = network.defaultGasLimitTokens.toString(10);
+ } else {
+ gasLimitTooltipCurrency = networkSymbol;
+ gasLimitTooltipValue = network.defaultGasLimit.toString(10);
+ }
+
+ return (
+
+
+
+ Gas limit
+
+ Gas limit is the amount of gas to send with your transaction.
+ TX fee = gas price * gas limit & is paid to miners for including your TX in a block.
+ Increasing this number will not get your TX mined faster.
+ Default value for sending {gasLimitTooltipCurrency} is {gasLimitTooltipValue}
+
+ )}
+ placement="top"
+ >
+
+
+
+ )}
+ bottomText={errors.gasLimit || warnings.gasLimit || infos.gasLimit}
+ value={gasLimit}
+ isDisabled={networkSymbol === currency && data.length > 0}
+ onChange={event => onGasLimitChange(event.target.value)}
+ />
+
+
+ Gas price
+
+ Gas Price is the amount you pay per unit of gas.
+ TX fee = gas price * gas limit & is paid to miners for including your TX in a block.
+ Higher the gas price = faster transaction, but more expensive. Recommended is {recommendedGasPrice} GWEI.
+ Read more
+
+ )}
+ placement="top"
+ >
+
+
+
+ )}
+ bottomText={errors.gasPrice || warnings.gasPrice || infos.gasPrice}
+ value={gasPrice}
+ onChange={event => onGasPriceChange(event.target.value)}
+ />
+
+
+
+ Data
+
+ Data is usually used when you send transactions to contracts.
+
+ )}
+ placement="top"
+ >
+
+
+
+ )}
+ bottomText={errors.data || warnings.data || infos.data}
+ disabled={networkSymbol !== currency}
+ value={networkSymbol !== currency ? '' : data}
+ onChange={event => onDataChange(event.target.value)}
+ />
+
+
+ { props.children }
+
+
+ );
+};
+
+export default AdvancedForm;
\ No newline at end of file
diff --git a/src/views/Wallet/views/AccountSend/index.js b/src/views/Wallet/views/AccountSend/index.js
index c2318e72..64863ab3 100644
--- a/src/views/Wallet/views/AccountSend/index.js
+++ b/src/views/Wallet/views/AccountSend/index.js
@@ -1,6 +1,6 @@
/* @flow */
-import React, { Component } from 'react';
+import React from 'react';
import styled, { css } from 'styled-components';
import { Select } from 'components/Select';
import Button from 'components/Button';
@@ -12,11 +12,9 @@ import { FONT_SIZE, FONT_WEIGHT, TRANSITION } from 'config/variables';
import colors from 'config/colors';
import P from 'components/Paragraph';
import { H2 } from 'components/Heading';
-import Textarea from 'components/Textarea';
-import Tooltip from 'components/Tooltip';
-import { calculate, validation } from 'actions/SendFormActions';
import SelectedAccount from 'views/Wallet/components/SelectedAccount';
import type { Token } from 'flowtype';
+import AdvancedForm from './components/Advanced';
import PendingTransactions from './components/PendingTransactions';
import type { Props } from './Container';
@@ -25,11 +23,6 @@ import type { Props } from './Container';
// and put it inside config/variables.js
const SmallScreenWidth = '850px';
-type State = {
- isAdvancedSettingsHidden: boolean,
- shouldAnimateAdvancedSettingsToggle: boolean,
-};
-
const Wrapper = styled.section`
padding: 0 48px;
`;
@@ -143,453 +136,255 @@ const SendButton = styled(Button)`
}
`;
-const AdvancedSettingsWrapper = styled.div`
- padding: 20px 0;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
-
- border-top: 1px solid ${colors.DIVIDER};
-`;
-
-const GasInputRow = styled(InputRow)`
- width: 100%;
- display: flex;
-`;
-
-const GasInput = styled(Input)`
- &:first-child {
- padding-right: 20px;
- }
-`;
-
-const AdvancedSettingsSendButtonWrapper = styled.div`
- width: 100%;
- display: flex;
- justify-content: flex-end;
-`;
-
-const StyledTextarea = styled(Textarea)`
- margin-bottom: 20px;
- height: 80px;
-`;
-
const AdvancedSettingsIcon = styled(Icon)`
margin-left: 10px;
`;
-const GreenSpan = styled.span`
- color: ${colors.GREEN_PRIMARY};
-`;
+// render helpers
+const getAddressInputState = (address: string, addressErrors: string, addressWarnings: string): string => {
+ let state = '';
+ if (address && !addressErrors) {
+ state = 'success';
+ }
+ if (addressWarnings && !addressErrors) {
+ state = 'warning';
+ }
+ if (addressErrors) {
+ state = 'error';
+ }
+ return state;
+};
-const InputLabelWrapper = styled.div`
- display: flex;
- align-items: center;
-`;
+const getAmountInputState = (amountErrors: string, amountWarnings: string): string => {
+ let state = '';
+ if (amountWarnings && !amountErrors) {
+ state = 'warning';
+ }
+ if (amountErrors) {
+ state = 'error';
+ }
+ return state;
+};
-class AccountSend extends Component {
- constructor(props: Props) {
- super(props);
- this.state = {
- isAdvancedSettingsHidden: true,
- shouldAnimateAdvancedSettingsToggle: false,
- };
+const getTokensSelectData = (tokens: Array, accountNetwork: any): Array<{ value: string, label: string }> => {
+ const tokensSelectData: Array<{ value: string, label: string }> = tokens.map(t => ({ value: t.symbol, label: t.symbol }));
+ tokensSelectData.unshift({ value: accountNetwork.symbol, label: accountNetwork.symbol });
+
+ return tokensSelectData;
+};
+
+// stateless component
+const AccountSend = (props: Props) => {
+ const device = props.wallet.selectedDevice;
+ const {
+ account,
+ network,
+ discovery,
+ tokens,
+ } = props.selectedAccount;
+ const {
+ address,
+ amount,
+ setMax,
+ networkSymbol,
+ currency,
+ feeLevels,
+ selectedFeeLevel,
+ gasPriceNeedsUpdate,
+ total,
+ errors,
+ warnings,
+ infos,
+ data,
+ sending,
+ advanced,
+ } = props.sendForm;
+
+ const {
+ toggleAdvanced,
+ onAddressChange,
+ onAmountChange,
+ onSetMax,
+ onCurrencyChange,
+ onFeeLevelChange,
+ updateFeeLevels,
+ onSend,
+ } = props.sendFormActions;
+
+ if (!device || !account || !discovery || !network) return null;
+
+ let isSendButtonDisabled: boolean = Object.keys(errors).length > 0 || total === '0' || amount.length === 0 || address.length === 0 || sending;
+ let sendButtonText: string = 'Send';
+ if (networkSymbol !== currency && amount.length > 0 && !errors.amount) {
+ sendButtonText += ` ${amount} ${currency.toUpperCase()}`;
+ } else if (networkSymbol === currency && total !== '0') {
+ sendButtonText += ` ${total} ${network.symbol}`;
}
- componentWillReceiveProps(newProps: Props) {
- calculate(this.props, newProps);
- validation(newProps);
+ if (!device.connected) {
+ sendButtonText = 'Device is not connected';
+ isSendButtonDisabled = true;
+ } else if (!device.available) {
+ sendButtonText = 'Device is unavailable';
+ isSendButtonDisabled = true;
+ } else if (!discovery.completed) {
+ sendButtonText = 'Loading accounts';
+ isSendButtonDisabled = true;
}
- getAddressInputState(address: string, addressErrors: string, addressWarnings: string) {
- let state = '';
- if (address && !addressErrors) {
- state = 'success';
- }
- if (addressWarnings && !addressErrors) {
- state = 'warning';
- }
- if (addressErrors) {
- state = 'error';
- }
- return state;
- }
+ const tokensSelectData = getTokensSelectData(tokens, network);
+ const isAdvancedSettingsHidden = !advanced;
+ // eslint workaround (is this some bug?)
+ // if i put {true} directly to "AdvancedSettingsIcon" component
+ // i get eslint error
+ const advancedButtonCanAnimate = true;
- getAmountInputState(amountErrors: string, amountWarnings: string) {
- let state = '';
- if (amountWarnings && !amountErrors) {
- state = 'warning';
- }
- if (amountErrors) {
- state = 'error';
- }
- return state;
- }
+ return (
+
+
+ Send Ethereum or tokens
+
+ onAddressChange(event.target.value)}
+ />
+
- getGasLimitInputState(gasLimitErrors: string, gasLimitWarnings: string) {
- let state = '';
- if (gasLimitWarnings && !gasLimitErrors) {
- state = 'warning';
- }
- if (gasLimitErrors) {
- state = 'error';
- }
- return state;
- }
-
- getGasPriceInputState(gasPriceErrors: string, gasPriceWarnings: string) {
- let state = '';
- if (gasPriceWarnings && !gasPriceErrors) {
- state = 'warning';
- }
- if (gasPriceErrors) {
- state = 'error';
- }
- return state;
- }
-
- getTokensSelectData(tokens: Array, accountNetwork: any) {
- const tokensSelectData: Array<{ value: string, label: string }> = tokens.map(t => ({ value: t.symbol, label: t.symbol }));
- tokensSelectData.unshift({ value: accountNetwork.symbol, label: accountNetwork.symbol });
-
- return tokensSelectData;
- }
-
- handleToggleAdvancedSettingsButton() {
- this.toggleAdvancedSettings();
- }
-
- toggleAdvancedSettings() {
- this.setState(previousState => ({
- isAdvancedSettingsHidden: !previousState.isAdvancedSettingsHidden,
- shouldAnimateAdvancedSettingsToggle: true,
- }));
- }
-
- render() {
- const device = this.props.wallet.selectedDevice;
- const {
- account,
- network,
- discovery,
- tokens,
- } = this.props.selectedAccount;
- const {
- address,
- amount,
- setMax,
- networkSymbol,
- currency,
- feeLevels,
- selectedFeeLevel,
- recommendedGasPrice,
- gasPriceNeedsUpdate,
- total,
- errors,
- warnings,
- infos,
- data,
- sending,
- gasLimit,
- gasPrice,
- } = this.props.sendForm;
-
- const {
- onAddressChange,
- onAmountChange,
- onSetMax,
- onCurrencyChange,
- onFeeLevelChange,
- updateFeeLevels,
- onSend,
- onGasLimitChange,
- onGasPriceChange,
- onDataChange,
- } = this.props.sendFormActions;
-
- if (!device || !account || !discovery || !network) return null;
-
- let isSendButtonDisabled: boolean = Object.keys(errors).length > 0 || total === '0' || amount.length === 0 || address.length === 0 || sending;
- let sendButtonText: string = 'Send';
- if (networkSymbol !== currency && amount.length > 0 && !errors.amount) {
- sendButtonText += ` ${amount} ${currency.toUpperCase()}`;
- } else if (networkSymbol === currency && total !== '0') {
- sendButtonText += ` ${total} ${network.symbol}`;
- }
-
- if (!device.connected) {
- sendButtonText = 'Device is not connected';
- isSendButtonDisabled = true;
- } else if (!device.available) {
- sendButtonText = 'Device is unavailable';
- isSendButtonDisabled = true;
- } else if (!discovery.completed) {
- sendButtonText = 'Loading accounts';
- isSendButtonDisabled = true;
- }
-
- const tokensSelectData = this.getTokensSelectData(tokens, network);
-
- let gasLimitTooltipCurrency: string;
- let gasLimitTooltipValue: string;
- if (networkSymbol !== currency) {
- gasLimitTooltipCurrency = 'tokens';
- gasLimitTooltipValue = network.defaultGasLimitTokens.toString(10);
- } else {
- gasLimitTooltipCurrency = networkSymbol;
- gasLimitTooltipValue = network.defaultGasLimit.toString(10);
- }
-
-
- return (
-
-
- Send Ethereum or tokens
-
- onAddressChange(event.target.value)}
- />
-
-
-
- onAmountChange(event.target.value)}
- bottomText={errors.amount || warnings.amount || infos.amount}
- sideAddons={[
- (
- onSetMax()}
- isActive={setMax}
- >
- {!setMax && (
-
- )}
- {setMax && (
-
- )}
- Set max
-
- ),
- (
-
- ),
- ]}
- />
-
-
-
-
- Fee
- {gasPriceNeedsUpdate && (
-
-
- Recommended fees updated. Click here to use them
-
- )}
-
-
-
-
- this.handleToggleAdvancedSettingsButton()}
- >
- Advanced settings
-
-
-
- {this.state.isAdvancedSettingsHidden && (
- onSend()}
- >
- {sendButtonText}
-
- )}
-
-
- {!this.state.isAdvancedSettingsHidden && (
-
-
-
- Gas limit
-
- Gas limit is the amount of gas to send with your transaction.
- TX fee = gas price * gas limit & is paid to miners for including your TX in a block.
- Increasing this number will not get your TX mined faster.
- Default value for sending {gasLimitTooltipCurrency} is {gasLimitTooltipValue}
-
- )}
- placement="top"
- >
-
-
-
- )}
- bottomText={errors.gasLimit || warnings.gasLimit || infos.gasLimit}
- value={gasLimit}
- isDisabled={networkSymbol === currency && data.length > 0}
- onChange={event => onGasLimitChange(event.target.value)}
- />
-
-
- Gas price
-
- Gas Price is the amount you pay per unit of gas.
- TX fee = gas price * gas limit & is paid to miners for including your TX in a block.
- Higher the gas price = faster transaction, but more expensive. Recommended is {recommendedGasPrice} GWEI.
- Read more
-
- )}
- placement="top"
- >
-
-
-
- )}
- bottomText={errors.gasPrice || warnings.gasPrice || infos.gasPrice}
- value={gasPrice}
- onChange={event => onGasPriceChange(event.target.value)}
- />
-
-
-
- Data
-
- Data is usually used when you send transactions to contracts.
-
- )}
- placement="top"
- >
-
-
-
- )}
- disabled={networkSymbol !== currency}
- value={networkSymbol !== currency ? '' : data}
- onChange={event => onDataChange(event.target.value)}
- />
-
-
- onSend()}
+
+ onAmountChange(event.target.value)}
+ bottomText={errors.amount || warnings.amount || infos.amount}
+ sideAddons={[
+ (
+ onSetMax()}
+ isActive={setMax}
>
- {sendButtonText}
-
-
-
- )}
+ {!setMax && (
+
+ )}
+ {setMax && (
+
+ )}
+ Set max
+
+ ),
+ (
+
+ ),
+ ]}
+ />
+
- {this.props.selectedAccount.pending.length > 0 && (
-
+
+ Fee
+ {gasPriceNeedsUpdate && (
+
+
+ Recommended fees updated. Click here to use them
+
+ )}
+
+
-
- );
- }
-}
+
+ {isAdvancedSettingsHidden && (
+ onSend()}
+ >
+ {sendButtonText}
+
+ )}
+
+
+ {advanced && (
+
+ onSend()}
+ >
+ {sendButtonText}
+
+
+ )}
+
+ {props.selectedAccount.pending.length > 0 && (
+
+ )}
+
+
+ );
+};
export default AccountSend;