mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge remote-tracking branch 'origin/develop' into Version-v8.0.0
* origin/develop: Use error.value.message with error.message as fallback (#8825) Fix dropped tx detection (#8824) delete targetDomainMetadata selector remove top/bottom margin on info icon (#8822) add send token button on fullscreen asset list (#8812) fix getTargetDomainMetadata selector select current address in permissions connect (#8811) Fix encrypt/decrypt beforeunload bugs (#8816)
This commit is contained in:
commit
d730c28cd9
@ -79,7 +79,7 @@ export default class PendingTransactionTracker extends EventEmitter {
|
|||||||
try {
|
try {
|
||||||
await this._resubmitTx(txMeta, blockNumber)
|
await this._resubmitTx(txMeta, blockNumber)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const errorMessage = err.message.toLowerCase()
|
const errorMessage = err.value?.message?.toLowerCase() || err.message.toLowerCase()
|
||||||
const isKnownTx = (
|
const isKnownTx = (
|
||||||
// geth
|
// geth
|
||||||
errorMessage.includes('replacement transaction underpriced') ||
|
errorMessage.includes('replacement transaction underpriced') ||
|
||||||
@ -209,9 +209,9 @@ export default class PendingTransactionTracker extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
async _checkIfTxWasDropped (txMeta) {
|
async _checkIfTxWasDropped (txMeta) {
|
||||||
const { hash: txHash, txParams: { nonce, from } } = txMeta
|
const { hash: txHash, txParams: { nonce, from } } = txMeta
|
||||||
const networkNonce = await this.query.getTransactionCount(from)
|
const networkNextNonce = await this.query.getTransactionCount(from)
|
||||||
|
|
||||||
if (parseInt(nonce) > parseInt(networkNonce)) {
|
if (parseInt(nonce, 16) >= parseInt(networkNextNonce, 16)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ export default class DecryptMessageManager extends EventEmitter {
|
|||||||
addUnapprovedMessageAsync (msgParams, req) {
|
addUnapprovedMessageAsync (msgParams, req) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!msgParams.from) {
|
if (!msgParams.from) {
|
||||||
reject(new Error('MetaMask Message for Decryption: from field is required.'))
|
reject(new Error('MetaMask Decryption: from field is required.'))
|
||||||
}
|
}
|
||||||
const msgId = this.addUnapprovedMessage(msgParams, req)
|
const msgId = this.addUnapprovedMessage(msgParams, req)
|
||||||
this.once(`${msgId}:finished`, (data) => {
|
this.once(`${msgId}:finished`, (data) => {
|
||||||
@ -90,11 +90,11 @@ export default class DecryptMessageManager extends EventEmitter {
|
|||||||
case 'decrypted':
|
case 'decrypted':
|
||||||
return resolve(data.rawData)
|
return resolve(data.rawData)
|
||||||
case 'rejected':
|
case 'rejected':
|
||||||
return reject(ethErrors.provider.userRejectedRequest('MetaMask Message for Decryption: User denied message decryption.'))
|
return reject(ethErrors.provider.userRejectedRequest('MetaMask Decryption: User denied message decryption.'))
|
||||||
case 'errored':
|
case 'errored':
|
||||||
return reject(new Error('This message cannot be decrypted'))
|
return reject(new Error('This message cannot be decrypted'))
|
||||||
default:
|
default:
|
||||||
return reject(new Error(`MetaMask Message for Decryption: Unknown problem: ${JSON.stringify(msgParams)}`))
|
return reject(new Error(`MetaMask Decryption: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -79,7 +79,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
|||||||
addUnapprovedMessageAsync (address, req) {
|
addUnapprovedMessageAsync (address, req) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!address) {
|
if (!address) {
|
||||||
reject(new Error('MetaMask Message for EncryptionPublicKey: address field is required.'))
|
reject(new Error('MetaMask Message: address field is required.'))
|
||||||
}
|
}
|
||||||
const msgId = this.addUnapprovedMessage(address, req)
|
const msgId = this.addUnapprovedMessage(address, req)
|
||||||
this.once(`${msgId}:finished`, (data) => {
|
this.once(`${msgId}:finished`, (data) => {
|
||||||
@ -87,9 +87,9 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
|||||||
case 'received':
|
case 'received':
|
||||||
return resolve(data.rawData)
|
return resolve(data.rawData)
|
||||||
case 'rejected':
|
case 'rejected':
|
||||||
return reject(ethErrors.provider.userRejectedRequest('MetaMask Message for EncryptionPublicKey: User denied message EncryptionPublicKey.'))
|
return reject(ethErrors.provider.userRejectedRequest('MetaMask EncryptionPublicKey: User denied message EncryptionPublicKey.'))
|
||||||
default:
|
default:
|
||||||
return reject(new Error(`MetaMask Message for EncryptionPublicKey: Unknown problem: ${JSON.stringify(address)}`))
|
return reject(new Error(`MetaMask EncryptionPublicKey: Unknown problem: ${JSON.stringify(address)}`))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -415,8 +415,6 @@ describe('MetaMask', function () {
|
|||||||
|
|
||||||
await driver.delay(regularDelayMs)
|
await driver.delay(regularDelayMs)
|
||||||
|
|
||||||
await driver.clickElement(By.css('.permissions-connect-choose-account__account'))
|
|
||||||
|
|
||||||
await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`))
|
await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`))
|
||||||
await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`))
|
await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`))
|
||||||
|
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
import React from 'react'
|
import React, { useMemo } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import Identicon from '../../ui/identicon'
|
import Identicon from '../../ui/identicon'
|
||||||
import ListItem from '../../ui/list-item'
|
import ListItem from '../../ui/list-item'
|
||||||
import Tooltip from '../../ui/tooltip-v2'
|
import Tooltip from '../../ui/tooltip-v2'
|
||||||
import InfoIcon from '../../ui/icon/info-icon.component'
|
import InfoIcon from '../../ui/icon/info-icon.component'
|
||||||
|
import Button from '../../ui/button'
|
||||||
|
import { useI18nContext } from '../../../hooks/useI18nContext'
|
||||||
|
import { useMetricEvent } from '../../../hooks/useMetricEvent'
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
|
import { updateSendToken } from '../../../store/actions'
|
||||||
|
import { useHistory } from 'react-router-dom'
|
||||||
|
import { SEND_ROUTE } from '../../../helpers/constants/routes'
|
||||||
|
|
||||||
|
|
||||||
const AssetListItem = ({
|
const AssetListItem = ({
|
||||||
@ -13,11 +20,23 @@ const AssetListItem = ({
|
|||||||
iconClassName,
|
iconClassName,
|
||||||
onClick,
|
onClick,
|
||||||
tokenAddress,
|
tokenAddress,
|
||||||
|
tokenSymbol,
|
||||||
|
tokenDecimals,
|
||||||
tokenImage,
|
tokenImage,
|
||||||
warning,
|
warning,
|
||||||
primary,
|
primary,
|
||||||
secondary,
|
secondary,
|
||||||
}) => {
|
}) => {
|
||||||
|
const t = useI18nContext()
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const history = useHistory()
|
||||||
|
const sendTokenEvent = useMetricEvent({
|
||||||
|
eventOpts: {
|
||||||
|
category: 'Navigation',
|
||||||
|
action: 'Home',
|
||||||
|
name: 'Clicked Send: Token',
|
||||||
|
},
|
||||||
|
})
|
||||||
const titleIcon = warning
|
const titleIcon = warning
|
||||||
? (
|
? (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@ -40,6 +59,38 @@ const AssetListItem = ({
|
|||||||
)
|
)
|
||||||
: null
|
: null
|
||||||
|
|
||||||
|
const sendTokenButton = useMemo(() => {
|
||||||
|
if (tokenAddress == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
className="asset-list-item__send-token-button"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
sendTokenEvent()
|
||||||
|
dispatch(updateSendToken({
|
||||||
|
address: tokenAddress,
|
||||||
|
decimals: tokenDecimals,
|
||||||
|
symbol: tokenSymbol,
|
||||||
|
}))
|
||||||
|
history.push(SEND_ROUTE)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('sendSpecifiedTokens', [tokenSymbol])}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}, [
|
||||||
|
tokenSymbol,
|
||||||
|
sendTokenEvent,
|
||||||
|
tokenAddress,
|
||||||
|
tokenDecimals,
|
||||||
|
history,
|
||||||
|
t,
|
||||||
|
dispatch,
|
||||||
|
])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItem
|
<ListItem
|
||||||
className={classnames('asset-list-item', className)}
|
className={classnames('asset-list-item', className)}
|
||||||
@ -57,7 +108,12 @@ const AssetListItem = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
midContent={midContent}
|
midContent={midContent}
|
||||||
rightContent={<i className="fas fa-chevron-right asset-list-item__chevron-right" />}
|
rightContent={(
|
||||||
|
<>
|
||||||
|
<i className="fas fa-chevron-right asset-list-item__chevron-right" />
|
||||||
|
{sendTokenButton}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -68,6 +124,8 @@ AssetListItem.propTypes = {
|
|||||||
iconClassName: PropTypes.string,
|
iconClassName: PropTypes.string,
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
tokenAddress: PropTypes.string,
|
tokenAddress: PropTypes.string,
|
||||||
|
tokenSymbol: PropTypes.string,
|
||||||
|
tokenDecimals: PropTypes.number,
|
||||||
tokenImage: PropTypes.string,
|
tokenImage: PropTypes.string,
|
||||||
warning: PropTypes.node,
|
warning: PropTypes.node,
|
||||||
primary: PropTypes.string,
|
primary: PropTypes.string,
|
||||||
|
@ -17,6 +17,13 @@
|
|||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__send-token-button {
|
||||||
|
display: none;
|
||||||
|
text-transform: uppercase;
|
||||||
|
width: fit-content;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 576px) {
|
@media (min-width: 576px) {
|
||||||
&__warning-tooltip {
|
&__warning-tooltip {
|
||||||
display: none;
|
display: none;
|
||||||
@ -25,5 +32,13 @@
|
|||||||
.list-item__mid-content {
|
.list-item__mid-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__send-token-button {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__chevron-right {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,14 @@
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import PermissionPageContainer from './permission-page-container.component'
|
import PermissionPageContainer from './permission-page-container.component'
|
||||||
import {
|
import { getMetaMaskIdentities } from '../../../selectors'
|
||||||
getTargetDomainMetadata,
|
|
||||||
getMetaMaskIdentities,
|
|
||||||
} from '../../../selectors'
|
|
||||||
|
|
||||||
const mapStateToProps = (state, ownProps) => {
|
const mapStateToProps = (state, ownProps) => {
|
||||||
const { request, cachedOrigin, selectedIdentities } = ownProps
|
const { selectedIdentities } = ownProps
|
||||||
const targetDomainMetadata = getTargetDomainMetadata(state, request, cachedOrigin)
|
|
||||||
|
|
||||||
const allIdentities = getMetaMaskIdentities(state)
|
const allIdentities = getMetaMaskIdentities(state)
|
||||||
const allIdentitiesSelected = Object.keys(selectedIdentities).length === Object.keys(allIdentities).length && selectedIdentities.length > 1
|
const allIdentitiesSelected = Object.keys(selectedIdentities).length === Object.keys(allIdentities).length && selectedIdentities.length > 1
|
||||||
|
|
||||||
return {
|
return {
|
||||||
targetDomainMetadata,
|
|
||||||
allIdentitiesSelected,
|
allIdentitiesSelected,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,15 @@ import { useI18nContext } from '../../../hooks/useI18nContext'
|
|||||||
import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount'
|
import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount'
|
||||||
|
|
||||||
|
|
||||||
export default function TokenCell ({ address, outdatedBalance, symbol, string, image, onClick }) {
|
export default function TokenCell ({
|
||||||
|
address,
|
||||||
|
decimals,
|
||||||
|
outdatedBalance,
|
||||||
|
symbol,
|
||||||
|
string,
|
||||||
|
image,
|
||||||
|
onClick,
|
||||||
|
}) {
|
||||||
const userAddress = useSelector(getSelectedAddress)
|
const userAddress = useSelector(getSelectedAddress)
|
||||||
const t = useI18nContext()
|
const t = useI18nContext()
|
||||||
|
|
||||||
@ -37,6 +45,8 @@ export default function TokenCell ({ address, outdatedBalance, symbol, string, i
|
|||||||
onClick={onClick.bind(null, address)}
|
onClick={onClick.bind(null, address)}
|
||||||
tokenAddress={address}
|
tokenAddress={address}
|
||||||
tokenImage={image}
|
tokenImage={image}
|
||||||
|
tokenSymbol={symbol}
|
||||||
|
tokenDecimals={decimals}
|
||||||
warning={warning}
|
warning={warning}
|
||||||
primary={`${string || 0} ${symbol}`}
|
primary={`${string || 0} ${symbol}`}
|
||||||
secondary={formattedFiat}
|
secondary={formattedFiat}
|
||||||
@ -49,6 +59,7 @@ TokenCell.propTypes = {
|
|||||||
address: PropTypes.string,
|
address: PropTypes.string,
|
||||||
outdatedBalance: PropTypes.bool,
|
outdatedBalance: PropTypes.bool,
|
||||||
symbol: PropTypes.string,
|
symbol: PropTypes.string,
|
||||||
|
decimals: PropTypes.number,
|
||||||
string: PropTypes.string,
|
string: PropTypes.string,
|
||||||
image: PropTypes.string,
|
image: PropTypes.string,
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
|
@ -5,6 +5,7 @@ import { Provider } from 'react-redux'
|
|||||||
import configureMockStore from 'redux-mock-store'
|
import configureMockStore from 'redux-mock-store'
|
||||||
import { mount } from 'enzyme'
|
import { mount } from 'enzyme'
|
||||||
import sinon from 'sinon'
|
import sinon from 'sinon'
|
||||||
|
import { MemoryRouter } from 'react-router-dom'
|
||||||
|
|
||||||
import TokenCell from '.'
|
import TokenCell from '.'
|
||||||
import Identicon from '../../ui/identicon'
|
import Identicon from '../../ui/identicon'
|
||||||
@ -44,14 +45,16 @@ describe('Token Cell', function () {
|
|||||||
onClick = sinon.stub()
|
onClick = sinon.stub()
|
||||||
wrapper = mount(
|
wrapper = mount(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<TokenCell
|
<MemoryRouter>
|
||||||
address="0xAnotherToken"
|
<TokenCell
|
||||||
symbol="TEST"
|
address="0xAnotherToken"
|
||||||
string="5.000"
|
symbol="TEST"
|
||||||
currentCurrency="usd"
|
string="5.000"
|
||||||
image="./test-image"
|
currentCurrency="usd"
|
||||||
onClick={onClick}
|
image="./test-image"
|
||||||
/>
|
onClick={onClick}
|
||||||
|
/>
|
||||||
|
</MemoryRouter>
|
||||||
</Provider>
|
</Provider>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.info-icon {
|
.info-icon {
|
||||||
margin: 4px;
|
margin: 0 4px;
|
||||||
|
|
||||||
&--success {
|
&--success {
|
||||||
fill: $success-green;
|
fill: $success-green;
|
||||||
|
@ -52,9 +52,14 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
this._removeBeforeUnload()
|
this._removeBeforeUnload()
|
||||||
}
|
}
|
||||||
|
|
||||||
_beforeUnload = (event) => {
|
_beforeUnload = async (event) => {
|
||||||
const { clearConfirmTransaction, cancelDecryptMessage } = this.props
|
const {
|
||||||
|
clearConfirmTransaction,
|
||||||
|
cancelDecryptMessage,
|
||||||
|
txData,
|
||||||
|
} = this.props
|
||||||
const { metricsEvent } = this.context
|
const { metricsEvent } = this.context
|
||||||
|
await cancelDecryptMessage(txData, event)
|
||||||
metricsEvent({
|
metricsEvent({
|
||||||
eventOpts: {
|
eventOpts: {
|
||||||
category: 'Messages',
|
category: 'Messages',
|
||||||
@ -63,7 +68,6 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
clearConfirmTransaction()
|
clearConfirmTransaction()
|
||||||
cancelDecryptMessage(event)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_removeBeforeUnload = () => {
|
_removeBeforeUnload = () => {
|
||||||
@ -103,11 +107,12 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
|
|
||||||
renderAccount = () => {
|
renderAccount = () => {
|
||||||
const { fromAccount } = this.state
|
const { fromAccount } = this.state
|
||||||
|
const { t } = this.context
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="request-decrypt-message__account">
|
<div className="request-decrypt-message__account">
|
||||||
<div className="request-decrypt-message__account-text">
|
<div className="request-decrypt-message__account-text">
|
||||||
{ `${this.context.t('account')}:` }
|
{ `${t('account')}:` }
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="request-decrypt-message__account-item">
|
<div className="request-decrypt-message__account-item">
|
||||||
@ -123,6 +128,7 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
renderBalance = () => {
|
renderBalance = () => {
|
||||||
const { conversionRate } = this.props
|
const { conversionRate } = this.props
|
||||||
const { fromAccount: { balance } } = this.state
|
const { fromAccount: { balance } } = this.state
|
||||||
|
const { t } = this.context
|
||||||
|
|
||||||
const balanceInEther = conversionUtil(balance, {
|
const balanceInEther = conversionUtil(balance, {
|
||||||
fromNumericBase: 'hex',
|
fromNumericBase: 'hex',
|
||||||
@ -135,7 +141,7 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
return (
|
return (
|
||||||
<div className="request-decrypt-message__balance">
|
<div className="request-decrypt-message__balance">
|
||||||
<div className="request-decrypt-message__balance-text">
|
<div className="request-decrypt-message__balance-text">
|
||||||
{ `${this.context.t('balance')}:` }
|
{ `${t('balance')}:` }
|
||||||
</div>
|
</div>
|
||||||
<div className="request-decrypt-message__balance-value">
|
<div className="request-decrypt-message__balance-value">
|
||||||
{ `${balanceInEther} ETH` }
|
{ `${balanceInEther} ETH` }
|
||||||
@ -168,10 +174,11 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderBody = () => {
|
renderBody = () => {
|
||||||
const { txData } = this.props
|
const { decryptMessageInline, domainMetadata, txData } = this.props
|
||||||
|
const { t } = this.context
|
||||||
|
|
||||||
const origin = this.props.domainMetadata[txData.msgParams.origin]
|
const origin = domainMetadata[txData.msgParams.origin]
|
||||||
const notice = this.context.t('decryptMessageNotice', [origin.name])
|
const notice = t('decryptMessageNotice', [origin.name])
|
||||||
|
|
||||||
const {
|
const {
|
||||||
hasCopied,
|
hasCopied,
|
||||||
@ -228,7 +235,7 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
'request-decrypt-message__message-lock--pressed': hasDecrypted || hasError,
|
'request-decrypt-message__message-lock--pressed': hasDecrypted || hasError,
|
||||||
})}
|
})}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
this.props.decryptMessageInline(txData, event).then((result) => {
|
decryptMessageInline(txData, event).then((result) => {
|
||||||
if (!result.error) {
|
if (!result.error) {
|
||||||
this.setState({ hasDecrypted: true, rawMessage: result.rawData })
|
this.setState({ hasDecrypted: true, rawMessage: result.rawData })
|
||||||
} else {
|
} else {
|
||||||
@ -241,7 +248,7 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
<div
|
<div
|
||||||
className="request-decrypt-message__message-lock-text"
|
className="request-decrypt-message__message-lock-text"
|
||||||
>
|
>
|
||||||
{this.context.t('decryptMetamask')}
|
{t('decryptMetamask')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -258,13 +265,13 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
>
|
>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
position="bottom"
|
position="bottom"
|
||||||
title={hasCopied ? this.context.t('copiedExclamation') : this.context.t('copyToClipboard')}
|
title={hasCopied ? t('copiedExclamation') : t('copyToClipboard')}
|
||||||
wrapperClassName="request-decrypt-message__message-copy-tooltip"
|
wrapperClassName="request-decrypt-message__message-copy-tooltip"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="request-decrypt-message__message-copy-text"
|
className="request-decrypt-message__message-copy-text"
|
||||||
>
|
>
|
||||||
{this.context.t('decryptCopy')}
|
{t('decryptCopy')}
|
||||||
</div>
|
</div>
|
||||||
<img src="images/copy-to-clipboard.svg" />
|
<img src="images/copy-to-clipboard.svg" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@ -286,6 +293,7 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
mostRecentOverviewPage,
|
mostRecentOverviewPage,
|
||||||
txData,
|
txData,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
const { metricsEvent, t } = this.context
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="request-decrypt-message__footer">
|
<div className="request-decrypt-message__footer">
|
||||||
@ -296,7 +304,7 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
onClick={async (event) => {
|
onClick={async (event) => {
|
||||||
this._removeBeforeUnload()
|
this._removeBeforeUnload()
|
||||||
await cancelDecryptMessage(txData, event)
|
await cancelDecryptMessage(txData, event)
|
||||||
this.context.metricsEvent({
|
metricsEvent({
|
||||||
eventOpts: {
|
eventOpts: {
|
||||||
category: 'Messages',
|
category: 'Messages',
|
||||||
action: 'Decrypt Message Request',
|
action: 'Decrypt Message Request',
|
||||||
@ -307,7 +315,7 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
history.push(mostRecentOverviewPage)
|
history.push(mostRecentOverviewPage)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{ this.context.t('cancel') }
|
{ t('cancel') }
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="secondary"
|
type="secondary"
|
||||||
@ -316,7 +324,7 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
onClick={async (event) => {
|
onClick={async (event) => {
|
||||||
this._removeBeforeUnload()
|
this._removeBeforeUnload()
|
||||||
await decryptMessage(txData, event)
|
await decryptMessage(txData, event)
|
||||||
this.context.metricsEvent({
|
metricsEvent({
|
||||||
eventOpts: {
|
eventOpts: {
|
||||||
category: 'Messages',
|
category: 'Messages',
|
||||||
action: 'Decrypt Message Request',
|
action: 'Decrypt Message Request',
|
||||||
@ -327,7 +335,7 @@ export default class ConfirmDecryptMessage extends Component {
|
|||||||
history.push(mostRecentOverviewPage)
|
history.push(mostRecentOverviewPage)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{ this.context.t('decrypt') }
|
{ t('decrypt') }
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -46,9 +46,14 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
|||||||
this._removeBeforeUnload()
|
this._removeBeforeUnload()
|
||||||
}
|
}
|
||||||
|
|
||||||
_beforeUnload = (event) => {
|
_beforeUnload = async (event) => {
|
||||||
const { clearConfirmTransaction, cancelEncryptionPublicKey } = this.props
|
const {
|
||||||
|
clearConfirmTransaction,
|
||||||
|
cancelEncryptionPublicKey,
|
||||||
|
txData,
|
||||||
|
} = this.props
|
||||||
const { metricsEvent } = this.context
|
const { metricsEvent } = this.context
|
||||||
|
await cancelEncryptionPublicKey(txData, event)
|
||||||
metricsEvent({
|
metricsEvent({
|
||||||
eventOpts: {
|
eventOpts: {
|
||||||
category: 'Messages',
|
category: 'Messages',
|
||||||
@ -57,7 +62,6 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
clearConfirmTransaction()
|
clearConfirmTransaction()
|
||||||
cancelEncryptionPublicKey(event)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_removeBeforeUnload = () => {
|
_removeBeforeUnload = () => {
|
||||||
@ -84,11 +88,12 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
|||||||
|
|
||||||
renderAccount = () => {
|
renderAccount = () => {
|
||||||
const { fromAccount } = this.state
|
const { fromAccount } = this.state
|
||||||
|
const { t } = this.context
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="request-encryption-public-key__account">
|
<div className="request-encryption-public-key__account">
|
||||||
<div className="request-encryption-public-key__account-text">
|
<div className="request-encryption-public-key__account-text">
|
||||||
{ `${this.context.t('account')}:` }
|
{ `${t('account')}:` }
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="request-encryption-public-key__account-item">
|
<div className="request-encryption-public-key__account-item">
|
||||||
@ -103,6 +108,7 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
|||||||
|
|
||||||
renderBalance = () => {
|
renderBalance = () => {
|
||||||
const { conversionRate } = this.props
|
const { conversionRate } = this.props
|
||||||
|
const { t } = this.context
|
||||||
const { fromAccount: { balance } } = this.state
|
const { fromAccount: { balance } } = this.state
|
||||||
|
|
||||||
const balanceInEther = conversionUtil(balance, {
|
const balanceInEther = conversionUtil(balance, {
|
||||||
@ -116,7 +122,7 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
|||||||
return (
|
return (
|
||||||
<div className="request-encryption-public-key__balance">
|
<div className="request-encryption-public-key__balance">
|
||||||
<div className="request-encryption-public-key__balance-text">
|
<div className="request-encryption-public-key__balance-text">
|
||||||
{ `${this.context.t('balance')}:` }
|
{ `${t('balance')}:` }
|
||||||
</div>
|
</div>
|
||||||
<div className="request-encryption-public-key__balance-value">
|
<div className="request-encryption-public-key__balance-value">
|
||||||
{ `${balanceInEther} ETH` }
|
{ `${balanceInEther} ETH` }
|
||||||
@ -149,10 +155,11 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderBody = () => {
|
renderBody = () => {
|
||||||
const { txData } = this.props
|
const { domainMetadata, txData } = this.props
|
||||||
|
const { t } = this.context
|
||||||
|
|
||||||
const origin = this.props.domainMetadata[txData.origin]
|
const origin = domainMetadata[txData.origin]
|
||||||
const notice = this.context.t('encryptionPublicKeyNotice', [origin.name])
|
const notice = t('encryptionPublicKeyNotice', [origin.name])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="request-encryption-public-key__body">
|
<div className="request-encryption-public-key__body">
|
||||||
@ -191,6 +198,7 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
|||||||
mostRecentOverviewPage,
|
mostRecentOverviewPage,
|
||||||
txData,
|
txData,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
const { t, metricsEvent } = this.context
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="request-encryption-public-key__footer">
|
<div className="request-encryption-public-key__footer">
|
||||||
@ -201,7 +209,7 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
|||||||
onClick={async (event) => {
|
onClick={async (event) => {
|
||||||
this._removeBeforeUnload()
|
this._removeBeforeUnload()
|
||||||
await cancelEncryptionPublicKey(txData, event)
|
await cancelEncryptionPublicKey(txData, event)
|
||||||
this.context.metricsEvent({
|
metricsEvent({
|
||||||
eventOpts: {
|
eventOpts: {
|
||||||
category: 'Messages',
|
category: 'Messages',
|
||||||
action: 'Encryption public key Request',
|
action: 'Encryption public key Request',
|
||||||
@ -232,7 +240,7 @@ export default class ConfirmEncryptionPublicKey extends Component {
|
|||||||
history.push(mostRecentOverviewPage)
|
history.push(mostRecentOverviewPage)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{ this.context.t('provide') }
|
{ t('provide') }
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -17,6 +17,7 @@ export default class PermissionConnect extends Component {
|
|||||||
getRequestAccountTabIds: PropTypes.func.isRequired,
|
getRequestAccountTabIds: PropTypes.func.isRequired,
|
||||||
getCurrentWindowTab: PropTypes.func.isRequired,
|
getCurrentWindowTab: PropTypes.func.isRequired,
|
||||||
accounts: PropTypes.array.isRequired,
|
accounts: PropTypes.array.isRequired,
|
||||||
|
currentAddress: PropTypes.string.isRequired,
|
||||||
origin: PropTypes.string,
|
origin: PropTypes.string,
|
||||||
showNewAccountModal: PropTypes.func.isRequired,
|
showNewAccountModal: PropTypes.func.isRequired,
|
||||||
newAccountNumber: PropTypes.number.isRequired,
|
newAccountNumber: PropTypes.number.isRequired,
|
||||||
@ -46,9 +47,7 @@ export default class PermissionConnect extends Component {
|
|||||||
|
|
||||||
state = {
|
state = {
|
||||||
redirecting: false,
|
redirecting: false,
|
||||||
selectedAccountAddresses: this.props.accounts.length === 1
|
selectedAccountAddresses: new Set([this.props.currentAddress]),
|
||||||
? new Set([this.props.accounts[0].address])
|
|
||||||
: new Set(),
|
|
||||||
permissionsApproved: null,
|
permissionsApproved: null,
|
||||||
origin: this.props.origin,
|
origin: this.props.origin,
|
||||||
targetDomainMetadata: this.props.targetDomainMetadata || {},
|
targetDomainMetadata: this.props.targetDomainMetadata || {},
|
||||||
@ -207,7 +206,6 @@ export default class PermissionConnect extends Component {
|
|||||||
const {
|
const {
|
||||||
selectedAccountAddresses,
|
selectedAccountAddresses,
|
||||||
permissionsApproved,
|
permissionsApproved,
|
||||||
origin,
|
|
||||||
redirecting,
|
redirecting,
|
||||||
targetDomainMetadata,
|
targetDomainMetadata,
|
||||||
} = this.state
|
} = this.state
|
||||||
@ -258,7 +256,7 @@ export default class PermissionConnect extends Component {
|
|||||||
}}
|
}}
|
||||||
rejectPermissionsRequest={(requestId) => this.cancelPermissionsRequest(requestId)}
|
rejectPermissionsRequest={(requestId) => this.cancelPermissionsRequest(requestId)}
|
||||||
selectedIdentities={accounts.filter((account) => selectedAccountAddresses.has(account.address))}
|
selectedIdentities={accounts.filter((account) => selectedAccountAddresses.has(account.address))}
|
||||||
cachedOrigin={origin}
|
targetDomainMetadata={targetDomainMetadata}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
@ -6,7 +6,8 @@ import {
|
|||||||
getNativeCurrency,
|
getNativeCurrency,
|
||||||
getAccountsWithLabels,
|
getAccountsWithLabels,
|
||||||
getLastConnectedInfo,
|
getLastConnectedInfo,
|
||||||
getTargetDomainMetadata,
|
getDomainMetadata,
|
||||||
|
getSelectedAddress,
|
||||||
} from '../../selectors'
|
} from '../../selectors'
|
||||||
|
|
||||||
import { formatDate } from '../../helpers/utils/util'
|
import { formatDate } from '../../helpers/utils/util'
|
||||||
@ -28,6 +29,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
location: { pathname },
|
location: { pathname },
|
||||||
} = ownProps
|
} = ownProps
|
||||||
const permissionsRequests = getPermissionsRequests(state)
|
const permissionsRequests = getPermissionsRequests(state)
|
||||||
|
const currentAddress = getSelectedAddress(state)
|
||||||
|
|
||||||
const permissionsRequest = permissionsRequests
|
const permissionsRequest = permissionsRequests
|
||||||
.find((permissionsRequest) => permissionsRequest.metadata.id === permissionsRequestId)
|
.find((permissionsRequest) => permissionsRequest.metadata.id === permissionsRequestId)
|
||||||
@ -40,6 +42,15 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
const { origin } = metadata
|
const { origin } = metadata
|
||||||
const nativeCurrency = getNativeCurrency(state)
|
const nativeCurrency = getNativeCurrency(state)
|
||||||
|
|
||||||
|
const domainMetadata = getDomainMetadata(state)
|
||||||
|
const targetDomainMetadata = origin
|
||||||
|
? domainMetadata[origin] || {
|
||||||
|
origin,
|
||||||
|
name: (new URL(origin)).hostname,
|
||||||
|
icon: null,
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
|
||||||
const accountsWithLabels = getAccountsWithLabels(state)
|
const accountsWithLabels = getAccountsWithLabels(state)
|
||||||
|
|
||||||
const lastConnectedInfo = getLastConnectedInfo(state) || {}
|
const lastConnectedInfo = getLastConnectedInfo(state) || {}
|
||||||
@ -61,13 +72,12 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
throw new Error('Incorrect path for permissions-connect component')
|
throw new Error('Incorrect path for permissions-connect component')
|
||||||
}
|
}
|
||||||
|
|
||||||
const targetDomainMetadata = getTargetDomainMetadata(state, permissionsRequest, origin)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
permissionsRequest,
|
permissionsRequest,
|
||||||
permissionsRequestId,
|
permissionsRequestId,
|
||||||
hasPendingPermissionsRequests,
|
hasPendingPermissionsRequests,
|
||||||
accounts: accountsWithLabels,
|
accounts: accountsWithLabels,
|
||||||
|
currentAddress,
|
||||||
origin,
|
origin,
|
||||||
newAccountNumber: accountsWithLabels.length + 1,
|
newAccountNumber: accountsWithLabels.length + 1,
|
||||||
nativeCurrency,
|
nativeCurrency,
|
||||||
|
@ -287,18 +287,6 @@ export function getDomainMetadata (state) {
|
|||||||
return state.metamask.domainMetadata
|
return state.metamask.domainMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTargetDomainMetadata (state, request, defaultOrigin) {
|
|
||||||
const domainMetadata = getDomainMetadata(state)
|
|
||||||
|
|
||||||
const { metadata: requestMetadata = {} } = request || {}
|
|
||||||
const origin = requestMetadata.origin || defaultOrigin
|
|
||||||
const hostname = (new URL(origin).hostname)
|
|
||||||
const targetDomainMetadata = (domainMetadata[origin] || { name: hostname, icon: null })
|
|
||||||
targetDomainMetadata.origin = origin
|
|
||||||
|
|
||||||
return targetDomainMetadata
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getBackgroundMetaMetricState = (state) => {
|
export const getBackgroundMetaMetricState = (state) => {
|
||||||
return {
|
return {
|
||||||
network: getCurrentNetworkId(state),
|
network: getCurrentNetworkId(state),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user