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:
parent
43ddffb6e9
commit
00ee6465c9
@ -36,6 +36,7 @@ export const updateSelectedValues = (prevState: State, action: Action): AsyncAct
|
|||||||
const locationChange: boolean = action.type === LOCATION_CHANGE;
|
const locationChange: boolean = action.type === LOCATION_CHANGE;
|
||||||
const state: State = getState();
|
const state: State = getState();
|
||||||
const location = state.router.location;
|
const location = state.router.location;
|
||||||
|
const prevLocation = prevState.router.location;
|
||||||
|
|
||||||
let needUpdate: boolean = false;
|
let needUpdate: boolean = false;
|
||||||
|
|
||||||
@ -51,13 +52,14 @@ export const updateSelectedValues = (prevState: State, action: Action): AsyncAct
|
|||||||
|| prevState.accounts !== state.accounts
|
|| prevState.accounts !== state.accounts
|
||||||
|| prevState.discovery !== state.discovery
|
|| prevState.discovery !== state.discovery
|
||||||
|| prevState.tokens !== state.tokens
|
|| prevState.tokens !== state.tokens
|
||||||
|
|| prevState.pending !== state.pending
|
||||||
|| prevState.web3 !== state.web3) {
|
|| prevState.web3 !== state.web3) {
|
||||||
|
|
||||||
const account = stateUtils.getSelectedAccount(state);
|
const account = stateUtils.getSelectedAccount(state);
|
||||||
const network = stateUtils.getSelectedNetwork(state);
|
const network = stateUtils.getSelectedNetwork(state);
|
||||||
const discovery = stateUtils.getDiscoveryProcess(state);
|
const discovery = stateUtils.getDiscoveryProcess(state);
|
||||||
const tokens = stateUtils.getAccountTokens(state, account);
|
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 web3 = stateUtils.getWeb3(state);
|
||||||
|
|
||||||
const payload: $ElementType<State, 'selectedAccount'> = {
|
const payload: $ElementType<State, 'selectedAccount'> = {
|
||||||
@ -81,13 +83,17 @@ export const updateSelectedValues = (prevState: State, action: Action): AsyncAct
|
|||||||
dispatch({
|
dispatch({
|
||||||
type: ACCOUNT.UPDATE_SELECTED_ACCOUNT,
|
type: ACCOUNT.UPDATE_SELECTED_ACCOUNT,
|
||||||
payload,
|
payload,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locationChange) {
|
if (locationChange) {
|
||||||
|
|
||||||
if (prevState.router.location && prevState.router.location.state.send) {
|
if (prevLocation) {
|
||||||
SessionStorageActions.save(prevState.router.location.pathname, state.sendForm);
|
// 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() );
|
dispatch( dispose() );
|
||||||
|
@ -18,8 +18,10 @@ import { initialState } from '../reducers/SendFormReducer';
|
|||||||
import { findAccount } from '../reducers/AccountsReducer';
|
import { findAccount } from '../reducers/AccountsReducer';
|
||||||
import { findToken } from '../reducers/TokensReducer';
|
import { findToken } from '../reducers/TokensReducer';
|
||||||
import { findDevice } from '../reducers/utils';
|
import { findDevice } from '../reducers/utils';
|
||||||
|
import * as stateUtils from '../reducers/utils';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
PendingTx,
|
||||||
Dispatch,
|
Dispatch,
|
||||||
GetState,
|
GetState,
|
||||||
Action,
|
Action,
|
||||||
@ -41,6 +43,8 @@ export type SendTxAction = {
|
|||||||
account: Account,
|
account: Account,
|
||||||
selectedCurrency: string,
|
selectedCurrency: string,
|
||||||
amount: string,
|
amount: string,
|
||||||
|
total: string,
|
||||||
|
tx: any,
|
||||||
txid: string,
|
txid: string,
|
||||||
txData: any,
|
txData: any,
|
||||||
};
|
};
|
||||||
@ -156,8 +160,6 @@ export const calculate = (prevProps: Props, props: Props) => {
|
|||||||
} = props.selectedAccount;
|
} = props.selectedAccount;
|
||||||
if (!account) return;
|
if (!account) return;
|
||||||
|
|
||||||
console.warn("CALCULATE!", props)
|
|
||||||
|
|
||||||
const prevState = prevProps.sendForm;
|
const prevState = prevProps.sendForm;
|
||||||
const state = props.sendForm;
|
const state = props.sendForm;
|
||||||
const isToken: boolean = state.currency !== state.networkSymbol;
|
const isToken: boolean = state.currency !== state.networkSymbol;
|
||||||
@ -173,18 +175,16 @@ export const calculate = (prevProps: Props, props: Props) => {
|
|||||||
|
|
||||||
if (state.setMax) {
|
if (state.setMax) {
|
||||||
|
|
||||||
const pendingAmount = pending.reduce((value, p) => {
|
const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, state.currency);
|
||||||
//if (p.tx.amount)
|
|
||||||
console.warn("PENDING AMOUNT!", p, value);
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
if (isToken) {
|
if (isToken) {
|
||||||
const token: ?Token = findToken(tokens, account.address, state.currency, account.deviceState);
|
const token: ?Token = findToken(tokens, account.address, state.currency, account.deviceState);
|
||||||
if (token) {
|
if (token) {
|
||||||
state.amount = token.balance;
|
state.amount = new BigNumber(token.balance).minus(pendingAmount).toString();
|
||||||
}
|
}
|
||||||
} else {
|
} 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,
|
account,
|
||||||
network,
|
network,
|
||||||
tokens,
|
tokens,
|
||||||
|
pending,
|
||||||
} = props.selectedAccount;
|
} = props.selectedAccount;
|
||||||
if (!account || !network) return;
|
if (!account || !network) return;
|
||||||
|
|
||||||
@ -389,6 +390,7 @@ export const validation = (props: Props): void => {
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
let decimalRegExp: RegExp;
|
let decimalRegExp: RegExp;
|
||||||
|
const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, state.currency);
|
||||||
|
|
||||||
if (state.currency !== state.networkSymbol) {
|
if (state.currency !== state.networkSymbol) {
|
||||||
const token = findToken(tokens, account.address, state.currency, account.deviceState);
|
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`;
|
errors.amount = `Maximum ${ token.decimals} decimals allowed`;
|
||||||
} else if (new BigNumber(state.total).greaterThan(account.balance)) {
|
} else if (new BigNumber(state.total).greaterThan(account.balance)) {
|
||||||
errors.amount = `Not enough ${ state.networkSymbol } to cover transaction fee`;
|
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';
|
errors.amount = 'Not enough funds';
|
||||||
} else if (new BigNumber(state.amount).lessThanOrEqualTo('0')) {
|
} else if (new BigNumber(state.amount).lessThanOrEqualTo('0')) {
|
||||||
errors.amount = 'Amount is too low';
|
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})$');
|
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)) {
|
if (!state.amount.match(decimalRegExp)) {
|
||||||
errors.amount = `Maximum 18 decimals allowed`;
|
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';
|
errors.amount = 'Not enough funds';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -916,6 +918,8 @@ export const onSend = (): AsyncAction => {
|
|||||||
account: account,
|
account: account,
|
||||||
selectedCurrency: currentState.currency,
|
selectedCurrency: currentState.currency,
|
||||||
amount: currentState.amount,
|
amount: currentState.amount,
|
||||||
|
total: currentState.total,
|
||||||
|
tx,
|
||||||
txid,
|
txid,
|
||||||
txData,
|
txData,
|
||||||
});
|
});
|
||||||
|
@ -34,7 +34,7 @@ const PendingTransactions = (props: Props) => {
|
|||||||
const bgColorFactory = new ColorHash({lightness: 0.7});
|
const bgColorFactory = new ColorHash({lightness: 0.7});
|
||||||
const textColorFactory = new ColorHash();
|
const textColorFactory = new ColorHash();
|
||||||
|
|
||||||
const pendingTxs = pending.map((tx, i) => {
|
const pendingTxs: React$Element<string> = pending.map((tx, i) => {
|
||||||
|
|
||||||
let iconColor: Style;
|
let iconColor: Style;
|
||||||
let symbol: string;
|
let symbol: string;
|
||||||
@ -80,7 +80,7 @@ const PendingTransactions = (props: Props) => {
|
|||||||
<div className="name">
|
<div className="name">
|
||||||
<a href={ `${props.network.explorer.tx}${tx.id}`} target="_blank" rel="noreferrer noopener">{ name }</a>
|
<a href={ `${props.network.explorer.tx}${tx.id}`} target="_blank" rel="noreferrer noopener">{ name }</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="amount">{ tx.amount } { symbol }</div>
|
<div className="amount">{ tx.total } { symbol }</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,7 @@ import SelectedAccount from '../SelectedAccount';
|
|||||||
import { Notification } from '~/js/components/common/Notification';
|
import { Notification } from '~/js/components/common/Notification';
|
||||||
import SummaryDetails from './SummaryDetails.js';
|
import SummaryDetails from './SummaryDetails.js';
|
||||||
import SummaryTokens from './SummaryTokens.js';
|
import SummaryTokens from './SummaryTokens.js';
|
||||||
|
import * as stateUtils from '~/js/reducers/utils';
|
||||||
|
|
||||||
import type { Props } from './index';
|
import type { Props } from './index';
|
||||||
import type { NetworkToken } from '~/js/reducers/LocalStorageReducer';
|
import type { NetworkToken } from '~/js/reducers/LocalStorageReducer';
|
||||||
@ -21,6 +22,7 @@ const Summary = (props: Props) => {
|
|||||||
account,
|
account,
|
||||||
network,
|
network,
|
||||||
tokens,
|
tokens,
|
||||||
|
pending
|
||||||
} = props.selectedAccount;
|
} = props.selectedAccount;
|
||||||
|
|
||||||
// flow
|
// flow
|
||||||
@ -33,6 +35,9 @@ const Summary = (props: Props) => {
|
|||||||
);
|
);
|
||||||
const explorerLink: string = `${network.explorer.address}${account.address}`;
|
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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2 className={ `summary-header ${account.network}` }>
|
<h2 className={ `summary-header ${account.network}` }>
|
||||||
@ -43,7 +48,7 @@ const Summary = (props: Props) => {
|
|||||||
<SummaryDetails
|
<SummaryDetails
|
||||||
coin={ network }
|
coin={ network }
|
||||||
summary={ props.summary }
|
summary={ props.summary }
|
||||||
balance={ account.balance }
|
balance={ balance }
|
||||||
network={ network.network }
|
network={ network.network }
|
||||||
fiat={ props.fiat }
|
fiat={ props.fiat }
|
||||||
localStorage={ props.localStorage }
|
localStorage={ props.localStorage }
|
||||||
|
@ -6,6 +6,7 @@ import { Link, NavLink } from 'react-router-dom';
|
|||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
|
|
||||||
import { findDeviceAccounts } from '~/js/reducers/AccountsReducer';
|
import { findDeviceAccounts } from '~/js/reducers/AccountsReducer';
|
||||||
|
import * as stateUtils from '~/js/reducers/utils';
|
||||||
import Loader from '~/js/components/common/LoaderCircle';
|
import Loader from '~/js/components/common/LoaderCircle';
|
||||||
import Tooltip from 'rc-tooltip';
|
import Tooltip from 'rc-tooltip';
|
||||||
|
|
||||||
@ -36,12 +37,16 @@ const AccountSelection = (props: Props): ?React$Element<string> => {
|
|||||||
|
|
||||||
let balance: string = 'Loading...';
|
let balance: string = 'Loading...';
|
||||||
if (account.balance !== '') {
|
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) {
|
if (fiatRate) {
|
||||||
const accountBalance = new BigNumber(account.balance);
|
const accountBalance = new BigNumber(availableBalance);
|
||||||
const fiat = accountBalance.times(fiatRate.value).toFixed(2);
|
const fiat = accountBalance.times(fiatRate.value).toFixed(2);
|
||||||
balance = `${ account.balance } ${ selectedCoin.symbol } / $${ fiat }`;
|
balance = `${ availableBalance } ${ selectedCoin.symbol } / $${ fiat }`;
|
||||||
} else {
|
} else {
|
||||||
balance = `${ account.balance } ${ selectedCoin.symbol }`;
|
balance = `${ availableBalance } ${ selectedCoin.symbol }`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ type StateProps = {
|
|||||||
discovery: $ElementType<State, 'discovery'>,
|
discovery: $ElementType<State, 'discovery'>,
|
||||||
wallet: $ElementType<State, 'wallet'>,
|
wallet: $ElementType<State, 'wallet'>,
|
||||||
devices: $ElementType<State, 'devices'>,
|
devices: $ElementType<State, 'devices'>,
|
||||||
|
pending: $ElementType<State, 'pending'>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type DispatchProps = {
|
type DispatchProps = {
|
||||||
@ -52,7 +53,8 @@ const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: St
|
|||||||
localStorage: state.localStorage,
|
localStorage: state.localStorage,
|
||||||
discovery: state.discovery,
|
discovery: state.discovery,
|
||||||
wallet: state.wallet,
|
wallet: state.wallet,
|
||||||
devices: state.devices
|
devices: state.devices,
|
||||||
|
pending: state.pending,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ export type PendingTx = {
|
|||||||
+network: string;
|
+network: string;
|
||||||
+currency: string;
|
+currency: string;
|
||||||
+amount: string;
|
+amount: string;
|
||||||
|
+total: string;
|
||||||
|
+tx: any;
|
||||||
+address: string;
|
+address: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +29,8 @@ const add = (state: State, action: SendTxAction): State => {
|
|||||||
network: action.account.network,
|
network: action.account.network,
|
||||||
currency: action.selectedCurrency,
|
currency: action.selectedCurrency,
|
||||||
amount: action.amount,
|
amount: action.amount,
|
||||||
|
total: action.total,
|
||||||
|
tx: action.tx,
|
||||||
address: action.account.address,
|
address: action.account.address,
|
||||||
});
|
});
|
||||||
return newState;
|
return newState;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
import * as LogActions from '~/js/actions/LogActions';
|
import * as LogActions from '~/js/actions/LogActions';
|
||||||
import * as STORAGE from '~/js/actions/constants/localStorage';
|
import * as STORAGE from '~/js/actions/constants/localStorage';
|
||||||
import * as WALLET from '~/js/actions/constants/wallet';
|
import * as WALLET from '~/js/actions/constants/wallet';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Middleware,
|
Middleware,
|
||||||
@ -84,15 +85,24 @@ export const getDiscoveryProcess = (state: State): ?Discovery => {
|
|||||||
return state.discovery.find(d => d.deviceState === device.state && d.network === locationState.network);
|
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;
|
const a = account;
|
||||||
if (!a) return state.selectedAccount.pending.length > 0 ? [] : state.selectedAccount.pending;
|
if (!a) return [];
|
||||||
return state.pending.filter(p => p.network === a.network && p.address === a.address);
|
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> => {
|
export const getAccountTokens = (state: State, account: ?Account): Array<Token> => {
|
||||||
const a = account;
|
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);
|
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;
|
const locationState = state.router.location.state;
|
||||||
if (!locationState.network) return null;
|
if (!locationState.network) return null;
|
||||||
return state.web3.find(w3 => w3.network === locationState.network);
|
return state.web3.find(w3 => w3.network === locationState.network);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user