1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-30 16:18:07 +01:00
metamask-extension/ui/app/components/ens-input.js

172 lines
4.8 KiB
JavaScript
Raw Normal View History

const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const extend = require('xtend')
const debounce = require('debounce')
const copyToClipboard = require('copy-to-clipboard')
const ENS = require('ethjs-ens')
2017-05-09 20:28:39 +02:00
const networkMap = require('ethjs-ens/lib/network-map.json')
const ensRE = /.+\..+$/
2017-06-13 22:38:27 +02:00
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
const connect = require('../metamask-connect')
module.exports = connect()(EnsInput)
inherits(EnsInput, Component)
function EnsInput () {
Component.call(this)
}
EnsInput.prototype.render = function () {
const props = this.props
const opts = extend(props, {
2017-03-09 20:31:00 +01:00
list: 'addresses',
onChange: () => {
const network = this.props.network
2017-05-09 20:28:39 +02:00
const networkHasEnsSupport = getNetworkEnsSupport(network)
if (!networkHasEnsSupport) return
const recipient = document.querySelector('input[name="address"]').value
if (recipient.match(ensRE) === null) {
return this.setState({
loadingEns: false,
ensResolution: null,
ensFailure: null,
})
}
this.setState({
loadingEns: true,
})
this.checkName()
},
})
return h('div', {
style: { width: '100%' },
}, [
h('input.large-input.send-screen-input', opts),
2017-03-10 18:34:13 +01:00
// The address book functionality.
2017-03-14 22:04:52 +01:00
h('datalist#addresses',
2017-03-09 20:31:00 +01:00
[
2017-03-10 18:34:13 +01:00
// Corresponds to the addresses owned.
2017-03-09 20:31:00 +01:00
Object.keys(props.identities).map((key) => {
2017-04-27 06:05:45 +02:00
const identity = props.identities[key]
return h('option', {
value: identity.address,
label: identity.name,
key: identity.address,
})
2017-03-09 20:31:00 +01:00
}),
2017-03-10 18:34:13 +01:00
// Corresponds to previously sent-to addresses.
props.addressBook.map((identity) => {
return h('option', {
value: identity.address,
label: identity.name,
key: identity.address,
})
}),
2017-03-09 20:31:00 +01:00
]),
this.ensIcon(),
])
}
EnsInput.prototype.componentDidMount = function () {
const network = this.props.network
2017-05-09 20:28:39 +02:00
const networkHasEnsSupport = getNetworkEnsSupport(network)
2017-06-13 22:38:27 +02:00
this.setState({ ensResolution: ZERO_ADDRESS })
2017-05-09 20:28:39 +02:00
if (networkHasEnsSupport) {
2017-05-08 21:29:08 +02:00
const provider = global.ethereumProvider
this.ens = new ENS({ provider, network })
this.checkName = debounce(this.lookupEnsName.bind(this), 200)
}
}
EnsInput.prototype.lookupEnsName = function () {
const recipient = document.querySelector('input[name="address"]').value
const { ensResolution } = this.state
log.info(`ENS attempting to resolve name: ${recipient}`)
this.ens.lookup(recipient.trim())
.then((address) => {
if (address === ZERO_ADDRESS) throw new Error(this.props.t('noAddressForName'))
if (address !== ensResolution) {
this.setState({
loadingEns: false,
ensResolution: address,
nickname: recipient.trim(),
hoverText: address + '\n' + this.props.t('clickCopy'),
2017-06-05 22:00:15 +02:00
ensFailure: false,
})
}
})
.catch((reason) => {
log.error(reason)
return this.setState({
loadingEns: false,
2017-06-13 22:38:27 +02:00
ensResolution: ZERO_ADDRESS,
ensFailure: true,
hoverText: reason.message,
})
})
}
EnsInput.prototype.componentDidUpdate = function (prevProps, prevState) {
const state = this.state || {}
const ensResolution = state.ensResolution
2017-03-10 18:34:13 +01:00
// 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 (prevState && ensResolution && this.props.onChange &&
ensResolution !== prevState.ensResolution) {
this.props.onChange(ensResolution, nickname)
}
}
EnsInput.prototype.ensIcon = function (recipient) {
const { hoverText } = this.state || {}
return h('span.#ensIcon', {
title: hoverText,
style: {
position: 'absolute',
padding: '9px',
transform: 'translatex(-40px)',
},
}, this.ensIconContents(recipient))
}
EnsInput.prototype.ensIconContents = function (recipient) {
2017-06-13 22:38:27 +02:00
const { loadingEns, ensFailure, ensResolution } = this.state || { ensResolution: ZERO_ADDRESS}
if (loadingEns) {
return h('img', {
src: 'images/loading.svg',
style: {
width: '30px',
height: '30px',
transform: 'translateY(-6px)',
},
})
}
if (ensFailure) {
return h('i.fa.fa-warning.fa-lg.warning')
}
2017-06-13 22:38:27 +02:00
if (ensResolution && (ensResolution !== ZERO_ADDRESS)) {
return h('i.fa.fa-check-circle.fa-lg.cursor-pointer', {
style: { color: 'green' },
onClick: (event) => {
event.preventDefault()
event.stopPropagation()
copyToClipboard(ensResolution)
},
})
}
}
2017-05-09 20:28:39 +02:00
2017-05-16 00:22:49 +02:00
function getNetworkEnsSupport (network) {
2017-05-09 20:28:39 +02:00
return Boolean(networkMap[network])
2017-05-16 00:22:49 +02:00
}