aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/app/add-token.js5
-rw-r--r--ui/app/app.js25
-rw-r--r--ui/app/components/account-menu/index.js14
-rw-r--r--ui/app/components/customize-gas-modal/index.js144
-rw-r--r--ui/app/components/modals/export-private-key-modal.js1
-rw-r--r--ui/app/components/network.js7
-rw-r--r--ui/app/components/pending-tx/confirm-send-ether.js2
-rw-r--r--ui/app/components/send/currency-display.js36
-rw-r--r--ui/app/components/send/send-constants.js20
-rw-r--r--ui/app/components/send/send-utils.js39
-rw-r--r--ui/app/components/send/send-v2-container.js8
-rw-r--r--ui/app/components/tx-view.js7
-rw-r--r--ui/app/components/wallet-view.js99
-rw-r--r--ui/app/css/itcss/components/account-menu.scss13
-rw-r--r--ui/app/css/itcss/components/add-token.scss13
-rw-r--r--ui/app/css/itcss/components/confirm.scss6
-rw-r--r--ui/app/css/itcss/components/currency-display.scss10
-rw-r--r--ui/app/css/itcss/components/modal.scss1
-rw-r--r--ui/app/css/itcss/components/network.scss15
-rw-r--r--ui/app/css/itcss/components/newui-sections.scss89
-rw-r--r--ui/app/css/itcss/components/send.scss23
-rw-r--r--ui/app/css/itcss/components/settings.scss7
-rw-r--r--ui/app/css/itcss/components/token-list.scss6
-rw-r--r--ui/app/css/itcss/tools/utilities.scss1
-rw-r--r--ui/app/selectors.js23
-rw-r--r--ui/app/send-v2.js33
-rw-r--r--ui/app/settings.js2
27 files changed, 469 insertions, 180 deletions
diff --git a/ui/app/add-token.js b/ui/app/add-token.js
index e313babf3..148a8c622 100644
--- a/ui/app/add-token.js
+++ b/ui/app/add-token.js
@@ -350,7 +350,10 @@ AddTokenScreen.prototype.render = function () {
h('div.add-token__footers', [
h('div.add-token__add-custom', {
onClick: () => this.setState({ isCollapsed: !isCollapsed }),
- }, 'Add custom token'),
+ }, [
+ 'Add custom token',
+ h(`i.fa.fa-angle-${isCollapsed ? 'down' : 'up'}`),
+ ]),
this.renderCustomForm(),
]),
]),
diff --git a/ui/app/app.js b/ui/app/app.js
index 35ff8603a..0cfbb5af5 100644
--- a/ui/app/app.js
+++ b/ui/app/app.js
@@ -203,6 +203,16 @@ App.prototype.renderSidebar = function () {
}
App.prototype.renderAppBar = function () {
+ const {
+ isUnlocked,
+ network,
+ provider,
+ networkDropdownOpen,
+ showNetworkDropdown,
+ hideNetworkDropdown,
+ currentView,
+ } = this.props
+
if (window.METAMASK_UI_TYPE === 'notification') {
return null
}
@@ -243,22 +253,21 @@ App.prototype.renderAppBar = function () {
}, [
// Network Indicator
h(NetworkIndicator, {
- network: this.props.network,
- provider: this.props.provider,
+ network,
+ provider,
+ disabled: currentView.name === 'confTx',
onClick: (event) => {
event.preventDefault()
event.stopPropagation()
- if (this.props.networkDropdownOpen === false) {
- this.props.showNetworkDropdown()
- } else {
- this.props.hideNetworkDropdown()
- }
+ return networkDropdownOpen === false
+ ? showNetworkDropdown()
+ : hideNetworkDropdown()
},
}),
]),
- h('div.account-menu__icon', { onClick: this.props.toggleAccountMenu }, [
+ isUnlocked && h('div.account-menu__icon', { onClick: this.props.toggleAccountMenu }, [
h(Identicon, {
address: this.props.selectedAddress,
diameter: 32,
diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js
index 85bd21076..e0f38ae78 100644
--- a/ui/app/components/account-menu/index.js
+++ b/ui/app/components/account-menu/index.js
@@ -63,10 +63,11 @@ AccountMenu.prototype.render = function () {
h(CloseArea, { onClick: toggleAccountMenu }),
h(Item, {
className: 'account-menu__header',
- onClick: lockMetamask,
}, [
'My Accounts',
- h('button.account-menu__logout-button', 'Log out'),
+ h('button.account-menu__logout-button', {
+ onClick: lockMetamask,
+ }, 'Log out'),
]),
h(Divider),
h('div.account-menu__accounts', this.renderAccounts()),
@@ -98,15 +99,14 @@ AccountMenu.prototype.renderAccounts = function () {
const {
identities,
accounts,
- selected,
+ selectedAddress,
keyrings,
showAccountDetail,
} = this.props
- console.log({ accounts })
return Object.keys(identities).map((key, index) => {
const identity = identities[key]
- const isSelected = identity.address === selected
+ const isSelected = identity.address === selectedAddress
const balanceValue = accounts[key] ? accounts[key].balance : ''
const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...'
@@ -122,7 +122,7 @@ AccountMenu.prototype.renderAccounts = function () {
{ onClick: () => showAccountDetail(identity.address) },
[
h('div.account-menu__check-mark', [
- isSelected ? h('i.fa.fa-check') : null,
+ isSelected ? h('div.account-menu__check-mark-icon') : null,
]),
h(
@@ -148,6 +148,6 @@ AccountMenu.prototype.indicateIfLoose = function (keyring) {
try { // Sometimes keyrings aren't loaded yet:
const type = keyring.type
const isLoose = type !== 'HD Key Tree'
- return isLoose ? h('.keyring-label', 'LOOSE') : null
+ return isLoose ? h('.keyring-label', 'IMPORTED') : null
} catch (e) { return }
}
diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js
index 744891c47..710ee24c0 100644
--- a/ui/app/components/customize-gas-modal/index.js
+++ b/ui/app/components/customize-gas-modal/index.js
@@ -6,23 +6,46 @@ const actions = require('../../actions')
const GasModalCard = require('./gas-modal-card')
const {
- MIN_GAS_PRICE,
- MIN_GAS_LIMIT,
+ MIN_GAS_PRICE_DEC,
+ MIN_GAS_LIMIT_DEC,
+ MIN_GAS_PRICE_GWEI,
} = require('../send/send-constants')
-const { conversionUtil, multiplyCurrencies } = require('../../conversion-util')
+const {
+ isBalanceSufficient,
+} = require('../send/send-utils')
+
+const {
+ conversionUtil,
+ multiplyCurrencies,
+ conversionGreaterThan,
+} = require('../../conversion-util')
const {
getGasPrice,
getGasLimit,
conversionRateSelector,
+ getSendAmount,
+ getSelectedToken,
+ getSendFrom,
+ getCurrentAccountWithSendEtherInfo,
+ getSelectedTokenToFiatRate,
} = require('../../selectors')
function mapStateToProps (state) {
+ const selectedToken = getSelectedToken(state)
+ const currentAccount = getSendFrom(state) || getCurrentAccountWithSendEtherInfo(state)
+ const conversionRate = conversionRateSelector(state)
+
return {
gasPrice: getGasPrice(state),
gasLimit: getGasLimit(state),
- conversionRate: conversionRateSelector(state),
+ conversionRate,
+ amount: getSendAmount(state),
+ balance: currentAccount.balance,
+ primaryCurrency: selectedToken && selectedToken.symbol,
+ selectedToken,
+ amountConversionRate: selectedToken ? getSelectedTokenToFiatRate(state) : conversionRate,
}
}
@@ -39,15 +62,26 @@ inherits(CustomizeGasModal, Component)
function CustomizeGasModal (props) {
Component.call(this)
+ const gasPrice = props.gasPrice || MIN_GAS_PRICE_DEC
+ const gasLimit = props.gasLimit || MIN_GAS_LIMIT_DEC
+
+ const gasTotal = multiplyCurrencies(gasLimit, gasPrice, {
+ toNumericBase: 'hex',
+ multiplicandBase: 16,
+ multiplierBase: 16,
+ })
+
this.state = {
- gasPrice: props.gasPrice || MIN_GAS_PRICE,
- gasLimit: props.gasLimit || MIN_GAS_LIMIT,
+ gasPrice,
+ gasLimit,
+ gasTotal,
+ error: null,
}
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(CustomizeGasModal)
-CustomizeGasModal.prototype.save = function (gasPrice, gasLimit) {
+CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) {
const {
updateGasPrice,
updateGasLimit,
@@ -55,41 +89,101 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit) {
updateGasTotal
} = this.props
- const newGasTotal = multiplyCurrencies(gasLimit, gasPrice, {
- toNumericBase: 'hex',
- multiplicandBase: 16,
- multiplierBase: 16,
- })
-
updateGasPrice(gasPrice)
updateGasLimit(gasLimit)
- updateGasTotal(newGasTotal)
+ updateGasTotal(gasTotal)
hideModal()
}
+CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) {
+ const {
+ amount,
+ balance,
+ primaryCurrency,
+ selectedToken,
+ amountConversionRate,
+ conversionRate,
+ } = this.props
+
+ let error = null
+
+ const balanceIsSufficient = isBalanceSufficient({
+ amount,
+ gasTotal,
+ balance,
+ primaryCurrency,
+ selectedToken,
+ amountConversionRate,
+ conversionRate,
+ })
+
+ if (!balanceIsSufficient) {
+ error = 'Insufficient balance for current gas total'
+ }
+
+ const gasLimitTooLow = gasLimit && conversionGreaterThan(
+ {
+ value: MIN_GAS_LIMIT_DEC,
+ fromNumericBase: 'dec',
+ conversionRate,
+ },
+ {
+ value: gasLimit,
+ fromNumericBase: 'hex',
+ },
+ )
+
+ if (gasLimitTooLow) {
+ error = 'Gas limit must be at least 21000'
+ }
+
+ this.setState({ error })
+ return error
+}
+
CustomizeGasModal.prototype.convertAndSetGasLimit = function (newGasLimit) {
- const convertedGasLimit = conversionUtil(newGasLimit, {
+ const { gasPrice } = this.state
+
+ const gasLimit = conversionUtil(newGasLimit, {
fromNumericBase: 'dec',
toNumericBase: 'hex',
})
- this.setState({ gasLimit: convertedGasLimit })
+ const gasTotal = multiplyCurrencies(gasLimit, gasPrice, {
+ toNumericBase: 'hex',
+ multiplicandBase: 16,
+ multiplierBase: 16,
+ })
+
+ this.validate({ gasTotal, gasLimit })
+
+ this.setState({ gasTotal, gasLimit })
}
CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) {
- const convertedGasPrice = conversionUtil(newGasPrice, {
+ const { gasLimit } = this.state
+
+ const gasPrice = conversionUtil(newGasPrice, {
fromNumericBase: 'dec',
toNumericBase: 'hex',
fromDenomination: 'GWEI',
toDenomination: 'WEI',
})
- this.setState({ gasPrice: convertedGasPrice })
+ const gasTotal = multiplyCurrencies(gasLimit, gasPrice, {
+ toNumericBase: 'hex',
+ multiplicandBase: 16,
+ multiplierBase: 16,
+ })
+
+ this.validate({ gasTotal })
+
+ this.setState({ gasTotal, gasPrice })
}
CustomizeGasModal.prototype.render = function () {
const { hideModal, conversionRate } = this.props
- const { gasPrice, gasLimit } = this.state
+ const { gasPrice, gasLimit, gasTotal, error } = this.state
const convertedGasPrice = conversionUtil(gasPrice, {
fromNumericBase: 'hex',
@@ -120,7 +214,7 @@ CustomizeGasModal.prototype.render = function () {
h(GasModalCard, {
value: convertedGasPrice,
- min: MIN_GAS_PRICE,
+ min: MIN_GAS_PRICE_GWEI,
// max: 1000,
step: 1,
onChange: value => this.convertAndSetGasPrice(value),
@@ -130,7 +224,7 @@ CustomizeGasModal.prototype.render = function () {
h(GasModalCard, {
value: convertedGasLimit,
- min: MIN_GAS_LIMIT,
+ min: 1,
// max: 100000,
step: 1,
onChange: value => this.convertAndSetGasLimit(value),
@@ -141,6 +235,10 @@ CustomizeGasModal.prototype.render = function () {
]),
h('div.send-v2__customize-gas__footer', {}, [
+
+ error && h('div.send-v2__customize-gas__error-message', [
+ error,
+ ]),
h('div.send-v2__customize-gas__revert', {
onClick: () => console.log('Revert'),
@@ -151,8 +249,8 @@ CustomizeGasModal.prototype.render = function () {
onClick: this.props.hideModal,
}, ['CANCEL']),
- h('div.send-v2__customize-gas__save', {
- onClick: () => this.save(gasPrice, gasLimit),
+ h(`div.send-v2__customize-gas__save${error ? '__error' : ''}`, {
+ onClick: () => !error && this.save(gasPrice, gasLimit, gasTotal),
}, ['SAVE']),
])
diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js
index 302596eda..80d7779ef 100644
--- a/ui/app/components/modals/export-private-key-modal.js
+++ b/ui/app/components/modals/export-private-key-modal.js
@@ -66,7 +66,6 @@ ExportPrivateKeyModal.prototype.renderPasswordInput = function (privateKey) {
})
: h('input.private-key-password-input', {
type: 'password',
- placeholder: 'Type password',
onChange: event => this.setState({ password: event.target.value }),
})
}
diff --git a/ui/app/components/network.js b/ui/app/components/network.js
index b24505750..229d02e36 100644
--- a/ui/app/components/network.js
+++ b/ui/app/components/network.js
@@ -64,13 +64,18 @@ Network.prototype.render = function () {
return (
h('div.network-component.pointer', {
className: classnames('network-component pointer', {
+ 'network-component--disabled': this.props.disabled,
'ethereum-network': providerName === 'mainnet',
'ropsten-test-network': providerName === 'ropsten' || parseInt(networkNumber) === 3,
'kovan-test-network': providerName === 'kovan',
'rinkeby-test-network': providerName === 'rinkeby',
}),
title: hoverText,
- onClick: (event) => this.props.onClick(event),
+ onClick: (event) => {
+ if (!this.props.disabled) {
+ this.props.onClick(event)
+ }
+ },
}, [
(function () {
switch (iconName) {
diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js
index 7162c7122..64da630f6 100644
--- a/ui/app/components/pending-tx/confirm-send-ether.js
+++ b/ui/app/components/pending-tx/confirm-send-ether.js
@@ -50,7 +50,7 @@ ConfirmSendEther.prototype.getAmount = function () {
const { conversionRate, currentCurrency } = this.props
const txMeta = this.gatherTxMeta()
const txParams = txMeta.txParams || {}
- console.log(`conversionRate, currentCurrency`, conversionRate, currentCurrency);
+
const FIAT = conversionUtil(txParams.value, {
fromNumericBase: 'hex',
toNumericBase: 'dec',
diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js
index 799e9b56d..5dba6a8dd 100644
--- a/ui/app/components/send/currency-display.js
+++ b/ui/app/components/send/currency-display.js
@@ -20,14 +20,6 @@ function isValidInput (text) {
return re.test(text)
}
-function resetCaretIfPastEnd (value, event) {
- const caretPosition = event.target.selectionStart
-
- if (caretPosition > value.length) {
- event.target.setSelectionRange(value.length, value.length)
- }
-}
-
function toHexWei (value) {
return conversionUtil(value, {
fromNumericBase: 'dec',
@@ -82,6 +74,8 @@ CurrencyDisplay.prototype.render = function () {
conversionRate,
})
+ const inputSizeMultiplier = readOnly ? 1 : 1.2;
+
return h('div', {
className,
style: {
@@ -95,35 +89,33 @@ CurrencyDisplay.prototype.render = function () {
h('input', {
className: primaryBalanceClassName,
- value: `${value || initValueToRender} ${primaryCurrency}`,
- placeholder: `${0} ${primaryCurrency}`,
+ value: `${value || initValueToRender}`,
+ placeholder: '0',
+ size: (value || initValueToRender).length * inputSizeMultiplier,
readOnly,
onChange: (event) => {
- let newValue = event.target.value.split(' ')[0]
+ let newValue = event.target.value
if (newValue === '') {
- this.setState({ value: '0' })
+ newValue = '0'
}
else if (newValue.match(/^0[1-9]$/)) {
- this.setState({ value: newValue.match(/[1-9]/)[0] })
+ newValue = newValue.match(/[1-9]/)[0]
}
- else if (newValue && !isValidInput(newValue)) {
+
+ if (newValue && !isValidInput(newValue)) {
event.preventDefault()
}
else {
+ validate(this.getAmount(newValue))
this.setState({ value: newValue })
}
},
- onBlur: event => !readOnly && handleChange(this.getAmount(event.target.value.split(' ')[0])),
- onKeyUp: event => {
- if (!readOnly) {
- validate(toHexWei(value || initValueToRender))
- resetCaretIfPastEnd(value || initValueToRender, event)
- }
- },
- onClick: event => !readOnly && resetCaretIfPastEnd(value || initValueToRender, event),
+ onBlur: event => !readOnly && handleChange(this.getAmount(event.target.value)),
}),
+ h('span.currency-display__currency-symbol', primaryCurrency),
+
]),
]),
diff --git a/ui/app/components/send/send-constants.js b/ui/app/components/send/send-constants.js
index a819a8c28..8b56607cc 100644
--- a/ui/app/components/send/send-constants.js
+++ b/ui/app/components/send/send-constants.js
@@ -3,12 +3,19 @@ const { multiplyCurrencies } = require('../../conversion-util')
const MIN_GAS_PRICE_GWEI = '1'
const GWEI_FACTOR = '1e9'
-const MIN_GAS_PRICE = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, {
+const MIN_GAS_PRICE_HEX = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, {
multiplicandBase: 16,
multiplierBase: 16,
+ toNumericBase: 'hex',
+})
+const MIN_GAS_PRICE_DEC = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, {
+ multiplicandBase: 16,
+ multiplierBase: 16,
+ toNumericBase: 'dec',
})
-const MIN_GAS_LIMIT = (21000).toString(16)
-const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT, MIN_GAS_PRICE, {
+const MIN_GAS_LIMIT_HEX = (21000).toString(16)
+const MIN_GAS_LIMIT_DEC = 21000
+const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT_HEX, MIN_GAS_PRICE_HEX, {
toNumericBase: 'hex',
multiplicandBase: 16,
multiplierBase: 16,
@@ -16,8 +23,9 @@ const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT, MIN_GAS_PRICE, {
module.exports = {
MIN_GAS_PRICE_GWEI,
- GWEI_FACTOR,
- MIN_GAS_PRICE,
- MIN_GAS_LIMIT,
+ MIN_GAS_PRICE_HEX,
+ MIN_GAS_PRICE_DEC,
+ MIN_GAS_LIMIT_HEX,
+ MIN_GAS_LIMIT_DEC,
MIN_GAS_TOTAL,
}
diff --git a/ui/app/components/send/send-utils.js b/ui/app/components/send/send-utils.js
new file mode 100644
index 000000000..bf096d610
--- /dev/null
+++ b/ui/app/components/send/send-utils.js
@@ -0,0 +1,39 @@
+const { addCurrencies, conversionGreaterThan } = require('../../conversion-util')
+
+function isBalanceSufficient({
+ amount,
+ gasTotal,
+ balance,
+ primaryCurrency,
+ selectedToken,
+ amountConversionRate,
+ conversionRate,
+}) {
+ const totalAmount = addCurrencies(amount, gasTotal, {
+ aBase: 16,
+ bBase: 16,
+ toNumericBase: 'hex',
+ })
+
+ const balanceIsSufficient = conversionGreaterThan(
+ {
+ value: balance,
+ fromNumericBase: 'hex',
+ fromCurrency: primaryCurrency,
+ conversionRate,
+ },
+ {
+ value: totalAmount,
+ fromNumericBase: 'hex',
+ conversionRate: amountConversionRate,
+ fromCurrency: selectedToken || primaryCurrency,
+ conversionRate: amountConversionRate,
+ },
+ )
+
+ return balanceIsSufficient
+}
+
+module.exports = {
+ isBalanceSufficient,
+} \ No newline at end of file
diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js
index 80b52a3ab..fb2634de2 100644
--- a/ui/app/components/send/send-v2-container.js
+++ b/ui/app/components/send/send-v2-container.js
@@ -17,6 +17,7 @@ const {
getAddressBook,
getSendFrom,
getCurrentCurrency,
+ getSelectedTokenToFiatRate,
} = require('../../selectors')
module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther)
@@ -26,7 +27,6 @@ function mapStateToProps (state) {
const selectedAddress = getSelectedAddress(state)
const selectedToken = getSelectedToken(state)
const tokenExchangeRates = state.metamask.tokenExchangeRates
- const selectedTokenExchangeRate = getSelectedTokenExchangeRate(state)
const conversionRate = conversionRateSelector(state)
let data;
@@ -40,11 +40,7 @@ function mapStateToProps (state) {
primaryCurrency = selectedToken.symbol
- tokenToFiatRate = multiplyCurrencies(
- conversionRate,
- selectedTokenExchangeRate,
- { toNumericBase: 'dec' }
- )
+ tokenToFiatRate = getSelectedTokenToFiatRate(state)
}
return {
diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js
index d903998c0..ebef22680 100644
--- a/ui/app/components/tx-view.js
+++ b/ui/app/components/tx-view.js
@@ -109,14 +109,15 @@ TxView.prototype.render = function () {
margin: '1em 0.9em',
alignItems: 'center',
},
- onClick: () => {
- this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar()
- },
}, [
h('div.fa.fa-bars', {
style: {
fontSize: '1.3em',
+ cursor: 'pointer',
+ },
+ onClick: () => {
+ this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar()
},
}, []),
diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js
index a870a24e3..215103396 100644
--- a/ui/app/components/wallet-view.js
+++ b/ui/app/components/wallet-view.js
@@ -3,7 +3,8 @@ const connect = require('react-redux').connect
const h = require('react-hyperscript')
const inherits = require('util').inherits
const Identicon = require('./identicon')
-const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns
+// const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns
+const copyToClipboard = require('copy-to-clipboard')
const actions = require('../actions')
const BalanceComponent = require('./balance-component')
const TokenList = require('./token-list')
@@ -19,6 +20,7 @@ function mapStateToProps (state) {
identities: state.metamask.identities,
accounts: state.metamask.accounts,
tokens: state.metamask.tokens,
+ keyrings: state.metamask.keyrings,
selectedAddress: selectors.getSelectedAddress(state),
selectedIdentity: selectors.getSelectedIdentity(state),
selectedAccount: selectors.getSelectedAccount(state),
@@ -28,9 +30,13 @@ function mapStateToProps (state) {
function mapDispatchToProps (dispatch) {
return {
- showSendPage: () => { dispatch(actions.showSendPage()) },
- hideSidebar: () => { dispatch(actions.hideSidebar()) },
+ showSendPage: () => dispatch(actions.showSendPage()),
+ hideSidebar: () => dispatch(actions.hideSidebar()),
unsetSelectedToken: () => dispatch(actions.setSelectedToken()),
+ showAccountDetailModal: () => {
+ dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' }))
+ },
+ showAddTokenPage: () => dispatch(actions.showAddTokenPage()),
}
}
@@ -47,7 +53,7 @@ WalletView.prototype.renderWalletBalance = function () {
hideSidebar,
sidebarOpen,
} = this.props
- console.log({ selectedAccount })
+
const selectedClass = selectedTokenAddress
? ''
: 'wallet-balance-wrapper--active'
@@ -73,13 +79,25 @@ WalletView.prototype.renderWalletBalance = function () {
WalletView.prototype.render = function () {
const {
- network, responsiveDisplayClassname, identities,
- selectedAddress, accounts,
+ responsiveDisplayClassname,
+ selectedAddress,
selectedIdentity,
+ keyrings,
+ showAccountDetailModal,
+ hideSidebar,
+ showAddTokenPage,
} = this.props
// temporary logs + fake extra wallets
// console.log('walletview, selectedAccount:', selectedAccount)
+ const keyring = keyrings.find((kr) => {
+ return kr.accounts.includes(selectedAddress) ||
+ kr.accounts.includes(selectedIdentity.address)
+ })
+
+ const type = keyring.type
+ const isLoose = type !== 'HD Key Tree'
+
return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), {
style: {},
}, [
@@ -88,57 +106,16 @@ WalletView.prototype.render = function () {
h('div.flex-column.wallet-view-account-details', {
style: {},
}, [
+ h('div.wallet-view__sidebar-close', {
+ onClick: hideSidebar,
+ }),
- h('div.flex-row.account-options-menu', {
- style: {
- position: 'relative',
- },
- }, [
+ h('div.wallet-view__keyring-label', isLoose ? 'IMPORTED' : ''),
- h(AccountDropdowns, {
- selected: selectedAddress,
- network,
- identities,
- useCssTransition: true,
- enableAccountOptions: true,
- dropdownWrapperStyle: {
- padding: '1px 15px',
- marginLeft: '-25px',
- position: 'absolute',
- width: '122%', // TODO, refactor all of this component out into media queries
- },
- menuItemStyles: {
- padding: '0px 0px',
- margin: '22px 0px',
- },
- }, []),
-
- ]),
-
- h('div.flex-column.flex-center', {
+ h('div.flex-column.flex-center.wallet-view__name-container', {
+ style: { margin: '0 auto' },
+ onClick: showAccountDetailModal,
}, [
- h('div', {
- style: {
- position: 'relative',
- },
- }, [
- h(AccountDropdowns, {
- accounts,
- style: {
- position: 'absolute',
- left: 'calc(50% + 28px + 5.5px)',
- top: '14px',
- },
- innerStyle: {
- padding: '10px 16px',
- },
- useCssTransition: true,
- selected: selectedAddress,
- network,
- identities,
- }, []),
- ]),
-
h(Identicon, {
diameter: 54,
address: selectedAddress,
@@ -150,13 +127,20 @@ WalletView.prototype.render = function () {
selectedIdentity.name,
]),
+ h('button.wallet-view__details-button', 'DETAILS'),
]),
]),
+
+ h('div.wallet-view__address', { onClick: () => copyToClipboard(selectedAddress) }, [
+ `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`,
+ h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }),
+ ]),
+
// 'Wallet' - Title
// Not visible on mobile
- h('div.flex-column.wallet-view-title-wrapper', {}, [
- h('span.wallet-view-title', {}, [
+ h('div.flex-column.wallet-view-title-wrapper', [
+ h('span.wallet-view-title', [
'Wallet',
]),
]),
@@ -165,6 +149,9 @@ WalletView.prototype.render = function () {
h(TokenList),
+ h('button.wallet-view__add-token-button', {
+ onClick: showAddTokenPage,
+ }, 'Add Token'),
])
}
diff --git a/ui/app/css/itcss/components/account-menu.scss b/ui/app/css/itcss/components/account-menu.scss
index 090710f7b..91884e658 100644
--- a/ui/app/css/itcss/components/account-menu.scss
+++ b/ui/app/css/itcss/components/account-menu.scss
@@ -65,6 +65,8 @@
.keyring-label {
margin-top: 5px;
+ background-color: $black;
+ color: $dusty-gray;
}
}
@@ -88,9 +90,20 @@
&__check-mark {
width: 14px;
+ margin-right: 12px;
flex: 0 0 auto;
}
+ &__check-mark-icon {
+ background-image: url("images/check-white.svg");
+ height: 18px;
+ width: 18px;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: contain;
+ margin: 3px 0;
+ }
+
.identicon {
margin: 0 12px 0 0;
flex: 0 0 auto;
diff --git a/ui/app/css/itcss/components/add-token.scss b/ui/app/css/itcss/components/add-token.scss
index aa8221c9a..9bdda6a9b 100644
--- a/ui/app/css/itcss/components/add-token.scss
+++ b/ui/app/css/itcss/components/add-token.scss
@@ -109,7 +109,18 @@
cursor: pointer;
&:hover {
- background-color: $gallery;
+ background-color: rgba(0, 0, 0, .05);
+ }
+
+ &:active {
+ background-color: rgba(0, 0, 0, .1);
+ }
+
+ .fa {
+ position: absolute;
+ right: 24px;
+ font-size: 24px;
+ line-height: 24px;
}
}
diff --git a/ui/app/css/itcss/components/confirm.scss b/ui/app/css/itcss/components/confirm.scss
index d4f0fe5ac..c498afba2 100644
--- a/ui/app/css/itcss/components/confirm.scss
+++ b/ui/app/css/itcss/components/confirm.scss
@@ -37,7 +37,7 @@
overflow-y: auto;
top: 0;
box-shadow: none;
- height: calc(100vh - 58px - 100px);
+ height: calc(100vh - 58px - 85px);
border-top-left-radius: 0;
border-top-right-radius: 0;
}
@@ -271,6 +271,7 @@ section .confirm-screen-account-number,
box-shadow: none;
flex: 1 0 auto;
font-weight: 300;
+ margin: 0 8px;
}
.btn-light.confirm-screen-cancel-button {
@@ -288,6 +289,7 @@ section .confirm-screen-account-number,
cursor: pointer;
flex: 1 0 auto;
font-weight: 300;
+ margin: 0 8px;
}
#pending-tx-form {
@@ -296,7 +298,7 @@ section .confirm-screen-account-number,
display: flex;
flex-flow: row nowrap;
background-color: $white;
- padding: 19px 18px;
+ padding: 12px 18px;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
width: 100%;
diff --git a/ui/app/css/itcss/components/currency-display.scss b/ui/app/css/itcss/components/currency-display.scss
index eb1776c58..9459629b6 100644
--- a/ui/app/css/itcss/components/currency-display.scss
+++ b/ui/app/css/itcss/components/currency-display.scss
@@ -22,6 +22,7 @@
line-height: 22px;
border: none;
outline: 0 !important;
+ max-width: 100%;
}
&__primary-currency {
@@ -43,4 +44,13 @@
font-size: 12px;
line-height: 12px;
}
+
+ &__input-wrapper {
+ position: relative;
+ display: flex;
+ }
+
+ &__currency-symbol {
+ margin-top: 1px;
+ }
} \ No newline at end of file
diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss
index 1ffea58a9..139e5a8f2 100644
--- a/ui/app/css/itcss/components/modal.scss
+++ b/ui/app/css/itcss/components/modal.scss
@@ -372,6 +372,7 @@
resize: none;
padding: 9px 13px 8px;
text-transform: uppercase;
+ font-weight: 300;
}
diff --git a/ui/app/css/itcss/components/network.scss b/ui/app/css/itcss/components/network.scss
index bb8c4eea8..0bc66ea1a 100644
--- a/ui/app/css/itcss/components/network.scss
+++ b/ui/app/css/itcss/components/network.scss
@@ -1,3 +1,12 @@
+.network-component--disabled {
+ border-color: transparent !important;
+ cursor: default;
+
+ .fa-caret-down {
+ opacity: 0;
+ }
+}
+
.network-component.pointer {
border: 1px solid $shark;
border-radius: 82px;
@@ -40,7 +49,7 @@
.dropdown-menu-item {
.menu-icon-circle,
.menu-icon-circle--active {
- margin: 0 16px;
+ margin: 0 14px;
}
}
@@ -116,8 +125,8 @@
.menu-icon-circle div,
.menu-icon-circle--active div {
- height: 17px;
- width: 17px;
+ height: 12px;
+ width: 12px;
border-radius: 17px;
}
diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss
index 1ee8283ef..d975c56b7 100644
--- a/ui/app/css/itcss/components/newui-sections.scss
+++ b/ui/app/css/itcss/components/newui-sections.scss
@@ -45,6 +45,8 @@ $wallet-view-bg: $wild-sand;
flex-direction: column;
flex: 33.5 0 33.5%;
background: $wallet-view-bg;
+ z-index: 200;
+ position: relative;
@media screen and (min-width: 576px) {
overflow-y: scroll;
@@ -52,7 +54,77 @@ $wallet-view-bg: $wild-sand;
}
.wallet-view-account-details {
- flex: 0 0 150px;
+ flex: 0 0 auto;
+ }
+
+ &__name-container {
+ flex: 0 0 auto;
+ cursor: pointer;
+ }
+
+ &__keyring-label {
+ height: 40px;
+ color: $dusty-gray;
+ font-family: Roboto;
+ font-size: 10px;
+ line-height: 40px;
+ text-align: right;
+ padding: 0 20px;
+ }
+
+ &__details-button {
+ color: $curious-blue;
+ font-size: 10px;
+ line-height: 13px;
+ text-align: center;
+ border: 1px solid $curious-blue;
+ border-radius: 10.5px;
+ background-color: transparent;
+ margin: 0 auto;
+ padding: 4px 12px;
+ flex: 0 0 auto;
+ }
+
+ &__address {
+ border-radius: 3px;
+ background-color: $alto;
+ color: $scorpion;
+ font-size: 14px;
+ line-height: 12px;
+ padding: 4px 12px;
+ margin: 24px auto;
+ font-weight: 300;
+ cursor: pointer;
+ flex: 0 0 auto;
+ }
+
+ &__sidebar-close {
+
+ @media screen and (max-width: 575px) {
+ &::after {
+ content: '\00D7';
+ font-size: 40px;
+ color: $tundora;
+ position: absolute;
+ top: 12px;
+ left: 12px;
+ cursor: pointer;
+ }
+ }
+ }
+
+ &__add-token-button {
+ flex: 0 0 auto;
+ color: $dusty-gray;
+ font-size: 14px;
+ line-height: 19px;
+ text-align: center;
+ margin: 36px auto;
+ border: 1px solid $dusty-gray;
+ border-radius: 2px;
+ font-weight: 300;
+ background: none;
+ padding: 9px 30px;
}
}
@@ -173,15 +245,12 @@ $wallet-view-bg: $wild-sand;
// wallet view
.account-name {
-
- @media screen and (max-width: 575px) {
- font-size: 102%;
- margin-left: 3%;
- }
-
- @media screen and (max-width: 575px) {
- text-align: center;
- }
+ font-size: 24px;
+ font-weight: 200;
+ line-height: 20px;
+ color: $scorpion;
+ margin-top: 8px;
+ margin-bottom: 24px;
}
// account options dropdown
diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss
index c4efeccf0..bac5f4d05 100644
--- a/ui/app/css/itcss/components/send.scss
+++ b/ui/app/css/itcss/components/send.scss
@@ -657,15 +657,14 @@
width: 163px;
text-align: center;
height: 55px;
- width: 163px;
border-radius: 2px;
background-color: $white;
font-family: Roboto;
font-size: 16px;
font-weight: 300;
line-height: 21px;
- text-align: center;
border: 1px solid;
+ margin: 0 4px;
}
&__next-btn,
@@ -738,6 +737,7 @@
align-items: center;
justify-content: space-between;
font-size: 22px;
+ position: relative;
}
&__buttons {
@@ -747,7 +747,7 @@
margin-right: 21.25px;
}
- &__revert, &__cancel, &__save {
+ &__revert, &__cancel, &__save, &__save__error {
display: flex;
justify-content: center;
align-items: center;
@@ -760,7 +760,7 @@
margin-left: 21.25px;
}
- &__cancel, &__save {
+ &__cancel, &__save, &__save__error {
height: 34.64px;
width: 85.74px;
border: 1px solid $dusty-gray;
@@ -769,6 +769,21 @@
font-size: 12px;
color: $dusty-gray;
}
+
+ &__save__error {
+ opacity: 0.5;
+ cursor: auto;
+ }
+
+ &__error-message {
+ display: block;
+ position: absolute;
+ top: 4px;
+ right: 4px;
+ font-size: 12px;
+ line-height: 12px;
+ color: $red;
+ }
}
&__gas-modal-card {
diff --git a/ui/app/css/itcss/components/settings.scss b/ui/app/css/itcss/components/settings.scss
index d4bcdcc4b..d37a9d10d 100644
--- a/ui/app/css/itcss/components/settings.scss
+++ b/ui/app/css/itcss/components/settings.scss
@@ -38,6 +38,7 @@
@media screen and (max-width: 575px) {
flex-direction: column;
+ padding: 10px 0;
}
}
@@ -48,6 +49,11 @@
flex-direction: column;
padding: 0 5px;
height: 71px;
+
+ @media screen and (max-width: 575px) {
+ height: initial;
+ padding: 5px 0;
+ }
}
.settings__content-item-col {
@@ -71,6 +77,7 @@
padding-left: 10px;
font-size: 14px;
height: 40px;
+ border: 1px solid $alto;
}
.settings__input::-webkit-input-placeholder {
diff --git a/ui/app/css/itcss/components/token-list.scss b/ui/app/css/itcss/components/token-list.scss
index bbc64c324..d4add71b1 100644
--- a/ui/app/css/itcss/components/token-list.scss
+++ b/ui/app/css/itcss/components/token-list.scss
@@ -67,19 +67,21 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and (
position: fixed;
margin-top: 20px;
margin-left: 105px;
+ z-index: 2000;
&__close-area {
position: fixed;
top: 0;
left: 0;
- z-index: 1000;
+ z-index: 2100;
width: 100%;
height: 100%;
+ cursor: default;
}
&__container {
padding: 16px 34px 32px;
- z-index: 1050;
+ z-index: 2200;
position: relative;
}
diff --git a/ui/app/css/itcss/tools/utilities.scss b/ui/app/css/itcss/tools/utilities.scss
index ca9fd0d9c..ee867640d 100644
--- a/ui/app/css/itcss/tools/utilities.scss
+++ b/ui/app/css/itcss/tools/utilities.scss
@@ -237,7 +237,6 @@ hr.horizontal-line {
color: #fff;
border-radius: 10px;
padding: 4px;
- width: 41px;
text-align: center;
height: 15px;
}
diff --git a/ui/app/selectors.js b/ui/app/selectors.js
index 4c3d21d33..3a15cef4c 100644
--- a/ui/app/selectors.js
+++ b/ui/app/selectors.js
@@ -1,5 +1,9 @@
const valuesFor = require('./util').valuesFor
+const {
+ multiplyCurrencies,
+} = require('./conversion-util')
+
const selectors = {
getSelectedAddress,
getSelectedIdentity,
@@ -16,6 +20,8 @@ const selectors = {
getAddressBook,
getSendFrom,
getCurrentCurrency,
+ getSendAmount,
+ getSelectedTokenToFiatRate,
}
module.exports = selectors
@@ -123,6 +129,23 @@ function getSendFrom (state) {
return state.metamask.send.from
}
+function getSendAmount (state) {
+ return state.metamask.send.amount
+}
+
function getCurrentCurrency (state) {
return state.metamask.currentCurrency
}
+
+function getSelectedTokenToFiatRate (state) {
+ const selectedTokenExchangeRate = getSelectedTokenExchangeRate(state)
+ const conversionRate = conversionRateSelector(state)
+
+ const tokenToFiatRate = multiplyCurrencies(
+ conversionRate,
+ selectedTokenExchangeRate,
+ { toNumericBase: 'dec' }
+ )
+
+ return tokenToFiatRate
+}
diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js
index 4986edf5f..7fa8ca18a 100644
--- a/ui/app/send-v2.js
+++ b/ui/app/send-v2.js
@@ -2,6 +2,7 @@ const { inherits } = require('util')
const PersistentForm = require('../lib/persistent-form')
const h = require('react-hyperscript')
const connect = require('react-redux').connect
+const classnames = require('classnames')
const Identicon = require('./components/identicon')
const FromDropdown = require('./components/send/from-dropdown')
@@ -19,6 +20,9 @@ const {
conversionGreaterThan,
addCurrencies,
} = require('./conversion-util')
+const {
+ isBalanceSufficient,
+} = require('./components/send/send-utils.js')
const { isValidAddress } = require('./util')
module.exports = SendTransactionScreen
@@ -237,28 +241,16 @@ SendTransactionScreen.prototype.validateAmount = function (value) {
let amountError = null
- const totalAmount = addCurrencies(amount, gasTotal, {
- aBase: 16,
- bBase: 16,
- toNumericBase: 'hex',
+ const sufficientBalance = isBalanceSufficient({
+ amount,
+ gasTotal,
+ balance,
+ primaryCurrency,
+ selectedToken,
+ amountConversionRate,
+ conversionRate,
})
- const sufficientBalance = conversionGreaterThan(
- {
- value: balance,
- fromNumericBase: 'hex',
- fromCurrency: primaryCurrency,
- conversionRate,
- },
- {
- value: totalAmount,
- fromNumericBase: 'hex',
- conversionRate: amountConversionRate,
- fromCurrency: selectedToken || primaryCurrency,
- conversionRate: amountConversionRate,
- },
- )
-
const amountLessThanZero = conversionGreaterThan(
{ value: 0, fromNumericBase: 'dec' },
{ value: amount, fromNumericBase: 'hex' },
@@ -399,7 +391,6 @@ SendTransactionScreen.prototype.renderFooter = function () {
},
}, 'Cancel'),
h(`button.send-v2__next-btn${errorClass}`, {
- onClick: event => noErrors && this.onSubmit(event),
}, 'Next'),
])
}
diff --git a/ui/app/settings.js b/ui/app/settings.js
index 2ac70d82d..b6fae7707 100644
--- a/ui/app/settings.js
+++ b/ui/app/settings.js
@@ -208,7 +208,7 @@ class Settings extends Component {
h('div.settings__content', [
warning && h('div.settings__error', warning),
this.renderCurrentConversion(),
- this.renderCurrentProvider(),
+ // this.renderCurrentProvider(),
this.renderNewRpcUrl(),
this.renderStateLogs(),
this.renderSeedWords(),