mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge pull request #1197 from MetaMask/i1130-ResolveENS
Allow ENS Names in Send Form
This commit is contained in:
commit
e602cb13c5
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
## Current Master
|
## Current Master
|
||||||
|
|
||||||
|
- Allow sending to ENS names in send form on Ropsten.
|
||||||
|
|
||||||
## 3.4.0 2017-3-8
|
## 3.4.0 2017-3-8
|
||||||
|
|
||||||
- Add two most recently used custom RPCs to network dropdown menu.
|
- Add two most recently used custom RPCs to network dropdown menu.
|
||||||
|
@ -2,73 +2,108 @@
|
|||||||
"metamask": {
|
"metamask": {
|
||||||
"isInitialized": true,
|
"isInitialized": true,
|
||||||
"isUnlocked": true,
|
"isUnlocked": true,
|
||||||
"currentDomain": "example.com",
|
|
||||||
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
"rpcTarget": "https://rawtestrpc.metamask.io/",
|
||||||
"identities": {
|
"identities": {
|
||||||
"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": {
|
"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": {
|
||||||
"name": "Wallet 1",
|
|
||||||
"address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825",
|
"address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825",
|
||||||
"mayBeFauceting": false
|
"name": "Account 1"
|
||||||
},
|
},
|
||||||
"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": {
|
"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": {
|
||||||
"name": "Wallet 2",
|
|
||||||
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||||
"mayBeFauceting": false
|
"name": "Account 2"
|
||||||
},
|
},
|
||||||
"0x2f8d4a878cfa04a6e60d46362f5644deab66572d": {
|
"0x2f8d4a878cfa04a6e60d46362f5644deab66572d": {
|
||||||
"name": "Wallet 3",
|
|
||||||
"address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d",
|
"address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d",
|
||||||
"mayBeFauceting": false
|
"name": "Account 3"
|
||||||
|
},
|
||||||
|
"0xd85a4b6a394794842887b8284293d69163007bbb": {
|
||||||
|
"address": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||||
|
"name": "Account 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"unconfTxs": {},
|
"unapprovedTxs": {},
|
||||||
"currentFiat": "USD",
|
"currentFiat": "USD",
|
||||||
"conversionRate": 11.21283484,
|
"conversionRate": 16.88200327,
|
||||||
"conversionDate": 1472158984,
|
"conversionDate": 1489013762,
|
||||||
|
"noActiveNotices": true,
|
||||||
|
"frequentRpcList": [],
|
||||||
|
"network": "3",
|
||||||
"accounts": {
|
"accounts": {
|
||||||
"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": {
|
"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825": {
|
||||||
"code": "0x",
|
"code": "0x",
|
||||||
"balance": "0x34693f54a1e25900",
|
"balance": "0x47c9d71831c76efe",
|
||||||
"nonce": "0x100013",
|
"nonce": "0x1b",
|
||||||
"address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"
|
"address": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"
|
||||||
},
|
},
|
||||||
"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": {
|
"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb": {
|
||||||
"code": "0x",
|
"code": "0x",
|
||||||
"nonce": "0x100000",
|
"balance": "0x37452b1315889f80",
|
||||||
"balance": "0x18af912cee770000",
|
"nonce": "0xa",
|
||||||
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"
|
"address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"
|
||||||
},
|
},
|
||||||
"0x2f8d4a878cfa04a6e60d46362f5644deab66572d": {
|
"0x2f8d4a878cfa04a6e60d46362f5644deab66572d": {
|
||||||
"code": "0x",
|
"code": "0x",
|
||||||
"nonce": "0x100000",
|
"balance": "0x0",
|
||||||
"balance": "0x2386f26fc10000",
|
"nonce": "0x0",
|
||||||
"address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d"
|
"address": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d"
|
||||||
|
},
|
||||||
|
"0xd85a4b6a394794842887b8284293d69163007bbb": {
|
||||||
|
"code": "0x",
|
||||||
|
"balance": "0x0",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"address": "0xd85a4b6a394794842887b8284293d69163007bbb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"transactions": [],
|
"transactions": {},
|
||||||
"network": "2",
|
"selectedAddressTxList": [],
|
||||||
"seedWords": null,
|
"unapprovedMsgs": {},
|
||||||
"unconfMsgs": {},
|
"unapprovedMsgCount": 0,
|
||||||
"messages": [],
|
"unapprovedPersonalMsgs": {},
|
||||||
"shapeShiftTxList": [],
|
"unapprovedPersonalMsgCount": 0,
|
||||||
|
"keyringTypes": [
|
||||||
|
"Simple Key Pair",
|
||||||
|
"HD Key Tree"
|
||||||
|
],
|
||||||
|
"keyrings": [
|
||||||
|
{
|
||||||
|
"type": "HD Key Tree",
|
||||||
|
"accounts": [
|
||||||
|
"fdea65c8e26263f6d9a1b5de9555d2931a33b825",
|
||||||
|
"c5b8dbac4c1d3f152cdeb400e2313f309c410acb",
|
||||||
|
"2f8d4a878cfa04a6e60d46362f5644deab66572d"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Simple Key Pair",
|
||||||
|
"accounts": [
|
||||||
|
"0xd85a4b6a394794842887b8284293d69163007bbb"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"selectedAddress": "0xd85a4b6a394794842887b8284293d69163007bbb",
|
||||||
|
"currentCurrency": "USD",
|
||||||
"provider": {
|
"provider": {
|
||||||
"type": "testnet"
|
"type": "testnet"
|
||||||
},
|
},
|
||||||
"selectedAddress": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"
|
"shapeShiftTxList": [],
|
||||||
|
"lostAccounts": []
|
||||||
},
|
},
|
||||||
"appState": {
|
"appState": {
|
||||||
"menuOpen": false,
|
"menuOpen": false,
|
||||||
"currentView": {
|
"currentView": {
|
||||||
"name": "sendTransaction"
|
"name": "sendTransaction",
|
||||||
|
"context": "0xd85a4b6a394794842887b8284293d69163007bbb"
|
||||||
},
|
},
|
||||||
"accountDetail": {
|
"accountDetail": {
|
||||||
"subview": "transactions"
|
"subview": "transactions",
|
||||||
|
"accountExport": "none",
|
||||||
|
"privateKey": ""
|
||||||
},
|
},
|
||||||
"currentDomain": "127.0.0.1:9966",
|
|
||||||
"transForward": true,
|
"transForward": true,
|
||||||
"isLoading": false,
|
"isLoading": false,
|
||||||
"warning": null,
|
"warning": null,
|
||||||
"detailView": {}
|
"scrollToBottom": false,
|
||||||
|
"forgottenPassword": null
|
||||||
},
|
},
|
||||||
"identities": {}
|
"identities": {}
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
"ethereumjs-tx": "^1.0.0",
|
"ethereumjs-tx": "^1.0.0",
|
||||||
"ethereumjs-util": "ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9",
|
"ethereumjs-util": "ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9",
|
||||||
"ethereumjs-wallet": "^0.6.0",
|
"ethereumjs-wallet": "^0.6.0",
|
||||||
|
"ethjs-ens": "^1.0.2",
|
||||||
"express": "^4.14.0",
|
"express": "^4.14.0",
|
||||||
"extension-link-enabler": "^1.0.0",
|
"extension-link-enabler": "^1.0.0",
|
||||||
"extensionizer": "^1.0.0",
|
"extensionizer": "^1.0.0",
|
||||||
|
145
ui/app/components/ens-input.js
Normal file
145
ui/app/components/ens-input.js
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
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')
|
||||||
|
const ensRE = /.+\.eth$/
|
||||||
|
|
||||||
|
const networkResolvers = {
|
||||||
|
'3': '112234455c3a32fd11230c42e7bccd4a84e02010',
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = EnsInput
|
||||||
|
|
||||||
|
inherits(EnsInput, Component)
|
||||||
|
function EnsInput () {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsInput.prototype.render = function () {
|
||||||
|
const props = this.props
|
||||||
|
const opts = extend(props, {
|
||||||
|
onChange: () => {
|
||||||
|
const network = this.props.network
|
||||||
|
let resolverAddress = networkResolvers[network]
|
||||||
|
if (!resolverAddress) 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', opts),
|
||||||
|
this.ensIcon(),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsInput.prototype.componentDidMount = function () {
|
||||||
|
const network = this.props.network
|
||||||
|
let resolverAddress = networkResolvers[network]
|
||||||
|
|
||||||
|
if (resolverAddress) {
|
||||||
|
const provider = web3.currentProvider
|
||||||
|
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
|
||||||
|
|
||||||
|
if (!this.ens) {
|
||||||
|
return this.setState({
|
||||||
|
loadingEns: false,
|
||||||
|
ensFailure: true,
|
||||||
|
hoverText: 'ENS is not supported on your current network.',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info(`ENS attempting to resolve name: ${recipient}`)
|
||||||
|
this.ens.lookup(recipient.trim())
|
||||||
|
.then((address) => {
|
||||||
|
if (address !== ensResolution) {
|
||||||
|
this.setState({
|
||||||
|
loadingEns: false,
|
||||||
|
ensResolution: address,
|
||||||
|
hoverText: address + '\nClick to Copy',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((reason) => {
|
||||||
|
return this.setState({
|
||||||
|
loadingEns: false,
|
||||||
|
ensFailure: true,
|
||||||
|
hoverText: reason.message,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsInput.prototype.componentDidUpdate = function (prevProps, prevState) {
|
||||||
|
const state = this.state || {}
|
||||||
|
const { ensResolution } = state
|
||||||
|
if (ensResolution && this.props.onChange &&
|
||||||
|
ensResolution !== prevState.ensResolution) {
|
||||||
|
this.props.onChange(ensResolution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsInput.prototype.ensIcon = function (recipient) {
|
||||||
|
const { hoverText } = this.state || {}
|
||||||
|
return h('span', {
|
||||||
|
title: hoverText,
|
||||||
|
style: {
|
||||||
|
position: 'absolute',
|
||||||
|
padding: '9px',
|
||||||
|
transform: 'translatex(-40px)',
|
||||||
|
},
|
||||||
|
}, this.ensIconContents(recipient))
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsInput.prototype.ensIconContents = function (recipient) {
|
||||||
|
const { loadingEns, ensFailure, ensResolution } = this.state || {}
|
||||||
|
|
||||||
|
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')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ensResolution) {
|
||||||
|
return h('i.fa.fa-check-circle.fa-lg.cursor-pointer', {
|
||||||
|
style: { color: 'green' },
|
||||||
|
onClick: (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
copyToClipboard(ensResolution)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -49,7 +49,7 @@ ConfirmTxScreen.prototype.render = function () {
|
|||||||
var isNotification = isPopupOrNotification() === 'notification'
|
var isNotification = isPopupOrNotification() === 'notification'
|
||||||
|
|
||||||
log.info(`rendering a combined ${unconfTxList.length} unconf msg & txs`)
|
log.info(`rendering a combined ${unconfTxList.length} unconf msg & txs`)
|
||||||
if (unconfTxList.length === 0) return h(Loading)
|
if (unconfTxList.length === 0) return h(Loading, { isLoading: true })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ const numericBalance = require('./util').numericBalance
|
|||||||
const addressSummary = require('./util').addressSummary
|
const addressSummary = require('./util').addressSummary
|
||||||
const isHex = require('./util').isHex
|
const isHex = require('./util').isHex
|
||||||
const EthBalance = require('./components/eth-balance')
|
const EthBalance = require('./components/eth-balance')
|
||||||
|
const EnsInput = require('./components/ens-input')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
module.exports = connect(mapStateToProps)(SendTransactionScreen)
|
module.exports = connect(mapStateToProps)(SendTransactionScreen)
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ function mapStateToProps (state) {
|
|||||||
accounts: state.metamask.accounts,
|
accounts: state.metamask.accounts,
|
||||||
identities: state.metamask.identities,
|
identities: state.metamask.identities,
|
||||||
warning: state.appState.warning,
|
warning: state.appState.warning,
|
||||||
|
network: state.metamask.network,
|
||||||
}
|
}
|
||||||
|
|
||||||
result.error = result.warning && result.warning.split('.')[0]
|
result.error = result.warning && result.warning.split('.')[0]
|
||||||
@ -41,6 +43,7 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
var address = state.address
|
var address = state.address
|
||||||
var account = state.account
|
var account = state.account
|
||||||
var identity = state.identity
|
var identity = state.identity
|
||||||
|
var network = state.network
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
@ -145,12 +148,11 @@ SendTransactionScreen.prototype.render = function () {
|
|||||||
|
|
||||||
// 'to' field
|
// 'to' field
|
||||||
h('section.flex-row.flex-center', [
|
h('section.flex-row.flex-center', [
|
||||||
h('input.large-input', {
|
h(EnsInput, {
|
||||||
name: 'address',
|
name: 'address',
|
||||||
placeholder: 'Recipient Address',
|
placeholder: 'Recipient Address',
|
||||||
dataset: {
|
onChange: this.recipientDidChange.bind(this),
|
||||||
persistentFormId: 'recipient-address',
|
network,
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
@ -220,8 +222,13 @@ SendTransactionScreen.prototype.back = function () {
|
|||||||
this.props.dispatch(actions.backToAccountDetail(address))
|
this.props.dispatch(actions.backToAccountDetail(address))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SendTransactionScreen.prototype.recipientDidChange = function (recipient) {
|
||||||
|
this.setState({ recipient })
|
||||||
|
}
|
||||||
|
|
||||||
SendTransactionScreen.prototype.onSubmit = function () {
|
SendTransactionScreen.prototype.onSubmit = function () {
|
||||||
const recipient = document.querySelector('input[name="address"]').value
|
const state = this.state || {}
|
||||||
|
const recipient = state.recipient || document.querySelector('input[name="address"]').value
|
||||||
const input = document.querySelector('input[name="amount"]').value
|
const input = document.querySelector('input[name="amount"]').value
|
||||||
const value = util.normalizeEthStringToWei(input)
|
const value = util.normalizeEthStringToWei(input)
|
||||||
const txData = document.querySelector('input[name="txData"]').value
|
const txData = document.querySelector('input[name="txData"]').value
|
||||||
|
Loading…
Reference in New Issue
Block a user