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

Merge pull request #2519 from danjm/NewUI-flat-lintfixes

[NewUI-flat] New ui flat lintfixes
This commit is contained in:
Thomas Huang 2017-11-02 10:02:09 -07:00 committed by GitHub
commit 86e88dc813
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 1142 additions and 970 deletions

View File

@ -46,8 +46,6 @@ class PreferencesController {
}
removeToken (rawAddress) {
const address = normalizeAddress(rawAddress)
const tokens = this.store.getState().tokens
const updatedTokens = tokens.filter(token => token.address !== rawAddress)

View File

@ -190,6 +190,7 @@
"enzyme": "^2.8.2",
"eslint-plugin-chai": "0.0.1",
"eslint-plugin-mocha": "^4.9.0",
"eslint-plugin-react": "^7.4.0",
"eth-json-rpc-middleware": "^1.2.7",
"fs-promise": "^2.0.3",
"gulp": "github:gulpjs/gulp#4.0",

View File

@ -17,6 +17,10 @@ function PrivateKeyImportView () {
Component.call(this)
}
PrivateKeyImportView.prototype.componentWillUnmount = function () {
this.props.dispatch(actions.displayWarning(null))
}
PrivateKeyImportView.prototype.render = function () {
const { error } = this.props

View File

@ -224,6 +224,8 @@ var actions = {
TOGGLE_ACCOUNT_MENU: 'TOGGLE_ACCOUNT_MENU',
toggleAccountMenu,
useEtherscanProvider,
}
module.exports = actions
@ -428,7 +430,7 @@ function addNewAccount () {
forceUpdateMetamaskState(dispatch)
return resolve(newAccountAddress)
})
});
})
}
}
@ -619,7 +621,7 @@ function updateSendErrors (error) {
function clearSend () {
return {
type: actions.CLEAR_SEND
type: actions.CLEAR_SEND,
}
}
@ -808,9 +810,50 @@ function updateMetamaskState (newState) {
}
}
const backgroundSetLocked = () => {
return new Promise((resolve, reject) => {
background.setLocked(error => {
if (error) {
return reject(error)
}
resolve()
})
})
}
const updateMetamaskStateFromBackground = () => {
log.debug(`background.getState`)
return new Promise((resolve, reject) => {
background.getState((error, newState) => {
if (error) {
return reject(error)
}
resolve(newState)
})
})
}
function lockMetamask () {
log.debug(`background.setLocked`)
return callBackgroundThenUpdate(background.setLocked)
return dispatch => {
dispatch(actions.showLoadingIndication())
return backgroundSetLocked()
.then(() => updateMetamaskStateFromBackground())
.catch(error => {
dispatch(actions.displayWarning(error.message))
return Promise.reject(error)
})
.then(newState => {
dispatch(actions.updateMetamaskState(newState))
dispatch({ type: actions.LOCK_METAMASK })
})
.catch(() => dispatch({ type: actions.LOCK_METAMASK }))
}
}
function setCurrentAccountTab (newTabName) {
@ -961,10 +1004,10 @@ function addTokens (tokens) {
}
}
function updateTokens(newTokens) {
function updateTokens (newTokens) {
return {
type: actions.UPDATE_TOKENS,
newTokens
newTokens,
}
}
@ -1038,7 +1081,7 @@ function setProviderType (type) {
}
}
function updateProviderType(type) {
function updateProviderType (type) {
return {
type: actions.SET_PROVIDER_TYPE,
value: type,
@ -1196,7 +1239,7 @@ function exportAccount (password, address) {
}
}
function exportAccountComplete() {
function exportAccountComplete () {
return {
type: actions.EXPORT_ACCOUNT,
}

View File

@ -21,9 +21,7 @@ const fuse = new Fuse(contractList, {
})
const actions = require('./actions')
const ethUtil = require('ethereumjs-util')
const abi = require('human-standard-token-abi')
const Eth = require('ethjs-query')
const EthContract = require('ethjs-contract')
const { tokenInfoGetter } = require('./token-util')
const R = require('ramda')
const emptyAddr = '0x0000000000000000000000000000000000000000'
@ -63,11 +61,7 @@ function AddTokenScreen () {
}
AddTokenScreen.prototype.componentWillMount = function () {
if (typeof global.ethereumProvider === 'undefined') return
this.eth = new Eth(global.ethereumProvider)
this.contract = new EthContract(this.eth)
this.TokenContract = this.contract(abi)
this.tokenInfoGetter = tokenInfoGetter()
}
AddTokenScreen.prototype.toggleToken = function (address, token) {
@ -164,18 +158,11 @@ AddTokenScreen.prototype.validate = function () {
}
AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address) {
const contract = this.TokenContract.at(address)
const results = await Promise.all([
contract.symbol(),
contract.decimals(),
])
const [ symbol, decimals ] = results
const { symbol, decimals } = await this.tokenInfoGetter(address)
if (symbol && decimals) {
this.setState({
customSymbol: symbol[0],
customDecimals: decimals[0].toString(),
customSymbol: symbol,
customDecimals: decimals.toString(),
})
}
}

View File

@ -2,7 +2,6 @@ const inherits = require('util').inherits
const Component = require('react').Component
const connect = require('react-redux').connect
const h = require('react-hyperscript')
const { checkFeatureToggle } = require('../lib/feature-toggle-utils')
const actions = require('./actions')
// mascara
const MascaraFirstTime = require('../../mascara/src/app/first-time').default
@ -12,9 +11,7 @@ const InitializeMenuScreen = require('./first-time/init-menu')
const NewKeyChainScreen = require('./new-keychain')
// accounts
const MainContainer = require('./main-container')
const SendTransactionScreen = require('./send')
const SendTransactionScreen2 = require('./components/send/send-v2-container')
const SendTokenScreen = require('./components/send-token')
const ConfirmTxScreen = require('./conf-tx')
// notice
const NoticeScreen = require('./components/notice')
@ -27,7 +24,6 @@ const WalletView = require('./components/wallet-view')
const Settings = require('./settings')
const AddTokenScreen = require('./add-token')
const Import = require('./accounts/import')
const InfoScreen = require('./info')
const Loading = require('./components/loading')
const NetworkIndicator = require('./components/network')
const Identicon = require('./components/identicon')
@ -38,6 +34,7 @@ const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation
const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
const NetworkDropdown = require('./components/dropdowns/network-dropdown')
const AccountMenu = require('./components/account-menu')
const QrView = require('./components/qr-code')
// Global Modals
const Modal = require('./components/modals/index').Modal
@ -148,7 +145,7 @@ App.prototype.render = function () {
(isLoading || isLoadingNetwork) && h(Loading, {
loadingMessage: loadMessage,
}),
// this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }),
// content
@ -228,8 +225,6 @@ App.prototype.renderAppBar = function () {
}
const props = this.props
const state = this.state || {}
const isNetworkMenuOpen = state.isNetworkMenuOpen || false
const {isMascara, isOnboarding} = props
// Do not render header if user is in mascara onboarding

View File

@ -32,6 +32,7 @@ function mapDispatchToProps (dispatch) {
},
lockMetamask: () => {
dispatch(actions.lockMetamask())
dispatch(actions.displayWarning(null))
dispatch(actions.toggleAccountMenu())
},
showConfigPage: () => {

View File

@ -2,7 +2,7 @@ const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const InputNumber = require('../input-number.js')
const GasSlider = require('./gas-slider.js')
// const GasSlider = require('./gas-slider.js')
module.exports = GasModalCard
@ -13,8 +13,7 @@ function GasModalCard () {
GasModalCard.prototype.render = function () {
const {
memo,
identities,
// memo,
onChange,
unitLabel,
value,
@ -22,7 +21,7 @@ GasModalCard.prototype.render = function () {
// max,
step,
title,
copy
copy,
} = this.props
return h('div.send-v2__gas-modal-card', [
@ -48,8 +47,8 @@ GasModalCard.prototype.render = function () {
// min,
// onChange,
// }),
])
}

View File

@ -1,50 +1,50 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
// const Component = require('react').Component
// const h = require('react-hyperscript')
// const inherits = require('util').inherits
module.exports = GasSlider
// module.exports = GasSlider
inherits(GasSlider, Component)
function GasSlider () {
Component.call(this)
}
// inherits(GasSlider, Component)
// function GasSlider () {
// Component.call(this)
// }
GasSlider.prototype.render = function () {
const {
memo,
identities,
onChange,
unitLabel,
value,
id,
step,
max,
min,
} = this.props
// GasSlider.prototype.render = function () {
// const {
// memo,
// identities,
// onChange,
// unitLabel,
// value,
// id,
// step,
// max,
// min,
// } = this.props
return h('div.gas-slider', [
// return h('div.gas-slider', [
h('input.gas-slider__input', {
type: 'range',
step,
max,
min,
value,
id: 'gasSlider',
onChange: event => onChange(event.target.value),
}, []),
// h('input.gas-slider__input', {
// type: 'range',
// step,
// max,
// min,
// value,
// id: 'gasSlider',
// onChange: event => onChange(event.target.value),
// }, []),
h('div.gas-slider__bar', [
// h('div.gas-slider__bar', [
h('div.gas-slider__low'),
// h('div.gas-slider__low'),
h('div.gas-slider__mid'),
// h('div.gas-slider__mid'),
h('div.gas-slider__high'),
// h('div.gas-slider__high'),
]),
])
}
// ]),
// ])
// }

View File

@ -58,7 +58,7 @@ function mapDispatchToProps (dispatch) {
}
}
function getOriginalState(props) {
function getOriginalState (props) {
const gasPrice = props.gasPrice || MIN_GAS_PRICE_DEC
const gasLimit = props.gasLimit || MIN_GAS_LIMIT_DEC
@ -90,7 +90,7 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) {
updateGasPrice,
updateGasLimit,
hideModal,
updateGasTotal
updateGasTotal,
} = this.props
updateGasPrice(gasPrice)
@ -126,9 +126,9 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) {
})
if (!balanceIsSufficient) {
error = 'Insufficient balance for current gas total'
error = 'Insufficient balance for current gas total'
}
const gasLimitTooLow = gasLimit && conversionGreaterThan(
{
value: MIN_GAS_LIMIT_DEC,
@ -142,7 +142,7 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) {
)
if (gasLimitTooLow) {
error = 'Gas limit must be at least 21000'
error = 'Gas limit must be at least 21000'
}
this.setState({ error })
@ -190,7 +190,7 @@ CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) {
}
CustomizeGasModal.prototype.render = function () {
const { hideModal, conversionRate } = this.props
const { hideModal } = this.props
const { gasPrice, gasLimit, gasTotal, error } = this.state
const convertedGasPrice = conversionUtil(gasPrice, {
@ -219,12 +219,12 @@ CustomizeGasModal.prototype.render = function () {
]),
h('div.send-v2__customize-gas__body', {}, [
h(GasModalCard, {
value: convertedGasPrice,
min: MIN_GAS_PRICE_GWEI,
// max: 1000,
step: 1,
step: MIN_GAS_PRICE_GWEI,
onChange: value => this.convertAndSetGasPrice(value),
title: 'Gas Price (GWEI)',
copy: 'We calculate the suggested gas prices based on network success rates.',
@ -247,7 +247,7 @@ CustomizeGasModal.prototype.render = function () {
error && h('div.send-v2__customize-gas__error-message', [
error,
]),
h('div.send-v2__customize-gas__revert', {
onClick: () => this.revert(),
}, ['Revert']),
@ -260,7 +260,7 @@ CustomizeGasModal.prototype.render = function () {
h(`div.send-v2__customize-gas__save${error ? '__error' : ''}`, {
onClick: () => !error && this.save(gasPrice, gasLimit, gasTotal),
}, ['SAVE']),
])
]),
]),

View File

@ -1,7 +1,6 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const Identicon = require('../identicon')
const AccountListItem = require('../send/account-list-item')
module.exports = AccountDropdownMini
@ -38,13 +37,13 @@ AccountDropdownMini.prototype.renderDropdown = function () {
...accounts.map(account => h(AccountListItem, {
account,
displayBalance: false,
displayAddress: false,
displayAddress: false,
handleClick: () => {
onSelect(account)
closeDropdown()
},
},
icon: this.getListItemIcon(account, selectedAccount),
}))
})),
]),
@ -53,10 +52,8 @@ AccountDropdownMini.prototype.renderDropdown = function () {
AccountDropdownMini.prototype.render = function () {
const {
accounts,
selectedAccount,
openDropdown,
closeDropdown,
dropdownOpen,
} = this.props
@ -67,12 +64,12 @@ AccountDropdownMini.prototype.render = function () {
handleClick: openDropdown,
displayBalance: false,
displayAddress: false,
icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } })
icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } }),
}),
dropdownOpen && this.renderDropdown(),
])
}

View File

@ -19,7 +19,7 @@ AccountOptionsDropdown.prototype.render = function () {
return h(AccountDropdowns, {
enableAccountOptions: true,
enableAccountsSelector: false,
selected: selectedAddress,
selected,
network,
identities,
style: style || {},

View File

@ -19,7 +19,7 @@ AccountSelectionDropdown.prototype.render = function () {
return h(AccountDropdowns, {
enableAccountOptions: false,
enableAccountsSelector: true,
selected: selectedAddress,
selected,
network,
identities,
style: style || {},

View File

@ -425,6 +425,21 @@ AccountDropdowns.propTypes = {
identities: PropTypes.objectOf(PropTypes.object),
selected: PropTypes.string,
keyrings: PropTypes.array,
accounts: PropTypes.object,
menuItemStyles: PropTypes.object,
actions: PropTypes.object,
// actions.showAccountDetail: ,
useCssTransition: PropTypes.bool,
innerStyle: PropTypes.object,
sidebarOpen: PropTypes.bool,
dropdownWrapperStyle: PropTypes.string,
// actions.showAccountDetailModal: ,
network: PropTypes.number,
// actions.showExportPrivateKeyModal: ,
style: PropTypes.object,
enableAccountsSelector: PropTypes.bool,
enableAccountOption: PropTypes.bool,
enableAccountOptions: PropTypes.bool,
}
const mapDispatchToProps = (dispatch) => {

View File

@ -68,6 +68,7 @@ Dropdown.propTypes = {
onClickOutside: PropTypes.func,
innerStyle: PropTypes.object,
useCssTransition: PropTypes.bool,
containerClassName: PropTypes.string,
}
class DropdownMenuItem extends Component {

View File

@ -1,4 +1,5 @@
const { Component, PropTypes } = require('react')
const { Component } = require('react')
const PropTypes = require('react').PropTypes
const h = require('react-hyperscript')
const classnames = require('classnames')
const R = require('ramda')

View File

@ -10,7 +10,7 @@ function mapDispatchToProps (dispatch) {
return {
showHideTokenConfirmationModal: (token) => {
dispatch(actions.showModal({ name: 'HIDE_TOKEN_CONFIRMATION', token }))
}
},
}
}
@ -36,14 +36,14 @@ TokenMenuDropdown.prototype.render = function () {
}),
h('div.token-menu-dropdown__container', {}, [
h('div.token-menu-dropdown__options', {}, [
h('div.token-menu-dropdown__option', {
onClick: (e) => {
e.stopPropagation()
showHideTokenConfirmationModal(this.props.token)
this.props.onClose()
},
}, 'Hide Token')
}, 'Hide Token'),
]),
]),

View File

@ -1,7 +1,12 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const { addCurrencies } = require('../conversion-util')
const {
addCurrencies,
conversionGTE,
conversionLTE,
toNegative,
} = require('../conversion-util')
module.exports = InputNumber
@ -17,8 +22,21 @@ InputNumber.prototype.setValue = function (newValue) {
newValue = Number(fixed ? newValue.toFixed(4) : newValue)
if (newValue >= min && newValue <= max) {
const newValueGreaterThanMin = conversionGTE(
{ value: newValue, fromNumericBase: 'dec' },
{ value: min, fromNumericBase: 'hex' },
)
const newValueLessThanMax = conversionLTE(
{ value: newValue, fromNumericBase: 'dec' },
{ value: max, fromNumericBase: 'hex' },
)
if (newValueGreaterThanMin && newValueLessThanMax) {
onChange(newValue)
} else if (!newValueGreaterThanMin) {
onChange(min)
} else if (!newValueLessThanMax) {
onChange(max)
}
}
@ -29,7 +47,7 @@ InputNumber.prototype.render = function () {
h('input.customize-gas-input', {
placeholder,
type: 'number',
value: value,
value,
onChange: (e) => this.setValue(e.target.value),
}),
h('span.gas-tooltip-input-detail', {}, [unitLabel]),
@ -39,7 +57,7 @@ InputNumber.prototype.render = function () {
}),
h('i.fa.fa-angle-down', {
style: { cursor: 'pointer' },
onClick: () => this.setValue(addCurrencies(value, step * -1)),
onClick: () => this.setValue(addCurrencies(value, toNegative(step))),
}),
]),
])

View File

@ -1,5 +1,6 @@
const { Component } = require('react')
const h = require('react-hyperscript')
const PropTypes = require('react').PropTypes
class LoadingIndicator extends Component {
renderMessage () {
@ -35,4 +36,8 @@ class LoadingIndicator extends Component {
}
}
LoadingIndicator.propTypes = {
loadingMessage: PropTypes.string,
}
module.exports = LoadingIndicator

View File

@ -4,7 +4,7 @@ const inherits = require('util').inherits
const connect = require('react-redux').connect
const actions = require('../../actions')
const AccountModalContainer = require('./account-modal-container')
const { getSelectedIdentity, getSelectedAddress } = require('../../selectors')
const { getSelectedIdentity } = require('../../selectors')
const genAccountLink = require('../../../lib/account-link.js')
const QrView = require('../qr-code')
const EditableLabel = require('../editable-label')

View File

@ -92,7 +92,6 @@ ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password,
ExportPrivateKeyModal.prototype.render = function () {
const {
selectedIdentity,
network,
warning,
showAccountDetailModal,
hideModal,

View File

@ -220,7 +220,7 @@ Modal.prototype.render = function () {
const children = modal.contents
const modalStyle = modal[isMobileView() ? 'mobileModalStyle' : 'laptopModalStyle']
const contentStyle = modal.contentStyle || {};
const contentStyle = modal.contentStyle || {}
return h(FadeModal,
{

View File

@ -1,17 +1,88 @@
const Component = require('react').Component
const { Component } = require('react')
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const inherits = require('util').inherits
const connect = require('react-redux').connect
const { connect } = require('react-redux')
const actions = require('../../actions')
function mapStateToProps (state) {
return {
network: state.metamask.network,
address: state.metamask.selectedAddress,
class NewAccountModal extends Component {
constructor (props) {
super(props)
const { numberOfExistingAccounts = 0 } = props
const newAccountNumber = numberOfExistingAccounts + 1
this.state = {
newAccountName: `Account ${newAccountNumber}`,
}
}
render () {
const { newAccountName } = this.state
return h('div', [
h('div.new-account-modal-wrapper', {
}, [
h('div.new-account-modal-header', {}, [
'New Account',
]),
h('div.modal-close-x', {
onClick: this.props.hideModal,
}),
h('div.new-account-modal-content', {}, [
'Account Name',
]),
h('div.new-account-input-wrapper', {}, [
h('input.new-account-input', {
value: this.state.newAccountName,
placeholder: 'E.g. My new account',
onChange: event => this.setState({ newAccountName: event.target.value }),
}, []),
]),
h('div.new-account-modal-content.after-input', {}, [
'or',
]),
h('div.new-account-modal-content.after-input.pointer', {
onClick: () => {
this.props.hideModal()
this.props.showImportPage()
},
}, 'Import an account'),
h('div.new-account-modal-content.button', {}, [
h('button.btn-clear', {
onClick: () => this.props.createAccount(newAccountName),
}, [
'SAVE',
]),
]),
]),
])
}
}
function mapDispatchToProps (dispatch) {
NewAccountModal.propTypes = {
hideModal: PropTypes.func,
showImportPage: PropTypes.func,
createAccount: PropTypes.func,
numberOfExistingAccounts: PropTypes.number,
}
const mapStateToProps = state => {
const { metamask: { network, selectedAddress, identities = {} } } = state
const numberOfExistingAccounts = Object.keys(identities).length
return {
network,
address: selectedAddress,
numberOfExistingAccounts,
}
}
const mapDispatchToProps = dispatch => {
return {
toCoinbase: (address) => {
dispatch(actions.buyEth({ network: '1', address, amount: 0 }))
@ -32,60 +103,4 @@ function mapDispatchToProps (dispatch) {
}
}
inherits(NewAccountModal, Component)
function NewAccountModal () {
Component.call(this)
this.state = {
newAccountName: '',
}
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(NewAccountModal)
NewAccountModal.prototype.render = function () {
const { newAccountName } = this.state
return h('div', {}, [
h('div.new-account-modal-wrapper', {
}, [
h('div.new-account-modal-header', {}, [
'New Account',
]),
h('div.modal-close-x', {
onClick: this.props.hideModal,
}),
h('div.new-account-modal-content', {}, [
'Account Name',
]),
h('div.new-account-input-wrapper', {}, [
h('input.new-account-input', {
placeholder: 'E.g. My new account',
onChange: event => this.setState({ newAccountName: event.target.value }),
}, []),
]),
h('div.new-account-modal-content.after-input', {}, [
'or',
]),
h('div.new-account-modal-content.after-input.pointer', {
onClick: () => {
this.props.hideModal()
this.props.showImportPage()
},
}, 'Import an account'),
h('div.new-account-modal-content.button', {}, [
h('button.btn-clear', {
onClick: () => this.props.createAccount(newAccountName),
}, [
'SAVE',
]),
]),
]),
])
}

View File

@ -35,6 +35,6 @@ ShapeshiftDepositTxModal.prototype.render = function () {
}, [
h('div', {}, [
h(QrView, {key: 'qr', Qr}),
])
]),
])
}

View File

@ -1,6 +1,6 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const classnames = require('classnames');
const classnames = require('classnames')
const inherits = require('util').inherits
const NetworkDropdownIcon = require('./dropdowns/components/network-dropdown-icon')

View File

@ -10,9 +10,7 @@ const BN = ethUtil.BN
const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
const { conversionUtil } = require('../../conversion-util')
const MIN_GAS_PRICE_GWEI_BN = new BN(1)
const GWEI_FACTOR = new BN(1e9)
const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmDeployContract)
@ -166,7 +164,7 @@ ConfirmDeployContract.prototype.getGasFee = function () {
const gasBn = hexToBn(gas)
// Gas Price
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16)
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_HEX
const gasPriceBn = hexToBn(gasPrice)
const txFeeBn = gasBn.mul(gasPriceBn)

View File

@ -10,9 +10,7 @@ const BN = ethUtil.BN
const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
const { conversionUtil, addCurrencies } = require('../../conversion-util')
const MIN_GAS_PRICE_GWEI_BN = new BN(1)
const GWEI_FACTOR = new BN(1e9)
const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendEther)
@ -93,7 +91,7 @@ ConfirmSendEther.prototype.getGasFee = function () {
// const safeGasLimit = safeGasLimitBN.toString(10)
// Gas Price
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16)
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_HEX
const gasPriceBn = hexToBn(gasPrice)
const txFeeBn = gasBn.mul(gasPriceBn)

View File

@ -10,19 +10,15 @@ const clone = require('clone')
const Identicon = require('../identicon')
const ethUtil = require('ethereumjs-util')
const BN = ethUtil.BN
const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
const {
conversionUtil,
multiplyCurrencies,
addCurrencies,
} = require('../../conversion-util')
const MIN_GAS_PRICE_GWEI_BN = new BN(1)
const GWEI_FACTOR = new BN(1e9)
const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
const {
getSelectedTokenExchangeRate,
getTokenExchangeRate,
getSelectedAddress,
} = require('../../selectors')
@ -38,7 +34,6 @@ function mapStateToProps (state, ownProps) {
identities,
currentCurrency,
} = state.metamask
const accounts = state.metamask.accounts
const selectedAddress = getSelectedAddress(state)
const tokenExchangeRate = getTokenExchangeRate(state, symbol)
@ -99,7 +94,7 @@ ConfirmSendToken.prototype.getGasFee = function () {
const { decimals } = token
const gas = txParams.gas
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16)
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_HEX
const gasTotal = multiplyCurrencies(gas, gasPrice, {
multiplicandBase: 16,
multiplierBase: 16,
@ -149,7 +144,7 @@ ConfirmSendToken.prototype.getData = function () {
const { value } = params[0] || {}
const txMeta = this.gatherTxMeta()
const txParams = txMeta.txParams || {}
return {
from: {
address: txParams.from,
@ -247,7 +242,6 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () {
ConfirmSendToken.prototype.render = function () {
const { backToAccountDetail, selectedAddress } = this.props
const txMeta = this.gatherTxMeta()
const txParams = txMeta.txParams || {}
const {
from: {

View File

@ -144,16 +144,15 @@ SendTokenScreen.prototype.validate = function () {
}
SendTokenScreen.prototype.setErrorsFor = function (field) {
const { balance, selectedToken } = this.props
const { errors: previousErrors } = this.state
const {
isValid,
errors: newErrors
errors: newErrors,
} = this.validate()
const nextErrors = Object.assign({}, previousErrors, {
[field]: newErrors[field] || null
[field]: newErrors[field] || null,
})
if (!isValid) {
@ -167,7 +166,7 @@ SendTokenScreen.prototype.setErrorsFor = function (field) {
SendTokenScreen.prototype.clearErrorsFor = function (field) {
const { errors: previousErrors } = this.state
const nextErrors = Object.assign({}, previousErrors, {
[field]: null
[field]: null,
})
this.setState({
@ -429,7 +428,7 @@ SendTokenScreen.prototype.render = function () {
this.renderAmountInput(),
this.renderGasInput(),
this.renderMemoInput(),
warning && h('div.send-screen-input-wrapper--error', {},
warning && h('div.send-screen-input-wrapper--error', {},
h('div.send-screen-input-wrapper__error-message', [
warning,
])

View File

@ -68,4 +68,4 @@ AccountListItem.prototype.render = function () {
}, name),
])
}
}

View File

@ -1,7 +1,6 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const Identicon = require('../identicon')
const { conversionUtil, multiplyCurrencies } = require('../../conversion-util')
module.exports = CurrencyDisplay
@ -48,8 +47,6 @@ CurrencyDisplay.prototype.render = function () {
conversionRate,
primaryCurrency,
convertedCurrency,
convertedPrefix = '',
placeholder = '0',
readOnly = false,
inError = false,
value: initValue,
@ -74,7 +71,7 @@ CurrencyDisplay.prototype.render = function () {
conversionRate,
})
const inputSizeMultiplier = readOnly ? 1 : 1.2;
const inputSizeMultiplier = readOnly ? 1 : 1.2
return h('div', {
className,
@ -98,15 +95,13 @@ CurrencyDisplay.prototype.render = function () {
if (newValue === '') {
newValue = '0'
}
else if (newValue.match(/^0[1-9]$/)) {
} else if (newValue.match(/^0[1-9]$/)) {
newValue = newValue.match(/[1-9]/)[0]
}
if (newValue && !isValidInput(newValue)) {
event.preventDefault()
}
else {
} else {
validate(this.getAmount(newValue))
this.setState({ value: newValue })
}
@ -125,6 +120,6 @@ CurrencyDisplay.prototype.render = function () {
}, `${convertedValue} ${convertedCurrency.toUpperCase()}`),
])
}

View File

@ -30,8 +30,8 @@ EthFeeDisplay.prototype.render = function () {
color: '#5d5d5d',
fontSize: '16px',
fontFamily: 'DIN OT',
lineHeight: '22.4px'
}
lineHeight: '22.4px',
},
})
}

View File

@ -1,7 +1,6 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const Identicon = require('../identicon')
const AccountListItem = require('./account-list-item')
module.exports = FromDropdown
@ -36,13 +35,13 @@ FromDropdown.prototype.renderDropdown = function () {
h('div.send-v2__from-dropdown__list', {}, [
...accounts.map(account => h(AccountListItem, {
account,
account,
handleClick: () => {
onSelect(account)
closeDropdown()
},
},
icon: this.getListItemIcon(account, selectedAccount),
}))
})),
]),
@ -51,10 +50,8 @@ FromDropdown.prototype.renderDropdown = function () {
FromDropdown.prototype.render = function () {
const {
accounts,
selectedAccount,
openDropdown,
closeDropdown,
dropdownOpen,
} = this.props
@ -63,12 +60,12 @@ FromDropdown.prototype.render = function () {
h(AccountListItem, {
account: selectedAccount,
handleClick: openDropdown,
icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } })
icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } }),
}),
dropdownOpen && this.renderDropdown(),
])
}

View File

@ -23,21 +23,20 @@ GasFeeDisplay.prototype.render = function () {
gasTotal
? h(CurrencyDisplay, {
primaryCurrency: 'ETH',
primaryCurrency,
convertedCurrency,
value: gasTotal,
conversionRate,
convertedPrefix: '$',
readOnly: true,
})
: h('div.currency-display', 'Loading...')
,
: h('div.currency-display', 'Loading...'),
h('div.send-v2__sliders-icon-container', {
onClick,
}, [
h('i.fa.fa-sliders.send-v2__sliders-icon'),
])
]),
])
}

View File

@ -1,33 +1,33 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const Identicon = require('../identicon')
// const Component = require('react').Component
// const h = require('react-hyperscript')
// const inherits = require('util').inherits
// const Identicon = require('../identicon')
module.exports = MemoTextArea
// module.exports = MemoTextArea
inherits(MemoTextArea, Component)
function MemoTextArea () {
Component.call(this)
}
// inherits(MemoTextArea, Component)
// function MemoTextArea () {
// Component.call(this)
// }
MemoTextArea.prototype.render = function () {
const { memo, identities, onChange } = this.props
// MemoTextArea.prototype.render = function () {
// const { memo, identities, onChange } = this.props
return h('div.send-v2__memo-text-area', [
// return h('div.send-v2__memo-text-area', [
h('textarea.send-v2__memo-text-area__input', {
placeholder: 'Optional',
value: memo,
onChange,
// onBlur: () => {
// this.setErrorsFor('memo')
// },
onFocus: event => {
// this.clearErrorsFor('memo')
},
}),
// h('textarea.send-v2__memo-text-area__input', {
// placeholder: 'Optional',
// value: memo,
// onChange,
// // onBlur: () => {
// // this.setErrorsFor('memo')
// // },
// onFocus: event => {
// // this.clearErrorsFor('memo')
// },
// }),
])
}
// ])
// }

View File

@ -1,20 +1,18 @@
const Identicon = require('../identicon')
const { multiplyCurrencies } = require('../../conversion-util')
const ethUtil = require('ethereumjs-util')
const { conversionUtil, multiplyCurrencies } = require('../../conversion-util')
const MIN_GAS_PRICE_GWEI = '1'
const GWEI_FACTOR = '1e9'
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_PRICE_HEX = (100000000).toString(16)
const MIN_GAS_PRICE_DEC = '100000000'
const MIN_GAS_LIMIT_HEX = (21000).toString(16)
const MIN_GAS_LIMIT_DEC = 21000
const MIN_GAS_PRICE_GWEI = ethUtil.addHexPrefix(conversionUtil(MIN_GAS_PRICE_HEX, {
fromDenomination: 'WEI',
toDenomination: 'GWEI',
fromNumericBase: 'hex',
toNumericBase: 'hex',
}))
const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT_HEX, MIN_GAS_PRICE_HEX, {
toNumericBase: 'hex',
multiplicandBase: 16,

View File

@ -1,6 +1,6 @@
const { addCurrencies, conversionGreaterThan } = require('../../conversion-util')
function isBalanceSufficient({
function isBalanceSufficient ({
amount,
gasTotal,
balance,
@ -27,7 +27,6 @@ function isBalanceSufficient({
fromNumericBase: 'hex',
conversionRate: amountConversionRate,
fromCurrency: selectedToken || primaryCurrency,
conversionRate: amountConversionRate,
},
)
@ -36,4 +35,4 @@ function isBalanceSufficient({
module.exports = {
isBalanceSufficient,
}
}

View File

@ -3,17 +3,12 @@ const actions = require('../../actions')
const abi = require('ethereumjs-abi')
const SendEther = require('../../send-v2')
const { multiplyCurrencies } = require('../../conversion-util')
const {
accountsWithSendEtherInfoSelector,
getCurrentAccountWithSendEtherInfo,
conversionRateSelector,
getSelectedToken,
getSelectedTokenExchangeRate,
getSelectedAddress,
getGasPrice,
getGasLimit,
getAddressBook,
getSendFrom,
getCurrentCurrency,
@ -26,12 +21,11 @@ function mapStateToProps (state) {
const fromAccounts = accountsWithSendEtherInfoSelector(state)
const selectedAddress = getSelectedAddress(state)
const selectedToken = getSelectedToken(state)
const tokenExchangeRates = state.metamask.tokenExchangeRates
const conversionRate = conversionRateSelector(state)
let data;
let primaryCurrency;
let tokenToFiatRate;
let data
let primaryCurrency
let tokenToFiatRate
if (selectedToken) {
data = Array.prototype.map.call(
abi.rawEncode(['address', 'uint256'], [selectedAddress, '0x0']),
@ -76,6 +70,6 @@ function mapDispatchToProps (dispatch) {
updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)),
updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)),
goHome: () => dispatch(actions.goHome()),
clearSend: () => dispatch(actions.clearSend())
clearSend: () => dispatch(actions.clearSend()),
}
}

View File

@ -1,7 +1,6 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const Identicon = require('../identicon')
const AccountListItem = require('./account-list-item')
module.exports = ToAutoComplete
@ -23,7 +22,6 @@ ToAutoComplete.prototype.getListItemIcon = function (listItemAddress, toAddress)
ToAutoComplete.prototype.renderDropdown = function () {
const {
accounts,
closeDropdown,
onChange,
to,
@ -39,15 +37,15 @@ ToAutoComplete.prototype.renderDropdown = function () {
h('div.send-v2__from-dropdown__list', {}, [
...accountsToRender.map(account => h(AccountListItem, {
account,
account,
handleClick: () => {
onChange(account.address)
closeDropdown()
},
},
icon: this.getListItemIcon(account.address, to),
displayBalance: false,
displayAddress: true,
}))
})),
]),
@ -69,8 +67,7 @@ ToAutoComplete.prototype.handleInputEvent = function (event = {}, cb) {
this.setState({ accountsToRender: [] })
event.target && event.target.select()
closeDropdown()
}
else {
} else {
this.setState({ accountsToRender: matchingAccounts })
openDropdown()
}
@ -86,9 +83,6 @@ ToAutoComplete.prototype.componentDidUpdate = function (nextProps, nextState) {
ToAutoComplete.prototype.render = function () {
const {
to,
accounts,
openDropdown,
closeDropdown,
dropdownOpen,
onChange,
inError,
@ -98,13 +92,13 @@ ToAutoComplete.prototype.render = function () {
h('input.send-v2__to-autocomplete__input', {
placeholder: 'Recipient Address',
className: inError ? `send-v2__error-border` : '',
className: inError ? `send-v2__error-border` : '',
value: to,
onChange: event => onChange(event.target.value),
onFocus: event => this.handleInputEvent(event),
style: {
borderColor: inError ? 'red' : null,
}
},
}),
!to && h(`i.fa.fa-caret-down.fa-lg.send-v2__to-autocomplete__down-caret`, {

View File

@ -28,8 +28,8 @@ USDFeeDisplay.prototype.render = function () {
color: '#5d5d5d',
fontSize: '16px',
fontFamily: 'DIN OT',
lineHeight: '22.4px'
}
lineHeight: '22.4px',
},
})
}

View File

@ -4,9 +4,9 @@ const inherits = require('util').inherits
const Identicon = require('./identicon')
const connect = require('react-redux').connect
const ethUtil = require('ethereumjs-util')
const PendingTxDetails = require('./pending-personal-msg-details')
const classnames = require('classnames')
const AccountDropdownMini = require('./dropdowns/account-dropdown-mini')
const BinaryRenderer = require('./binary-renderer')
const actions = require('../actions')
const { conversionUtil } = require('../conversion-util')
@ -27,13 +27,13 @@ function mapStateToProps (state) {
requester: null,
requesterAddress: null,
accounts: accountsWithSendEtherInfoSelector(state),
conversionRate: conversionRateSelector(state)
conversionRate: conversionRateSelector(state),
}
}
function mapDispatchToProps (dispatch) {
return {
goHome: () => dispatch(actions.goHome())
goHome: () => dispatch(actions.goHome()),
}
}
@ -84,7 +84,7 @@ SignatureRequest.prototype.renderAccountDropdown = function () {
dropdownOpen: accountDropdownOpen,
openDropdown: () => this.setState({ accountDropdownOpen: true }),
closeDropdown: () => this.setState({ accountDropdownOpen: false }),
})
}),
])
}
@ -113,7 +113,7 @@ SignatureRequest.prototype.renderAccountInfo = function () {
return h('div.request-signature__account-info', [
this.renderAccountDropdown(),
this.renderRequestIcon(),
this.renderBalance(),
@ -128,18 +128,16 @@ SignatureRequest.prototype.renderRequestIcon = function () {
h(Identicon, {
diameter: 40,
address: requesterAddress,
})
}),
])
}
SignatureRequest.prototype.renderRequestInfo = function () {
const { requester } = this.props
return h('div.request-signature__request-info', [
h('div.request-signature__headline', [
`Your signature is being requested`,
])
]),
])
}
@ -163,11 +161,9 @@ SignatureRequest.prototype.renderBody = function () {
if (type === 'personal_sign') {
rows = [{ name: 'Message', value: this.msgHexToText(data) }]
}
else if (type === 'eth_signTypedData') {
} else if (type === 'eth_signTypedData') {
rows = data
}
else if (type === 'eth_sign') {
} else if (type === 'eth_sign') {
rows = [{ name: 'Message', value: data }]
notice = `Signing this message can have
dangerous side effects. Only sign messages from
@ -181,13 +177,18 @@ SignatureRequest.prototype.renderBody = function () {
this.renderRequestInfo(),
h('div.request-signature__notice', [notice]),
h('div.request-signature__notice', {
className: classnames({
'request-signature__notice': type === 'personal_sign' || type === 'eth_signTypedData',
'request-signature__warning': type === 'eth_sign',
}),
}, [notice]),
h('div.request-signature__rows', [
...rows.map(({ name, value }) => {
return h('div.request-signature__row', [
h('div.request-signature__row-title', [`${name}:`]),
h('div.request-signature__row-title', [`${name}:`]),
h('div.request-signature__row-value', value),
])
}),
@ -199,7 +200,6 @@ SignatureRequest.prototype.renderBody = function () {
SignatureRequest.prototype.renderFooter = function () {
const {
goHome,
signPersonalMessage,
signTypedMessage,
cancelPersonalMessage,
@ -216,12 +216,10 @@ SignatureRequest.prototype.renderFooter = function () {
if (type === 'personal_sign') {
cancel = cancelPersonalMessage
sign = signPersonalMessage
}
else if (type === 'eth_signTypedData') {
} else if (type === 'eth_signTypedData') {
cancel = cancelTypedMessage
sign = signTypedMessage
}
else if (type === 'eth_sign') {
} else if (type === 'eth_sign') {
cancel = cancelMessage
sign = signMessage
}

View File

@ -1,5 +1,6 @@
const { Component } = require('react')
const h = require('react-hyperscript')
const PropTypes = require('react').PropTypes
const classnames = require('classnames')
class TabBar extends Component {
@ -37,4 +38,10 @@ class TabBar extends Component {
}
}
TabBar.propTypes = {
defaultTab: PropTypes.string,
tabs: PropTypes.array,
tabSelected: PropTypes.func,
}
module.exports = TabBar

View File

@ -6,7 +6,7 @@ const Identicon = require('./identicon')
const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
const selectors = require('../selectors')
const actions = require('../actions')
const { conversionUtil } = require('../conversion-util')
const { conversionUtil, multiplyCurrencies } = require('../conversion-util')
const TokenMenuDropdown = require('./dropdowns/token-menu-dropdown.js')
@ -17,7 +17,7 @@ function mapStateToProps (state) {
selectedTokenAddress: state.metamask.selectedTokenAddress,
userAddress: selectors.getSelectedAddress(state),
tokenExchangeRates: state.metamask.tokenExchangeRates,
ethToUSDRate: state.metamask.conversionRate,
conversionRate: state.metamask.conversionRate,
sidebarOpen: state.appState.sidebarOpen,
}
}
@ -61,32 +61,36 @@ TokenCell.prototype.render = function () {
setSelectedToken,
selectedTokenAddress,
tokenExchangeRates,
ethToUSDRate,
conversionRate,
hideSidebar,
sidebarOpen,
currentCurrency,
// userAddress,
} = props
const pair = `${symbol.toLowerCase()}_eth`;
let currentTokenToEthRate;
let currentTokenInFiat;
let formattedUSD = ''
const pair = `${symbol.toLowerCase()}_eth`
let currentTokenToFiatRate
let currentTokenInFiat
let formattedFiat = ''
if (tokenExchangeRates[pair]) {
currentTokenToEthRate = tokenExchangeRates[pair].rate;
currentTokenToFiatRate = multiplyCurrencies(
tokenExchangeRates[pair].rate,
conversionRate
)
currentTokenInFiat = conversionUtil(string, {
fromNumericBase: 'dec',
fromCurrency: symbol,
toCurrency: 'USD',
toCurrency: currentCurrency.toUpperCase(),
numberOfDecimals: 2,
conversionRate: currentTokenToEthRate,
ethToUSDRate,
conversionRate: currentTokenToFiatRate,
})
formattedUSD = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`;
formattedFiat = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`
}
const showFiat = Boolean(currentTokenInFiat) && currentCurrency.toUpperCase() !== symbol
return (
h('div.token-list-item', {
className: `token-list-item ${selectedTokenAddress === address ? 'token-list-item--active' : ''}`,
@ -108,9 +112,9 @@ TokenCell.prototype.render = function () {
h('h.token-list-item__balance-wrapper', null, [
h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`),
h('div.token-list-item__fiat-amount', {
showFiat && h('div.token-list-item__fiat-amount', {
style: {},
}, formattedUSD),
}, formattedFiat),
]),
h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', {

View File

@ -3,7 +3,6 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits
const TokenTracker = require('eth-token-tracker')
const TokenCell = require('./token-cell.js')
const normalizeAddress = require('eth-sig-util').normalize
const connect = require('react-redux').connect
const selectors = require('../selectors')
@ -38,6 +37,7 @@ function TokenList () {
}
TokenList.prototype.render = function () {
const { userAddress } = this.props
const state = this.state
const { tokens, isLoading, error } = state
@ -162,15 +162,15 @@ TokenList.prototype.componentWillUnmount = function () {
this.tracker.stop()
}
function uniqueMergeTokens (tokensA, tokensB = []) {
const uniqueAddresses = []
const result = []
tokensA.concat(tokensB).forEach((token) => {
const normal = normalizeAddress(token.address)
if (!uniqueAddresses.includes(normal)) {
uniqueAddresses.push(normal)
result.push(token)
}
})
return result
}
// function uniqueMergeTokens (tokensA, tokensB = []) {
// const uniqueAddresses = []
// const result = []
// tokensA.concat(tokensB).forEach((token) => {
// const normal = normalizeAddress(token.address)
// if (!uniqueAddresses.includes(normal)) {
// uniqueAddresses.push(normal)
// result.push(token)
// }
// })
// return result
// }

View File

@ -142,7 +142,7 @@ function formatDate (date) {
}
function renderErrorOrWarning (transaction) {
const { status, err, warning } = transaction
const { status } = transaction
// show rejected
if (status === 'rejected') {
@ -151,31 +151,31 @@ function renderErrorOrWarning (transaction) {
if (transaction.err || transaction.warning) {
const { err, warning = {} } = transaction
const errFirst = !!((err && warning) || err)
const message = errFirst ? err.message : warning.message
errFirst ? err.message : warning.message
// show error
if (err) {
const message = err.message || ''
return (
h(Tooltip, {
title: message,
position: 'bottom',
}, [
h(`span.error`, ` (Failed)`),
])
)
}
// show error
if (err) {
const message = err.message || ''
return (
h(Tooltip, {
title: message,
position: 'bottom',
}, [
h(`span.error`, ` (Failed)`),
])
)
}
// show warning
if (warning) {
const message = warning.message
return h(Tooltip, {
title: message,
position: 'bottom',
}, [
h(`span.warning`, ` (Warning)`),
])
// show warning
if (warning) {
const message = warning.message
return h(Tooltip, {
title: message,
position: 'bottom',
}, [
h(`span.warning`, ` (Warning)`),
])
}
}
}

View File

@ -6,10 +6,10 @@ const classnames = require('classnames')
const abi = require('human-standard-token-abi')
const abiDecoder = require('abi-decoder')
abiDecoder.addABI(abi)
const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
const Identicon = require('./identicon')
const contractMap = require('eth-contract-metadata')
const { conversionUtil } = require('../conversion-util')
const { conversionUtil, multiplyCurrencies } = require('../conversion-util')
const { getCurrentCurrency } = require('../selectors')
@ -19,12 +19,31 @@ function mapStateToProps (state) {
return {
tokens: state.metamask.tokens,
currentCurrency: getCurrentCurrency(state),
tokenExchangeRates: state.metamask.tokenExchangeRates,
}
}
inherits(TxListItem, Component)
function TxListItem () {
Component.call(this)
this.state = {
total: null,
fiatTotal: null,
}
}
TxListItem.prototype.componentDidMount = async function () {
const { txParams = {} } = this.props
const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
const { name: txDataName } = decodedData || {}
const { total, fiatTotal } = txDataName === 'transfer'
? await this.getSendTokenTotal()
: this.getSendEtherTotal()
this.setState({ total, fiatTotal })
}
TxListItem.prototype.getAddressText = function () {
@ -84,23 +103,67 @@ TxListItem.prototype.getSendEtherTotal = function () {
}
}
TxListItem.prototype.getSendTokenTotal = function () {
TxListItem.prototype.getTokenInfo = async function () {
const { txParams = {}, tokenInfoGetter, tokens } = this.props
const toAddress = txParams.to
let decimals
let symbol
({ decimals, symbol } = tokens.filter(({ address }) => address === toAddress)[0] || {})
if (!decimals && !symbol) {
({ decimals, symbol } = contractMap[toAddress] || {})
}
if (!decimals && !symbol) {
({ decimals, symbol } = await tokenInfoGetter(toAddress))
}
return { decimals, symbol }
}
TxListItem.prototype.getSendTokenTotal = async function () {
const {
txParams = {},
tokens,
conversionRate,
tokenExchangeRates,
currentCurrency,
} = this.props
const toAddress = txParams.to
const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
const { params = [] } = decodedData || {}
const { value } = params[1] || {}
const { decimals, symbol } = tokens.filter(({ address }) => address === toAddress)[0] || {}
const { decimals, symbol } = await this.getTokenInfo()
const multiplier = Math.pow(10, Number(decimals || 0))
const total = Number(value / multiplier)
const pair = symbol && `${symbol.toLowerCase()}_eth`
let tokenToFiatRate
let totalInFiat
if (tokenExchangeRates[pair]) {
tokenToFiatRate = multiplyCurrencies(
tokenExchangeRates[pair].rate,
conversionRate
)
totalInFiat = conversionUtil(total, {
fromNumericBase: 'dec',
toNumericBase: 'dec',
fromCurrency: symbol,
toCurrency: currentCurrency,
numberOfDecimals: 2,
conversionRate: tokenToFiatRate,
})
}
const showFiat = Boolean(totalInFiat) && currentCurrency.toUpperCase() !== symbol
return {
total: `${total} ${symbol}`,
fiatTotal: showFiat && `${totalInFiat} ${currentCurrency.toUpperCase()}`,
}
}
@ -112,15 +175,8 @@ TxListItem.prototype.render = function () {
dateString,
address,
className,
txParams = {},
} = this.props
const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
const { name: txDataName } = decodedData || {}
const { total, fiatTotal } = txDataName === 'transfer'
? this.getSendTokenTotal()
: this.getSendEtherTotal()
const { total, fiatTotal } = this.state
return h(`div${className || ''}`, {
key: transActionId,
@ -182,10 +238,10 @@ TxListItem.prototype.render = function () {
}),
}, total),
h('span.tx-list-fiat-value', fiatTotal),
fiatTotal && h('span.tx-list-fiat-value', fiatTotal),
]),
]),
]) // holding on icon from design
]), // holding on icon from design
])
}

View File

@ -6,9 +6,10 @@ const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
const selectors = require('../selectors')
const TxListItem = require('./tx-list-item')
const ShiftListItem = require('./shift-list-item')
const { formatBalance, formatDate } = require('../util')
const { formatDate } = require('../util')
const { showConfTxPage } = require('../actions')
const classnames = require('classnames')
const { tokenInfoGetter } = require('../token-util')
module.exports = connect(mapStateToProps, mapDispatchToProps)(TxList)
@ -21,7 +22,7 @@ function mapStateToProps (state) {
function mapDispatchToProps (dispatch) {
return {
showConfTxPage: ({ id }) => dispatch(showConfTxPage({ id }))
showConfTxPage: ({ id }) => dispatch(showConfTxPage({ id })),
}
}
@ -30,10 +31,11 @@ function TxList () {
Component.call(this)
}
TxList.prototype.componentWillMount = function () {
this.tokenInfoGetter = tokenInfoGetter()
}
TxList.prototype.render = function () {
const { txsToRender, showConfTxPage } = this.props
return h('div.flex-column.tx-list-container', {}, [
h('div.flex-row.tx-list-header-wrapper', [
@ -93,15 +95,15 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa
txParams: transaction.txParams,
transactionStatus,
transActionId,
key: transActionId,
dateString,
address,
transactionAmount,
transactionHash,
conversionRate,
tokenInfoGetter: this.tokenInfoGetter,
}
const isUnapproved = transactionStatus === 'unapproved';
const isUnapproved = transactionStatus === 'unapproved'
if (isUnapproved) {
opts.onClick = () => showConfTxPage({id: transActionId})

View File

@ -114,14 +114,14 @@ ConfirmTxScreen.prototype.render = function () {
function currentTxView (opts) {
log.info('rendering current tx view')
const { txData } = opts
const { txParams, msgParams, type } = txData
const { txParams, msgParams } = txData
if (txParams) {
log.debug('txParams detected, rendering pending tx')
return h(PendingTx, opts)
} else if (msgParams) {
log.debug('msgParams detected, rendering pending msg')
return h(SignatureRequest, opts)
// if (type === 'eth_sign') {

View File

@ -13,7 +13,6 @@
* @param {string} [options.fromDenomination = 'WEI'] The denomination of the passed value
* @param {number} [options.numberOfDecimals] The desired number of in the result
* @param {number} [options.conversionRate] The rate to use to make the fromCurrency -> toCurrency conversion
* @param {number} [options.ethToUSDRate] If present, a second conversion - at ethToUSDRate - happens after conversionRate is applied.
* @returns {(number | string | BN)}
*
* The utility passes value along with the options as a single object to the `converter` function.
@ -23,6 +22,8 @@
*/
const BigNumber = require('bignumber.js')
const ethUtil = require('ethereumjs-util')
const BN = ethUtil.BN
const R = require('ramda')
const { stripHexPrefix } = require('ethereumjs-util')
@ -38,6 +39,7 @@ const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber('1000000000')
const convert = R.invoker(1, 'times')
const round = R.invoker(2, 'round')(R.__, BigNumber.ROUND_DOWN)
const invertConversionRate = conversionRate => () => new BigNumber(1.0).div(conversionRate)
const decToBigNumberViaString = n => R.pipe(String, toBigNumber['dec'])
// Setter Maps
const toBigNumber = {
@ -51,7 +53,7 @@ const toNormalizedDenomination = {
}
const toSpecifiedDenomination = {
WEI: bigNumber => bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).round(),
GWEI: bigNumber => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).round(),
GWEI: bigNumber => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).round(1),
}
const baseChange = {
hex: n => n.toString(16),
@ -95,16 +97,16 @@ const whenPropApplySetterMap = (prop, setterMap) => whenPredSetWithPropAndSetter
// Conversion utility function
const converter = R.pipe(
whenPredSetCRWithPropAndSetter(R.prop('conversionRate'), 'conversionRate', decToBigNumberViaString),
whenPredSetCRWithPropAndSetter(R.prop('invertConversionRate'), 'conversionRate', invertConversionRate),
whenPropApplySetterMap('fromNumericBase', toBigNumber),
whenPropApplySetterMap('fromDenomination', toNormalizedDenomination),
whenPredSetWithPropAndSetter(fromAndToCurrencyPropsNotEqual, 'conversionRate', convert),
whenPropApplySetterMap('toDenomination', toSpecifiedDenomination),
whenPredSetWithPropAndSetter(R.prop('ethToUSDRate'), 'ethToUSDRate', convert),
whenPredSetWithPropAndSetter(R.prop('numberOfDecimals'), 'numberOfDecimals', round),
whenPropApplySetterMap('toNumericBase', baseChange),
R.view(R.lensProp('value'))
);
)
const conversionUtil = (value, {
fromCurrency = null,
@ -115,7 +117,6 @@ const conversionUtil = (value, {
toDenomination,
numberOfDecimals,
conversionRate,
ethToUSDRate,
invertConversionRate,
}) => converter({
fromCurrency,
@ -126,18 +127,17 @@ const conversionUtil = (value, {
toDenomination,
numberOfDecimals,
conversionRate,
ethToUSDRate,
invertConversionRate,
value: value || '0',
});
})
const addCurrencies = (a, b, options = {}) => {
const {
aBase,
bBase,
...conversionOptions,
...conversionOptions
} = options
const value = (new BigNumber(a, aBase)).add(b, bBase);
const value = (new BigNumber(a, aBase)).add(b, bBase)
return converter({
value,
@ -149,10 +149,13 @@ const multiplyCurrencies = (a, b, options = {}) => {
const {
multiplicandBase,
multiplierBase,
...conversionOptions,
...conversionOptions
} = options
const value = (new BigNumber(a, multiplicandBase)).times(b, multiplierBase);
const bigNumberA = new BigNumber(String(a), multiplicandBase)
const bigNumberB = new BigNumber(String(b), multiplierBase)
const value = bigNumberA.times(bigNumberB)
return converter({
value,
@ -162,16 +165,41 @@ const multiplyCurrencies = (a, b, options = {}) => {
const conversionGreaterThan = (
{ ...firstProps },
{ ...secondProps },
{ ...secondProps },
) => {
const firstValue = converter({ ...firstProps })
const secondValue = converter({ ...secondProps })
return firstValue.gt(secondValue)
}
const conversionGTE = (
{ ...firstProps },
{ ...secondProps },
) => {
const firstValue = converter({ ...firstProps })
const secondValue = converter({ ...secondProps })
return firstValue.greaterThanOrEqualTo(secondValue)
}
const conversionLTE = (
{ ...firstProps },
{ ...secondProps },
) => {
const firstValue = converter({ ...firstProps })
const secondValue = converter({ ...secondProps })
return firstValue.lessThanOrEqualTo(secondValue)
}
const toNegative = (n, options = {}) => {
return multiplyCurrencies(n, -1, options)
}
module.exports = {
conversionUtil,
addCurrencies,
multiplyCurrencies,
conversionGreaterThan,
}
conversionGTE,
conversionLTE,
toNegative,
}

View File

@ -15,6 +15,7 @@
width: 250px;
font-size: 14px;
text-align: center;
border: 1px solid $alto;
&--error {
border: 1px solid $monzo;

View File

@ -131,8 +131,8 @@
margin-top: 20px;
}
&__notice {
color: #9B9B9B;
&__notice,
&__warning {
font-family: "Avenir Next";
font-size: 14px;
line-height: 19px;
@ -142,6 +142,14 @@
width: 100%;
}
&__notice {
color: $dusty-gray;
}
&__warning {
color: $crimson;
}
&__rows {
height: 100%;
overflow-y: scroll;

View File

@ -37,11 +37,7 @@ MainContainer.prototype.render = function () {
break
case 'config':
log.debug('rendering config screen from unlock screen.')
contents = {
component: Settings,
key: 'config',
}
break
return h(Settings, {key: 'config'})
default:
log.debug('rendering locked screen')
contents = {

View File

@ -44,7 +44,7 @@ function reduceApp (state, action) {
},
previousModalState: {
name: null,
}
},
},
sidebarOpen: false,
networkDropdownOpen: false,
@ -100,7 +100,7 @@ function reduceApp (state, action) {
state.appState.modal,
{ open: false },
{ modalState: { name: null } },
{ previousModalState: appState.modal.modalState},
{ previousModalState: appState.modal.modalState},
),
})

View File

@ -235,7 +235,7 @@ function reduceMetamask (state, action) {
errors: {
...metamaskState.send.errors,
...action.value,
}
},
},
})

View File

@ -1,8 +1,6 @@
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')
@ -13,12 +11,9 @@ const GasFeeDisplay = require('./components/send/gas-fee-display-v2')
const { MIN_GAS_TOTAL } = require('./components/send/send-constants')
const { showModal } = require('./actions')
const {
multiplyCurrencies,
conversionGreaterThan,
addCurrencies,
} = require('./conversion-util')
const {
isBalanceSufficient,
@ -99,7 +94,7 @@ SendTransactionScreen.prototype.renderHeaderIcon = function () {
diameter: 40,
address: selectedToken.address,
})
: h('img.send-v2__send-header-icon', { src: '../images/eth_logo.svg' })
: h('img.send-v2__send-header-icon', { src: '../images/eth_logo.svg' }),
])
}
@ -140,12 +135,12 @@ SendTransactionScreen.prototype.renderHeader = function () {
])
}
SendTransactionScreen.prototype.renderErrorMessage = function(errorType) {
SendTransactionScreen.prototype.renderErrorMessage = function (errorType) {
const { errors } = this.props
const errorMessage = errors[errorType];
const errorMessage = errors[errorType]
return errorMessage
? h('div.send-v2__error', [ errorMessage ] )
? h('div.send-v2__error', [ errorMessage ])
: null
}
@ -154,7 +149,6 @@ SendTransactionScreen.prototype.renderFromRow = function () {
from,
fromAccounts,
conversionRate,
setSelectedAddress,
updateSendFrom,
} = this.props
@ -243,7 +237,6 @@ SendTransactionScreen.prototype.validateAmount = function (value) {
amountConversionRate,
conversionRate,
primaryCurrency,
toCurrency,
selectedToken,
gasTotal,
} = this.props
@ -440,7 +433,6 @@ SendTransactionScreen.prototype.onSubmit = function (event) {
signTokenTx,
signTx,
selectedToken,
toAccounts,
clearSend,
errors: { amount: amountError, to: toError },
} = this.props

File diff suppressed because it is too large Load Diff

36
ui/app/token-util.js Normal file
View File

@ -0,0 +1,36 @@
const abi = require('human-standard-token-abi')
const Eth = require('ethjs-query')
const EthContract = require('ethjs-contract')
const tokenInfoGetter = function () {
if (typeof global.ethereumProvider === 'undefined') return
const eth = new Eth(global.ethereumProvider)
const contract = new EthContract(eth)
const TokenContract = contract(abi)
const tokens = {}
return async (address) => {
if (tokens[address]) {
return tokens[address]
}
const contract = TokenContract.at(address)
const result = await Promise.all([
contract.symbol(),
contract.decimals(),
])
const [ symbol = [], decimals = [] ] = result
tokens[address] = { symbol: symbol[0], decimals: decimals[0] }
return tokens[address]
}
}
module.exports = {
tokenInfoGetter,
}