aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan J Miller <danjm.com@gmail.com>2018-06-28 03:39:44 +0800
committerGitHub <noreply@github.com>2018-06-28 03:39:44 +0800
commit1839ab53461913716d573a54511a408eb7865077 (patch)
treeae3a080754f2a29e9dde278d09efabf79fe4e5c1
parent60feeb393be5d84679dd7b94dba58540ffa166bd (diff)
parent97a7bc48947000163990be081058c6a6a3cddcad (diff)
downloadtangerine-wallet-browser-1839ab53461913716d573a54511a408eb7865077.tar
tangerine-wallet-browser-1839ab53461913716d573a54511a408eb7865077.tar.gz
tangerine-wallet-browser-1839ab53461913716d573a54511a408eb7865077.tar.bz2
tangerine-wallet-browser-1839ab53461913716d573a54511a408eb7865077.tar.lz
tangerine-wallet-browser-1839ab53461913716d573a54511a408eb7865077.tar.xz
tangerine-wallet-browser-1839ab53461913716d573a54511a408eb7865077.tar.zst
tangerine-wallet-browser-1839ab53461913716d573a54511a408eb7865077.zip
Merge pull request #4574 from MetaMask/i4409-i4410-ens-input-enhancements
[new-ui] Improve ENS input errors and update ens validation on network change
-rw-r--r--app/_locales/en/messages.json3
-rw-r--r--ui/app/components/ens-input.js77
-rw-r--r--ui/app/components/send_/send-content/send-to-row/send-to-row.component.js6
-rw-r--r--ui/app/components/send_/send-content/send-to-row/send-to-row.utils.js6
-rw-r--r--ui/app/components/send_/send-content/send-to-row/tests/send-to-row-component.test.js12
-rw-r--r--ui/app/components/send_/send-content/send-to-row/tests/send-to-row-utils.test.js6
-rw-r--r--ui/app/util.js5
7 files changed, 74 insertions, 41 deletions
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index 2579da87d..46fbdc1a7 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -265,6 +265,9 @@
"encryptNewDen": {
"message": "Encrypt your new DEN"
},
+ "ensNameNotFound": {
+ "message": "ENS name not found"
+ },
"enterPassword": {
"message": "Enter password"
},
diff --git a/ui/app/components/ens-input.js b/ui/app/components/ens-input.js
index aff4b6ef6..292dcdde6 100644
--- a/ui/app/components/ens-input.js
+++ b/ui/app/components/ens-input.js
@@ -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.render = function () {
- const props = this.props
- const opts = extend(props, {
- list: 'addresses',
- onChange: (recipient) => {
- const network = this.props.network
- const networkHasEnsSupport = getNetworkEnsSupport(network)
+EnsInput.prototype.onChange = function (recipient) {
+ const network = this.props.network
+ const networkHasEnsSupport = getNetworkEnsSupport(network)
- props.onChange(recipient)
+ this.props.onChange({ toAddress: recipient })
- if (!networkHasEnsSupport) return
+ if (!networkHasEnsSupport) return
- if (recipient.match(ensRE) === null) {
- return this.setState({
- loadingEns: false,
- ensResolution: null,
- ensFailure: null,
- })
- }
+ if (recipient.match(ensRE) === null) {
+ return this.setState({
+ loadingEns: false,
+ ensResolution: null,
+ ensFailure: null,
+ toError: null,
+ })
+ }
- this.setState({
- loadingEns: true,
- })
- this.checkName(recipient)
- },
+ this.setState({
+ loadingEns: true,
+ })
+ this.checkName(recipient)
+}
+
+EnsInput.prototype.render = function () {
+ const props = this.props
+ const opts = extend(props, {
+ list: 'addresses',
+ 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', {
diff --git a/ui/app/components/send_/send-content/send-to-row/send-to-row.component.js b/ui/app/components/send_/send-content/send-to-row/send-to-row.component.js
index 0a83186a5..1c2ecdf9c 100644
--- a/ui/app/components/send_/send-content/send-to-row/send-to-row.component.js
+++ b/ui/app/components/send_/send-content/send-to-row/send-to-row.component.js
@@ -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}
diff --git a/ui/app/components/send_/send-content/send-to-row/send-to-row.utils.js b/ui/app/components/send_/send-content/send-to-row/send-to-row.utils.js
index cea51ee20..6b90a9f09 100644
--- a/ui/app/components/send_/send-content/send-to-row/send-to-row.utils.js
+++ b/ui/app/components/send_/send-content/send-to-row/send-to-row.utils.js
@@ -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
}
diff --git a/ui/app/components/send_/send-content/send-to-row/tests/send-to-row-component.test.js b/ui/app/components/send_/send-content/send-to-row/tests/send-to-row-component.test.js
index 58fe51dcf..781371004 100644
--- a/ui/app/components/send_/send-content/send-to-row/tests/send-to-row-component.test.js
+++ b/ui/app/components/send_/send-content/send-to-row/tests/send-to-row-component.test.js
@@ -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']
)
})
})
diff --git a/ui/app/components/send_/send-content/send-to-row/tests/send-to-row-utils.test.js b/ui/app/components/send_/send-content/send-to-row/tests/send-to-row-utils.test.js
index 615c9581b..4d2447c32 100644
--- a/ui/app/components/send_/send-content/send-to-row/tests/send-to-row-utils.test.js
+++ b/ui/app/components/send_/send-content/send-to-row/tests/send-to-row-utils.test.js
@@ -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',
+ })
+ })
})
})
diff --git a/ui/app/util.js b/ui/app/util.js
index 1ccd17ba7..8c85c5926 100644
--- a/ui/app/util.js
+++ b/ui/app/util.js
@@ -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