mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge branch 'NewUI-flat' into NewUI-flat-disable-send-next-in-error
This commit is contained in:
commit
09445ef692
14
app/images/check-white.svg
Normal file
14
app/images/check-white.svg
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="16px" height="13px" viewBox="0 0 16 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 47 (45396) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>check-white</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="MetaMascara-v2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="account-dropdown-top-bar-IXD" transform="translate(-17.000000, -80.000000)" fill-rule="nonzero" fill="#FFFFFF">
|
||||||
|
<g id="Group-11" transform="translate(18.000000, 74.000000)">
|
||||||
|
<polygon id="check-white" points="4.2 15.5712828 0.714212839 12.0143571 -0.714212839 13.4142143 4.2 18.4287172 14.7142128 7.69992858 13.2857872 6.30007142"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 872 B |
@ -350,7 +350,10 @@ AddTokenScreen.prototype.render = function () {
|
|||||||
h('div.add-token__footers', [
|
h('div.add-token__footers', [
|
||||||
h('div.add-token__add-custom', {
|
h('div.add-token__add-custom', {
|
||||||
onClick: () => this.setState({ isCollapsed: !isCollapsed }),
|
onClick: () => this.setState({ isCollapsed: !isCollapsed }),
|
||||||
}, 'Add custom token'),
|
}, [
|
||||||
|
'Add custom token',
|
||||||
|
h(`i.fa.fa-angle-${isCollapsed ? 'down' : 'up'}`),
|
||||||
|
]),
|
||||||
this.renderCustomForm(),
|
this.renderCustomForm(),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
|
@ -203,6 +203,16 @@ App.prototype.renderSidebar = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
App.prototype.renderAppBar = function () {
|
App.prototype.renderAppBar = function () {
|
||||||
|
const {
|
||||||
|
isUnlocked,
|
||||||
|
network,
|
||||||
|
provider,
|
||||||
|
networkDropdownOpen,
|
||||||
|
showNetworkDropdown,
|
||||||
|
hideNetworkDropdown,
|
||||||
|
currentView,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
if (window.METAMASK_UI_TYPE === 'notification') {
|
if (window.METAMASK_UI_TYPE === 'notification') {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -243,22 +253,21 @@ App.prototype.renderAppBar = function () {
|
|||||||
}, [
|
}, [
|
||||||
// Network Indicator
|
// Network Indicator
|
||||||
h(NetworkIndicator, {
|
h(NetworkIndicator, {
|
||||||
network: this.props.network,
|
network,
|
||||||
provider: this.props.provider,
|
provider,
|
||||||
|
disabled: currentView.name === 'confTx',
|
||||||
onClick: (event) => {
|
onClick: (event) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
if (this.props.networkDropdownOpen === false) {
|
return networkDropdownOpen === false
|
||||||
this.props.showNetworkDropdown()
|
? showNetworkDropdown()
|
||||||
} else {
|
: hideNetworkDropdown()
|
||||||
this.props.hideNetworkDropdown()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
|
||||||
h('div.account-menu__icon', { onClick: this.props.toggleAccountMenu }, [
|
isUnlocked && h('div.account-menu__icon', { onClick: this.props.toggleAccountMenu }, [
|
||||||
h(Identicon, {
|
h(Identicon, {
|
||||||
address: this.props.selectedAddress,
|
address: this.props.selectedAddress,
|
||||||
diameter: 32,
|
diameter: 32,
|
||||||
|
@ -63,10 +63,11 @@ AccountMenu.prototype.render = function () {
|
|||||||
h(CloseArea, { onClick: toggleAccountMenu }),
|
h(CloseArea, { onClick: toggleAccountMenu }),
|
||||||
h(Item, {
|
h(Item, {
|
||||||
className: 'account-menu__header',
|
className: 'account-menu__header',
|
||||||
onClick: lockMetamask,
|
|
||||||
}, [
|
}, [
|
||||||
'My Accounts',
|
'My Accounts',
|
||||||
h('button.account-menu__logout-button', 'Log out'),
|
h('button.account-menu__logout-button', {
|
||||||
|
onClick: lockMetamask,
|
||||||
|
}, 'Log out'),
|
||||||
]),
|
]),
|
||||||
h(Divider),
|
h(Divider),
|
||||||
h('div.account-menu__accounts', this.renderAccounts()),
|
h('div.account-menu__accounts', this.renderAccounts()),
|
||||||
@ -98,15 +99,14 @@ AccountMenu.prototype.renderAccounts = function () {
|
|||||||
const {
|
const {
|
||||||
identities,
|
identities,
|
||||||
accounts,
|
accounts,
|
||||||
selected,
|
selectedAddress,
|
||||||
keyrings,
|
keyrings,
|
||||||
showAccountDetail,
|
showAccountDetail,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
console.log({ accounts })
|
|
||||||
return Object.keys(identities).map((key, index) => {
|
return Object.keys(identities).map((key, index) => {
|
||||||
const identity = identities[key]
|
const identity = identities[key]
|
||||||
const isSelected = identity.address === selected
|
const isSelected = identity.address === selectedAddress
|
||||||
|
|
||||||
const balanceValue = accounts[key] ? accounts[key].balance : ''
|
const balanceValue = accounts[key] ? accounts[key].balance : ''
|
||||||
const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...'
|
const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...'
|
||||||
@ -122,7 +122,7 @@ AccountMenu.prototype.renderAccounts = function () {
|
|||||||
{ onClick: () => showAccountDetail(identity.address) },
|
{ onClick: () => showAccountDetail(identity.address) },
|
||||||
[
|
[
|
||||||
h('div.account-menu__check-mark', [
|
h('div.account-menu__check-mark', [
|
||||||
isSelected ? h('i.fa.fa-check') : null,
|
isSelected ? h('div.account-menu__check-mark-icon') : null,
|
||||||
]),
|
]),
|
||||||
|
|
||||||
h(
|
h(
|
||||||
@ -148,6 +148,6 @@ AccountMenu.prototype.indicateIfLoose = function (keyring) {
|
|||||||
try { // Sometimes keyrings aren't loaded yet:
|
try { // Sometimes keyrings aren't loaded yet:
|
||||||
const type = keyring.type
|
const type = keyring.type
|
||||||
const isLoose = type !== 'HD Key Tree'
|
const isLoose = type !== 'HD Key Tree'
|
||||||
return isLoose ? h('.keyring-label', 'LOOSE') : null
|
return isLoose ? h('.keyring-label', 'IMPORTED') : null
|
||||||
} catch (e) { return }
|
} catch (e) { return }
|
||||||
}
|
}
|
||||||
|
@ -6,23 +6,46 @@ const actions = require('../../actions')
|
|||||||
const GasModalCard = require('./gas-modal-card')
|
const GasModalCard = require('./gas-modal-card')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
MIN_GAS_PRICE,
|
MIN_GAS_PRICE_DEC,
|
||||||
MIN_GAS_LIMIT,
|
MIN_GAS_LIMIT_DEC,
|
||||||
|
MIN_GAS_PRICE_GWEI,
|
||||||
} = require('../send/send-constants')
|
} = require('../send/send-constants')
|
||||||
|
|
||||||
const { conversionUtil, multiplyCurrencies } = require('../../conversion-util')
|
const {
|
||||||
|
isBalanceSufficient,
|
||||||
|
} = require('../send/send-utils')
|
||||||
|
|
||||||
|
const {
|
||||||
|
conversionUtil,
|
||||||
|
multiplyCurrencies,
|
||||||
|
conversionGreaterThan,
|
||||||
|
} = require('../../conversion-util')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getGasPrice,
|
getGasPrice,
|
||||||
getGasLimit,
|
getGasLimit,
|
||||||
conversionRateSelector,
|
conversionRateSelector,
|
||||||
|
getSendAmount,
|
||||||
|
getSelectedToken,
|
||||||
|
getSendFrom,
|
||||||
|
getCurrentAccountWithSendEtherInfo,
|
||||||
|
getSelectedTokenToFiatRate,
|
||||||
} = require('../../selectors')
|
} = require('../../selectors')
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
|
const selectedToken = getSelectedToken(state)
|
||||||
|
const currentAccount = getSendFrom(state) || getCurrentAccountWithSendEtherInfo(state)
|
||||||
|
const conversionRate = conversionRateSelector(state)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
gasPrice: getGasPrice(state),
|
gasPrice: getGasPrice(state),
|
||||||
gasLimit: getGasLimit(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) {
|
function CustomizeGasModal (props) {
|
||||||
Component.call(this)
|
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 = {
|
this.state = {
|
||||||
gasPrice: props.gasPrice || MIN_GAS_PRICE,
|
gasPrice,
|
||||||
gasLimit: props.gasLimit || MIN_GAS_LIMIT,
|
gasLimit,
|
||||||
|
gasTotal,
|
||||||
|
error: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(CustomizeGasModal)
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(CustomizeGasModal)
|
||||||
|
|
||||||
CustomizeGasModal.prototype.save = function (gasPrice, gasLimit) {
|
CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) {
|
||||||
const {
|
const {
|
||||||
updateGasPrice,
|
updateGasPrice,
|
||||||
updateGasLimit,
|
updateGasLimit,
|
||||||
@ -55,41 +89,101 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit) {
|
|||||||
updateGasTotal
|
updateGasTotal
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const newGasTotal = multiplyCurrencies(gasLimit, gasPrice, {
|
updateGasPrice(gasPrice)
|
||||||
|
updateGasLimit(gasLimit)
|
||||||
|
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 { gasPrice } = this.state
|
||||||
|
|
||||||
|
const gasLimit = conversionUtil(newGasLimit, {
|
||||||
|
fromNumericBase: 'dec',
|
||||||
|
toNumericBase: 'hex',
|
||||||
|
})
|
||||||
|
|
||||||
|
const gasTotal = multiplyCurrencies(gasLimit, gasPrice, {
|
||||||
toNumericBase: 'hex',
|
toNumericBase: 'hex',
|
||||||
multiplicandBase: 16,
|
multiplicandBase: 16,
|
||||||
multiplierBase: 16,
|
multiplierBase: 16,
|
||||||
})
|
})
|
||||||
|
|
||||||
updateGasPrice(gasPrice)
|
this.validate({ gasTotal, gasLimit })
|
||||||
updateGasLimit(gasLimit)
|
|
||||||
updateGasTotal(newGasTotal)
|
|
||||||
hideModal()
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomizeGasModal.prototype.convertAndSetGasLimit = function (newGasLimit) {
|
this.setState({ gasTotal, gasLimit })
|
||||||
const convertedGasLimit = conversionUtil(newGasLimit, {
|
|
||||||
fromNumericBase: 'dec',
|
|
||||||
toNumericBase: 'hex',
|
|
||||||
})
|
|
||||||
|
|
||||||
this.setState({ gasLimit: convertedGasLimit })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) {
|
CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) {
|
||||||
const convertedGasPrice = conversionUtil(newGasPrice, {
|
const { gasLimit } = this.state
|
||||||
|
|
||||||
|
const gasPrice = conversionUtil(newGasPrice, {
|
||||||
fromNumericBase: 'dec',
|
fromNumericBase: 'dec',
|
||||||
toNumericBase: 'hex',
|
toNumericBase: 'hex',
|
||||||
fromDenomination: 'GWEI',
|
fromDenomination: 'GWEI',
|
||||||
toDenomination: 'WEI',
|
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 () {
|
CustomizeGasModal.prototype.render = function () {
|
||||||
const { hideModal, conversionRate } = this.props
|
const { hideModal, conversionRate } = this.props
|
||||||
const { gasPrice, gasLimit } = this.state
|
const { gasPrice, gasLimit, gasTotal, error } = this.state
|
||||||
|
|
||||||
const convertedGasPrice = conversionUtil(gasPrice, {
|
const convertedGasPrice = conversionUtil(gasPrice, {
|
||||||
fromNumericBase: 'hex',
|
fromNumericBase: 'hex',
|
||||||
@ -120,7 +214,7 @@ CustomizeGasModal.prototype.render = function () {
|
|||||||
|
|
||||||
h(GasModalCard, {
|
h(GasModalCard, {
|
||||||
value: convertedGasPrice,
|
value: convertedGasPrice,
|
||||||
min: MIN_GAS_PRICE,
|
min: MIN_GAS_PRICE_GWEI,
|
||||||
// max: 1000,
|
// max: 1000,
|
||||||
step: 1,
|
step: 1,
|
||||||
onChange: value => this.convertAndSetGasPrice(value),
|
onChange: value => this.convertAndSetGasPrice(value),
|
||||||
@ -130,7 +224,7 @@ CustomizeGasModal.prototype.render = function () {
|
|||||||
|
|
||||||
h(GasModalCard, {
|
h(GasModalCard, {
|
||||||
value: convertedGasLimit,
|
value: convertedGasLimit,
|
||||||
min: MIN_GAS_LIMIT,
|
min: 1,
|
||||||
// max: 100000,
|
// max: 100000,
|
||||||
step: 1,
|
step: 1,
|
||||||
onChange: value => this.convertAndSetGasLimit(value),
|
onChange: value => this.convertAndSetGasLimit(value),
|
||||||
@ -141,6 +235,10 @@ CustomizeGasModal.prototype.render = function () {
|
|||||||
]),
|
]),
|
||||||
|
|
||||||
h('div.send-v2__customize-gas__footer', {}, [
|
h('div.send-v2__customize-gas__footer', {}, [
|
||||||
|
|
||||||
|
error && h('div.send-v2__customize-gas__error-message', [
|
||||||
|
error,
|
||||||
|
]),
|
||||||
|
|
||||||
h('div.send-v2__customize-gas__revert', {
|
h('div.send-v2__customize-gas__revert', {
|
||||||
onClick: () => console.log('Revert'),
|
onClick: () => console.log('Revert'),
|
||||||
@ -151,8 +249,8 @@ CustomizeGasModal.prototype.render = function () {
|
|||||||
onClick: this.props.hideModal,
|
onClick: this.props.hideModal,
|
||||||
}, ['CANCEL']),
|
}, ['CANCEL']),
|
||||||
|
|
||||||
h('div.send-v2__customize-gas__save', {
|
h(`div.send-v2__customize-gas__save${error ? '__error' : ''}`, {
|
||||||
onClick: () => this.save(gasPrice, gasLimit),
|
onClick: () => !error && this.save(gasPrice, gasLimit, gasTotal),
|
||||||
}, ['SAVE']),
|
}, ['SAVE']),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -66,7 +66,6 @@ ExportPrivateKeyModal.prototype.renderPasswordInput = function (privateKey) {
|
|||||||
})
|
})
|
||||||
: h('input.private-key-password-input', {
|
: h('input.private-key-password-input', {
|
||||||
type: 'password',
|
type: 'password',
|
||||||
placeholder: 'Type password',
|
|
||||||
onChange: event => this.setState({ password: event.target.value }),
|
onChange: event => this.setState({ password: event.target.value }),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -64,13 +64,18 @@ Network.prototype.render = function () {
|
|||||||
return (
|
return (
|
||||||
h('div.network-component.pointer', {
|
h('div.network-component.pointer', {
|
||||||
className: classnames('network-component pointer', {
|
className: classnames('network-component pointer', {
|
||||||
|
'network-component--disabled': this.props.disabled,
|
||||||
'ethereum-network': providerName === 'mainnet',
|
'ethereum-network': providerName === 'mainnet',
|
||||||
'ropsten-test-network': providerName === 'ropsten' || parseInt(networkNumber) === 3,
|
'ropsten-test-network': providerName === 'ropsten' || parseInt(networkNumber) === 3,
|
||||||
'kovan-test-network': providerName === 'kovan',
|
'kovan-test-network': providerName === 'kovan',
|
||||||
'rinkeby-test-network': providerName === 'rinkeby',
|
'rinkeby-test-network': providerName === 'rinkeby',
|
||||||
}),
|
}),
|
||||||
title: hoverText,
|
title: hoverText,
|
||||||
onClick: (event) => this.props.onClick(event),
|
onClick: (event) => {
|
||||||
|
if (!this.props.disabled) {
|
||||||
|
this.props.onClick(event)
|
||||||
|
}
|
||||||
|
},
|
||||||
}, [
|
}, [
|
||||||
(function () {
|
(function () {
|
||||||
switch (iconName) {
|
switch (iconName) {
|
||||||
|
@ -50,7 +50,7 @@ ConfirmSendEther.prototype.getAmount = function () {
|
|||||||
const { conversionRate, currentCurrency } = this.props
|
const { conversionRate, currentCurrency } = this.props
|
||||||
const txMeta = this.gatherTxMeta()
|
const txMeta = this.gatherTxMeta()
|
||||||
const txParams = txMeta.txParams || {}
|
const txParams = txMeta.txParams || {}
|
||||||
console.log(`conversionRate, currentCurrency`, conversionRate, currentCurrency);
|
|
||||||
const FIAT = conversionUtil(txParams.value, {
|
const FIAT = conversionUtil(txParams.value, {
|
||||||
fromNumericBase: 'hex',
|
fromNumericBase: 'hex',
|
||||||
toNumericBase: 'dec',
|
toNumericBase: 'dec',
|
||||||
|
@ -20,14 +20,6 @@ function isValidInput (text) {
|
|||||||
return re.test(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) {
|
function toHexWei (value) {
|
||||||
return conversionUtil(value, {
|
return conversionUtil(value, {
|
||||||
fromNumericBase: 'dec',
|
fromNumericBase: 'dec',
|
||||||
@ -82,6 +74,8 @@ CurrencyDisplay.prototype.render = function () {
|
|||||||
conversionRate,
|
conversionRate,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const inputSizeMultiplier = readOnly ? 1 : 1.2;
|
||||||
|
|
||||||
return h('div', {
|
return h('div', {
|
||||||
className,
|
className,
|
||||||
style: {
|
style: {
|
||||||
@ -95,35 +89,33 @@ CurrencyDisplay.prototype.render = function () {
|
|||||||
|
|
||||||
h('input', {
|
h('input', {
|
||||||
className: primaryBalanceClassName,
|
className: primaryBalanceClassName,
|
||||||
value: `${value || initValueToRender} ${primaryCurrency}`,
|
value: `${value || initValueToRender}`,
|
||||||
placeholder: `${0} ${primaryCurrency}`,
|
placeholder: '0',
|
||||||
|
size: (value || initValueToRender).length * inputSizeMultiplier,
|
||||||
readOnly,
|
readOnly,
|
||||||
onChange: (event) => {
|
onChange: (event) => {
|
||||||
let newValue = event.target.value.split(' ')[0]
|
let newValue = event.target.value
|
||||||
|
|
||||||
if (newValue === '') {
|
if (newValue === '') {
|
||||||
this.setState({ value: '0' })
|
newValue = '0'
|
||||||
}
|
}
|
||||||
else if (newValue.match(/^0[1-9]$/)) {
|
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()
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
validate(this.getAmount(newValue))
|
||||||
this.setState({ value: newValue })
|
this.setState({ value: newValue })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onBlur: event => !readOnly && handleChange(this.getAmount(event.target.value.split(' ')[0])),
|
onBlur: event => !readOnly && handleChange(this.getAmount(event.target.value)),
|
||||||
onKeyUp: event => {
|
|
||||||
if (!readOnly) {
|
|
||||||
validate(toHexWei(value || initValueToRender))
|
|
||||||
resetCaretIfPastEnd(value || initValueToRender, event)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClick: event => !readOnly && resetCaretIfPastEnd(value || initValueToRender, event),
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
h('span.currency-display__currency-symbol', primaryCurrency),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
@ -3,12 +3,19 @@ const { multiplyCurrencies } = require('../../conversion-util')
|
|||||||
|
|
||||||
const MIN_GAS_PRICE_GWEI = '1'
|
const MIN_GAS_PRICE_GWEI = '1'
|
||||||
const GWEI_FACTOR = '1e9'
|
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,
|
multiplicandBase: 16,
|
||||||
multiplierBase: 16,
|
multiplierBase: 16,
|
||||||
|
toNumericBase: 'hex',
|
||||||
})
|
})
|
||||||
const MIN_GAS_LIMIT = (21000).toString(16)
|
const MIN_GAS_PRICE_DEC = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, {
|
||||||
const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT, MIN_GAS_PRICE, {
|
multiplicandBase: 16,
|
||||||
|
multiplierBase: 16,
|
||||||
|
toNumericBase: 'dec',
|
||||||
|
})
|
||||||
|
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',
|
toNumericBase: 'hex',
|
||||||
multiplicandBase: 16,
|
multiplicandBase: 16,
|
||||||
multiplierBase: 16,
|
multiplierBase: 16,
|
||||||
@ -16,8 +23,9 @@ const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT, MIN_GAS_PRICE, {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
MIN_GAS_PRICE_GWEI,
|
MIN_GAS_PRICE_GWEI,
|
||||||
GWEI_FACTOR,
|
MIN_GAS_PRICE_HEX,
|
||||||
MIN_GAS_PRICE,
|
MIN_GAS_PRICE_DEC,
|
||||||
MIN_GAS_LIMIT,
|
MIN_GAS_LIMIT_HEX,
|
||||||
|
MIN_GAS_LIMIT_DEC,
|
||||||
MIN_GAS_TOTAL,
|
MIN_GAS_TOTAL,
|
||||||
}
|
}
|
||||||
|
39
ui/app/components/send/send-utils.js
Normal file
39
ui/app/components/send/send-utils.js
Normal file
@ -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,
|
||||||
|
}
|
@ -17,6 +17,7 @@ const {
|
|||||||
getAddressBook,
|
getAddressBook,
|
||||||
getSendFrom,
|
getSendFrom,
|
||||||
getCurrentCurrency,
|
getCurrentCurrency,
|
||||||
|
getSelectedTokenToFiatRate,
|
||||||
} = require('../../selectors')
|
} = require('../../selectors')
|
||||||
|
|
||||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther)
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther)
|
||||||
@ -26,7 +27,6 @@ function mapStateToProps (state) {
|
|||||||
const selectedAddress = getSelectedAddress(state)
|
const selectedAddress = getSelectedAddress(state)
|
||||||
const selectedToken = getSelectedToken(state)
|
const selectedToken = getSelectedToken(state)
|
||||||
const tokenExchangeRates = state.metamask.tokenExchangeRates
|
const tokenExchangeRates = state.metamask.tokenExchangeRates
|
||||||
const selectedTokenExchangeRate = getSelectedTokenExchangeRate(state)
|
|
||||||
const conversionRate = conversionRateSelector(state)
|
const conversionRate = conversionRateSelector(state)
|
||||||
|
|
||||||
let data;
|
let data;
|
||||||
@ -40,11 +40,7 @@ function mapStateToProps (state) {
|
|||||||
|
|
||||||
primaryCurrency = selectedToken.symbol
|
primaryCurrency = selectedToken.symbol
|
||||||
|
|
||||||
tokenToFiatRate = multiplyCurrencies(
|
tokenToFiatRate = getSelectedTokenToFiatRate(state)
|
||||||
conversionRate,
|
|
||||||
selectedTokenExchangeRate,
|
|
||||||
{ toNumericBase: 'dec' }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -109,14 +109,15 @@ TxView.prototype.render = function () {
|
|||||||
margin: '1em 0.9em',
|
margin: '1em 0.9em',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
onClick: () => {
|
|
||||||
this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar()
|
|
||||||
},
|
|
||||||
}, [
|
}, [
|
||||||
|
|
||||||
h('div.fa.fa-bars', {
|
h('div.fa.fa-bars', {
|
||||||
style: {
|
style: {
|
||||||
fontSize: '1.3em',
|
fontSize: '1.3em',
|
||||||
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar()
|
||||||
},
|
},
|
||||||
}, []),
|
}, []),
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@ const connect = require('react-redux').connect
|
|||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const inherits = require('util').inherits
|
const inherits = require('util').inherits
|
||||||
const Identicon = require('./identicon')
|
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 actions = require('../actions')
|
||||||
const BalanceComponent = require('./balance-component')
|
const BalanceComponent = require('./balance-component')
|
||||||
const TokenList = require('./token-list')
|
const TokenList = require('./token-list')
|
||||||
@ -19,6 +20,7 @@ function mapStateToProps (state) {
|
|||||||
identities: state.metamask.identities,
|
identities: state.metamask.identities,
|
||||||
accounts: state.metamask.accounts,
|
accounts: state.metamask.accounts,
|
||||||
tokens: state.metamask.tokens,
|
tokens: state.metamask.tokens,
|
||||||
|
keyrings: state.metamask.keyrings,
|
||||||
selectedAddress: selectors.getSelectedAddress(state),
|
selectedAddress: selectors.getSelectedAddress(state),
|
||||||
selectedIdentity: selectors.getSelectedIdentity(state),
|
selectedIdentity: selectors.getSelectedIdentity(state),
|
||||||
selectedAccount: selectors.getSelectedAccount(state),
|
selectedAccount: selectors.getSelectedAccount(state),
|
||||||
@ -28,9 +30,13 @@ function mapStateToProps (state) {
|
|||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
function mapDispatchToProps (dispatch) {
|
||||||
return {
|
return {
|
||||||
showSendPage: () => { dispatch(actions.showSendPage()) },
|
showSendPage: () => dispatch(actions.showSendPage()),
|
||||||
hideSidebar: () => { dispatch(actions.hideSidebar()) },
|
hideSidebar: () => dispatch(actions.hideSidebar()),
|
||||||
unsetSelectedToken: () => dispatch(actions.setSelectedToken()),
|
unsetSelectedToken: () => dispatch(actions.setSelectedToken()),
|
||||||
|
showAccountDetailModal: () => {
|
||||||
|
dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' }))
|
||||||
|
},
|
||||||
|
showAddTokenPage: () => dispatch(actions.showAddTokenPage()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +53,7 @@ WalletView.prototype.renderWalletBalance = function () {
|
|||||||
hideSidebar,
|
hideSidebar,
|
||||||
sidebarOpen,
|
sidebarOpen,
|
||||||
} = this.props
|
} = this.props
|
||||||
console.log({ selectedAccount })
|
|
||||||
const selectedClass = selectedTokenAddress
|
const selectedClass = selectedTokenAddress
|
||||||
? ''
|
? ''
|
||||||
: 'wallet-balance-wrapper--active'
|
: 'wallet-balance-wrapper--active'
|
||||||
@ -73,13 +79,25 @@ WalletView.prototype.renderWalletBalance = function () {
|
|||||||
|
|
||||||
WalletView.prototype.render = function () {
|
WalletView.prototype.render = function () {
|
||||||
const {
|
const {
|
||||||
network, responsiveDisplayClassname, identities,
|
responsiveDisplayClassname,
|
||||||
selectedAddress, accounts,
|
selectedAddress,
|
||||||
selectedIdentity,
|
selectedIdentity,
|
||||||
|
keyrings,
|
||||||
|
showAccountDetailModal,
|
||||||
|
hideSidebar,
|
||||||
|
showAddTokenPage,
|
||||||
} = this.props
|
} = this.props
|
||||||
// temporary logs + fake extra wallets
|
// temporary logs + fake extra wallets
|
||||||
// console.log('walletview, selectedAccount:', selectedAccount)
|
// 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 || ''), {
|
return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), {
|
||||||
style: {},
|
style: {},
|
||||||
}, [
|
}, [
|
||||||
@ -88,57 +106,16 @@ WalletView.prototype.render = function () {
|
|||||||
h('div.flex-column.wallet-view-account-details', {
|
h('div.flex-column.wallet-view-account-details', {
|
||||||
style: {},
|
style: {},
|
||||||
}, [
|
}, [
|
||||||
|
h('div.wallet-view__sidebar-close', {
|
||||||
|
onClick: hideSidebar,
|
||||||
|
}),
|
||||||
|
|
||||||
h('div.flex-row.account-options-menu', {
|
h('div.wallet-view__keyring-label', isLoose ? 'IMPORTED' : ''),
|
||||||
style: {
|
|
||||||
position: 'relative',
|
h('div.flex-column.flex-center.wallet-view__name-container', {
|
||||||
},
|
style: { margin: '0 auto' },
|
||||||
|
onClick: showAccountDetailModal,
|
||||||
}, [
|
}, [
|
||||||
|
|
||||||
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', {
|
|
||||||
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, {
|
h(Identicon, {
|
||||||
diameter: 54,
|
diameter: 54,
|
||||||
address: selectedAddress,
|
address: selectedAddress,
|
||||||
@ -150,13 +127,20 @@ WalletView.prototype.render = function () {
|
|||||||
selectedIdentity.name,
|
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
|
// 'Wallet' - Title
|
||||||
// Not visible on mobile
|
// Not visible on mobile
|
||||||
h('div.flex-column.wallet-view-title-wrapper', {}, [
|
h('div.flex-column.wallet-view-title-wrapper', [
|
||||||
h('span.wallet-view-title', {}, [
|
h('span.wallet-view-title', [
|
||||||
'Wallet',
|
'Wallet',
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
@ -165,6 +149,9 @@ WalletView.prototype.render = function () {
|
|||||||
|
|
||||||
h(TokenList),
|
h(TokenList),
|
||||||
|
|
||||||
|
h('button.wallet-view__add-token-button', {
|
||||||
|
onClick: showAddTokenPage,
|
||||||
|
}, 'Add Token'),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,8 @@
|
|||||||
|
|
||||||
.keyring-label {
|
.keyring-label {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
background-color: $black;
|
||||||
|
color: $dusty-gray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,9 +90,20 @@
|
|||||||
|
|
||||||
&__check-mark {
|
&__check-mark {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
|
margin-right: 12px;
|
||||||
flex: 0 0 auto;
|
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 {
|
.identicon {
|
||||||
margin: 0 12px 0 0;
|
margin: 0 12px 0 0;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
@ -109,7 +109,18 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&: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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
top: 0;
|
top: 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
height: calc(100vh - 58px - 100px);
|
height: calc(100vh - 58px - 85px);
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
}
|
}
|
||||||
@ -271,6 +271,7 @@ section .confirm-screen-account-number,
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
|
margin: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-light.confirm-screen-cancel-button {
|
.btn-light.confirm-screen-cancel-button {
|
||||||
@ -288,6 +289,7 @@ section .confirm-screen-account-number,
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
|
margin: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pending-tx-form {
|
#pending-tx-form {
|
||||||
@ -296,7 +298,7 @@ section .confirm-screen-account-number,
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row nowrap;
|
flex-flow: row nowrap;
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
padding: 19px 18px;
|
padding: 12px 18px;
|
||||||
border-bottom-left-radius: 8px;
|
border-bottom-left-radius: 8px;
|
||||||
border-bottom-right-radius: 8px;
|
border-bottom-right-radius: 8px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
border: none;
|
border: none;
|
||||||
outline: 0 !important;
|
outline: 0 !important;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__primary-currency {
|
&__primary-currency {
|
||||||
@ -43,4 +44,13 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 12px;
|
line-height: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__input-wrapper {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__currency-symbol {
|
||||||
|
margin-top: 1px;
|
||||||
|
}
|
||||||
}
|
}
|
@ -372,6 +372,7 @@
|
|||||||
resize: none;
|
resize: none;
|
||||||
padding: 9px 13px 8px;
|
padding: 9px 13px 8px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
font-weight: 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
.network-component--disabled {
|
||||||
|
border-color: transparent !important;
|
||||||
|
cursor: default;
|
||||||
|
|
||||||
|
.fa-caret-down {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.network-component.pointer {
|
.network-component.pointer {
|
||||||
border: 1px solid $shark;
|
border: 1px solid $shark;
|
||||||
border-radius: 82px;
|
border-radius: 82px;
|
||||||
@ -40,7 +49,7 @@
|
|||||||
.dropdown-menu-item {
|
.dropdown-menu-item {
|
||||||
.menu-icon-circle,
|
.menu-icon-circle,
|
||||||
.menu-icon-circle--active {
|
.menu-icon-circle--active {
|
||||||
margin: 0 16px;
|
margin: 0 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,8 +125,8 @@
|
|||||||
|
|
||||||
.menu-icon-circle div,
|
.menu-icon-circle div,
|
||||||
.menu-icon-circle--active div {
|
.menu-icon-circle--active div {
|
||||||
height: 17px;
|
height: 12px;
|
||||||
width: 17px;
|
width: 12px;
|
||||||
border-radius: 17px;
|
border-radius: 17px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,8 @@ $wallet-view-bg: $wild-sand;
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 33.5 0 33.5%;
|
flex: 33.5 0 33.5%;
|
||||||
background: $wallet-view-bg;
|
background: $wallet-view-bg;
|
||||||
|
z-index: 200;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
@media screen and (min-width: 576px) {
|
@media screen and (min-width: 576px) {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
@ -52,7 +54,77 @@ $wallet-view-bg: $wild-sand;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wallet-view-account-details {
|
.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
|
// wallet view
|
||||||
.account-name {
|
.account-name {
|
||||||
|
font-size: 24px;
|
||||||
@media screen and (max-width: 575px) {
|
font-weight: 200;
|
||||||
font-size: 102%;
|
line-height: 20px;
|
||||||
margin-left: 3%;
|
color: $scorpion;
|
||||||
}
|
margin-top: 8px;
|
||||||
|
margin-bottom: 24px;
|
||||||
@media screen and (max-width: 575px) {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// account options dropdown
|
// account options dropdown
|
||||||
|
@ -657,15 +657,14 @@
|
|||||||
width: 163px;
|
width: 163px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 55px;
|
height: 55px;
|
||||||
width: 163px;
|
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
font-family: Roboto;
|
font-family: Roboto;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
line-height: 21px;
|
line-height: 21px;
|
||||||
text-align: center;
|
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
|
margin: 0 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__next-btn,
|
&__next-btn,
|
||||||
@ -738,6 +737,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__buttons {
|
&__buttons {
|
||||||
@ -747,7 +747,7 @@
|
|||||||
margin-right: 21.25px;
|
margin-right: 21.25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__revert, &__cancel, &__save {
|
&__revert, &__cancel, &__save, &__save__error {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -760,7 +760,7 @@
|
|||||||
margin-left: 21.25px;
|
margin-left: 21.25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__cancel, &__save {
|
&__cancel, &__save, &__save__error {
|
||||||
height: 34.64px;
|
height: 34.64px;
|
||||||
width: 85.74px;
|
width: 85.74px;
|
||||||
border: 1px solid $dusty-gray;
|
border: 1px solid $dusty-gray;
|
||||||
@ -769,6 +769,21 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: $dusty-gray;
|
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 {
|
&__gas-modal-card {
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
@media screen and (max-width: 575px) {
|
@media screen and (max-width: 575px) {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
padding: 10px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +49,11 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
height: 71px;
|
height: 71px;
|
||||||
|
|
||||||
|
@media screen and (max-width: 575px) {
|
||||||
|
height: initial;
|
||||||
|
padding: 5px 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings__content-item-col {
|
.settings__content-item-col {
|
||||||
@ -71,6 +77,7 @@
|
|||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
border: 1px solid $alto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings__input::-webkit-input-placeholder {
|
.settings__input::-webkit-input-placeholder {
|
||||||
|
@ -67,19 +67,21 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and (
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
margin-left: 105px;
|
margin-left: 105px;
|
||||||
|
z-index: 2000;
|
||||||
|
|
||||||
&__close-area {
|
&__close-area {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 1000;
|
z-index: 2100;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__container {
|
&__container {
|
||||||
padding: 16px 34px 32px;
|
padding: 16px 34px 32px;
|
||||||
z-index: 1050;
|
z-index: 2200;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +237,6 @@ hr.horizontal-line {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
width: 41px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
const valuesFor = require('./util').valuesFor
|
const valuesFor = require('./util').valuesFor
|
||||||
|
|
||||||
|
const {
|
||||||
|
multiplyCurrencies,
|
||||||
|
} = require('./conversion-util')
|
||||||
|
|
||||||
const selectors = {
|
const selectors = {
|
||||||
getSelectedAddress,
|
getSelectedAddress,
|
||||||
getSelectedIdentity,
|
getSelectedIdentity,
|
||||||
@ -16,6 +20,8 @@ const selectors = {
|
|||||||
getAddressBook,
|
getAddressBook,
|
||||||
getSendFrom,
|
getSendFrom,
|
||||||
getCurrentCurrency,
|
getCurrentCurrency,
|
||||||
|
getSendAmount,
|
||||||
|
getSelectedTokenToFiatRate,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = selectors
|
module.exports = selectors
|
||||||
@ -123,6 +129,23 @@ function getSendFrom (state) {
|
|||||||
return state.metamask.send.from
|
return state.metamask.send.from
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSendAmount (state) {
|
||||||
|
return state.metamask.send.amount
|
||||||
|
}
|
||||||
|
|
||||||
function getCurrentCurrency (state) {
|
function getCurrentCurrency (state) {
|
||||||
return state.metamask.currentCurrency
|
return state.metamask.currentCurrency
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSelectedTokenToFiatRate (state) {
|
||||||
|
const selectedTokenExchangeRate = getSelectedTokenExchangeRate(state)
|
||||||
|
const conversionRate = conversionRateSelector(state)
|
||||||
|
|
||||||
|
const tokenToFiatRate = multiplyCurrencies(
|
||||||
|
conversionRate,
|
||||||
|
selectedTokenExchangeRate,
|
||||||
|
{ toNumericBase: 'dec' }
|
||||||
|
)
|
||||||
|
|
||||||
|
return tokenToFiatRate
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ const { inherits } = require('util')
|
|||||||
const PersistentForm = require('../lib/persistent-form')
|
const PersistentForm = require('../lib/persistent-form')
|
||||||
const h = require('react-hyperscript')
|
const h = require('react-hyperscript')
|
||||||
const connect = require('react-redux').connect
|
const connect = require('react-redux').connect
|
||||||
|
const classnames = require('classnames')
|
||||||
|
|
||||||
const Identicon = require('./components/identicon')
|
const Identicon = require('./components/identicon')
|
||||||
const FromDropdown = require('./components/send/from-dropdown')
|
const FromDropdown = require('./components/send/from-dropdown')
|
||||||
@ -19,6 +20,9 @@ const {
|
|||||||
conversionGreaterThan,
|
conversionGreaterThan,
|
||||||
addCurrencies,
|
addCurrencies,
|
||||||
} = require('./conversion-util')
|
} = require('./conversion-util')
|
||||||
|
const {
|
||||||
|
isBalanceSufficient,
|
||||||
|
} = require('./components/send/send-utils.js')
|
||||||
const { isValidAddress } = require('./util')
|
const { isValidAddress } = require('./util')
|
||||||
|
|
||||||
module.exports = SendTransactionScreen
|
module.exports = SendTransactionScreen
|
||||||
@ -237,28 +241,16 @@ SendTransactionScreen.prototype.validateAmount = function (value) {
|
|||||||
|
|
||||||
let amountError = null
|
let amountError = null
|
||||||
|
|
||||||
const totalAmount = addCurrencies(amount, gasTotal, {
|
const sufficientBalance = isBalanceSufficient({
|
||||||
aBase: 16,
|
amount,
|
||||||
bBase: 16,
|
gasTotal,
|
||||||
toNumericBase: 'hex',
|
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(
|
const amountLessThanZero = conversionGreaterThan(
|
||||||
{ value: 0, fromNumericBase: 'dec' },
|
{ value: 0, fromNumericBase: 'dec' },
|
||||||
{ value: amount, fromNumericBase: 'hex' },
|
{ value: amount, fromNumericBase: 'hex' },
|
||||||
@ -399,7 +391,6 @@ SendTransactionScreen.prototype.renderFooter = function () {
|
|||||||
},
|
},
|
||||||
}, 'Cancel'),
|
}, 'Cancel'),
|
||||||
h(`button.send-v2__next-btn${errorClass}`, {
|
h(`button.send-v2__next-btn${errorClass}`, {
|
||||||
onClick: event => noErrors && this.onSubmit(event),
|
|
||||||
}, 'Next'),
|
}, 'Next'),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ class Settings extends Component {
|
|||||||
h('div.settings__content', [
|
h('div.settings__content', [
|
||||||
warning && h('div.settings__error', warning),
|
warning && h('div.settings__error', warning),
|
||||||
this.renderCurrentConversion(),
|
this.renderCurrentConversion(),
|
||||||
this.renderCurrentProvider(),
|
// this.renderCurrentProvider(),
|
||||||
this.renderNewRpcUrl(),
|
this.renderNewRpcUrl(),
|
||||||
this.renderStateLogs(),
|
this.renderStateLogs(),
|
||||||
this.renderSeedWords(),
|
this.renderSeedWords(),
|
||||||
|
14
yarn.lock
14
yarn.lock
@ -3450,9 +3450,9 @@ eth-json-rpc-middleware@^1.0.0, eth-json-rpc-middleware@^1.2.7:
|
|||||||
promise-to-callback "^1.0.0"
|
promise-to-callback "^1.0.0"
|
||||||
tape "^4.6.3"
|
tape "^4.6.3"
|
||||||
|
|
||||||
eth-keyring-controller@^2.1.0:
|
eth-keyring-controller@^2.1.2:
|
||||||
version "2.1.1"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-2.1.1.tgz#08129c8300f0ac6de9110e0b8d51292b5c6327e3"
|
resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-2.1.2.tgz#1af179d8fd7ff470eb91e113a0fd3a440bd66bcc"
|
||||||
dependencies:
|
dependencies:
|
||||||
bip39 "^2.4.0"
|
bip39 "^2.4.0"
|
||||||
bluebird "^3.5.0"
|
bluebird "^3.5.0"
|
||||||
@ -8540,14 +8540,12 @@ samsam@1.x, samsam@^1.1.3:
|
|||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.2.1.tgz#edd39093a3184370cb859243b2bdf255e7d8ea67"
|
resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.2.1.tgz#edd39093a3184370cb859243b2bdf255e7d8ea67"
|
||||||
|
|
||||||
sandwich-expando@^1.0.5:
|
sandwich-expando@^1.1.3:
|
||||||
version "1.1.1"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/sandwich-expando/-/sandwich-expando-1.1.1.tgz#83806fcca2375af8b6c30e6f52ed4f989debb165"
|
resolved "https://registry.yarnpkg.com/sandwich-expando/-/sandwich-expando-1.1.3.tgz#6ba78d034c32f8bf5ab5934c214f8384614a88a5"
|
||||||
dependencies:
|
dependencies:
|
||||||
babel-preset-es2015 "^6.6.0"
|
babel-preset-es2015 "^6.6.0"
|
||||||
babelify "^7.3.0"
|
babelify "^7.3.0"
|
||||||
brfs "^1.4.3"
|
|
||||||
raphael "^2.2.0"
|
|
||||||
react "^15.0.2"
|
react "^15.0.2"
|
||||||
react-dom "^15.0.2"
|
react-dom "^15.0.2"
|
||||||
react-hyperscript "^2.4.0"
|
react-hyperscript "^2.4.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user