mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
ENS Reverse Resolution support (#7177)
* ENS Reverse Resolution support * Save punycode for ENS domains with Unicode characters * Update SenderToRecipient recipientEns tooltip * Use cached results when reverse-resolving ENS names * Display ENS names in tx activity log
This commit is contained in:
parent
f9cd775eae
commit
eed4a9ed65
25
app/scripts/controllers/ens/ens.js
Normal file
25
app/scripts/controllers/ens/ens.js
Normal file
@ -0,0 +1,25 @@
|
||||
const EthJsEns = require('ethjs-ens')
|
||||
const ensNetworkMap = require('ethjs-ens/lib/network-map.json')
|
||||
|
||||
class Ens {
|
||||
static getNetworkEnsSupport (network) {
|
||||
return Boolean(ensNetworkMap[network])
|
||||
}
|
||||
|
||||
constructor ({ network, provider } = {}) {
|
||||
this._ethJsEns = new EthJsEns({
|
||||
network,
|
||||
provider,
|
||||
})
|
||||
}
|
||||
|
||||
lookup (ensName) {
|
||||
return this._ethJsEns.lookup(ensName)
|
||||
}
|
||||
|
||||
reverse (address) {
|
||||
return this._ethJsEns.reverse(address)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Ens
|
75
app/scripts/controllers/ens/index.js
Normal file
75
app/scripts/controllers/ens/index.js
Normal file
@ -0,0 +1,75 @@
|
||||
const ethUtil = require('ethereumjs-util')
|
||||
const ObservableStore = require('obs-store')
|
||||
const punycode = require('punycode')
|
||||
const Ens = require('./ens')
|
||||
|
||||
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
||||
const ZERO_X_ERROR_ADDRESS = '0x'
|
||||
|
||||
class EnsController {
|
||||
constructor ({ ens, provider, networkStore } = {}) {
|
||||
const initState = {
|
||||
ensResolutionsByAddress: {},
|
||||
}
|
||||
|
||||
this._ens = ens
|
||||
if (!this._ens) {
|
||||
const network = networkStore.getState()
|
||||
if (Ens.getNetworkEnsSupport(network)) {
|
||||
this._ens = new Ens({
|
||||
network,
|
||||
provider,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.store = new ObservableStore(initState)
|
||||
networkStore.subscribe((network) => {
|
||||
this.store.putState(initState)
|
||||
this._ens = new Ens({
|
||||
network,
|
||||
provider,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
reverseResolveAddress (address) {
|
||||
return this._reverseResolveAddress(ethUtil.toChecksumAddress(address))
|
||||
}
|
||||
|
||||
async _reverseResolveAddress (address) {
|
||||
if (!this._ens) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const state = this.store.getState()
|
||||
if (state.ensResolutionsByAddress[address]) {
|
||||
return state.ensResolutionsByAddress[address]
|
||||
}
|
||||
|
||||
const domain = await this._ens.reverse(address)
|
||||
const registeredAddress = await this._ens.lookup(domain)
|
||||
if (registeredAddress === ZERO_ADDRESS || registeredAddress === ZERO_X_ERROR_ADDRESS) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
if (ethUtil.toChecksumAddress(registeredAddress) !== address) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
this._updateResolutionsByAddress(address, punycode.toASCII(domain))
|
||||
return domain
|
||||
}
|
||||
|
||||
_updateResolutionsByAddress (address, domain) {
|
||||
const oldState = this.store.getState()
|
||||
this.store.putState({
|
||||
ensResolutionsByAddress: {
|
||||
...oldState.ensResolutionsByAddress,
|
||||
[address]: domain,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EnsController
|
@ -23,6 +23,7 @@ const createLoggerMiddleware = require('./lib/createLoggerMiddleware')
|
||||
const providerAsMiddleware = require('eth-json-rpc-middleware/providerAsMiddleware')
|
||||
const {setupMultiplex} = require('./lib/stream-utils.js')
|
||||
const KeyringController = require('eth-keyring-controller')
|
||||
const EnsController = require('./controllers/ens')
|
||||
const NetworkController = require('./controllers/network')
|
||||
const PreferencesController = require('./controllers/preferences')
|
||||
const AppStateController = require('./controllers/app-state')
|
||||
@ -138,6 +139,11 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
networkController: this.networkController,
|
||||
})
|
||||
|
||||
this.ensController = new EnsController({
|
||||
provider: this.provider,
|
||||
networkStore: this.networkController.networkStore,
|
||||
})
|
||||
|
||||
this.incomingTransactionsController = new IncomingTransactionsController({
|
||||
blockTracker: this.blockTracker,
|
||||
networkController: this.networkController,
|
||||
@ -315,6 +321,8 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
// ThreeBoxController
|
||||
ThreeBoxController: this.threeBoxController.store,
|
||||
ABTestController: this.abTestController.store,
|
||||
// ENS Controller
|
||||
EnsController: this.ensController.store,
|
||||
})
|
||||
this.memStore.subscribe(this.sendUpdate.bind(this))
|
||||
}
|
||||
@ -501,6 +509,9 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
// AppStateController
|
||||
setLastActiveTime: nodeify(this.appStateController.setLastActiveTime, this.appStateController),
|
||||
|
||||
// EnsController
|
||||
tryReverseResolveAddress: nodeify(this.ensController.reverseResolveAddress, this.ensController),
|
||||
|
||||
// KeyringController
|
||||
setLocked: nodeify(this.setLocked, this),
|
||||
createNewVaultAndKeychain: nodeify(this.createNewVaultAndKeychain, this),
|
||||
|
@ -141,6 +141,7 @@
|
||||
"prop-types": "^15.6.1",
|
||||
"pubnub": "4.24.4",
|
||||
"pump": "^3.0.0",
|
||||
"punycode": "^2.1.1",
|
||||
"qrcode-generator": "1.4.1",
|
||||
"ramda": "^0.24.1",
|
||||
"react": "^15.6.2",
|
||||
|
135
test/unit/app/controllers/ens-controller-test.js
Normal file
135
test/unit/app/controllers/ens-controller-test.js
Normal file
@ -0,0 +1,135 @@
|
||||
const assert = require('assert')
|
||||
const sinon = require('sinon')
|
||||
const ObservableStore = require('obs-store')
|
||||
const HttpProvider = require('ethjs-provider-http')
|
||||
const EnsController = require('../../../../app/scripts/controllers/ens')
|
||||
|
||||
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
||||
const ZERO_X_ERROR_ADDRESS = '0x'
|
||||
|
||||
describe('EnsController', function () {
|
||||
describe('#constructor', function () {
|
||||
it('should construct the controller given a provider and a network', async () => {
|
||||
const provider = new HttpProvider('https://ropsten.infura.io')
|
||||
const currentNetworkId = '3'
|
||||
const networkStore = new ObservableStore(currentNetworkId)
|
||||
const ens = new EnsController({
|
||||
provider,
|
||||
networkStore,
|
||||
})
|
||||
|
||||
assert.ok(ens._ens)
|
||||
})
|
||||
|
||||
it('should construct the controller given an existing ENS instance', async () => {
|
||||
const networkStore = {
|
||||
subscribe: sinon.spy(),
|
||||
}
|
||||
const ens = new EnsController({
|
||||
ens: {},
|
||||
networkStore,
|
||||
})
|
||||
|
||||
assert.ok(ens._ens)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#reverseResolveName', function () {
|
||||
it('should resolve to an ENS name', async () => {
|
||||
const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'
|
||||
const networkStore = {
|
||||
subscribe: sinon.spy(),
|
||||
}
|
||||
const ens = new EnsController({
|
||||
ens: {
|
||||
reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'),
|
||||
lookup: sinon.stub().withArgs('peaksignal.eth').returns(address),
|
||||
},
|
||||
networkStore,
|
||||
})
|
||||
|
||||
const name = await ens.reverseResolveAddress(address)
|
||||
assert.equal(name, 'peaksignal.eth')
|
||||
})
|
||||
|
||||
it('should only resolve an ENS name once', async () => {
|
||||
const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'
|
||||
const reverse = sinon.stub().withArgs(address).returns('peaksignal.eth')
|
||||
const lookup = sinon.stub().withArgs('peaksignal.eth').returns(address)
|
||||
const networkStore = {
|
||||
subscribe: sinon.spy(),
|
||||
}
|
||||
const ens = new EnsController({
|
||||
ens: {
|
||||
reverse,
|
||||
lookup,
|
||||
},
|
||||
networkStore,
|
||||
})
|
||||
|
||||
assert.equal(await ens.reverseResolveAddress(address), 'peaksignal.eth')
|
||||
assert.equal(await ens.reverseResolveAddress(address), 'peaksignal.eth')
|
||||
assert.ok(lookup.calledOnce)
|
||||
assert.ok(reverse.calledOnce)
|
||||
})
|
||||
|
||||
it('should fail if the name is registered to a different address than the reverse-resolved', async () => {
|
||||
const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'
|
||||
const networkStore = {
|
||||
subscribe: sinon.spy(),
|
||||
}
|
||||
const ens = new EnsController({
|
||||
ens: {
|
||||
reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'),
|
||||
lookup: sinon.stub().withArgs('peaksignal.eth').returns('0xfoo'),
|
||||
},
|
||||
networkStore,
|
||||
})
|
||||
|
||||
const name = await ens.reverseResolveAddress(address)
|
||||
assert.strictEqual(name, undefined)
|
||||
})
|
||||
|
||||
it('should throw an error when the lookup resolves to the zero address', async () => {
|
||||
const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'
|
||||
const networkStore = {
|
||||
subscribe: sinon.spy(),
|
||||
}
|
||||
const ens = new EnsController({
|
||||
ens: {
|
||||
reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'),
|
||||
lookup: sinon.stub().withArgs('peaksignal.eth').returns(ZERO_ADDRESS),
|
||||
},
|
||||
networkStore,
|
||||
})
|
||||
|
||||
try {
|
||||
await ens.reverseResolveAddress(address)
|
||||
assert.fail('#reverseResolveAddress did not throw')
|
||||
} catch (e) {
|
||||
assert.ok(e)
|
||||
}
|
||||
})
|
||||
|
||||
it('should throw an error the lookup resolves to the zero x address', async () => {
|
||||
const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'
|
||||
const networkStore = {
|
||||
subscribe: sinon.spy(),
|
||||
}
|
||||
const ens = new EnsController({
|
||||
ens: {
|
||||
reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'),
|
||||
lookup: sinon.stub().withArgs('peaksignal.eth').returns(ZERO_X_ERROR_ADDRESS),
|
||||
},
|
||||
networkStore,
|
||||
})
|
||||
|
||||
try {
|
||||
await ens.reverseResolveAddress(address)
|
||||
assert.fail('#reverseResolveAddress did not throw')
|
||||
} catch (e) {
|
||||
assert.ok(e)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
@ -24,6 +24,7 @@ export default class ConfirmPageContainer extends Component {
|
||||
fromName: PropTypes.string,
|
||||
toAddress: PropTypes.string,
|
||||
toName: PropTypes.string,
|
||||
toEns: PropTypes.string,
|
||||
toNickname: PropTypes.string,
|
||||
// Content
|
||||
contentComponent: PropTypes.node,
|
||||
@ -69,6 +70,7 @@ export default class ConfirmPageContainer extends Component {
|
||||
fromName,
|
||||
fromAddress,
|
||||
toName,
|
||||
toEns,
|
||||
toNickname,
|
||||
toAddress,
|
||||
disabled,
|
||||
@ -128,6 +130,7 @@ export default class ConfirmPageContainer extends Component {
|
||||
senderAddress={fromAddress}
|
||||
recipientName={toName}
|
||||
recipientAddress={toAddress}
|
||||
recipientEns={toEns}
|
||||
recipientNickname={toNickname}
|
||||
assetImage={renderAssetImage ? assetImage : undefined}
|
||||
/>
|
||||
|
@ -1 +1 @@
|
||||
export { default } from './transaction-list-item-details.component'
|
||||
export { default } from './transaction-list-item-details.container'
|
||||
|
@ -17,6 +17,10 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
metricsEvent: PropTypes.func,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
recipientEns: null,
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
onCancel: PropTypes.func,
|
||||
onRetry: PropTypes.func,
|
||||
@ -26,7 +30,11 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
isEarliestNonce: PropTypes.bool,
|
||||
cancelDisabled: PropTypes.bool,
|
||||
transactionGroup: PropTypes.object,
|
||||
recipientEns: PropTypes.string,
|
||||
recipientAddress: PropTypes.string.isRequired,
|
||||
rpcPrefs: PropTypes.object,
|
||||
senderAddress: PropTypes.string.isRequired,
|
||||
tryReverseResolveAddress: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
state = {
|
||||
@ -82,6 +90,12 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
})
|
||||
}
|
||||
|
||||
async componentDidMount () {
|
||||
const { recipientAddress, tryReverseResolveAddress } = this.props
|
||||
|
||||
tryReverseResolveAddress(recipientAddress)
|
||||
}
|
||||
|
||||
renderCancel () {
|
||||
const { t } = this.context
|
||||
const {
|
||||
@ -128,11 +142,14 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
showRetry,
|
||||
onCancel,
|
||||
onRetry,
|
||||
recipientEns,
|
||||
recipientAddress,
|
||||
rpcPrefs: { blockExplorerUrl } = {},
|
||||
senderAddress,
|
||||
isEarliestNonce,
|
||||
} = this.props
|
||||
const { primaryTransaction: transaction } = transactionGroup
|
||||
const { hash, txParams: { to, from } = {} } = transaction
|
||||
const { hash } = transaction
|
||||
|
||||
return (
|
||||
<div className="transaction-list-item-details">
|
||||
@ -192,8 +209,9 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
<SenderToRecipient
|
||||
variant={FLAT_VARIANT}
|
||||
addressOnly
|
||||
recipientAddress={to}
|
||||
senderAddress={from}
|
||||
recipientEns={recipientEns}
|
||||
recipientAddress={recipientAddress}
|
||||
senderAddress={senderAddress}
|
||||
onRecipientClick={() => {
|
||||
this.context.metricsEvent({
|
||||
eventOpts: {
|
||||
|
@ -0,0 +1,28 @@
|
||||
import { connect } from 'react-redux'
|
||||
import TransactionListItemDetails from './transaction-list-item-details.component'
|
||||
import { checksumAddress } from '../../../helpers/utils/util'
|
||||
import { tryReverseResolveAddress } from '../../../store/actions'
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const { metamask } = state
|
||||
const {
|
||||
ensResolutionsByAddress,
|
||||
} = metamask
|
||||
const { recipientAddress } = ownProps
|
||||
const address = checksumAddress(recipientAddress)
|
||||
const recipientEns = ensResolutionsByAddress[address] || ''
|
||||
|
||||
return {
|
||||
recipientEns,
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
tryReverseResolveAddress: (address) => {
|
||||
return dispatch(tryReverseResolveAddress(address))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TransactionListItemDetails)
|
@ -191,6 +191,7 @@ export default class TransactionListItem extends PureComponent {
|
||||
} = this.props
|
||||
const { txParams = {} } = transaction
|
||||
const { showTransactionDetails } = this.state
|
||||
const fromAddress = txParams.from
|
||||
const toAddress = tokenData
|
||||
? tokenData.params && tokenData.params[0] && tokenData.params[0].value || txParams.to
|
||||
: txParams.to
|
||||
@ -253,6 +254,8 @@ export default class TransactionListItem extends PureComponent {
|
||||
showCancel={showCancel}
|
||||
cancelDisabled={!hasEnoughCancelGas}
|
||||
rpcPrefs={rpcPrefs}
|
||||
senderAddress={fromAddress}
|
||||
recipientAddress={toAddress}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
@ -5,7 +5,7 @@ import Identicon from '../identicon'
|
||||
import Tooltip from '../tooltip-v2'
|
||||
import copyToClipboard from 'copy-to-clipboard'
|
||||
import { DEFAULT_VARIANT, CARDS_VARIANT, FLAT_VARIANT } from './sender-to-recipient.constants'
|
||||
import { checksumAddress } from '../../../helpers/utils/util'
|
||||
import { checksumAddress, addressSlicer } from '../../../helpers/utils/util'
|
||||
|
||||
const variantHash = {
|
||||
[DEFAULT_VARIANT]: 'sender-to-recipient--default',
|
||||
@ -18,6 +18,7 @@ export default class SenderToRecipient extends PureComponent {
|
||||
senderName: PropTypes.string,
|
||||
senderAddress: PropTypes.string,
|
||||
recipientName: PropTypes.string,
|
||||
recipientEns: PropTypes.string,
|
||||
recipientAddress: PropTypes.string,
|
||||
recipientNickname: PropTypes.string,
|
||||
t: PropTypes.func,
|
||||
@ -60,14 +61,28 @@ export default class SenderToRecipient extends PureComponent {
|
||||
return (
|
||||
<Tooltip
|
||||
position="bottom"
|
||||
title={this.state.senderAddressCopied ? t('copiedExclamation') : t('copyAddress')}
|
||||
html={
|
||||
this.state.senderAddressCopied
|
||||
? <p>{t('copiedExclamation')}</p>
|
||||
: addressOnly
|
||||
? <p>{t('copyAddress')}</p>
|
||||
: (
|
||||
<p>
|
||||
{addressSlicer(checksummedSenderAddress)}<br/>
|
||||
{t('copyAddress')}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
wrapperClassName="sender-to-recipient__tooltip-wrapper"
|
||||
containerClassName="sender-to-recipient__tooltip-container"
|
||||
onHidden={() => this.setState({ senderAddressCopied: false })}
|
||||
>
|
||||
<div className="sender-to-recipient__name">
|
||||
<span>{ addressOnly ? `${t('from')}: ` : '' }</span>
|
||||
{ addressOnly ? checksummedSenderAddress : senderName }
|
||||
{
|
||||
addressOnly
|
||||
? <span>{`${t('from')}: ${checksummedSenderAddress}`}</span>
|
||||
: senderName
|
||||
}
|
||||
</div>
|
||||
</Tooltip>
|
||||
)
|
||||
@ -90,7 +105,7 @@ export default class SenderToRecipient extends PureComponent {
|
||||
|
||||
renderRecipientWithAddress () {
|
||||
const { t } = this.context
|
||||
const { recipientName, recipientAddress, recipientNickname, addressOnly, onRecipientClick } = this.props
|
||||
const { recipientEns, recipientName, recipientAddress, recipientNickname, addressOnly, onRecipientClick } = this.props
|
||||
const checksummedRecipientAddress = checksumAddress(recipientAddress)
|
||||
|
||||
return (
|
||||
@ -107,7 +122,18 @@ export default class SenderToRecipient extends PureComponent {
|
||||
{ this.renderRecipientIdenticon() }
|
||||
<Tooltip
|
||||
position="bottom"
|
||||
title={this.state.recipientAddressCopied ? t('copiedExclamation') : t('copyAddress')}
|
||||
html={
|
||||
this.state.senderAddressCopied
|
||||
? <p>{t('copiedExclamation')}</p>
|
||||
: (addressOnly && !recipientNickname && !recipientEns)
|
||||
? <p>{t('copyAddress')}</p>
|
||||
: (
|
||||
<p>
|
||||
{addressSlicer(checksummedRecipientAddress)}<br/>
|
||||
{t('copyAddress')}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
wrapperClassName="sender-to-recipient__tooltip-wrapper"
|
||||
containerClassName="sender-to-recipient__tooltip-container"
|
||||
onHidden={() => this.setState({ recipientAddressCopied: false })}
|
||||
@ -116,8 +142,8 @@ export default class SenderToRecipient extends PureComponent {
|
||||
<span>{ addressOnly ? `${t('to')}: ` : '' }</span>
|
||||
{
|
||||
addressOnly
|
||||
? checksummedRecipientAddress
|
||||
: (recipientNickname || recipientName || this.context.t('newContract'))
|
||||
? (recipientNickname || recipientEns || checksummedRecipientAddress)
|
||||
: (recipientNickname || recipientEns || recipientName || this.context.t('newContract'))
|
||||
}
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
@ -8,6 +8,7 @@ export default class Tooltip extends PureComponent {
|
||||
children: null,
|
||||
containerClassName: '',
|
||||
hideOnClick: false,
|
||||
html: null,
|
||||
onHidden: null,
|
||||
position: 'left',
|
||||
size: 'small',
|
||||
@ -21,6 +22,7 @@ export default class Tooltip extends PureComponent {
|
||||
children: PropTypes.node,
|
||||
containerClassName: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
html: PropTypes.node,
|
||||
onHidden: PropTypes.func,
|
||||
position: PropTypes.oneOf([
|
||||
'top',
|
||||
@ -38,9 +40,9 @@ export default class Tooltip extends PureComponent {
|
||||
}
|
||||
|
||||
render () {
|
||||
const {arrow, children, containerClassName, disabled, position, size, title, trigger, onHidden, wrapperClassName, style } = this.props
|
||||
const {arrow, children, containerClassName, disabled, position, html, size, title, trigger, onHidden, wrapperClassName, style } = this.props
|
||||
|
||||
if (!title) {
|
||||
if (!title && !html) {
|
||||
return (
|
||||
<div className={wrapperClassName}>
|
||||
{children}
|
||||
@ -51,6 +53,7 @@ export default class Tooltip extends PureComponent {
|
||||
return (
|
||||
<div className={wrapperClassName}>
|
||||
<ReactTippy
|
||||
html={html}
|
||||
className={containerClassName}
|
||||
disabled={disabled}
|
||||
title={title}
|
||||
|
@ -64,6 +64,7 @@ export default class ConfirmTransactionBase extends Component {
|
||||
tokenData: PropTypes.object,
|
||||
tokenProps: PropTypes.object,
|
||||
toName: PropTypes.string,
|
||||
toEns: PropTypes.string,
|
||||
toNickname: PropTypes.string,
|
||||
transactionStatus: PropTypes.string,
|
||||
txData: PropTypes.object,
|
||||
@ -103,6 +104,7 @@ export default class ConfirmTransactionBase extends Component {
|
||||
transactionCategory: PropTypes.string,
|
||||
getNextNonce: PropTypes.func,
|
||||
nextNonce: PropTypes.number,
|
||||
tryReverseResolveAddress: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
state = {
|
||||
@ -567,7 +569,7 @@ export default class ConfirmTransactionBase extends Component {
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
const { txData: { origin, id } = {}, cancelTransaction, getNextNonce } = this.props
|
||||
const { toAddress, txData: { origin, id } = {}, cancelTransaction, getNextNonce, tryReverseResolveAddress } = this.props
|
||||
const { metricsEvent } = this.context
|
||||
metricsEvent({
|
||||
eventOpts: {
|
||||
@ -598,6 +600,7 @@ export default class ConfirmTransactionBase extends Component {
|
||||
}
|
||||
|
||||
getNextNonce()
|
||||
tryReverseResolveAddress(toAddress)
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
@ -613,6 +616,7 @@ export default class ConfirmTransactionBase extends Component {
|
||||
fromAddress,
|
||||
toName,
|
||||
toAddress,
|
||||
toEns,
|
||||
toNickname,
|
||||
methodData,
|
||||
valid: propsValid = true,
|
||||
@ -643,6 +647,7 @@ export default class ConfirmTransactionBase extends Component {
|
||||
fromAddress={fromAddress}
|
||||
toName={toName}
|
||||
toAddress={toAddress}
|
||||
toEns={toEns}
|
||||
toNickname={toNickname}
|
||||
showEdit={onEdit && !isTxReprice}
|
||||
// In the event that the key is falsy (and inherently invalid), use a fallback string
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
setMetaMetricsSendCount,
|
||||
updateTransaction,
|
||||
getNextNonce,
|
||||
tryReverseResolveAddress,
|
||||
} from '../../store/actions'
|
||||
import {
|
||||
INSUFFICIENT_FUNDS_ERROR_KEY,
|
||||
@ -51,6 +52,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
const isMainnet = getIsMainnet(state)
|
||||
const { confirmTransaction, metamask } = state
|
||||
const {
|
||||
ensResolutionsByAddress,
|
||||
conversionRate,
|
||||
identities,
|
||||
addressBook,
|
||||
@ -93,7 +95,9 @@ const mapStateToProps = (state, ownProps) => {
|
||||
: addressSlicer(checksumAddress(toAddress))
|
||||
)
|
||||
|
||||
const addressBookObject = addressBook[checksumAddress(toAddress)]
|
||||
const checksummedAddress = checksumAddress(toAddress)
|
||||
const addressBookObject = addressBook[checksummedAddress]
|
||||
const toEns = ensResolutionsByAddress[checksummedAddress] || ''
|
||||
const toNickname = addressBookObject ? addressBookObject.name : ''
|
||||
const isTxReprice = Boolean(lastGasPrice)
|
||||
const transactionStatus = transaction ? transaction.status : ''
|
||||
@ -134,6 +138,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
fromAddress,
|
||||
fromName,
|
||||
toAddress,
|
||||
toEns,
|
||||
toName,
|
||||
toNickname,
|
||||
ethTransactionAmount,
|
||||
@ -176,6 +181,9 @@ const mapStateToProps = (state, ownProps) => {
|
||||
|
||||
export const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
tryReverseResolveAddress: (address) => {
|
||||
return dispatch(tryReverseResolveAddress(address))
|
||||
},
|
||||
updateCustomNonce: value => {
|
||||
customNonceValue = value
|
||||
dispatch(updateCustomNonce(value))
|
||||
|
@ -392,6 +392,8 @@ var actions = {
|
||||
setShowRestorePromptToFalse,
|
||||
turnThreeBoxSyncingOn,
|
||||
turnThreeBoxSyncingOnAndInitialize,
|
||||
|
||||
tryReverseResolveAddress,
|
||||
}
|
||||
|
||||
module.exports = actions
|
||||
@ -599,6 +601,19 @@ function requestRevealSeedWords (password) {
|
||||
}
|
||||
}
|
||||
|
||||
function tryReverseResolveAddress (address) {
|
||||
return () => {
|
||||
return new Promise((resolve) => {
|
||||
background.tryReverseResolveAddress(address, (err) => {
|
||||
if (err) {
|
||||
log.error(err)
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function fetchInfoToSync () {
|
||||
return dispatch => {
|
||||
log.debug(`background.fetchInfoToSync`)
|
||||
|
@ -21366,7 +21366,7 @@ punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1:
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
||||
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
|
||||
|
||||
punycode@^2.1.0:
|
||||
punycode@^2.1.0, punycode@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
Loading…
Reference in New Issue
Block a user