import { showNotification, TShowNotification } from 'actions/notifications'; import { broadcastTx, TBroadcastTx } from 'actions/wallet'; import Big from 'bignumber.js'; import { BalanceSidebar } from 'components'; // COMPONENTS import { UnlockHeader } from 'components/ui'; import { donationAddressMap, NetworkConfig, NodeConfig } from 'config/data'; // CONFIG import { TransactionWithoutGas } from 'libs/messages'; import { RPCNode } from 'libs/nodes'; import { BroadcastTransactionStatus, CompleteTransaction, formatTxInput, generateCompleteTransaction, getBalanceMinusGasCosts, TransactionInput } from 'libs/transaction'; import { Ether, GWei, UnitKey, Wei } from 'libs/units'; import { isValidETHAddress } from 'libs/validators'; // LIBS import { IWallet } from 'libs/wallet/IWallet'; import pickBy from 'lodash/pickBy'; import React from 'react'; // REDUX import { connect } from 'react-redux'; import { AppState } from 'reducers'; import { getGasPriceGwei, getNetworkConfig, getNodeConfig, getNodeLib } from 'selectors/config'; // SELECTORS import { getTokenBalances, getTokens, getTxFromBroadcastTransactionStatus, MergedToken, TokenBalance } from 'selectors/wallet'; import translate from 'translations'; // UTILS import { formatGasLimit } from 'utils/formatters'; import { AddressField, AmountField, ConfirmationModal, CustomMessage, DataField, GasField } from './components'; // MISC import customMessages from './messages'; function getParam(query: { [key: string]: string }, key: string) { const keys = Object.keys(query); const index = keys.findIndex(k => k.toLowerCase() === key.toLowerCase()); if (index === -1) { return null; } return query[keys[index]]; } interface State { hasQueryString: boolean; readOnly: boolean; to: string; // amount value value: string; unit: UnitKey; token?: MergedToken | null; gasLimit: string; data: string; gasChanged: boolean; transaction: CompleteTransaction | null; showTxConfirm: boolean; generateDisabled: boolean; } interface Props { location: { query: { [key: string]: string; }; }; wallet: IWallet; balance: Ether; node: NodeConfig; nodeLib: RPCNode; network: NetworkConfig; tokens: MergedToken[]; tokenBalances: TokenBalance[]; gasPrice: Wei; transactions: BroadcastTransactionStatus[]; showNotification: TShowNotification; broadcastTx: TBroadcastTx; } const initialState: State = { hasQueryString: false, readOnly: false, to: '', value: '', unit: 'ether', token: null, gasLimit: '21000', data: '', gasChanged: false, showTxConfirm: false, transaction: null, generateDisabled: true }; export class SendTransaction extends React.Component { public state: State = initialState; public componentDidMount() { const queryPresets = pickBy(this.parseQuery()); if (Object.keys(queryPresets).length) { this.setState({ ...queryPresets, hasQueryString: true }); } } public componentDidUpdate(prevProps: Props, prevState: State) { // TODO listen to gas price changes here // TODO debounce the call if ( // if gas has not changed !this.state.gasChanged && // if we have valid tx this.isValid() && // if any relevant fields changed (this.state.to !== prevState.to || this.state.value !== prevState.value || this.state.unit !== prevState.unit || this.state.data !== prevState.data) ) { if (!isNaN(parseInt(this.state.value, 10))) { this.estimateGas(); } } if (this.state.generateDisabled === this.isValid()) { this.setState({ generateDisabled: !this.isValid() }); } const componentStateTransaction = this.state.transaction; if (componentStateTransaction) { // lives in redux state const currentTxAsSignedTransaction = getTxFromBroadcastTransactionStatus( this.props.transactions, componentStateTransaction.signedTx ); // if there is a matching tx in redux state if (currentTxAsSignedTransaction) { // if the broad-casted transaction attempt is successful, clear the form if (currentTxAsSignedTransaction.successfullyBroadcast) { this.resetTx(); } } } } public render() { const unlocked = !!this.props.wallet; const { to, value, unit, gasLimit, data, readOnly, hasQueryString, showTxConfirm, transaction } = this.state; const customMessage = customMessages.find(m => m.to === to); return (
{/* Send Form */} {unlocked && (
{hasQueryString && (

{translate('WARN_Send_Link')}

)} !token.balance.eq(0)) .map(token => token.symbol) .sort()} onChange={readOnly ? void 0 : this.onAmountChange} /> {unit === 'ether' && ( )}
{transaction && (