1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-22 19:26:13 +02:00

Merge pull request #7635 from MetaMask/Version-v7.7.1

Version v7.7.1 RC
This commit is contained in:
Dan Finlay 2019-12-09 10:22:45 -08:00 committed by GitHub
commit 70bbb689d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 133 additions and 53 deletions

View File

@ -2,6 +2,33 @@
## Current Develop Branch ## Current Develop Branch
## 7.7.1 Wed Dec 04 2019
- [#7488](https://github.com/MetaMask/metamask-extension/pull/7488): Fix text overlap when expanding transaction
- [#7491](https://github.com/MetaMask/metamask-extension/pull/7491): Update gas when asset is changed on send screen
- [#7500](https://github.com/MetaMask/metamask-extension/pull/7500): Remove unused onClick prop from Dropdown component
- [#7502](https://github.com/MetaMask/metamask-extension/pull/7502): Fix chainId for non standard networks
- [#7519](https://github.com/MetaMask/metamask-extension/pull/7519): Fixing hardware connect error display
- [#7501](https://github.com/MetaMask/metamask-extension/pull/7501): Fix accessibility of first-time-flow terms checkboxes
- [#7579](https://github.com/MetaMask/metamask-extension/pull/7579): Prevent Maker migration dismissal timeout state from being overwritten
- [#7581](https://github.com/MetaMask/metamask-extension/pull/7581): Persist Maker migration dismissal timeout
- [#7484](https://github.com/MetaMask/metamask-extension/pull/7484): Ensure transactions are shown in the order they are received
- [#7604](https://github.com/MetaMask/metamask-extension/pull/7604): Process URL fragment for ens-ipfs redirects
- [#7628](https://github.com/MetaMask/metamask-extension/pull/7628): Fix typo that resulted in degrated account menu performance
- [#7558](https://github.com/MetaMask/metamask-extension/pull/7558): Use localized messages for NotificationModal buttons
## 7.7.0 Thu Nov 28 2019 [WITHDRAWN]
- [#7004](https://github.com/MetaMask/metamask-extension/pull/7004): Connect distinct accounts per site
- [#7480](https://github.com/MetaMask/metamask-extension/pull/7480): Fixed link on root README.md
- [#7482](https://github.com/MetaMask/metamask-extension/pull/7482): Update Wyre ETH purchase url
- [#7484](https://github.com/MetaMask/metamask-extension/pull/7484): Ensure transactions are shown in the order they are received
- [#7491](https://github.com/MetaMask/metamask-extension/pull/7491): Update gas when token is changed on the send screen
- [#7501](https://github.com/MetaMask/metamask-extension/pull/7501): Fix accessibility of first-time-flow terms checkboxes
- [#7502](https://github.com/MetaMask/metamask-extension/pull/7502): Fix chainId for non standard networks
- [#7579](https://github.com/MetaMask/metamask-extension/pull/7579): Fix timing of DAI migration notifications after dismissal
- [#7519](https://github.com/MetaMask/metamask-extension/pull/7519): Fixing hardware connect error display
- [#7558](https://github.com/MetaMask/metamask-extension/pull/7558): Use localized messages for NotificationModal buttons
- [#7488](https://github.com/MetaMask/metamask-extension/pull/7488): Fix text overlap when expanding transaction
## 7.6.1 Tue Nov 19 2019 ## 7.6.1 Tue Nov 19 2019
- [#7475](https://github.com/MetaMask/metamask-extension/pull/7475): Add 'Remind Me Later' to the Maker notification - [#7475](https://github.com/MetaMask/metamask-extension/pull/7475): Add 'Remind Me Later' to the Maker notification
- [#7436](https://github.com/MetaMask/metamask-extension/pull/7436): Add additional rpcUrl verification - [#7436](https://github.com/MetaMask/metamask-extension/pull/7436): Add additional rpcUrl verification

View File

@ -1,7 +1,7 @@
{ {
"name": "__MSG_appName__", "name": "__MSG_appName__",
"short_name": "__MSG_appName__", "short_name": "__MSG_appName__",
"version": "7.6.1", "version": "7.7.1",
"manifest_version": 2, "manifest_version": 2,
"author": "https://metamask.io", "author": "https://metamask.io",
"description": "__MSG_appDescription__", "description": "__MSG_appDescription__",

View File

@ -45,7 +45,7 @@ class AppStateController {
* @private * @private
*/ */
_setInactiveTimeout (timeoutMinutes) { _setInactiveTimeout (timeoutMinutes) {
this.store.putState({ this.store.updateState({
timeoutMinutes, timeoutMinutes,
}) })

View File

@ -192,13 +192,18 @@ class TransactionController extends EventEmitter {
throw new Error(`Transaction from address isn't valid for this account`) throw new Error(`Transaction from address isn't valid for this account`)
} }
txUtils.validateTxParams(normalizedTxParams) txUtils.validateTxParams(normalizedTxParams)
// construct txMeta /**
const { transactionCategory, getCodeResponse } = await this._determineTransactionCategory(txParams) `generateTxMeta` adds the default txMeta properties to the passed object.
These include the tx's `id`. As we use the id for determining order of
txes in the tx-state-manager, it is necessary to call the asynchronous
method `this._determineTransactionCategory` after `generateTxMeta`.
*/
let txMeta = this.txStateManager.generateTxMeta({ let txMeta = this.txStateManager.generateTxMeta({
txParams: normalizedTxParams, txParams: normalizedTxParams,
type: TRANSACTION_TYPE_STANDARD, type: TRANSACTION_TYPE_STANDARD,
transactionCategory,
}) })
const { transactionCategory, getCodeResponse } = await this._determineTransactionCategory(txParams)
txMeta.transactionCategory = transactionCategory
this.addTx(txMeta) this.addTx(txMeta)
this.emit('newUnapprovedTx', txMeta) this.emit('newUnapprovedTx', txMeta)

View File

@ -159,7 +159,12 @@ class TransactionStateManager extends EventEmitter {
transactions.splice(index, 1) transactions.splice(index, 1)
} }
} }
transactions.push(txMeta) const newTxIndex = transactions
.findIndex((currentTxMeta) => currentTxMeta.time > txMeta.time)
newTxIndex === -1
? transactions.push(txMeta)
: transactions.splice(newTxIndex, 0, txMeta)
this._saveTxList(transactions) this._saveTxList(transactions)
return txMeta return txMeta
} }

View File

@ -26,22 +26,22 @@ function setupEnsIpfsResolver ({ provider }) {
if (tabId === -1) return if (tabId === -1) return
// parse ens name // parse ens name
const urlData = urlUtil.parse(url) const urlData = urlUtil.parse(url)
const { hostname: name, path, search } = urlData const { hostname: name, path, search, hash: fragment } = urlData
const domainParts = name.split('.') const domainParts = name.split('.')
const topLevelDomain = domainParts[domainParts.length - 1] const topLevelDomain = domainParts[domainParts.length - 1]
// if unsupported TLD, abort // if unsupported TLD, abort
if (!supportedTopLevelDomains.includes(topLevelDomain)) return if (!supportedTopLevelDomains.includes(topLevelDomain)) return
// otherwise attempt resolve // otherwise attempt resolve
attemptResolve({ tabId, name, path, search }) attemptResolve({ tabId, name, path, search, fragment })
} }
async function attemptResolve ({ tabId, name, path, search }) { async function attemptResolve ({ tabId, name, path, search, fragment }) {
extension.tabs.update(tabId, { url: `loading.html` }) extension.tabs.update(tabId, { url: `loading.html` })
let url = `https://manager.ens.domains/name/${name}` let url = `https://app.ens.domains/name/${name}`
try { try {
const {type, hash} = await resolveEnsToIpfsContentId({ provider, name }) const {type, hash} = await resolveEnsToIpfsContentId({ provider, name })
if (type === 'ipfs-ns') { if (type === 'ipfs-ns') {
const resolvedUrl = `https://gateway.ipfs.io/ipfs/${hash}${path}${search || ''}` const resolvedUrl = `https://gateway.ipfs.io/ipfs/${hash}${path}${search || ''}${fragment || ''}`
try { try {
// check if ipfs gateway has result // check if ipfs gateway has result
const response = await fetch(resolvedUrl, { method: 'HEAD' }) const response = await fetch(resolvedUrl, { method: 'HEAD' })
@ -50,11 +50,11 @@ function setupEnsIpfsResolver ({ provider }) {
console.warn(err) console.warn(err)
} }
} else if (type === 'swarm-ns') { } else if (type === 'swarm-ns') {
url = `https://swarm-gateways.net/bzz:/${hash}${path}${search || ''}` url = `https://swarm-gateways.net/bzz:/${hash}${path}${search || ''}${fragment || ''}`
} else if (type === 'onion' || type === 'onion3') { } else if (type === 'onion' || type === 'onion3') {
url = `http://${hash}.onion${path}${search || ''}` url = `http://${hash}.onion${path}${search || ''}${fragment || ''}`
} else if (type === 'zeronet') { } else if (type === 'zeronet') {
url = `http://127.0.0.1:43110/${hash}${path}${search || ''}` url = `http://127.0.0.1:43110/${hash}${path}${search || ''}${fragment || ''}`
} }
} catch (err) { } catch (err) {
console.warn(err) console.warn(err)

View File

@ -15,8 +15,8 @@ const standardNetworkId = {
} }
function selectChainId (metamaskState) { function selectChainId (metamaskState) {
const { network, provider: { chaindId } } = metamaskState const { network, provider: { chainId } } = metamaskState
return standardNetworkId[network] || `0x${parseInt(chaindId, 10).toString(16)}` return standardNetworkId[network] || `0x${parseInt(chainId, 10).toString(16)}`
} }
module.exports = selectChainId module.exports = selectChainId

View File

@ -109,6 +109,7 @@ module.exports = class MetamaskController extends EventEmitter {
this.appStateController = new AppStateController({ this.appStateController = new AppStateController({
preferencesStore: this.preferencesController.store, preferencesStore: this.preferencesController.store,
onInactiveTimeout: () => this.setLocked(), onInactiveTimeout: () => this.setLocked(),
initState: initState.AppStateController,
}) })
// currency controller // currency controller

View File

@ -28,7 +28,6 @@ export default class AccountMenu extends PureComponent {
history: PropTypes.object, history: PropTypes.object,
identities: PropTypes.object, identities: PropTypes.object,
isAccountMenuOpen: PropTypes.bool, isAccountMenuOpen: PropTypes.bool,
prevIsAccountMenuOpen: PropTypes.bool,
keyrings: PropTypes.array, keyrings: PropTypes.array,
lockMetamask: PropTypes.func, lockMetamask: PropTypes.func,
selectedAddress: PropTypes.string, selectedAddress: PropTypes.string,
@ -42,7 +41,7 @@ export default class AccountMenu extends PureComponent {
} }
componentDidUpdate (prevProps) { componentDidUpdate (prevProps) {
const { prevIsAccountMenuOpen } = prevProps const { isAccountMenuOpen: prevIsAccountMenuOpen } = prevProps
const { isAccountMenuOpen } = this.props const { isAccountMenuOpen } = this.props
if (!prevIsAccountMenuOpen && isAccountMenuOpen) { if (!prevIsAccountMenuOpen && isAccountMenuOpen) {

View File

@ -58,7 +58,6 @@ Dropdown.defaultProps = {
Dropdown.propTypes = { Dropdown.propTypes = {
isOpen: PropTypes.bool.isRequired, isOpen: PropTypes.bool.isRequired,
onClick: PropTypes.func.isRequired,
children: PropTypes.node, children: PropTypes.node,
style: PropTypes.object.isRequired, style: PropTypes.object.isRequired,
onClickOutside: PropTypes.func, onClickOutside: PropTypes.func,

View File

@ -5,6 +5,10 @@ const connect = require('react-redux').connect
const actions = require('../../../store/actions') const actions = require('../../../store/actions')
class NotificationModal extends Component { class NotificationModal extends Component {
static contextProps = {
t: PropTypes.func.isRequired,
}
render () { render () {
const { const {
header, header,
@ -15,6 +19,8 @@ class NotificationModal extends Component {
onConfirm, onConfirm,
} = this.props } = this.props
const { t } = this.context
const showButtons = showCancelButton || showConfirmButton const showButtons = showCancelButton || showConfirmButton
return h('div', [ return h('div', [
@ -39,14 +45,14 @@ class NotificationModal extends Component {
showCancelButton && h('div.btn-default.notification-modal__buttons__btn', { showCancelButton && h('div.btn-default.notification-modal__buttons__btn', {
onClick: hideModal, onClick: hideModal,
}, 'Cancel'), }, t('cancel')),
showConfirmButton && h('div.button.btn-secondary.notification-modal__buttons__btn', { showConfirmButton && h('div.button.btn-secondary.notification-modal__buttons__btn', {
onClick: () => { onClick: () => {
onConfirm() onConfirm()
hideModal() hideModal()
}, },
}, 'Confirm'), }, t('confirm')),
]), ]),

View File

@ -139,6 +139,7 @@
&__expander { &__expander {
max-height: 0px; max-height: 0px;
width: 100%; width: 100%;
overflow: hidden;
&--show { &--show {
max-height: 1000px; max-height: 1000px;

View File

@ -322,7 +322,9 @@ function reduceMetamask (state, action) {
let { selectedAddressTxList } = metamaskState let { selectedAddressTxList } = metamaskState
selectedAddressTxList = selectedAddressTxList.map(tx => { selectedAddressTxList = selectedAddressTxList.map(tx => {
if (tx.id === txId) { if (tx.id === txId) {
tx.txParams = value const newTx = Object.assign({}, tx)
newTx.txParams = value
return newTx
} }
return tx return tx
}) })

View File

@ -116,10 +116,11 @@ class ConnectHardwareForm extends Component {
} }
}) })
.catch(e => { .catch(e => {
if (e === 'Window blocked') { const errorMessage = e.message
if (errorMessage === 'Window blocked') {
this.setState({ browserSupported: false, error: null}) this.setState({ browserSupported: false, error: null})
} else if (e !== 'Window closed' && e !== 'Popup closed') { } else if (errorMessage !== 'Window closed' && errorMessage !== 'Popup closed') {
this.setState({ error: e.toString() }) this.setState({ error: errorMessage })
} }
}) })
} }
@ -134,7 +135,7 @@ class ConnectHardwareForm extends Component {
unlocked: false, unlocked: false,
}) })
}).catch(e => { }).catch(e => {
this.setState({ error: e.toString() }) this.setState({ error: e.message })
}) })
} }
@ -162,10 +163,10 @@ class ConnectHardwareForm extends Component {
name: 'Error connecting hardware wallet', name: 'Error connecting hardware wallet',
}, },
customVariables: { customVariables: {
error: e.toString(), error: e.message,
}, },
}) })
this.setState({ error: e.toString() }) this.setState({ error: e.message })
}) })
} }

View File

@ -175,6 +175,12 @@ export default class ImportWithSeedPhrase extends PureComponent {
return !passwordError && !confirmPasswordError && !seedPhraseError return !passwordError && !confirmPasswordError && !seedPhraseError
} }
onTermsKeyPress = ({key}) => {
if (key === ' ' || key === 'Enter') {
this.toggleTermsCheck()
}
}
toggleTermsCheck = () => { toggleTermsCheck = () => {
this.context.metricsEvent({ this.context.metricsEvent({
eventOpts: { eventOpts: {
@ -183,7 +189,6 @@ export default class ImportWithSeedPhrase extends PureComponent {
name: 'Check ToS', name: 'Check ToS',
}, },
}) })
this.setState((prevState) => ({ this.setState((prevState) => ({
termsChecked: !prevState.termsChecked, termsChecked: !prevState.termsChecked,
})) }))
@ -267,10 +272,17 @@ export default class ImportWithSeedPhrase extends PureComponent {
largeLabel largeLabel
/> />
<div className="first-time-flow__checkbox-container" onClick={this.toggleTermsCheck}> <div className="first-time-flow__checkbox-container" onClick={this.toggleTermsCheck}>
<div className="first-time-flow__checkbox"> <div
className="first-time-flow__checkbox"
tabIndex="0"
role="checkbox"
onKeyPress={this.onTermsKeyPress}
aria-checked={termsChecked}
aria-labelledby="ftf-chk1-label"
>
{termsChecked ? <i className="fa fa-check fa-2x" /> : null} {termsChecked ? <i className="fa fa-check fa-2x" /> : null}
</div> </div>
<span className="first-time-flow__checkbox-label"> <span id="ftf-chk1-label" className="first-time-flow__checkbox-label">
I have read and agree to the <a I have read and agree to the <a
href="https://metamask.io/terms.html" href="https://metamask.io/terms.html"
target="_blank" target="_blank"

View File

@ -3,7 +3,6 @@ import PropTypes from 'prop-types'
import Button from '../../../../components/ui/button' import Button from '../../../../components/ui/button'
import { import {
INITIALIZE_SEED_PHRASE_ROUTE, INITIALIZE_SEED_PHRASE_ROUTE,
INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE,
INITIALIZE_SELECT_ACTION_ROUTE, INITIALIZE_SELECT_ACTION_ROUTE,
} from '../../../../helpers/constants/routes' } from '../../../../helpers/constants/routes'
import TextField from '../../../../components/ui/text-field' import TextField from '../../../../components/ui/text-field'
@ -115,13 +114,6 @@ export default class NewAccount extends PureComponent {
} }
} }
handleImportWithSeedPhrase = event => {
const { history } = this.props
event.preventDefault()
history.push(INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE)
}
toggleTermsCheck = () => { toggleTermsCheck = () => {
this.context.metricsEvent({ this.context.metricsEvent({
eventOpts: { eventOpts: {
@ -136,6 +128,12 @@ export default class NewAccount extends PureComponent {
})) }))
} }
onTermsKeyPress = ({key}) => {
if (key === ' ' || key === 'Enter') {
this.toggleTermsCheck()
}
}
render () { render () {
const { t } = this.context const { t } = this.context
const { password, confirmPassword, passwordError, confirmPasswordError, termsChecked } = this.state const { password, confirmPassword, passwordError, confirmPasswordError, termsChecked } = this.state
@ -195,10 +193,17 @@ export default class NewAccount extends PureComponent {
largeLabel largeLabel
/> />
<div className="first-time-flow__checkbox-container" onClick={this.toggleTermsCheck}> <div className="first-time-flow__checkbox-container" onClick={this.toggleTermsCheck}>
<div className="first-time-flow__checkbox"> <div
className="first-time-flow__checkbox"
tabIndex="0"
role="checkbox"
onKeyPress={this.onTermsKeyPress}
aria-checked={termsChecked}
aria-labelledby="ftf-chk1-label"
>
{termsChecked ? <i className="fa fa-check fa-2x" /> : null} {termsChecked ? <i className="fa fa-check fa-2x" /> : null}
</div> </div>
<span className="first-time-flow__checkbox-label"> <span id="ftf-chk1-label" className="first-time-flow__checkbox-label">
I have read and agree to the <a I have read and agree to the <a
href="https://metamask.io/terms.html" href="https://metamask.io/terms.html"
target="_blank" target="_blank"

View File

@ -165,6 +165,7 @@ export default class SendTransactionScreen extends PersistentForm {
if (selectedTokenAddress && prevTokenAddress !== selectedTokenAddress) { if (selectedTokenAddress && prevTokenAddress !== selectedTokenAddress) {
this.updateSendToken() this.updateSendToken()
this.updateGas()
} }
} }

View File

@ -57,10 +57,10 @@ describe('Send Component', function () {
primaryCurrency="mockPrimaryCurrency" primaryCurrency="mockPrimaryCurrency"
recentBlocks={['mockBlock']} recentBlocks={['mockBlock']}
selectedAddress="mockSelectedAddress" selectedAddress="mockSelectedAddress"
selectedToken="mockSelectedToken" selectedToken={{ address: 'mockTokenAddress', decimals: 18, symbol: 'TST' }}
showHexData showHexData
tokenBalance="mockTokenBalance" tokenBalance="mockTokenBalance"
tokenContract="mockTokenContract" tokenContract={{ method: 'mockTokenMethod' }}
updateAndSetGasLimit={propsMethodSpies.updateAndSetGasLimit} updateAndSetGasLimit={propsMethodSpies.updateAndSetGasLimit}
updateSendErrors={propsMethodSpies.updateSendErrors} updateSendErrors={propsMethodSpies.updateSendErrors}
updateSendTokenBalance={propsMethodSpies.updateSendTokenBalance} updateSendTokenBalance={propsMethodSpies.updateSendTokenBalance}
@ -79,6 +79,7 @@ describe('Send Component', function () {
propsMethodSpies.updateAndSetGasLimit.resetHistory() propsMethodSpies.updateAndSetGasLimit.resetHistory()
propsMethodSpies.updateSendErrors.resetHistory() propsMethodSpies.updateSendErrors.resetHistory()
propsMethodSpies.updateSendTokenBalance.resetHistory() propsMethodSpies.updateSendTokenBalance.resetHistory()
propsMethodSpies.updateToNicknameIfNecessary.resetHistory()
}) })
it('should call componentDidMount', () => { it('should call componentDidMount', () => {
@ -129,7 +130,7 @@ describe('Send Component', function () {
prevBalance: '', prevBalance: '',
prevGasTotal: undefined, prevGasTotal: undefined,
prevTokenBalance: undefined, prevTokenBalance: undefined,
selectedToken: 'mockSelectedToken', selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' },
tokenBalance: 'mockTokenBalance', tokenBalance: 'mockTokenBalance',
} }
) )
@ -162,7 +163,7 @@ describe('Send Component', function () {
conversionRate: 10, conversionRate: 10,
gasTotal: 'mockGasTotal', gasTotal: 'mockGasTotal',
primaryCurrency: 'mockPrimaryCurrency', primaryCurrency: 'mockPrimaryCurrency',
selectedToken: 'mockSelectedToken', selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' },
tokenBalance: 'mockTokenBalance', tokenBalance: 'mockTokenBalance',
} }
) )
@ -184,7 +185,7 @@ describe('Send Component', function () {
conversionRate: 10, conversionRate: 10,
gasTotal: 'mockGasTotal', gasTotal: 'mockGasTotal',
primaryCurrency: 'mockPrimaryCurrency', primaryCurrency: 'mockPrimaryCurrency',
selectedToken: 'mockSelectedToken', selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' },
} }
) )
}) })
@ -225,7 +226,7 @@ describe('Send Component', function () {
it('should call updateSendErrors with the expected params if selectedToken is truthy', () => { it('should call updateSendErrors with the expected params if selectedToken is truthy', () => {
propsMethodSpies.updateSendErrors.resetHistory() propsMethodSpies.updateSendErrors.resetHistory()
wrapper.setProps({ selectedToken: 'someToken' }) wrapper.setProps({ selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' }})
wrapper.instance().componentDidUpdate({ wrapper.instance().componentDidUpdate({
from: { from: {
balance: 'balanceChanged', balance: 'balanceChanged',
@ -246,6 +247,7 @@ describe('Send Component', function () {
balance: 'balanceChanged', balance: 'balanceChanged',
}, },
network: '3', network: '3',
selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' }, // Make sure not to hit updateGas when changing asset
}) })
assert.equal(propsMethodSpies.updateSendTokenBalance.callCount, 0) assert.equal(propsMethodSpies.updateSendTokenBalance.callCount, 0)
assert.equal(SendTransactionScreen.prototype.updateGas.callCount, 0) assert.equal(SendTransactionScreen.prototype.updateGas.callCount, 0)
@ -260,6 +262,7 @@ describe('Send Component', function () {
balance: 'balanceChanged', balance: 'balanceChanged',
}, },
network: '3', network: '3',
selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' }, // Make sure not to hit updateGas when changing asset
}) })
assert.equal(propsMethodSpies.updateSendTokenBalance.callCount, 0) assert.equal(propsMethodSpies.updateSendTokenBalance.callCount, 0)
assert.equal(SendTransactionScreen.prototype.updateGas.callCount, 0) assert.equal(SendTransactionScreen.prototype.updateGas.callCount, 0)
@ -273,13 +276,14 @@ describe('Send Component', function () {
balance: 'balanceChanged', balance: 'balanceChanged',
}, },
network: '2', network: '2',
selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' }, // Make sure not to hit updateGas when changing asset
}) })
assert.equal(propsMethodSpies.updateSendTokenBalance.callCount, 1) assert.equal(propsMethodSpies.updateSendTokenBalance.callCount, 1)
assert.deepEqual( assert.deepEqual(
propsMethodSpies.updateSendTokenBalance.getCall(0).args[0], propsMethodSpies.updateSendTokenBalance.getCall(0).args[0],
{ {
selectedToken: 'mockSelectedToken', selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' }, // Make sure not to hit updateGas when changing asset
tokenContract: 'mockTokenContract', tokenContract: { method: 'mockTokenMethod' },
address: 'mockAddress', address: 'mockAddress',
} }
) )
@ -289,6 +293,20 @@ describe('Send Component', function () {
[] []
) )
}) })
it('should call updateGas when selectedToken.address is changed', () => {
SendTransactionScreen.prototype.updateGas.resetHistory()
propsMethodSpies.updateAndSetGasLimit.resetHistory()
wrapper.instance().componentDidUpdate({
from: {
balance: 'balancedChanged',
},
network: '3', // Make sure not to hit updateGas when changing network
selectedToken: { address: 'newSelectedToken' },
})
assert.equal(propsMethodSpies.updateToNicknameIfNecessary.callCount, 0) // Network did not change
assert.equal(propsMethodSpies.updateAndSetGasLimit.callCount, 1)
})
}) })
describe('updateGas', () => { describe('updateGas', () => {
@ -305,7 +323,7 @@ describe('Send Component', function () {
gasPrice: 'mockGasPrice', gasPrice: 'mockGasPrice',
recentBlocks: ['mockBlock'], recentBlocks: ['mockBlock'],
selectedAddress: 'mockSelectedAddress', selectedAddress: 'mockSelectedAddress',
selectedToken: 'mockSelectedToken', selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' },
to: '', to: '',
value: 'mockAmount', value: 'mockAmount',
data: undefined, data: undefined,
@ -431,9 +449,7 @@ describe('Send Component', function () {
}) })
it('should warn when send to a known token contract address', () => { it('should warn when send to a known token contract address', () => {
wrapper.setProps({ wrapper.setProps({ address: '0x888', decimals: 18, symbol: '888' })
selectedToken: '0x888',
})
const instance = wrapper.instance() const instance = wrapper.instance()
instance.onRecipientInputChange('0x13cb85823f78Cff38f0B0E90D3e975b8CB3AAd64') instance.onRecipientInputChange('0x13cb85823f78Cff38f0B0E90D3e975b8CB3AAd64')