diff --git a/src/actions/LocalStorageActions.js b/src/actions/LocalStorageActions.js index 7742b345..3fed5c65 100644 --- a/src/actions/LocalStorageActions.js +++ b/src/actions/LocalStorageActions.js @@ -63,7 +63,7 @@ const findTokens = (accounts: Array, tokens: Array): Array, discovery: Array): Array => devices.reduce((arr, dev) => arr.concat(discovery.filter(d => d.deviceState === dev.state && d.completed)), []); -const findPendingTxs = (accounts: Array, pending: Array): Array => accounts.reduce((result, account) => result.concat(pending.filter(p => p.address === account.descriptor && p.network === account.network)), []); +const findPendingTxs = (accounts: Array, pending: Array): Array => accounts.reduce((result, account) => result.concat(pending.filter(p => p.descriptor === account.descriptor && p.network === account.network)), []); export const save = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { const devices: Array = getState().devices.filter(d => d.features && d.remember === true); diff --git a/src/actions/ethereum/BlockchainActions.js b/src/actions/ethereum/BlockchainActions.js index 24e51ff4..8632e013 100644 --- a/src/actions/ethereum/BlockchainActions.js +++ b/src/actions/ethereum/BlockchainActions.js @@ -131,10 +131,10 @@ export const onBlockMined = (network: string): PromiseAction => async (dis export const onNotification = (payload: $ElementType): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { const { notification } = payload; - const account = getState().accounts.find(a => a.descriptor === notification.address); + const account = getState().accounts.find(a => a.descriptor === notification.descriptor); if (!account) return; - if (notification.status === 'pending') { + if (!notification.blockHeight) { dispatch({ type: PENDING.ADD, payload: { diff --git a/src/actions/ethereum/SendFormActions.js b/src/actions/ethereum/SendFormActions.js index 0b4be855..af5d3108 100644 --- a/src/actions/ethereum/SendFormActions.js +++ b/src/actions/ethereum/SendFormActions.js @@ -530,9 +530,7 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge const fee = ValidationActions.calculateFee(currentState.gasLimit, currentState.gasPrice); const blockchainNotification = { type: 'send', - status: 'pending', - confirmations: 0, - address: account.descriptor, + descriptor: account.descriptor, inputs: [ { addresses: [account.descriptor], @@ -553,7 +551,14 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge total: currentState.total, sequence: nonce, - currency: isToken ? currentState.currency : undefined, + tokens: isToken ? [{ + name: currentState.currency, + shortcut: currentState.currency, + value: currentState.amount, + }] : undefined, + + blockHeight: 0, + blockHash: undefined, }; dispatch(BlockchainActions.onNotification({ diff --git a/src/actions/ripple/BlockchainActions.js b/src/actions/ripple/BlockchainActions.js index bd59339d..fbea7721 100644 --- a/src/actions/ripple/BlockchainActions.js +++ b/src/actions/ripple/BlockchainActions.js @@ -89,12 +89,12 @@ export const onBlockMined = (network: string): PromiseAction => async (dis export const onNotification = (payload: $ElementType): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { const { notification } = payload; - const account = getState().accounts.find(a => a.descriptor === notification.address); + const account = getState().accounts.find(a => a.descriptor === notification.descriptor); if (!account) return; const { network } = getState().selectedAccount; if (!network) return; // flowtype fallback - if (notification.status === 'pending') { + if (!notification.blockHeight) { dispatch({ type: PENDING.ADD, payload: { @@ -109,7 +109,7 @@ export const onNotification = (payload: $ElementType { const url = `${network.explorer.tx}${tx.hash}`; - const date = typeof tx.timestamp === 'string' && tx.confirmations > 0 ? tx.timestamp : undefined; // TODO: format date + const date = typeof tx.timestamp === 'string' ? tx.timestamp : undefined; // TODO: format date const addresses = (tx.type === 'send' ? tx.outputs : tx.inputs).reduce((arr, item) => arr.concat(item.addresses), []); - const currency = tx.currency || tx.network; - const isToken = currency !== tx.network; - const amount = isToken ? `${tx.amount} ${currency}` : `${tx.total} ${network.symbol}`; - const fee = isToken && tx.type === 'send' ? `${tx.fee} ${network.symbol}` : undefined; const operation = tx.type === 'send' ? '-' : '+'; + const amount = tx.tokens ? tx.tokens.map(t => ({operation}{t.value} {t.shortcut})) : {operation}{tx.total} {network.symbol}; + const fee = tx.tokens && tx.type === 'send' ? `${tx.fee} ${network.symbol}` : undefined; return ( { date && ({ date })} { addresses.map(addr => (
{addr}
)) } - { tx.confirmations <= 0 && ( + { !tx.blockHeight && ( Transaction hash: {tx.hash} )}
- {operation}{amount} + {amount} { fee && ({operation}{fee}) }
diff --git a/src/reducers/utils/index.js b/src/reducers/utils/index.js index df7c6cc3..4bab40c1 100644 --- a/src/reducers/utils/index.js +++ b/src/reducers/utils/index.js @@ -86,18 +86,27 @@ export const getDiscoveryProcess = (state: State): ?Discovery => { export const getAccountPendingTx = (pending: Array, account: ?Account): Array => { const a = account; if (!a) return []; - return pending.filter(p => p.network === a.network && p.address === a.descriptor); + return pending.filter(p => p.network === a.network && p.descriptor === a.descriptor); }; -export const getPendingSequence = (pending: Array): number => pending.reduce((value: number, tx: Transaction) => { +export const getPendingSequence = (pending: Array): number => pending.reduce((value: number, tx: Transaction): number => { if (tx.rejected) return value; return Math.max(value, tx.sequence + 1); }, 0); -export const getPendingAmount = (pending: Array, currency: string, token: boolean = false): BigNumber => pending.reduce((value: BigNumber, tx: Transaction) => { - if (tx.currency === currency && !tx.rejected) { - return new BigNumber(value).plus(token ? tx.amount : tx.total); +export const getPendingAmount = (pending: Array, currency: string, token: boolean = false): BigNumber => pending.reduce((value: BigNumber, tx: Transaction): BigNumber => { + if (!token) { + // regular transactions + // add fees from token txs and amount from regular txs + return new BigNumber(value).plus(tx.tokens ? tx.fee : tx.total); } + if (tx.tokens) { + // token transactions + const allTokens = tx.tokens.filter(t => t.shortcut === currency); + const tokensValue: BigNumber = allTokens.reduce((tv, t) => new BigNumber(value).plus(t.value), new BigNumber('0')); + return new BigNumber(value).plus(tokensValue); + } + // default return value; }, new BigNumber('0')); diff --git a/src/views/Wallet/views/Account/Send/ethereum/index.js b/src/views/Wallet/views/Account/Send/ethereum/index.js index dc699a6e..6b88ff53 100644 --- a/src/views/Wallet/views/Account/Send/ethereum/index.js +++ b/src/views/Wallet/views/Account/Send/ethereum/index.js @@ -1,6 +1,7 @@ /* @flow */ import React from 'react'; +import BigNumber from 'bignumber.js'; import styled, { css } from 'styled-components'; import { Select } from 'components/Select'; import Button from 'components/Button'; @@ -13,6 +14,7 @@ import colors from 'config/colors'; import Title from 'views/Wallet/components/Title'; import P from 'components/Paragraph'; import Content from 'views/Wallet/components/Content'; +import * as stateUtils from 'reducers/utils'; import type { Token } from 'flowtype'; import AdvancedForm from './components/AdvancedForm'; import PendingTransactions from '../components/PendingTransactions'; @@ -221,10 +223,11 @@ const AccountSend = (props: Props) => { const isCurrentCurrencyToken = networkSymbol !== currency; - let selectedTokenBalance = 0; + let selectedTokenBalance = '0'; const selectedToken = tokens.find(t => t.symbol === currency); if (selectedToken) { - selectedTokenBalance = selectedToken.balance; + const pendingAmount: BigNumber = stateUtils.getPendingAmount(props.selectedAccount.pending, selectedToken.symbol, true); + selectedTokenBalance = new BigNumber(selectedToken.balance).minus(pendingAmount).toString(10); } let isSendButtonDisabled: boolean = Object.keys(errors).length > 0 || total === '0' || amount.length === 0 || address.length === 0 || sending;