aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app
diff options
context:
space:
mode:
authorThomas Huang <tmashuang@users.noreply.github.com>2018-11-23 03:06:46 +0800
committerGitHub <noreply@github.com>2018-11-23 03:06:46 +0800
commitbe3619cd802536894097d81e7f31d38b0c2b3e9f (patch)
tree2591ff5a9fe64f2dbd9fa089f5c51e8d0141be24 /ui/app
parent337a4e1b4ea7a560d773bc262b2adffd1617a39b (diff)
parent804b273cec61246f0d23efd461ccd2cc5c64bf22 (diff)
downloadtangerine-wallet-browser-be3619cd802536894097d81e7f31d38b0c2b3e9f.tar
tangerine-wallet-browser-be3619cd802536894097d81e7f31d38b0c2b3e9f.tar.gz
tangerine-wallet-browser-be3619cd802536894097d81e7f31d38b0c2b3e9f.tar.bz2
tangerine-wallet-browser-be3619cd802536894097d81e7f31d38b0c2b3e9f.tar.lz
tangerine-wallet-browser-be3619cd802536894097d81e7f31d38b0c2b3e9f.tar.xz
tangerine-wallet-browser-be3619cd802536894097d81e7f31d38b0c2b3e9f.tar.zst
tangerine-wallet-browser-be3619cd802536894097d81e7f31d38b0c2b3e9f.zip
Merge pull request #5793 from MetaMask/develop
Bring master up to date with develop
Diffstat (limited to 'ui/app')
-rw-r--r--ui/app/actions.js23
-rw-r--r--ui/app/components/app-header/app-header.component.js2
-rw-r--r--ui/app/components/balance-component.js4
-rw-r--r--ui/app/components/confirm-page-container/confirm-page-container-header/index.scss2
-rwxr-xr-xui/app/components/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js69
-rwxr-xr-xui/app/components/confirm-page-container/confirm-page-container-navigation/index.js1
-rwxr-xr-xui/app/components/confirm-page-container/confirm-page-container-navigation/index.scss54
-rw-r--r--ui/app/components/confirm-page-container/confirm-page-container.component.js35
-rw-r--r--ui/app/components/confirm-page-container/index.js2
-rw-r--r--ui/app/components/confirm-page-container/index.scss2
-rw-r--r--ui/app/components/currency-display/currency-display.container.js19
-rw-r--r--ui/app/components/currency-display/tests/currency-display.container.test.js2
-rw-r--r--ui/app/components/index.scss4
-rw-r--r--ui/app/components/menu-bar/menu-bar.component.js2
-rw-r--r--ui/app/components/modals/clear-approved-origins/clear-approved-origins.component.js39
-rw-r--r--ui/app/components/modals/clear-approved-origins/clear-approved-origins.container.js16
-rw-r--r--ui/app/components/modals/clear-approved-origins/index.js1
-rw-r--r--ui/app/components/modals/modal.js14
-rw-r--r--ui/app/components/network-display/index.scss5
-rw-r--r--ui/app/components/network-display/network-display.component.js17
-rw-r--r--ui/app/components/page-container/index.scss1
-rw-r--r--ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js88
-rw-r--r--ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.container.js5
-rw-r--r--ui/app/components/pages/confirm-transaction-switch/confirm-transaction-switch.component.js10
-rw-r--r--ui/app/components/pages/create-account/connect-hardware/account-list.js2
-rw-r--r--ui/app/components/pages/create-account/connect-hardware/connect-screen.js16
-rw-r--r--ui/app/components/pages/create-account/connect-hardware/index.js7
-rw-r--r--ui/app/components/pages/home/home.component.js10
-rw-r--r--ui/app/components/pages/home/home.container.js2
-rw-r--r--ui/app/components/pages/provider-approval/index.js1
-rw-r--r--ui/app/components/pages/provider-approval/provider-approval.component.js28
-rw-r--r--ui/app/components/pages/provider-approval/provider-approval.container.js12
-rw-r--r--ui/app/components/pages/settings/settings-tab/settings-tab.component.js63
-rw-r--r--ui/app/components/pages/settings/settings-tab/settings-tab.container.js8
-rw-r--r--ui/app/components/provider-page-container/index.js3
-rw-r--r--ui/app/components/provider-page-container/index.scss121
-rw-r--r--ui/app/components/provider-page-container/provider-page-container-content/index.js1
-rw-r--r--ui/app/components/provider-page-container/provider-page-container-content/provider-page-container-content.component.js77
-rw-r--r--ui/app/components/provider-page-container/provider-page-container-content/provider-page-container-content.container.js11
-rw-r--r--ui/app/components/provider-page-container/provider-page-container-header/index.js1
-rw-r--r--ui/app/components/provider-page-container/provider-page-container-header/provider-page-container-header.component.js12
-rw-r--r--ui/app/components/provider-page-container/provider-page-container.component.js50
-rw-r--r--ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js4
-rw-r--r--ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js25
-rw-r--r--ui/app/components/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js2
-rw-r--r--ui/app/components/send/send-content/send-amount-row/send-amount-row.component.js5
-rw-r--r--ui/app/components/send/send-content/send-amount-row/send-amount-row.container.js4
-rw-r--r--ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js1
-rw-r--r--ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.component.js4
-rw-r--r--ui/app/components/send/send-content/send-from-row/send-from-row.component.js5
-rw-r--r--ui/app/components/send/send-content/send-from-row/send-from-row.container.js10
-rw-r--r--ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js4
-rw-r--r--ui/app/components/send/send-content/send-gas-row/send-gas-row.container.js6
-rw-r--r--ui/app/components/send/send-content/send-to-row/send-to-row.component.js4
-rw-r--r--ui/app/components/send/send-footer/send-footer.component.js4
-rw-r--r--ui/app/components/send/send.component.js6
-rw-r--r--ui/app/components/send/send.utils.js6
-rw-r--r--ui/app/components/send/tests/send-component.test.js2
-rw-r--r--ui/app/components/send/tests/send-utils.test.js3
-rw-r--r--ui/app/components/token-balance/index.scss14
-rw-r--r--ui/app/components/token-balance/token-balance.component.js12
-rw-r--r--ui/app/components/token-currency-display/token-currency-display.component.js15
-rw-r--r--ui/app/components/token-input/token-input.component.js8
-rw-r--r--ui/app/components/transaction-list-item/index.scss2
-rw-r--r--ui/app/components/transaction-status/tests/transaction-status.component.test.js35
-rw-r--r--ui/app/components/transaction-status/transaction-status.component.js1
-rw-r--r--ui/app/components/transaction-view-balance/index.scss26
-rw-r--r--ui/app/components/transaction-view-balance/transaction-view-balance.component.js16
-rw-r--r--ui/app/components/unit-input/index.scss4
-rw-r--r--ui/app/components/unit-input/unit-input.component.js2
-rw-r--r--ui/app/conversion-util.js2
-rw-r--r--ui/app/css/itcss/components/new-account.scss43
-rw-r--r--ui/app/css/itcss/components/pages/index.scss2
-rw-r--r--ui/app/css/itcss/components/pages/provider-approval.scss11
-rw-r--r--ui/app/css/itcss/components/send.scss2
-rw-r--r--ui/app/ducks/confirm-transaction.duck.js7
-rw-r--r--ui/app/reducers/metamask.js11
-rw-r--r--ui/app/select-app.js29
-rw-r--r--ui/app/selectors.js8
-rw-r--r--ui/app/selectors/confirm-transaction.js9
-rw-r--r--ui/app/token-util.js2
-rw-r--r--ui/app/welcome-screen.js2
82 files changed, 982 insertions, 218 deletions
diff --git a/ui/app/actions.js b/ui/app/actions.js
index a8b9189e9..e3cf57c9e 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -325,6 +325,9 @@ var actions = {
clearPendingTokens,
createCancelTransaction,
+ approveProviderRequest,
+ rejectProviderRequest,
+ clearApprovedOrigins,
}
module.exports = actions
@@ -992,7 +995,7 @@ function updateSendTokenBalance ({
.then(usersToken => {
if (usersToken) {
const newTokenBalance = calcTokenBalance({ selectedToken, usersToken })
- dispatch(setSendTokenBalance(newTokenBalance.toString(10)))
+ dispatch(setSendTokenBalance(newTokenBalance))
}
})
.catch(err => {
@@ -2484,3 +2487,21 @@ function setPendingTokens (pendingTokens) {
payload: tokens,
}
}
+
+function approveProviderRequest (origin) {
+ return (dispatch) => {
+ background.approveProviderRequest(origin)
+ }
+}
+
+function rejectProviderRequest (origin) {
+ return (dispatch) => {
+ background.rejectProviderRequest(origin)
+ }
+}
+
+function clearApprovedOrigins () {
+ return (dispatch) => {
+ background.clearApprovedOrigins()
+ }
+}
diff --git a/ui/app/components/app-header/app-header.component.js b/ui/app/components/app-header/app-header.component.js
index c82dc1de9..83ec4809d 100644
--- a/ui/app/components/app-header/app-header.component.js
+++ b/ui/app/components/app-header/app-header.component.js
@@ -108,7 +108,7 @@ export default class AppHeader extends PureComponent {
>
<img
className="app-header__metafox-logo app-header__metafox-logo--horizontal"
- src="/images/logo/metamask-logo-horizontal-beta.svg"
+ src="/images/logo/metamask-logo-horizontal.svg"
height={30}
/>
<img
diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js
index 0f8514c81..4e2769ee8 100644
--- a/ui/app/components/balance-component.js
+++ b/ui/app/components/balance-component.js
@@ -86,13 +86,13 @@ BalanceComponent.prototype.renderBalance = function () {
className: 'token-amount',
value: balanceValue,
type: PRIMARY,
- ethNumberOfDecimals: 3,
+ ethNumberOfDecimals: 4,
}),
showFiat && h(UserPreferencedCurrencyDisplay, {
value: balanceValue,
type: SECONDARY,
- ethNumberOfDecimals: 3,
+ ethNumberOfDecimals: 4,
}),
])
}
diff --git a/ui/app/components/confirm-page-container/confirm-page-container-header/index.scss b/ui/app/components/confirm-page-container/confirm-page-container-header/index.scss
index 43e1e4427..be77edbdf 100644
--- a/ui/app/components/confirm-page-container/confirm-page-container-header/index.scss
+++ b/ui/app/components/confirm-page-container/confirm-page-container-header/index.scss
@@ -7,7 +7,7 @@
display: flex;
justify-content: space-between;
border-bottom: 1px solid $geyser;
- padding: 13px 13px 13px 24px;
+ padding: 4px 13px 4px 13px;
flex: 0 0 auto;
}
diff --git a/ui/app/components/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js b/ui/app/components/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js
new file mode 100755
index 000000000..8327f997b
--- /dev/null
+++ b/ui/app/components/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js
@@ -0,0 +1,69 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+const ConfirmPageContainerNavigation = props => {
+ const { onNextTx, totalTx, positionOfCurrentTx, nextTxId, prevTxId, showNavigation, firstTx, lastTx, ofText, requestsWaitingText } = props
+
+ return (
+ <div className="confirm-page-container-navigation"
+ style={{
+ display: showNavigation ? 'flex' : 'none',
+ }}
+ >
+ <div className="confirm-page-container-navigation__container"
+ style={{
+ visibility: prevTxId ? 'initial' : 'hidden',
+ }}>
+ <div
+ className="confirm-page-container-navigation__arrow"
+ onClick={() => onNextTx(firstTx)}>
+ <img src="/images/double-arrow.svg" />
+ </div>
+ <div
+ className="confirm-page-container-navigation__arrow"
+ onClick={() => onNextTx(prevTxId)}>
+ <img src="/images/single-arrow.svg" />
+ </div>
+ </div>
+ <div className="confirm-page-container-navigation__textcontainer">
+ <div className="confirm-page-container-navigation__navtext">
+ {positionOfCurrentTx} {ofText} {totalTx}
+ </div>
+ <div className="confirm-page-container-navigation__longtext">
+ {requestsWaitingText}
+ </div>
+ </div>
+ <div
+ className="confirm-page-container-navigation__container"
+ style={{
+ visibility: nextTxId ? 'initial' : 'hidden',
+ }}>
+ <div
+ className="confirm-page-container-navigation__arrow"
+ onClick={() => onNextTx(nextTxId)}>
+ <img className="confirm-page-container-navigation__imageflip" src="/images/single-arrow.svg" />
+ </div>
+ <div
+ className="confirm-page-container-navigation__arrow"
+ onClick={() => onNextTx(lastTx)}>
+ <img className="confirm-page-container-navigation__imageflip" src="/images/double-arrow.svg" />
+ </div>
+ </div>
+ </div>
+ )
+}
+
+ConfirmPageContainerNavigation.propTypes = {
+ totalTx: PropTypes.number,
+ positionOfCurrentTx: PropTypes.number,
+ onNextTx: PropTypes.func,
+ nextTxId: PropTypes.string,
+ prevTxId: PropTypes.string,
+ showNavigation: PropTypes.bool,
+ firstTx: PropTypes.string,
+ lastTx: PropTypes.string,
+ ofText: PropTypes.string,
+ requestsWaitingText: PropTypes.string,
+}
+
+export default ConfirmPageContainerNavigation
diff --git a/ui/app/components/confirm-page-container/confirm-page-container-navigation/index.js b/ui/app/components/confirm-page-container/confirm-page-container-navigation/index.js
new file mode 100755
index 000000000..d97c1b447
--- /dev/null
+++ b/ui/app/components/confirm-page-container/confirm-page-container-navigation/index.js
@@ -0,0 +1 @@
+export { default } from './confirm-page-container-navigation.component'
diff --git a/ui/app/components/confirm-page-container/confirm-page-container-navigation/index.scss b/ui/app/components/confirm-page-container/confirm-page-container-navigation/index.scss
new file mode 100755
index 000000000..0cf184c60
--- /dev/null
+++ b/ui/app/components/confirm-page-container/confirm-page-container-navigation/index.scss
@@ -0,0 +1,54 @@
+.confirm-page-container-navigation {
+ display: flex;
+ justify-content: space-between;
+ font: inherit;
+ padding: 4px 10px 4px 10px;
+ border-bottom: 1px solid $geyser;
+ flex: 0 0 auto;
+
+ &__container {
+ display: flex;
+ }
+
+ &__arrow {
+ cursor: pointer;
+ display: flex;
+ padding-left: 5px;
+ padding-right: 5px;
+ }
+
+ &__arrow:hover {
+ -webkit-transform: scale(1.1);
+ -moz-transform: scale(1.1);
+ -o-transform: scale(1.1);
+ transform: scale(1.1);
+ }
+
+ &__arrow:active {
+ -webkit-transform: scale(0.95);
+ -moz-transform: scale(0.95);
+ -o-transform: scale(0.95);
+ transform: scale(0.95);
+ }
+
+ &__textcontainer {
+ text-align: center;
+ }
+
+ &__navtext {
+ font-size: 9px;
+ font-weight: bold;
+ }
+
+ &__longtext {
+ color: $oslo-gray;
+ font-size: 8px;
+ }
+
+ &__imageflip {
+ -webkit-transform: scaleX(-1);
+ -moz-transform: scaleX(-1);
+ -o-transform: scaleX(-1);
+ transform: scaleX(-1);
+ }
+} \ No newline at end of file
diff --git a/ui/app/components/confirm-page-container/confirm-page-container.component.js b/ui/app/components/confirm-page-container/confirm-page-container.component.js
index 8b2e47cbb..10edf3b16 100644
--- a/ui/app/components/confirm-page-container/confirm-page-container.component.js
+++ b/ui/app/components/confirm-page-container/confirm-page-container.component.js
@@ -2,7 +2,7 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types'
import SenderToRecipient from '../sender-to-recipient'
import { PageContainerFooter } from '../page-container'
-import { ConfirmPageContainerHeader, ConfirmPageContainerContent } from './'
+import { ConfirmPageContainerHeader, ConfirmPageContainerContent, ConfirmPageContainerNavigation } from './'
export default class ConfirmPageContainer extends Component {
static contextTypes = {
@@ -43,6 +43,17 @@ export default class ConfirmPageContainer extends Component {
summaryComponent: PropTypes.node,
warning: PropTypes.string,
unapprovedTxCount: PropTypes.number,
+ // Navigation
+ totalTx: PropTypes.number,
+ positionOfCurrentTx: PropTypes.number,
+ nextTxId: PropTypes.string,
+ prevTxId: PropTypes.string,
+ showNavigation: PropTypes.bool,
+ onNextTx: PropTypes.func,
+ firstTx: PropTypes.string,
+ lastTx: PropTypes.string,
+ ofText: PropTypes.string,
+ requestsWaitingText: PropTypes.string,
// Footer
onCancelAll: PropTypes.func,
onCancel: PropTypes.func,
@@ -79,11 +90,33 @@ export default class ConfirmPageContainer extends Component {
unapprovedTxCount,
assetImage,
warning,
+ totalTx,
+ positionOfCurrentTx,
+ nextTxId,
+ prevTxId,
+ showNavigation,
+ onNextTx,
+ firstTx,
+ lastTx,
+ ofText,
+ requestsWaitingText,
} = this.props
const renderAssetImage = contentComponent || (!contentComponent && !identiconAddress)
return (
<div className="page-container">
+ <ConfirmPageContainerNavigation
+ totalTx={totalTx}
+ positionOfCurrentTx={positionOfCurrentTx}
+ nextTxId={nextTxId}
+ prevTxId={prevTxId}
+ showNavigation={showNavigation}
+ onNextTx={(txId) => onNextTx(txId)}
+ firstTx={firstTx}
+ lastTx={lastTx}
+ ofText={ofText}
+ requestsWaitingText={requestsWaitingText}
+ />
<ConfirmPageContainerHeader
showEdit={showEdit}
onEdit={() => onEdit()}
diff --git a/ui/app/components/confirm-page-container/index.js b/ui/app/components/confirm-page-container/index.js
index ee88aa5d3..28b17614e 100644
--- a/ui/app/components/confirm-page-container/index.js
+++ b/ui/app/components/confirm-page-container/index.js
@@ -1,6 +1,8 @@
export { default } from './confirm-page-container.component'
export { default as ConfirmPageContainerHeader } from './confirm-page-container-header'
export { default as ConfirmDetailRow } from './confirm-detail-row'
+export { default as ConfirmPageContainerNavigation } from './confirm-page-container-navigation'
+
export {
default as ConfirmPageContainerContent,
ConfirmPageContainerSummary,
diff --git a/ui/app/components/confirm-page-container/index.scss b/ui/app/components/confirm-page-container/index.scss
index af7a5b555..d41cd4423 100644
--- a/ui/app/components/confirm-page-container/index.scss
+++ b/ui/app/components/confirm-page-container/index.scss
@@ -3,3 +3,5 @@
@import './confirm-page-container-header/index';
@import './confirm-detail-row/index';
+
+@import './confirm-page-container-navigation/index'; \ No newline at end of file
diff --git a/ui/app/components/currency-display/currency-display.container.js b/ui/app/components/currency-display/currency-display.container.js
index 6ddf07172..e581f8a5e 100644
--- a/ui/app/components/currency-display/currency-display.container.js
+++ b/ui/app/components/currency-display/currency-display.container.js
@@ -20,15 +20,24 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
currency,
denomination,
hideLabel,
+ displayValue: propsDisplayValue,
+ suffix: propsSuffix,
...restOwnProps
} = ownProps
const toCurrency = currency || currentCurrency
- const convertedValue = getValueFromWeiHex({
- value, fromCurrency: nativeCurrency, toCurrency, conversionRate, numberOfDecimals, toDenomination: denomination,
- })
- const displayValue = formatCurrency(convertedValue, toCurrency)
- const suffix = hideLabel ? undefined : toCurrency.toUpperCase()
+
+ const displayValue = propsDisplayValue || formatCurrency(
+ getValueFromWeiHex({
+ value,
+ fromCurrency: nativeCurrency,
+ toCurrency, conversionRate,
+ numberOfDecimals,
+ toDenomination: denomination,
+ }),
+ toCurrency
+ )
+ const suffix = propsSuffix || (hideLabel ? undefined : toCurrency.toUpperCase())
return {
...restStateProps,
diff --git a/ui/app/components/currency-display/tests/currency-display.container.test.js b/ui/app/components/currency-display/tests/currency-display.container.test.js
index 0c886af50..9888c366e 100644
--- a/ui/app/components/currency-display/tests/currency-display.container.test.js
+++ b/ui/app/components/currency-display/tests/currency-display.container.test.js
@@ -131,7 +131,7 @@ describe('CurrencyDisplay container', () => {
},
result: {
nativeCurrency: 'ETH',
- displayValue: '1e-9',
+ displayValue: '0.000000001',
suffix: undefined,
},
},
diff --git a/ui/app/components/index.scss b/ui/app/components/index.scss
index 72de6cb93..f901aed7d 100644
--- a/ui/app/components/index.scss
+++ b/ui/app/components/index.scss
@@ -32,12 +32,16 @@
@import './pages/index';
+@import './provider-page-container/index';
+
@import './selected-account/index';
@import './sender-to-recipient/index';
@import './tabs/index';
+@import './token-balance/index';
+
@import './transaction-activity-log/index';
@import './transaction-breakdown/index';
diff --git a/ui/app/components/menu-bar/menu-bar.component.js b/ui/app/components/menu-bar/menu-bar.component.js
index 7460e8dd5..e64809f3f 100644
--- a/ui/app/components/menu-bar/menu-bar.component.js
+++ b/ui/app/components/menu-bar/menu-bar.component.js
@@ -52,7 +52,7 @@ export default class MenuBar extends PureComponent {
{
accountDetailsMenuOpen && (
<AccountDetailsDropdown
- className="menu-bar__account-details-dropdown"
+ className="menu-bar__account-details-dropdown"
onClose={() => this.setState({ accountDetailsMenuOpen: false })}
/>
)
diff --git a/ui/app/components/modals/clear-approved-origins/clear-approved-origins.component.js b/ui/app/components/modals/clear-approved-origins/clear-approved-origins.component.js
new file mode 100644
index 000000000..ceaa20a95
--- /dev/null
+++ b/ui/app/components/modals/clear-approved-origins/clear-approved-origins.component.js
@@ -0,0 +1,39 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import Modal, { ModalContent } from '../../modal'
+
+export default class ClearApprovedOrigins extends PureComponent {
+ static propTypes = {
+ hideModal: PropTypes.func.isRequired,
+ clearApprovedOrigins: PropTypes.func.isRequired,
+ }
+
+ static contextTypes = {
+ t: PropTypes.func,
+ }
+
+ handleClear = () => {
+ const { clearApprovedOrigins, hideModal } = this.props
+ clearApprovedOrigins()
+ hideModal()
+ }
+
+ render () {
+ const { t } = this.context
+
+ return (
+ <Modal
+ onSubmit={this.handleClear}
+ onCancel={() => this.props.hideModal()}
+ submitText={t('ok')}
+ cancelText={t('nevermind')}
+ submitType="secondary"
+ >
+ <ModalContent
+ title={t('clearApprovalData')}
+ description={t('confirmClear')}
+ />
+ </Modal>
+ )
+ }
+}
diff --git a/ui/app/components/modals/clear-approved-origins/clear-approved-origins.container.js b/ui/app/components/modals/clear-approved-origins/clear-approved-origins.container.js
new file mode 100644
index 000000000..3a801a062
--- /dev/null
+++ b/ui/app/components/modals/clear-approved-origins/clear-approved-origins.container.js
@@ -0,0 +1,16 @@
+import { connect } from 'react-redux'
+import { compose } from 'recompose'
+import withModalProps from '../../../higher-order-components/with-modal-props'
+import ClearApprovedOriginsComponent from './clear-approved-origins.component'
+import { clearApprovedOrigins } from '../../../actions'
+
+const mapDispatchToProps = dispatch => {
+ return {
+ clearApprovedOrigins: () => dispatch(clearApprovedOrigins()),
+ }
+}
+
+export default compose(
+ withModalProps,
+ connect(null, mapDispatchToProps)
+)(ClearApprovedOriginsComponent)
diff --git a/ui/app/components/modals/clear-approved-origins/index.js b/ui/app/components/modals/clear-approved-origins/index.js
new file mode 100644
index 000000000..b3e321995
--- /dev/null
+++ b/ui/app/components/modals/clear-approved-origins/index.js
@@ -0,0 +1 @@
+export { default } from './clear-approved-origins.container'
diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js
index 338229a28..5aff4f5e1 100644
--- a/ui/app/components/modals/modal.js
+++ b/ui/app/components/modals/modal.js
@@ -28,6 +28,7 @@ import ConfirmCustomizeGasModal from './customize-gas'
import CancelTransaction from './cancel-transaction'
import WelcomeBeta from './welcome-beta'
import RejectTransactions from './reject-transactions'
+import ClearApprovedOrigins from './clear-approved-origins'
const modalContainerBaseStyle = {
transform: 'translate3d(-50%, 0, 0px)',
@@ -212,6 +213,19 @@ const MODALS = {
},
},
+ CLEAR_APPROVED_ORIGINS: {
+ contents: h(ClearApprovedOrigins),
+ mobileModalStyle: {
+ ...modalContainerMobileStyle,
+ },
+ laptopModalStyle: {
+ ...modalContainerLaptopStyle,
+ },
+ contentStyle: {
+ borderRadius: '8px',
+ },
+ },
+
OLD_UI_NOTIFICATION_MODAL: {
contents: [
h(NotifcationModal, {
diff --git a/ui/app/components/network-display/index.scss b/ui/app/components/network-display/index.scss
index 2085cff67..e9f2f2057 100644
--- a/ui/app/components/network-display/index.scss
+++ b/ui/app/components/network-display/index.scss
@@ -3,11 +3,14 @@
display: flex;
align-items: center;
justify-content: flex-start;
- background-color: lighten(rgb(125, 128, 130), 45%);
padding: 0 10px;
border-radius: 4px;
height: 25px;
+ &--colored {
+ background-color: lighten(rgb(125, 128, 130), 45%);
+ }
+
&--mainnet {
background-color: lighten($blue-lagoon, 68%);
}
diff --git a/ui/app/components/network-display/network-display.component.js b/ui/app/components/network-display/network-display.component.js
index 82f9ff9c3..22d617099 100644
--- a/ui/app/components/network-display/network-display.component.js
+++ b/ui/app/components/network-display/network-display.component.js
@@ -16,7 +16,12 @@ const networkToClassHash = {
}
export default class NetworkDisplay extends Component {
+ static defaultProps = {
+ colored: true,
+ }
+
static propTypes = {
+ colored: PropTypes.bool,
network: PropTypes.string,
provider: PropTypes.object,
}
@@ -41,14 +46,16 @@ export default class NetworkDisplay extends Component {
}
render () {
- const { network, provider: { type, nickname } } = this.props
+ const { colored, network, provider: { type, nickname } } = this.props
const networkClass = networkToClassHash[network]
return (
- <div className={classnames(
- 'network-display__container',
- networkClass && ('network-display__container--' + networkClass)
- )}>
+ <div
+ className={classnames('network-display__container', {
+ 'network-display__container--colored': colored,
+ ['network-display__container--' + networkClass]: colored && networkClass,
+ })}
+ >
{
networkClass
? <div className={`network-display__icon network-display__icon--${networkClass}`} />
diff --git a/ui/app/components/page-container/index.scss b/ui/app/components/page-container/index.scss
index 6742e3082..ba1215e84 100644
--- a/ui/app/components/page-container/index.scss
+++ b/ui/app/components/page-container/index.scss
@@ -101,6 +101,7 @@
font-size: 2rem;
font-weight: 500;
line-height: 2rem;
+ margin-right: 1.5rem;
}
&__subtitle {
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 7d01aaffb..e3abde233 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
@@ -1,8 +1,9 @@
+import ethUtil from 'ethereumjs-util'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import ConfirmPageContainer, { ConfirmDetailRow } from '../../confirm-page-container'
import { isBalanceSufficient } from '../../send/send.utils'
-import { DEFAULT_ROUTE } from '../../../routes'
+import { DEFAULT_ROUTE, CONFIRM_TRANSACTION_ROUTE } from '../../../routes'
import {
INSUFFICIENT_FUNDS_ERROR_KEY,
TRANSACTION_ERROR_KEY,
@@ -55,6 +56,7 @@ export default class ConfirmTransactionBase extends Component {
transactionStatus: PropTypes.string,
txData: PropTypes.object,
unapprovedTxCount: PropTypes.number,
+ currentNetworkUnapprovedTxs: PropTypes.object,
// Component props
action: PropTypes.string,
contentComponent: PropTypes.node,
@@ -238,7 +240,7 @@ export default class ConfirmTransactionBase extends Component {
)
}
<div className="confirm-page-container-content__data-box-label">
- {`${t('hexData')}:`}
+ {`${t('hexData')}: ${ethUtil.toBuffer(data).length} bytes`}
</div>
<div className="confirm-page-container-content__data-box">
{ data }
@@ -293,22 +295,35 @@ export default class ConfirmTransactionBase extends Component {
return
}
- this.setState({ submitting: true, submitError: null })
-
- if (onSubmit) {
- Promise.resolve(onSubmit(txData))
- .then(this.setState({ submitting: false }))
- } else {
- sendTransaction(txData)
- .then(() => {
- clearConfirmTransaction()
- this.setState({ submitting: false })
- history.push(DEFAULT_ROUTE)
- })
- .catch(error => {
- this.setState({ submitting: false, submitError: error.message })
- })
- }
+ this.setState({
+ submitting: true,
+ submitError: null,
+ }, () => {
+ if (onSubmit) {
+ Promise.resolve(onSubmit(txData))
+ .then(() => {
+ this.setState({
+ submitting: false,
+ })
+ })
+ } else {
+ sendTransaction(txData)
+ .then(() => {
+ clearConfirmTransaction()
+ this.setState({
+ submitting: false,
+ }, () => {
+ history.push(DEFAULT_ROUTE)
+ })
+ })
+ .catch(error => {
+ this.setState({
+ submitting: false,
+ submitError: error.message,
+ })
+ })
+ }
+ })
}
renderTitleComponent () {
@@ -348,6 +363,32 @@ export default class ConfirmTransactionBase extends Component {
)
}
+ handleNextTx (txId) {
+ const { history, clearConfirmTransaction } = this.props
+ if (txId) {
+ clearConfirmTransaction()
+ history.push(`${CONFIRM_TRANSACTION_ROUTE}/${txId}`)
+ }
+ }
+
+ getNavigateTxData () {
+ const { currentNetworkUnapprovedTxs, txData: { id } = {} } = this.props
+ const enumUnapprovedTxs = Object.keys(currentNetworkUnapprovedTxs).reverse()
+ const currentPosition = enumUnapprovedTxs.indexOf(id.toString())
+
+ return {
+ totalTx: enumUnapprovedTxs.length,
+ positionOfCurrentTx: currentPosition + 1,
+ nextTxId: enumUnapprovedTxs[currentPosition + 1],
+ prevTxId: enumUnapprovedTxs[currentPosition - 1],
+ showNavigation: enumUnapprovedTxs.length > 1,
+ firstTx: enumUnapprovedTxs[0],
+ lastTx: enumUnapprovedTxs[enumUnapprovedTxs.length - 1],
+ ofText: this.context.t('ofTextNofM'),
+ requestsWaitingText: this.context.t('requestsAwaitingAcknowledgement'),
+ }
+ }
+
render () {
const {
isTxReprice,
@@ -376,6 +417,7 @@ export default class ConfirmTransactionBase extends Component {
const { name } = methodData
const { valid, errorKey } = this.getErrorKey()
+ const { totalTx, positionOfCurrentTx, nextTxId, prevTxId, showNavigation, firstTx, lastTx, ofText, requestsWaitingText } = this.getNavigateTxData()
return (
<ConfirmPageContainer
@@ -401,6 +443,16 @@ export default class ConfirmTransactionBase extends Component {
errorMessage={errorMessage || submitError}
errorKey={propsErrorKey || errorKey}
warning={warning}
+ totalTx={totalTx}
+ positionOfCurrentTx={positionOfCurrentTx}
+ nextTxId={nextTxId}
+ prevTxId={prevTxId}
+ showNavigation={showNavigation}
+ onNextTx={(txId) => this.handleNextTx(txId)}
+ firstTx={firstTx}
+ lastTx={lastTx}
+ ofText={ofText}
+ requestsWaitingText={requestsWaitingText}
disabled={!propsValid || !valid || submitting}
onEdit={() => this.handleEdit()}
onCancelAll={() => this.handleCancelAll()}
diff --git a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.container.js
index c366d5137..45bf62fb9 100644
--- a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.container.js
+++ b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.container.js
@@ -73,9 +73,9 @@ const mapStateToProps = (state, props) => {
const currentNetworkUnapprovedTxs = R.filter(
({ metamaskNetworkId }) => metamaskNetworkId === network,
- valuesFor(unapprovedTxs),
+ unapprovedTxs,
)
- const unapprovedTxCount = currentNetworkUnapprovedTxs.length
+ const unapprovedTxCount = valuesFor(currentNetworkUnapprovedTxs).length
return {
balance,
@@ -104,6 +104,7 @@ const mapStateToProps = (state, props) => {
assetImage,
unapprovedTxs,
unapprovedTxCount,
+ currentNetworkUnapprovedTxs,
}
}
diff --git a/ui/app/components/pages/confirm-transaction-switch/confirm-transaction-switch.component.js b/ui/app/components/pages/confirm-transaction-switch/confirm-transaction-switch.component.js
index 2c44b6094..76782cf6a 100644
--- a/ui/app/components/pages/confirm-transaction-switch/confirm-transaction-switch.component.js
+++ b/ui/app/components/pages/confirm-transaction-switch/confirm-transaction-switch.component.js
@@ -32,21 +32,15 @@ export default class ConfirmTransactionSwitch extends Component {
txData,
methodData: { name },
fetchingData,
- isEtherTransaction,
} = this.props
const { id, txParams: { data } = {} } = txData
- if (isConfirmDeployContract(txData)) {
- const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_DEPLOY_CONTRACT_PATH}`
- return <Redirect to={{ pathname }} />
- }
-
if (fetchingData) {
return <Loading />
}
- if (isEtherTransaction) {
- const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_SEND_ETHER_PATH}`
+ if (isConfirmDeployContract(txData)) {
+ const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_DEPLOY_CONTRACT_PATH}`
return <Redirect to={{ pathname }} />
}
diff --git a/ui/app/components/pages/create-account/connect-hardware/account-list.js b/ui/app/components/pages/create-account/connect-hardware/account-list.js
index 2767b2e1f..c63de234a 100644
--- a/ui/app/components/pages/create-account/connect-hardware/account-list.js
+++ b/ui/app/components/pages/create-account/connect-hardware/account-list.js
@@ -152,7 +152,7 @@ class AccountList extends Component {
}, [this.context.t('cancel')]),
h(Button, {
- type: 'primary',
+ type: 'confirm',
large: true,
className: 'new-account-connect-form__button unlock',
disabled,
diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js
index d3abf3119..49a5610c1 100644
--- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js
+++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js
@@ -45,11 +45,13 @@ class ConnectScreen extends Component {
this.renderConnectToLedgerButton(),
this.renderConnectToTrezorButton(),
]),
- h(
- `button.hw-connect__connect-btn${!this.state.selectedDevice ? '.disabled' : ''}`,
- { onClick: this.connect },
- this.context.t('connect')
- ),
+ h(Button, {
+ type: 'confirm',
+ large: true,
+ className: 'hw-connect__connect-btn',
+ onClick: this.connect,
+ disabled: !this.state.selectedDevice,
+ }, this.context.t('connect')),
])
)
}
@@ -67,9 +69,7 @@ class ConnectScreen extends Component {
onClick: () => global.platform.openWindow({
url: 'https://google.com/chrome',
}),
- },
- this.context.t('downloadGoogleChrome')
- ),
+ }, this.context.t('downloadGoogleChrome')),
])
)
}
diff --git a/ui/app/components/pages/create-account/connect-hardware/index.js b/ui/app/components/pages/create-account/connect-hardware/index.js
index 547df5223..4fe25f629 100644
--- a/ui/app/components/pages/create-account/connect-hardware/index.js
+++ b/ui/app/components/pages/create-account/connect-hardware/index.js
@@ -50,9 +50,8 @@ class ConnectHardwareForm extends Component {
}
connectToHardwareWallet = (device) => {
- // None of the hardware wallets are supported
- // At least for now
- if (getPlatform() === PLATFORM_FIREFOX) {
+ // Ledger hardware wallets are not supported on firefox
+ if (getPlatform() === PLATFORM_FIREFOX && device === 'ledger') {
this.setState({ browserSupported: false, error: null})
return null
}
@@ -126,7 +125,7 @@ class ConnectHardwareForm extends Component {
.catch(e => {
if (e === 'Window blocked') {
this.setState({ browserSupported: false, error: null})
- } else if (e !== 'Window closed') {
+ } else if (e !== 'Window closed' && e !== 'Popup closed') {
this.setState({ error: e.toString() })
}
})
diff --git a/ui/app/components/pages/home/home.component.js b/ui/app/components/pages/home/home.component.js
index d3c71c4f6..b9ec3c258 100644
--- a/ui/app/components/pages/home/home.component.js
+++ b/ui/app/components/pages/home/home.component.js
@@ -4,6 +4,8 @@ import Media from 'react-media'
import { Redirect } from 'react-router-dom'
import WalletView from '../../wallet-view'
import TransactionView from '../../transaction-view'
+import ProviderApproval from '../provider-approval'
+
import {
INITIALIZE_BACKUP_PHRASE_ROUTE,
RESTORE_VAULT_ROUTE,
@@ -21,6 +23,7 @@ export default class Home extends PureComponent {
seedWords: PropTypes.string,
suggestedTokens: PropTypes.object,
unconfirmedTransactionsCount: PropTypes.number,
+ providerRequests: PropTypes.array,
}
componentDidMount () {
@@ -46,6 +49,7 @@ export default class Home extends PureComponent {
lostAccounts,
forgottenPassword,
seedWords,
+ providerRequests,
} = this.props
// notices
@@ -62,6 +66,12 @@ export default class Home extends PureComponent {
return <Redirect to={{ pathname: RESTORE_VAULT_ROUTE }} />
}
+ if (providerRequests && providerRequests.length > 0) {
+ return (
+ <ProviderApproval providerRequest={providerRequests[0]} />
+ )
+ }
+
return (
<div className="main-container">
<div className="account-and-transaction-details">
diff --git a/ui/app/components/pages/home/home.container.js b/ui/app/components/pages/home/home.container.js
index 58001df6b..bb8cf5e81 100644
--- a/ui/app/components/pages/home/home.container.js
+++ b/ui/app/components/pages/home/home.container.js
@@ -11,6 +11,7 @@ const mapStateToProps = state => {
lostAccounts,
seedWords,
suggestedTokens,
+ providerRequests,
} = metamask
const { forgottenPassword } = appState
@@ -21,6 +22,7 @@ const mapStateToProps = state => {
seedWords,
suggestedTokens,
unconfirmedTransactionsCount: unconfirmedTransactionsCountSelector(state),
+ providerRequests,
}
}
diff --git a/ui/app/components/pages/provider-approval/index.js b/ui/app/components/pages/provider-approval/index.js
new file mode 100644
index 000000000..4162f3155
--- /dev/null
+++ b/ui/app/components/pages/provider-approval/index.js
@@ -0,0 +1 @@
+export { default } from './provider-approval.container'
diff --git a/ui/app/components/pages/provider-approval/provider-approval.component.js b/ui/app/components/pages/provider-approval/provider-approval.component.js
new file mode 100644
index 000000000..da98bc3fc
--- /dev/null
+++ b/ui/app/components/pages/provider-approval/provider-approval.component.js
@@ -0,0 +1,28 @@
+import PropTypes from 'prop-types'
+import React, { Component } from 'react'
+import ProviderPageContainer from '../../provider-page-container'
+
+export default class ProviderApproval extends Component {
+ static propTypes = {
+ approveProviderRequest: PropTypes.func.isRequired,
+ providerRequest: PropTypes.object.isRequired,
+ rejectProviderRequest: PropTypes.func.isRequired,
+ };
+
+ static contextTypes = {
+ t: PropTypes.func,
+ };
+
+ render () {
+ const { approveProviderRequest, providerRequest, rejectProviderRequest } = this.props
+ return (
+ <ProviderPageContainer
+ approveProviderRequest={approveProviderRequest}
+ origin={providerRequest.origin}
+ rejectProviderRequest={rejectProviderRequest}
+ siteImage={providerRequest.siteImage}
+ siteTitle={providerRequest.siteTitle}
+ />
+ )
+ }
+}
diff --git a/ui/app/components/pages/provider-approval/provider-approval.container.js b/ui/app/components/pages/provider-approval/provider-approval.container.js
new file mode 100644
index 000000000..b223244a1
--- /dev/null
+++ b/ui/app/components/pages/provider-approval/provider-approval.container.js
@@ -0,0 +1,12 @@
+import { connect } from 'react-redux'
+import ProviderApproval from './provider-approval.component'
+import { approveProviderRequest, rejectProviderRequest } from '../../../actions'
+
+function mapDispatchToProps (dispatch) {
+ return {
+ approveProviderRequest: origin => dispatch(approveProviderRequest(origin)),
+ rejectProviderRequest: origin => dispatch(rejectProviderRequest(origin)),
+ }
+}
+
+export default connect(null, mapDispatchToProps)(ProviderApproval)
diff --git a/ui/app/components/pages/settings/settings-tab/settings-tab.component.js b/ui/app/components/pages/settings/settings-tab/settings-tab.component.js
index cd81491a8..a0a8ed47e 100644
--- a/ui/app/components/pages/settings/settings-tab/settings-tab.component.js
+++ b/ui/app/components/pages/settings/settings-tab/settings-tab.component.js
@@ -39,12 +39,15 @@ export default class SettingsTab extends PureComponent {
metamask: PropTypes.object,
setUseBlockie: PropTypes.func,
setHexDataFeatureFlag: PropTypes.func,
+ setPrivacyMode: PropTypes.func,
+ privacyMode: PropTypes.bool,
setCurrentCurrency: PropTypes.func,
setRpcTarget: PropTypes.func,
delRpcTarget: PropTypes.func,
displayWarning: PropTypes.func,
revealSeedConfirmation: PropTypes.func,
setFeatureFlagToBeta: PropTypes.func,
+ showClearApprovalModal: PropTypes.func,
showResetAccountConfirmationModal: PropTypes.func,
warning: PropTypes.string,
history: PropTypes.object,
@@ -276,6 +279,36 @@ export default class SettingsTab extends PureComponent {
)
}
+ renderClearApproval () {
+ const { t } = this.context
+ const { showClearApprovalModal } = this.props
+ return (
+ <div className="settings-page__content-row">
+ <div className="settings-page__content-item">
+ <span>{ t('approvalData') }</span>
+ <span className="settings-page__content-description">
+ { t('approvalDataDescription') }
+ </span>
+ </div>
+ <div className="settings-page__content-item">
+ <div className="settings-page__content-item-col">
+ <Button
+ type="secondary"
+ large
+ className="settings-tab__button--orange"
+ onClick={event => {
+ event.preventDefault()
+ showClearApprovalModal()
+ }}
+ >
+ { t('clearApprovalData') }
+ </Button>
+ </div>
+ </div>
+ </div>
+ )
+ }
+
renderSeedWords () {
const { t } = this.context
const { history } = this.props
@@ -461,6 +494,32 @@ export default class SettingsTab extends PureComponent {
)
}
+ renderPrivacyOptIn () {
+ const { t } = this.context
+ const { privacyMode, setPrivacyMode } = this.props
+
+ return (
+ <div className="settings-page__content-row">
+ <div className="settings-page__content-item">
+ <span>{ t('privacyMode') }</span>
+ <div className="settings-page__content-description">
+ { t('privacyModeDescription') }
+ </div>
+ </div>
+ <div className="settings-page__content-item">
+ <div className="settings-page__content-item-col">
+ <ToggleButton
+ value={privacyMode}
+ onToggle={value => setPrivacyMode(!value)}
+ activeLabel=""
+ inactiveLabel=""
+ />
+ </div>
+ </div>
+ </div>
+ )
+ }
+
render () {
const { warning, isMascara } = this.props
@@ -475,8 +534,10 @@ export default class SettingsTab extends PureComponent {
{ this.renderSeedWords() }
{ !isMascara && this.renderOldUI() }
{ this.renderResetAccount() }
- { this.renderBlockieOptIn() }
+ { this.renderClearApproval() }
+ { this.renderPrivacyOptIn() }
{ this.renderHexDataOptIn() }
+ { this.renderBlockieOptIn() }
</div>
)
}
diff --git a/ui/app/components/pages/settings/settings-tab/settings-tab.container.js b/ui/app/components/pages/settings/settings-tab/settings-tab.container.js
index f4110207e..b6c33a5b2 100644
--- a/ui/app/components/pages/settings/settings-tab/settings-tab.container.js
+++ b/ui/app/components/pages/settings/settings-tab/settings-tab.container.js
@@ -22,7 +22,10 @@ const mapStateToProps = state => {
conversionDate,
nativeCurrency,
useBlockie,
- featureFlags: { sendHexData } = {},
+ featureFlags: {
+ sendHexData,
+ privacyMode,
+ } = {},
provider = {},
isMascara,
currentLocale,
@@ -38,6 +41,7 @@ const mapStateToProps = state => {
nativeCurrency,
useBlockie,
sendHexData,
+ privacyMode,
provider,
useNativeCurrencyAsPrimaryCurrency,
}
@@ -55,10 +59,12 @@ const mapDispatchToProps = dispatch => {
return dispatch(setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL'))
},
setHexDataFeatureFlag: shouldShow => dispatch(setFeatureFlag('sendHexData', shouldShow)),
+ setPrivacyMode: enabled => dispatch(setFeatureFlag('privacyMode', enabled)),
showResetAccountConfirmationModal: () => dispatch(showModal({ name: 'CONFIRM_RESET_ACCOUNT' })),
setUseNativeCurrencyAsPrimaryCurrencyPreference: value => {
return dispatch(setUseNativeCurrencyAsPrimaryCurrencyPreference(value))
},
+ showClearApprovalModal: () => dispatch(showModal({ name: 'CLEAR_APPROVED_ORIGINS' })),
}
}
diff --git a/ui/app/components/provider-page-container/index.js b/ui/app/components/provider-page-container/index.js
new file mode 100644
index 000000000..927c35940
--- /dev/null
+++ b/ui/app/components/provider-page-container/index.js
@@ -0,0 +1,3 @@
+export {default} from './provider-page-container.component'
+export {default as ProviderPageContainerContent} from './provider-page-container-content'
+export {default as ProviderPageContainerHeader} from './provider-page-container-header'
diff --git a/ui/app/components/provider-page-container/index.scss b/ui/app/components/provider-page-container/index.scss
new file mode 100644
index 000000000..8d35ac179
--- /dev/null
+++ b/ui/app/components/provider-page-container/index.scss
@@ -0,0 +1,121 @@
+.provider-approval-container {
+ display: flex;
+
+ &__header {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ border-bottom: 1px solid $geyser;
+ padding: 9px;
+ }
+
+ &__content {
+ display: flex;
+ overflow-y: auto;
+ flex: 1;
+ flex-direction: column;
+ justify-content: space-between;
+ color: #7C808E;
+
+ h1, h2 {
+ color: #4A4A4A;
+ display: flex;
+ justify-content: center;
+ text-align: center;
+ }
+
+ h2 {
+ font-size: 16px;
+ line-height: 18px;
+ padding: 20px;
+ }
+
+ h1 {
+ font-size: 22px;
+ line-height: 26px;
+ padding: 20px;
+ }
+
+ p {
+ padding: 0 40px;
+ text-align: center;
+ font-size: 12px;
+ line-height: 18px;
+ }
+
+ a, a:hover {
+ color: $dodger-blue;
+ }
+
+ .provider-approval-visual {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-evenly;
+ position: relative;
+ margin: 0 32px;
+
+ section {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ flex: 1;
+ }
+
+ h1 {
+ font-size: 14px;
+ line-height: 18px;
+ padding: 8px 0 0;
+ }
+
+ h2 {
+ font-size: 10px;
+ line-height: 14px;
+ padding: 0;
+ color: #A2A4AC;
+ }
+
+ &__check {
+ width: 40px;
+ height: 40px;
+ background: white url("/images/provider-approval-check.svg") no-repeat;
+ margin-top: 14px;
+ }
+
+ &__identicon {
+ width: 64px;
+ height: 64px;
+
+ &--default {
+ background-color: #777A87;
+ color: white;
+ width: 64px;
+ height: 64px;
+ border-radius: 32px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-weight: bold;
+ }
+ }
+
+ &:before {
+ border-top: 2px dashed #CDD1E4;
+ content: "";
+ margin: 0 auto;
+ position: absolute;
+ top: 32px;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ width: 65%;
+ z-index: -1;
+ }
+ }
+
+ .secure-badge {
+ display: flex;
+ justify-content: center;
+ padding: 25px;
+ }
+ }
+}
diff --git a/ui/app/components/provider-page-container/provider-page-container-content/index.js b/ui/app/components/provider-page-container/provider-page-container-content/index.js
new file mode 100644
index 000000000..73e491adc
--- /dev/null
+++ b/ui/app/components/provider-page-container/provider-page-container-content/index.js
@@ -0,0 +1 @@
+export {default} from './provider-page-container-content.container'
diff --git a/ui/app/components/provider-page-container/provider-page-container-content/provider-page-container-content.component.js b/ui/app/components/provider-page-container/provider-page-container-content/provider-page-container-content.component.js
new file mode 100644
index 000000000..268db613f
--- /dev/null
+++ b/ui/app/components/provider-page-container/provider-page-container-content/provider-page-container-content.component.js
@@ -0,0 +1,77 @@
+import PropTypes from 'prop-types'
+import React, {PureComponent} from 'react'
+import Identicon from '../../identicon'
+
+export default class ProviderPageContainerContent extends PureComponent {
+ static propTypes = {
+ origin: PropTypes.string.isRequired,
+ selectedIdentity: PropTypes.string.isRequired,
+ siteImage: PropTypes.string,
+ siteTitle: PropTypes.string.isRequired,
+ }
+
+ static contextTypes = {
+ t: PropTypes.func,
+ };
+
+ renderConnectVisual = () => {
+ const { origin, selectedIdentity, siteImage, siteTitle } = this.props
+
+ return (
+ <div className="provider-approval-visual">
+ <section>
+ {siteImage ? (
+ <img
+ className="provider-approval-visual__identicon"
+ src={siteImage}
+ />
+ ) : (
+ <i className="provider-approval-visual__identicon--default">
+ {siteTitle.charAt(0).toUpperCase()}
+ </i>
+ )}
+ <h1>{siteTitle}</h1>
+ <h2>{origin}</h2>
+ </section>
+ <span className="provider-approval-visual__check" />
+ <section>
+ <Identicon
+ className="provider-approval-visual__identicon"
+ address={selectedIdentity.address}
+ diameter={64}
+ />
+ <h1>{selectedIdentity.name}</h1>
+ </section>
+ </div>
+ )
+ }
+
+ render () {
+ const { siteTitle } = this.props
+ const { t } = this.context
+
+ return (
+ <div className="provider-approval-container__content">
+ <section>
+ <h2>{t('connectRequest')}</h2>
+ {this.renderConnectVisual()}
+ <h1>{t('providerRequest', [siteTitle])}</h1>
+ <p>
+ {t('providerRequestInfo')}
+ <br/>
+ <a
+ href="https://medium.com/metamask/introducing-privacy-mode-42549d4870fa"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ {t('learnMore')}.
+ </a>
+ </p>
+ </section>
+ <section className="secure-badge">
+ <img src="/images/mm-secure.svg" />
+ </section>
+ </div>
+ )
+ }
+}
diff --git a/ui/app/components/provider-page-container/provider-page-container-content/provider-page-container-content.container.js b/ui/app/components/provider-page-container/provider-page-container-content/provider-page-container-content.container.js
new file mode 100644
index 000000000..3ea1ce20e
--- /dev/null
+++ b/ui/app/components/provider-page-container/provider-page-container-content/provider-page-container-content.container.js
@@ -0,0 +1,11 @@
+import { connect } from 'react-redux'
+import ProviderPageContainerContent from './provider-page-container-content.component'
+import { getSelectedIdentity } from '../../../selectors'
+
+const mapStateToProps = (state) => {
+ return {
+ selectedIdentity: getSelectedIdentity(state),
+ }
+}
+
+export default connect(mapStateToProps)(ProviderPageContainerContent)
diff --git a/ui/app/components/provider-page-container/provider-page-container-header/index.js b/ui/app/components/provider-page-container/provider-page-container-header/index.js
new file mode 100644
index 000000000..430627d3a
--- /dev/null
+++ b/ui/app/components/provider-page-container/provider-page-container-header/index.js
@@ -0,0 +1 @@
+export {default} from './provider-page-container-header.component'
diff --git a/ui/app/components/provider-page-container/provider-page-container-header/provider-page-container-header.component.js b/ui/app/components/provider-page-container/provider-page-container-header/provider-page-container-header.component.js
new file mode 100644
index 000000000..41bf6c3dd
--- /dev/null
+++ b/ui/app/components/provider-page-container/provider-page-container-header/provider-page-container-header.component.js
@@ -0,0 +1,12 @@
+import React, {PureComponent} from 'react'
+import NetworkDisplay from '../../network-display'
+
+export default class ProviderPageContainerHeader extends PureComponent {
+ render () {
+ return (
+ <div className="provider-approval-container__header">
+ <NetworkDisplay colored={false} />
+ </div>
+ )
+ }
+}
diff --git a/ui/app/components/provider-page-container/provider-page-container.component.js b/ui/app/components/provider-page-container/provider-page-container.component.js
new file mode 100644
index 000000000..902733616
--- /dev/null
+++ b/ui/app/components/provider-page-container/provider-page-container.component.js
@@ -0,0 +1,50 @@
+import PropTypes from 'prop-types'
+import React, {PureComponent} from 'react'
+import { ProviderPageContainerContent, ProviderPageContainerHeader } from './'
+import { PageContainerFooter } from '../page-container'
+
+export default class ProviderPageContainer extends PureComponent {
+ static propTypes = {
+ approveProviderRequest: PropTypes.func.isRequired,
+ origin: PropTypes.string.isRequired,
+ rejectProviderRequest: PropTypes.func.isRequired,
+ siteImage: PropTypes.string,
+ siteTitle: PropTypes.string.isRequired,
+ };
+
+ static contextTypes = {
+ t: PropTypes.func,
+ };
+
+ onCancel = () => {
+ const { origin, rejectProviderRequest } = this.props
+ rejectProviderRequest(origin)
+ }
+
+ onSubmit = () => {
+ const { approveProviderRequest, origin } = this.props
+ approveProviderRequest(origin)
+ }
+
+ render () {
+ const {origin, siteImage, siteTitle} = this.props
+
+ return (
+ <div className="page-container provider-approval-container">
+ <ProviderPageContainerHeader />
+ <ProviderPageContainerContent
+ origin={origin}
+ siteImage={siteImage}
+ siteTitle={siteTitle}
+ />
+ <PageContainerFooter
+ onCancel={() => this.onCancel()}
+ cancelText={this.context.t('cancel')}
+ onSubmit={() => this.onSubmit()}
+ submitText={this.context.t('connect')}
+ submitButtonType="confirm"
+ />
+ </div>
+ )
+ }
+}
diff --git a/ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js b/ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js
index ceb620941..80518977e 100644
--- a/ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js
+++ b/ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js
@@ -11,11 +11,11 @@ export default class AmountMaxButton extends Component {
setAmountToMax: PropTypes.func,
setMaxModeTo: PropTypes.func,
tokenBalance: PropTypes.string,
- };
+ }
static contextTypes = {
t: PropTypes.func,
- };
+ }
setMaxAmount () {
const {
diff --git a/ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js b/ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js
index b490a7fd7..27181d2f5 100644
--- a/ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js
+++ b/ui/app/components/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js
@@ -5,16 +5,23 @@ const {
const ethUtil = require('ethereumjs-util')
function calcMaxAmount ({ balance, gasTotal, selectedToken, tokenBalance }) {
- const { decimals } = selectedToken || {}
- const multiplier = Math.pow(10, Number(decimals || 0))
+ const { decimals } = selectedToken || {}
+ const multiplier = Math.pow(10, Number(decimals || 0))
- return selectedToken
- ? multiplyCurrencies(tokenBalance, multiplier, {toNumericBase: 'hex'})
- : subtractCurrencies(
- ethUtil.addHexPrefix(balance),
- ethUtil.addHexPrefix(gasTotal),
- { toNumericBase: 'hex' }
- )
+ return selectedToken
+ ? multiplyCurrencies(
+ tokenBalance,
+ multiplier,
+ {
+ toNumericBase: 'hex',
+ multiplicandBase: 16,
+ }
+ )
+ : subtractCurrencies(
+ ethUtil.addHexPrefix(balance),
+ ethUtil.addHexPrefix(gasTotal),
+ { toNumericBase: 'hex' }
+ )
}
module.exports = {
diff --git a/ui/app/components/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js b/ui/app/components/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js
index 816df6a12..1ee858f67 100644
--- a/ui/app/components/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js
+++ b/ui/app/components/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js
@@ -19,7 +19,7 @@ describe('amount-max-button utils', () => {
selectedToken: {
decimals: 10,
},
- tokenBalance: 100,
+ tokenBalance: '64',
}), 'e8d4a51000')
})
})
diff --git a/ui/app/components/send/send-content/send-amount-row/send-amount-row.component.js b/ui/app/components/send/send-content/send-amount-row/send-amount-row.component.js
index 0268376bf..4df1e0ffa 100644
--- a/ui/app/components/send/send-content/send-amount-row/send-amount-row.component.js
+++ b/ui/app/components/send/send-content/send-amount-row/send-amount-row.component.js
@@ -26,11 +26,11 @@ export default class SendAmountRow extends Component {
updateSendAmount: PropTypes.func,
updateSendAmountError: PropTypes.func,
updateGas: PropTypes.func,
- };
+ }
static contextTypes = {
t: PropTypes.func,
- };
+ }
validateAmount (amount) {
const {
@@ -58,7 +58,6 @@ export default class SendAmountRow extends Component {
if (selectedToken) {
updateGasFeeError({
- amount,
amountConversionRate,
balance,
conversionRate,
diff --git a/ui/app/components/send/send-content/send-amount-row/send-amount-row.container.js b/ui/app/components/send/send-content/send-amount-row/send-amount-row.container.js
index 3504d1b73..2b6fe0f6c 100644
--- a/ui/app/components/send/send-content/send-amount-row/send-amount-row.container.js
+++ b/ui/app/components/send/send-content/send-amount-row/send-amount-row.container.js
@@ -45,10 +45,10 @@ function mapDispatchToProps (dispatch) {
setMaxModeTo: bool => dispatch(setMaxModeTo(bool)),
updateSendAmount: newAmount => dispatch(updateSendAmount(newAmount)),
updateGasFeeError: (amountDataObject) => {
- dispatch(updateSendErrors(getGasFeeErrorObject(amountDataObject)))
+ dispatch(updateSendErrors(getGasFeeErrorObject(amountDataObject)))
},
updateSendAmountError: (amountDataObject) => {
- dispatch(updateSendErrors(getAmountErrorObject(amountDataObject)))
+ dispatch(updateSendErrors(getAmountErrorObject(amountDataObject)))
},
}
}
diff --git a/ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js b/ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js
index 56e80cb83..14a71129f 100644
--- a/ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js
+++ b/ui/app/components/send/send-content/send-amount-row/tests/send-amount-row-component.test.js
@@ -82,7 +82,6 @@ describe('SendAmountRow Component', function () {
assert.deepEqual(
propsMethodSpies.updateGasFeeError.getCall(0).args,
[{
- amount: 'someAmount',
amountConversionRate: 'mockAmountConversionRate',
balance: 'mockBalance',
conversionRate: 7,
diff --git a/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.component.js b/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.component.js
index 4f43a9d61..d512f7d0b 100644
--- a/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.component.js
+++ b/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.component.js
@@ -12,11 +12,11 @@ export default class FromDropdown extends Component {
onSelect: PropTypes.func,
openDropdown: PropTypes.func,
selectedAccount: PropTypes.object,
- };
+ }
static contextTypes = {
t: PropTypes.func,
- };
+ }
render () {
const {
diff --git a/ui/app/components/send/send-content/send-from-row/send-from-row.component.js b/ui/app/components/send/send-content/send-from-row/send-from-row.component.js
index 3e0e0de22..b6de9d222 100644
--- a/ui/app/components/send/send-content/send-from-row/send-from-row.component.js
+++ b/ui/app/components/send/send-content/send-from-row/send-from-row.component.js
@@ -15,11 +15,11 @@ export default class SendFromRow extends Component {
tokenContract: PropTypes.object,
updateSendFrom: PropTypes.func,
setSendTokenBalance: PropTypes.func,
- };
+ }
static contextTypes = {
t: PropTypes.func,
- };
+ }
async handleFromChange (newFrom) {
const {
@@ -32,6 +32,7 @@ export default class SendFromRow extends Component {
const usersToken = await tokenContract.balanceOf(newFrom.address)
setSendTokenBalance(usersToken)
}
+
updateSendFrom(newFrom)
}
diff --git a/ui/app/components/send/send-content/send-from-row/send-from-row.container.js b/ui/app/components/send/send-content/send-from-row/send-from-row.container.js
index 33cb63b43..7008bbea4 100644
--- a/ui/app/components/send/send-content/send-from-row/send-from-row.container.js
+++ b/ui/app/components/send/send-content/send-from-row/send-from-row.container.js
@@ -10,8 +10,8 @@ import {
} from './send-from-row.selectors.js'
import { calcTokenBalance } from '../../send.utils.js'
import {
- updateSendFrom,
- setSendTokenBalance,
+ updateSendFrom,
+ setSendTokenBalance,
} from '../../../../actions'
import {
closeFromDropdown,
@@ -37,10 +37,10 @@ function mapDispatchToProps (dispatch) {
openFromDropdown: () => dispatch(openFromDropdown()),
updateSendFrom: newFrom => dispatch(updateSendFrom(newFrom)),
setSendTokenBalance: (usersToken, selectedToken) => {
- if (!usersToken) return
+ if (!usersToken) return
- const tokenBalance = calcTokenBalance({ usersToken, selectedToken })
- dispatch(setSendTokenBalance(tokenBalance))
+ const tokenBalance = calcTokenBalance({ usersToken, selectedToken })
+ dispatch(setSendTokenBalance(tokenBalance))
},
}
}
diff --git a/ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js b/ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js
index 91b58cfd0..6ad4499ff 100644
--- a/ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js
+++ b/ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js
@@ -12,11 +12,11 @@ export default class SendGasRow extends Component {
gasLoadingError: PropTypes.bool,
gasTotal: PropTypes.string,
showCustomizeGasModal: PropTypes.func,
- };
+ }
static contextTypes = {
t: PropTypes.func,
- };
+ }
render () {
const {
diff --git a/ui/app/components/send/send-content/send-gas-row/send-gas-row.container.js b/ui/app/components/send/send-content/send-gas-row/send-gas-row.container.js
index 8f8e3e4dd..e44fe4ef1 100644
--- a/ui/app/components/send/send-content/send-gas-row/send-gas-row.container.js
+++ b/ui/app/components/send/send-content/send-gas-row/send-gas-row.container.js
@@ -1,8 +1,8 @@
import { connect } from 'react-redux'
import {
- getConversionRate,
- getCurrentCurrency,
- getGasTotal,
+ getConversionRate,
+ getCurrentCurrency,
+ getGasTotal,
} from '../../send.selectors.js'
import { getGasLoadingError, gasFeeIsInError } from './send-gas-row.selectors.js'
import { showModal } from '../../../../actions'
diff --git a/ui/app/components/send/send-content/send-to-row/send-to-row.component.js b/ui/app/components/send/send-content/send-to-row/send-to-row.component.js
index 17c75c817..ce5325314 100644
--- a/ui/app/components/send/send-content/send-to-row/send-to-row.component.js
+++ b/ui/app/components/send/send-content/send-to-row/send-to-row.component.js
@@ -19,11 +19,11 @@ export default class SendToRow extends Component {
updateSendTo: PropTypes.func,
updateSendToError: PropTypes.func,
scanQrCode: PropTypes.func,
- };
+ }
static contextTypes = {
t: PropTypes.func,
- };
+ }
handleToChange (to, nickname = '', toError) {
const { hasHexData, updateSendTo, updateSendToError, updateGas } = this.props
diff --git a/ui/app/components/send/send-footer/send-footer.component.js b/ui/app/components/send/send-footer/send-footer.component.js
index 230bf450f..b78b56373 100644
--- a/ui/app/components/send/send-footer/send-footer.component.js
+++ b/ui/app/components/send/send-footer/send-footer.component.js
@@ -26,11 +26,11 @@ export default class SendFooter extends Component {
tokenBalance: PropTypes.string,
unapprovedTxs: PropTypes.object,
update: PropTypes.func,
- };
+ }
static contextTypes = {
t: PropTypes.func,
- };
+ }
onCancel () {
this.props.clearSend()
diff --git a/ui/app/components/send/send.component.js b/ui/app/components/send/send.component.js
index fb7beca16..a27401f30 100644
--- a/ui/app/components/send/send.component.js
+++ b/ui/app/components/send/send.component.js
@@ -41,11 +41,11 @@ export default class SendTransactionScreen extends PersistentForm {
scanQrCode: PropTypes.func,
qrCodeDetected: PropTypes.func,
qrCodeData: PropTypes.object,
- };
+ }
static contextTypes = {
t: PropTypes.func,
- };
+ }
componentWillReceiveProps (nextProps) {
if (nextProps.qrCodeData) {
@@ -138,14 +138,12 @@ export default class SendTransactionScreen extends PersistentForm {
})
const gasFeeErrorObject = selectedToken
? getGasFeeErrorObject({
- amount,
amountConversionRate,
balance,
conversionRate,
gasTotal,
primaryCurrency,
selectedToken,
- tokenBalance,
})
: { gasFee: null }
updateSendErrors(Object.assign(amountErrorObject, gasFeeErrorObject))
diff --git a/ui/app/components/send/send.utils.js b/ui/app/components/send/send.utils.js
index eb1667c63..b2ac41e9c 100644
--- a/ui/app/components/send/send.utils.js
+++ b/ui/app/components/send/send.utils.js
@@ -89,11 +89,10 @@ function isTokenBalanceSufficient ({
const tokenBalanceIsSufficient = conversionGTE(
{
value: tokenBalance,
- fromNumericBase: 'dec',
+ fromNumericBase: 'hex',
},
{
value: calcTokenAmount(amountInDec, decimals),
- fromNumericBase: 'dec',
},
)
@@ -151,7 +150,6 @@ function getAmountErrorObject ({
}
function getGasFeeErrorObject ({
- amount,
amountConversionRate,
balance,
conversionRate,
@@ -180,7 +178,7 @@ function getGasFeeErrorObject ({
function calcTokenBalance ({ selectedToken, usersToken }) {
const { decimals } = selectedToken || {}
- return calcTokenAmount(usersToken.balance.toString(), decimals) + ''
+ return calcTokenAmount(usersToken.balance.toString(), decimals).toString(16)
}
function doesAmountErrorRequireUpdate ({
diff --git a/ui/app/components/send/tests/send-component.test.js b/ui/app/components/send/tests/send-component.test.js
index f4943e707..bd136a0b8 100644
--- a/ui/app/components/send/tests/send-component.test.js
+++ b/ui/app/components/send/tests/send-component.test.js
@@ -158,14 +158,12 @@ describe('Send Component', function () {
assert.deepEqual(
utilsMethodStubs.getGasFeeErrorObject.getCall(0).args[0],
{
- amount: 'mockAmount',
amountConversionRate: 'mockAmountConversionRate',
balance: 'mockBalance',
conversionRate: 10,
gasTotal: 'mockGasTotal',
primaryCurrency: 'mockPrimaryCurrency',
selectedToken: 'mockSelectedToken',
- tokenBalance: 'mockTokenBalance',
}
)
})
diff --git a/ui/app/components/send/tests/send-utils.test.js b/ui/app/components/send/tests/send-utils.test.js
index b72d87eee..f31e1221b 100644
--- a/ui/app/components/send/tests/send-utils.test.js
+++ b/ui/app/components/send/tests/send-utils.test.js
@@ -285,11 +285,10 @@ describe('send utils', () => {
[
{
value: 123,
- fromNumericBase: 'dec',
+ fromNumericBase: 'hex',
},
{
value: 'calc:1610',
- fromNumericBase: 'dec',
},
]
)
diff --git a/ui/app/components/token-balance/index.scss b/ui/app/components/token-balance/index.scss
new file mode 100644
index 000000000..2ff6dfbc8
--- /dev/null
+++ b/ui/app/components/token-balance/index.scss
@@ -0,0 +1,14 @@
+.token-balance-component {
+ display: flex;
+ align-items: center;
+
+ &__text {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ &__suffix {
+ padding-left: 4px;
+ }
+}
diff --git a/ui/app/components/token-balance/token-balance.component.js b/ui/app/components/token-balance/token-balance.component.js
index 2b4f73980..af1a32578 100644
--- a/ui/app/components/token-balance/token-balance.component.js
+++ b/ui/app/components/token-balance/token-balance.component.js
@@ -1,6 +1,6 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
-import classnames from 'classnames'
+import CurrencyDisplay from '../currency-display'
export default class TokenBalance extends PureComponent {
static propTypes = {
@@ -12,12 +12,14 @@ export default class TokenBalance extends PureComponent {
}
render () {
- const { className, string, withSymbol, symbol } = this.props
+ const { className, string, symbol } = this.props
return (
- <div className={classnames('hide-text-overflow', className)}>
- { string + (withSymbol ? ` ${symbol}` : '') }
- </div>
+ <CurrencyDisplay
+ className={className}
+ displayValue={string}
+ suffix={symbol}
+ />
)
}
}
diff --git a/ui/app/components/token-currency-display/token-currency-display.component.js b/ui/app/components/token-currency-display/token-currency-display.component.js
index 4bb09a4b6..6e9a65300 100644
--- a/ui/app/components/token-currency-display/token-currency-display.component.js
+++ b/ui/app/components/token-currency-display/token-currency-display.component.js
@@ -1,6 +1,6 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
-import CurrencyDisplay from '../currency-display/currency-display.component'
+import CurrencyDisplay from '../currency-display'
import { getTokenData } from '../../helpers/transactions.util'
import { getTokenValue, calcTokenAmount } from '../../token-util'
@@ -12,6 +12,7 @@ export default class TokenCurrencyDisplay extends PureComponent {
state = {
displayValue: '',
+ suffix: '',
}
componentDidMount () {
@@ -29,25 +30,27 @@ export default class TokenCurrencyDisplay extends PureComponent {
setDisplayValue () {
const { transactionData: data, token } = this.props
- const { decimals = '', symbol = '' } = token
+ const { decimals = '', symbol: suffix = '' } = token
const tokenData = getTokenData(data)
let displayValue
if (tokenData.params && tokenData.params.length) {
const tokenValue = getTokenValue(tokenData.params)
- const tokenAmount = calcTokenAmount(tokenValue, decimals)
- displayValue = `${tokenAmount} ${symbol}`
+ displayValue = calcTokenAmount(tokenValue, decimals).toString()
}
- this.setState({ displayValue })
+ this.setState({ displayValue, suffix })
}
render () {
+ const { displayValue, suffix } = this.state
+
return (
<CurrencyDisplay
{...this.props}
- displayValue={this.state.displayValue}
+ displayValue={displayValue}
+ suffix={suffix}
/>
)
}
diff --git a/ui/app/components/token-input/token-input.component.js b/ui/app/components/token-input/token-input.component.js
index d1388945b..10fa1151e 100644
--- a/ui/app/components/token-input/token-input.component.js
+++ b/ui/app/components/token-input/token-input.component.js
@@ -32,7 +32,7 @@ export default class TokenInput extends PureComponent {
super(props)
const { value: hexValue } = props
- const decimalValue = hexValue ? this.getDecimalValue(props) : 0
+ const decimalValue = hexValue ? this.getValue(props) : 0
this.state = {
decimalValue,
@@ -46,12 +46,12 @@ export default class TokenInput extends PureComponent {
const { hexValue: stateHexValue } = this.state
if (prevPropsHexValue !== propsHexValue && propsHexValue !== stateHexValue) {
- const decimalValue = this.getDecimalValue(this.props)
+ const decimalValue = this.getValue(this.props)
this.setState({ hexValue: propsHexValue, decimalValue })
}
}
- getDecimalValue (props) {
+ getValue (props) {
const { value: hexValue, selectedToken: { decimals, symbol } = {} } = props
const multiplier = Math.pow(10, Number(decimals || 0))
@@ -63,7 +63,7 @@ export default class TokenInput extends PureComponent {
invertConversionRate: true,
})
- return Number(decimalValueString) || 0
+ return Number(decimalValueString) ? decimalValueString : ''
}
handleChange = decimalValue => {
diff --git a/ui/app/components/transaction-list-item/index.scss b/ui/app/components/transaction-list-item/index.scss
index ac0e7beeb..449974734 100644
--- a/ui/app/components/transaction-list-item/index.scss
+++ b/ui/app/components/transaction-list-item/index.scss
@@ -80,6 +80,8 @@
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
+ min-width: 0;
+ max-width: 100%;
&--primary {
text-align: end;
diff --git a/ui/app/components/transaction-status/tests/transaction-status.component.test.js b/ui/app/components/transaction-status/tests/transaction-status.component.test.js
new file mode 100644
index 000000000..9e3bffe4f
--- /dev/null
+++ b/ui/app/components/transaction-status/tests/transaction-status.component.test.js
@@ -0,0 +1,35 @@
+import React from 'react'
+import assert from 'assert'
+import { mount } from 'enzyme'
+import TransactionStatus from '../transaction-status.component'
+import Tooltip from '../../tooltip-v2'
+
+describe('TransactionStatus Component', () => {
+ it('should render APPROVED properly', () => {
+ const wrapper = mount(
+ <TransactionStatus
+ statusKey="approved"
+ title="test-title"
+ />,
+ { context: { t: str => str.toUpperCase() } }
+ )
+
+ assert.ok(wrapper)
+ const tooltipProps = wrapper.find(Tooltip).props()
+ assert.equal(tooltipProps.children, 'APPROVED')
+ assert.equal(tooltipProps.title, 'test-title')
+ })
+
+ it('should render SUBMITTED properly', () => {
+ const wrapper = mount(
+ <TransactionStatus
+ statusKey="submitted"
+ />,
+ { context: { t: str => str.toUpperCase() } }
+ )
+
+ assert.ok(wrapper)
+ const tooltipProps = wrapper.find(Tooltip).props()
+ assert.equal(tooltipProps.children, 'PENDING')
+ })
+})
diff --git a/ui/app/components/transaction-status/transaction-status.component.js b/ui/app/components/transaction-status/transaction-status.component.js
index c22baf18a..0d47d7868 100644
--- a/ui/app/components/transaction-status/transaction-status.component.js
+++ b/ui/app/components/transaction-status/transaction-status.component.js
@@ -25,7 +25,6 @@ const statusToClassNameHash = {
}
const statusToTextHash = {
- [APPROVED_STATUS]: 'pending',
[SUBMITTED_STATUS]: 'pending',
}
diff --git a/ui/app/components/transaction-view-balance/index.scss b/ui/app/components/transaction-view-balance/index.scss
index 659f896ff..43e87459b 100644
--- a/ui/app/components/transaction-view-balance/index.scss
+++ b/ui/app/components/transaction-view-balance/index.scss
@@ -6,6 +6,12 @@
height: 54px;
min-width: 0;
+ @media screen and (max-width: $break-small) {
+ flex-direction: column;
+ height: initial;
+ width: 100%;
+ }
+
&__balance {
margin: 0 12px;
display: flex;
@@ -15,17 +21,8 @@
@media screen and (max-width: $break-small) {
align-items: center;
margin: 16px 0;
- }
- }
-
- &__token-balance {
- margin-left: 12px;
- font-size: 1.5rem;
-
- @media screen and (max-width: $break-small) {
- margin: 12px 0;
- margin-left: 0;
- font-size: 1.75rem;
+ padding: 0 16px;
+ max-width: 100%;
}
}
@@ -34,6 +31,7 @@
@media screen and (max-width: $break-small) {
font-size: 1.75rem;
+ width: 100%;
}
}
@@ -51,6 +49,7 @@
@media screen and (max-width: $break-small) {
flex-direction: column;
+ width: 100%;
}
}
@@ -71,9 +70,4 @@
margin-right: 12px;
}
}
-
- @media screen and (max-width: $break-small) {
- flex-direction: column;
- height: initial
- }
}
diff --git a/ui/app/components/transaction-view-balance/transaction-view-balance.component.js b/ui/app/components/transaction-view-balance/transaction-view-balance.component.js
index 273845c47..a24b97478 100644
--- a/ui/app/components/transaction-view-balance/transaction-view-balance.component.js
+++ b/ui/app/components/transaction-view-balance/transaction-view-balance.component.js
@@ -26,24 +26,26 @@ export default class TransactionViewBalance extends PureComponent {
return selectedToken
? (
- <TokenBalance
- token={selectedToken}
- withSymbol
- className="transaction-view-balance__token-balance"
- />
+ <div className="transaction-view-balance__balance">
+ <TokenBalance
+ token={selectedToken}
+ withSymbol
+ className="transaction-view-balance__primary-balance"
+ />
+ </div>
) : (
<div className="transaction-view-balance__balance">
<UserPreferencedCurrencyDisplay
className="transaction-view-balance__primary-balance"
value={balance}
type={PRIMARY}
- ethNumberOfDecimals={3}
+ ethNumberOfDecimals={4}
/>
<UserPreferencedCurrencyDisplay
className="transaction-view-balance__secondary-balance"
value={balance}
type={SECONDARY}
- ethNumberOfDecimals={3}
+ ethNumberOfDecimals={4}
/>
</div>
)
diff --git a/ui/app/components/unit-input/index.scss b/ui/app/components/unit-input/index.scss
index 28c5bf6f0..7995696aa 100644
--- a/ui/app/components/unit-input/index.scss
+++ b/ui/app/components/unit-input/index.scss
@@ -38,6 +38,10 @@
align-items: center;
}
+ &__suffix {
+ margin-left: 3px;
+ }
+
&--error {
border-color: $red;
}
diff --git a/ui/app/components/unit-input/unit-input.component.js b/ui/app/components/unit-input/unit-input.component.js
index f1ebf4d77..0c6b21797 100644
--- a/ui/app/components/unit-input/unit-input.component.js
+++ b/ui/app/components/unit-input/unit-input.component.js
@@ -66,7 +66,7 @@ export default class UnitInput extends PureComponent {
const valueString = String(value)
const valueLength = valueString.length || 1
const decimalPointDeficit = valueString.match(/\./) ? -0.5 : 0
- return (valueLength + decimalPointDeficit + 0.75) + 'ch'
+ return (valueLength + decimalPointDeficit + 0.5) + 'ch'
}
render () {
diff --git a/ui/app/conversion-util.js b/ui/app/conversion-util.js
index f271b5683..8cc531773 100644
--- a/ui/app/conversion-util.js
+++ b/ui/app/conversion-util.js
@@ -62,7 +62,7 @@ const toSpecifiedDenomination = {
}
const baseChange = {
hex: n => n.toString(16),
- dec: n => Number(n).toString(10),
+ dec: n => (new BigNumber(n)).toString(10),
BN: n => new BN(n.toString(16)),
}
diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss
index e4c7a4e0d..7bfa2d443 100644
--- a/ui/app/css/itcss/components/new-account.scss
+++ b/ui/app/css/itcss/components/new-account.scss
@@ -3,6 +3,7 @@
background-color: #FFFFFF;
box-shadow: 0 0 7px 0 rgba(0,0,0,0.08);
z-index: 25;
+ height: 100%;
&__header {
display: flex;
@@ -186,22 +187,8 @@
}
&__connect-btn {
- background-color: #259De5;
- color: #fff;
- border: none;
width: 315px;
- min-height: 54px;
- font-weight: 300;
- font-size: 14px;
- margin-bottom: 20px;
- margin-top: 20px;
- border-radius: 5px;
- display: flex;
- flex: 1;
- margin-left: 20px;
- margin-right: 20px;
- justify-content: center;
- text-transform: uppercase;
+ margin: 20px;
}
&__connect-btn.disabled {
@@ -449,6 +436,7 @@
margin-top: 10px;
&__button {
+ background: #fff;
height: 19px;
display: flex;
color: #33a4e7;
@@ -489,29 +477,8 @@
justify-content: space-between;
}
- &__button {
- width: 150px;
- min-width: initial;
- }
-
- .btn-primary {
- background-color: #259DE5;
- color: #FFFFFF;
- border: none;
- width: 100%;
- min-height: 54px;
- font-weight: 300;
- font-size: 14px;
- margin-bottom: 20px
- }
-
- &__button.unlock {
- width: 50%;
- }
-
- &__button.btn-primary--disabled {
- cursor: not-allowed;
- opacity: .5;
+ &__button:not(:last-child) {
+ margin-right: 16px;
}
}
diff --git a/ui/app/css/itcss/components/pages/index.scss b/ui/app/css/itcss/components/pages/index.scss
index 709f8baf6..45e47f447 100644
--- a/ui/app/css/itcss/components/pages/index.scss
+++ b/ui/app/css/itcss/components/pages/index.scss
@@ -1 +1,3 @@
@import './reveal-seed.scss';
+
+@import './provider-approval.scss';
diff --git a/ui/app/css/itcss/components/pages/provider-approval.scss b/ui/app/css/itcss/components/pages/provider-approval.scss
new file mode 100644
index 000000000..f172165ab
--- /dev/null
+++ b/ui/app/css/itcss/components/pages/provider-approval.scss
@@ -0,0 +1,11 @@
+.provider_approval_content {
+ height: auto;
+ overflow: auto;
+ padding: 16px;
+}
+
+.provider_approval_origin {
+ font-weight: 999;
+ margin-top: 16px;
+ word-wrap: break-word;
+}
diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss
index a57653b45..c791a24c7 100644
--- a/ui/app/css/itcss/components/send.scss
+++ b/ui/app/css/itcss/components/send.scss
@@ -552,6 +552,7 @@
&__form-field {
flex: 1 1 auto;
+ min-width: 0;
.currency-display {
color: $tundora;
@@ -580,6 +581,7 @@
line-height: 22px;
width: 88px;
font-weight: 400;
+ flex: 0 0 auto;
}
&__from-dropdown {
diff --git a/ui/app/ducks/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction.duck.js
index 275eb1551..e228d2d39 100644
--- a/ui/app/ducks/confirm-transaction.duck.js
+++ b/ui/app/ducks/confirm-transaction.duck.js
@@ -370,11 +370,16 @@ export function setTransactionToConfirm (transactionId) {
dispatch(setFetchingData(true))
const methodData = await getMethodData(data)
dispatch(updateMethodData(methodData))
+ } catch (error) {
+ dispatch(updateMethodData({}))
+ dispatch(setFetchingData(false))
+ }
+
+ try {
const toSmartContract = await isSmartContractAddress(to)
dispatch(updateToSmartContract(toSmartContract))
dispatch(setFetchingData(false))
} catch (error) {
- dispatch(updateMethodData({}))
dispatch(setFetchingData(false))
}
diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js
index 22fa53098..302d1627a 100644
--- a/ui/app/reducers/metamask.js
+++ b/ui/app/reducers/metamask.js
@@ -33,7 +33,7 @@ function reduceMetamask (state, action) {
gasLimit: null,
gasPrice: null,
gasTotal: null,
- tokenBalance: null,
+ tokenBalance: '0x0',
from: '',
to: '',
amount: '0x0',
@@ -74,6 +74,7 @@ function reduceMetamask (state, action) {
case actions.CLEAR_NOTICES:
return extend(metamaskState, {
noActiveNotices: true,
+ nextUnreadNotice: undefined,
})
case actions.UPDATE_METAMASK_STATE:
@@ -294,8 +295,10 @@ function reduceMetamask (state, action) {
amount: '0x0',
memo: '',
errors: {},
+ maxModeOn: false,
editingTransactionId: null,
forceGasMin: null,
+ toNickname: '',
},
})
@@ -333,9 +336,9 @@ function reduceMetamask (state, action) {
})
case actions.SET_USE_BLOCKIE:
- return extend(metamaskState, {
- useBlockie: action.value,
- })
+ return extend(metamaskState, {
+ useBlockie: action.value,
+ })
case actions.UPDATE_FEATURE_FLAGS:
return extend(metamaskState, {
diff --git a/ui/app/select-app.js b/ui/app/select-app.js
index f2e8e8d10..f5f9e33ab 100644
--- a/ui/app/select-app.js
+++ b/ui/app/select-app.js
@@ -5,17 +5,14 @@ const h = require('react-hyperscript')
const { HashRouter } = require('react-router-dom')
const App = require('./app')
const OldApp = require('../../old-ui/app/app')
-const { autoAddToBetaUI } = require('./selectors')
+const { getShouldUseNewUi } = require('./selectors')
const { setFeatureFlag } = require('./actions')
const I18nProvider = require('./i18n-provider')
function mapStateToProps (state) {
return {
- betaUI: state.metamask.featureFlags.betaUI,
- autoAdd: autoAddToBetaUI(state),
- isUnlocked: state.metamask.isUnlocked,
isMascara: state.metamask.isMascara,
- firstTime: Object.keys(state.metamask.identities).length === 0,
+ shouldUseNewUi: getShouldUseNewUi(state),
}
}
@@ -56,17 +53,13 @@ SelectedApp.prototype.componentWillReceiveProps = function (nextProps) {
}
SelectedApp.prototype.render = function () {
- // Code commented out until we begin auto adding users to NewUI
- // const { betaUI, isMascara, firstTime } = this.props
- // const Selected = betaUI || isMascara || firstTime ? App : OldApp
-
- const { betaUI, isMascara } = this.props
-
- return betaUI || isMascara
- ? h(HashRouter, {
- hashType: 'noslash',
- }, [
- h(I18nProvider, [ h(App) ]),
- ])
- : h(OldApp)
+ const { shouldUseNewUi } = this.props
+ const newUi = h(HashRouter, {
+ hashType: 'noslash',
+ }, [
+ h(I18nProvider, [
+ h(App),
+ ]),
+ ])
+ return shouldUseNewUi ? newUi : h(OldApp)
}
diff --git a/ui/app/selectors.js b/ui/app/selectors.js
index 7209f19d1..b518527c9 100644
--- a/ui/app/selectors.js
+++ b/ui/app/selectors.js
@@ -31,6 +31,7 @@ const selectors = {
getSelectedTokenToFiatRate,
getSelectedTokenContract,
autoAddToBetaUI,
+ getShouldUseNewUi,
getSendMaxModeState,
getCurrentViewContext,
getTotalUnapprovedCount,
@@ -185,6 +186,13 @@ function autoAddToBetaUI (state) {
return userIsNotInBeta && userPassesThreshold
}
+function getShouldUseNewUi (state) {
+ const isAlreadyUsingBetaUi = state.metamask.featureFlags.betaUI
+ const isMascara = state.metamask.isMascara
+ const isFreshInstall = Object.keys(state.metamask.identities).length === 0
+ return isAlreadyUsingBetaUi || isMascara || isFreshInstall
+}
+
function getCurrentViewContext (state) {
const { currentView = {} } = state.appState
return currentView.context
diff --git a/ui/app/selectors/confirm-transaction.js b/ui/app/selectors/confirm-transaction.js
index 90924c036..23ef26d95 100644
--- a/ui/app/selectors/confirm-transaction.js
+++ b/ui/app/selectors/confirm-transaction.js
@@ -137,11 +137,12 @@ export const tokenAmountAndToAddressSelector = createSelector(
const valueParam = params.find(param => param.name === TOKEN_PARAM_VALUE)
toAddress = toParam ? toParam.value : params[0].value
const value = valueParam ? Number(valueParam.value) : Number(params[1].value)
- tokenAmount = roundExponential(value)
if (tokenDecimals) {
- tokenAmount = calcTokenAmount(value, tokenDecimals)
+ tokenAmount = calcTokenAmount(value, tokenDecimals).toNumber()
}
+
+ tokenAmount = roundExponential(tokenAmount)
}
return {
@@ -163,7 +164,7 @@ export const approveTokenAmountAndToAddressSelector = createSelector(
const value = Number(params.find(param => param.name === TOKEN_PARAM_VALUE).value)
if (tokenDecimals) {
- tokenAmount = calcTokenAmount(value, tokenDecimals)
+ tokenAmount = calcTokenAmount(value, tokenDecimals).toNumber()
}
tokenAmount = roundExponential(tokenAmount)
@@ -188,7 +189,7 @@ export const sendTokenTokenAmountAndToAddressSelector = createSelector(
let value = Number(params.find(param => param.name === TOKEN_PARAM_VALUE).value)
if (tokenDecimals) {
- value = calcTokenAmount(value, tokenDecimals)
+ value = calcTokenAmount(value, tokenDecimals).toNumber()
}
tokenAmount = roundExponential(value)
diff --git a/ui/app/token-util.js b/ui/app/token-util.js
index 6e4992763..35a19a69f 100644
--- a/ui/app/token-util.js
+++ b/ui/app/token-util.js
@@ -109,7 +109,7 @@ export function tokenInfoGetter () {
export function calcTokenAmount (value, decimals) {
const multiplier = Math.pow(10, Number(decimals || 0))
- return new BigNumber(String(value)).div(multiplier).toNumber()
+ return new BigNumber(String(value)).div(multiplier)
}
export function getTokenValue (tokenParams = []) {
diff --git a/ui/app/welcome-screen.js b/ui/app/welcome-screen.js
index 63512cd50..146661eb3 100644
--- a/ui/app/welcome-screen.js
+++ b/ui/app/welcome-screen.js
@@ -50,7 +50,7 @@ class WelcomeScreen extends Component {
height: '225',
}),
- h('div.welcome-screen__info__header', this.context.t('welcomeBeta')),
+ h('div.welcome-screen__info__header', this.context.t('welcome')),
h('div.welcome-screen__info__copy', this.context.t('metamaskDescription')),