1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 01:39:44 +01:00

Merge branch 'NewUI-flat' into NewUI-flat-disable-send-next-in-error

This commit is contained in:
Daniel Tsui 2017-10-24 04:32:19 -07:00 committed by GitHub
commit 09445ef692
29 changed files with 494 additions and 193 deletions

View 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

View File

@ -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(),
]),
]),

View File

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

View File

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

View File

@ -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, {
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',
multiplicandBase: 16,
multiplierBase: 16,
})
updateGasPrice(gasPrice)
updateGasLimit(gasLimit)
updateGasTotal(newGasTotal)
hideModal()
}
this.validate({ gasTotal, gasLimit })
CustomizeGasModal.prototype.convertAndSetGasLimit = function (newGasLimit) {
const convertedGasLimit = conversionUtil(newGasLimit, {
fromNumericBase: 'dec',
toNumericBase: 'hex',
})
this.setState({ gasLimit: convertedGasLimit })
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']),
])

View File

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

View File

@ -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) {

View File

@ -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',

View File

@ -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),
]),
]),

View File

@ -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_LIMIT = (21000).toString(16)
const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT, MIN_GAS_PRICE, {
const MIN_GAS_PRICE_DEC = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, {
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',
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,
}

View 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,
}

View File

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

View File

@ -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()
},
}, []),

View File

@ -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('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, {
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'),
])
}

View File

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

View File

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

View File

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

View File

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

View File

@ -372,6 +372,7 @@
resize: none;
padding: 9px 13px 8px;
text-transform: uppercase;
font-weight: 300;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -237,7 +237,6 @@ hr.horizontal-line {
color: #fff;
border-radius: 10px;
padding: 4px;
width: 41px;
text-align: center;
height: 15px;
}

View File

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

View File

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

View File

@ -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(),

View File

@ -3450,9 +3450,9 @@ eth-json-rpc-middleware@^1.0.0, eth-json-rpc-middleware@^1.2.7:
promise-to-callback "^1.0.0"
tape "^4.6.3"
eth-keyring-controller@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-2.1.1.tgz#08129c8300f0ac6de9110e0b8d51292b5c6327e3"
eth-keyring-controller@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-2.1.2.tgz#1af179d8fd7ff470eb91e113a0fd3a440bd66bcc"
dependencies:
bip39 "^2.4.0"
bluebird "^3.5.0"
@ -8540,14 +8540,12 @@ samsam@1.x, samsam@^1.1.3:
version "1.2.1"
resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.2.1.tgz#edd39093a3184370cb859243b2bdf255e7d8ea67"
sandwich-expando@^1.0.5:
version "1.1.1"
resolved "https://registry.yarnpkg.com/sandwich-expando/-/sandwich-expando-1.1.1.tgz#83806fcca2375af8b6c30e6f52ed4f989debb165"
sandwich-expando@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/sandwich-expando/-/sandwich-expando-1.1.3.tgz#6ba78d034c32f8bf5ab5934c214f8384614a88a5"
dependencies:
babel-preset-es2015 "^6.6.0"
babelify "^7.3.0"
brfs "^1.4.3"
raphael "^2.2.0"
react "^15.0.2"
react-dom "^15.0.2"
react-hyperscript "^2.4.0"