Merge pull request #6765 from MetaMask/master

Using admin privilege to bypass code owner review because it has already [been reviewed](https://github.com/MetaMask/metamask-extension/pull/6763) and those code owners are out today.
feature/default_network_editable
Dan Finlay 5 years ago committed by GitHub
commit 448720327b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      .circleci/config.yml
  2. 12
      CHANGELOG.md
  3. 2
      app/manifest.json
  4. 14
      test/e2e/beta/contract-test/contract.js
  5. 26
      test/e2e/beta/metamask-beta-ui.spec.js
  6. 21
      ui/app/helpers/utils/token-util.js
  7. 20
      ui/app/helpers/utils/transactions.util.js
  8. 29
      ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js
  9. 4
      ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js
  10. 9
      ui/app/pages/confirm-transaction/confirm-transaction.component.js
  11. 9
      ui/app/pages/confirm-transaction/confirm-transaction.container.js
  12. 43
      ui/app/store/actions.js

@ -8,9 +8,9 @@ workflows:
- prep-build:
requires:
- prep-deps-npm
- prep-docs:
requires:
- prep-deps-npm
# - prep-docs:
# requires:
# - prep-deps-npm
- prep-scss:
requires:
- prep-deps-npm
@ -73,7 +73,7 @@ workflows:
requires:
- prep-deps-npm
- prep-build
- prep-docs
# - prep-docs
- job-screens
- all-tests-pass
@ -258,12 +258,12 @@ jobs:
- run:
name: sentry sourcemaps upload
command: npm run sentry:publish
- run:
name: github gh-pages docs publish
command: >
git config --global user.name "metamaskbot" &&
git config --global user.email "admin@metamask.io" &&
npm run publish-docs
# - run:
# name: github gh-pages docs publish
# command: >
# git config --global user.name "metamaskbot" &&
# git config --global user.email "admin@metamask.io" &&
# npm run publish-docs
test-unit:
docker:

@ -1,6 +1,18 @@
# Changelog
## Current Develop Branch
## 6.7.1 Fri Jun 28 2019
- [#6764](https://github.com/MetaMask/metamask-extension/pull/6764): Fix display of token amount on confirm transaction screen
## 6.7.0 Tue Jun 18 2019
- [#6623](https://github.com/MetaMask/metamask-extension/pull/6623): Improve contract method data fetching (#6623)
- [#6551](https://github.com/MetaMask/metamask-extension/pull/6551): Adds 4byte registry fallback to getMethodData() (#6435)
- [#6718, #6650](https://github.com/MetaMask/metamask-extension/pull/6718, #6650): Add delete to custom RPC form
- [#6700](https://github.com/MetaMask/metamask-extension/pull/6700): Fix styles on 'import account' page, update help link
- [#6714](https://github.com/MetaMask/metamask-extension/pull/6714): Wrap smaller custom block explorer url text
- [#6706](https://github.com/MetaMask/metamask-extension/pull/6706): Pin ethereumjs-tx
- [#6700](https://github.com/MetaMask/metamask-extension/pull/6700): Fix styles on 'import account' page, update help link
## 6.6.2 Fri Jun 07 2019

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

File diff suppressed because one or more lines are too long

@ -983,9 +983,9 @@ describe('MetaMask', function () {
it('renders the balance for the new token', async () => {
const balance = await findElement(driver, By.css('.transaction-view-balance .transaction-view-balance__primary-balance'))
await driver.wait(until.elementTextMatches(balance, /^100\s*TST\s*$/))
await driver.wait(until.elementTextMatches(balance, /^10.000\s*TST\s*$/))
const tokenAmount = await balance.getText()
assert.ok(/^100\s*TST\s*$/.test(tokenAmount))
assert.ok(/^10.000\s*TST\s*$/.test(tokenAmount))
await delay(regularDelayMs)
})
})
@ -1000,7 +1000,7 @@ describe('MetaMask', function () {
const inputAddress = await findElement(driver, By.css('input[placeholder="Recipient Address"]'))
const inputAmount = await findElement(driver, By.css('.unit-input__input'))
await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970')
await inputAmount.sendKeys('50')
await inputAmount.sendKeys('1')
// Set the gas limit
const configureGas = await findElement(driver, By.css('.advanced-gas-options-btn'))
@ -1036,6 +1036,10 @@ describe('MetaMask', function () {
const functionTypeText = await functionType.getText()
assert.equal(functionTypeText, 'Transfer')
const tokenAmount = await findElement(driver, By.css('.confirm-page-container-summary__title-text'))
const tokenAmountText = await tokenAmount.getText()
assert.equal(tokenAmountText, '1 TST')
const confirmDataDiv = await findElement(driver, By.css('.confirm-page-container-content__data-box'))
const confirmDataText = await confirmDataDiv.getText()
@ -1063,7 +1067,7 @@ describe('MetaMask', function () {
// test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved,
// or possibly until we use latest version of firefox in the tests
if (process.env.SELENIUM_BROWSER !== 'firefox') {
await driver.wait(until.elementTextMatches(txValues[0], /-50\s*TST/), 10000)
await driver.wait(until.elementTextMatches(txValues[0], /-1\s*TST/), 10000)
}
await driver.wait(async () => {
@ -1094,7 +1098,7 @@ describe('MetaMask', function () {
await findElements(driver, By.css('.transaction-list__pending-transactions'))
const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/), 10000)
await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/), 10000)
await txListValue.click()
await delay(regularDelayMs)
@ -1148,6 +1152,10 @@ describe('MetaMask', function () {
})
it('submits the transaction', async function () {
const tokenAmount = await findElement(driver, By.css('.confirm-page-container-summary__title-text'))
const tokenAmountText = await tokenAmount.getText()
assert.equal(tokenAmountText, '1.5 TST')
const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
await confirmButton.click()
await delay(regularDelayMs)
@ -1161,7 +1169,7 @@ describe('MetaMask', function () {
await delay(regularDelayMs)
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
await driver.wait(until.elementTextMatches(txValues[0], /-7\s*TST/))
await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/))
const txStatuses = await findElements(driver, By.css('.transaction-list-item__action'))
await driver.wait(until.elementTextMatches(txStatuses[0], /Sent\sToken/), 10000)
@ -1176,7 +1184,7 @@ describe('MetaMask', function () {
// or possibly until we use latest version of firefox in the tests
if (process.env.SELENIUM_BROWSER !== 'firefox') {
const tokenBalanceAmount = await findElements(driver, By.css('.transaction-view-balance__primary-balance'))
await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /43\s*TST/), 10000)
await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.500\s*TST/), 10000)
}
})
})
@ -1326,7 +1334,7 @@ describe('MetaMask', function () {
const [txListItem] = await findElements(driver, By.css('.transaction-list-item'))
const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/))
await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/))
await txListItem.click()
await delay(regularDelayMs)
})
@ -1345,7 +1353,7 @@ describe('MetaMask', function () {
}, 10000)
const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
await driver.wait(until.elementTextMatches(txValues[0], /-7\s*TST/))
await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/))
const txStatuses = await findElements(driver, By.css('.transaction-list-item__action'))
await driver.wait(until.elementTextMatches(txStatuses[0], /Sent Tokens/))
})

@ -68,6 +68,22 @@ async function getDecimals (tokenAddress) {
return decimals
}
export async function fetchSymbolAndDecimals (tokenAddress) {
let symbol, decimals
try {
symbol = await getSymbol(tokenAddress)
decimals = await getDecimals(tokenAddress)
} catch (error) {
log.warn(`symbol() and decimal() calls for token at address ${tokenAddress} resulted in error:`, error)
}
return {
symbol: symbol || DEFAULT_SYMBOL,
decimals: decimals || DEFAULT_DECIMALS,
}
}
export async function getSymbolAndDecimals (tokenAddress, existingTokens = []) {
const existingToken = existingTokens.find(({ address }) => tokenAddress === address)
@ -116,3 +132,8 @@ export function getTokenValue (tokenParams = []) {
const valueData = tokenParams.find(param => param.name === '_value')
return valueData && valueData.value
}
export function getTokenToAddress (tokenParams = []) {
const toAddressData = tokenParams.find(param => param.name === '_to')
return toAddressData && toAddressData.value
}

@ -102,6 +102,20 @@ export function getFourBytePrefix (data = '') {
return fourBytePrefix
}
/**
* Given an transaction category, returns a boolean which indicates whether the transaction is calling an erc20 token method
*
* @param {string} transactionCategory - The category of transaction being evaluated
* @returns {boolean} - whether the transaction is calling an erc20 token method
*/
export function isTokenMethodAction (transactionCategory) {
return [
TOKEN_METHOD_TRANSFER,
TOKEN_METHOD_APPROVE,
TOKEN_METHOD_TRANSFER_FROM,
].includes(transactionCategory)
}
/**
* Returns the action of a transaction as a key to be passed into the translator.
* @param {Object} transaction - txData object
@ -122,11 +136,7 @@ export function getTransactionActionKey (transaction) {
return DEPLOY_CONTRACT_ACTION_KEY
}
const isTokenAction = [
TOKEN_METHOD_TRANSFER,
TOKEN_METHOD_APPROVE,
TOKEN_METHOD_TRANSFER_FROM,
].find(actionName => actionName === transactionCategory)
const isTokenAction = isTokenMethodAction(transactionCategory)
const isNonTokenSmartContract = transactionCategory === CONTRACT_INTERACTION_KEY
if (isTokenAction || isNonTokenSmartContract) {

@ -1,27 +1,42 @@
import { connect } from 'react-redux'
import ConfirmTokenTransactionBase from './confirm-token-transaction-base.component'
import {
tokenAmountAndToAddressSelector,
contractExchangeRateSelector,
} from '../../selectors/confirm-transaction'
import { tokenSelector } from '../../selectors/tokens'
import {
getTokenData,
} from '../../helpers/utils/transactions.util'
import {
calcTokenAmount,
getTokenToAddress,
getTokenValue,
} from '../../helpers/utils/token-util'
const mapStateToProps = (state, ownProps) => {
const { tokenAmount: ownTokenAmount } = ownProps
const mapStateToProps = (state) => {
const { confirmTransaction, metamask: { currentCurrency, conversionRate } } = state
const {
txData: { txParams: { to: tokenAddress } = {} } = {},
tokenProps: { tokenSymbol } = {},
txData: { txParams: { to: tokenAddress, data } = {} } = {},
fiatTransactionTotal,
ethTransactionTotal,
} = confirmTransaction
const { tokenAmount, toAddress } = tokenAmountAndToAddressSelector(state)
const tokens = tokenSelector(state)
const currentToken = tokens && tokens.find(({ address }) => tokenAddress === address)
const { decimals, symbol: tokenSymbol } = currentToken || {}
const tokenData = getTokenData(data)
const tokenValue = tokenData && getTokenValue(tokenData.params)
const toAddress = tokenData && getTokenToAddress(tokenData.params)
const tokenAmount = tokenData && calcTokenAmount(tokenValue, decimals).toString()
const contractExchangeRate = contractExchangeRateSelector(state)
return {
toAddress,
tokenAddress,
tokenAmount: typeof ownTokenAmount !== 'undefined' ? ownTokenAmount : tokenAmount,
tokenAmount,
tokenSymbol,
currentCurrency,
conversionRate,

@ -91,6 +91,10 @@ const mapStateToProps = (state, ownProps) => {
const transaction = R.find(({ id }) => id === (transactionId || Number(paramsTransactionId)))(selectedAddressTxList)
const transactionStatus = transaction ? transaction.status : ''
if (transaction && transaction.simulationFails) {
txData.simulationFails = transaction.simulationFails
}
const currentNetworkUnapprovedTxs = R.filter(
({ metamaskNetworkId }) => metamaskNetworkId === network,
unapprovedTxs,

@ -37,6 +37,8 @@ export default class ConfirmTransaction extends Component {
getContractMethodData: PropTypes.func,
transactionId: PropTypes.string,
paramsTransactionId: PropTypes.string,
getTokenParams: PropTypes.func,
isTokenMethodAction: PropTypes.bool,
}
getParamsTransactionId () {
@ -49,11 +51,13 @@ export default class ConfirmTransaction extends Component {
totalUnapprovedCount = 0,
send = {},
history,
transaction: { txParams: { data } = {} } = {},
transaction: { txParams: { data, to } = {} } = {},
fetchBasicGasAndTimeEstimates,
getContractMethodData,
transactionId,
paramsTransactionId,
getTokenParams,
isTokenMethodAction,
} = this.props
if (!totalUnapprovedCount && !send.to) {
@ -63,6 +67,9 @@ export default class ConfirmTransaction extends Component {
fetchBasicGasAndTimeEstimates()
getContractMethodData(data)
if (isTokenMethodAction) {
getTokenParams(to)
}
this.props.setTransactionToConfirm(transactionId || paramsTransactionId)
}

@ -5,12 +5,16 @@ import {
setTransactionToConfirm,
clearConfirmTransaction,
} from '../../ducks/confirm-transaction/confirm-transaction.duck'
import {
isTokenMethodAction,
} from '../../helpers/utils/transactions.util'
import {
fetchBasicGasAndTimeEstimates,
} from '../../ducks/gas/gas.duck'
import {
getContractMethodData,
getTokenParams,
} from '../../store/actions'
import ConfirmTransaction from './confirm-transaction.component'
import { unconfirmedTransactionsListSelector } from '../../selectors/confirm-transaction'
@ -25,6 +29,7 @@ const mapStateToProps = (state, ownProps) => {
const transaction = totalUnconfirmed
? unapprovedTxs[id] || unconfirmedTransactions[totalUnconfirmed - 1]
: {}
const { id: transactionId, transactionCategory } = transaction
return {
totalUnapprovedCount: totalUnconfirmed,
@ -33,9 +38,10 @@ const mapStateToProps = (state, ownProps) => {
unapprovedTxs,
id,
paramsTransactionId: id && String(id),
transactionId: transaction.id && String(transaction.id),
transactionId: transactionId && String(transactionId),
unconfirmedTransactions,
transaction,
isTokenMethodAction: isTokenMethodAction(transactionCategory),
}
}
@ -47,6 +53,7 @@ const mapDispatchToProps = dispatch => {
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
fetchBasicGasAndTimeEstimates: () => dispatch(fetchBasicGasAndTimeEstimates()),
getContractMethodData: (data) => dispatch(getContractMethodData(data)),
getTokenParams: (tokenAddress) => dispatch(getTokenParams(tokenAddress)),
}
}

@ -9,6 +9,7 @@ const {
const ethUtil = require('ethereumjs-util')
const { fetchLocale } = require('../helpers/utils/i18n-helper')
const { getMethodDataAsync } = require('../helpers/utils/transactions.util')
const { fetchSymbolAndDecimals } = require('../helpers/utils/token-util')
const log = require('loglevel')
const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../../app/scripts/lib/enums')
const { hasUnconfirmedTransactions } = require('../helpers/utils/confirm-tx.util')
@ -367,6 +368,12 @@ var actions = {
loadingMethoDataFinished,
LOADING_METHOD_DATA_STARTED: 'LOADING_METHOD_DATA_STARTED',
LOADING_METHOD_DATA_FINISHED: 'LOADING_METHOD_DATA_FINISHED',
getTokenParams,
loadingTokenParamsStarted,
LOADING_TOKEN_PARAMS_STARTED: 'LOADING_TOKEN_PARAMS_STARTED',
loadingTokenParamsFinished,
LOADING_TOKEN_PARAMS_FINISHED: 'LOADING_TOKEN_PARAMS_FINISHED',
}
module.exports = actions
@ -2812,3 +2819,39 @@ function getContractMethodData (data = '') {
})
}
}
function loadingTokenParamsStarted () {
return {
type: actions.LOADING_TOKEN_PARAMS_STARTED,
}
}
function loadingTokenParamsFinished () {
return {
type: actions.LOADING_TOKEN_PARAMS_FINISHED,
}
}
function getTokenParams (tokenAddress) {
return (dispatch, getState) => {
const existingTokens = getState().metamask.tokens
const existingToken = existingTokens.find(({ address }) => tokenAddress === address)
if (existingToken) {
return Promise.resolve({
symbol: existingToken.symbol,
decimals: existingToken.decimals,
})
}
dispatch(actions.loadingTokenParamsStarted())
log.debug(`loadingTokenParams`)
return fetchSymbolAndDecimals(tokenAddress, existingTokens)
.then(({ symbol, decimals }) => {
dispatch(actions.addToken(tokenAddress, symbol, decimals))
dispatch(actions.loadingTokenParamsFinished())
})
}
}

Loading…
Cancel
Save