mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Merge pull request #4574 from MetaMask/i4409-i4410-ens-input-enhancements
[new-ui] Improve ENS input errors and update ens validation on network change
This commit is contained in:
commit
1839ab5346
@ -265,6 +265,9 @@
|
||||
"encryptNewDen": {
|
||||
"message": "Encrypt your new DEN"
|
||||
},
|
||||
"ensNameNotFound": {
|
||||
"message": "ENS name not found"
|
||||
},
|
||||
"enterPassword": {
|
||||
"message": "Enter password"
|
||||
},
|
||||
|
@ -12,6 +12,7 @@ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
||||
const connect = require('react-redux').connect
|
||||
const ToAutoComplete = require('./send/to-autocomplete')
|
||||
const log = require('loglevel')
|
||||
const { isValidENSAddress } = require('../util')
|
||||
|
||||
EnsInput.contextTypes = {
|
||||
t: PropTypes.func,
|
||||
@ -25,31 +26,34 @@ function EnsInput () {
|
||||
Component.call(this)
|
||||
}
|
||||
|
||||
EnsInput.prototype.onChange = function (recipient) {
|
||||
const network = this.props.network
|
||||
const networkHasEnsSupport = getNetworkEnsSupport(network)
|
||||
|
||||
this.props.onChange({ toAddress: recipient })
|
||||
|
||||
if (!networkHasEnsSupport) return
|
||||
|
||||
if (recipient.match(ensRE) === null) {
|
||||
return this.setState({
|
||||
loadingEns: false,
|
||||
ensResolution: null,
|
||||
ensFailure: null,
|
||||
toError: null,
|
||||
})
|
||||
}
|
||||
|
||||
this.setState({
|
||||
loadingEns: true,
|
||||
})
|
||||
this.checkName(recipient)
|
||||
}
|
||||
|
||||
EnsInput.prototype.render = function () {
|
||||
const props = this.props
|
||||
const opts = extend(props, {
|
||||
list: 'addresses',
|
||||
onChange: (recipient) => {
|
||||
const network = this.props.network
|
||||
const networkHasEnsSupport = getNetworkEnsSupport(network)
|
||||
|
||||
props.onChange(recipient)
|
||||
|
||||
if (!networkHasEnsSupport) return
|
||||
|
||||
if (recipient.match(ensRE) === null) {
|
||||
return this.setState({
|
||||
loadingEns: false,
|
||||
ensResolution: null,
|
||||
ensFailure: null,
|
||||
})
|
||||
}
|
||||
|
||||
this.setState({
|
||||
loadingEns: true,
|
||||
})
|
||||
this.checkName(recipient)
|
||||
},
|
||||
onChange: this.onChange.bind(this),
|
||||
})
|
||||
return h('div', {
|
||||
style: { width: '100%', position: 'relative' },
|
||||
@ -85,17 +89,27 @@ EnsInput.prototype.lookupEnsName = function (recipient) {
|
||||
nickname: recipient.trim(),
|
||||
hoverText: address + '\n' + this.context.t('clickCopy'),
|
||||
ensFailure: false,
|
||||
toError: null,
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch((reason) => {
|
||||
log.error(reason)
|
||||
return this.setState({
|
||||
const setStateObj = {
|
||||
loadingEns: false,
|
||||
ensResolution: ZERO_ADDRESS,
|
||||
ensResolution: recipient,
|
||||
ensFailure: true,
|
||||
hoverText: reason.message,
|
||||
})
|
||||
toError: null,
|
||||
}
|
||||
if (isValidENSAddress(recipient) && reason.message === 'ENS name not defined.') {
|
||||
setStateObj.hoverText = this.context.t('ensNameNotFound')
|
||||
setStateObj.toError = 'ensNameNotFound'
|
||||
setStateObj.ensFailure = false
|
||||
} else {
|
||||
log.error(reason)
|
||||
setStateObj.hoverText = reason.message
|
||||
}
|
||||
|
||||
return this.setState(setStateObj)
|
||||
})
|
||||
}
|
||||
|
||||
@ -105,9 +119,14 @@ EnsInput.prototype.componentDidUpdate = function (prevProps, prevState) {
|
||||
// If an address is sent without a nickname, meaning not from ENS or from
|
||||
// the user's own accounts, a default of a one-space string is used.
|
||||
const nickname = state.nickname || ' '
|
||||
if (prevProps.network !== this.props.network) {
|
||||
const provider = global.ethereumProvider
|
||||
this.ens = new ENS({ provider, network: this.props.network })
|
||||
this.onChange(ensResolution)
|
||||
}
|
||||
if (prevState && ensResolution && this.props.onChange &&
|
||||
ensResolution !== prevState.ensResolution) {
|
||||
this.props.onChange(ensResolution, nickname)
|
||||
this.props.onChange({ toAddress: ensResolution, nickname, toError: state.toError })
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,7 +143,9 @@ EnsInput.prototype.ensIcon = function (recipient) {
|
||||
}
|
||||
|
||||
EnsInput.prototype.ensIconContents = function (recipient) {
|
||||
const { loadingEns, ensFailure, ensResolution } = this.state || { ensResolution: ZERO_ADDRESS}
|
||||
const { loadingEns, ensFailure, ensResolution, toError } = this.state || { ensResolution: ZERO_ADDRESS }
|
||||
|
||||
if (toError) return
|
||||
|
||||
if (loadingEns) {
|
||||
return h('img', {
|
||||
|
@ -19,9 +19,9 @@ export default class SendToRow extends Component {
|
||||
updateSendToError: PropTypes.func,
|
||||
};
|
||||
|
||||
handleToChange (to, nickname = '') {
|
||||
handleToChange (to, nickname = '', toError) {
|
||||
const { updateSendTo, updateSendToError, updateGas } = this.props
|
||||
const toErrorObject = getToErrorObject(to)
|
||||
const toErrorObject = getToErrorObject(to, toError)
|
||||
updateSendTo(to, nickname)
|
||||
updateSendToError(toErrorObject)
|
||||
if (toErrorObject.to === null) {
|
||||
@ -53,7 +53,7 @@ export default class SendToRow extends Component {
|
||||
inError={inError}
|
||||
name={'address'}
|
||||
network={network}
|
||||
onChange={(newTo, newNickname) => this.handleToChange(newTo, newNickname)}
|
||||
onChange={({ toAddress, nickname, toError }) => this.handleToChange(toAddress, nickname, toError)}
|
||||
openDropdown={() => openToDropdown()}
|
||||
placeholder={this.context.t('recipientAddress')}
|
||||
to={to}
|
||||
|
@ -4,12 +4,10 @@ const {
|
||||
} = require('../../send.constants')
|
||||
const { isValidAddress } = require('../../../../util')
|
||||
|
||||
function getToErrorObject (to) {
|
||||
let toError = null
|
||||
|
||||
function getToErrorObject (to, toError = null) {
|
||||
if (!to) {
|
||||
toError = REQUIRED_ERROR
|
||||
} else if (!isValidAddress(to)) {
|
||||
} else if (!isValidAddress(to) && !toError) {
|
||||
toError = INVALID_RECIPIENT_ADDRESS_ERROR
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,8 @@ import proxyquire from 'proxyquire'
|
||||
|
||||
const SendToRow = proxyquire('../send-to-row.component.js', {
|
||||
'./send-to-row.utils.js': {
|
||||
getToErrorObject: (to) => ({
|
||||
to: to === false ? null : `mockToErrorObject:${to}`,
|
||||
getToErrorObject: (to, toError) => ({
|
||||
to: to === false ? null : `mockToErrorObject:${to}${toError}`,
|
||||
}),
|
||||
},
|
||||
}).default
|
||||
@ -67,11 +67,11 @@ describe('SendToRow Component', function () {
|
||||
|
||||
it('should call updateSendToError', () => {
|
||||
assert.equal(propsMethodSpies.updateSendToError.callCount, 0)
|
||||
instance.handleToChange('mockTo2')
|
||||
instance.handleToChange('mockTo2', '', 'mockToError')
|
||||
assert.equal(propsMethodSpies.updateSendToError.callCount, 1)
|
||||
assert.deepEqual(
|
||||
propsMethodSpies.updateSendToError.getCall(0).args,
|
||||
[{ to: 'mockToErrorObject:mockTo2' }]
|
||||
[{ to: 'mockToErrorObject:mockTo2mockToError' }]
|
||||
)
|
||||
})
|
||||
|
||||
@ -138,11 +138,11 @@ describe('SendToRow Component', function () {
|
||||
openDropdown()
|
||||
assert.equal(propsMethodSpies.openToDropdown.callCount, 1)
|
||||
assert.equal(SendToRow.prototype.handleToChange.callCount, 0)
|
||||
onChange('mockNewTo', 'mockNewNickname')
|
||||
onChange({ toAddress: 'mockNewTo', nickname: 'mockNewNickname', toError: 'mockToError' })
|
||||
assert.equal(SendToRow.prototype.handleToChange.callCount, 1)
|
||||
assert.deepEqual(
|
||||
SendToRow.prototype.handleToChange.getCall(0).args,
|
||||
['mockNewTo', 'mockNewNickname']
|
||||
['mockNewTo', 'mockNewNickname', 'mockToError']
|
||||
)
|
||||
})
|
||||
})
|
||||
|
@ -40,6 +40,12 @@ describe('send-to-row utils', () => {
|
||||
to: null,
|
||||
})
|
||||
})
|
||||
|
||||
it('should return the passed error if to is truthy but invalid if to is truthy and valid', () => {
|
||||
assert.deepEqual(getToErrorObject('invalid #$ 345878', 'someExplicitError'), {
|
||||
to: 'someExplicitError',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -36,6 +36,7 @@ module.exports = {
|
||||
miniAddressSummary: miniAddressSummary,
|
||||
isAllOneCase: isAllOneCase,
|
||||
isValidAddress: isValidAddress,
|
||||
isValidENSAddress,
|
||||
numericBalance: numericBalance,
|
||||
parseBalance: parseBalance,
|
||||
formatBalance: formatBalance,
|
||||
@ -87,6 +88,10 @@ function isValidAddress (address) {
|
||||
return (isAllOneCase(prefixed) && ethUtil.isValidAddress(prefixed)) || ethUtil.isValidChecksumAddress(prefixed)
|
||||
}
|
||||
|
||||
function isValidENSAddress (address) {
|
||||
return address.match(/^.{7,}\.(eth|test)$/)
|
||||
}
|
||||
|
||||
function isInvalidChecksumAddress (address) {
|
||||
var prefixed = ethUtil.addHexPrefix(address)
|
||||
if (address === '0x0000000000000000000000000000000000000000') return false
|
||||
|
Loading…
Reference in New Issue
Block a user