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

Fix naming, add eth.getCode check for actions, fix translations for statuses

This commit is contained in:
Alexander Tseung 2018-08-23 16:44:38 -07:00
parent 2d76ee754b
commit 342522c6cf
24 changed files with 85 additions and 97 deletions

View File

@ -705,6 +705,9 @@
"pasteSeed": { "pasteSeed": {
"message": "Paste your seed phrase here!" "message": "Paste your seed phrase here!"
}, },
"pending": {
"message": "pending"
},
"personalAddressDetected": { "personalAddressDetected": {
"message": "Personal address detected. Input the token contract address." "message": "Personal address detected. Input the token contract address."
}, },

File diff suppressed because one or more lines are too long

View File

@ -4,8 +4,7 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits const inherits = require('util').inherits
const TokenBalance = require('./token-balance') const TokenBalance = require('./token-balance')
const Identicon = require('./identicon') const Identicon = require('./identicon')
const currencyFormatter = require('currency-formatter') import CurrencyDisplay from './currency-display'
const currencies = require('currency-formatter/currencies')
const { formatBalance, generateBalanceObject } = require('../util') const { formatBalance, generateBalanceObject } = require('../util')
@ -80,38 +79,12 @@ BalanceComponent.prototype.renderBalance = function () {
style: {}, style: {},
}, this.getTokenBalance(formattedBalance, shorten)), }, this.getTokenBalance(formattedBalance, shorten)),
showFiat ? this.renderFiatValue(formattedBalance) : null, showFiat && h(CurrencyDisplay, {
value: balanceValue,
}),
]) ])
} }
BalanceComponent.prototype.renderFiatValue = function (formattedBalance) {
const { conversionRate, currentCurrency } = this.props
const fiatDisplayNumber = this.getFiatDisplayNumber(formattedBalance, conversionRate)
const fiatPrefix = currentCurrency === 'USD' ? '$' : ''
return this.renderFiatAmount(fiatDisplayNumber, currentCurrency, fiatPrefix)
}
BalanceComponent.prototype.renderFiatAmount = function (fiatDisplayNumber, fiatSuffix, fiatPrefix) {
const shouldNotRenderFiat = fiatDisplayNumber === 'N/A' || Number(fiatDisplayNumber) === 0
if (shouldNotRenderFiat) return null
const upperCaseFiatSuffix = fiatSuffix.toUpperCase()
const display = currencies.find(currency => currency.code === upperCaseFiatSuffix)
? currencyFormatter.format(Number(fiatDisplayNumber), {
code: upperCaseFiatSuffix,
})
: `${fiatPrefix}${fiatDisplayNumber} ${upperCaseFiatSuffix}`
return h('div.fiat-amount', {
style: {},
}, display)
}
BalanceComponent.prototype.getTokenBalance = function (formattedBalance, shorten) { BalanceComponent.prototype.getTokenBalance = function (formattedBalance, shorten) {
const balanceObj = generateBalanceObject(formattedBalance, shorten ? 1 : 3) const balanceObj = generateBalanceObject(formattedBalance, shorten ? 1 : 3)

View File

@ -1,11 +1,13 @@
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { ETH } from '../../constants/common'
export default class CurrencyDisplay extends PureComponent { export default class CurrencyDisplay extends PureComponent {
static propTypes = { static propTypes = {
className: PropTypes.string, className: PropTypes.string,
displayValue: PropTypes.string, displayValue: PropTypes.string,
prefix: PropTypes.string, prefix: PropTypes.string,
currency: PropTypes.oneOf([ETH]),
} }
render () { render () {

View File

@ -1,13 +1,12 @@
import { connect } from 'react-redux' import { connect } from 'react-redux'
import CurrencyDisplay from './currency-display.component' import CurrencyDisplay from './currency-display.component'
import { getValueFromWeiHex, formatCurrency } from '../../helpers/confirm-transaction/util' import { getValueFromWeiHex, formatCurrency } from '../../helpers/confirm-transaction/util'
import { ETH } from '../../constants/common'
const mapStateToProps = (state, ownProps) => { const mapStateToProps = (state, ownProps) => {
const { value, numberOfDecimals = 2, currency } = ownProps const { value, numberOfDecimals = 2, currency } = ownProps
const { metamask: { currentCurrency, conversionRate } } = state const { metamask: { currentCurrency, conversionRate } } = state
const toCurrency = currency === ETH ? ETH : currentCurrency const toCurrency = currency || currentCurrency
const convertedValue = getValueFromWeiHex({ value, toCurrency, conversionRate, numberOfDecimals }) const convertedValue = getValueFromWeiHex({ value, toCurrency, conversionRate, numberOfDecimals })
const formattedValue = formatCurrency(convertedValue, toCurrency) const formattedValue = formatCurrency(convertedValue, toCurrency)
const displayValue = `${formattedValue} ${toCurrency.toUpperCase()}` const displayValue = `${formattedValue} ${toCurrency.toUpperCase()}`

View File

@ -24,9 +24,9 @@
@import './tabs/index'; @import './tabs/index';
@import './token-view/index'; @import './transaction-view/index';
@import './token-view-balance/index'; @import './transaction-view-balance/index';
@import './transaction-list/index'; @import './transaction-list/index';

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import Media from 'react-media' import Media from 'react-media'
import { Redirect } from 'react-router-dom' import { Redirect } from 'react-router-dom'
import WalletView from '../../wallet-view' import WalletView from '../../wallet-view'
import TokenView from '../../token-view' import TransactionView from '../../transaction-view'
import { import {
INITIALIZE_BACKUP_PHRASE_ROUTE, INITIALIZE_BACKUP_PHRASE_ROUTE,
RESTORE_VAULT_ROUTE, RESTORE_VAULT_ROUTE,
@ -58,7 +58,7 @@ export default class Home extends PureComponent {
query="(min-width: 576px)" query="(min-width: 576px)"
render={() => <WalletView />} render={() => <WalletView />}
/> />
<TokenView /> <TransactionView />
</div> </div>
</div> </div>
) )

View File

@ -4,7 +4,7 @@ import CurrencyDisplay from '../currency-display/currency-display.component'
import { getTokenData } from '../../helpers/transactions.util' import { getTokenData } from '../../helpers/transactions.util'
import { calcTokenAmount } from '../../token-util' import { calcTokenAmount } from '../../token-util'
export default class TokenCurrencyDisplayContainer extends PureComponent { export default class TokenCurrencyDisplay extends PureComponent {
static propTypes = { static propTypes = {
transactionData: PropTypes.string, transactionData: PropTypes.string,
token: PropTypes.object, token: PropTypes.object,

View File

@ -1 +0,0 @@
export { default } from './token-view-balance.container'

View File

@ -1 +0,0 @@
export { default } from './token-view.component'

View File

@ -25,7 +25,7 @@ export default class TransactionAction extends PureComponent {
this.getTransactionAction() this.getTransactionAction()
} }
getTransactionAction () { async getTransactionAction () {
const { transactionAction } = this.state const { transactionAction } = this.state
const { transaction, methodData } = this.props const { transaction, methodData } = this.props
const { data, done } = methodData const { data, done } = methodData
@ -34,18 +34,18 @@ export default class TransactionAction extends PureComponent {
return return
} }
const actionKey = getTransactionActionKey(transaction, data) const actionKey = await getTransactionActionKey(transaction, data)
const action = actionKey && this.context.tOrDefault(actionKey) const action = actionKey && this.context.tOrDefault(actionKey)
this.setState({ transactionAction: action }) this.setState({ transactionAction: action })
} }
render () { render () {
const { className, methodData: { isFetching } } = this.props const { className, methodData: { done } } = this.props
const { transactionAction } = this.state const { transactionAction } = this.state
return ( return (
<div className={className}> <div className={className}>
{ (!isFetching && transactionAction) || '--' } { (done && transactionAction) || '--' }
</div> </div>
) )
} }

View File

@ -127,13 +127,13 @@ export default class TransactionListItem extends PureComponent {
</div> </div>
<TransactionStatus <TransactionStatus
className="transaction-list-item__status" className="transaction-list-item__status"
status={transaction.status} statusKey={transaction.status}
/> />
{ this.renderPrimaryCurrency() } { this.renderPrimaryCurrency() }
{ this.renderSecondaryCurrency() } { this.renderSecondaryCurrency() }
</div> </div>
{ {
showRetry && !methodData.isFetching && ( showRetry && methodData.done && (
<div <div
className="transaction-list-item__retry" className="transaction-list-item__retry"
onClick={this.handleRetryClick} onClick={this.handleRetryClick}

View File

@ -1,15 +1,16 @@
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import classnames from 'classnames' import classnames from 'classnames'
import {
const UNAPPROVED_STATUS = 'unapproved' UNAPPROVED_STATUS,
const REJECTED_STATUS = 'rejected' REJECTED_STATUS,
const APPROVED_STATUS = 'approved' APPROVED_STATUS,
const SIGNED_STATUS = 'signed' SIGNED_STATUS,
const SUBMITTED_STATUS = 'submitted' SUBMITTED_STATUS,
const CONFIRMED_STATUS = 'confirmed' CONFIRMED_STATUS,
const FAILED_STATUS = 'failed' FAILED_STATUS,
const DROPPED_STATUS = 'dropped' DROPPED_STATUS,
} from '../../constants/transactions'
const statusToClassNameHash = { const statusToClassNameHash = {
[UNAPPROVED_STATUS]: 'transaction-status--unapproved', [UNAPPROVED_STATUS]: 'transaction-status--unapproved',
@ -28,17 +29,22 @@ const statusToTextHash = {
} }
export default class TransactionStatus extends PureComponent { export default class TransactionStatus extends PureComponent {
static contextTypes = {
t: PropTypes.func,
}
static propTypes = { static propTypes = {
status: PropTypes.string, statusKey: PropTypes.string,
className: PropTypes.string, className: PropTypes.string,
} }
render () { render () {
const { className, status } = this.props const { className, statusKey } = this.props
const statusText = this.context.t(statusToTextHash[statusKey] || statusKey)
return ( return (
<div className={classnames('transaction-status', className, statusToClassNameHash[status])}> <div className={classnames('transaction-status', className, statusToClassNameHash[statusKey])}>
{ statusToTextHash[status] || status } { statusText }
</div> </div>
) )
} }

View File

@ -0,0 +1 @@
export { default } from './transaction-view-balance.container'

View File

@ -1,4 +1,4 @@
.token-view-balance { .transaction-view-balance {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;

View File

@ -5,7 +5,7 @@ import sinon from 'sinon'
import TokenBalance from '../../token-balance' import TokenBalance from '../../token-balance'
import CurrencyDisplay from '../../currency-display' import CurrencyDisplay from '../../currency-display'
import { SEND_ROUTE } from '../../../routes' import { SEND_ROUTE } from '../../../routes'
import TokenViewBalance from '../token-view-balance.component' import TransactionViewBalance from '../transaction-view-balance.component'
const propsMethodSpies = { const propsMethodSpies = {
showDepositModal: sinon.spy(), showDepositModal: sinon.spy(),
@ -17,14 +17,14 @@ const historySpies = {
const t = (str1, str2) => str2 ? str1 + str2 : str1 const t = (str1, str2) => str2 ? str1 + str2 : str1
describe('TokenViewBalance Component', () => { describe('TransactionViewBalance Component', () => {
afterEach(() => { afterEach(() => {
propsMethodSpies.showDepositModal.resetHistory() propsMethodSpies.showDepositModal.resetHistory()
historySpies.push.resetHistory() historySpies.push.resetHistory()
}) })
it('should render ETH balance properly', () => { it('should render ETH balance properly', () => {
const wrapper = shallow(<TokenViewBalance const wrapper = shallow(<TransactionViewBalance
showDepositModal={propsMethodSpies.showDepositModal} showDepositModal={propsMethodSpies.showDepositModal}
history={historySpies} history={historySpies}
network="3" network="3"
@ -33,11 +33,11 @@ describe('TokenViewBalance Component', () => {
currentCurrency="usd" currentCurrency="usd"
/>, { context: { t } }) />, { context: { t } })
assert.equal(wrapper.find('.token-view-balance').length, 1) assert.equal(wrapper.find('.transaction-view-balance').length, 1)
assert.equal(wrapper.find('.token-view-balance__button').length, 2) assert.equal(wrapper.find('.transaction-view-balance__button').length, 2)
assert.equal(wrapper.find(CurrencyDisplay).length, 2) assert.equal(wrapper.find(CurrencyDisplay).length, 2)
const buttons = wrapper.find('.token-view-balance__buttons') const buttons = wrapper.find('.transaction-view-balance__buttons')
assert.equal(propsMethodSpies.showDepositModal.callCount, 0) assert.equal(propsMethodSpies.showDepositModal.callCount, 0)
buttons.childAt(0).simulate('click') buttons.childAt(0).simulate('click')
assert.equal(propsMethodSpies.showDepositModal.callCount, 1) assert.equal(propsMethodSpies.showDepositModal.callCount, 1)
@ -54,7 +54,7 @@ describe('TokenViewBalance Component', () => {
symbol: 'ABC', symbol: 'ABC',
} }
const wrapper = shallow(<TokenViewBalance const wrapper = shallow(<TransactionViewBalance
showDepositModal={propsMethodSpies.showDepositModal} showDepositModal={propsMethodSpies.showDepositModal}
history={historySpies} history={historySpies}
network="3" network="3"
@ -64,8 +64,8 @@ describe('TokenViewBalance Component', () => {
selectedToken={token} selectedToken={token}
/>, { context: { t } }) />, { context: { t } })
assert.equal(wrapper.find('.token-view-balance').length, 1) assert.equal(wrapper.find('.transaction-view-balance').length, 1)
assert.equal(wrapper.find('.token-view-balance__button').length, 1) assert.equal(wrapper.find('.transaction-view-balance__button').length, 1)
assert.equal(wrapper.find(TokenBalance).length, 1) assert.equal(wrapper.find(TokenBalance).length, 1)
}) })
}) })

View File

@ -7,7 +7,7 @@ import CurrencyDisplay from '../currency-display'
import { SEND_ROUTE } from '../../routes' import { SEND_ROUTE } from '../../routes'
import { ETH } from '../../constants/common' import { ETH } from '../../constants/common'
export default class TokenViewBalance extends PureComponent { export default class TransactionViewBalance extends PureComponent {
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
} }
@ -28,18 +28,18 @@ export default class TokenViewBalance extends PureComponent {
<TokenBalance <TokenBalance
token={selectedToken} token={selectedToken}
withSymbol withSymbol
className="token-view-balance__token-balance" className="transaction-view-balance__token-balance"
/> />
) : ( ) : (
<div className="token-view-balance__balance"> <div className="transaction-view-balance__balance">
<CurrencyDisplay <CurrencyDisplay
className="token-view-balance__primary-balance" className="transaction-view-balance__primary-balance"
value={balance} value={balance}
currency={ETH} currency={ETH}
numberOfDecimals={3} numberOfDecimals={3}
/> />
<CurrencyDisplay <CurrencyDisplay
className="token-view-balance__secondary-balance" className="transaction-view-balance__secondary-balance"
value={balance} value={balance}
/> />
</div> </div>
@ -51,12 +51,12 @@ export default class TokenViewBalance extends PureComponent {
const { selectedToken, showDepositModal, history } = this.props const { selectedToken, showDepositModal, history } = this.props
return ( return (
<div className="token-view-balance__buttons"> <div className="transaction-view-balance__buttons">
{ {
!selectedToken && ( !selectedToken && (
<Button <Button
type="primary" type="primary"
className="token-view-balance__button" className="transaction-view-balance__button"
onClick={() => showDepositModal()} onClick={() => showDepositModal()}
> >
{ t('deposit') } { t('deposit') }
@ -65,7 +65,7 @@ export default class TokenViewBalance extends PureComponent {
} }
<Button <Button
type="primary" type="primary"
className="token-view-balance__button" className="transaction-view-balance__button"
onClick={() => history.push(SEND_ROUTE)} onClick={() => history.push(SEND_ROUTE)}
> >
{ t('send') } { t('send') }
@ -78,8 +78,8 @@ export default class TokenViewBalance extends PureComponent {
const { network, selectedToken } = this.props const { network, selectedToken } = this.props
return ( return (
<div className="token-view-balance"> <div className="transaction-view-balance">
<div className="token-view-balance__balance-container"> <div className="transaction-view-balance__balance-container">
<Identicon <Identicon
diameter={50} diameter={50}
address={selectedToken && selectedToken.address} address={selectedToken && selectedToken.address}

View File

@ -1,7 +1,7 @@
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom' import { withRouter } from 'react-router-dom'
import { compose } from 'recompose' import { compose } from 'recompose'
import TokenViewBalance from './token-view-balance.component' import TransactionViewBalance from './transaction-view-balance.component'
import { getSelectedToken, getSelectedAddress } from '../../selectors' import { getSelectedToken, getSelectedAddress } from '../../selectors'
import { showModal } from '../../actions' import { showModal } from '../../actions'
@ -27,4 +27,4 @@ const mapDispatchToProps = dispatch => {
export default compose( export default compose(
withRouter, withRouter,
connect(mapStateToProps, mapDispatchToProps) connect(mapStateToProps, mapDispatchToProps)
)(TokenViewBalance) )(TransactionViewBalance)

View File

@ -0,0 +1 @@
export { default } from './transaction-view.component'

View File

@ -1,4 +1,4 @@
.token-view { .transaction-view {
flex: 1 1 66.5%; flex: 1 1 66.5%;
background: $white; background: $white;
min-width: 0; min-width: 0;

View File

@ -2,23 +2,23 @@ import React, { PureComponent } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import Media from 'react-media' import Media from 'react-media'
import MenuBar from '../menu-bar' import MenuBar from '../menu-bar'
import TokenViewBalance from '../token-view-balance' import TransactionViewBalance from '../transaction-view-balance'
import TransactionList from '../transaction-list' import TransactionList from '../transaction-list'
export default class TokenView extends PureComponent { export default class TransactionView extends PureComponent {
static contextTypes = { static contextTypes = {
t: PropTypes.func, t: PropTypes.func,
} }
render () { render () {
return ( return (
<div className="token-view"> <div className="transaction-view">
<Media <Media
query="(max-width: 575px)" query="(max-width: 575px)"
render={() => <MenuBar />} render={() => <MenuBar />}
/> />
<div className="token-view__balance-wrapper"> <div className="transaction-view__balance-wrapper">
<TokenViewBalance /> <TransactionViewBalance />
</div> </div>
<TransactionList /> <TransactionList />
</div> </div>

View File

@ -12,10 +12,9 @@ import {
addEth, addEth,
increaseLastGasPrice, increaseLastGasPrice,
hexGreaterThan, hexGreaterThan,
isSmartContractAddress,
} from '../helpers/confirm-transaction/util' } from '../helpers/confirm-transaction/util'
import { getTokenData, getMethodData } from '../helpers/transactions.util' import { getTokenData, getMethodData, isSmartContractAddress } from '../helpers/transactions.util'
import { getSymbolAndDecimals } from '../token-util' import { getSymbolAndDecimals } from '../token-util'
import { conversionUtil } from '../conversion-util' import { conversionUtil } from '../conversion-util'

View File

@ -123,8 +123,3 @@ export function roundExponential (value) {
// In JS, numbers with exponentials greater than 20 get displayed as an exponential. // In JS, numbers with exponentials greater than 20 get displayed as an exponential.
return bigNumberValue.e > 20 ? Number(bigNumberValue.toPrecision(PRECISION)) : value return bigNumberValue.e > 20 ? Number(bigNumberValue.toPrecision(PRECISION)) : value
} }
export async function isSmartContractAddress (address) {
const code = await global.eth.getCode(address)
return code && code !== '0x'
}

View File

@ -41,8 +41,8 @@ export function isConfirmDeployContract (txData = {}) {
return !txParams.to return !txParams.to
} }
export function getTransactionActionKey (transaction, methodData) { export async function getTransactionActionKey (transaction, methodData) {
const { txParams: { data } = {}, msgParams } = transaction const { txParams: { data, to } = {}, msgParams } = transaction
if (msgParams) { if (msgParams) {
return SIGNATURE_REQUEST_KEY return SIGNATURE_REQUEST_KEY
@ -53,6 +53,12 @@ export function getTransactionActionKey (transaction, methodData) {
} }
if (data) { if (data) {
const toSmartContract = await isSmartContractAddress(to)
if (!toSmartContract) {
return SEND_ETHER_ACTION_KEY
}
const { name } = methodData const { name } = methodData
const methodName = name && name.toLowerCase() const methodName = name && name.toLowerCase()
@ -92,3 +98,8 @@ export function getLatestSubmittedTxWithNonce (transactions = [], nonce = '0x0')
} }
}, {}) }, {})
} }
export async function isSmartContractAddress (address) {
const code = await global.eth.getCode(address)
return code && code !== '0x'
}