mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
Prevent send to token warning (#6058)
This commit is contained in:
parent
fba17d77de
commit
2d7c9b3dac
@ -104,6 +104,7 @@
|
|||||||
"amount": "0x0",
|
"amount": "0x0",
|
||||||
"memo": "",
|
"memo": "",
|
||||||
"errors": {},
|
"errors": {},
|
||||||
|
"warnings": {},
|
||||||
"maxModeOn": false,
|
"maxModeOn": false,
|
||||||
"editingTransactionId": null
|
"editingTransactionId": null
|
||||||
},
|
},
|
||||||
|
@ -159,7 +159,8 @@
|
|||||||
"send": {
|
"send": {
|
||||||
"fromDropdownOpen": false,
|
"fromDropdownOpen": false,
|
||||||
"toDropdownOpen": false,
|
"toDropdownOpen": false,
|
||||||
"errors": {}
|
"errors": {},
|
||||||
|
"warnings": {}
|
||||||
},
|
},
|
||||||
"confirmTransaction": {
|
"confirmTransaction": {
|
||||||
"txData": {},
|
"txData": {},
|
||||||
|
@ -148,6 +148,7 @@
|
|||||||
"amount": "0x1bc16d674ec80000",
|
"amount": "0x1bc16d674ec80000",
|
||||||
"memo": "",
|
"memo": "",
|
||||||
"errors": {},
|
"errors": {},
|
||||||
|
"warnings": {},
|
||||||
"maxModeOn": false,
|
"maxModeOn": false,
|
||||||
"editingTransactionId": null
|
"editingTransactionId": null
|
||||||
},
|
},
|
||||||
|
@ -106,6 +106,7 @@
|
|||||||
"amount": "0x0",
|
"amount": "0x0",
|
||||||
"memo": "",
|
"memo": "",
|
||||||
"errors": {},
|
"errors": {},
|
||||||
|
"warnings": {},
|
||||||
"maxModeOn": false,
|
"maxModeOn": false,
|
||||||
"editingTransactionId": null
|
"editingTransactionId": null
|
||||||
},
|
},
|
||||||
|
@ -280,7 +280,8 @@
|
|||||||
"send": {
|
"send": {
|
||||||
"fromDropdownOpen": false,
|
"fromDropdownOpen": false,
|
||||||
"toDropdownOpen": false,
|
"toDropdownOpen": false,
|
||||||
"errors": {}
|
"errors": {},
|
||||||
|
"warnings": {}
|
||||||
},
|
},
|
||||||
"confirmTransaction": {
|
"confirmTransaction": {
|
||||||
"txData": {
|
"txData": {
|
||||||
|
@ -128,6 +128,7 @@
|
|||||||
"amount": "0x1bc16d674ec80000",
|
"amount": "0x1bc16d674ec80000",
|
||||||
"memo": "",
|
"memo": "",
|
||||||
"errors": {},
|
"errors": {},
|
||||||
|
"warnings": {},
|
||||||
"maxModeOn": false,
|
"maxModeOn": false,
|
||||||
"editingTransactionId": null
|
"editingTransactionId": null
|
||||||
},
|
},
|
||||||
@ -161,7 +162,8 @@
|
|||||||
"send": {
|
"send": {
|
||||||
"fromDropdownOpen": false,
|
"fromDropdownOpen": false,
|
||||||
"toDropdownOpen": false,
|
"toDropdownOpen": false,
|
||||||
"errors": {}
|
"errors": {},
|
||||||
|
"warnings": {}
|
||||||
},
|
},
|
||||||
"confirmTransaction": {
|
"confirmTransaction": {
|
||||||
"txData": {},
|
"txData": {},
|
||||||
|
@ -107,6 +107,7 @@
|
|||||||
"amount": "0x0",
|
"amount": "0x0",
|
||||||
"memo": "",
|
"memo": "",
|
||||||
"errors": {},
|
"errors": {},
|
||||||
|
"warnings": {},
|
||||||
"maxModeOn": false,
|
"maxModeOn": false,
|
||||||
"editingTransactionId": null
|
"editingTransactionId": null
|
||||||
},
|
},
|
||||||
@ -141,6 +142,7 @@
|
|||||||
"fromDropdownOpen": false,
|
"fromDropdownOpen": false,
|
||||||
"toDropdownOpen": false,
|
"toDropdownOpen": false,
|
||||||
"errors": {},
|
"errors": {},
|
||||||
|
"warnings": {},
|
||||||
"gasButtonGroupShown": true
|
"gasButtonGroupShown": true
|
||||||
},
|
},
|
||||||
"confirmTransaction": {
|
"confirmTransaction": {
|
||||||
|
@ -133,7 +133,8 @@
|
|||||||
"send": {
|
"send": {
|
||||||
"fromDropdownOpen": false,
|
"fromDropdownOpen": false,
|
||||||
"toDropdownOpen": false,
|
"toDropdownOpen": false,
|
||||||
"errors": {}
|
"errors": {},
|
||||||
|
"warnings": {}
|
||||||
},
|
},
|
||||||
"gas": {
|
"gas": {
|
||||||
"customData": {
|
"customData": {
|
||||||
|
@ -191,6 +191,7 @@ var actions = {
|
|||||||
UPDATE_SEND_AMOUNT: 'UPDATE_SEND_AMOUNT',
|
UPDATE_SEND_AMOUNT: 'UPDATE_SEND_AMOUNT',
|
||||||
UPDATE_SEND_MEMO: 'UPDATE_SEND_MEMO',
|
UPDATE_SEND_MEMO: 'UPDATE_SEND_MEMO',
|
||||||
UPDATE_SEND_ERRORS: 'UPDATE_SEND_ERRORS',
|
UPDATE_SEND_ERRORS: 'UPDATE_SEND_ERRORS',
|
||||||
|
UPDATE_SEND_WARNINGS: 'UPDATE_SEND_WARNINGS',
|
||||||
UPDATE_MAX_MODE: 'UPDATE_MAX_MODE',
|
UPDATE_MAX_MODE: 'UPDATE_MAX_MODE',
|
||||||
UPDATE_SEND: 'UPDATE_SEND',
|
UPDATE_SEND: 'UPDATE_SEND',
|
||||||
CLEAR_SEND: 'CLEAR_SEND',
|
CLEAR_SEND: 'CLEAR_SEND',
|
||||||
@ -211,6 +212,7 @@ var actions = {
|
|||||||
setMaxModeTo,
|
setMaxModeTo,
|
||||||
updateSend,
|
updateSend,
|
||||||
updateSendErrors,
|
updateSendErrors,
|
||||||
|
updateSendWarnings,
|
||||||
clearSend,
|
clearSend,
|
||||||
setSelectedAddress,
|
setSelectedAddress,
|
||||||
gasLoadingStarted,
|
gasLoadingStarted,
|
||||||
@ -1068,6 +1070,13 @@ function updateSendErrors (errorObject) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateSendWarnings (warningObject) {
|
||||||
|
return {
|
||||||
|
type: actions.UPDATE_SEND_WARNINGS,
|
||||||
|
value: warningObject,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function setSendTokenBalance (tokenBalance) {
|
function setSendTokenBalance (tokenBalance) {
|
||||||
return {
|
return {
|
||||||
type: actions.UPDATE_SEND_TOKEN_BALANCE,
|
type: actions.UPDATE_SEND_TOKEN_BALANCE,
|
||||||
|
@ -128,7 +128,7 @@ EnsInput.prototype.componentDidUpdate = function (prevProps, prevState) {
|
|||||||
}
|
}
|
||||||
if (prevState && ensResolution && this.props.onChange &&
|
if (prevState && ensResolution && this.props.onChange &&
|
||||||
ensResolution !== prevState.ensResolution) {
|
ensResolution !== prevState.ensResolution) {
|
||||||
this.props.onChange({ toAddress: ensResolution, nickname, toError: state.toError })
|
this.props.onChange({ toAddress: ensResolution, nickname, toError: state.toError, toWarning: state.toWarning })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
export { default } from './send-row-warning-message.container'
|
@ -0,0 +1,27 @@
|
|||||||
|
import React, { Component } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
|
export default class SendRowWarningMessage extends Component {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
warnings: PropTypes.object,
|
||||||
|
warningType: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
t: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { warnings, warningType } = this.props
|
||||||
|
|
||||||
|
const warningMessage = warningType in warnings && warnings[warningType]
|
||||||
|
|
||||||
|
return (
|
||||||
|
warningMessage
|
||||||
|
? <div className="send-v2__warning">{this.context.t(warningMessage)}</div>
|
||||||
|
: null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { getSendWarnings } from '../../../send.selectors'
|
||||||
|
import SendRowWarningMessage from './send-row-warning-message.component'
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(SendRowWarningMessage)
|
||||||
|
|
||||||
|
function mapStateToProps (state, ownProps) {
|
||||||
|
return {
|
||||||
|
warnings: getSendWarnings(state),
|
||||||
|
warningType: ownProps.warningType,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
import SendRowWarningMessage from '../send-row-warning-message.component.js'
|
||||||
|
|
||||||
|
describe('SendRowWarningMessage Component', function () {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<SendRowWarningMessage
|
||||||
|
warnings={{ warning1: 'abc', warning2: 'def' }}
|
||||||
|
warningType={'warning3'}
|
||||||
|
/>, { context: { t: str => str + '_t' } })
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('render', () => {
|
||||||
|
it('should render null if the passed warnings do not contain a warning of warningType', () => {
|
||||||
|
assert.equal(wrapper.find('.send-v2__warning').length, 0)
|
||||||
|
assert.equal(wrapper.html(), null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should render a warning message if the passed warnings contain a warning of warningType', () => {
|
||||||
|
wrapper.setProps({ warnings: { warning1: 'abc', warning2: 'def', warning3: 'xyz' } })
|
||||||
|
assert.equal(wrapper.find('.send-v2__warning').length, 1)
|
||||||
|
assert.equal(wrapper.find('.send-v2__warning').text(), 'xyz_t')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,28 @@
|
|||||||
|
import assert from 'assert'
|
||||||
|
import proxyquire from 'proxyquire'
|
||||||
|
|
||||||
|
let mapStateToProps
|
||||||
|
|
||||||
|
proxyquire('../send-row-warning-message.container.js', {
|
||||||
|
'react-redux': {
|
||||||
|
connect: (ms, md) => {
|
||||||
|
mapStateToProps = ms
|
||||||
|
return () => ({})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'../../../send.selectors': { getSendWarnings: (s) => `mockWarnings:${s}` },
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('send-row-warning-message container', () => {
|
||||||
|
|
||||||
|
describe('mapStateToProps()', () => {
|
||||||
|
|
||||||
|
it('should map the correct properties to props', () => {
|
||||||
|
assert.deepEqual(mapStateToProps('mockState', { warningType: 'someType' }), {
|
||||||
|
warnings: 'mockWarnings:mockState',
|
||||||
|
warningType: 'someType' })
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
@ -1,6 +1,7 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import SendRowErrorMessage from './send-row-error-message/'
|
import SendRowErrorMessage from './send-row-error-message/'
|
||||||
|
import SendRowWarningMessage from './send-row-warning-message/'
|
||||||
|
|
||||||
export default class SendRowWrapper extends Component {
|
export default class SendRowWrapper extends Component {
|
||||||
|
|
||||||
@ -9,6 +10,8 @@ export default class SendRowWrapper extends Component {
|
|||||||
errorType: PropTypes.string,
|
errorType: PropTypes.string,
|
||||||
label: PropTypes.string,
|
label: PropTypes.string,
|
||||||
showError: PropTypes.bool,
|
showError: PropTypes.bool,
|
||||||
|
showWarning: PropTypes.bool,
|
||||||
|
warningType: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
@ -21,8 +24,9 @@ export default class SendRowWrapper extends Component {
|
|||||||
errorType = '',
|
errorType = '',
|
||||||
label,
|
label,
|
||||||
showError = false,
|
showError = false,
|
||||||
|
showWarning = false,
|
||||||
|
warningType = '',
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const formField = Array.isArray(children) ? children[1] || children[0] : children
|
const formField = Array.isArray(children) ? children[1] || children[0] : children
|
||||||
const customLabelContent = children.length > 1 ? children[0] : null
|
const customLabelContent = children.length > 1 ? children[0] : null
|
||||||
|
|
||||||
@ -31,6 +35,7 @@ export default class SendRowWrapper extends Component {
|
|||||||
<div className="send-v2__form-label">
|
<div className="send-v2__form-label">
|
||||||
{label}
|
{label}
|
||||||
{showError && <SendRowErrorMessage errorType={errorType}/>}
|
{showError && <SendRowErrorMessage errorType={errorType}/>}
|
||||||
|
{!showError && showWarning && <SendRowWarningMessage warningType={warningType} />}
|
||||||
{customLabelContent}
|
{customLabelContent}
|
||||||
</div>
|
</div>
|
||||||
<div className="send-v2__form-field">
|
<div className="send-v2__form-field">
|
||||||
|
@ -2,7 +2,7 @@ import React, { Component } from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import SendRowWrapper from '../send-row-wrapper/'
|
import SendRowWrapper from '../send-row-wrapper/'
|
||||||
import EnsInput from '../../../ens-input'
|
import EnsInput from '../../../ens-input'
|
||||||
import { getToErrorObject } from './send-to-row.utils.js'
|
import { getToErrorObject, getToWarningObject } from './send-to-row.utils.js'
|
||||||
|
|
||||||
export default class SendToRow extends Component {
|
export default class SendToRow extends Component {
|
||||||
|
|
||||||
@ -10,6 +10,7 @@ export default class SendToRow extends Component {
|
|||||||
closeToDropdown: PropTypes.func,
|
closeToDropdown: PropTypes.func,
|
||||||
hasHexData: PropTypes.bool.isRequired,
|
hasHexData: PropTypes.bool.isRequired,
|
||||||
inError: PropTypes.bool,
|
inError: PropTypes.bool,
|
||||||
|
inWarning: PropTypes.bool,
|
||||||
network: PropTypes.string,
|
network: PropTypes.string,
|
||||||
openToDropdown: PropTypes.func,
|
openToDropdown: PropTypes.func,
|
||||||
selectedToken: PropTypes.object,
|
selectedToken: PropTypes.object,
|
||||||
@ -20,6 +21,7 @@ export default class SendToRow extends Component {
|
|||||||
updateGas: PropTypes.func,
|
updateGas: PropTypes.func,
|
||||||
updateSendTo: PropTypes.func,
|
updateSendTo: PropTypes.func,
|
||||||
updateSendToError: PropTypes.func,
|
updateSendToError: PropTypes.func,
|
||||||
|
updateSendToWarning: PropTypes.func,
|
||||||
scanQrCode: PropTypes.func,
|
scanQrCode: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,11 +29,13 @@ export default class SendToRow extends Component {
|
|||||||
t: PropTypes.func,
|
t: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
handleToChange (to, nickname = '', toError) {
|
handleToChange (to, nickname = '', toError, toWarning) {
|
||||||
const { hasHexData, updateSendTo, updateSendToError, updateGas, tokens, selectedToken } = this.props
|
const { hasHexData, updateSendTo, updateSendToError, updateGas, tokens, selectedToken, updateSendToWarning } = this.props
|
||||||
const toErrorObject = getToErrorObject(to, toError, hasHexData, tokens, selectedToken)
|
const toErrorObject = getToErrorObject(to, toError, hasHexData)
|
||||||
|
const toWarningObject = getToWarningObject(to, toWarning, tokens, selectedToken)
|
||||||
updateSendTo(to, nickname)
|
updateSendTo(to, nickname)
|
||||||
updateSendToError(toErrorObject)
|
updateSendToError(toErrorObject)
|
||||||
|
updateSendToWarning(toWarningObject)
|
||||||
if (toErrorObject.to === null) {
|
if (toErrorObject.to === null) {
|
||||||
updateGas({ to })
|
updateGas({ to })
|
||||||
}
|
}
|
||||||
@ -41,6 +45,7 @@ export default class SendToRow extends Component {
|
|||||||
const {
|
const {
|
||||||
closeToDropdown,
|
closeToDropdown,
|
||||||
inError,
|
inError,
|
||||||
|
inWarning,
|
||||||
network,
|
network,
|
||||||
openToDropdown,
|
openToDropdown,
|
||||||
to,
|
to,
|
||||||
@ -53,6 +58,8 @@ export default class SendToRow extends Component {
|
|||||||
errorType={'to'}
|
errorType={'to'}
|
||||||
label={`${this.context.t('to')}: `}
|
label={`${this.context.t('to')}: `}
|
||||||
showError={inError}
|
showError={inError}
|
||||||
|
showWarning={inWarning}
|
||||||
|
warningType={'to'}
|
||||||
>
|
>
|
||||||
<EnsInput
|
<EnsInput
|
||||||
scanQrCode={_ => this.props.scanQrCode()}
|
scanQrCode={_ => this.props.scanQrCode()}
|
||||||
@ -62,7 +69,7 @@ export default class SendToRow extends Component {
|
|||||||
inError={inError}
|
inError={inError}
|
||||||
name={'address'}
|
name={'address'}
|
||||||
network={network}
|
network={network}
|
||||||
onChange={({ toAddress, nickname, toError }) => this.handleToChange(toAddress, nickname, toError)}
|
onChange={({ toAddress, nickname, toError, toWarning }) => this.handleToChange(toAddress, nickname, toError, toWarning)}
|
||||||
openDropdown={() => openToDropdown()}
|
openDropdown={() => openToDropdown()}
|
||||||
placeholder={this.context.t('recipientAddress')}
|
placeholder={this.context.t('recipientAddress')}
|
||||||
to={to}
|
to={to}
|
||||||
|
@ -10,12 +10,14 @@ import {
|
|||||||
getToDropdownOpen,
|
getToDropdownOpen,
|
||||||
getTokens,
|
getTokens,
|
||||||
sendToIsInError,
|
sendToIsInError,
|
||||||
|
sendToIsInWarning,
|
||||||
} from './send-to-row.selectors.js'
|
} from './send-to-row.selectors.js'
|
||||||
import {
|
import {
|
||||||
updateSendTo,
|
updateSendTo,
|
||||||
} from '../../../../actions'
|
} from '../../../../actions'
|
||||||
import {
|
import {
|
||||||
updateSendErrors,
|
updateSendErrors,
|
||||||
|
updateSendWarnings,
|
||||||
openToDropdown,
|
openToDropdown,
|
||||||
closeToDropdown,
|
closeToDropdown,
|
||||||
} from '../../../../ducks/send.duck'
|
} from '../../../../ducks/send.duck'
|
||||||
@ -27,6 +29,7 @@ function mapStateToProps (state) {
|
|||||||
return {
|
return {
|
||||||
hasHexData: Boolean(getSendHexData(state)),
|
hasHexData: Boolean(getSendHexData(state)),
|
||||||
inError: sendToIsInError(state),
|
inError: sendToIsInError(state),
|
||||||
|
inWarning: sendToIsInWarning(state),
|
||||||
network: getCurrentNetwork(state),
|
network: getCurrentNetwork(state),
|
||||||
selectedToken: getSelectedToken(state),
|
selectedToken: getSelectedToken(state),
|
||||||
to: getSendTo(state),
|
to: getSendTo(state),
|
||||||
@ -44,5 +47,8 @@ function mapDispatchToProps (dispatch) {
|
|||||||
updateSendToError: (toErrorObject) => {
|
updateSendToError: (toErrorObject) => {
|
||||||
dispatch(updateSendErrors(toErrorObject))
|
dispatch(updateSendErrors(toErrorObject))
|
||||||
},
|
},
|
||||||
|
updateSendToWarning: (toWarningObject) => {
|
||||||
|
dispatch(updateSendWarnings(toWarningObject))
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ const selectors = {
|
|||||||
getToDropdownOpen,
|
getToDropdownOpen,
|
||||||
getTokens,
|
getTokens,
|
||||||
sendToIsInError,
|
sendToIsInError,
|
||||||
|
sendToIsInWarning,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = selectors
|
module.exports = selectors
|
||||||
@ -14,6 +15,10 @@ function sendToIsInError (state) {
|
|||||||
return Boolean(state.send.errors.to)
|
return Boolean(state.send.errors.to)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendToIsInWarning (state) {
|
||||||
|
return Boolean(state.send.warnings.to)
|
||||||
|
}
|
||||||
|
|
||||||
function getTokens (state) {
|
function getTokens (state) {
|
||||||
return state.metamask.tokens
|
return state.metamask.tokens
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,17 @@ function getToErrorObject (to, toError = null, hasHexData = false, tokens = [],
|
|||||||
} else if (selectedToken && (ethUtil.toChecksumAddress(to) in contractMap || checkExistingAddresses(to, tokens))) {
|
} else if (selectedToken && (ethUtil.toChecksumAddress(to) in contractMap || checkExistingAddresses(to, tokens))) {
|
||||||
toError = KNOWN_RECIPIENT_ADDRESS_ERROR
|
toError = KNOWN_RECIPIENT_ADDRESS_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
return { to: toError }
|
return { to: toError }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getToWarningObject (to, toWarning = null, tokens = [], selectedToken = null) {
|
||||||
|
if (selectedToken && (ethUtil.toChecksumAddress(to) in contractMap || checkExistingAddresses(to, tokens))) {
|
||||||
|
toWarning = KNOWN_RECIPIENT_ADDRESS_ERROR
|
||||||
|
}
|
||||||
|
return { to: toWarning }
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getToErrorObject,
|
getToErrorObject,
|
||||||
|
getToWarningObject,
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,9 @@ const SendToRow = proxyquire('../send-to-row.component.js', {
|
|||||||
getToErrorObject: (to, toError) => ({
|
getToErrorObject: (to, toError) => ({
|
||||||
to: to === false ? null : `mockToErrorObject:${to}${toError}`,
|
to: to === false ? null : `mockToErrorObject:${to}${toError}`,
|
||||||
}),
|
}),
|
||||||
|
getToWarningObject: (to, toWarning) => ({
|
||||||
|
to: to === false ? null : `mockToWarningObject:${to}${toWarning}`,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}).default
|
}).default
|
||||||
|
|
||||||
@ -21,6 +24,7 @@ const propsMethodSpies = {
|
|||||||
updateGas: sinon.spy(),
|
updateGas: sinon.spy(),
|
||||||
updateSendTo: sinon.spy(),
|
updateSendTo: sinon.spy(),
|
||||||
updateSendToError: sinon.spy(),
|
updateSendToError: sinon.spy(),
|
||||||
|
updateSendToWarning: sinon.spy(),
|
||||||
}
|
}
|
||||||
|
|
||||||
sinon.spy(SendToRow.prototype, 'handleToChange')
|
sinon.spy(SendToRow.prototype, 'handleToChange')
|
||||||
@ -33,6 +37,7 @@ describe('SendToRow Component', function () {
|
|||||||
wrapper = shallow(<SendToRow
|
wrapper = shallow(<SendToRow
|
||||||
closeToDropdown={propsMethodSpies.closeToDropdown}
|
closeToDropdown={propsMethodSpies.closeToDropdown}
|
||||||
inError={false}
|
inError={false}
|
||||||
|
inWarning={false}
|
||||||
network={'mockNetwork'}
|
network={'mockNetwork'}
|
||||||
openToDropdown={propsMethodSpies.openToDropdown}
|
openToDropdown={propsMethodSpies.openToDropdown}
|
||||||
to={'mockTo'}
|
to={'mockTo'}
|
||||||
@ -41,6 +46,7 @@ describe('SendToRow Component', function () {
|
|||||||
updateGas={propsMethodSpies.updateGas}
|
updateGas={propsMethodSpies.updateGas}
|
||||||
updateSendTo={propsMethodSpies.updateSendTo}
|
updateSendTo={propsMethodSpies.updateSendTo}
|
||||||
updateSendToError={propsMethodSpies.updateSendToError}
|
updateSendToError={propsMethodSpies.updateSendToError}
|
||||||
|
updateSendToWarning={propsMethodSpies.updateSendToWarning}
|
||||||
/>, { context: { t: str => str + '_t' } })
|
/>, { context: { t: str => str + '_t' } })
|
||||||
instance = wrapper.instance()
|
instance = wrapper.instance()
|
||||||
})
|
})
|
||||||
@ -50,6 +56,7 @@ describe('SendToRow Component', function () {
|
|||||||
propsMethodSpies.openToDropdown.resetHistory()
|
propsMethodSpies.openToDropdown.resetHistory()
|
||||||
propsMethodSpies.updateSendTo.resetHistory()
|
propsMethodSpies.updateSendTo.resetHistory()
|
||||||
propsMethodSpies.updateSendToError.resetHistory()
|
propsMethodSpies.updateSendToError.resetHistory()
|
||||||
|
propsMethodSpies.updateSendToWarning.resetHistory()
|
||||||
SendToRow.prototype.handleToChange.resetHistory()
|
SendToRow.prototype.handleToChange.resetHistory()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -75,6 +82,16 @@ describe('SendToRow Component', function () {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should call updateSendToWarning', () => {
|
||||||
|
assert.equal(propsMethodSpies.updateSendToWarning.callCount, 0)
|
||||||
|
instance.handleToChange('mockTo2', '', '', 'mockToWarning')
|
||||||
|
assert.equal(propsMethodSpies.updateSendToWarning.callCount, 1)
|
||||||
|
assert.deepEqual(
|
||||||
|
propsMethodSpies.updateSendToWarning.getCall(0).args,
|
||||||
|
[{ to: 'mockToWarningObject:mockTo2mockToWarning' }]
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it('should not call updateGas if there is a to error', () => {
|
it('should not call updateGas if there is a to error', () => {
|
||||||
assert.equal(propsMethodSpies.updateGas.callCount, 0)
|
assert.equal(propsMethodSpies.updateGas.callCount, 0)
|
||||||
instance.handleToChange('mockTo2')
|
instance.handleToChange('mockTo2')
|
||||||
@ -138,11 +155,11 @@ describe('SendToRow Component', function () {
|
|||||||
openDropdown()
|
openDropdown()
|
||||||
assert.equal(propsMethodSpies.openToDropdown.callCount, 1)
|
assert.equal(propsMethodSpies.openToDropdown.callCount, 1)
|
||||||
assert.equal(SendToRow.prototype.handleToChange.callCount, 0)
|
assert.equal(SendToRow.prototype.handleToChange.callCount, 0)
|
||||||
onChange({ toAddress: 'mockNewTo', nickname: 'mockNewNickname', toError: 'mockToError' })
|
onChange({ toAddress: 'mockNewTo', nickname: 'mockNewNickname', toError: 'mockToError', toWarning: 'mockToWarning' })
|
||||||
assert.equal(SendToRow.prototype.handleToChange.callCount, 1)
|
assert.equal(SendToRow.prototype.handleToChange.callCount, 1)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
SendToRow.prototype.handleToChange.getCall(0).args,
|
SendToRow.prototype.handleToChange.getCall(0).args,
|
||||||
['mockNewTo', 'mockNewNickname', 'mockToError']
|
['mockNewTo', 'mockNewNickname', 'mockToError', 'mockToWarning']
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -12,6 +12,7 @@ const duckActionSpies = {
|
|||||||
closeToDropdown: sinon.spy(),
|
closeToDropdown: sinon.spy(),
|
||||||
openToDropdown: sinon.spy(),
|
openToDropdown: sinon.spy(),
|
||||||
updateSendErrors: sinon.spy(),
|
updateSendErrors: sinon.spy(),
|
||||||
|
updateSendWarnings: sinon.spy(),
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyquire('../send-to-row.container.js', {
|
proxyquire('../send-to-row.container.js', {
|
||||||
@ -32,6 +33,7 @@ proxyquire('../send-to-row.container.js', {
|
|||||||
'./send-to-row.selectors.js': {
|
'./send-to-row.selectors.js': {
|
||||||
getToDropdownOpen: (s) => `mockToDropdownOpen:${s}`,
|
getToDropdownOpen: (s) => `mockToDropdownOpen:${s}`,
|
||||||
sendToIsInError: (s) => `mockInError:${s}`,
|
sendToIsInError: (s) => `mockInError:${s}`,
|
||||||
|
sendToIsInWarning: (s) => `mockInWarning:${s}`,
|
||||||
getTokens: (s) => `mockTokens:${s}`,
|
getTokens: (s) => `mockTokens:${s}`,
|
||||||
},
|
},
|
||||||
'../../../../actions': actionSpies,
|
'../../../../actions': actionSpies,
|
||||||
@ -46,6 +48,7 @@ describe('send-to-row container', () => {
|
|||||||
assert.deepEqual(mapStateToProps('mockState'), {
|
assert.deepEqual(mapStateToProps('mockState'), {
|
||||||
hasHexData: true,
|
hasHexData: true,
|
||||||
inError: 'mockInError:mockState',
|
inError: 'mockInError:mockState',
|
||||||
|
inWarning: 'mockInWarning:mockState',
|
||||||
network: 'mockNetwork:mockState',
|
network: 'mockNetwork:mockState',
|
||||||
selectedToken: 'mockSelectedToken:mockState',
|
selectedToken: 'mockSelectedToken:mockState',
|
||||||
to: 'mockTo:mockState',
|
to: 'mockTo:mockState',
|
||||||
@ -114,6 +117,18 @@ describe('send-to-row container', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('updateSendToWarning()', () => {
|
||||||
|
it('should dispatch an action', () => {
|
||||||
|
mapDispatchToPropsObject.updateSendToWarning('mockToWarningObject')
|
||||||
|
assert(dispatchSpy.calledOnce)
|
||||||
|
assert(duckActionSpies.updateSendWarnings.calledOnce)
|
||||||
|
assert.equal(
|
||||||
|
duckActionSpies.updateSendWarnings.getCall(0).args[0],
|
||||||
|
'mockToWarningObject'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -19,6 +19,7 @@ const toRowUtils = proxyquire('../send-to-row.utils.js', {
|
|||||||
})
|
})
|
||||||
const {
|
const {
|
||||||
getToErrorObject,
|
getToErrorObject,
|
||||||
|
getToWarningObject,
|
||||||
} = toRowUtils
|
} = toRowUtils
|
||||||
|
|
||||||
describe('send-to-row utils', () => {
|
describe('send-to-row utils', () => {
|
||||||
@ -78,4 +79,29 @@ describe('send-to-row utils', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('getToWarningObject()', () => {
|
||||||
|
it('should return a known address recipient if to is truthy but part of state tokens', () => {
|
||||||
|
assert.deepEqual(getToWarningObject('0xabc123', undefined, [{'address': '0xabc123'}], {'address': '0xabc123'}), {
|
||||||
|
to: KNOWN_RECIPIENT_ADDRESS_ERROR,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should null if to is truthy part of tokens but selectedToken falsy', () => {
|
||||||
|
assert.deepEqual(getToWarningObject('0xabc123', undefined, [{'address': '0xabc123'}]), {
|
||||||
|
to: null,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return a known address recipient if to is truthy but part of contract metadata', () => {
|
||||||
|
assert.deepEqual(getToWarningObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, [{'address': '0xabc123'}], {'address': '0xabc123'}), {
|
||||||
|
to: KNOWN_RECIPIENT_ADDRESS_ERROR,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('should null if to is truthy part of contract metadata but selectedToken falsy', () => {
|
||||||
|
assert.deepEqual(getToWarningObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, [{'address': '0xabc123'}], {'address': '0xabc123'}), {
|
||||||
|
to: KNOWN_RECIPIENT_ADDRESS_ERROR,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -51,6 +51,7 @@ const selectors = {
|
|||||||
getSendMaxModeState,
|
getSendMaxModeState,
|
||||||
getSendTo,
|
getSendTo,
|
||||||
getSendToAccounts,
|
getSendToAccounts,
|
||||||
|
getSendWarnings,
|
||||||
getTokenBalance,
|
getTokenBalance,
|
||||||
getTokenExchangeRate,
|
getTokenExchangeRate,
|
||||||
getUnapprovedTxs,
|
getUnapprovedTxs,
|
||||||
@ -268,6 +269,10 @@ function getSendToAccounts (state) {
|
|||||||
return Object.entries(allAccounts).map(([key, account]) => account)
|
return Object.entries(allAccounts).map(([key, account]) => account)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSendWarnings (state) {
|
||||||
|
return state.send.warnings
|
||||||
|
}
|
||||||
|
|
||||||
function getTokenBalance (state) {
|
function getTokenBalance (state) {
|
||||||
return state.metamask.send.tokenBalance
|
return state.metamask.send.tokenBalance
|
||||||
}
|
}
|
||||||
|
@ -520,6 +520,13 @@
|
|||||||
color: $red;
|
color: $red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__warning {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 12px;
|
||||||
|
left: 8px;
|
||||||
|
color: $orange;
|
||||||
|
}
|
||||||
|
|
||||||
&__error-border {
|
&__error-border {
|
||||||
color: $red;
|
color: $red;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ const CLOSE_FROM_DROPDOWN = 'metamask/send/CLOSE_FROM_DROPDOWN'
|
|||||||
const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN'
|
const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN'
|
||||||
const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN'
|
const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN'
|
||||||
const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS'
|
const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS'
|
||||||
|
const UPDATE_SEND_WARNINGS = 'metamask/send/UPDATE_SEND_WARNINGS'
|
||||||
const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE'
|
const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE'
|
||||||
const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP'
|
const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP'
|
||||||
const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP'
|
const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP'
|
||||||
@ -16,6 +17,7 @@ const initState = {
|
|||||||
toDropdownOpen: false,
|
toDropdownOpen: false,
|
||||||
gasButtonGroupShown: true,
|
gasButtonGroupShown: true,
|
||||||
errors: {},
|
errors: {},
|
||||||
|
warnings: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reducer
|
// Reducer
|
||||||
@ -46,6 +48,13 @@ export default function reducer ({ send: sendState = initState }, action = {}) {
|
|||||||
...action.value,
|
...action.value,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
case UPDATE_SEND_WARNINGS:
|
||||||
|
return extend(newState, {
|
||||||
|
warnings: {
|
||||||
|
...newState.warnings,
|
||||||
|
...action.value,
|
||||||
|
},
|
||||||
|
})
|
||||||
case SHOW_GAS_BUTTON_GROUP:
|
case SHOW_GAS_BUTTON_GROUP:
|
||||||
return extend(newState, {
|
return extend(newState, {
|
||||||
gasButtonGroupShown: true,
|
gasButtonGroupShown: true,
|
||||||
@ -85,6 +94,13 @@ export function updateSendErrors (errorObject) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function updateSendWarnings (warningObject) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SEND_WARNINGS,
|
||||||
|
value: warningObject,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function resetSendState () {
|
export function resetSendState () {
|
||||||
return { type: RESET_SEND_STATE }
|
return { type: RESET_SEND_STATE }
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import SendReducer, {
|
|||||||
updateSendErrors,
|
updateSendErrors,
|
||||||
showGasButtonGroup,
|
showGasButtonGroup,
|
||||||
hideGasButtonGroup,
|
hideGasButtonGroup,
|
||||||
|
updateSendWarnings,
|
||||||
} from '../send.duck.js'
|
} from '../send.duck.js'
|
||||||
|
|
||||||
describe('Send Duck', () => {
|
describe('Send Duck', () => {
|
||||||
@ -19,12 +20,14 @@ describe('Send Duck', () => {
|
|||||||
toDropdownOpen: false,
|
toDropdownOpen: false,
|
||||||
errors: {},
|
errors: {},
|
||||||
gasButtonGroupShown: true,
|
gasButtonGroupShown: true,
|
||||||
|
warnings: {},
|
||||||
}
|
}
|
||||||
const OPEN_FROM_DROPDOWN = 'metamask/send/OPEN_FROM_DROPDOWN'
|
const OPEN_FROM_DROPDOWN = 'metamask/send/OPEN_FROM_DROPDOWN'
|
||||||
const CLOSE_FROM_DROPDOWN = 'metamask/send/CLOSE_FROM_DROPDOWN'
|
const CLOSE_FROM_DROPDOWN = 'metamask/send/CLOSE_FROM_DROPDOWN'
|
||||||
const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN'
|
const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN'
|
||||||
const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN'
|
const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN'
|
||||||
const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS'
|
const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS'
|
||||||
|
const UPDATE_SEND_WARNINGS = 'metamask/send/UPDATE_SEND_WARNINGS'
|
||||||
const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE'
|
const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE'
|
||||||
const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP'
|
const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP'
|
||||||
const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP'
|
const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP'
|
||||||
@ -173,4 +176,11 @@ describe('Send Duck', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('updateSendWarnings', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
updateSendWarnings('mockWarningObject'),
|
||||||
|
{ type: UPDATE_SEND_WARNINGS, value: 'mockWarningObject' }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user