1
0
mirror of https://github.com/trezor/trezor-wallet synced 2024-11-24 09:18:09 +00:00

Account balance - pending txs

This commit is contained in:
Szymon Lesisz 2018-05-28 11:21:47 +02:00
parent 43ddffb6e9
commit 00ee6465c9
8 changed files with 63 additions and 26 deletions

View File

@ -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<State, 'selectedAccount'> = {
@ -81,14 +83,18 @@ 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) {
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() );
if (location.state.send) {

View File

@ -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,
});

View File

@ -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<string> = pending.map((tx, i) => {
let iconColor: Style;
let symbol: string;
@ -80,7 +80,7 @@ const PendingTransactions = (props: Props) => {
<div className="name">
<a href={ `${props.network.explorer.tx}${tx.id}`} target="_blank" rel="noreferrer noopener">{ name }</a>
</div>
<div className="amount">{ tx.amount } { symbol }</div>
<div className="amount">{ tx.total } { symbol }</div>
</div>
)
});

View File

@ -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 (
<div>
<h2 className={ `summary-header ${account.network}` }>
@ -43,7 +48,7 @@ const Summary = (props: Props) => {
<SummaryDetails
coin={ network }
summary={ props.summary }
balance={ account.balance }
balance={ balance }
network={ network.network }
fiat={ props.fiat }
localStorage={ props.localStorage }

View File

@ -6,6 +6,7 @@ import { Link, NavLink } from 'react-router-dom';
import BigNumber from 'bignumber.js';
import { findDeviceAccounts } from '~/js/reducers/AccountsReducer';
import * as stateUtils from '~/js/reducers/utils';
import Loader from '~/js/components/common/LoaderCircle';
import Tooltip from 'rc-tooltip';
@ -36,12 +37,16 @@ const AccountSelection = (props: Props): ?React$Element<string> => {
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 }`;
}
}

View File

@ -28,6 +28,7 @@ type StateProps = {
discovery: $ElementType<State, 'discovery'>,
wallet: $ElementType<State, 'wallet'>,
devices: $ElementType<State, 'devices'>,
pending: $ElementType<State, 'pending'>,
}
type DispatchProps = {
@ -52,7 +53,8 @@ const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: St
localStorage: state.localStorage,
discovery: state.discovery,
wallet: state.wallet,
devices: state.devices
devices: state.devices,
pending: state.pending,
};
}

View File

@ -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;

View File

@ -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<PendingTx> => {
export const getAccountPendingTx = (pending: Array<PendingTx>, account: ?Account): Array<PendingTx> => {
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<PendingTx>, 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<Token> => {
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);
}
@ -101,3 +111,4 @@ export const getWeb3 = (state: State): ?Web3Instance => {
if (!locationState.network) return null;
return state.web3.find(w3 => w3.network === locationState.network);
}