diff --git a/src/js/actions/SelectedAccountActions.js b/src/js/actions/SelectedAccountActions.js index 9190201a..6f801039 100644 --- a/src/js/actions/SelectedAccountActions.js +++ b/src/js/actions/SelectedAccountActions.js @@ -36,6 +36,7 @@ export const updateSelectedValues = (prevState: State, action: Action): AsyncAct const locationChange: boolean = action.type === LOCATION_CHANGE; const state: State = getState(); const location = state.router.location; + const prevLocation = prevState.router.location; let needUpdate: boolean = false; @@ -51,13 +52,14 @@ export const updateSelectedValues = (prevState: State, action: Action): AsyncAct || prevState.accounts !== state.accounts || prevState.discovery !== state.discovery || prevState.tokens !== state.tokens + || prevState.pending !== state.pending || prevState.web3 !== state.web3) { const account = stateUtils.getSelectedAccount(state); const network = stateUtils.getSelectedNetwork(state); const discovery = stateUtils.getDiscoveryProcess(state); const tokens = stateUtils.getAccountTokens(state, account); - const pending = stateUtils.getAccountPendingTx(state, account); + const pending = stateUtils.getAccountPendingTx(state.pending, account); const web3 = stateUtils.getWeb3(state); const payload: $ElementType = { @@ -81,13 +83,17 @@ export const updateSelectedValues = (prevState: State, action: Action): AsyncAct dispatch({ type: ACCOUNT.UPDATE_SELECTED_ACCOUNT, payload, - }) + }); } if (locationChange) { - if (prevState.router.location && prevState.router.location.state.send) { - SessionStorageActions.save(prevState.router.location.pathname, state.sendForm); + if (prevLocation) { + // save form data to session storage + // TODO: move to state.sendForm on change event + if (prevLocation.state.send) { + SessionStorageActions.save(prevState.router.location.pathname, state.sendForm); + } } dispatch( dispose() ); diff --git a/src/js/actions/SendFormActions.js b/src/js/actions/SendFormActions.js index db041763..4867afd6 100644 --- a/src/js/actions/SendFormActions.js +++ b/src/js/actions/SendFormActions.js @@ -18,8 +18,10 @@ import { initialState } from '../reducers/SendFormReducer'; import { findAccount } from '../reducers/AccountsReducer'; import { findToken } from '../reducers/TokensReducer'; import { findDevice } from '../reducers/utils'; +import * as stateUtils from '../reducers/utils'; import type { + PendingTx, Dispatch, GetState, Action, @@ -41,6 +43,8 @@ export type SendTxAction = { account: Account, selectedCurrency: string, amount: string, + total: string, + tx: any, txid: string, txData: any, }; @@ -156,8 +160,6 @@ export const calculate = (prevProps: Props, props: Props) => { } = props.selectedAccount; if (!account) return; - console.warn("CALCULATE!", props) - const prevState = prevProps.sendForm; const state = props.sendForm; const isToken: boolean = state.currency !== state.networkSymbol; @@ -173,18 +175,16 @@ export const calculate = (prevProps: Props, props: Props) => { if (state.setMax) { - const pendingAmount = pending.reduce((value, p) => { - //if (p.tx.amount) - console.warn("PENDING AMOUNT!", p, value); - }, 0); + const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, state.currency); if (isToken) { const token: ?Token = findToken(tokens, account.address, state.currency, account.deviceState); if (token) { - state.amount = token.balance; + state.amount = new BigNumber(token.balance).minus(pendingAmount).toString(); } } else { - state.amount = calculateMaxAmount(account.balance, state.gasPrice, state.gasLimit); + const b = new BigNumber(account.balance).minus(pendingAmount).toString(); + state.amount = calculateMaxAmount(b, state.gasPrice, state.gasLimit); } } @@ -350,6 +350,7 @@ export const validation = (props: Props): void => { account, network, tokens, + pending, } = props.selectedAccount; if (!account || !network) return; @@ -389,6 +390,7 @@ export const validation = (props: Props): void => { } else { let decimalRegExp: RegExp; + const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, state.currency); if (state.currency !== state.networkSymbol) { const token = findToken(tokens, account.address, state.currency, account.deviceState); @@ -405,7 +407,7 @@ export const validation = (props: Props): void => { errors.amount = `Maximum ${ token.decimals} decimals allowed`; } else if (new BigNumber(state.total).greaterThan(account.balance)) { errors.amount = `Not enough ${ state.networkSymbol } to cover transaction fee`; - } else if (new BigNumber(state.amount).greaterThan(token.balance)) { + } else if (new BigNumber(state.amount).greaterThan( new BigNumber(token.balance).minus(pendingAmount) )) { errors.amount = 'Not enough funds'; } else if (new BigNumber(state.amount).lessThanOrEqualTo('0')) { errors.amount = 'Amount is too low'; @@ -416,7 +418,7 @@ export const validation = (props: Props): void => { decimalRegExp = new RegExp('^(0|0\\.([0-9]{0,18})?|[1-9][0-9]*\\.?([0-9]{0,18})?|\\.[0-9]{0,18})$'); if (!state.amount.match(decimalRegExp)) { errors.amount = `Maximum 18 decimals allowed`; - } else if (new BigNumber(state.total).greaterThan(account.balance)) { + } else if (new BigNumber(state.total).greaterThan( new BigNumber(account.balance).minus(pendingAmount) )) { errors.amount = 'Not enough funds'; } } @@ -916,6 +918,8 @@ export const onSend = (): AsyncAction => { account: account, selectedCurrency: currentState.currency, amount: currentState.amount, + total: currentState.total, + tx, txid, txData, }); diff --git a/src/js/components/wallet/account/send/PendingTransactions.js b/src/js/components/wallet/account/send/PendingTransactions.js index 9449e9b1..d8dee0ca 100644 --- a/src/js/components/wallet/account/send/PendingTransactions.js +++ b/src/js/components/wallet/account/send/PendingTransactions.js @@ -34,7 +34,7 @@ const PendingTransactions = (props: Props) => { const bgColorFactory = new ColorHash({lightness: 0.7}); const textColorFactory = new ColorHash(); - const pendingTxs = pending.map((tx, i) => { + const pendingTxs: React$Element = pending.map((tx, i) => { let iconColor: Style; let symbol: string; @@ -80,7 +80,7 @@ const PendingTransactions = (props: Props) => {
{ name }
-
{ tx.amount } { symbol }
+
{ tx.total } { symbol }
) }); diff --git a/src/js/components/wallet/account/summary/Summary.js b/src/js/components/wallet/account/summary/Summary.js index 4d053439..5c240b33 100644 --- a/src/js/components/wallet/account/summary/Summary.js +++ b/src/js/components/wallet/account/summary/Summary.js @@ -11,6 +11,7 @@ import SelectedAccount from '../SelectedAccount'; import { Notification } from '~/js/components/common/Notification'; import SummaryDetails from './SummaryDetails.js'; import SummaryTokens from './SummaryTokens.js'; +import * as stateUtils from '~/js/reducers/utils'; import type { Props } from './index'; import type { NetworkToken } from '~/js/reducers/LocalStorageReducer'; @@ -21,6 +22,7 @@ const Summary = (props: Props) => { account, network, tokens, + pending } = props.selectedAccount; // flow @@ -33,6 +35,9 @@ const Summary = (props: Props) => { ); const explorerLink: string = `${network.explorer.address}${account.address}`; + const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, network.symbol); + const balance: string = new BigNumber(account.balance).minus(pendingAmount).toString(); + return (

@@ -43,7 +48,7 @@ const Summary = (props: Props) => { => { let balance: string = 'Loading...'; if (account.balance !== '') { + const pending = stateUtils.getAccountPendingTx(props.pending, account); + const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, selectedCoin.symbol); + const availableBalance: string = new BigNumber(account.balance).minus(pendingAmount).toString(); + if (fiatRate) { - const accountBalance = new BigNumber(account.balance); + const accountBalance = new BigNumber(availableBalance); const fiat = accountBalance.times(fiatRate.value).toFixed(2); - balance = `${ account.balance } ${ selectedCoin.symbol } / $${ fiat }`; + balance = `${ availableBalance } ${ selectedCoin.symbol } / $${ fiat }`; } else { - balance = `${ account.balance } ${ selectedCoin.symbol }`; + balance = `${ availableBalance } ${ selectedCoin.symbol }`; } } diff --git a/src/js/components/wallet/aside/index.js b/src/js/components/wallet/aside/index.js index 89494174..ebc877a2 100644 --- a/src/js/components/wallet/aside/index.js +++ b/src/js/components/wallet/aside/index.js @@ -28,6 +28,7 @@ type StateProps = { discovery: $ElementType, wallet: $ElementType, devices: $ElementType, + pending: $ElementType, } type DispatchProps = { @@ -52,7 +53,8 @@ const mapStateToProps: MapStateToProps = (state: St localStorage: state.localStorage, discovery: state.discovery, wallet: state.wallet, - devices: state.devices + devices: state.devices, + pending: state.pending, }; } diff --git a/src/js/reducers/PendingTxReducer.js b/src/js/reducers/PendingTxReducer.js index 42491005..7042d812 100644 --- a/src/js/reducers/PendingTxReducer.js +++ b/src/js/reducers/PendingTxReducer.js @@ -13,6 +13,8 @@ export type PendingTx = { +network: string; +currency: string; +amount: string; + +total: string; + +tx: any; +address: string; } @@ -27,6 +29,8 @@ const add = (state: State, action: SendTxAction): State => { network: action.account.network, currency: action.selectedCurrency, amount: action.amount, + total: action.total, + tx: action.tx, address: action.account.address, }); return newState; diff --git a/src/js/reducers/utils/index.js b/src/js/reducers/utils/index.js index 28f7a8a5..3f81e7e2 100644 --- a/src/js/reducers/utils/index.js +++ b/src/js/reducers/utils/index.js @@ -4,6 +4,7 @@ import * as LogActions from '~/js/actions/LogActions'; import * as STORAGE from '~/js/actions/constants/localStorage'; import * as WALLET from '~/js/actions/constants/wallet'; +import BigNumber from 'bignumber.js'; import type { Middleware, @@ -84,15 +85,24 @@ export const getDiscoveryProcess = (state: State): ?Discovery => { return state.discovery.find(d => d.deviceState === device.state && d.network === locationState.network); } -export const getAccountPendingTx = (state: State, account: ?Account): Array => { +export const getAccountPendingTx = (pending: Array, account: ?Account): Array => { const a = account; - if (!a) return state.selectedAccount.pending.length > 0 ? [] : state.selectedAccount.pending; - return state.pending.filter(p => p.network === a.network && p.address === a.address); + if (!a) return []; + return pending.filter(p => p.network === a.network && p.address === a.address); +} + +export const getPendingAmount = (pending: Array, currency: string): BigNumber => { + return pending.reduce((value: BigNumber, tx: PendingTx) => { + if (tx.currency === currency) { + return new BigNumber(value).plus(tx.amount); + } + return value; + }, new BigNumber('0')); } export const getAccountTokens = (state: State, account: ?Account): Array => { const a = account; - if (!a) return state.selectedAccount.tokens.length > 0 ? [] : state.selectedAccount.tokens; + if (!a) return []; return state.tokens.filter(t => t.ethAddress === a.address && t.network === a.network && t.deviceState === a.deviceState); } @@ -100,4 +110,5 @@ export const getWeb3 = (state: State): ?Web3Instance => { const locationState = state.router.location.state; if (!locationState.network) return null; return state.web3.find(w3 => w3.network === locationState.network); -} \ No newline at end of file +} +