diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index e849517a823e..698857e68a71 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -139,6 +139,9 @@ "balance": { "message": "Balance" }, + "balanceOutdated": { + "message": "Balance may be outdated" + }, "balances": { "message": "Token balance(s)" }, diff --git a/development/states/confirm-sig-requests.json b/development/states/confirm-sig-requests.json index f261ce67fc74..e69060e2a585 100644 --- a/development/states/confirm-sig-requests.json +++ b/development/states/confirm-sig-requests.json @@ -22,6 +22,7 @@ "name": "Send Account 4" } }, + "cachedBalances": {}, "unapprovedTxs": {}, "currentCurrency": "USD", "conversionRate": 1200.88200327, diff --git a/development/states/currency-localization.json b/development/states/currency-localization.json index 43acf7fda235..9be7b2ad3e04 100644 --- a/development/states/currency-localization.json +++ b/development/states/currency-localization.json @@ -22,6 +22,7 @@ "name": "Send Account 4" } }, + "cachedBalances": {}, "unapprovedTxs": {}, "currentCurrency": "USD", "conversionRate": 19855, diff --git a/development/states/send-edit.json b/development/states/send-edit.json index 09a380730d1a..51cb8a627781 100644 --- a/development/states/send-edit.json +++ b/development/states/send-edit.json @@ -22,6 +22,7 @@ "name": "Send Account 4" } }, + "cachedBalances": {}, "assetImages": {}, "unapprovedTxs": {}, "currentCurrency": "USD", diff --git a/development/states/send-new-ui.json b/development/states/send-new-ui.json index 60a4af2286e8..2393f69870be 100644 --- a/development/states/send-new-ui.json +++ b/development/states/send-new-ui.json @@ -22,6 +22,7 @@ "name": "Send Account 4" } }, + "cachedBalances": {}, "unapprovedTxs": {}, "currentCurrency": "USD", "conversionRate": 1200.88200327, diff --git a/development/states/tx-list-items.json b/development/states/tx-list-items.json index a3fcd91843e9..b78e7068c96e 100644 --- a/development/states/tx-list-items.json +++ b/development/states/tx-list-items.json @@ -22,6 +22,7 @@ "name": "Send Account 4" } }, + "cachedBalances": {}, "currentCurrency": "USD", "conversionRate": 1200.88200327, "conversionDate": 1489013762, diff --git a/test/data/mock-state.json b/test/data/mock-state.json index 8deff5531265..6716971822ce 100644 --- a/test/data/mock-state.json +++ b/test/data/mock-state.json @@ -11,6 +11,7 @@ "name": "Test Account 2" } }, + "cachedBalances": {}, "unapprovedTxs": { "8393540981007587": { "id": 8393540981007587, diff --git a/test/unit/ui/app/selectors.spec.js b/test/unit/ui/app/selectors.spec.js index e2b198abfa1b..070de0bcd394 100644 --- a/test/unit/ui/app/selectors.spec.js +++ b/test/unit/ui/app/selectors.spec.js @@ -19,6 +19,7 @@ describe('Selectors', function () { 'address': '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', }, }, + cachedBalances: {}, }, } }) diff --git a/ui/app/components/currency-display/currency-display.component.js b/ui/app/components/currency-display/currency-display.component.js index 2d7413b57fbe..6a743cc4ed03 100644 --- a/ui/app/components/currency-display/currency-display.component.js +++ b/ui/app/components/currency-display/currency-display.component.js @@ -17,10 +17,11 @@ export default class CurrencyDisplay extends PureComponent { value: PropTypes.string, numberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), hideLabel: PropTypes.bool, + hideTitle: PropTypes.bool, } render () { - const { className, displayValue, prefix, prefixComponent, style, suffix } = this.props + const { className, displayValue, prefix, prefixComponent, style, suffix, hideTitle } = this.props const text = `${prefix || ''}${displayValue}` const title = `${text} ${suffix}` @@ -28,9 +29,9 @@ export default class CurrencyDisplay extends PureComponent {
- { prefixComponent} + { prefixComponent } { text } { suffix && ( diff --git a/ui/app/components/send/account-list-item/account-list-item.component.js b/ui/app/components/send/account-list-item/account-list-item.component.js index a61467bb399a..665383e58048 100644 --- a/ui/app/components/send/account-list-item/account-list-item.component.js +++ b/ui/app/components/send/account-list-item/account-list-item.component.js @@ -1,9 +1,11 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' +import classnames from 'classnames' import { checksumAddress } from '../../../util' import Identicon from '../../identicon' import UserPreferencedCurrencyDisplay from '../../user-preferenced-currency-display' import { PRIMARY, SECONDARY } from '../../../constants/common' +import Tooltip from '../../tooltip-v2' export default class AccountListItem extends Component { @@ -16,6 +18,7 @@ export default class AccountListItem extends Component { displayBalance: PropTypes.bool, handleClick: PropTypes.func, icon: PropTypes.node, + balanceIsCached: PropTypes.bool, }; static contextTypes = { @@ -30,6 +33,7 @@ export default class AccountListItem extends Component { displayBalance = true, handleClick, icon = null, + balanceIsCached, } = this.props const { name, address, balance } = account || {} @@ -58,16 +62,34 @@ export default class AccountListItem extends Component { { displayBalance && ( -
- - -
+ +
+
+ + { + balanceIsCached ? * : null + } +
+ +
+
) } diff --git a/ui/app/components/send/account-list-item/account-list-item.container.js b/ui/app/components/send/account-list-item/account-list-item.container.js index f8e73d923305..03a60be678c2 100644 --- a/ui/app/components/send/account-list-item/account-list-item.container.js +++ b/ui/app/components/send/account-list-item/account-list-item.container.js @@ -4,6 +4,9 @@ import { getCurrentCurrency, getNativeCurrency, } from '../send.selectors.js' +import { + isBalanceCached, +} from '../../../selectors' import AccountListItem from './account-list-item.component' export default connect(mapStateToProps)(AccountListItem) @@ -13,5 +16,6 @@ function mapStateToProps (state) { conversionRate: getConversionRate(state), currentCurrency: getCurrentCurrency(state), nativeCurrency: getNativeCurrency(state), + balanceIsCached: isBalanceCached(state), } } diff --git a/ui/app/components/send/account-list-item/tests/account-list-item-component.test.js b/ui/app/components/send/account-list-item/tests/account-list-item-component.test.js index 6ffc0b1c6795..f2ddb73c0277 100644 --- a/ui/app/components/send/account-list-item/tests/account-list-item-component.test.js +++ b/ui/app/components/send/account-list-item/tests/account-list-item-component.test.js @@ -121,6 +121,7 @@ describe('AccountListItem Component', function () { { type: 'PRIMARY', value: 'mockBalance', + hideTitle: true, } ) }) diff --git a/ui/app/components/send/account-list-item/tests/account-list-item-container.test.js b/ui/app/components/send/account-list-item/tests/account-list-item-container.test.js index 7c2f5fcb258d..8c22bc8f8b7a 100644 --- a/ui/app/components/send/account-list-item/tests/account-list-item-container.test.js +++ b/ui/app/components/send/account-list-item/tests/account-list-item-container.test.js @@ -15,6 +15,9 @@ proxyquire('../account-list-item.container.js', { getCurrentCurrency: (s) => `mockCurrentCurrency:${s}`, getNativeCurrency: (s) => `mockNativeCurrency:${s}`, }, + '../../../selectors.js': { + isBalanceCached: (s) => `mockBalanceIsCached:${s}`, + }, }) describe('account-list-item container', () => { @@ -26,6 +29,7 @@ describe('account-list-item container', () => { conversionRate: 'mockConversionRate:mockState', currentCurrency: 'mockCurrentCurrency:mockState', nativeCurrency: 'mockNativeCurrency:mockState', + balanceIsCached: 'mockBalanceIsCached:mockState', }) }) diff --git a/ui/app/components/send/tests/send-selectors-test-data.js b/ui/app/components/send/tests/send-selectors-test-data.js index 30a2666cf1c3..66c0da229867 100644 --- a/ui/app/components/send/tests/send-selectors-test-data.js +++ b/ui/app/components/send/tests/send-selectors-test-data.js @@ -22,6 +22,7 @@ module.exports = { 'name': 'Send Account 4', }, }, + 'cachedBalances': {}, 'currentBlockGasLimit': '0x4c1878', 'currentCurrency': 'USD', 'conversionRate': 1200.88200327, diff --git a/ui/app/components/tooltip-v2.js b/ui/app/components/tooltip-v2.js index 054782203204..b5402679491a 100644 --- a/ui/app/components/tooltip-v2.js +++ b/ui/app/components/tooltip-v2.js @@ -20,6 +20,7 @@ export default class Tooltip extends PureComponent { arrow: PropTypes.bool, children: PropTypes.node, containerClassName: PropTypes.string, + disabled: PropTypes.bool, onHidden: PropTypes.func, position: PropTypes.oneOf([ 'top', @@ -33,10 +34,11 @@ export default class Tooltip extends PureComponent { title: PropTypes.string, trigger: PropTypes.any, wrapperClassName: PropTypes.string, + style: PropTypes.object, } render () { - const {arrow, children, containerClassName, position, size, title, trigger, onHidden, wrapperClassName } = this.props + const {arrow, children, containerClassName, disabled, position, size, title, trigger, onHidden, wrapperClassName, style } = this.props if (!title) { return ( @@ -50,6 +52,7 @@ export default class Tooltip extends PureComponent {
{children} diff --git a/ui/app/components/transaction-view-balance/index.scss b/ui/app/components/transaction-view-balance/index.scss index 43e87459bfeb..b64320a51dc9 100644 --- a/ui/app/components/transaction-view-balance/index.scss +++ b/ui/app/components/transaction-view-balance/index.scss @@ -17,6 +17,7 @@ display: flex; flex-direction: column; min-width: 0; + position: relative; @media screen and (max-width: $break-small) { align-items: center; @@ -26,6 +27,10 @@ } } + &__primary-container { + display: flex; + } + &__primary-balance { font-size: 1.5rem; @@ -35,6 +40,19 @@ } } + &__cached-star { + margin-left: 4px; + } + + &__cached-balance, &__cached-star { + color: $web-orange; + } + + &__cached-secondary-balance { + color: rgba(220, 153, 18, 0.6901960784313725); + font-size: 1.15rem; + } + &__secondary-balance { font-size: 1.15rem; color: #a0a0a0; diff --git a/ui/app/components/transaction-view-balance/transaction-view-balance.component.js b/ui/app/components/transaction-view-balance/transaction-view-balance.component.js index a24b9747813f..bd6b4bdb641d 100644 --- a/ui/app/components/transaction-view-balance/transaction-view-balance.component.js +++ b/ui/app/components/transaction-view-balance/transaction-view-balance.component.js @@ -1,11 +1,13 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' +import classnames from 'classnames' import Button from '../button' import Identicon from '../identicon' import TokenBalance from '../token-balance' import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display' import { SEND_ROUTE } from '../../routes' import { PRIMARY, SECONDARY } from '../../constants/common' +import Tooltip from '../tooltip-v2' export default class TransactionViewBalance extends PureComponent { static contextTypes = { @@ -19,10 +21,11 @@ export default class TransactionViewBalance extends PureComponent { network: PropTypes.string, balance: PropTypes.string, assetImage: PropTypes.string, + balanceIsCached: PropTypes.bool, } renderBalance () { - const { selectedToken, balance } = this.props + const { selectedToken, balance, balanceIsCached } = this.props return selectedToken ? ( @@ -34,20 +37,34 @@ export default class TransactionViewBalance extends PureComponent { />
) : ( -
- - -
+ +
+
+ + { + balanceIsCached ? * : null + } +
+ +
+
) } diff --git a/ui/app/components/transaction-view-balance/transaction-view-balance.container.js b/ui/app/components/transaction-view-balance/transaction-view-balance.container.js index f9f05b0ae808..354db5ae13de 100644 --- a/ui/app/components/transaction-view-balance/transaction-view-balance.container.js +++ b/ui/app/components/transaction-view-balance/transaction-view-balance.container.js @@ -8,6 +8,7 @@ import { getNativeCurrency, getSelectedTokenAssetImage, getMetaMaskAccounts, + isBalanceCached, } from '../../selectors' import { showModal } from '../../actions' @@ -24,6 +25,7 @@ const mapStateToProps = state => { balance, nativeCurrency: getNativeCurrency(state), assetImage: getSelectedTokenAssetImage(state), + balanceIsCached: isBalanceCached(state), } } diff --git a/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.component.js b/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.component.js index f2a834ea7402..d9f29327da61 100644 --- a/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.component.js +++ b/ui/app/components/user-preferenced-currency-display/user-preferenced-currency-display.component.js @@ -10,6 +10,7 @@ export default class UserPreferencedCurrencyDisplay extends PureComponent { value: PropTypes.string, numberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), hideLabel: PropTypes.bool, + hideTitle: PropTypes.bool, style: PropTypes.object, showEthLogo: PropTypes.bool, ethLogoHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), diff --git a/ui/app/css/itcss/components/account-dropdown.scss b/ui/app/css/itcss/components/account-dropdown.scss index b29afdc8cee1..716404cc3c0d 100644 --- a/ui/app/css/itcss/components/account-dropdown.scss +++ b/ui/app/css/itcss/components/account-dropdown.scss @@ -24,6 +24,10 @@ position: relative; } + &__tooltip-wrapper { + left: -10px; + } + &__account-balances { height: auto; border: none; @@ -34,6 +38,24 @@ position: relative; } + &__primary-cached-container { + display: flex; + } + + &__cached-star { + margin-left: 4px; + } + + &__cached-balances { + div:first-of-type { + color: $web-orange; + } + + div:last-of-type { + color: rgba(220, 153, 18, 0.6901960784313725) + } + } + &__account-name { font-size: 16px; margin-left: 8px; @@ -52,6 +74,13 @@ font-size: 12px; } + &__balance-flag { + position: absolute; + top: 3px; + left: -8px; + color: $curious-blue; + } + &__account-primary-balance { color: $scorpion; border: none; diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss index 42a8655df15f..89bd8b96a1da 100644 --- a/ui/app/css/itcss/settings/variables.scss +++ b/ui/app/css/itcss/settings/variables.scss @@ -59,6 +59,7 @@ $oslo-gray: #8C8E94; $polar: #fafcfe; $blizzard-blue: #bfdef3; $mischka: #dddee9; +$web-orange: #f2a202; /* Z-Indicies diff --git a/ui/app/selectors.js b/ui/app/selectors.js index f1ef41f28eaa..c60b27ab4144 100644 --- a/ui/app/selectors.js +++ b/ui/app/selectors.js @@ -37,6 +37,7 @@ const selectors = { getMetaMaskAccounts, getCurrentEthBalance, getNetworkIdentifier, + isBalanceCached, } module.exports = selectors @@ -62,7 +63,7 @@ function getSelectedIdentity (state) { function getMetaMaskAccounts (state) { const currentAccounts = state.metamask.accounts - const cachedBalances = state.metamask.cachedBalances + const cachedBalances = state.metamask.cachedBalances[state.metamask.network] const selectedAccounts = {} Object.keys(currentAccounts).forEach(accountID => { @@ -70,7 +71,7 @@ function getMetaMaskAccounts (state) { if (account && account.balance === null || account.balance === undefined) { selectedAccounts[accountID] = { ...account, - balance: cachedBalances[accountID], + balance: cachedBalances && cachedBalances[accountID], } } else { selectedAccounts[accountID] = account @@ -79,6 +80,20 @@ function getMetaMaskAccounts (state) { return selectedAccounts } +function isBalanceCached (state) { + const selectedAccountBalance = state.metamask.accounts[getSelectedAddress(state)].balance + const cachedBalance = getSelectedAccountCachedBalance(state) + + return Boolean(!selectedAccountBalance && cachedBalance) +} + +function getSelectedAccountCachedBalance (state) { + const cachedBalances = state.metamask.cachedBalances[state.metamask.network] + const selectedAddress = getSelectedAddress(state) + + return cachedBalances && cachedBalances[selectedAddress] +} + function getSelectedAccount (state) { const accounts = getMetaMaskAccounts(state) const selectedAddress = getSelectedAddress(state)