From 9dd637569d5c820d07ff15a8039f5ce5590f41dd Mon Sep 17 00:00:00 2001 From: 03-26 <37808790+03-26@users.noreply.github.com> Date: Sun, 15 Jul 2018 15:09:18 +0900 Subject: [PATCH 01/23] Update --- app/_locales/ja/messages.json | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 75deeaddf..c9d192139 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -122,6 +122,9 @@ "copy": { "message": "コピー" }, + "copyContractAddress": { + "message": "コントラクトアドレスをコピー" + }, "copyToClipboard": { "message": "クリップボードへコピー" }, @@ -395,6 +398,9 @@ "mainnet": { "message": "Ethereumメインネットワーク" }, + "menu": { + "message": "メニュー" + }, "message": { "message": "メッセージ" }, @@ -464,6 +470,9 @@ "oldUIMessage": { "message": "旧UIを表示しています。右上のドロップダウンメニューのオプションより、新UIへ切り替えが可能です。" }, + "openInTab": { + "message": "タブを開く" + }, "or": { "message": "または", "description": "choice between creating or importing a new account" @@ -573,6 +582,15 @@ "searchResults": { "message": "検索結果" }, + "newPassword8Chars": { + "message": "新しいパスワード (8桁以上)" + }, + "select": { + "message": "選択" + }, + "selectCurrency": { + "message": "通貨を選択" + }, "selectService": { "message": "サービスを選択" }, @@ -586,10 +604,14 @@ "message": "ETHの送信" }, "sendTokens": { - "message": "トークンを送る" + "message": "トークンを送信" }, "onlySendToEtherAddress": { - "message": "ETHはイーサリウムアカウントのみに送信できます。" + "message": "ETH はイーサリウムアカウントのみに送信できます。" + }, + "onlySendTokensToAccountAddress": { + "message": "$1 はイーサリアムアカウントのみに送信できます。", + "description": "displays token symbol" }, "searchTokens": { "message": "トークンの検索" @@ -690,10 +712,10 @@ "message": "パスワードの入力" }, "uiWelcome": { - "message": "新UIへようこそ!(ベータ版)" + "message": "新UIへようこそ! (ベータ版)" }, "uiWelcomeMessage": { - "message": "現在Metamaskの新しいUIをお使いになっています。トークン送信など、新たな機能を試してみましょう!何か問題があればご報告ください。" + "message": "現在、MetaMask の新しいUIをお使いになっています。トークン送信など、新たな機能を試してみましょう! 何か問題があればご報告ください。" }, "unavailable": { "message": "有効ではありません。" @@ -720,6 +742,9 @@ "viewAccount": { "message": "アカウントを見る" }, + "viewOnEtherscan": { + "message": "Etherscan で見る" + }, "warning": { "message": "警告" }, From c3c0193a64fe8479ac5e23ae0b73016c09789f9f Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 17 Jul 2018 20:14:53 -0700 Subject: [PATCH 02/23] Added codeowners file --- .github/CODEOWNERS | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..1cdadda65 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +# Lines starting with '#' are comments. +# Each line is a file pattern followed by one or more owners. + +ui/ @danjm @alextsg @whymarrh +app/scripts/controllers/transactions @frankiebee + From dd9e3587d47c9a233cea5f7b305d8faa08ee6a0e Mon Sep 17 00:00:00 2001 From: Dan Finlay <542863+danfinlay@users.noreply.github.com> Date: Wed, 18 Jul 2018 15:23:32 -0700 Subject: [PATCH 03/23] Do not inject on ani.gamer.com.tw Fixes #4799 --- app/scripts/contentscript.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 04dd51b01..f2a2469c9 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -178,6 +178,7 @@ function blacklistedDomainCheck () { 'adyen.com', 'gravityforms.com', 'harbourair.com', + 'ani.gamer.com.tw', ] var currentUrl = window.location.href var currentRegex From cdda52d799ea9edeb135de44e02fecc9d6d8e94b Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 20 Jul 2018 10:25:45 -0700 Subject: [PATCH 04/23] Add ButtonGroup component --- .../button-group/button-group.component.js | 61 +++++++++++++++++++ .../button-group/button-group.stories.js | 49 +++++++++++++++ ui/app/components/button-group/index.js | 1 + ui/app/components/button-group/index.scss | 38 ++++++++++++ ui/app/components/index.scss | 2 + 5 files changed, 151 insertions(+) create mode 100644 ui/app/components/button-group/button-group.component.js create mode 100644 ui/app/components/button-group/button-group.stories.js create mode 100644 ui/app/components/button-group/index.js create mode 100644 ui/app/components/button-group/index.scss diff --git a/ui/app/components/button-group/button-group.component.js b/ui/app/components/button-group/button-group.component.js new file mode 100644 index 000000000..f99f710ce --- /dev/null +++ b/ui/app/components/button-group/button-group.component.js @@ -0,0 +1,61 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' +import classnames from 'classnames' + +export default class ButtonGroup extends PureComponent { + static propTypes = { + defaultActiveButtonIndex: PropTypes.number, + disabled: PropTypes.bool, + children: PropTypes.array, + className: PropTypes.string, + style: PropTypes.object, + } + + static defaultProps = { + className: 'button-group', + } + + state = { + activeButtonIndex: this.props.defaultActiveButtonIndex || 0, + } + + handleButtonClick (activeButtonIndex) { + this.setState({ activeButtonIndex }) + } + + renderButtons () { + const { children, disabled } = this.props + + return React.Children.map(children, (child, index) => { + return child && ( + + ) + }) + } + + render () { + const { className, style } = this.props + + return ( +
+ { this.renderButtons() } +
+ ) + } +} diff --git a/ui/app/components/button-group/button-group.stories.js b/ui/app/components/button-group/button-group.stories.js new file mode 100644 index 000000000..14e1a7e49 --- /dev/null +++ b/ui/app/components/button-group/button-group.stories.js @@ -0,0 +1,49 @@ +import React from 'react' +import { storiesOf } from '@storybook/react' +import { action } from '@storybook/addon-actions' +import ButtonGroup from './' +import Button from '../button' +import { text, boolean } from '@storybook/addon-knobs/react' + +storiesOf('ButtonGroup', module) + .add('with Buttons', () => + + + + + + ) + .add('with a disabled Button', () => + + + + + ) diff --git a/ui/app/components/button-group/index.js b/ui/app/components/button-group/index.js new file mode 100644 index 000000000..df470bd57 --- /dev/null +++ b/ui/app/components/button-group/index.js @@ -0,0 +1 @@ +export { default } from './button-group.component' diff --git a/ui/app/components/button-group/index.scss b/ui/app/components/button-group/index.scss new file mode 100644 index 000000000..29713c75b --- /dev/null +++ b/ui/app/components/button-group/index.scss @@ -0,0 +1,38 @@ +.button-group { + display: flex; + justify-content: center; + align-items: center; + + &__button { + font-family: Roboto; + font-size: 1rem; + color: $tundora; + border-style: solid; + border-color: $alto; + border-width: 1px 1px 1px; + border-left: 0; + flex: 1; + padding: 12px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + &:first-child { + border-left: 1px solid $alto; + border-radius: 4px 0 0 4px; + } + + &:last-child { + border-radius: 0 4px 4px 0; + } + + &--active { + background-color: $dodger-blue; + color: $white; + } + + &:disabled { + opacity: .5; + } + } +} \ No newline at end of file diff --git a/ui/app/components/index.scss b/ui/app/components/index.scss index 32f0e90e4..b3e14ce23 100644 --- a/ui/app/components/index.scss +++ b/ui/app/components/index.scss @@ -1,3 +1,5 @@ +@import './button-group/index'; + @import './export-text-container/index'; @import './selected-account/index'; From 519ca1c74ba4dab1e803a30722149902c5da550a Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Mon, 23 Jul 2018 09:38:02 -0700 Subject: [PATCH 05/23] Update Chinese naming I sincerely hope this is a non-controversial change. --- app/_locales/index.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/_locales/index.json b/app/_locales/index.json index 7717502b7..f50c09f88 100644 --- a/app/_locales/index.json +++ b/app/_locales/index.json @@ -17,6 +17,6 @@ { "code": "tml", "name": "Tamil" }, { "code": "tr", "name": "Turkish" }, { "code": "vi", "name": "Vietnamese" }, - { "code": "zh_CN", "name": "Mandarin" }, - { "code": "zh_TW", "name": "Taiwanese" } + { "code": "zh_CN", "name": "Chinese (Simplified)" }, + { "code": "zh_TW", "name": "Chinese (Traditional)" } ] From a146e5ebbcdf3ff334d2a5fb3b7aba1dcac9ab12 Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Mon, 23 Jul 2018 16:49:28 -0230 Subject: [PATCH 06/23] Adds tests for button group component. --- .../tests/button-group-component.test.js | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 ui/app/components/button-group/tests/button-group-component.test.js diff --git a/ui/app/components/button-group/tests/button-group-component.test.js b/ui/app/components/button-group/tests/button-group-component.test.js new file mode 100644 index 000000000..f07bb97c8 --- /dev/null +++ b/ui/app/components/button-group/tests/button-group-component.test.js @@ -0,0 +1,97 @@ +import React from 'react' +import assert from 'assert' +import { shallow } from 'enzyme' +import sinon from 'sinon' +import ButtonGroup from '../button-group.component.js' + +const childButtonSpies = { + onClick: sinon.spy(), +} + +sinon.spy(ButtonGroup.prototype, 'handleButtonClick') +sinon.spy(ButtonGroup.prototype, 'renderButtons') + +const mockButtons = [ + , + , + , +] + +describe('ButtonGroup Component', function () { + let wrapper + + beforeEach(() => { + wrapper = shallow({mockButtons}) + }) + + afterEach(() => { + childButtonSpies.onClick.resetHistory() + ButtonGroup.prototype.handleButtonClick.resetHistory() + ButtonGroup.prototype.renderButtons.resetHistory() + }) + + describe('handleButtonClick', () => { + it('should set the activeButtonIndex', () => { + assert.equal(wrapper.state('activeButtonIndex'), 1) + wrapper.instance().handleButtonClick(2) + assert.equal(wrapper.state('activeButtonIndex'), 2) + }) + }) + + describe('renderButtons', () => { + it('should render a button for each child', () => { + const childButtons = wrapper.find('.button-group__button') + assert.equal(childButtons.length, 3) + }) + + it('should render the correct button with an active state', () => { + const childButtons = wrapper.find('.button-group__button') + const activeChildButton = wrapper.find('.button-group__button--active') + assert.deepEqual(childButtons.get(1), activeChildButton.get(0)) + }) + + it('should call handleButtonClick and the respective button\'s onClick method when a button is clicked', () => { + assert.equal(ButtonGroup.prototype.handleButtonClick.callCount, 0) + assert.equal(childButtonSpies.onClick.callCount, 0) + const childButtons = wrapper.find('.button-group__button') + childButtons.at(0).props().onClick() + childButtons.at(1).props().onClick() + childButtons.at(2).props().onClick() + assert.equal(ButtonGroup.prototype.handleButtonClick.callCount, 3) + assert.equal(childButtonSpies.onClick.callCount, 3) + }) + + it('should render all child buttons as disabled if props.disabled is true', () => { + const childButtons = wrapper.find('.button-group__button') + childButtons.forEach(button => { + assert.equal(button.props().disabled, undefined) + }) + wrapper.setProps({ disabled: true }) + const disabledChildButtons = wrapper.find('[disabled=true]') + assert.equal(disabledChildButtons.length, 3) + }) + + it('should render the children of the button', () => { + const mockClass = wrapper.find('.mockClass') + assert.equal(mockClass.length, 1) + }) + }) + + describe('render', () => { + it('should render a div with the expected class and style', () => { + assert.equal(wrapper.find('div').at(0).props().className, 'someClassName') + assert.deepEqual(wrapper.find('div').at(0).props().style, { color: 'red' }) + }) + + it('should call renderButtons when rendering', () => { + assert.equal(ButtonGroup.prototype.renderButtons.callCount, 1) + wrapper.instance().render() + assert.equal(ButtonGroup.prototype.renderButtons.callCount, 2) + }) + }) +}) From 2359062b62cf65f38b36ccb6bb33fa7d15ada1ae Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Mon, 23 Jul 2018 22:20:06 -0230 Subject: [PATCH 07/23] UI confirm screen closes confirmation window on submit or cancel of a tx --- app/scripts/platforms/extension.js | 6 ++++++ app/scripts/ui.js | 8 ++++---- .../confirm-transaction-base.component.js | 19 +++++++++++++++---- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 901c26cab..bd4f7bd9f 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -14,6 +14,12 @@ class ExtensionPlatform { extension.tabs.create({ url }) } + closeCurrentWindow (cb) { + return extension.windows.getCurrent((windowDetails) => { + return extension.windows.remove(windowDetails.id) + }) + } + getVersion () { return extension.runtime.getManifest().version } diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 9bf97be87..42703f029 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -64,16 +64,16 @@ async function start () { css = betaUIState ? NewMetaMaskUiCss() : OldMetaMaskUiCss() deleteInjectedCss = injectCss(css) } - if (state.appState.shouldClose) notificationManager.closePopup() + // if (state.appState.shouldClose) notificationManager.closePopup() }) }) function closePopupIfOpen (windowType) { - if (windowType !== ENVIRONMENT_TYPE_NOTIFICATION) { + // if (windowType !== ENVIRONMENT_TYPE_NOTIFICATION) { // should close only chrome popup - notificationManager.closePopup() - } + // notificationManager.closePopup() + // } } function displayCriticalError (err) { diff --git a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js index e1bf2210f..2811e6157 100644 --- a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -8,6 +8,9 @@ import { INSUFFICIENT_FUNDS_ERROR_KEY, TRANSACTION_ERROR_KEY, } from '../../../constants/error-keys' +import { + ENVIRONMENT_TYPE_NOTIFICATION, +} from '../../../../../app/scripts/lib/enums' export default class ConfirmTransactionBase extends Component { static contextTypes = { @@ -250,8 +253,12 @@ export default class ConfirmTransactionBase extends Component { } else { cancelTransaction(txData) .then(() => { - clearConfirmTransaction() - history.push(DEFAULT_ROUTE) + if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION) { + return global.platform.closeCurrentWindow() + } else { + clearConfirmTransaction() + history.push(DEFAULT_ROUTE) + } }) } } @@ -264,8 +271,12 @@ export default class ConfirmTransactionBase extends Component { } else { sendTransaction(txData) .then(() => { - clearConfirmTransaction() - history.push(DEFAULT_ROUTE) + if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION) { + return global.platform.closeCurrentWindow() + } else { + clearConfirmTransaction() + history.push(DEFAULT_ROUTE) + } }) } } From 152246f3b0862c8c5a8b42872852d236400c0e9d Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Mon, 23 Jul 2018 20:25:04 -0700 Subject: [PATCH 08/23] Add close window support to signature requests. Move logic to actions --- ui/app/actions.js | 73 ++++++++++++++++--- .../confirm-transaction-base.component.js | 19 +---- ui/app/components/pages/home.js | 12 +-- ui/app/helpers/confirm-transaction/util.js | 6 ++ ui/app/selectors/confirm-transaction.js | 29 +++++++- 5 files changed, 108 insertions(+), 31 deletions(-) diff --git a/ui/app/actions.js b/ui/app/actions.js index 6c947fc35..7a8d9667d 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -10,6 +10,8 @@ const { const ethUtil = require('ethereumjs-util') const { fetchLocale } = require('../i18n-helper') const log = require('loglevel') +const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../app/scripts/lib/enums') +const { hasUnconfirmedTransactions } = require('./helpers/confirm-transaction/util') var actions = { _setBackgroundConnection: _setBackgroundConnection, @@ -743,7 +745,7 @@ function setCurrentCurrency (currencyCode) { function signMsg (msgData) { log.debug('action - signMsg') - return (dispatch) => { + return (dispatch, getState) => { dispatch(actions.showLoadingIndication()) return new Promise((resolve, reject) => { @@ -760,6 +762,12 @@ function signMsg (msgData) { } dispatch(actions.completedTx(msgData.metamaskId)) + + if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION && + !hasUnconfirmedTransactions(getState())) { + return global.platform.closeCurrentWindow() + } + return resolve(msgData) }) }) @@ -768,7 +776,7 @@ function signMsg (msgData) { function signPersonalMsg (msgData) { log.debug('action - signPersonalMsg') - return dispatch => { + return (dispatch, getState) => { dispatch(actions.showLoadingIndication()) return new Promise((resolve, reject) => { @@ -785,6 +793,12 @@ function signPersonalMsg (msgData) { } dispatch(actions.completedTx(msgData.metamaskId)) + + if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION && + !hasUnconfirmedTransactions(getState())) { + return global.platform.closeCurrentWindow() + } + return resolve(msgData) }) }) @@ -793,7 +807,7 @@ function signPersonalMsg (msgData) { function signTypedMsg (msgData) { log.debug('action - signTypedMsg') - return (dispatch) => { + return (dispatch, getState) => { dispatch(actions.showLoadingIndication()) return new Promise((resolve, reject) => { @@ -810,6 +824,12 @@ function signTypedMsg (msgData) { } dispatch(actions.completedTx(msgData.metamaskId)) + + if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION && + !hasUnconfirmedTransactions(getState())) { + return global.platform.closeCurrentWindow() + } + return resolve(msgData) }) }) @@ -1003,7 +1023,7 @@ function clearSend () { function sendTx (txData) { log.info(`actions - sendTx: ${JSON.stringify(txData.txParams)}`) - return (dispatch) => { + return (dispatch, getState) => { log.debug(`actions calling background.approveTransaction`) background.approveTransaction(txData.id, (err) => { if (err) { @@ -1011,6 +1031,11 @@ function sendTx (txData) { return log.error(err.message) } dispatch(actions.completedTx(txData.id)) + + if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION && + !hasUnconfirmedTransactions(getState())) { + return global.platform.closeCurrentWindow() + } }) } } @@ -1059,7 +1084,7 @@ function updateTransaction (txData) { function updateAndApproveTx (txData) { log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData)) - return dispatch => { + return (dispatch, getState) => { log.debug(`actions calling background.updateAndApproveTx`) dispatch(actions.showLoadingIndication()) @@ -1084,6 +1109,12 @@ function updateAndApproveTx (txData) { dispatch(actions.clearSend()) dispatch(actions.completedTx(txData.id)) dispatch(actions.hideLoadingIndication()) + + if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION && + !hasUnconfirmedTransactions(getState())) { + return global.platform.closeCurrentWindow() + } + return txData }) } @@ -1112,7 +1143,7 @@ function txError (err) { } function cancelMsg (msgData) { - return dispatch => { + return (dispatch, getState) => { dispatch(actions.showLoadingIndication()) return new Promise((resolve, reject) => { @@ -1126,6 +1157,12 @@ function cancelMsg (msgData) { } dispatch(actions.completedTx(msgData.id)) + + if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION && + !hasUnconfirmedTransactions(getState())) { + return global.platform.closeCurrentWindow() + } + return resolve(msgData) }) }) @@ -1133,7 +1170,7 @@ function cancelMsg (msgData) { } function cancelPersonalMsg (msgData) { - return dispatch => { + return (dispatch, getState) => { dispatch(actions.showLoadingIndication()) return new Promise((resolve, reject) => { @@ -1147,6 +1184,12 @@ function cancelPersonalMsg (msgData) { } dispatch(actions.completedTx(id)) + + if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION && + !hasUnconfirmedTransactions(getState())) { + return global.platform.closeCurrentWindow() + } + return resolve(msgData) }) }) @@ -1154,7 +1197,7 @@ function cancelPersonalMsg (msgData) { } function cancelTypedMsg (msgData) { - return dispatch => { + return (dispatch, getState) => { dispatch(actions.showLoadingIndication()) return new Promise((resolve, reject) => { @@ -1168,6 +1211,12 @@ function cancelTypedMsg (msgData) { } dispatch(actions.completedTx(id)) + + if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION && + !hasUnconfirmedTransactions(getState())) { + return global.platform.closeCurrentWindow() + } + return resolve(msgData) }) }) @@ -1175,7 +1224,7 @@ function cancelTypedMsg (msgData) { } function cancelTx (txData) { - return dispatch => { + return (dispatch, getState) => { log.debug(`background.cancelTransaction`) dispatch(actions.showLoadingIndication()) @@ -1194,6 +1243,12 @@ function cancelTx (txData) { dispatch(actions.clearSend()) dispatch(actions.completedTx(txData.id)) dispatch(actions.hideLoadingIndication()) + + if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION && + !hasUnconfirmedTransactions(getState())) { + return global.platform.closeCurrentWindow() + } + return txData }) } diff --git a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js index 2811e6157..e1bf2210f 100644 --- a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -8,9 +8,6 @@ import { INSUFFICIENT_FUNDS_ERROR_KEY, TRANSACTION_ERROR_KEY, } from '../../../constants/error-keys' -import { - ENVIRONMENT_TYPE_NOTIFICATION, -} from '../../../../../app/scripts/lib/enums' export default class ConfirmTransactionBase extends Component { static contextTypes = { @@ -253,12 +250,8 @@ export default class ConfirmTransactionBase extends Component { } else { cancelTransaction(txData) .then(() => { - if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION) { - return global.platform.closeCurrentWindow() - } else { - clearConfirmTransaction() - history.push(DEFAULT_ROUTE) - } + clearConfirmTransaction() + history.push(DEFAULT_ROUTE) }) } } @@ -271,12 +264,8 @@ export default class ConfirmTransactionBase extends Component { } else { sendTransaction(txData) .then(() => { - if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION) { - return global.platform.closeCurrentWindow() - } else { - clearConfirmTransaction() - history.push(DEFAULT_ROUTE) - } + clearConfirmTransaction() + history.push(DEFAULT_ROUTE) }) } } diff --git a/ui/app/components/pages/home.js b/ui/app/components/pages/home.js index 38aa02dae..5e3fdc9af 100644 --- a/ui/app/components/pages/home.js +++ b/ui/app/components/pages/home.js @@ -27,19 +27,17 @@ const { NOTICE_ROUTE, } = require('../../routes') +const { unconfirmedTransactionsCountSelector } = require('../../selectors/confirm-transaction') + class Home extends Component { componentDidMount () { const { history, - unapprovedTxs = {}, - unapprovedMsgCount = 0, - unapprovedPersonalMsgCount = 0, - unapprovedTypedMessagesCount = 0, + unconfirmedTransactionsCount = 0, } = this.props // unapprovedTxs and unapproved messages - if (Object.keys(unapprovedTxs).length || - unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount > 0) { + if (unconfirmedTransactionsCount > 0) { history.push(CONFIRM_TRANSACTION_ROUTE) } } @@ -167,6 +165,7 @@ Home.propTypes = { isPopup: PropTypes.bool, isMouseUser: PropTypes.bool, t: PropTypes.func, + unconfirmedTransactionsCount: PropTypes.number, } function mapStateToProps (state) { @@ -230,6 +229,7 @@ function mapStateToProps (state) { // state needed to get account dropdown temporarily rendering from app bar selected, + unconfirmedTransactionsCount: unconfirmedTransactionsCountSelector(state), } } diff --git a/ui/app/helpers/confirm-transaction/util.js b/ui/app/helpers/confirm-transaction/util.js index 1373d28df..f015b2bf5 100644 --- a/ui/app/helpers/confirm-transaction/util.js +++ b/ui/app/helpers/confirm-transaction/util.js @@ -16,6 +16,8 @@ import { conversionGreaterThan, } from '../../conversion-util' +import { unconfirmedTransactionsCountSelector } from '../../selectors/confirm-transaction' + export function getTokenData (data = {}) { return abiDecoder.decodeMethod(data) } @@ -131,3 +133,7 @@ export function convertTokenToFiat ({ conversionRate: totalExchangeRate, }) } + +export function hasUnconfirmedTransactions (state) { + return unconfirmedTransactionsCountSelector(state) > 0 +} diff --git a/ui/app/selectors/confirm-transaction.js b/ui/app/selectors/confirm-transaction.js index 54016a30e..8f8e0ea74 100644 --- a/ui/app/selectors/confirm-transaction.js +++ b/ui/app/selectors/confirm-transaction.js @@ -62,6 +62,34 @@ export const unconfirmedTransactionsHashSelector = createSelector( } ) +const unapprovedMsgCountSelector = state => state.metamask.unapprovedMsgCount +const unapprovedPersonalMsgCountSelector = state => state.metamask.unapprovedPersonalMsgCount +const unapprovedTypedMessagesCountSelector = state => state.metamask.unapprovedTypedMessagesCount + +export const unconfirmedTransactionsCountSelector = createSelector( + unapprovedTxsSelector, + unapprovedMsgCountSelector, + unapprovedPersonalMsgCountSelector, + unapprovedTypedMessagesCountSelector, + networkSelector, + ( + unapprovedTxs = {}, + unapprovedMsgCount = 0, + unapprovedPersonalMsgCount = 0, + unapprovedTypedMessagesCount = 0, + network + ) => { + const filteredUnapprovedTxIds = Object.keys(unapprovedTxs).filter(txId => { + const { metamaskNetworkId } = unapprovedTxs[txId] + return metamaskNetworkId === network + }) + + return filteredUnapprovedTxIds.length + unapprovedTypedMessagesCount + unapprovedMsgCount + + unapprovedPersonalMsgCount + } +) + + export const currentCurrencySelector = state => state.metamask.currentCurrency export const conversionRateSelector = state => state.metamask.conversionRate @@ -156,7 +184,6 @@ export const sendTokenTokenAmountAndToAddressSelector = createSelector( } ) - export const contractExchangeRateSelector = createSelector( contractExchangeRatesSelector, tokenAddressSelector, From cb8ea12db626e82b7230317fc74b6b80ce20f793 Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Tue, 24 Jul 2018 11:24:36 -0230 Subject: [PATCH 09/23] Updates e2e beta tests to ensure that popup window closes after confirming a simple send. --- test/e2e/beta/metamask-beta-ui.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js index ee1aa0ff1..ca1977c5a 100644 --- a/test/e2e/beta/metamask-beta-ui.spec.js +++ b/test/e2e/beta/metamask-beta-ui.spec.js @@ -472,7 +472,7 @@ describe('MetaMask', function () { await confirmButton.click() await delay(regularDelayMs) - await closeAllWindowHandlesExcept(driver, [extension, dapp]) + await waitUntilXWindowHandles(driver, 2) await driver.switchTo().window(extension) await delay(regularDelayMs) }) From 64a82fd3dae66f33b0934d58e43e85df27fbfe1d Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Tue, 24 Jul 2018 11:45:36 -0230 Subject: [PATCH 10/23] Uncomment closePopupIfOpen code. --- app/scripts/ui.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 42703f029..cbe15c92d 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -70,10 +70,10 @@ async function start () { function closePopupIfOpen (windowType) { - // if (windowType !== ENVIRONMENT_TYPE_NOTIFICATION) { + if (windowType !== ENVIRONMENT_TYPE_NOTIFICATION) { // should close only chrome popup - // notificationManager.closePopup() - // } + notificationManager.closePopup() + } } function displayCriticalError (err) { From a61227f224e37559c8d6e2c59441b0032633feaf Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Tue, 24 Jul 2018 15:01:03 -0230 Subject: [PATCH 11/23] Remove unneeded code from i4829-close-notifications-from-ui branch. --- app/scripts/platforms/extension.js | 2 +- app/scripts/ui.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index bd4f7bd9f..0803164e8 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -14,7 +14,7 @@ class ExtensionPlatform { extension.tabs.create({ url }) } - closeCurrentWindow (cb) { + closeCurrentWindow () { return extension.windows.getCurrent((windowDetails) => { return extension.windows.remove(windowDetails.id) }) diff --git a/app/scripts/ui.js b/app/scripts/ui.js index cbe15c92d..da100f928 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -64,7 +64,6 @@ async function start () { css = betaUIState ? NewMetaMaskUiCss() : OldMetaMaskUiCss() deleteInjectedCss = injectCss(css) } - // if (state.appState.shouldClose) notificationManager.closePopup() }) }) From 653e42cf79f20e57af63f2bcc36cb3c236239e9b Mon Sep 17 00:00:00 2001 From: Antoine Nauleau <30602458+ajnauleau@users.noreply.github.com> Date: Tue, 24 Jul 2018 19:51:32 +0200 Subject: [PATCH 12/23] Update Babel to Current Standard "babel-preset-env" (#4812) * Update .babelrc and package.json to babel-preset-env standard * Install babel-preset-env babel-stage-0 * Regenerate package-lock.json by running npm install --package-lock-only && npm audit fix * Resolve PR #4812 merge conflicts * Merge #4847 Solves previous cache issues with cirlce-ci --- .babelrc | 4 ++-- package-lock.json | 43 +++++++++++++++++++++++++------------------ package.json | 21 ++++++++++++++++----- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/.babelrc b/.babelrc index 307583ffd..628fe652c 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,4 @@ { - "presets": ["es2015", "stage-0", "react"], - "plugins": ["transform-runtime", "transform-async-to-generator"] + "presets": [["env", { "debug": true }], "react", "stage-0"], + "plugins": ["transform-runtime", "transform-async-to-generator", "transform-class-properties"] } diff --git a/package-lock.json b/package-lock.json index 443e173a9..1a2897a9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3618,9 +3618,9 @@ } }, "babel-preset-env": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", - "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", "requires": { "babel-plugin-check-es2015-constants": "^6.22.0", "babel-plugin-syntax-trailing-function-commas": "^6.22.0", @@ -3649,7 +3649,7 @@ "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", "babel-plugin-transform-exponentiation-operator": "^6.22.0", "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^2.1.2", + "browserslist": "^3.2.6", "invariant": "^2.2.2", "semver": "^5.3.0" } @@ -4664,12 +4664,19 @@ } }, "browserslist": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.0.tgz", - "integrity": "sha512-mNYp0RNeu1xueGuJFSXkU+K0nH+dBE/gcjtyhtNKfU8hwdrVIfoA7i5iFSjOmzkGdL2QaO7YX9ExiVPE7AY9JA==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", "requires": { - "caniuse-lite": "^1.0.30000784", - "electron-to-chromium": "^1.3.30" + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + }, + "dependencies": { + "electron-to-chromium": { + "version": "1.3.52", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz", + "integrity": "sha1-0tnxJwuko7lnuDHEDvcftNmrXOA=" + } } }, "bs58": { @@ -4996,9 +5003,9 @@ "integrity": "sha1-MN/YMAnVcE8C3/s3clBo7RKjZrs=" }, "caniuse-lite": { - "version": "1.0.30000786", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000786.tgz", - "integrity": "sha1-G0Jc2FaNgFvFY4veSQXNhjVod0Y=" + "version": "1.0.30000865", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz", + "integrity": "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw==" }, "capture-stack-trace": { "version": "1.0.0", @@ -13470,9 +13477,9 @@ "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" }, "node-sass": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.1.tgz", - "integrity": "sha512-m6H1I6cHXsHsJ7BIWdnJsz9S9gVMyh+/H2cOTXgl2/2WqyyWlBcl4PHJcqrXo5RZVCfCUFqOtjPN0+0XbVHR5Q==", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.2.tgz", + "integrity": "sha512-LdxoJLZutx0aQXHtWIYwJKMj+9pTjneTcLWJgzf2XbGu0q5pRNqW5QvFCEdm3mc5rJOdru/mzln5d0EZLacf6g==", "requires": { "async-foreach": "^0.1.3", "chalk": "^1.1.1", @@ -20653,9 +20660,9 @@ } }, "node-sass": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.1.tgz", - "integrity": "sha512-m6H1I6cHXsHsJ7BIWdnJsz9S9gVMyh+/H2cOTXgl2/2WqyyWlBcl4PHJcqrXo5RZVCfCUFqOtjPN0+0XbVHR5Q==", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.2.tgz", + "integrity": "sha512-LdxoJLZutx0aQXHtWIYwJKMj+9pTjneTcLWJgzf2XbGu0q5pRNqW5QvFCEdm3mc5rJOdru/mzln5d0EZLacf6g==", "dev": true, "requires": { "async-foreach": "^0.1.3", diff --git a/package.json b/package.json index 376f773e5..96b0829db 100644 --- a/package.json +++ b/package.json @@ -54,9 +54,19 @@ "babelify", { "presets": [ - "es2015", + [ + "env", + { + "debug": true + } + ], "stage-0" ] + }, + { + "plugins": [ + "transform-class-properties" + ] } ], "reactify", @@ -94,6 +104,7 @@ "eslint-plugin-react": "^7.4.0", "eth-bin-to-ops": "^1.0.1", "eth-contract-metadata": "github:MetaMask/eth-contract-metadata#master", + "eth-ens-namehash": "^2.0.8", "eth-hd-keyring": "^2.0.0", "eth-json-rpc-filters": "^1.2.6", "eth-json-rpc-infura": "^3.0.0", @@ -142,6 +153,7 @@ "metamascara": "^2.0.0", "metamask-logo": "^2.1.4", "mkdirp": "^0.5.1", + "multihashes": "^0.4.12", "multiplex": "^6.7.0", "number-to-bn": "^1.7.0", "obj-multiplex": "^1.0.0", @@ -195,9 +207,7 @@ "web3": "^0.20.1", "web3-provider-engine": "^14.0.5", "web3-stream-provider": "^3.0.1", - "xtend": "^4.0.1", - "multihashes": "^0.4.12", - "eth-ens-namehash": "^2.0.8" + "xtend": "^4.0.1" }, "devDependencies": { "@sentry/cli": "^1.30.3", @@ -209,6 +219,7 @@ "babel-plugin-transform-async-to-generator": "^6.24.1", "babel-plugin-transform-runtime": "^6.23.0", "babel-polyfill": "^6.23.0", + "babel-preset-env": "^1.7.0", "babel-preset-react": "^6.24.1", "babel-preset-stage-0": "^6.24.1", "babel-register": "^6.7.2", @@ -274,7 +285,7 @@ "mocha-jsdom": "^1.1.0", "mocha-sinon": "^2.0.0", "nock": "^9.0.14", - "node-sass": "^4.9.1", + "node-sass": "^4.9.2", "nsp": "^3.2.1", "nyc": "^13.0.0", "open": "0.0.5", From 00bae744757d0a83c5a7e27adaa70107313bcaac Mon Sep 17 00:00:00 2001 From: Jenny Pollack Date: Tue, 24 Jul 2018 14:16:37 -0700 Subject: [PATCH 13/23] tx-gas-utils - catch all errors from gas estimation --- app/scripts/controllers/transactions/tx-gas-utils.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/scripts/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js index ab4031faa..5cd0f5407 100644 --- a/app/scripts/controllers/transactions/tx-gas-utils.js +++ b/app/scripts/controllers/transactions/tx-gas-utils.js @@ -30,14 +30,10 @@ class TxGasUtil { try { estimatedGasHex = await this.estimateTxGas(txMeta, block.gasLimit) } catch (err) { - const simulationFailed = ( - err.message.includes('Transaction execution error.') || - err.message.includes('gas required exceeds allowance or always failing transaction') - ) - if (simulationFailed) { - txMeta.simulationFails = true - return txMeta + txMeta.simulationFails = { + reason: err.message, } + return txMeta } this.setTxGas(txMeta, block.gasLimit, estimatedGasHex) return txMeta From 3667f3cb8556d55ad893ec8c1a0f84447273906f Mon Sep 17 00:00:00 2001 From: pinkiebell <40266861+pinkiebell@users.noreply.github.com> Date: Wed, 25 Jul 2018 00:03:36 +0200 Subject: [PATCH 14/23] network.js: convert rpc protocol to lower case (#4855) Fixes #4253 --- CHANGELOG.md | 1 + app/scripts/controllers/network/network.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2d78b6b1..7e1e1ff4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Add Trezor Support - Allow to remove accounts (Imported and Hardware Wallets) - [#4840](https://github.com/MetaMask/metamask-extension/pull/4840): Now shows notifications when transactions are completed. +- [#4855](https://github.com/MetaMask/metamask-extension/pull/4855): network.js: convert rpc protocol to lower case. ## 4.8.0 Thur Jun 14 2018 diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index a50f6dc45..b6f7705b5 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -9,6 +9,7 @@ const extend = require('xtend') const EthQuery = require('eth-query') const createEventEmitterProxy = require('../../lib/events-proxy.js') const log = require('loglevel') +const urlUtil = require('url') const { ROPSTEN, RINKEBY, @@ -155,6 +156,8 @@ module.exports = class NetworkController extends EventEmitter { } _configureStandardProvider ({ rpcUrl }) { + // urlUtil handles malformed urls + rpcUrl = urlUtil.parse(rpcUrl).format() const providerParams = extend(this._baseProviderParams, { rpcUrl, engineParams: { From 87f42468b76bd1a82b74ee6295565ae110554f2b Mon Sep 17 00:00:00 2001 From: bobby dresser Date: Wed, 25 Jul 2018 10:30:47 -0700 Subject: [PATCH 15/23] add current release to the README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8a1eda46c..9c16f8b9e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # MetaMask Browser Extension [![Build Status](https://circleci.com/gh/MetaMask/metamask-extension.svg?style=shield&circle-token=a1ddcf3cd38e29267f254c9c59d556d513e3a1fd)](https://circleci.com/gh/MetaMask/metamask-extension) [![Coverage Status](https://coveralls.io/repos/github/MetaMask/metamask-extension/badge.svg?branch=master)](https://coveralls.io/github/MetaMask/metamask-extension?branch=master) [![Greenkeeper badge](https://badges.greenkeeper.io/MetaMask/metamask-extension.svg)](https://greenkeeper.io/) [![Stories in Ready](https://badge.waffle.io/MetaMask/metamask-extension.png?label=in%20progress&title=waffle.io)](https://waffle.io/MetaMask/metamask-extension) +🚨 As of 7/25/18, the MetaMask extension has been removed from the Chrome Web Store. To download the latest version of MetaMask, use the [4.8 Chrome build](https://github.com/MetaMask/metamask-extension/releases/download/v4.8.0/metamask-chrome-4.8.0.zip) (also available on our [Releases](https://github.com/MetaMask/metamask-extension/releases) list), and load it on the `chrome://extensions` page. For more detailed steps, visit our help center[here](https://consensys.zendesk.com/hc/en-us/articles/360004134152-How-to-Install-MetaMask-Manually). Follow [@metamask_io](https://twitter.com/metamask_io) on Twitter for updates. 🚨 + ## Support If you're a user seeking support, [here is our support site](https://metamask.helpscoutdocs.com/). From 8cd36c8725541118c324738934510177d755d6ec Mon Sep 17 00:00:00 2001 From: bobby dresser Date: Wed, 25 Jul 2018 11:48:15 -0700 Subject: [PATCH 16/23] fix link bracket --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c16f8b9e..af4a8138a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # MetaMask Browser Extension [![Build Status](https://circleci.com/gh/MetaMask/metamask-extension.svg?style=shield&circle-token=a1ddcf3cd38e29267f254c9c59d556d513e3a1fd)](https://circleci.com/gh/MetaMask/metamask-extension) [![Coverage Status](https://coveralls.io/repos/github/MetaMask/metamask-extension/badge.svg?branch=master)](https://coveralls.io/github/MetaMask/metamask-extension?branch=master) [![Greenkeeper badge](https://badges.greenkeeper.io/MetaMask/metamask-extension.svg)](https://greenkeeper.io/) [![Stories in Ready](https://badge.waffle.io/MetaMask/metamask-extension.png?label=in%20progress&title=waffle.io)](https://waffle.io/MetaMask/metamask-extension) -🚨 As of 7/25/18, the MetaMask extension has been removed from the Chrome Web Store. To download the latest version of MetaMask, use the [4.8 Chrome build](https://github.com/MetaMask/metamask-extension/releases/download/v4.8.0/metamask-chrome-4.8.0.zip) (also available on our [Releases](https://github.com/MetaMask/metamask-extension/releases) list), and load it on the `chrome://extensions` page. For more detailed steps, visit our help center[here](https://consensys.zendesk.com/hc/en-us/articles/360004134152-How-to-Install-MetaMask-Manually). Follow [@metamask_io](https://twitter.com/metamask_io) on Twitter for updates. 🚨 +🚨 As of 7/25/18, the MetaMask extension has been removed from the Chrome Web Store. To download the latest version of MetaMask, use the [4.8 Chrome build](https://github.com/MetaMask/metamask-extension/releases/download/v4.8.0/metamask-chrome-4.8.0.zip) (also available on our [Releases](https://github.com/MetaMask/metamask-extension/releases) list), and load it on the `chrome://extensions` page. For more detailed steps, visit our [help center](https://consensys.zendesk.com/hc/en-us/articles/360004134152-How-to-Install-MetaMask-Manually). Follow [@metamask_io](https://twitter.com/metamask_io) on Twitter for updates. 🚨 ## Support From 45379e867dbad2dec1f6694687091dcb1a3bec80 Mon Sep 17 00:00:00 2001 From: bobby dresser Date: Wed, 25 Jul 2018 11:58:27 -0700 Subject: [PATCH 17/23] remove current version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index af4a8138a..86d515377 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # MetaMask Browser Extension [![Build Status](https://circleci.com/gh/MetaMask/metamask-extension.svg?style=shield&circle-token=a1ddcf3cd38e29267f254c9c59d556d513e3a1fd)](https://circleci.com/gh/MetaMask/metamask-extension) [![Coverage Status](https://coveralls.io/repos/github/MetaMask/metamask-extension/badge.svg?branch=master)](https://coveralls.io/github/MetaMask/metamask-extension?branch=master) [![Greenkeeper badge](https://badges.greenkeeper.io/MetaMask/metamask-extension.svg)](https://greenkeeper.io/) [![Stories in Ready](https://badge.waffle.io/MetaMask/metamask-extension.png?label=in%20progress&title=waffle.io)](https://waffle.io/MetaMask/metamask-extension) -🚨 As of 7/25/18, the MetaMask extension has been removed from the Chrome Web Store. To download the latest version of MetaMask, use the [4.8 Chrome build](https://github.com/MetaMask/metamask-extension/releases/download/v4.8.0/metamask-chrome-4.8.0.zip) (also available on our [Releases](https://github.com/MetaMask/metamask-extension/releases) list), and load it on the `chrome://extensions` page. For more detailed steps, visit our [help center](https://consensys.zendesk.com/hc/en-us/articles/360004134152-How-to-Install-MetaMask-Manually). Follow [@metamask_io](https://twitter.com/metamask_io) on Twitter for updates. 🚨 +🚨 As of 7/25/18, the MetaMask extension has been removed from the Chrome Web Store. In the meantime, you can download the latest version of MetaMask on our [Releases](https://github.com/MetaMask/metamask-extension/releases) page and load it in Chrome by visiting `chrome://extensions`. For more detailed steps, see our [help center](https://consensys.zendesk.com/hc/en-us/articles/360004134152-How-to-Install-MetaMask-Manually). Follow [@metamask_io](https://twitter.com/metamask_io) on Twitter for updates. 🚨 ## Support From 9ca4b66c82ab9ec46c6599778df7b661e927edfa Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Wed, 25 Jul 2018 11:57:41 -0700 Subject: [PATCH 18/23] Add tests for Confirm Detail Row --- .../confirm-detail-row.component.test.js | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js diff --git a/ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js b/ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js new file mode 100644 index 000000000..334ec4497 --- /dev/null +++ b/ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js @@ -0,0 +1,64 @@ +import React from 'react' +import assert from 'assert' +import { shallow } from 'enzyme' +import ConfirmDetailRow from '../confirm-detail-row.component.js' +import sinon from 'sinon' + +const propsMethodSpies = { + onHeaderClick: sinon.spy(), +} + +describe('Confirm Detail Row Component', function () { + let wrapper + + beforeEach(() => { + wrapper = shallow() + }) + + describe('render', () => { + it('should render a div with a confirm-detail-row class', () => { + assert.equal(wrapper.find('div.confirm-detail-row').length, 1) + }) + + it('should render the label as a child of the confirm-detail-row__label', () => { + assert.equal(wrapper.find('.confirm-detail-row > .confirm-detail-row__label').childAt(0).text(), 'mockLabel') + }) + + it('should render the headerText as a child of the confirm-detail-row__header-text', () => { + assert.equal(wrapper.find('.confirm-detail-row__details > .confirm-detail-row__header-text').childAt(0).text(), 'mockHeaderText') + }) + + it('should render the fiatText as a child of the confirm-detail-row__fiat', () => { + assert.equal(wrapper.find('.confirm-detail-row__details > .confirm-detail-row__fiat').childAt(0).text(), 'mockFiatFee') + }) + + it('should render the ethText as a child of the confirm-detail-row__eth', () => { + assert.equal(wrapper.find('.confirm-detail-row__details > .confirm-detail-row__eth').childAt(0).text(), '♦ mockEthFee') + }) + + it('should set the fiatTextColor on confirm-detail-row__fiat', () => { + assert.equal(wrapper.find('.confirm-detail-row__fiat').props().style.color, 'mockColor') + }) + + it('should assure the confirm-detail-row__header-text classname is correct', () => { + assert.equal(wrapper.find('.confirm-detail-row__header-text').props().className, 'confirm-detail-row__header-text mockHeaderClass') + }) + + it('should call onHeaderClick when headerText div gets clicked', () => { + wrapper.find('.confirm-detail-row__header-text').props().onClick() + assert.equal(assert.equal(propsMethodSpies.onHeaderClick.callCount, 1)) + }) + + + }) +}) From 527b62ee8e57335360402c2e121bf34d3e621a8c Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 25 Jul 2018 14:11:07 -0700 Subject: [PATCH 19/23] migrations - fix to include 27 --- app/scripts/migrations/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 04d90bfff..bd0005221 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -37,4 +37,5 @@ module.exports = [ require('./024'), require('./025'), require('./026'), + require('./027'), ] From 6eadf5b22b9ffac4fe41be0e690e95f825e700ea Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Wed, 25 Jul 2018 16:26:30 -0700 Subject: [PATCH 20/23] Update prop names --- .../tests/confirm-detail-row.component.test.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js b/ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js index 334ec4497..fb5cff1c1 100644 --- a/ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js +++ b/ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js @@ -8,7 +8,7 @@ const propsMethodSpies = { onHeaderClick: sinon.spy(), } -describe('Confirm Detail Row Component', function () { +describe.only('Confirm Detail Row Component', function () { let wrapper beforeEach(() => { @@ -16,16 +16,16 @@ describe('Confirm Detail Row Component', function () { errorType={'mockErrorType'} label={'mockLabel'} showError={false} - fiatFee = {'mockFiatFee'} - ethFee = {'mockEthFee'} - fiatFeeColor= {'mockColor'} + fiatText = {'mockFiatText'} + ethText = {'mockEthText'} + fiatTextColor= {'mockColor'} onHeaderClick= {propsMethodSpies.onHeaderClick} headerText = {'mockHeaderText'} headerTextClassName = {'mockHeaderClass'} />) }) - describe('render', () => { + describe.only('render', () => { it('should render a div with a confirm-detail-row class', () => { assert.equal(wrapper.find('div.confirm-detail-row').length, 1) }) @@ -39,11 +39,11 @@ describe('Confirm Detail Row Component', function () { }) it('should render the fiatText as a child of the confirm-detail-row__fiat', () => { - assert.equal(wrapper.find('.confirm-detail-row__details > .confirm-detail-row__fiat').childAt(0).text(), 'mockFiatFee') + assert.equal(wrapper.find('.confirm-detail-row__details > .confirm-detail-row__fiat').childAt(0).text(), 'mockFiatText') }) it('should render the ethText as a child of the confirm-detail-row__eth', () => { - assert.equal(wrapper.find('.confirm-detail-row__details > .confirm-detail-row__eth').childAt(0).text(), '♦ mockEthFee') + assert.equal(wrapper.find('.confirm-detail-row__details > .confirm-detail-row__eth').childAt(0).text(), 'mockEthText') }) it('should set the fiatTextColor on confirm-detail-row__fiat', () => { From 9934690bd976b74cadd3211ab492022d1ff00a20 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Wed, 25 Jul 2018 16:31:33 -0700 Subject: [PATCH 21/23] lint fix --- .../tests/confirm-detail-row.component.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js b/ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js index fb5cff1c1..6f2489071 100644 --- a/ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js +++ b/ui/app/components/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js @@ -8,7 +8,7 @@ const propsMethodSpies = { onHeaderClick: sinon.spy(), } -describe.only('Confirm Detail Row Component', function () { +describe('Confirm Detail Row Component', function () { let wrapper beforeEach(() => { @@ -25,7 +25,7 @@ describe.only('Confirm Detail Row Component', function () { />) }) - describe.only('render', () => { + describe('render', () => { it('should render a div with a confirm-detail-row class', () => { assert.equal(wrapper.find('div.confirm-detail-row').length, 1) }) From c8d45cb4a8a671bad20cd5a5aa1bcbbd88463bdb Mon Sep 17 00:00:00 2001 From: Esteban MIno Date: Wed, 25 Jul 2018 20:02:12 -0400 Subject: [PATCH 22/23] only show retry button on earliest pending tx --- old-ui/app/components/transaction-list-item.js | 8 +++++++- ui/app/components/tx-list-item.js | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/old-ui/app/components/transaction-list-item.js b/old-ui/app/components/transaction-list-item.js index e9280419a..e12f9cd6a 100644 --- a/old-ui/app/components/transaction-list-item.js +++ b/old-ui/app/components/transaction-list-item.js @@ -39,11 +39,17 @@ TransactionListItem.prototype.showRetryButton = function () { const currentNonce = txParams.nonce const currentNonceTxs = transactions.filter(tx => tx.txParams.nonce === currentNonce) const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => tx.status === 'submitted') + const currentSubmittedTxs = transactions.filter(tx => tx.status === 'submitted') const lastSubmittedTxWithCurrentNonce = currentNonceSubmittedTxs[0] const currentTxIsLatestWithNonce = lastSubmittedTxWithCurrentNonce && lastSubmittedTxWithCurrentNonce.id === transaction.id + const lastTx = currentSubmittedTxs.reduce((tx1, tx2) => { + if (tx1.id < tx2.id) return tx1 + return tx2 + }) - return currentTxIsLatestWithNonce && Date.now() - submittedTime > 30000 + const currentTxIsLatest = lastTx.id === transaction.id + return currentTxIsLatestWithNonce && Date.now() - submittedTime > 30000 && currentTxIsLatest } TransactionListItem.prototype.render = function () { diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 0d693b805..92466568c 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -216,11 +216,17 @@ TxListItem.prototype.showRetryButton = function () { const currentNonce = txParams.nonce const currentNonceTxs = selectedAddressTxList.filter(tx => tx.txParams.nonce === currentNonce) const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => tx.status === 'submitted') + const currentSubmittedTxs = selectedAddressTxList.filter(tx => tx.status === 'submitted') const lastSubmittedTxWithCurrentNonce = currentNonceSubmittedTxs[currentNonceSubmittedTxs.length - 1] const currentTxIsLatestWithNonce = lastSubmittedTxWithCurrentNonce && lastSubmittedTxWithCurrentNonce.id === transactionId + const lastTx = currentSubmittedTxs.reduce((tx1, tx2) => { + if (tx1.id < tx2.id) return tx1 + return tx2 + }) + const currentTxIsLatest = lastTx.id === transactionId - return currentTxIsLatestWithNonce && Date.now() - transactionSubmittedTime > 30000 + return currentTxIsLatestWithNonce && Date.now() - transactionSubmittedTime > 30000 && currentTxIsLatest } TxListItem.prototype.setSelectedToken = function (tokenAddress) { From b580f60d749b862fe08adfc7457c726905ebc623 Mon Sep 17 00:00:00 2001 From: Esteban MIno Date: Wed, 25 Jul 2018 20:58:20 -0400 Subject: [PATCH 23/23] earliest tx by submittedTime --- old-ui/app/components/transaction-list-item.js | 13 ++++++++----- ui/app/components/tx-list-item.js | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/old-ui/app/components/transaction-list-item.js b/old-ui/app/components/transaction-list-item.js index e12f9cd6a..f479ce666 100644 --- a/old-ui/app/components/transaction-list-item.js +++ b/old-ui/app/components/transaction-list-item.js @@ -36,6 +36,7 @@ TransactionListItem.prototype.showRetryButton = function () { return false } + let currentTxIsLatest = false const currentNonce = txParams.nonce const currentNonceTxs = transactions.filter(tx => tx.txParams.nonce === currentNonce) const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => tx.status === 'submitted') @@ -43,12 +44,14 @@ TransactionListItem.prototype.showRetryButton = function () { const lastSubmittedTxWithCurrentNonce = currentNonceSubmittedTxs[0] const currentTxIsLatestWithNonce = lastSubmittedTxWithCurrentNonce && lastSubmittedTxWithCurrentNonce.id === transaction.id - const lastTx = currentSubmittedTxs.reduce((tx1, tx2) => { - if (tx1.id < tx2.id) return tx1 - return tx2 - }) + if (currentSubmittedTxs.length > 0) { + const lastTx = currentSubmittedTxs.reduce((tx1, tx2) => { + if (tx1.submittedTime < tx2.submittedTime) return tx1 + return tx2 + }) + currentTxIsLatest = lastTx.id === transaction.id + } - const currentTxIsLatest = lastTx.id === transaction.id return currentTxIsLatestWithNonce && Date.now() - submittedTime > 30000 && currentTxIsLatest } diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 92466568c..1a639d0b9 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -213,6 +213,7 @@ TxListItem.prototype.showRetryButton = function () { if (!txParams) { return false } + let currentTxIsLatest = false const currentNonce = txParams.nonce const currentNonceTxs = selectedAddressTxList.filter(tx => tx.txParams.nonce === currentNonce) const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => tx.status === 'submitted') @@ -220,11 +221,13 @@ TxListItem.prototype.showRetryButton = function () { const lastSubmittedTxWithCurrentNonce = currentNonceSubmittedTxs[currentNonceSubmittedTxs.length - 1] const currentTxIsLatestWithNonce = lastSubmittedTxWithCurrentNonce && lastSubmittedTxWithCurrentNonce.id === transactionId - const lastTx = currentSubmittedTxs.reduce((tx1, tx2) => { - if (tx1.id < tx2.id) return tx1 - return tx2 - }) - const currentTxIsLatest = lastTx.id === transactionId + if (currentSubmittedTxs.length > 0) { + const lastTx = currentSubmittedTxs.reduce((tx1, tx2) => { + if (tx1.submittedTime < tx2.submittedTime) return tx1 + return tx2 + }) + currentTxIsLatest = lastTx.id === transactionId + } return currentTxIsLatestWithNonce && Date.now() - transactionSubmittedTime > 30000 && currentTxIsLatest }