From df8eb494fe0228b634f234070f443a5c37557cb8 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Fri, 24 Jul 2020 11:26:45 -0500 Subject: [PATCH 001/137] Updates Typography Variables and styles. (#9017) Co-authored-by: Mark Stacey --- .../add-to-addressbook-modal/index.scss | 2 +- .../app/modals/new-account-modal/index.scss | 2 +- .../app/permission-page-container/index.scss | 4 +- .../app/permissions-connect-footer/index.scss | 3 +- .../app/permissions-connect-header/index.scss | 4 +- ui/app/components/ui/button/buttons.scss | 7 +- ui/app/components/ui/list-item/index.scss | 2 +- ui/app/components/ui/popover/index.scss | 7 +- ui/app/css/itcss/components/modal.scss | 3 +- ui/app/css/itcss/settings/index.scss | 1 - ui/app/css/itcss/settings/typography.scss | 84 ----------- ui/app/css/itcss/settings/variables.scss | 69 ---------- ui/app/css/variables/index.scss | 1 + ui/app/css/variables/typography.scss | 130 ++++++++++++++++++ ui/app/pages/home/index.scss | 3 +- .../choose-account/index.scss | 13 +- ui/app/pages/permissions-connect/index.scss | 5 +- .../permissions-connect/redirect/index.scss | 2 +- ui/app/pages/send/send.scss | 8 +- 19 files changed, 159 insertions(+), 191 deletions(-) delete mode 100644 ui/app/css/itcss/settings/typography.scss create mode 100644 ui/app/css/variables/typography.scss diff --git a/ui/app/components/app/modals/add-to-addressbook-modal/index.scss b/ui/app/components/app/modals/add-to-addressbook-modal/index.scss index b5e3b9ae7738..64d0f733641d 100644 --- a/ui/app/components/app/modals/add-to-addressbook-modal/index.scss +++ b/ui/app/components/app/modals/add-to-addressbook-modal/index.scss @@ -9,7 +9,7 @@ border-bottom: 1px solid $Grey-100; &__header { - @extend %h3; + @extend %H3; } } diff --git a/ui/app/components/app/modals/new-account-modal/index.scss b/ui/app/components/app/modals/new-account-modal/index.scss index 31dfff92d58e..97d6210b80c4 100644 --- a/ui/app/components/app/modals/new-account-modal/index.scss +++ b/ui/app/components/app/modals/new-account-modal/index.scss @@ -9,7 +9,7 @@ border-bottom: 1px solid $Grey-100; &__header { - @extend %header--18; + @extend %H4; font-weight: bold; display: flex; diff --git a/ui/app/components/app/permission-page-container/index.scss b/ui/app/components/app/permission-page-container/index.scss index c26189e0c094..458eb5b703bd 100644 --- a/ui/app/components/app/permission-page-container/index.scss +++ b/ui/app/components/app/permission-page-container/index.scss @@ -31,7 +31,7 @@ } &__title { - @extend %header--18; + @extend %H4; line-height: 25px; text-align: center; @@ -84,7 +84,7 @@ } &__permissions-header { - @extend %content-text; + @extend %H6; line-height: 20px; color: #6a737d; diff --git a/ui/app/components/app/permissions-connect-footer/index.scss b/ui/app/components/app/permissions-connect-footer/index.scss index ac650841743e..229da218a389 100644 --- a/ui/app/components/app/permissions-connect-footer/index.scss +++ b/ui/app/components/app/permissions-connect-footer/index.scss @@ -5,9 +5,8 @@ align-items: center; &__text { - @extend %content-text; + @extend %H7; - font-size: 12px; line-height: 17px; color: #6a737d; display: flex; diff --git a/ui/app/components/app/permissions-connect-header/index.scss b/ui/app/components/app/permissions-connect-header/index.scss index 1b29ec3e0611..ca8d4c0e6c4f 100644 --- a/ui/app/components/app/permissions-connect-header/index.scss +++ b/ui/app/components/app/permissions-connect-header/index.scss @@ -26,7 +26,7 @@ } &__title { - @extend %header--24; + @extend %H3; text-align: center; color: $Black-100; @@ -35,7 +35,7 @@ &__text, &__subtitle { - @extend %content-text; + @extend %H6; text-align: center; color: $Grey-500; diff --git a/ui/app/components/ui/button/buttons.scss b/ui/app/components/ui/button/buttons.scss index 2fdc1da013e9..83f02f7e0ba8 100644 --- a/ui/app/components/ui/button/buttons.scss +++ b/ui/app/components/ui/button/buttons.scss @@ -11,7 +11,7 @@ $hover-orange: #ffd3b5; $warning-light-orange: #f8b588; %button { - @include h6; + @extend %H6; font-weight: 500; font-family: Roboto, Arial; @@ -34,7 +34,7 @@ $warning-light-orange: #f8b588; } %link { - @include h4; + @extend %H4; color: $Blue-500; line-height: 1.25rem; @@ -60,8 +60,7 @@ $warning-light-orange: #f8b588; %small-link { @extend %link; - - @include h6; + @extend %H6; } .button { diff --git a/ui/app/components/ui/list-item/index.scss b/ui/app/components/ui/list-item/index.scss index a26efcb4ca73..cc9edd87fe7e 100644 --- a/ui/app/components/ui/list-item/index.scss +++ b/ui/app/components/ui/list-item/index.scss @@ -5,7 +5,7 @@ background: #fff; padding: 24px 16px; - @extend %font; + @extend %Paragraph; border-top: 1px solid $mercury; border-bottom: 1px solid $mercury; diff --git a/ui/app/components/ui/popover/index.scss b/ui/app/components/ui/popover/index.scss index 1c3d8744c262..af3d7b279dcf 100644 --- a/ui/app/components/ui/popover/index.scss +++ b/ui/app/components/ui/popover/index.scss @@ -33,10 +33,9 @@ align-items: center; justify-content: space-between; - @extend %font; + @extend %H4; font-weight: bold; - font-size: 18px; line-height: 25px; padding-bottom: 8px; @@ -52,10 +51,8 @@ } &__subtitle { - @extend %font; + @extend %H6; - font-weight: normal; - font-size: 14px; line-height: 20px; } diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index 567e7a418053..3e804498968e 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -287,8 +287,7 @@ } &__button { - @include paragraph; - + @extend %Paragraph; @extend %button; width: 141px; diff --git a/ui/app/css/itcss/settings/index.scss b/ui/app/css/itcss/settings/index.scss index bbf79c80f939..a7152a435356 100644 --- a/ui/app/css/itcss/settings/index.scss +++ b/ui/app/css/itcss/settings/index.scss @@ -1,2 +1 @@ @import './variables'; -@import './typography'; diff --git a/ui/app/css/itcss/settings/typography.scss b/ui/app/css/itcss/settings/typography.scss deleted file mode 100644 index 27390b6ee564..000000000000 --- a/ui/app/css/itcss/settings/typography.scss +++ /dev/null @@ -1,84 +0,0 @@ -$fa-font-path: 'fonts/fontawesome'; - -@import '../../../../../node_modules/@fortawesome/fontawesome-free/scss/fontawesome'; -@import '../../../../../node_modules/@fortawesome/fontawesome-free/scss/solid'; -@import '../../../../../node_modules/@fortawesome/fontawesome-free/scss/regular'; - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 100; - src: local('Roboto Thin'), local('Roboto-Thin'), url('fonts/Roboto/Roboto-Thin.ttf') format('truetype'); -} - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url('fonts/Roboto/Roboto-Light.ttf') format('truetype'); -} - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: local('Roboto'), local('Roboto-Regular'), url('fonts/Roboto/Roboto-Regular.ttf') format('truetype'); -} - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 500; - src: local('Roboto Medium'), local('Roboto-Medium'), url('fonts/Roboto/Roboto-Medium.ttf') format('truetype'); -} - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 700; - src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/Roboto/Roboto-Bold.ttf') format('truetype'); -} - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 900; - src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); -} - -@mixin fontScale($weight: 400, $size: 1rem) { - font-weight: $weight; - font-size: $size; -} - -@mixin h1($weight: 400, $size: 2.5rem) { - @include fontScale($weight, $size); -} - -@mixin h2($weight: 400, $size: 2rem) { - @include fontScale($weight, $size); -} - -@mixin h3($weight: 400, $size: 1.5rem) { - @include fontScale($weight, $size); -} - -@mixin h4($weight: 400, $size: 1.125rem) { - @include fontScale($weight, $size); -} - -@mixin h5($weight: 400, $size: 1rem) { - @include fontScale($weight, $size); -} - -@mixin h6($weight: 400, $size: 0.875rem) { - @include fontScale($weight, $size); -} - -@mixin h7($weight: 400, $size: 0.75rem) { - @include fontScale($weight, $size); -} - -@mixin paragraph($weight: 400, $size: 1rem) { - @include fontScale($weight, $size); -} diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss index 9a40ec9ffc01..fa6727ee292d 100644 --- a/ui/app/css/itcss/settings/variables.scss +++ b/ui/app/css/itcss/settings/variables.scss @@ -105,42 +105,6 @@ $break-small: 575px; $break-midpoint: 780px; $break-large: 576px; - -$primary-font-type: Roboto; - - -// Font Sizes -%h3 { - font-size: 1.5rem; - line-height: 2.125rem; - font-weight: 400; -} - -%h4 { - font-size: 1.125rem; - line-height: 1.3125rem; - font-weight: 400; -} - -%h5 { - font-size: 1rem; - line-height: 1.25rem; - font-weight: 400; -} - -%h6 { - font-size: 0.875rem; - line-height: 1.25rem; - font-weight: 400; -} - -%h8 { - font-size: 0.75rem; - line-height: 1.0625rem; - font-weight: 400; -} - - /* Spacing Variables */ @@ -176,36 +140,3 @@ $xxlarge-spacing: 64px; border-color: $Blue-500; } } - -// Font mixin - -%font { - font-family: Roboto; - font-style: normal; - font-weight: normal; - color: $Grey-800; -} - -%font--bold { - @extend %font; - - font-weight: bold; -} - -%header--18 { - @extend %font; - - font-size: 18px; -} - -%header--24 { - @extend %font; - - font-size: 24px; -} - -%content-text { - @extend %font; - - font-size: 14px; -} diff --git a/ui/app/css/variables/index.scss b/ui/app/css/variables/index.scss index 7aa2d674f096..8d79fd9c7abb 100644 --- a/ui/app/css/variables/index.scss +++ b/ui/app/css/variables/index.scss @@ -1 +1,2 @@ @import './colors.scss'; +@import './typography.scss'; diff --git a/ui/app/css/variables/typography.scss b/ui/app/css/variables/typography.scss new file mode 100644 index 000000000000..12bc4fccbc16 --- /dev/null +++ b/ui/app/css/variables/typography.scss @@ -0,0 +1,130 @@ +$fa-font-path: 'fonts/fontawesome'; + +@import '../../../../node_modules/@fortawesome/fontawesome-free/scss/fontawesome'; +@import '../../../../node_modules/@fortawesome/fontawesome-free/scss/solid'; +@import '../../../../node_modules/@fortawesome/fontawesome-free/scss/regular'; + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + src: local('Roboto Thin'), local('Roboto-Thin'), url('fonts/Roboto/Roboto-Thin.ttf') format('truetype'); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local('Roboto Light'), local('Roboto-Light'), url('fonts/Roboto/Roboto-Light.ttf') format('truetype'); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto'), local('Roboto-Regular'), url('fonts/Roboto/Roboto-Regular.ttf') format('truetype'); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local('Roboto Medium'), local('Roboto-Medium'), url('fonts/Roboto/Roboto-Medium.ttf') format('truetype'); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/Roboto/Roboto-Bold.ttf') format('truetype'); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 900; + src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); +} + +$font-family: Roboto, Helvetica, Arial, sans-serif; + +// Typography +%H1 { + font-style: normal; + font-weight: normal; + font-size: 2.5rem; + font-family: $font-family; + line-height: 140%; +} + +%H2 { + font-style: normal; + font-weight: normal; + font-size: 2rem; + font-family: $font-family; + line-height: 140%; +} + +%H3 { + font-style: normal; + font-weight: normal; + font-size: 1.5rem; + font-family: $font-family; + line-height: 140%; +} + +%H4 { + font-style: normal; + font-weight: normal; + font-size: 1.125rem; + font-family: $font-family; + line-height: 140%; +} + +%H5 { + font-style: normal; + font-weight: normal; + font-size: 1rem; + font-family: $font-family; + line-height: 140%; +} + +%H6 { + font-style: normal; + font-weight: normal; + font-size: 0.875rem; + font-family: $font-family; +} + +%Paragraph { + font-style: normal; + font-weight: normal; + font-size: 1rem; + font-family: $font-family; + line-height: 140%; +} + +%H7 { + font-style: normal; + font-weight: normal; + font-size: 0.75rem; + font-family: $font-family; + line-height: 140%; +} + +%H8 { + font-style: normal; + font-weight: normal; + font-size: 0.625rem; + font-family: $font-family; + line-height: 140%; +} + +%H9 { + font-style: normal; + font-weight: normal; + font-size: 0.5rem; + font-family: $font-family; + line-height: 140%; +} + diff --git a/ui/app/pages/home/index.scss b/ui/app/pages/home/index.scss index 814223bf399b..37911bdc6c6d 100644 --- a/ui/app/pages/home/index.scss +++ b/ui/app/pages/home/index.scss @@ -43,10 +43,11 @@ display: flex; flex-direction: column; - @extend %content-text; + @extend %H6; padding-left: 24px; padding-right: 24px; + color: $Grey-800; div { margin-bottom: 20px; diff --git a/ui/app/pages/permissions-connect/choose-account/index.scss b/ui/app/pages/permissions-connect/choose-account/index.scss index 4f71942c175a..b79c9c923bd2 100644 --- a/ui/app/pages/permissions-connect/choose-account/index.scss +++ b/ui/app/pages/permissions-connect/choose-account/index.scss @@ -24,13 +24,13 @@ &__title { - @extend %header--18; + @extend %H4; } &__text, &__text-blue, &__text-grey { - @extend %content-text; + @extend %H6; } &__text-blue { @@ -120,7 +120,7 @@ } &__label { - @extend %content-text; + @extend %H6; color: $Black-100; text-overflow: ellipsis; @@ -129,17 +129,14 @@ } &__balance { - @extend %content-text; + @extend %H7; - font-size: 12px; color: $Grey-500; } &__last-connected { - @extend %content-text; + @extend %H8; - font-size: 10px; - line-height: 140.62%; display: flex; flex-direction: column; align-items: flex-end; diff --git a/ui/app/pages/permissions-connect/index.scss b/ui/app/pages/permissions-connect/index.scss index a5f9f1d2d37d..58263d9b489f 100644 --- a/ui/app/pages/permissions-connect/index.scss +++ b/ui/app/pages/permissions-connect/index.scss @@ -24,7 +24,7 @@ } &__back { - @extend %content-text; + @extend %H6; color: $Grey-600; cursor: pointer; @@ -35,9 +35,8 @@ } &__page-count { - @extend %content-text; + @extend %H7; - font-size: 12px; color: #6a737d; grid-column: 2; justify-self: end; diff --git a/ui/app/pages/permissions-connect/redirect/index.scss b/ui/app/pages/permissions-connect/redirect/index.scss index b2cc68554c42..2151385ed1c4 100644 --- a/ui/app/pages/permissions-connect/redirect/index.scss +++ b/ui/app/pages/permissions-connect/redirect/index.scss @@ -4,7 +4,7 @@ justify-content: center; &__result { - @extend %header--24; + @extend %H3; position: absolute; top: 30%; diff --git a/ui/app/pages/send/send.scss b/ui/app/pages/send/send.scss index e9b8cd265437..eb64a4105679 100644 --- a/ui/app/pages/send/send.scss +++ b/ui/app/pages/send/send.scss @@ -6,7 +6,7 @@ padding: 14px 0 3px 0; .page-container__title { - @extend %h4; + @extend %H4; text-align: center; } @@ -91,7 +91,7 @@ } &__group-label { - @extend %h8; + @extend %H8; background-color: $Grey-000; color: $Grey-600; @@ -136,7 +136,7 @@ } &__subtitle { - @extend %h8; + @extend %H8; color: $Grey-500; } @@ -186,7 +186,7 @@ } &__input { - @extend %h6; + @extend %H6; flex: 1 1 auto; width: 0; From b4663eb78b975886aeef462a2688bbdfa49f222d Mon Sep 17 00:00:00 2001 From: ryanml Date: Fri, 24 Jul 2020 15:47:40 -0700 Subject: [PATCH 002/137] Fixes MetaMask/metamask-extension#8626 - verifies password on requesting seed phrase (#9063) --- app/scripts/metamask-controller.js | 10 ++++++++++ package.json | 2 +- ui/app/store/actions.js | 4 ++-- yarn.lock | 8 ++++---- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 3f1511333e6b..5aa4539e325c 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -478,6 +478,7 @@ export default class MetamaskController extends EventEmitter { // vault management submitPassword: nodeify(this.submitPassword, this), + verifyPassword: nodeify(this.verifyPassword, this), // network management setProviderType: nodeify(networkController.setProviderType, networkController), @@ -808,6 +809,15 @@ export default class MetamaskController extends EventEmitter { return this.keyringController.fullUpdate() } + /** + * Submits a user's password to check its validity. + * + * @param {string} password The user's password + */ + async verifyPassword (password) { + await this.keyringController.verifyPassword(password) + } + /** * @type Identity * @property {string} name - The account nickname. diff --git a/package.json b/package.json index d0b2a48b63e3..a433b99cd6fe 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "eth-json-rpc-filters": "^4.1.1", "eth-json-rpc-infura": "^4.0.2", "eth-json-rpc-middleware": "^5.0.2", - "eth-keyring-controller": "^6.0.1", + "eth-keyring-controller": "^6.1.0", "eth-method-registry": "^1.2.0", "eth-phishing-detect": "^1.1.4", "eth-query": "^2.1.2", diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index abb855233fa3..49a43da246a4 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -168,7 +168,7 @@ export function createNewVault (password) { export function verifyPassword (password) { return new Promise((resolve, reject) => { - background.submitPassword(password, (error) => { + background.verifyPassword(password, (error) => { if (error) { return reject(error) } @@ -193,7 +193,7 @@ export function verifySeedPhrase () { export function requestRevealSeedWords (password) { return async (dispatch) => { dispatch(showLoadingIndication()) - log.debug(`background.submitPassword`) + log.debug(`background.verifyPassword`) try { await verifyPassword(password) diff --git a/yarn.lock b/yarn.lock index 0290b9ac1b63..30f8e5ecf1d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10131,10 +10131,10 @@ eth-keyring-controller@^5.3.0, eth-keyring-controller@^5.6.1: loglevel "^1.5.0" obs-store "^4.0.3" -eth-keyring-controller@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.0.1.tgz#6a4cdd5802b0587320c711be6c1752b2a88221aa" - integrity sha512-60j71F1HgLcvwzg7U5R45bA/kgQSUlmiZrsUIIhW4qS7QOYqJn0OQ64enf0ZaxMMPVVcKSfCDersYJiqm/yrlw== +eth-keyring-controller@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.1.0.tgz#dc9313d0b793e085dc1badf84dd4f5e3004e127e" + integrity sha512-wPxH++98VDBcDv9YkPzxhZC0gF1ixuRbyKR2u/NOT/roBpNQDe4reqyllBRC7jhPehiKnRxzf7r6HEyirRnPxQ== dependencies: bip39 "^2.4.0" bluebird "^3.5.0" From ef1b1d57383c90b8a192828857b43615e1fad7bf Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Mon, 27 Jul 2020 11:33:25 -0700 Subject: [PATCH 003/137] Fix popup/notification when browser is in fullscreen, primarily on macOS. (#9075) * Fix popup/notification when browser is in fullscreen, primarily on OSX. The issue was reported internally via Slack. User was running Mac OSX Chrome in fullscreen mode where Chrome is created in a new Desktop workspace. The issue reproduced on OSX Chrome in fullscreen/maximized view overrides the explicitly set width and height for `windows.create()`. Possibly not overrides, but creates a window based off of the window that it was created from. Found a related [Chromium bug](https://bugs.chromium.org/p/chromium/issues/detail?id=263092&q=window%20create%20width%20os%3DMac&can=2). The fullscreen `popup.left` pixel will calculate the window position incorrectly since we set and assume the width of the created window. The incorrect `left` position the window and transition the focus Desktop/Workspace incorrectly and make is seem to lose focus of the new window/workspace. Incidentally this will make the popup full width/height, and create a new workspace for the view, which we have no control over until Chrome fixes it. This will check if the popup is 'fullscreen', which it gets passed from the origin window, if so then don't reposition the window. If Chrome fixes the issue we can revert this change. * Feedback commit Co-authored-by: Mark Stacey Co-authored-by: Mark Stacey --- app/scripts/lib/notification-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js index 497100354587..631ae3290257 100644 --- a/app/scripts/lib/notification-manager.js +++ b/app/scripts/lib/notification-manager.js @@ -56,7 +56,7 @@ export default class NotificationManager { }) // Firefox currently ignores left/top for create, but it works for update - if (popupWindow.left !== left) { + if (popupWindow.left !== left && popupWindow.state !== 'fullscreen') { await this.platform.updateWindowPosition(popupWindow.id, left, top) } this._popupId = popupWindow.id From 57715a8da194f9e5d2ad4b1a9913e57a8fda99a1 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Mon, 27 Jul 2020 15:01:21 -0500 Subject: [PATCH 004/137] support longer text in network dropdown (#9085) --- ui/app/css/itcss/components/network.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/css/itcss/components/network.scss b/ui/app/css/itcss/components/network.scss index 194a59fbdba6..02d0dcfcd35f 100644 --- a/ui/app/css/itcss/components/network.scss +++ b/ui/app/css/itcss/components/network.scss @@ -175,7 +175,7 @@ } .network-dropdown-content { - height: 36px; + min-height: 36px; width: 265px; color: $dusty-gray; font-family: Roboto; From d9f07a796d220b7f0b4fc7f391b679dfc1a4986f Mon Sep 17 00:00:00 2001 From: ryanml Date: Mon, 27 Jul 2020 14:03:26 -0700 Subject: [PATCH 005/137] Complete onboarding upon importing/verifying seed (#8873) Fixes #8679 --- .../import-with-seed-phrase.component.js | 6 ++++-- .../import-with-seed-phrase.container.js | 2 ++ .../first-time-flow/end-of-flow/end-of-flow.component.js | 4 +--- .../first-time-flow/end-of-flow/end-of-flow.container.js | 9 +-------- .../end-of-flow/tests/end-of-flow.test.js | 2 -- .../confirm-seed-phrase/confirm-seed-phrase.component.js | 8 +++++++- .../confirm-seed-phrase/confirm-seed-phrase.container.js | 2 ++ .../tests/confirm-seed-phrase-component.test.js | 1 + 8 files changed, 18 insertions(+), 16 deletions(-) diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js index b130889155fe..2c3dc1c78193 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js @@ -19,6 +19,7 @@ export default class ImportWithSeedPhrase extends PureComponent { onSubmit: PropTypes.func.isRequired, setSeedPhraseBackedUp: PropTypes.func, initializeThreeBox: PropTypes.func, + completeOnboarding: PropTypes.func, } state = { @@ -119,7 +120,7 @@ export default class ImportWithSeedPhrase extends PureComponent { } const { password, seedPhrase } = this.state - const { history, onSubmit, setSeedPhraseBackedUp, initializeThreeBox } = this.props + const { history, onSubmit, setSeedPhraseBackedUp, initializeThreeBox, completeOnboarding } = this.props try { await onSubmit(password, this.parseSeedPhrase(seedPhrase)) @@ -131,7 +132,8 @@ export default class ImportWithSeedPhrase extends PureComponent { }, }) - setSeedPhraseBackedUp(true).then(() => { + setSeedPhraseBackedUp(true).then(async () => { + await completeOnboarding() initializeThreeBox() history.push(INITIALIZE_END_OF_FLOW_ROUTE) }) diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js index 32038e07d8e0..018666b139cc 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js @@ -3,12 +3,14 @@ import ImportWithSeedPhrase from './import-with-seed-phrase.component' import { setSeedPhraseBackedUp, initializeThreeBox, + setCompletedOnboarding, } from '../../../../store/actions' const mapDispatchToProps = (dispatch) => { return { setSeedPhraseBackedUp: (seedPhraseBackupState) => dispatch(setSeedPhraseBackedUp(seedPhraseBackupState)), initializeThreeBox: () => dispatch(initializeThreeBox()), + completeOnboarding: () => dispatch(setCompletedOnboarding()), } } diff --git a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js index 275dcc587f8d..a6510553dafe 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js +++ b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js @@ -14,7 +14,6 @@ export default class EndOfFlowScreen extends PureComponent { static propTypes = { history: PropTypes.object, - completeOnboarding: PropTypes.func, completionMetaMetricsName: PropTypes.string, onboardingInitiator: PropTypes.exact({ location: PropTypes.string, @@ -23,9 +22,8 @@ export default class EndOfFlowScreen extends PureComponent { } onComplete = async () => { - const { history, completeOnboarding, completionMetaMetricsName, onboardingInitiator } = this.props + const { history, completionMetaMetricsName, onboardingInitiator } = this.props - await completeOnboarding() this.context.metricsEvent({ eventOpts: { category: 'Onboarding', diff --git a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js index 61af2fdaa29e..d52f74dbc560 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js +++ b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js @@ -1,6 +1,5 @@ import { connect } from 'react-redux' import EndOfFlow from './end-of-flow.component' -import { setCompletedOnboarding } from '../../../store/actions' import { getOnboardingInitiator } from '../../../selectors' const firstTimeFlowTypeNameMap = { @@ -17,10 +16,4 @@ const mapStateToProps = (state) => { } } -const mapDispatchToProps = (dispatch) => { - return { - completeOnboarding: () => dispatch(setCompletedOnboarding()), - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(EndOfFlow) +export default connect(mapStateToProps)(EndOfFlow) diff --git a/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js b/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js index 56f4aba0d25b..2cc5b971085e 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js +++ b/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js @@ -12,7 +12,6 @@ describe('End of Flow Screen', function () { history: { push: sinon.spy(), }, - completeOnboarding: sinon.spy(), } beforeEach(function () { @@ -30,7 +29,6 @@ describe('End of Flow Screen', function () { endOfFlowButton.simulate('click') setImmediate(() => { - assert(props.completeOnboarding.calledOnce) assert(props.history.push.calledOnceWithExactly(DEFAULT_ROUTE)) done() }) diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index 18f496ca74e8..8847a0d01f14 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -26,6 +26,7 @@ export default class ConfirmSeedPhrase extends PureComponent { seedPhrase: PropTypes.string, initializeThreeBox: PropTypes.func, setSeedPhraseBackedUp: PropTypes.func, + completeOnboarding: PropTypes.func, } state = { @@ -66,6 +67,10 @@ export default class ConfirmSeedPhrase extends PureComponent { exportAsFile('', this.props.seedPhrase, 'text/plain') } + setOnboardingCompleted = async () => { + await this.props.completeOnboarding() + } + handleSubmit = async () => { const { history, @@ -86,8 +91,9 @@ export default class ConfirmSeedPhrase extends PureComponent { }, }) - setSeedPhraseBackedUp(true).then(() => { + setSeedPhraseBackedUp(true).then(async () => { initializeThreeBox() + this.setOnboardingCompleted() history.push(INITIALIZE_END_OF_FLOW_ROUTE) }) } catch (error) { diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js index 393998f8d54d..176601e49a40 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js @@ -3,12 +3,14 @@ import ConfirmSeedPhrase from './confirm-seed-phrase.component' import { setSeedPhraseBackedUp, initializeThreeBox, + setCompletedOnboarding, } from '../../../../store/actions' const mapDispatchToProps = (dispatch) => { return { setSeedPhraseBackedUp: (seedPhraseBackupState) => dispatch(setSeedPhraseBackedUp(seedPhraseBackupState)), initializeThreeBox: () => dispatch(initializeThreeBox()), + completeOnboarding: () => dispatch(setCompletedOnboarding()), } } diff --git a/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js index 449bd33477a5..a5846a944af9 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js +++ b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js @@ -142,6 +142,7 @@ describe('ConfirmSeedPhrase Component', function () { history: { push: pushSpy }, setSeedPhraseBackedUp: () => Promise.resolve(), initializeThreeBox: initialize3BoxSpy, + completeOnboarding: sinon.spy(), }, { metricsEvent: metricsEventSpy, From f6f8e5cc4a4a46fde826043eaefb66304c493ee7 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Mon, 27 Jul 2020 14:35:09 -0700 Subject: [PATCH 006/137] Robustify permissions controller requestUserApproval tests (#9064) * convert requestUserApproval mock to wrapper --- .../app/controllers/permissions/helpers.js | 43 +++++++++++++------ .../permissions-controller-test.js | 41 +++++++----------- .../permissions-middleware-test.js | 31 ++++++++++++- 3 files changed, 77 insertions(+), 38 deletions(-) diff --git a/test/unit/app/controllers/permissions/helpers.js b/test/unit/app/controllers/permissions/helpers.js index 8879329a458e..0378dc08910a 100644 --- a/test/unit/app/controllers/permissions/helpers.js +++ b/test/unit/app/controllers/permissions/helpers.js @@ -19,25 +19,44 @@ export function grantPermissions (permController, origin, permissions) { } /** - * Sets the underlying rpc-cap requestUserApproval function, and returns - * a promise that's resolved once it has been set. + * Returns a wrapper for the given permissions controller's requestUserApproval + * function, so we don't have to worry about its internals. * - * This function must be called on the given permissions controller every - * time you want such a Promise. As of writing, it's only called once per test. + * @param {PermissionsController} permController - The permissions controller. + * @return {Function} A convenient wrapper for the requestUserApproval function. + */ +export function getRequestUserApprovalHelper (permController) { + /** + * Returns a request object that can be passed to requestUserApproval. + * + * @param {string} id - The internal permissions request ID (not the RPC request ID). + * @param {string} [origin] - The origin of the request, if necessary. + * @returns {Object} The corresponding request object. + */ + return (id, origin = 'defaultOrigin') => { + return permController.permissions.requestUserApproval({ metadata: { id, origin } }) + } +} + +/** + * Returns a Promise that resolves once a pending user approval has been set. + * Calls the underlying requestUserApproval function as normal, and restores it + * once the Promise is resolved. + * + * This function must be called on the permissions controller for each request. * * @param {PermissionsController} - A permissions controller. * @returns {Promise} A Promise that resolves once a pending approval * has been set. */ export function getUserApprovalPromise (permController) { - return new Promise((resolveForCaller) => { - permController.permissions.requestUserApproval = async (req) => { - const { origin, metadata: { id } } = req - - return new Promise((resolve, reject) => { - permController.pendingApprovals.set(id, { origin, resolve, reject }) - resolveForCaller() - }) + const originalFunction = permController.permissions.requestUserApproval + return new Promise((resolveHelperPromise) => { + permController.permissions.requestUserApproval = (req) => { + const userApprovalPromise = originalFunction(req) + permController.permissions.requestUserApproval = originalFunction + resolveHelperPromise() + return userApprovalPromise } }) } diff --git a/test/unit/app/controllers/permissions/permissions-controller-test.js b/test/unit/app/controllers/permissions/permissions-controller-test.js index 98b0cd55ddda..1b4f315a342d 100644 --- a/test/unit/app/controllers/permissions/permissions-controller-test.js +++ b/test/unit/app/controllers/permissions/permissions-controller-test.js @@ -15,6 +15,7 @@ import { } from '../../../../../app/scripts/controllers/permissions' import { + getRequestUserApprovalHelper, grantPermissions, } from './helpers' @@ -58,12 +59,6 @@ const initPermController = (notifications = initNotifications()) => { }) } -const getMockRequestUserApprovalFunction = (permController) => (id, origin) => { - return new Promise((resolve, reject) => { - permController.pendingApprovals.set(id, { origin, resolve, reject }) - }) -} - describe('permissions controller', function () { describe('getAccounts', function () { @@ -951,13 +946,11 @@ describe('permissions controller', function () { describe('approvePermissionsRequest', function () { - let permController, mockRequestUserApproval + let permController, requestUserApproval beforeEach(function () { permController = initPermController() - mockRequestUserApproval = getMockRequestUserApprovalFunction( - permController, - ) + requestUserApproval = getRequestUserApprovalHelper(permController) }) it('does nothing if called on non-existing request', async function () { @@ -994,14 +987,14 @@ describe('permissions controller', function () { PERMS.requests.eth_accounts(), ) - const requestRejection = assert.rejects( - mockRequestUserApproval(REQUEST_IDS.a), + const rejectionPromise = assert.rejects( + requestUserApproval(REQUEST_IDS.a), ERRORS.validatePermittedAccounts.invalidParam(), - 'should reject bad accounts', + 'should reject with "null" accounts', ) await permController.approvePermissionsRequest(request, null) - await requestRejection + await rejectionPromise assert.equal( permController.pendingApprovals.size, 0, @@ -1014,7 +1007,7 @@ describe('permissions controller', function () { const request = PERMS.approvedRequest(REQUEST_IDS.a, {}) const requestRejection = assert.rejects( - mockRequestUserApproval(REQUEST_IDS.a), + requestUserApproval(REQUEST_IDS.a), ERRORS.approvePermissionsRequest.noPermsRequested(), 'should reject if no permissions in request', ) @@ -1036,7 +1029,7 @@ describe('permissions controller', function () { const requestApproval = assert.doesNotReject( async () => { - perms = await mockRequestUserApproval(REQUEST_IDS.a) + perms = await requestUserApproval(REQUEST_IDS.a) }, 'should not reject single valid request', ) @@ -1065,14 +1058,14 @@ describe('permissions controller', function () { const approval1 = assert.doesNotReject( async () => { - perms1 = await mockRequestUserApproval(REQUEST_IDS.a) + perms1 = await requestUserApproval(REQUEST_IDS.a, DOMAINS.a.origin) }, 'should not reject request', ) const approval2 = assert.doesNotReject( async () => { - perms2 = await mockRequestUserApproval(REQUEST_IDS.b) + perms2 = await requestUserApproval(REQUEST_IDS.b, DOMAINS.b.origin) }, 'should not reject request', ) @@ -1105,13 +1098,11 @@ describe('permissions controller', function () { describe('rejectPermissionsRequest', function () { - let permController, mockRequestUserApproval + let permController, requestUserApproval beforeEach(async function () { permController = initPermController() - mockRequestUserApproval = getMockRequestUserApprovalFunction( - permController, - ) + requestUserApproval = getRequestUserApprovalHelper(permController) }) it('does nothing if called on non-existing request', async function () { @@ -1135,7 +1126,7 @@ describe('permissions controller', function () { it('rejects single existing request', async function () { const requestRejection = assert.rejects( - mockRequestUserApproval(REQUEST_IDS.a), + requestUserApproval(REQUEST_IDS.a), ERRORS.rejectPermissionsRequest.rejection(), 'should reject with expected error', ) @@ -1152,13 +1143,13 @@ describe('permissions controller', function () { it('rejects requests regardless of order', async function () { const requestRejection1 = assert.rejects( - mockRequestUserApproval(REQUEST_IDS.b), + requestUserApproval(REQUEST_IDS.b, DOMAINS.b.origin), ERRORS.rejectPermissionsRequest.rejection(), 'should reject with expected error', ) const requestRejection2 = assert.rejects( - mockRequestUserApproval(REQUEST_IDS.c), + requestUserApproval(REQUEST_IDS.c, DOMAINS.c.origin), ERRORS.rejectPermissionsRequest.rejection(), 'should reject with expected error', ) diff --git a/test/unit/app/controllers/permissions/permissions-middleware-test.js b/test/unit/app/controllers/permissions/permissions-middleware-test.js index b835ea8e8ec2..8b56eb764339 100644 --- a/test/unit/app/controllers/permissions/permissions-middleware-test.js +++ b/test/unit/app/controllers/permissions/permissions-middleware-test.js @@ -70,11 +70,15 @@ describe('permissions middleware', function () { ) const res = {} + const userApprovalPromise = getUserApprovalPromise(permController) + const pendingApproval = assert.doesNotReject( aMiddleware(req, res), 'should not reject permissions request', ) + await userApprovalPromise + assert.equal( permController.pendingApprovals.size, 1, 'perm controller should have single pending approval', @@ -131,11 +135,15 @@ describe('permissions middleware', function () { // send, approve, and validate first request // note use of ACCOUNTS.a.permitted + let userApprovalPromise = getUserApprovalPromise(permController) + const pendingApproval1 = assert.doesNotReject( aMiddleware(req1, res1), 'should not reject permissions request', ) + await userApprovalPromise + const id1 = permController.pendingApprovals.keys().next().value const approvedReq1 = PERMS.approvedRequest(id1, PERMS.requests.eth_accounts()) @@ -187,11 +195,15 @@ describe('permissions middleware', function () { // send, approve, and validate second request // note use of ACCOUNTS.b.permitted + userApprovalPromise = getUserApprovalPromise(permController) + const pendingApproval2 = assert.doesNotReject( aMiddleware(req2, res2), 'should not reject permissions request', ) + await userApprovalPromise + const id2 = permController.pendingApprovals.keys().next().value const approvedReq2 = PERMS.approvedRequest(id2, { ...requestedPerms2 }) @@ -251,12 +263,16 @@ describe('permissions middleware', function () { const expectedError = ERRORS.rejectPermissionsRequest.rejection() + const userApprovalPromise = getUserApprovalPromise(permController) + const requestRejection = assert.rejects( aMiddleware(req, res), expectedError, 'request should be rejected with correct error', ) + await userApprovalPromise + assert.equal( permController.pendingApprovals.size, 1, 'perm controller should have single pending approval', @@ -343,11 +359,15 @@ describe('permissions middleware', function () { ) const resA1 = {} + let userApprovalPromise = getUserApprovalPromise(permController) + const requestApproval1 = assert.doesNotReject( aMiddleware(reqA1, resA1), 'should not reject permissions request', ) + await userApprovalPromise + // create and start processing first request for second origin const reqB1 = RPC_REQUESTS.requestPermission( @@ -355,11 +375,15 @@ describe('permissions middleware', function () { ) const resB1 = {} + userApprovalPromise = getUserApprovalPromise(permController) + const requestApproval2 = assert.doesNotReject( bMiddleware(reqB1, resB1), 'should not reject permissions request', ) + await userApprovalPromise + assert.equal( permController.pendingApprovals.size, 2, 'perm controller should have expected number of pending approvals', @@ -373,12 +397,17 @@ describe('permissions middleware', function () { ) const resA2 = {} - await assert.rejects( + userApprovalPromise = getUserApprovalPromise(permController) + + const requestApprovalFail = assert.rejects( aMiddleware(reqA2, resA2), expectedError, 'request should be rejected with correct error', ) + await userApprovalPromise + await requestApprovalFail + assert.ok( ( !resA2.result && resA2.error && From 5cb22ee8df89c8c283daba87991168f7cea6b9f3 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Sat, 25 Jul 2020 11:25:34 -0700 Subject: [PATCH 007/137] fix timing-reliant network controller test --- test/unit/app/controllers/network/network-controller-test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/unit/app/controllers/network/network-controller-test.js b/test/unit/app/controllers/network/network-controller-test.js index 14d3bf31f24f..416274ab8248 100644 --- a/test/unit/app/controllers/network/network-controller-test.js +++ b/test/unit/app/controllers/network/network-controller-test.js @@ -34,8 +34,10 @@ describe('NetworkController', function () { assert.equal(providerProxy.test, true) }) }) + describe('#getNetworkState', function () { it('should return loading when new', function () { + networkController = new NetworkController() const networkState = networkController.getNetworkState() assert.equal(networkState, 'loading', 'network is loading') }) From 13aafa4702b52bb1c94dab0bb8246c39554b74a5 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Mon, 27 Jul 2020 17:15:44 -0500 Subject: [PATCH 008/137] Add euclid fontface (#9018) --- .../Euclid/EuclidCircularB-Bold-WebXL.ttf | Bin 0 -> 150928 bytes .../Euclid/EuclidCircularB-Regular-WebXL.ttf | Bin 0 -> 154192 bytes .../EuclidCircularB-RegularItalic-WebXL.ttf | Bin 0 -> 157072 bytes ui/app/css/variables/typography.scss | 21 ++++++++++++++++++ 4 files changed, 21 insertions(+) create mode 100644 app/fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf create mode 100644 app/fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf create mode 100644 app/fonts/Euclid/EuclidCircularB-RegularItalic-WebXL.ttf diff --git a/app/fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf b/app/fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf new file mode 100644 index 0000000000000000000000000000000000000000..244ebba0a48132cefec3cb28bc356537190566da GIT binary patch literal 150928 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 _#Tk7*DV*^sG!F#HKA0_!w%gwm1 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 QI_#MO?3P0CYs=aH4`8D400000 literal 0 HcmV?d00001 diff --git a/app/fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf b/app/fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6cf177fe1b2377316697d96a9bde76ff3e90f8af GIT binary patch literal 154192 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�$p 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 E1AJW2Pyhe` literal 0 HcmV?d00001 diff --git a/ui/app/css/variables/typography.scss b/ui/app/css/variables/typography.scss index 12bc4fccbc16..0a51e173833a 100644 --- a/ui/app/css/variables/typography.scss +++ b/ui/app/css/variables/typography.scss @@ -46,6 +46,27 @@ $fa-font-path: 'fonts/fontawesome'; src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); } +@font-face { + font-family: 'Euclid'; + font-style: normal; + font-weight: 400; + src: url('fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf') format('truetype'); +} + +@font-face { + font-family: 'Euclid'; + font-style: italic; + font-weight: 400; + src: url('fonts/Euclid/EuclidCircularB-RegularItalic-WebXL.ttf') format('truetype'); +} + +@font-face { + font-family: 'Euclid'; + font-style: normal; + font-weight: 700; + src: url('fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf') format('truetype'); +} + $font-family: Roboto, Helvetica, Arial, sans-serif; // Typography From b3e5befe743a905b7dc1573db77de4d8b74ba398 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Mon, 27 Jul 2020 15:28:58 -0700 Subject: [PATCH 009/137] call initializeProvider where necessary --- test/unit/app/controllers/network/network-controller-test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/app/controllers/network/network-controller-test.js b/test/unit/app/controllers/network/network-controller-test.js index 416274ab8248..9c2aabc94774 100644 --- a/test/unit/app/controllers/network/network-controller-test.js +++ b/test/unit/app/controllers/network/network-controller-test.js @@ -18,7 +18,6 @@ describe('NetworkController', function () { .reply(200) networkController = new NetworkController() - networkController.initializeProvider(networkControllerProviderConfig) }) afterEach(function () { @@ -37,7 +36,6 @@ describe('NetworkController', function () { describe('#getNetworkState', function () { it('should return loading when new', function () { - networkController = new NetworkController() const networkState = networkController.getNetworkState() assert.equal(networkState, 'loading', 'network is loading') }) @@ -53,11 +51,13 @@ describe('NetworkController', function () { describe('#setProviderType', function () { it('should update provider.type', function () { + networkController.initializeProvider(networkControllerProviderConfig) networkController.setProviderType('mainnet') const type = networkController.getProviderConfig().type assert.equal(type, 'mainnet', 'provider type is updated') }) it('should set the network to loading', function () { + networkController.initializeProvider(networkControllerProviderConfig) networkController.setProviderType('mainnet') const loading = networkController.isNetworkLoading() assert.ok(loading, 'network is loading') From 826d1462f05ec35577303c6fea86cc7647f81dbe Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Mon, 27 Jul 2020 15:31:10 -0700 Subject: [PATCH 010/137] fixup! call initializeProvider where necessary --- test/unit/app/controllers/network/network-controller-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/app/controllers/network/network-controller-test.js b/test/unit/app/controllers/network/network-controller-test.js index 9c2aabc94774..08164d99d39b 100644 --- a/test/unit/app/controllers/network/network-controller-test.js +++ b/test/unit/app/controllers/network/network-controller-test.js @@ -35,7 +35,7 @@ describe('NetworkController', function () { }) describe('#getNetworkState', function () { - it('should return loading when new', function () { + it('should return "loading" when new', function () { const networkState = networkController.getNetworkState() assert.equal(networkState, 'loading', 'network is loading') }) From 99899b5df98749ff1c91e49c143a3d4f36da9fb7 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Tue, 28 Jul 2020 10:01:24 -0700 Subject: [PATCH 011/137] json-rpc-engine@5.2.0 (#9091) --- package.json | 2 +- yarn.lock | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index a433b99cd6fe..cafe5bc84018 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "fuse.js": "^3.2.0", "human-standard-token-abi": "^2.0.0", "jazzicon": "^2.0.0", - "json-rpc-engine": "^5.1.8", + "json-rpc-engine": "^5.2.0", "json-rpc-middleware-stream": "^2.1.1", "jsonschema": "^1.2.4", "lodash": "^4.17.19", diff --git a/yarn.lock b/yarn.lock index 30f8e5ecf1d4..83d52e6c2814 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15765,6 +15765,14 @@ json-rpc-engine@^5.1.3, json-rpc-engine@^5.1.5, json-rpc-engine@^5.1.8: promise-to-callback "^1.0.0" safe-event-emitter "^1.0.1" +json-rpc-engine@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.2.0.tgz#0ea1162f56de53a41d47a4995168b56dc82bbf47" + integrity sha512-F9xjrIjMqPNCxzk9jtOgJMs9mt+80p03IbJALnO278grtSU+Sh/fSqb7gNk/gwlTxavO2+ABKenyz4ZP3kwKIQ== + dependencies: + eth-rpc-errors "^2.1.1" + safe-event-emitter "^1.0.1" + json-rpc-error@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" From 1e0ef76524a7f7cbd255744766398f7f1d69e041 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 28 Jul 2020 16:09:20 -0300 Subject: [PATCH 012/137] Use development metametrics project during tests (#9093) e2e tests will now reference the development MetaMetrics project instead of the production one. The metrics endpoint should be stubbed out during e2e tests anyway, but this seemed like a better default regardless. --- ui/app/helpers/utils/metametrics.util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/helpers/utils/metametrics.util.js b/ui/app/helpers/utils/metametrics.util.js index f0ec2249677a..629dc25675fc 100644 --- a/ui/app/helpers/utils/metametrics.util.js +++ b/ui/app/helpers/utils/metametrics.util.js @@ -2,7 +2,7 @@ import ethUtil from 'ethereumjs-util' -const inDevelopment = process.env.NODE_ENV === 'development' +const inDevelopment = process.env.METAMASK_DEBUG || process.env.IN_TEST const METAMETRICS_BASE_URL = 'https://chromeextensionmm.innocraft.cloud/piwik.php' const METAMETRICS_REQUIRED_PARAMS = `?idsite=${inDevelopment ? 1 : 2}&rec=1&apiv=1` From 8a7c8e8aebb45bd6a169d77be36f8e7113b9e713 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 28 Jul 2020 16:59:27 -0300 Subject: [PATCH 013/137] Use environment variable for MetaMetrics project ID (#9094) The MetaMetrics project ID can now be set via environment variable. It has not been set yet in practice, so for now the old project IDs will still be used. This is in preparation for migrating to a new project. --- development/build/scripts.js | 1 + ui/app/helpers/utils/metametrics.util.js | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/development/build/scripts.js b/development/build/scripts.js index 0cb3e85ea2f7..2ce9b86a0877 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -334,6 +334,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) { bundler.transform(envify({ METAMASK_DEBUG: opts.devMode, METAMASK_ENVIRONMENT: environment, + METAMETRICS_PROJECT_ID: process.env.METAMETRICS_PROJECT_ID, NODE_ENV: opts.devMode ? 'development' : 'production', IN_TEST: opts.testing ? 'true' : false, PUBNUB_SUB_KEY: process.env.PUBNUB_SUB_KEY || '', diff --git a/ui/app/helpers/utils/metametrics.util.js b/ui/app/helpers/utils/metametrics.util.js index 629dc25675fc..98b83f3d8aec 100644 --- a/ui/app/helpers/utils/metametrics.util.js +++ b/ui/app/helpers/utils/metametrics.util.js @@ -4,8 +4,13 @@ import ethUtil from 'ethereumjs-util' const inDevelopment = process.env.METAMASK_DEBUG || process.env.IN_TEST +let projectId = process.env.METAMETRICS_PROJECT_ID +if (!projectId) { + projectId = inDevelopment ? 1 : 2 +} + const METAMETRICS_BASE_URL = 'https://chromeextensionmm.innocraft.cloud/piwik.php' -const METAMETRICS_REQUIRED_PARAMS = `?idsite=${inDevelopment ? 1 : 2}&rec=1&apiv=1` +const METAMETRICS_REQUIRED_PARAMS = `?idsite=${projectId}&rec=1&apiv=1` const METAMETRICS_BASE_FULL = METAMETRICS_BASE_URL + METAMETRICS_REQUIRED_PARAMS const METAMETRICS_TRACKING_URL = inDevelopment From 869c252088605037ed0607dd8ea6a663b16bdf07 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 28 Jul 2020 16:59:47 -0300 Subject: [PATCH 014/137] Disable Sentry in development (#9095) In a non-production environment, Sentry was configured to send error reports to a "test" MetaMask project. It will still do this during e2e tests, but in development Sentry is now disabled completely. In practice this was never useful in development. --- app/scripts/lib/setupSentry.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 04c4b50144f8..9eca2ef5b23e 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -72,7 +72,9 @@ export const SENTRY_STATE = { export default function setupSentry ({ release, getState }) { let sentryTarget - if (METAMASK_DEBUG || process.env.IN_TEST) { + if (METAMASK_DEBUG) { + return + } else if (process.env.IN_TEST) { console.log(`Setting up Sentry Remote Error Reporting for '${METAMASK_ENVIRONMENT}': SENTRY_DSN_DEV`) sentryTarget = SENTRY_DSN_DEV } else { From 4cc3fff96afdb8208f35e1eb61e714e7f6921812 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Tue, 28 Jul 2020 15:16:30 -0500 Subject: [PATCH 015/137] Update css folder structure (#9071) --- .../generic/index.scss => base-styles.scss} | 30 ----------- ui/app/css/design-system/breakpoints.scss | 6 +++ .../{variables => design-system}/colors.scss | 0 .../css/design-system/deprecated-colors.scss | 48 +++++++++++++++++ ui/app/css/design-system/index.scss | 4 ++ .../typography.scss | 1 - ui/app/css/index.scss | 5 +- ui/app/css/itcss/settings/variables.scss | 54 ------------------- ui/app/css/{itcss/generic => }/reset.scss | 2 - ui/app/css/variables/index.scss | 2 - 10 files changed, 61 insertions(+), 91 deletions(-) rename ui/app/css/{itcss/generic/index.scss => base-styles.scss} (80%) create mode 100644 ui/app/css/design-system/breakpoints.scss rename ui/app/css/{variables => design-system}/colors.scss (100%) create mode 100644 ui/app/css/design-system/deprecated-colors.scss create mode 100644 ui/app/css/design-system/index.scss rename ui/app/css/{variables => design-system}/typography.scss (99%) rename ui/app/css/{itcss/generic => }/reset.scss (96%) delete mode 100644 ui/app/css/variables/index.scss diff --git a/ui/app/css/itcss/generic/index.scss b/ui/app/css/base-styles.scss similarity index 80% rename from ui/app/css/itcss/generic/index.scss rename to ui/app/css/base-styles.scss index 64c9688f650b..1e17639f7461 100644 --- a/ui/app/css/itcss/generic/index.scss +++ b/ui/app/css/base-styles.scss @@ -1,8 +1,4 @@ -/* - Generic - */ -@import './reset'; * { box-sizing: border-box; @@ -12,7 +8,6 @@ html, body { font-family: Roboto, Arial; color: #4d4d4d; - font-weight: 400; width: 100%; height: 100%; margin: 0; @@ -25,15 +20,6 @@ html { min-height: 500px; } -.app-root { - overflow: hidden; - position: relative; -} - -.app-primary { - display: flex; -} - .mouse-user-styles { button:focus, input:focus, @@ -121,19 +107,3 @@ input.form-control { } } -.hide-text-overflow { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.pinned-to-bottom { - position: absolute; - bottom: 0; -} - -.pinned-to-bottom-right { - position: absolute; - bottom: 0; - right: 0; -} diff --git a/ui/app/css/design-system/breakpoints.scss b/ui/app/css/design-system/breakpoints.scss new file mode 100644 index 000000000000..80a4176b0e57 --- /dev/null +++ b/ui/app/css/design-system/breakpoints.scss @@ -0,0 +1,6 @@ +/* +Responsive Breakpoints +*/ +$break-small: 575px; +$break-midpoint: 780px; +$break-large: 576px; diff --git a/ui/app/css/variables/colors.scss b/ui/app/css/design-system/colors.scss similarity index 100% rename from ui/app/css/variables/colors.scss rename to ui/app/css/design-system/colors.scss diff --git a/ui/app/css/design-system/deprecated-colors.scss b/ui/app/css/design-system/deprecated-colors.scss new file mode 100644 index 000000000000..c65f0bfa0100 --- /dev/null +++ b/ui/app/css/design-system/deprecated-colors.scss @@ -0,0 +1,48 @@ +/** + These colors are either deprecated or will move into colors.scss + when approved for the design system +**/ + +// Base Colors +$white: #fff; +$black: #000; +$orange: #ffa500; +$red: #f00; +$gray: #808080; + +/* + Colors + http://chir.ag/projects/name-that-color + */ +$gallery: #efefef; +$wild-sand: #f6f6f6; +$dusty-gray: #9b9b9b; +$alto: #dedede; +$alabaster: #fafafa; +$silver-chalice: #aeaeae; +$tundora: #4d4d4d; +$nile-blue: #1b344d; +$scorpion: #5d5d5d; +$silver: #cdcdcd; +$caribbean-green: #02c9b1; +$monzo: #d0021b; +$crimson: #e91550; +$blue-lagoon: #038789; +$purple: #690496; +$tulip-tree: #ebb33f; +$malibu-blue: #7ac9fd; +$athens-grey: #e9edf0; +$geyser: #d2d8dd; +$manatee: #93949d; +$spindle: #c7ddec; +$mid-gray: #5b5d67; +$cape-cod: #38393a; +$dodger-blue: #3099f2; +$ecstasy: #f7861c; +$linen: #fdf4f4; +$oslo-gray: #8c8e94; +$polar: #fafcfe; +$blizzard-blue: #bfdef3; +$mischka: #dddee9; +$web-orange: #f2a202; +$mercury: #e5e5e5; diff --git a/ui/app/css/design-system/index.scss b/ui/app/css/design-system/index.scss new file mode 100644 index 000000000000..08b0c8b25826 --- /dev/null +++ b/ui/app/css/design-system/index.scss @@ -0,0 +1,4 @@ +@import './colors.scss'; +@import './deprecated-colors.scss'; +@import './typography.scss'; +@import './breakpoints.scss'; diff --git a/ui/app/css/variables/typography.scss b/ui/app/css/design-system/typography.scss similarity index 99% rename from ui/app/css/variables/typography.scss rename to ui/app/css/design-system/typography.scss index 0a51e173833a..37e05faeb87b 100644 --- a/ui/app/css/variables/typography.scss +++ b/ui/app/css/design-system/typography.scss @@ -148,4 +148,3 @@ $font-family: Roboto, Helvetica, Arial, sans-serif; font-family: $font-family; line-height: 140%; } - diff --git a/ui/app/css/index.scss b/ui/app/css/index.scss index d757a2374ed7..9b994f19ab71 100644 --- a/ui/app/css/index.scss +++ b/ui/app/css/index.scss @@ -4,7 +4,9 @@ They are included first because they will be used to replace bad variable names in itcss prior to it being fully removed from the system. */ -@import './variables/index'; +@import './reset.scss'; +@import './design-system/index'; +@import './base-styles.scss'; /* ITCSS @@ -17,7 +19,6 @@ */ @import './itcss/settings/index'; @import './itcss/tools/index'; -@import './itcss/generic/index'; @import './itcss/objects/index'; @import './itcss/components/index'; @import './itcss/trumps/index'; diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss index fa6727ee292d..dec39888414a 100644 --- a/ui/app/css/itcss/settings/variables.scss +++ b/ui/app/css/itcss/settings/variables.scss @@ -1,51 +1,3 @@ -/* - Variables - */ - -// Base Colors -$white: #fff; -$black: #000; -$orange: #ffa500; -$red: #f00; -$gray: #808080; - -/* - Colors - http://chir.ag/projects/name-that-color - */ -$gallery: #efefef; -$wild-sand: #f6f6f6; -$dusty-gray: #9b9b9b; -$alto: #dedede; -$alabaster: #fafafa; -$silver-chalice: #aeaeae; -$tundora: #4d4d4d; -$nile-blue: #1b344d; -$scorpion: #5d5d5d; -$silver: #cdcdcd; -$caribbean-green: #02c9b1; -$monzo: #d0021b; -$crimson: #e91550; -$blue-lagoon: #038789; -$purple: #690496; -$tulip-tree: #ebb33f; -$malibu-blue: #7ac9fd; -$athens-grey: #e9edf0; -$geyser: #d2d8dd; -$manatee: #93949d; -$spindle: #c7ddec; -$mid-gray: #5b5d67; -$cape-cod: #38393a; -$dodger-blue: #3099f2; -$ecstasy: #f7861c; -$linen: #fdf4f4; -$oslo-gray: #8c8e94; -$polar: #fafcfe; -$blizzard-blue: #bfdef3; -$mischka: #dddee9; -$web-orange: #f2a202; -$mercury: #e5e5e5; - /* Z-Indicies */ @@ -98,12 +50,6 @@ $sidebar-overlay-z-index: 25; mascot - 0 - remove? */ -/* - Responsive Breakpoints - */ -$break-small: 575px; -$break-midpoint: 780px; -$break-large: 576px; /* Spacing Variables diff --git a/ui/app/css/itcss/generic/reset.scss b/ui/app/css/reset.scss similarity index 96% rename from ui/app/css/itcss/generic/reset.scss rename to ui/app/css/reset.scss index b60fcd068db1..43146fec8be3 100644 --- a/ui/app/css/itcss/generic/reset.scss +++ b/ui/app/css/reset.scss @@ -88,9 +88,7 @@ video { padding: 0; border: 0; font-size: 100%; - /* stylelint-disable */ font: inherit; - /* stylelint-enable */ vertical-align: baseline; } diff --git a/ui/app/css/variables/index.scss b/ui/app/css/variables/index.scss deleted file mode 100644 index 8d79fd9c7abb..000000000000 --- a/ui/app/css/variables/index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './colors.scss'; -@import './typography.scss'; From 1582855e28916edea1e1d4a16ba147796686141f Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Wed, 29 Jul 2020 10:35:53 -0500 Subject: [PATCH 016/137] Use mixins for typography instead of placeholder selectors (#9072) Using extend would not work inside of some css, namely inside of media queries. This made it a clear choice to use mixins for these styles. --- .../add-to-addressbook-modal/index.scss | 2 +- .../app/modals/new-account-modal/index.scss | 2 +- .../app/permission-page-container/index.scss | 4 +-- .../app/permissions-connect-footer/index.scss | 2 +- .../app/permissions-connect-header/index.scss | 4 +-- ui/app/components/ui/button/buttons.scss | 7 +++--- ui/app/components/ui/list-item/index.scss | 2 +- ui/app/components/ui/popover/index.scss | 4 +-- ui/app/css/design-system/typography.scss | 25 ++++++++++--------- ui/app/css/itcss/components/modal.scss | 3 ++- ui/app/pages/home/index.scss | 2 +- .../choose-account/index.scss | 10 ++++---- ui/app/pages/permissions-connect/index.scss | 4 +-- .../permissions-connect/redirect/index.scss | 2 +- ui/app/pages/send/send.scss | 8 +++--- 15 files changed, 42 insertions(+), 39 deletions(-) diff --git a/ui/app/components/app/modals/add-to-addressbook-modal/index.scss b/ui/app/components/app/modals/add-to-addressbook-modal/index.scss index 64d0f733641d..cb84f30a0379 100644 --- a/ui/app/components/app/modals/add-to-addressbook-modal/index.scss +++ b/ui/app/components/app/modals/add-to-addressbook-modal/index.scss @@ -9,7 +9,7 @@ border-bottom: 1px solid $Grey-100; &__header { - @extend %H3; + @include H3; } } diff --git a/ui/app/components/app/modals/new-account-modal/index.scss b/ui/app/components/app/modals/new-account-modal/index.scss index 97d6210b80c4..bbe4400412d3 100644 --- a/ui/app/components/app/modals/new-account-modal/index.scss +++ b/ui/app/components/app/modals/new-account-modal/index.scss @@ -9,7 +9,7 @@ border-bottom: 1px solid $Grey-100; &__header { - @extend %H4; + @include H4; font-weight: bold; display: flex; diff --git a/ui/app/components/app/permission-page-container/index.scss b/ui/app/components/app/permission-page-container/index.scss index 458eb5b703bd..2e3f10aa8919 100644 --- a/ui/app/components/app/permission-page-container/index.scss +++ b/ui/app/components/app/permission-page-container/index.scss @@ -31,7 +31,7 @@ } &__title { - @extend %H4; + @include H4; line-height: 25px; text-align: center; @@ -84,7 +84,7 @@ } &__permissions-header { - @extend %H6; + @include H6; line-height: 20px; color: #6a737d; diff --git a/ui/app/components/app/permissions-connect-footer/index.scss b/ui/app/components/app/permissions-connect-footer/index.scss index 229da218a389..51ee8a09fc57 100644 --- a/ui/app/components/app/permissions-connect-footer/index.scss +++ b/ui/app/components/app/permissions-connect-footer/index.scss @@ -5,7 +5,7 @@ align-items: center; &__text { - @extend %H7; + @include H7; line-height: 17px; color: #6a737d; diff --git a/ui/app/components/app/permissions-connect-header/index.scss b/ui/app/components/app/permissions-connect-header/index.scss index ca8d4c0e6c4f..1ec0628e053a 100644 --- a/ui/app/components/app/permissions-connect-header/index.scss +++ b/ui/app/components/app/permissions-connect-header/index.scss @@ -26,7 +26,7 @@ } &__title { - @extend %H3; + @include H3; text-align: center; color: $Black-100; @@ -35,7 +35,7 @@ &__text, &__subtitle { - @extend %H6; + @include H6; text-align: center; color: $Grey-500; diff --git a/ui/app/components/ui/button/buttons.scss b/ui/app/components/ui/button/buttons.scss index 83f02f7e0ba8..693deec26ea7 100644 --- a/ui/app/components/ui/button/buttons.scss +++ b/ui/app/components/ui/button/buttons.scss @@ -11,7 +11,7 @@ $hover-orange: #ffd3b5; $warning-light-orange: #f8b588; %button { - @extend %H6; + @include H6; font-weight: 500; font-family: Roboto, Arial; @@ -34,7 +34,7 @@ $warning-light-orange: #f8b588; } %link { - @extend %H4; + @include H4; color: $Blue-500; line-height: 1.25rem; @@ -60,7 +60,8 @@ $warning-light-orange: #f8b588; %small-link { @extend %link; - @extend %H6; + + @include H6; } .button { diff --git a/ui/app/components/ui/list-item/index.scss b/ui/app/components/ui/list-item/index.scss index cc9edd87fe7e..2117dfc4d931 100644 --- a/ui/app/components/ui/list-item/index.scss +++ b/ui/app/components/ui/list-item/index.scss @@ -5,7 +5,7 @@ background: #fff; padding: 24px 16px; - @extend %Paragraph; + @include Paragraph; border-top: 1px solid $mercury; border-bottom: 1px solid $mercury; diff --git a/ui/app/components/ui/popover/index.scss b/ui/app/components/ui/popover/index.scss index af3d7b279dcf..a1ef85b06df5 100644 --- a/ui/app/components/ui/popover/index.scss +++ b/ui/app/components/ui/popover/index.scss @@ -33,7 +33,7 @@ align-items: center; justify-content: space-between; - @extend %H4; + @include H4; font-weight: bold; line-height: 25px; @@ -51,7 +51,7 @@ } &__subtitle { - @extend %H6; + @include H6; line-height: 20px; } diff --git a/ui/app/css/design-system/typography.scss b/ui/app/css/design-system/typography.scss index 37e05faeb87b..8c37bcea7f31 100644 --- a/ui/app/css/design-system/typography.scss +++ b/ui/app/css/design-system/typography.scss @@ -70,7 +70,7 @@ $fa-font-path: 'fonts/fontawesome'; $font-family: Roboto, Helvetica, Arial, sans-serif; // Typography -%H1 { +@mixin H1 { font-style: normal; font-weight: normal; font-size: 2.5rem; @@ -78,7 +78,8 @@ $font-family: Roboto, Helvetica, Arial, sans-serif; line-height: 140%; } -%H2 { + +@mixin H2 { font-style: normal; font-weight: normal; font-size: 2rem; @@ -86,7 +87,7 @@ $font-family: Roboto, Helvetica, Arial, sans-serif; line-height: 140%; } -%H3 { +@mixin H3 { font-style: normal; font-weight: normal; font-size: 1.5rem; @@ -94,7 +95,7 @@ $font-family: Roboto, Helvetica, Arial, sans-serif; line-height: 140%; } -%H4 { +@mixin H4 { font-style: normal; font-weight: normal; font-size: 1.125rem; @@ -102,7 +103,7 @@ $font-family: Roboto, Helvetica, Arial, sans-serif; line-height: 140%; } -%H5 { +@mixin H5 { font-style: normal; font-weight: normal; font-size: 1rem; @@ -110,14 +111,14 @@ $font-family: Roboto, Helvetica, Arial, sans-serif; line-height: 140%; } -%H6 { +@mixin H6 { font-style: normal; font-weight: normal; - font-size: 0.875rem; - font-family: $font-family; + font-size: 0.875rem; // 14px @default + line-height: 140%; } -%Paragraph { +@mixin Paragraph { font-style: normal; font-weight: normal; font-size: 1rem; @@ -125,7 +126,7 @@ $font-family: Roboto, Helvetica, Arial, sans-serif; line-height: 140%; } -%H7 { +@mixin H7 { font-style: normal; font-weight: normal; font-size: 0.75rem; @@ -133,7 +134,7 @@ $font-family: Roboto, Helvetica, Arial, sans-serif; line-height: 140%; } -%H8 { +@mixin H8 { font-style: normal; font-weight: normal; font-size: 0.625rem; @@ -141,7 +142,7 @@ $font-family: Roboto, Helvetica, Arial, sans-serif; line-height: 140%; } -%H9 { +@mixin H9 { font-style: normal; font-weight: normal; font-size: 0.5rem; diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index 3e804498968e..a192f20f1c20 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -287,7 +287,8 @@ } &__button { - @extend %Paragraph; + @include Paragraph; + @extend %button; width: 141px; diff --git a/ui/app/pages/home/index.scss b/ui/app/pages/home/index.scss index 37911bdc6c6d..4d4926e86f07 100644 --- a/ui/app/pages/home/index.scss +++ b/ui/app/pages/home/index.scss @@ -43,7 +43,7 @@ display: flex; flex-direction: column; - @extend %H6; + @include H6; padding-left: 24px; padding-right: 24px; diff --git a/ui/app/pages/permissions-connect/choose-account/index.scss b/ui/app/pages/permissions-connect/choose-account/index.scss index b79c9c923bd2..bb4b05a42933 100644 --- a/ui/app/pages/permissions-connect/choose-account/index.scss +++ b/ui/app/pages/permissions-connect/choose-account/index.scss @@ -24,13 +24,13 @@ &__title { - @extend %H4; + @include H4; } &__text, &__text-blue, &__text-grey { - @extend %H6; + @include H6; } &__text-blue { @@ -120,7 +120,7 @@ } &__label { - @extend %H6; + @include H6; color: $Black-100; text-overflow: ellipsis; @@ -129,13 +129,13 @@ } &__balance { - @extend %H7; + @include H7; color: $Grey-500; } &__last-connected { - @extend %H8; + @include H8; display: flex; flex-direction: column; diff --git a/ui/app/pages/permissions-connect/index.scss b/ui/app/pages/permissions-connect/index.scss index 58263d9b489f..eb6b14dbf2b2 100644 --- a/ui/app/pages/permissions-connect/index.scss +++ b/ui/app/pages/permissions-connect/index.scss @@ -24,7 +24,7 @@ } &__back { - @extend %H6; + @include H6; color: $Grey-600; cursor: pointer; @@ -35,7 +35,7 @@ } &__page-count { - @extend %H7; + @include H7; color: #6a737d; grid-column: 2; diff --git a/ui/app/pages/permissions-connect/redirect/index.scss b/ui/app/pages/permissions-connect/redirect/index.scss index 2151385ed1c4..fa90ca0c1cc4 100644 --- a/ui/app/pages/permissions-connect/redirect/index.scss +++ b/ui/app/pages/permissions-connect/redirect/index.scss @@ -4,7 +4,7 @@ justify-content: center; &__result { - @extend %H3; + @include H3; position: absolute; top: 30%; diff --git a/ui/app/pages/send/send.scss b/ui/app/pages/send/send.scss index eb64a4105679..81de75a853da 100644 --- a/ui/app/pages/send/send.scss +++ b/ui/app/pages/send/send.scss @@ -6,7 +6,7 @@ padding: 14px 0 3px 0; .page-container__title { - @extend %H4; + @include H4; text-align: center; } @@ -91,7 +91,7 @@ } &__group-label { - @extend %H8; + @include H8; background-color: $Grey-000; color: $Grey-600; @@ -136,7 +136,7 @@ } &__subtitle { - @extend %H8; + @include H8; color: $Grey-500; } @@ -186,7 +186,7 @@ } &__input { - @extend %H6; + @include H6; flex: 1 1 auto; width: 0; From b7715f6e7011ca73f69c5b1705148ed6e4bedb76 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 29 Jul 2020 13:09:52 -0300 Subject: [PATCH 017/137] Only log error on first occurrence of missing substitution (#9096) A missing substitution for a localized message will now only log an error upon the first occurrence. Further errors are generally not useful. --- ui/app/helpers/utils/i18n-helper.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ui/app/helpers/utils/i18n-helper.js b/ui/app/helpers/utils/i18n-helper.js index a32120b4f71d..7fccc92cbf83 100644 --- a/ui/app/helpers/utils/i18n-helper.js +++ b/ui/app/helpers/utils/i18n-helper.js @@ -6,6 +6,7 @@ import * as Sentry from '@sentry/browser' const warned = {} const missingMessageErrors = {} +const missingSubstitutionErrors = {} /** * Returns a localized message for the given key @@ -55,7 +56,11 @@ export const getMessage = (localeCode, localeMessages, key, substitutions) => { return part } const substituteIndex = Number(subMatch[1]) - 1 - if (substitutions[substituteIndex] == null) { + if (substitutions[substituteIndex] == null && !missingSubstitutionErrors[localeCode]?.[key]) { + if (!missingSubstitutionErrors[localeCode]) { + missingSubstitutionErrors[localeCode] = {} + } + missingSubstitutionErrors[localeCode][key] = true const error = new Error(`Insufficient number of substitutions for message: '${phrase}'`) log.error(error) Sentry.captureException(error) From d7a5319222d597a6470aab8fd566a30f31f70f96 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 29 Jul 2020 13:14:08 -0300 Subject: [PATCH 018/137] Use environment variable for production Sentry DSN (#9097) The Sentry DSN is now expected to be provided via environment variable for production builds. The build script will fail if it is missing, and an error will be thrown at runtime if it is missing. The `SENTRY_DSN` environment variable has been set in CI to the old value for `SENTRY_PROD_DSN`. We can migrate to a new DSN at some point in the future. --- app/scripts/lib/setupSentry.js | 12 +++++++----- development/build/scripts.js | 5 +++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 9eca2ef5b23e..a6d1bb9b2b2b 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -5,7 +5,6 @@ import extractEthjsErrorMessage from './extractEthjsErrorMessage' const METAMASK_DEBUG = process.env.METAMASK_DEBUG const METAMASK_ENVIRONMENT = process.env.METAMASK_ENVIRONMENT -const SENTRY_DSN_PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505' const SENTRY_DSN_DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' // This describes the subset of Redux state attached to errors sent to Sentry @@ -74,12 +73,15 @@ export default function setupSentry ({ release, getState }) { if (METAMASK_DEBUG) { return - } else if (process.env.IN_TEST) { + } else if (METAMASK_ENVIRONMENT === 'production') { + if (!process.env.SENTRY_DSN) { + throw new Error(`Missing SENTRY_DSN environment variable in production environment`) + } + console.log(`Setting up Sentry Remote Error Reporting for '${METAMASK_ENVIRONMENT}': SENTRY_DSN`) + sentryTarget = process.env.SENTRY_DSN + } else { console.log(`Setting up Sentry Remote Error Reporting for '${METAMASK_ENVIRONMENT}': SENTRY_DSN_DEV`) sentryTarget = SENTRY_DSN_DEV - } else { - console.log(`Setting up Sentry Remote Error Reporting for '${METAMASK_ENVIRONMENT}': SENTRY_DSN_PROD`) - sentryTarget = SENTRY_DSN_PROD } Sentry.init({ diff --git a/development/build/scripts.js b/development/build/scripts.js index 2ce9b86a0877..8a6b4911113f 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -330,6 +330,10 @@ function createScriptTasks ({ browserPlatforms, livereload }) { environment = 'other' } + if (environment === 'production' && !process.env.SENTRY_DSN) { + throw new Error('Missing SENTRY_DSN environment variable') + } + // Inject variables into bundle bundler.transform(envify({ METAMASK_DEBUG: opts.devMode, @@ -341,6 +345,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) { PUBNUB_PUB_KEY: process.env.PUBNUB_PUB_KEY || '', ETH_GAS_STATION_API_KEY: process.env.ETH_GAS_STATION_API_KEY || '', CONF: opts.devMode ? conf : ({}), + SENTRY_DSN: process.env.SENTRY_DSN, }), { global: true, }) From a3cad5d52e15cdbe8de9c90369927ab2e64a7ee8 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Wed, 29 Jul 2020 12:56:24 -0700 Subject: [PATCH 019/137] rpc-cap@3.1.0 (#9103) --- package.json | 2 +- yarn.lock | 83 +++++++++++++++++++++++----------------------------- 2 files changed, 38 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index cafe5bc84018..f26a98e85fb2 100644 --- a/package.json +++ b/package.json @@ -157,7 +157,7 @@ "redux": "^4.0.5", "redux-thunk": "^2.3.0", "reselect": "^3.0.1", - "rpc-cap": "^3.0.1", + "rpc-cap": "^3.1.0", "safe-event-emitter": "^1.0.1", "safe-json-stringify": "^1.2.0", "single-call-balance-checker-abi": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index 83d52e6c2814..eae41c1f7afb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1714,6 +1714,34 @@ web3 "^0.20.7" web3-provider-engine "^15.0.4" +"@metamask/controllers@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-2.0.2.tgz#100a5d87b6061751b39edec2288f16f07d471e2d" + integrity sha512-KKxNguTEdkzwvfv2Hl4BE2OMGULLeh7df6iAwcEG8ipXWbTWGZsLr13DBrczQxRi8TiNPaksAakv++6sMu6ngA== + dependencies: + await-semaphore "^0.1.3" + eth-contract-metadata "^1.11.0" + eth-ens-namehash "^2.0.8" + eth-json-rpc-errors "^2.0.2" + eth-json-rpc-infura "^4.0.1" + eth-keyring-controller "^5.6.1" + eth-method-registry "1.1.0" + eth-phishing-detect "^1.1.13" + eth-query "^2.1.2" + eth-sig-util "^2.3.0" + ethereumjs-util "^6.1.0" + ethereumjs-wallet "0.6.0" + ethjs-query "^0.3.8" + human-standard-collectible-abi "^1.0.2" + human-standard-token-abi "^2.0.0" + isomorphic-fetch "^2.2.1" + jsonschema "^1.2.4" + percentile "^1.2.1" + single-call-balance-checker-abi "^1.0.0" + uuid "^3.3.2" + web3 "^0.20.7" + web3-provider-engine "^15.0.4" + "@metamask/eslint-config@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-1.1.0.tgz#03c6fbec8ba3d95fa017d8b98ab5d0701f7458a4" @@ -10116,7 +10144,7 @@ eth-json-rpc-middleware@^5.0.2: pify "^3.0.0" safe-event-emitter "^1.0.1" -eth-keyring-controller@^5.3.0, eth-keyring-controller@^5.6.1: +eth-keyring-controller@^5.6.1: version "5.6.1" resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-5.6.1.tgz#7b7268400704c8f5ce98a055910341177dd207ca" integrity sha512-sxJ87bJg7PvvPzj1sY1jJYHQL1HVUhh84Q/a4QPrcnzAAng1yibvvUfww0pCez4XJfHuMkJvUxfF8eAusJM8fQ== @@ -12040,34 +12068,6 @@ fuse.js@^3.4.6: resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.6.tgz#545c3411fed88bf2e27c457cab6e73e7af697a45" integrity sha512-H6aJY4UpLFwxj1+5nAvufom5b2BT2v45P1MkPvdGIK8fWjQx/7o6tTT1+ALV0yawQvbmvCF0ufl2et8eJ7v7Cg== -gaba@^1.9.3: - version "1.11.0" - resolved "https://registry.yarnpkg.com/gaba/-/gaba-1.11.0.tgz#7ff49cad2f2b95941222121a1984bb63783fe076" - integrity sha512-rQcLgR/FHQ8W6oNza/vxFnkbav0vgauBxm6LKqK6BkbjJGB979qoBRVja9fU/H5dUMiYmHJO9CrHjL0ofG/ukA== - dependencies: - await-semaphore "^0.1.3" - eth-contract-metadata "^1.11.0" - eth-ens-namehash "^2.0.8" - eth-json-rpc-errors "^2.0.2" - eth-json-rpc-infura "^4.0.1" - eth-keyring-controller "^5.3.0" - eth-method-registry "1.1.0" - eth-phishing-detect "^1.1.13" - eth-query "^2.1.2" - eth-sig-util "^2.3.0" - ethereumjs-util "^6.1.0" - ethereumjs-wallet "0.6.0" - ethjs-query "^0.3.8" - human-standard-collectible-abi "^1.0.2" - human-standard-token-abi "^2.0.0" - isomorphic-fetch "^2.2.1" - jsonschema "^1.2.4" - percentile "^1.2.1" - single-call-balance-checker-abi "^1.0.0" - uuid "^3.3.2" - web3 "^0.20.7" - web3-provider-engine "^15.0.4" - ganache-cli@^6.9.1: version "6.9.1" resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.9.1.tgz#1e13eee098fb9f19b031a191ec3f62ae926ea8b3" @@ -14046,11 +14046,6 @@ interpret@^2.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.0.0.tgz#b783ffac0b8371503e9ab39561df223286aa5433" integrity sha512-e0/LknJ8wpMMhTiWcjivB+ESwIuvHnBSlBbmP/pSb8CQJldoj1p2qv7xGZ/+BtbTziYRFSz8OsvdbiX45LtYQA== -intersect-objects@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/intersect-objects/-/intersect-objects-1.0.0.tgz#b7630d28994b89b0f04d44728106136549ce816e" - integrity sha512-MS1xypHKJhWopnJgn4IbitVvt2vFy2KjINQJAPhAtDejZ+ZbMDfyPc6JsS/mWFRt9Eoku4A4usE4f2loEOoeKQ== - into-stream@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" @@ -15755,7 +15750,7 @@ json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: promise-to-callback "^1.0.0" safe-event-emitter "^1.0.1" -json-rpc-engine@^5.1.3, json-rpc-engine@^5.1.5, json-rpc-engine@^5.1.8: +json-rpc-engine@^5.1.3, json-rpc-engine@^5.1.5: version "5.1.8" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.1.8.tgz#5ba0147ce571899bbaa7133ffbc05317c34a3c7f" integrity sha512-vTBSDEPJV1fPAsbm2g5sEuPjsgLdiab2f1CTn2PyRr8nxggUpA996PDlNQDsM0gnrA99F8KIBLq2nIKrOFl1Mg== @@ -23363,19 +23358,15 @@ rn-host-detect@^1.1.5: resolved "https://registry.yarnpkg.com/rn-host-detect/-/rn-host-detect-1.1.5.tgz#fbecb982b73932f34529e97932b9a63e58d8deb6" integrity sha512-ufk2dFT3QeP9HyZ/xTuMtW27KnFy815CYitJMqQm+pgG3ZAtHBsrU8nXizNKkqXGy3bQmhEoloVbrfbvMJMqkg== -rpc-cap@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/rpc-cap/-/rpc-cap-3.0.1.tgz#127fdc37563736f3e15c4550af31f6866490dd85" - integrity sha512-egeRnp+QVennA3obsOhVi/XhNSR4qQk8LHu0YFBiEpUHcm+68FqBkjvx0U/3CSXBmrRc8WRLo6kE3T64gWW02w== +rpc-cap@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/rpc-cap/-/rpc-cap-3.1.0.tgz#61ae8ca27c43da93f40972393ff34df1a28c3b5e" + integrity sha512-DyvT8xJEJVqdWP+fJ4VCI+q+sG30eOhAgaAczZ7/13ah8mtcl2pv4d5MffmTg8kJM4EId2eEExTVhBG8wgaomg== dependencies: - clone "^2.1.2" - eth-json-rpc-errors "^2.0.2" - fast-deep-equal "^2.0.1" - gaba "^1.9.3" - intersect-objects "^1.0.0" + "@metamask/controllers" "^2.0.2" + eth-rpc-errors "^2.1.1" is-subset "^0.1.1" - json-rpc-engine "^5.1.8" - obs-store "^4.0.3" + json-rpc-engine "^5.2.0" uuid "^3.3.2" rsa-pem-to-jwk@^1.1.3: From 46ba1ef1008d5111924132229c281a449ea1a13a Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Wed, 29 Jul 2020 15:04:02 -0500 Subject: [PATCH 020/137] Update font family globally (#9073) --- .../gas-customization/gas-price-chart/index.scss | 2 -- .../components/app/home-notification/index.scss | 2 -- .../components/app/signature-request/index.scss | 2 -- .../signature-request-message/index.scss | 2 -- ui/app/components/ui/button-group/index.scss | 1 - ui/app/components/ui/button/buttons.scss | 2 -- ui/app/components/ui/dropdown/dropdown.scss | 1 - ui/app/components/ui/menu/menu.scss | 2 -- ui/app/components/ui/toggle-button/index.scss | 1 - ui/app/components/ui/unit-input/index.scss | 1 - ui/app/css/base-styles.scss | 6 +++++- ui/app/css/design-system/typography.scss | 2 +- ui/app/css/itcss/components/account-dropdown.scss | 6 ------ ui/app/css/itcss/components/confirm.scss | 6 ------ ui/app/css/itcss/components/currency-display.scss | 4 ---- ui/app/css/itcss/components/modal.scss | 14 -------------- ui/app/css/itcss/components/network.scss | 3 --- ui/app/css/itcss/components/new-account.scss | 10 ---------- ui/app/css/itcss/components/newui-sections.scss | 2 -- .../itcss/components/request-decrypt-message.scss | 4 ---- .../components/request-encryption-public-key.scss | 4 ---- .../css/itcss/components/request-signature.scss | 7 ------- ui/app/css/itcss/components/sections.scss | 5 ----- ui/app/css/itcss/components/send.scss | 15 --------------- ui/app/css/itcss/components/tooltip.scss | 1 - ui/app/css/itcss/components/transaction-list.scss | 2 -- ui/app/css/reset.scss | 6 +++++- .../confirm-approve-content/index.scss | 2 -- ui/app/pages/error/index.scss | 1 - .../pages/first-time-flow/end-of-flow/index.scss | 1 - ui/app/pages/first-time-flow/index.scss | 2 -- .../first-time-flow/metametrics-opt-in/index.scss | 2 -- .../first-time-flow/select-action/index.scss | 3 --- ui/app/pages/keychains/index.scss | 5 ----- ui/app/pages/settings/contact-list-tab/index.scss | 3 --- ui/app/pages/settings/index.scss | 1 - ui/app/pages/settings/networks-tab/index.scss | 2 -- 37 files changed, 11 insertions(+), 124 deletions(-) diff --git a/ui/app/components/app/gas-customization/gas-price-chart/index.scss b/ui/app/components/app/gas-customization/gas-price-chart/index.scss index a26b477a029a..774760cffd7c 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/index.scss +++ b/ui/app/components/app/gas-customization/gas-price-chart/index.scss @@ -17,7 +17,6 @@ .tick text, .c3-axis-x-label, .c3-axis-y-label { - font-family: Roboto; font-style: normal; font-weight: bold; line-height: normal; @@ -53,7 +52,6 @@ } .custom-tooltip th { - font-family: Roboto; font-style: normal; font-weight: 500; line-height: normal; diff --git a/ui/app/components/app/home-notification/index.scss b/ui/app/components/app/home-notification/index.scss index 1aedb90ec3cd..56222b454adb 100644 --- a/ui/app/components/app/home-notification/index.scss +++ b/ui/app/components/app/home-notification/index.scss @@ -35,7 +35,6 @@ } &__text { - font-family: Roboto, 'sans-serif'; font-style: normal; font-weight: normal; font-size: 12px; @@ -112,7 +111,6 @@ } &__content { - font-family: Roboto, 'sans-serif'; font-style: normal; font-weight: normal; font-size: 12px; diff --git a/ui/app/components/app/signature-request/index.scss b/ui/app/components/app/signature-request/index.scss index 27e7fcfbc821..4de4f249b9ac 100644 --- a/ui/app/components/app/signature-request/index.scss +++ b/ui/app/components/app/signature-request/index.scss @@ -38,7 +38,6 @@ min-height: min-content; &__title { - font-family: Roboto; font-style: normal; font-weight: 500; font-size: 18px; @@ -65,7 +64,6 @@ &__identicon-initial { position: absolute; - font-family: Roboto; font-style: normal; font-weight: 500; font-size: 60px; diff --git a/ui/app/components/app/signature-request/signature-request-message/index.scss b/ui/app/components/app/signature-request/signature-request-message/index.scss index 7eef17560fdd..37c0fba7250c 100644 --- a/ui/app/components/app/signature-request/signature-request-message/index.scss +++ b/ui/app/components/app/signature-request/signature-request-message/index.scss @@ -28,7 +28,6 @@ padding-left: 12px; padding-right: 12px; width: 360px; - font-family: monospace; @media screen and (min-width: 576px) { width: auto; @@ -36,7 +35,6 @@ } &__type-title { - font-family: monospace; font-style: normal; font-weight: normal; font-size: 14px; diff --git a/ui/app/components/ui/button-group/index.scss b/ui/app/components/ui/button-group/index.scss index aea6d826f8c2..4ba758c30331 100644 --- a/ui/app/components/ui/button-group/index.scss +++ b/ui/app/components/ui/button-group/index.scss @@ -4,7 +4,6 @@ align-items: center; &__button { - font-family: Roboto; font-size: 1rem; color: $tundora; border-style: solid; diff --git a/ui/app/components/ui/button/buttons.scss b/ui/app/components/ui/button/buttons.scss index 693deec26ea7..0e38c049cd61 100644 --- a/ui/app/components/ui/button/buttons.scss +++ b/ui/app/components/ui/button/buttons.scss @@ -14,7 +14,6 @@ $warning-light-orange: #f8b588; @include H6; font-weight: 500; - font-family: Roboto, Arial; line-height: 1.25rem; padding: 0.75rem 1rem; display: flex; @@ -249,7 +248,6 @@ button.primary { box-shadow: 0 3px 6px rgba(247, 134, 28, 0.36); color: $white; font-size: 1.1em; - font-family: Roboto; text-transform: uppercase; } diff --git a/ui/app/components/ui/dropdown/dropdown.scss b/ui/app/components/ui/dropdown/dropdown.scss index 296ea95c03cf..49a684bb7ce3 100644 --- a/ui/app/components/ui/dropdown/dropdown.scss +++ b/ui/app/components/ui/dropdown/dropdown.scss @@ -11,7 +11,6 @@ background-position: right 18px top 50%; background-color: white; padding: 8px 32px 8px 16px; - font-family: Roboto, 'sans-serif'; font-size: 14px; [dir='rtl'] & { diff --git a/ui/app/components/ui/menu/menu.scss b/ui/app/components/ui/menu/menu.scss index de3935539814..a34deda532d7 100644 --- a/ui/app/components/ui/menu/menu.scss +++ b/ui/app/components/ui/menu/menu.scss @@ -9,7 +9,6 @@ flex-direction: column; align-items: center; padding: 0 16px; - font-family: Roboto, 'sans-serif'; font-size: 14px; font-weight: normal; line-height: 20px; @@ -28,7 +27,6 @@ .menu-item { background: none; - font-family: inherit; font-size: inherit; display: grid; grid-template-columns: min-content auto; diff --git a/ui/app/components/ui/toggle-button/index.scss b/ui/app/components/ui/toggle-button/index.scss index cdd99f7f7ead..09827888cd2d 100644 --- a/ui/app/components/ui/toggle-button/index.scss +++ b/ui/app/components/ui/toggle-button/index.scss @@ -3,7 +3,6 @@ $self: &; &__status { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 16px; diff --git a/ui/app/components/ui/unit-input/index.scss b/ui/app/components/ui/unit-input/index.scss index ed80f26ac315..c86f487b5cef 100644 --- a/ui/app/components/ui/unit-input/index.scss +++ b/ui/app/components/ui/unit-input/index.scss @@ -36,7 +36,6 @@ &__input { color: #4d4d4d; font-size: 1rem; - font-family: Roboto; border: none; max-width: 22ch; height: 16px; diff --git a/ui/app/css/base-styles.scss b/ui/app/css/base-styles.scss index 1e17639f7461..6a970f9a3a11 100644 --- a/ui/app/css/base-styles.scss +++ b/ui/app/css/base-styles.scss @@ -6,7 +6,6 @@ html, body { - font-family: Roboto, Arial; color: #4d4d4d; width: 100%; height: 100%; @@ -107,3 +106,8 @@ input.form-control { } } +/** Default Typography on base elements **/ +* { + font-family: $font-family; +} + diff --git a/ui/app/css/design-system/typography.scss b/ui/app/css/design-system/typography.scss index 8c37bcea7f31..70cc4bef44ad 100644 --- a/ui/app/css/design-system/typography.scss +++ b/ui/app/css/design-system/typography.scss @@ -67,7 +67,7 @@ $fa-font-path: 'fonts/fontawesome'; src: url('fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf') format('truetype'); } -$font-family: Roboto, Helvetica, Arial, sans-serif; +$font-family: Euclid, Roboto, Helvetica, Arial, sans-serif; // Typography @mixin H1 { diff --git a/ui/app/css/itcss/components/account-dropdown.scss b/ui/app/css/itcss/components/account-dropdown.scss index 1d7baf7b6cb9..3d2e29b42dbf 100644 --- a/ui/app/css/itcss/components/account-dropdown.scss +++ b/ui/app/css/itcss/components/account-dropdown.scss @@ -1,7 +1,3 @@ -.account-dropdown-name { - font-family: Roboto; -} - .account-dropdown-balance { color: $dusty-gray; line-height: 19px; @@ -9,7 +5,6 @@ .account-dropdown-edit-button { color: $dusty-gray; - font-family: Roboto; &:hover { color: $white; @@ -69,7 +64,6 @@ &__account-primary-balance, &__account-secondary-balance { - font-family: Roboto; line-height: 16px; font-size: 12px; } diff --git a/ui/app/css/itcss/components/confirm.scss b/ui/app/css/itcss/components/confirm.scss index 7a034e4e9174..b382bcae608e 100644 --- a/ui/app/css/itcss/components/confirm.scss +++ b/ui/app/css/itcss/components/confirm.scss @@ -1,7 +1,6 @@ .confirm-screen-container { position: relative; align-items: center; - font-family: Roboto; flex: 1 0 auto; flex-flow: column nowrap; box-shadow: 0 2px 4px 0 rgba($black, 0.08); @@ -30,7 +29,6 @@ flex-flow: column nowrap; z-index: 25; align-items: center; - font-family: Roboto; position: relative; overflow-y: auto; overflow-x: hidden; @@ -99,7 +97,6 @@ .confirm-screen-back-button { color: $primary-blue; - font-family: Roboto; font-size: 1rem; position: absolute; top: 38px; @@ -162,7 +159,6 @@ text-align: center; font-size: 16px; margin-top: 30px; - font-family: Roboto; font-weight: 300; } @@ -324,7 +320,6 @@ section .confirm-screen-account-number, font-size: 16px; color: $white; text-align: center; - font-family: Roboto; padding-top: 15px; padding-bottom: 15px; border-width: 0; @@ -338,7 +333,6 @@ section .confirm-screen-account-number, background: none; border: none; opacity: 1; - font-family: Roboto; border-width: 0; padding-top: 15px; padding-bottom: 15px; diff --git a/ui/app/css/itcss/components/currency-display.scss b/ui/app/css/itcss/components/currency-display.scss index 9ece7a6721c2..b8a23d06b13d 100644 --- a/ui/app/css/itcss/components/currency-display.scss +++ b/ui/app/css/itcss/components/currency-display.scss @@ -4,7 +4,6 @@ border-radius: 4px; background-color: $white; color: $scorpion; - font-family: Roboto; font-size: 16px; padding: 8px 10px; position: relative; @@ -15,7 +14,6 @@ &__input { color: $scorpion; - font-family: Roboto; font-size: 16px; line-height: 22px; border: none; @@ -25,7 +23,6 @@ &__primary-currency { color: $scorpion; font-weight: 400; - font-family: Roboto; font-size: 16px; line-height: 22px; } @@ -37,7 +34,6 @@ &__converted-value, &__converted-currency { color: $dusty-gray; - font-family: Roboto; font-size: 12px; line-height: 12px; } diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index a192f20f1c20..318cfb1ee91c 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -39,7 +39,6 @@ padding: 5px 0 31px 0; border: 1px solid $silver; border-radius: 4px; - font-family: Roboto; button { cursor: pointer; @@ -55,7 +54,6 @@ &__text { margin-top: 2px; - font-family: Roboto; font-size: 14px; line-height: 18px; } @@ -101,7 +99,6 @@ justify-content: center; border: 1px solid $alto; padding: 5px 10px; - font-family: Roboto; margin-top: 7px; width: 286px; } @@ -166,7 +163,6 @@ .private-key-password::-webkit-input-placeholder { color: $dusty-gray; - font-family: Roboto; } .private-key-password-warning { @@ -179,7 +175,6 @@ width: 292px; padding: 9px 15px; margin-top: 18px; - font-family: Roboto; } .export-private-key-buttons { @@ -207,7 +202,6 @@ .private-key-password-display-textarea { color: $crimson; - font-family: Roboto; font-size: 16px; line-height: 21px; border: none; @@ -225,7 +219,6 @@ position: absolute; top: 25px; right: 17.5px; - font-family: sans-serif; cursor: pointer; } @@ -250,7 +243,6 @@ &__symbol { color: $tundora; - font-family: Roboto; font-size: 16px; line-height: 24px; text-align: center; @@ -261,7 +253,6 @@ height: 30px; width: 271.28px; color: $tundora; - font-family: Roboto; font-size: 22px; line-height: 30px; text-align: center; @@ -272,7 +263,6 @@ height: 41px; width: 318px; color: $scorpion; - font-family: Roboto; font-size: 14px; line-height: 18px; text-align: center; @@ -307,7 +297,6 @@ position: relative; border: 1px solid $alto; box-shadow: 0 0 2px 2px $alto; - font-family: Roboto; } &__header { @@ -349,7 +338,6 @@ // Deposit Ether Modal .deposit-ether-modal { border-radius: 8px; - font-family: Roboto; display: flex; flex-flow: column; height: 100%; @@ -503,7 +491,6 @@ width: 100%; height: 45px; line-height: 44px; - font-family: Roboto; font-weight: 300; } @@ -522,7 +509,6 @@ position: relative; border: 1px solid $alto; box-shadow: 0 0 2px 2px $alto; - font-family: Roboto; } .notification-modal-header { diff --git a/ui/app/css/itcss/components/network.scss b/ui/app/css/itcss/components/network.scss index 02d0dcfcd35f..ef8e7843ff86 100644 --- a/ui/app/css/itcss/components/network.scss +++ b/ui/app/css/itcss/components/network.scss @@ -66,7 +66,6 @@ .network-name { padding: 0 4px; - font-family: Roboto; font-size: 12px; line-height: 14px; flex: 1 1 auto; @@ -168,7 +167,6 @@ height: 25px; width: 120px; color: $white; - font-family: Roboto; font-size: 18px; line-height: 25px; text-align: center; @@ -178,7 +176,6 @@ min-height: 36px; width: 265px; color: $dusty-gray; - font-family: Roboto; font-size: 14px; line-height: 18px; } diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 77fd07afa104..c7aa38e035ca 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -23,7 +23,6 @@ &__title { color: $tundora; - font-family: Roboto; font-size: 32px; font-weight: 500; line-height: 43px; @@ -40,7 +39,6 @@ height: 54px; padding: 15px 10px; color: $dusty-gray; - font-family: Roboto; font-size: 18px; line-height: 24px; text-align: center; @@ -87,7 +85,6 @@ &__select-label { color: $scorpion; - font-family: Roboto; font-size: 16px; line-height: 21px; } @@ -123,7 +120,6 @@ &__instruction { color: $scorpion; - font-family: Roboto; font-size: 16px; line-height: 21px; align-self: flex-start; @@ -144,7 +140,6 @@ background-color: $white; margin-top: 16px; color: $scorpion; - font-family: Roboto; font-size: 16px; padding: 0 20px; } @@ -364,7 +359,6 @@ margin-bottom: 23px; align-self: flex-start; color: $scorpion; - font-family: Roboto; font-size: 16px; line-height: 21px; font-weight: bold; @@ -376,7 +370,6 @@ margin-bottom: 23px; align-self: flex-end; color: $scorpion; - font-family: Roboto; font-size: 16px; line-height: 21px; font-weight: normal; @@ -461,7 +454,6 @@ margin-left: 16px; padding: 0; text-transform: uppercase; - font-family: Roboto; } } @@ -520,7 +512,6 @@ &__input-label { color: $scorpion; - font-family: Roboto; font-size: 16px; line-height: 21px; align-self: flex-start; @@ -533,7 +524,6 @@ border-radius: 4px; background-color: $white; color: $scorpion; - font-family: Roboto; font-size: 16px; line-height: 21px; margin-top: 15px; diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss index 2572c5fa40e0..57c1f6d77085 100644 --- a/ui/app/css/itcss/components/newui-sections.scss +++ b/ui/app/css/itcss/components/newui-sections.scss @@ -17,7 +17,6 @@ $sub-mid-size-breakpoint-range: "screen and (min-width: #{$break-large}) and (ma // Main container .main-container { z-index: $main-container-z-index; - font-family: Roboto; } .main-container::-webkit-scrollbar { @@ -120,7 +119,6 @@ $sub-mid-size-breakpoint-range: "screen and (min-width: #{$break-large}) and (ma .unlock-screen-container { z-index: $main-container-z-index; - font-family: Roboto; display: flex; justify-content: center; align-items: center; diff --git a/ui/app/css/itcss/components/request-decrypt-message.scss b/ui/app/css/itcss/components/request-decrypt-message.scss index 7387e944a57d..fd2ee53a8a6f 100644 --- a/ui/app/css/itcss/components/request-decrypt-message.scss +++ b/ui/app/css/itcss/components/request-decrypt-message.scss @@ -8,7 +8,6 @@ flex-flow: column nowrap; z-index: 25; align-items: center; - font-family: Roboto; position: relative; height: 100%; @@ -63,7 +62,6 @@ &__header__text { color: #5b5d67; - font-family: Roboto; font-size: 22px; line-height: 29px; z-index: 3; @@ -105,7 +103,6 @@ &__account-item { height: 22px; background-color: $white; - font-family: Roboto; line-height: 16px; font-size: 12px; width: 124px; @@ -156,7 +153,6 @@ } &__notice { - font-family: "Avenir Next"; font-size: 14px; line-height: 19px; text-align: center; diff --git a/ui/app/css/itcss/components/request-encryption-public-key.scss b/ui/app/css/itcss/components/request-encryption-public-key.scss index a4d6012670f9..8860ca5d897b 100644 --- a/ui/app/css/itcss/components/request-encryption-public-key.scss +++ b/ui/app/css/itcss/components/request-encryption-public-key.scss @@ -8,7 +8,6 @@ flex-flow: column nowrap; z-index: 25; align-items: center; - font-family: Roboto; position: relative; height: 100%; @@ -63,7 +62,6 @@ &__header__text { color: #5b5d67; - font-family: Roboto; font-size: 22px; line-height: 29px; z-index: 3; @@ -105,7 +103,6 @@ &__account-item { height: 22px; background-color: $white; - font-family: Roboto; line-height: 16px; font-size: 12px; width: 124px; @@ -156,7 +153,6 @@ } &__notice { - font-family: "Avenir Next"; font-size: 14px; line-height: 19px; text-align: center; diff --git a/ui/app/css/itcss/components/request-signature.scss b/ui/app/css/itcss/components/request-signature.scss index 03623e187bd5..6af476fd697d 100644 --- a/ui/app/css/itcss/components/request-signature.scss +++ b/ui/app/css/itcss/components/request-signature.scss @@ -8,7 +8,6 @@ flex-flow: column nowrap; z-index: 25; align-items: center; - font-family: Roboto; position: relative; height: 100%; @@ -63,7 +62,6 @@ &__header__text { color: #5b5d67; - font-family: Roboto; font-size: 22px; line-height: 29px; z-index: 3; @@ -104,7 +102,6 @@ &__account-item { height: 22px; background-color: $white; - font-family: Roboto; line-height: 16px; font-size: 12px; width: 124px; @@ -163,7 +160,6 @@ height: 48px; width: 240px; color: $tundora; - font-family: Roboto; font-size: 18px; line-height: 24px; text-align: center; @@ -172,7 +168,6 @@ &__notice, &__warning { - font-family: "Avenir Next"; font-size: 14px; line-height: 19px; text-align: center; @@ -207,7 +202,6 @@ &__row-title { width: 80px; color: $dusty-gray; - font-family: Roboto; font-size: 16px; line-height: 22px; margin-top: 12px; @@ -217,7 +211,6 @@ &__row-value { color: $scorpion; - font-family: Roboto; font-size: 14px; line-height: 19px; width: 100%; diff --git a/ui/app/css/itcss/components/sections.scss b/ui/app/css/itcss/components/sections.scss index f9bba2827f52..c187b121bd82 100644 --- a/ui/app/css/itcss/components/sections.scss +++ b/ui/app/css/itcss/components/sections.scss @@ -252,7 +252,6 @@ textarea.twelve-word-phrase { /* Info screen */ .info-gray { - font-family: Roboto; text-transform: uppercase; color: $silver-chalice; } @@ -262,7 +261,6 @@ textarea.twelve-word-phrase { } .info { - font-family: Roboto, Arial; padding-bottom: 10px; display: inline-block; padding-left: 5px; @@ -311,7 +309,6 @@ textarea.twelve-word-phrase { } .buy-inputs { - font-family: Roboto; font-size: 13px; height: 20px; background: transparent; @@ -355,7 +352,6 @@ textarea.twelve-word-phrase { } .ex-coins { - font-family: Roboto; text-transform: uppercase; text-align: center; font-size: 33px; @@ -366,7 +362,6 @@ textarea.twelve-word-phrase { } .marketinfo { - font-family: Roboto; color: $silver-chalice; font-size: 15px; line-height: 17px; diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss index e82d938d662e..df18572cd196 100644 --- a/ui/app/css/itcss/components/send.scss +++ b/ui/app/css/itcss/components/send.scss @@ -2,7 +2,6 @@ display: flex; flex-flow: column nowrap; z-index: 25; - font-family: Roboto; @media screen and (max-width: $break-small) { width: 100%; @@ -76,7 +75,6 @@ margin: 4px 0 20px; font-size: 16px; line-height: 22.4px; - font-family: Roboto; } .send-screen-gas-input { @@ -186,7 +184,6 @@ padding: 13px 19px; font-size: 16px; border-radius: 4px; - font-family: Roboto; font-weight: 500; } @@ -316,7 +313,6 @@ display: flex; flex-flow: column nowrap; z-index: 25; - font-family: Roboto; &__content { width: 498px; @@ -407,7 +403,6 @@ flex-flow: column nowrap; z-index: 25; align-items: center; - font-family: Roboto; position: relative; @media screen and (max-width: $break-small) { @@ -588,7 +583,6 @@ &__form-label { color: $scorpion; - font-family: Roboto; font-size: 16px; line-height: 22px; width: 95px; @@ -602,7 +596,6 @@ border: 1px solid $alto; border-radius: 4px; background-color: $white; - font-family: Roboto; line-height: 16px; font-size: 12px; color: $tundora; @@ -745,7 +738,6 @@ background-color: $white; color: $tundora; padding: 10px; - font-family: Roboto; font-size: 16px; line-height: 21px; } @@ -763,14 +755,12 @@ background-color: $white; color: $tundora; padding: 10px; - font-family: Roboto; font-size: 16px; line-height: 21px; } } &__amount-max { - font-family: Roboto; font-size: 12px; position: relative; display: inline-block; @@ -873,7 +863,6 @@ border-radius: 4px; background-color: #fff; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.14); - font-family: Roboto; display: flex; flex-flow: column; @@ -903,7 +892,6 @@ content: '\00D7'; font-size: 1.8em; color: $dusty-gray; - font-family: sans-serif; cursor: pointer; margin-right: 19.25px; } @@ -1000,7 +988,6 @@ &__title { height: 26px; color: $tundora; - font-family: Roboto; font-size: 20px; line-height: 26px; margin-top: 17px; @@ -1010,7 +997,6 @@ height: 38px; width: 314px; color: $tundora; - font-family: Roboto; font-size: 14px; line-height: 19px; margin-top: 17px; @@ -1101,7 +1087,6 @@ font-size: 1em; font-size: 14px; color: #2f9ae0; - font-family: Roboto; } .sliders-icon { diff --git a/ui/app/css/itcss/components/tooltip.scss b/ui/app/css/itcss/components/tooltip.scss index 97840ca1a215..68728538ab4e 100644 --- a/ui/app/css/itcss/components/tooltip.scss +++ b/ui/app/css/itcss/components/tooltip.scss @@ -8,7 +8,6 @@ position: absolute; z-index: 1070; display: block; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-style: normal; font-weight: normal; letter-spacing: normal; diff --git a/ui/app/css/itcss/components/transaction-list.scss b/ui/app/css/itcss/components/transaction-list.scss index 486c48694cb5..e0aef961e51a 100644 --- a/ui/app/css/itcss/components/transaction-list.scss +++ b/ui/app/css/itcss/components/transaction-list.scss @@ -26,7 +26,6 @@ align-self: center; font-size: 12px; color: $dusty-gray; - font-family: Roboto; text-transform: uppercase; } } @@ -163,7 +162,6 @@ .tx-list-date { color: $dusty-gray; font-size: 12px; - font-family: Roboto; } .tx-list-identicon-wrapper { diff --git a/ui/app/css/reset.scss b/ui/app/css/reset.scss index 43146fec8be3..9ee5607cf3aa 100644 --- a/ui/app/css/reset.scss +++ b/ui/app/css/reset.scss @@ -88,7 +88,11 @@ video { padding: 0; border: 0; font-size: 100%; - font: inherit; + font-weight: inherit; + font-style: inherit; + font-variant: inherit; + font-size: inherit; + line-height: inherit; vertical-align: baseline; } diff --git a/ui/app/pages/confirm-approve/confirm-approve-content/index.scss b/ui/app/pages/confirm-approve/confirm-approve-content/index.scss index 70771fcaf90a..d6a5d71c904d 100644 --- a/ui/app/pages/confirm-approve/confirm-approve-content/index.scss +++ b/ui/app/pages/confirm-approve/confirm-approve-content/index.scss @@ -4,7 +4,6 @@ align-items: center; width: 100%; height: 100%; - font-family: Roboto; font-style: normal; &__identicon-wrapper { @@ -21,7 +20,6 @@ flex-flow: column; align-items: center; width: 390px; - font-family: Roboto; font-style: normal; padding-left: 24px; padding-right: 24px; diff --git a/ui/app/pages/error/index.scss b/ui/app/pages/error/index.scss index cf0c2aeb4dfe..14ec9da846f4 100644 --- a/ui/app/pages/error/index.scss +++ b/ui/app/pages/error/index.scss @@ -2,7 +2,6 @@ display: flex; flex-flow: column nowrap; align-items: center; - font-family: Roboto; font-style: normal; font-weight: normal; padding: 35px 10px 10px 10px; diff --git a/ui/app/pages/first-time-flow/end-of-flow/index.scss b/ui/app/pages/first-time-flow/end-of-flow/index.scss index f085ea99e81f..34d04d1c2284 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/index.scss +++ b/ui/app/pages/first-time-flow/end-of-flow/index.scss @@ -1,6 +1,5 @@ .end-of-flow { color: black; - font-family: Roboto; font-style: normal; .app-header__logo-container { diff --git a/ui/app/pages/first-time-flow/index.scss b/ui/app/pages/first-time-flow/index.scss index 3b7498b2bac4..19e769e10d1f 100644 --- a/ui/app/pages/first-time-flow/index.scss +++ b/ui/app/pages/first-time-flow/index.scss @@ -72,7 +72,6 @@ /*rtl:ignore*/ direction: ltr; font-size: 1rem; - font-family: Roboto; border: 1px solid #cdcdcd; border-radius: 6px; background-color: #fff; @@ -149,7 +148,6 @@ } &__checkbox-label { - font-family: Roboto; font-style: normal; font-weight: normal; line-height: normal; diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/index.scss b/ui/app/pages/first-time-flow/metametrics-opt-in/index.scss index a5cb6e1dadda..18df92891a62 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/index.scss +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/index.scss @@ -27,7 +27,6 @@ &__title { position: relative; margin-top: 20px; - font-family: Roboto; font-style: normal; font-weight: normal; line-height: normal; @@ -43,7 +42,6 @@ } &__description { - font-family: Roboto; font-style: normal; font-weight: normal; line-height: 21px; diff --git a/ui/app/pages/first-time-flow/select-action/index.scss b/ui/app/pages/first-time-flow/select-action/index.scss index 34a72a10cc6d..1b398a73e242 100644 --- a/ui/app/pages/first-time-flow/select-action/index.scss +++ b/ui/app/pages/first-time-flow/select-action/index.scss @@ -11,7 +11,6 @@ } &__body-header { - font-family: Roboto; font-style: normal; font-weight: normal; line-height: 39px; @@ -59,7 +58,6 @@ } &__button-text-big { - font-family: Roboto; font-style: normal; font-weight: normal; line-height: 28px; @@ -70,7 +68,6 @@ } &__button-text-small { - font-family: Roboto; font-style: normal; font-weight: normal; line-height: 20px; diff --git a/ui/app/pages/keychains/index.scss b/ui/app/pages/keychains/index.scss index a70255d0d09b..54b52981fb65 100644 --- a/ui/app/pages/keychains/index.scss +++ b/ui/app/pages/keychains/index.scss @@ -95,7 +95,6 @@ .import-account__faq-link { font-size: 18px; line-height: 23px; - font-family: Roboto; } .import-account__selector-label { @@ -110,7 +109,6 @@ background-color: #fff; margin-top: 14px; color: #5b5d67; - font-family: Roboto; font-size: 18px; line-height: 23px; padding: 14px 21px; @@ -125,7 +123,6 @@ font-size: 18px; line-height: 23px; margin-top: 21px; - font-family: Roboto; } .import-account__input-wrapper { @@ -173,7 +170,6 @@ border: 1px solid #1b344d; border-radius: 4px; color: #1b344d; - font-family: Roboto; font-size: 18px; display: flex; flex-flow: column nowrap; @@ -190,7 +186,6 @@ .import-account__file-name { color: #000; - font-family: Roboto; font-size: 18px; line-height: 23px; margin-left: 22px; diff --git a/ui/app/pages/settings/contact-list-tab/index.scss b/ui/app/pages/settings/contact-list-tab/index.scss index 02273a66f476..9c33c3701424 100644 --- a/ui/app/pages/settings/contact-list-tab/index.scss +++ b/ui/app/pages/settings/contact-list-tab/index.scss @@ -33,7 +33,6 @@ &__header, &__header--edit { &__name { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 24px; @@ -179,7 +178,6 @@ } &__header { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 18px; @@ -193,7 +191,6 @@ } &__text { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 14px; diff --git a/ui/app/pages/settings/index.scss b/ui/app/pages/settings/index.scss index 0c4371cf4d2a..b72deb39e70c 100644 --- a/ui/app/pages/settings/index.scss +++ b/ui/app/pages/settings/index.scss @@ -70,7 +70,6 @@ } &__sub-header-text { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 20px; diff --git a/ui/app/pages/settings/networks-tab/index.scss b/ui/app/pages/settings/networks-tab/index.scss index 92504f641943..e539ece40f31 100644 --- a/ui/app/pages/settings/networks-tab/index.scss +++ b/ui/app/pages/settings/networks-tab/index.scss @@ -96,7 +96,6 @@ } &__network-form-label { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 14px; @@ -177,7 +176,6 @@ &__networks-list-name { margin-left: 11px; - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 16px; From a69245d9ba0d110e9a6ad215f726800a1856ba5b Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 29 Jul 2020 17:31:01 -0300 Subject: [PATCH 021/137] Improve source maps (#9101) Our source maps were being corrupted during minification, because the `gulp-terser-js` plugin we were using didn't account for the existence of sourcemaps in the input. A configuration option to allow the input of sourcemaps was added in v5.2.0. The plugin has been updated, and we now use this option. Previously the generated sourcemaps had an invalid entry in the "sources" array, with the filename of the bundle itself. This was not a real source. After this change, this invalid source is no longer present. --- development/build/scripts.js | 3 +++ package.json | 2 +- yarn.lock | 20 ++++++++++---------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/development/build/scripts.js b/development/build/scripts.js index 8a6b4911113f..04f21aa76585 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -206,6 +206,9 @@ function createScriptTasks ({ browserPlatforms, livereload }) { mangle: { reserved: [ 'MetamaskInpageProvider' ], }, + sourceMap: { + content: true, + }, })) } diff --git a/package.json b/package.json index f26a98e85fb2..78e66b49b6f1 100644 --- a/package.json +++ b/package.json @@ -236,7 +236,7 @@ "gulp-sass": "^4.0.0", "gulp-sourcemaps": "^2.6.0", "gulp-stylelint": "^13.0.0", - "gulp-terser-js": "^5.0.0", + "gulp-terser-js": "^5.2.2", "gulp-watch": "^5.0.1", "gulp-zip": "^4.0.0", "jsdom": "^11.2.0", diff --git a/yarn.lock b/yarn.lock index eae41c1f7afb..f1ffc3d0c78a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12979,14 +12979,14 @@ gulp-stylelint@^13.0.0: strip-ansi "^6.0.0" through2 "^3.0.1" -gulp-terser-js@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/gulp-terser-js/-/gulp-terser-js-5.0.0.tgz#b570bb14e9c836aab78d633411073af0df8ca514" - integrity sha512-X5bduLqvRdX1RwUJmdm1J+HZu85gfIKkmDK95J6AAfXd4W/oYANt82gmIMZfhUGEmLm6e6xtKGsfTW6c0BRWnQ== +gulp-terser-js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/gulp-terser-js/-/gulp-terser-js-5.2.2.tgz#3d93db9b2b83f35dfcc5b209af6b1762756eb6a3" + integrity sha512-4ull0HzTWeWjRPiGmAFmdhRcEDOG+r7aXivNHOBQzElLzMaeVKQwmCPDi2juBzUUkjAkPkKb1jHVoJN/PKTvcA== dependencies: - object-assign "^4.1.1" plugin-error "^1.0.1" - terser "^4.1.4" + source-map "^0.7.3" + terser "^4.6.12" through2 "^3.0.1" vinyl-sourcemaps-apply "^0.2.1" @@ -25703,10 +25703,10 @@ terser@^4.1.2, terser@^4.4.3: source-map "~0.6.1" source-map-support "~0.5.12" -terser@^4.1.4: - version "4.3.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.1.tgz#09820bcb3398299c4b48d9a86aefc65127d0ed65" - integrity sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg== +terser@^4.6.12: + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== dependencies: commander "^2.20.0" source-map "~0.6.1" From 1207d439459dab4fe9bef83e2c0a413c0acdf594 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Wed, 29 Jul 2020 16:05:19 -0500 Subject: [PATCH 022/137] update email us to contact us (#9104) --- app/_locales/am/messages.json | 3 --- app/_locales/ar/messages.json | 3 --- app/_locales/bg/messages.json | 3 --- app/_locales/bn/messages.json | 3 --- app/_locales/ca/messages.json | 3 --- app/_locales/cs/messages.json | 3 --- app/_locales/da/messages.json | 3 --- app/_locales/de/messages.json | 3 --- app/_locales/el/messages.json | 3 --- app/_locales/en/messages.json | 6 +++--- app/_locales/es/messages.json | 3 --- app/_locales/es_419/messages.json | 3 --- app/_locales/et/messages.json | 3 --- app/_locales/fa/messages.json | 3 --- app/_locales/fi/messages.json | 3 --- app/_locales/fil/messages.json | 3 --- app/_locales/fr/messages.json | 3 --- app/_locales/he/messages.json | 3 --- app/_locales/hi/messages.json | 3 --- app/_locales/hn/messages.json | 3 --- app/_locales/hr/messages.json | 3 --- app/_locales/ht/messages.json | 3 --- app/_locales/hu/messages.json | 3 --- app/_locales/id/messages.json | 3 --- app/_locales/it/messages.json | 3 --- app/_locales/kn/messages.json | 3 --- app/_locales/ko/messages.json | 3 --- app/_locales/lt/messages.json | 3 --- app/_locales/lv/messages.json | 3 --- app/_locales/ms/messages.json | 3 --- app/_locales/nl/messages.json | 3 --- app/_locales/no/messages.json | 3 --- app/_locales/pl/messages.json | 3 --- app/_locales/pt/messages.json | 3 --- app/_locales/pt_BR/messages.json | 3 --- app/_locales/ro/messages.json | 3 --- app/_locales/ru/messages.json | 3 --- app/_locales/sk/messages.json | 3 --- app/_locales/sl/messages.json | 3 --- app/_locales/sr/messages.json | 3 --- app/_locales/sv/messages.json | 3 --- app/_locales/sw/messages.json | 3 --- app/_locales/ta/messages.json | 3 --- app/_locales/th/messages.json | 3 --- app/_locales/tr/messages.json | 3 --- app/_locales/uk/messages.json | 3 --- app/_locales/zh_CN/messages.json | 3 --- app/_locales/zh_TW/messages.json | 3 --- ui/app/pages/settings/info-tab/info-tab.component.js | 4 ++-- 49 files changed, 5 insertions(+), 146 deletions(-) diff --git a/app/_locales/am/messages.json b/app/_locales/am/messages.json index c279f5f170ac..c0ccc935204f 100644 --- a/app/_locales/am/messages.json +++ b/app/_locales/am/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "ዕውቂያን አርትዕ" }, - "emailUs": { - "message": "ኢሜይል ያድርጉልን!" - }, "endOfFlowMessage1": { "message": "ፈተናውን አልፈዋል - የዘር ሐረግዎን ደህንነቱ በተጠበቀ መንገድ ያስቀምጡ፣ የእርስዎ ሃላፊነት ነው! " }, diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index 46f240e2c46a..40815b680c34 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "تعديل جهة الاتصال" }, - "emailUs": { - "message": "راسلنا عبر البريد الإلكتروني!" - }, "endOfFlowMessage1": { "message": "لقد نجحت في الاختبار - احتفظ بعبارة الأمان الخاصة بك في مكان آمن، إنها مسؤوليتك!" }, diff --git a/app/_locales/bg/messages.json b/app/_locales/bg/messages.json index 668960321bc3..21b285807382 100644 --- a/app/_locales/bg/messages.json +++ b/app/_locales/bg/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "Редактиране на контакт" }, - "emailUs": { - "message": "Изпратете ни имейл!" - }, "endOfFlowMessage1": { "message": "Преминахте теста - пазете основната си фраза на сигурно място, това е Ваша отговорност!" }, diff --git a/app/_locales/bn/messages.json b/app/_locales/bn/messages.json index 0b24f07a4ded..773217e6dd39 100644 --- a/app/_locales/bn/messages.json +++ b/app/_locales/bn/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "পরিচিতি সম্পাদনা করুন" }, - "emailUs": { - "message": "আমাদের ইমেল করুন!" - }, "endOfFlowMessage1": { "message": "আপনি টেস্টটি পাস করেছেন - আপনার সীডফ্রেজ নিরাপদে রাখুন, এটি আপনার দায়িত্ব!" }, diff --git a/app/_locales/ca/messages.json b/app/_locales/ca/messages.json index 1d5eed5719bf..e948bc86e245 100644 --- a/app/_locales/ca/messages.json +++ b/app/_locales/ca/messages.json @@ -356,9 +356,6 @@ "editContact": { "message": "Editar Contacte" }, - "emailUs": { - "message": "Envia'ns un correu!" - }, "endOfFlowMessage1": { "message": "Has passat el test - mantingues la teva seedphrase segura, és la teva responsabilitat!" }, diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json index cf2cb9b059b2..b1f50c457369 100644 --- a/app/_locales/cs/messages.json +++ b/app/_locales/cs/messages.json @@ -148,9 +148,6 @@ "edit": { "message": "Upravit" }, - "emailUs": { - "message": "Napište nám e-mail!" - }, "enterPassword": { "message": "Zadejte heslo" }, diff --git a/app/_locales/da/messages.json b/app/_locales/da/messages.json index 136dd6a5504e..f6f6b0559012 100644 --- a/app/_locales/da/messages.json +++ b/app/_locales/da/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "Redigér Kontakt" }, - "emailUs": { - "message": "Send os en email!" - }, "endOfFlowMessage1": { "message": "Du bestod testen - pas godt på din seed-sætning, det er dit ansvar!" }, diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 14192b687d33..cf8596b32935 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -344,9 +344,6 @@ "editContact": { "message": "Kontakt bearbeiten" }, - "emailUs": { - "message": "Schreib uns eine Mail!" - }, "endOfFlowMessage1": { "message": "Sie haben den Test bestanden - bewahren Sie Ihre mnemonische Phrase sicher auf, Sie sind dafür verantwortlich! " }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index 7d021f7ab42f..ca3af0a616da 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -356,9 +356,6 @@ "editContact": { "message": "Επεξεργασία Επαφής" }, - "emailUs": { - "message": "Στείλτε μας email!" - }, "endOfFlowMessage1": { "message": "Περάσατε τη δοκιμή - κρατήστε τη φράση φύτρου σας ασφαλή, είναι δική σας ευθύνη!" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index caa1e1fa2efa..797c8e709f52 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -409,6 +409,9 @@ "contactsSettingsDescription": { "message": "Add, edit, remove, and manage your contacts" }, + "contactUs": { + "message": "Contact us!" + }, "continueToWyre": { "message": "Continue to Wyre" }, @@ -535,9 +538,6 @@ "editPermission": { "message": "Edit Permission" }, - "emailUs": { - "message": "Email us!" - }, "endOfFlowMessage1": { "message": "You passed the test - keep your seedphrase safe, it's your responsibility!" }, diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index d513a2f19e79..97576dba7323 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -313,9 +313,6 @@ "editContact": { "message": "Editar Contacto" }, - "emailUs": { - "message": "¡Envíanos un correo!" - }, "endOfFlowMessage8": { "message": "MetaMask no puede recuperar tu seedphrase. Saber más." }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index 8a83b65e8d30..a856b7e8826b 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -356,9 +356,6 @@ "editContact": { "message": "Editar contacto" }, - "emailUs": { - "message": "¡Envíanos un correo electrónico!" - }, "endOfFlowMessage1": { "message": "Pasaste la prueba. Es responsabilidad tuya mantener la frase de inicialización segura." }, diff --git a/app/_locales/et/messages.json b/app/_locales/et/messages.json index 5f1ca3132503..28c7cb3b7889 100644 --- a/app/_locales/et/messages.json +++ b/app/_locales/et/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "Muuda kontakti" }, - "emailUs": { - "message": "Saatke meile e-kiri!" - }, "endOfFlowMessage1": { "message": "Läbisite kontrolli – hoidke seemnefraasi turvaliselt, see on teie vastutusel!" }, diff --git a/app/_locales/fa/messages.json b/app/_locales/fa/messages.json index d59bb3f32f3b..30bb2e2a46e3 100644 --- a/app/_locales/fa/messages.json +++ b/app/_locales/fa/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "ویرایش تماس" }, - "emailUs": { - "message": "به ما ایمیل کنید!" - }, "endOfFlowMessage1": { "message": "شما در امتحان موفق شدید - عبارت بازیابی را مصؤن نگهدارید، این مسؤلیت شماست!" }, diff --git a/app/_locales/fi/messages.json b/app/_locales/fi/messages.json index a67ef40ea8fe..62ac9fd9e88a 100644 --- a/app/_locales/fi/messages.json +++ b/app/_locales/fi/messages.json @@ -356,9 +356,6 @@ "editContact": { "message": "Muokkaa yhteystietoa" }, - "emailUs": { - "message": "Lähetä meille sähköpostia!" - }, "endOfFlowMessage1": { "message": "Läpäisit kokeen – pidä salaustekstisi turvassa. Se on sinun vastuullasi!" }, diff --git a/app/_locales/fil/messages.json b/app/_locales/fil/messages.json index d925e9f63bf2..60ff2e03fa18 100644 --- a/app/_locales/fil/messages.json +++ b/app/_locales/fil/messages.json @@ -332,9 +332,6 @@ "editContact": { "message": "I-edit ang Contact" }, - "emailUs": { - "message": "Mag-email sa amin!" - }, "endOfFlowMessage1": { "message": "Pumasa ka sa test - panatilihing ligtas ang iyong seedphrase, responsibilidad mo ito!" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 7d28b3a0a2cb..3b5e665cdaeb 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -347,9 +347,6 @@ "editContact": { "message": "Modifier le contact" }, - "emailUs": { - "message": "Envoyez-nous un email !" - }, "endOfFlowMessage1": { "message": "Vous avez réussi l'essai : gardez votre phrase de départ en sécurité, c'est de votre responsabilité !" }, diff --git a/app/_locales/he/messages.json b/app/_locales/he/messages.json index 7fdd31a89099..02c7a496c47a 100644 --- a/app/_locales/he/messages.json +++ b/app/_locales/he/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "ערוך איש קשר" }, - "emailUs": { - "message": "שלח/י לנו מייל!" - }, "endOfFlowMessage1": { "message": "עברת את הבחינה - יש לשמור את ה-seedphrase שלך במקום בטוח, זה באחריותך!" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 1686b79df716..aad074d700fd 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "संपर्क संपादित करें" }, - "emailUs": { - "message": "हमें ईमेल करें!" - }, "endOfFlowMessage1": { "message": "आपने परीक्षा उत्तीर्ण कर ली - अपने बीज वाक्यांश को सुरक्षित रखें, यह आपकी जिम्मेदारी है!" }, diff --git a/app/_locales/hn/messages.json b/app/_locales/hn/messages.json index 81d190e0db7c..bfc32cd4e308 100644 --- a/app/_locales/hn/messages.json +++ b/app/_locales/hn/messages.json @@ -124,9 +124,6 @@ "edit": { "message": "संपादित करें" }, - "emailUs": { - "message": "हमें ईमेल करें!" - }, "enterPassword": { "message": "पासवर्ड दर्ज करें" }, diff --git a/app/_locales/hr/messages.json b/app/_locales/hr/messages.json index bc4d39ff402f..a818b79a6cfe 100644 --- a/app/_locales/hr/messages.json +++ b/app/_locales/hr/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "Uredi kontakt" }, - "emailUs": { - "message": "Pošaljite nam elektroničku poruku!" - }, "endOfFlowMessage1": { "message": "Prošli ste test – čuvajte svoju početnu rečenicu jer ste vi odgovorni za nju!" }, diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index c60e60c5a0c2..6881d8a1848c 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -205,9 +205,6 @@ "edit": { "message": "Korije" }, - "emailUs": { - "message": "Imèl nou!" - }, "enterPassword": { "message": "Mete modpas" }, diff --git a/app/_locales/hu/messages.json b/app/_locales/hu/messages.json index 84be04277e35..73d19f975ec1 100644 --- a/app/_locales/hu/messages.json +++ b/app/_locales/hu/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "Kapcsolatok szerkesztése" }, - "emailUs": { - "message": "Írjon nekünk!" - }, "endOfFlowMessage1": { "message": "Átment a teszten - tartsa biztonságban a seed mondatot, ez az ön felelőssége!" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 7d942d231d2e..267c5c079a6d 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -350,9 +350,6 @@ "editContact": { "message": "Sunting Kontak" }, - "emailUs": { - "message": "Kirimkan kami email!" - }, "endOfFlowMessage1": { "message": "Anda lulus tes - jagalah agar frasa benih Anda aman, itu tanggung jawab Anda!" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index a1358dc741c7..62683c407bbd 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -531,9 +531,6 @@ "editPermission": { "message": "Modifica Permessi" }, - "emailUs": { - "message": "Mandaci una mail!" - }, "endOfFlowMessage1": { "message": "Hai passato il test - tieni la tua frase seed al sicuro, è tua responsabilità!" }, diff --git a/app/_locales/kn/messages.json b/app/_locales/kn/messages.json index 7b8f6253f020..207dccfb7415 100644 --- a/app/_locales/kn/messages.json +++ b/app/_locales/kn/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "ಸಂಪರ್ಕವನ್ನು ಸಂಪಾದಿಸಿ" }, - "emailUs": { - "message": "ನಮಗೆ ಇಮೇಲ್ ಮಾಡಿ!" - }, "endOfFlowMessage1": { "message": "ನೀವು ಪರೀಕ್ಷೆಯನ್ನು ಪಾಸ್ ಮಾಡಿರುವಿರಿ - ನಿಮ್ಮ ಸೀಡ್‌ಫ್ರೇಸ್ ಸುರಕ್ಷಿತವಾಗಿರಿಸಿ, ಅದು ನಿಮ್ಮ ಜವಾಬ್ದಾರಿಯಾಗಿದೆ!" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 18f302c7d9c1..8b73492f8516 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -356,9 +356,6 @@ "editContact": { "message": "연락처 수정" }, - "emailUs": { - "message": "저자에게 메일 보내기!" - }, "endOfFlowMessage1": { "message": "인증을 통과했습니다 - 시드 구문을 안전하게 보관하세요. 그것은 당신의 의무입니다." }, diff --git a/app/_locales/lt/messages.json b/app/_locales/lt/messages.json index 30fa9dd23813..00d1cdb7e332 100644 --- a/app/_locales/lt/messages.json +++ b/app/_locales/lt/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "Taisyti kontaktą" }, - "emailUs": { - "message": "Rašykite mums el. paštu!" - }, "endOfFlowMessage1": { "message": "Jūs perėjote testą – laikykite saugiai savo atkūrimo frazę, tai jūsų atsakomybė!" }, diff --git a/app/_locales/lv/messages.json b/app/_locales/lv/messages.json index f06839e6c9e1..7d2906c49582 100644 --- a/app/_locales/lv/messages.json +++ b/app/_locales/lv/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "Rediģēt līgumu" }, - "emailUs": { - "message": "Raksiet mums e-pastu!" - }, "endOfFlowMessage1": { "message": "Jūs izgājāt pārbaudi — glabājiet atkopšanas frāzi drošībā, tā ir jūsu atbildība!" }, diff --git a/app/_locales/ms/messages.json b/app/_locales/ms/messages.json index 1cc5cd6bb3b1..c4d2b538e792 100644 --- a/app/_locales/ms/messages.json +++ b/app/_locales/ms/messages.json @@ -347,9 +347,6 @@ "editContact": { "message": "Edit Kenalan" }, - "emailUs": { - "message": "Hantarkan e-mel kepada kami!" - }, "endOfFlowMessage1": { "message": "Anda telah lulus ujian - simpan frasa benih anda di tempat yang selamat, itu tanggungjawab anda!" }, diff --git a/app/_locales/nl/messages.json b/app/_locales/nl/messages.json index 7d62e859a92b..ff4695c93ef2 100644 --- a/app/_locales/nl/messages.json +++ b/app/_locales/nl/messages.json @@ -118,9 +118,6 @@ "edit": { "message": "Bewerk" }, - "emailUs": { - "message": "Email ons!" - }, "enterPassword": { "message": "Voer wachtwoord in" }, diff --git a/app/_locales/no/messages.json b/app/_locales/no/messages.json index f4352505d4b0..54d2319b9c51 100644 --- a/app/_locales/no/messages.json +++ b/app/_locales/no/messages.json @@ -356,9 +356,6 @@ "editContact": { "message": "Rediger kontakt" }, - "emailUs": { - "message": "Send oss en e-post!" - }, "endOfFlowMessage1": { "message": "Du besto prøven - oppbevar den mnemoniske gjenopprettingsfrasen din på et sikkert sted, det er ditt ansvar! " }, diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index a3d06bba8681..b057d1642ee4 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -356,9 +356,6 @@ "editContact": { "message": "Edytuj kontakt" }, - "emailUs": { - "message": "Napisz do nas!" - }, "endOfFlowMessage1": { "message": "Zaliczyłeś test – zabezpiecz swoją frazę seed, to Twoja odpowiedzialność!" }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index cda66419d848..c3e710345cdf 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -124,9 +124,6 @@ "edit": { "message": "Editar" }, - "emailUs": { - "message": "Fale connosco!" - }, "enterPassword": { "message": "Introduza palavra-passe" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index 4a5b2efbe6b8..2eda26024885 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -353,9 +353,6 @@ "editContact": { "message": "Editar Contato" }, - "emailUs": { - "message": "Escreva para nós!" - }, "endOfFlowMessage1": { "message": "Você passou no teste — mantenha sua frase semente segura, a responsabilidade é sua!" }, diff --git a/app/_locales/ro/messages.json b/app/_locales/ro/messages.json index 40cc1f2d5c3e..96e94f9f4685 100644 --- a/app/_locales/ro/messages.json +++ b/app/_locales/ro/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "Editați contact" }, - "emailUs": { - "message": "Trimiteți-ne un email!" - }, "endOfFlowMessage1": { "message": "Ați trecut testul – păstrați expresia sursă în siguranță, este răspunderea dvs.!" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index 33d2e217ec23..24ea1aa245f1 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -154,9 +154,6 @@ "edit": { "message": "Редактировать" }, - "emailUs": { - "message": "Свяжитесь с нами по электронной почте!" - }, "enterPassword": { "message": "Введите пароль" }, diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index 940c816ec9fe..285e4375d3df 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -350,9 +350,6 @@ "editContact": { "message": "Upraviť kontakt" }, - "emailUs": { - "message": "Napište nám e-mail!" - }, "endOfFlowMessage1": { "message": "Úspešne ste prešli testom – uchovávajte svoju seed frázu v bezpečí. Je to vaša zodpovednosť!" }, diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index 84fda7bb1f92..c5659aaa6c6b 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "Uredi stik" }, - "emailUs": { - "message": "Pišite nam!" - }, "endOfFlowMessage1": { "message": "Opravili ste test - vaše geslo seed phrase je vaša odgovornost - skrbno pazite nanj!" }, diff --git a/app/_locales/sr/messages.json b/app/_locales/sr/messages.json index fcbcb4cf9999..468b55d6cc8b 100644 --- a/app/_locales/sr/messages.json +++ b/app/_locales/sr/messages.json @@ -356,9 +356,6 @@ "editContact": { "message": "Izmeni kontakt" }, - "emailUs": { - "message": "Pošaljite nam e-poštu!" - }, "endOfFlowMessage1": { "message": "Prošli ste test - čuvajte svoju frazu početnih vrednosti, to je vaša odgovornost!" }, diff --git a/app/_locales/sv/messages.json b/app/_locales/sv/messages.json index 944b710f1b3b..3cc07877f5fb 100644 --- a/app/_locales/sv/messages.json +++ b/app/_locales/sv/messages.json @@ -353,9 +353,6 @@ "editContact": { "message": "Redigera kontakt" }, - "emailUs": { - "message": "Mejla oss!" - }, "endOfFlowMessage1": { "message": "Du klarade testet. Håll din seed phrase hemlig, den är på ditt ansvar!" }, diff --git a/app/_locales/sw/messages.json b/app/_locales/sw/messages.json index 77e7268b5b17..aa0c03cd9b9b 100644 --- a/app/_locales/sw/messages.json +++ b/app/_locales/sw/messages.json @@ -353,9 +353,6 @@ "editContact": { "message": "Hariri Mawasiliano" }, - "emailUs": { - "message": "Tutumie barua pepe!" - }, "endOfFlowMessage1": { "message": "Umefaulu jaribio - weka kirai chako cha kuanzia mahali salama, ni wajibu wako!" }, diff --git a/app/_locales/ta/messages.json b/app/_locales/ta/messages.json index dfb39b6a3f84..fd849f557b9b 100644 --- a/app/_locales/ta/messages.json +++ b/app/_locales/ta/messages.json @@ -139,9 +139,6 @@ "edit": { "message": "திருத்து" }, - "emailUs": { - "message": "எங்களுக்கு மின்னஞ்சல்!" - }, "enterPassword": { "message": "கடவுச்சொல்லை உள்ளிடவும்" }, diff --git a/app/_locales/th/messages.json b/app/_locales/th/messages.json index 44bf097f0696..eacf2f961e50 100644 --- a/app/_locales/th/messages.json +++ b/app/_locales/th/messages.json @@ -178,9 +178,6 @@ "editContact": { "message": "แก้ไขผู้ติดต่อ" }, - "emailUs": { - "message": "อีเมลหาเรา!" - }, "endOfFlowMessage1": { "message": "คุณผ่านการทดสอบแล้ว กรุณารับผิดชอบในการรักษา Seed Phrase ให้ปลอดภัย" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index c47144713ce9..df904c9eba71 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -151,9 +151,6 @@ "edit": { "message": "Düzenle" }, - "emailUs": { - "message": "Bize e-posta atın!" - }, "enterPassword": { "message": "Parolanızı girin" }, diff --git a/app/_locales/uk/messages.json b/app/_locales/uk/messages.json index c9d389c7857b..14ff03db6353 100644 --- a/app/_locales/uk/messages.json +++ b/app/_locales/uk/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "Редагувати контракт" }, - "emailUs": { - "message": "Напишіть нам!" - }, "endOfFlowMessage1": { "message": "Ви пройшли тест, зберігайте вашу початкову фразу в безпеці - це ваша відповідальність!" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 05566ca8eb25..bd13f3ac1a03 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -359,9 +359,6 @@ "editContact": { "message": "编辑联系人" }, - "emailUs": { - "message": "联系我们" - }, "endOfFlowMessage1": { "message": "您已通过测试 - 请妥善保管你的种子密语。这是您的责任!" }, diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index 532799252175..3e2e5d8345ab 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -356,9 +356,6 @@ "editContact": { "message": "編輯聯絡資訊" }, - "emailUs": { - "message": "寄 Email 給我們!" - }, "endOfFlowMessage1": { "message": "你通過測試了—安全存放助記詞,這是你的責任!" }, diff --git a/ui/app/pages/settings/info-tab/info-tab.component.js b/ui/app/pages/settings/info-tab/info-tab.component.js index c229f56b7238..9d522a3a1931 100644 --- a/ui/app/pages/settings/info-tab/info-tab.component.js +++ b/ui/app/pages/settings/info-tab/info-tab.component.js @@ -76,12 +76,12 @@ export default class InfoTab extends PureComponent {

From d990de4a0c51cde9ac86509d8f2a83037d73e4b1 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jul 2020 19:39:47 -0230 Subject: [PATCH 023/137] Update dependencies (#9105) This change updates the following two dependencies to address high severity advisories in the production dependencies: * Use elliptic@6.5.3 * Use dot-prop@5.2.0 The public advisories: - `elliptic`: [npm](https://www.npmjs.com/advisories/1547) - `dot-prop`: [npm](https://www.npmjs.com/advisories/1213), [GHSA-ff7x-qrg7-qggm](https://github.com/advisories/GHSA-ff7x-qrg7-qggm) I don't believe there to be any functional changes here: - I don't think we hit any (important?) codepaths of the whole `ipld-zcash/zcash-bitcore-lib/elliptic` subtree of 3Box - `dot-prop` doesn't have a changelog but; - Looking through [`v3.0.0...v4.0.0`](https://github.com/sindresorhus/dot-prop/compare/v3.0.0...v4.0.0) it would seem that the breaking change was requiring Node.js 4 ([`88b6eb6`](https://github.com/sindresorhus/dot-prop/commit/88b6eb66cf4e119175a5ee7bf7faaec3ceb9497e)) - The only breaking change listed for [v5.0.0](https://github.com/sindresorhus/dot-prop/releases/tag/v5.0.0) was requiring Node.js 8. --- package.json | 3 +++ yarn.lock | 63 +++++++++++++--------------------------------------- 2 files changed, 18 insertions(+), 48 deletions(-) diff --git a/package.json b/package.json index 78e66b49b6f1..ae5ba7ec112a 100644 --- a/package.json +++ b/package.json @@ -52,10 +52,13 @@ "generate:migration": "./development/generate-migration.sh" }, "resolutions": { + "**/configstore/dot-prop": "^5.1.1", + "**/ethers/elliptic": "^6.5.3", "**/knex/minimist": "^1.2.5", "**/optimist/minimist": "^1.2.5", "**/socketcluster/minimist": "^1.2.5", "3box/ipfs/ipld-zcash/zcash-bitcore-lib/lodash": "^4.17.19", + "3box/ipfs/ipld-zcash/zcash-bitcore-lib/elliptic": "^6.5.3", "ganache-core/lodash": "^4.17.19" }, "dependencies": { diff --git a/yarn.lock b/yarn.lock index f1ffc3d0c78a..b34e2261ca65 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5449,11 +5449,6 @@ bn.js@^1.0.0: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-1.3.0.tgz#0db4cbf96f8f23b742f5bcb9d1aa7a9994a05e83" integrity sha1-DbTL+W+PI7dC9by50ap6mZSgXoM= -bn.js@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.2.0.tgz#12162bc2ae71fc40a5626c33438f3a875cd37625" - integrity sha1-EhYrwq5x/EClYmwzQ486h1zTdiU= - body-parser@1.19.0, body-parser@^1.15.0, body-parser@^1.16.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -8880,12 +8875,12 @@ domutils@^1.7.0: dom-serializer "0" domelementtype "1" -dot-prop@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== +dot-prop@^4.1.0, dot-prop@^5.1.1: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" + integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== dependencies: - is-obj "^1.0.0" + is-obj "^2.0.0" dotenv-defaults@^1.0.2: version "1.0.2" @@ -9081,43 +9076,10 @@ element-resize-detector@^1.2.1: dependencies: batch-processor "1.0.0" -elliptic@6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - inherits "^2.0.1" - -elliptic@=3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-3.0.3.tgz#865c9b420bfbe55006b9f969f97a0d2c44966595" - integrity sha1-hlybQgv75VAGuflp+XoNLESWZZU= - dependencies: - bn.js "^2.0.0" - brorand "^1.0.1" - hash.js "^1.0.0" - inherits "^2.0.1" - -elliptic@^6.0.0, elliptic@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" - integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8= - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - -elliptic@^6.4.1: - version "6.5.0" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.0.tgz#2b8ed4c891b7de3200e14412a5b8248c7af505ca" - integrity sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg== +elliptic@6.3.3, elliptic@=3.0.3, elliptic@^6.0.0, elliptic@^6.4.0, elliptic@^6.4.1, elliptic@^6.5.3: + version "6.5.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" + integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -15059,11 +15021,16 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^1.0.0, is-obj@^1.0.1: +is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + is-object@^1.0.1, is-object@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" From e0cc84bbfa029aa7ee28a5ea77d00c9be4ae4dcd Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jul 2020 19:50:20 -0230 Subject: [PATCH 024/137] Use async/await for getRestrictedMethods (#9099) --- .../permissions/restrictedMethods.js | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/app/scripts/controllers/permissions/restrictedMethods.js b/app/scripts/controllers/permissions/restrictedMethods.js index 074cbb5a546c..0e1ae4b9ab39 100644 --- a/app/scripts/controllers/permissions/restrictedMethods.js +++ b/app/scripts/controllers/permissions/restrictedMethods.js @@ -1,34 +1,30 @@ export default function getRestrictedMethods ({ getIdentities, getKeyringAccounts }) { return { 'eth_accounts': { - method: (_, res, __, end) => { - getKeyringAccounts() - .then((accounts) => { - const identities = getIdentities() - res.result = accounts - .sort((firstAddress, secondAddress) => { - if (!identities[firstAddress]) { - throw new Error(`Missing identity for address ${firstAddress}`) - } else if (!identities[secondAddress]) { - throw new Error(`Missing identity for address ${secondAddress}`) - } else if (identities[firstAddress].lastSelected === identities[secondAddress].lastSelected) { - return 0 - } else if (identities[firstAddress].lastSelected === undefined) { - return 1 - } else if (identities[secondAddress].lastSelected === undefined) { - return -1 - } + method: async (_, res, __, end) => { + try { + const accounts = await getKeyringAccounts() + const identities = getIdentities() + res.result = accounts.sort((firstAddress, secondAddress) => { + if (!identities[firstAddress]) { + throw new Error(`Missing identity for address ${firstAddress}`) + } else if (!identities[secondAddress]) { + throw new Error(`Missing identity for address ${secondAddress}`) + } else if (identities[firstAddress].lastSelected === identities[secondAddress].lastSelected) { + return 0 + } else if (identities[firstAddress].lastSelected === undefined) { + return 1 + } else if (identities[secondAddress].lastSelected === undefined) { + return -1 + } - return identities[secondAddress].lastSelected - identities[firstAddress].lastSelected - }) - end() + return identities[secondAddress].lastSelected - identities[firstAddress].lastSelected }) - .catch( - (err) => { - res.error = err - end(err) - }, - ) + end() + } catch (err) { + res.error = err + end(err) + } }, }, } From 002f021fc0b15d5b3a20858d9c00af4860897181 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jul 2020 19:50:38 -0230 Subject: [PATCH 025/137] Use async/await for seedPhraseVerifier.verifyAccounts (#9100) --- app/scripts/lib/seed-phrase-verifier.js | 60 +++++++++++-------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/app/scripts/lib/seed-phrase-verifier.js b/app/scripts/lib/seed-phrase-verifier.js index 6a2925c71e5b..f07e63a2c731 100644 --- a/app/scripts/lib/seed-phrase-verifier.js +++ b/app/scripts/lib/seed-phrase-verifier.js @@ -16,41 +16,33 @@ const seedPhraseVerifier = { * @returns {Promise} - Promises undefined * */ - verifyAccounts (createdAccounts, seedWords) { - - return new Promise((resolve, reject) => { - - if (!createdAccounts || createdAccounts.length < 1) { - return reject(new Error('No created accounts defined.')) - } - - const keyringController = new KeyringController({}) - const Keyring = keyringController.getKeyringClassForType('HD Key Tree') - const opts = { - mnemonic: seedWords, - numberOfAccounts: createdAccounts.length, + async verifyAccounts (createdAccounts, seedWords) { + if (!createdAccounts || createdAccounts.length < 1) { + throw new Error('No created accounts defined.') + } + + const keyringController = new KeyringController({}) + const Keyring = keyringController.getKeyringClassForType('HD Key Tree') + const opts = { + mnemonic: seedWords, + numberOfAccounts: createdAccounts.length, + } + + const keyring = new Keyring(opts) + const restoredAccounts = await keyring.getAccounts() + log.debug('Created accounts: ' + JSON.stringify(createdAccounts)) + log.debug('Restored accounts: ' + JSON.stringify(restoredAccounts)) + + if (restoredAccounts.length !== createdAccounts.length) { + // this should not happen... + throw new Error('Wrong number of accounts') + } + + for (let i = 0; i < restoredAccounts.length; i++) { + if (restoredAccounts[i].toLowerCase() !== createdAccounts[i].toLowerCase()) { + throw new Error('Not identical accounts! Original: ' + createdAccounts[i] + ', Restored: ' + restoredAccounts[i]) } - - const keyring = new Keyring(opts) - keyring.getAccounts() - .then((restoredAccounts) => { - - log.debug('Created accounts: ' + JSON.stringify(createdAccounts)) - log.debug('Restored accounts: ' + JSON.stringify(restoredAccounts)) - - if (restoredAccounts.length !== createdAccounts.length) { - // this should not happen... - return reject(new Error('Wrong number of accounts')) - } - - for (let i = 0; i < restoredAccounts.length; i++) { - if (restoredAccounts[i].toLowerCase() !== createdAccounts[i].toLowerCase()) { - return reject(new Error('Not identical accounts! Original: ' + createdAccounts[i] + ', Restored: ' + restoredAccounts[i])) - } - } - return resolve() - }) - }) + } }, } From d832b98bae620c7f3e67265140c54e5d008e8998 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 30 Jul 2020 13:55:56 -0300 Subject: [PATCH 026/137] Add `build-artifacts` to .gitignore (#9109) The `build-artifacts` directory is created on CI (as of #7151), and is used to store the sesify visualization and dependency logs. It's useful to have this ignored locally as well, for when those scripts are being tested. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 41575124bf49..6d11965cb7d2 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ builds.zip test-artifacts test-builds +build-artifacts #ignore css output and sourcemaps ui/app/css/output/ From 3f53db184629eea3f5bc26c197f3c0e623f4d947 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 30 Jul 2020 14:43:02 -0300 Subject: [PATCH 027/137] Update `source-map-explorer` from v2.0.1 to v2.4.2 (#9110) The output remains identical between these two versions, and none of the changelog entries appear relevant to us (aside from maybe some of the bug fixes). --- package.json | 2 +- yarn.lock | 130 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 95 insertions(+), 37 deletions(-) diff --git a/package.json b/package.json index ae5ba7ec112a..fa511502ac67 100644 --- a/package.json +++ b/package.json @@ -269,7 +269,7 @@ "sesify-viz": "^3.0.5", "sinon": "^9.0.0", "source-map": "^0.7.2", - "source-map-explorer": "^2.0.1", + "source-map-explorer": "^2.4.2", "string.prototype.matchall": "^4.0.2", "style-loader": "^0.21.0", "stylelint": "^13.6.1", diff --git a/yarn.lock b/yarn.lock index b34e2261ca65..c513bcb96e0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4110,6 +4110,11 @@ async.util.setimmediate@0.5.2: resolved "https://registry.yarnpkg.com/async.util.setimmediate/-/async.util.setimmediate-0.5.2.tgz#2812ebabf2a58027758d4bc7793d1ccfaf10255f" integrity sha1-KBLrq/KlgCd1jUvHeT0cz68QJV8= +async@0.9.x: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= + async@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/async/-/async-2.0.0.tgz#d0900ad385af13804540a109c42166e3ae7b2b9d" @@ -7187,7 +7192,7 @@ convert-source-map@^0.3.3: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190" integrity sha1-8dgClQr33SYxof6+BZZVDIarMZA= -convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -9020,16 +9025,18 @@ ejs@^2.4.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== -ejs@^2.6.2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.1.tgz#5b5ab57f718b79d4aca9254457afecd36fa80228" - integrity sha512-kS/gEPzZs3Y1rRsbGX4UOSjtP/CeJP0CxSNZHYxGfVM/VgLcv0ZqM7C45YyTj2DI2g7+P9Dd24C+IMIg6D0nYQ== - ejs@^2.7.4: version "2.7.4" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== +ejs@^3.0.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.3.tgz#514d967a8894084d18d3d47bd169a1c0560f093d" + integrity sha512-wmtrUGyfSC23GC/B1SMv2ogAUgbQEtDmTIhfqielrG5ExIM9TP4UoYdi90jLF1aTcsWCJNEO0UrgKzP0y3nTSg== + dependencies: + jake "^10.6.1" + electron-download@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8" @@ -11431,6 +11438,13 @@ file-uri-to-path@1, file-uri-to-path@1.0.0: resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== +filelist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.1.tgz#f10d1a3ae86c1694808e8f20906f43d4c9132dbb" + integrity sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ== + dependencies: + minimatch "^3.0.4" + filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -13006,6 +13020,14 @@ gzip-size@5.0.0: duplexer "^0.1.1" pify "^3.0.0" +gzip-size@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" + integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== + dependencies: + duplexer "^0.1.1" + pify "^4.0.1" + hamt-sharding@~0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/hamt-sharding/-/hamt-sharding-0.0.2.tgz#53691f72122f1929a92a4688c7bb59545a8998ac" @@ -14783,6 +14805,11 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= +is-docker@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" + integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== + is-dom@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/is-dom/-/is-dom-1.0.9.tgz#483832d52972073de12b9fe3f60320870da8370d" @@ -15296,10 +15323,12 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= -is-wsl@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.1.1.tgz#4a1c152d429df3d441669498e2486d3596ebaf1d" - integrity sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog== +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" is-yarn-global@^0.3.0: version "0.3.0" @@ -15475,6 +15504,16 @@ iterall@^1.1.3, iterall@^1.2.1: resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA== +jake@^10.6.1: + version "10.8.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b" + integrity sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A== + dependencies: + async "0.9.x" + chalk "^2.4.2" + filelist "^1.0.1" + minimatch "^3.0.4" + java-properties@^0.2.9: version "0.2.10" resolved "https://registry.yarnpkg.com/java-properties/-/java-properties-0.2.10.tgz#2551560c25fa1ad94d998218178f233ad9b18f60" @@ -19521,19 +19560,13 @@ only@~0.0.2: resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q= -open@^6.3.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" - integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== - dependencies: - is-wsl "^1.1.0" - -open@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/open/-/open-7.0.0.tgz#7e52999b14eb73f90f0f0807fe93897c4ae73ec9" - integrity sha512-K6EKzYqnwQzk+/dzJAQSBORub3xlBTxMz+ntpZpH/LyCa1o6KjXhuN+2npAaI9jaSmU3R1Q8NWf4KUWcyytGsQ== +open@^7.0.0, open@^7.0.3: + version "7.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-7.1.0.tgz#68865f7d3cb238520fa1225a63cf28bcf8368a1c" + integrity sha512-lLPI5KgOwEYCDKXf4np7y1PBEkj7HYIyP2DY8mVDRnx0VIIu6bNrRB0R66TuO7Mack6EnTNLm4uvcl1UoklTpA== dependencies: - is-wsl "^2.1.0" + is-docker "^2.0.0" + is-wsl "^2.1.1" opencollective-postinstall@^2.0.0: version "2.0.2" @@ -24380,22 +24413,23 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" integrity sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A== -source-map-explorer@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-map-explorer/-/source-map-explorer-2.0.1.tgz#988721e8320d7b6925bc40289e5de658fe4cad4d" - integrity sha512-mv2sv2b6oN2L9n18O/eLrYiP5zfWEHESLq4utWBqNw8GnkbuRuXs8twVCOhMT5hxRzfQgS7Yxh7HlQaW8oeiAQ== +source-map-explorer@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/source-map-explorer/-/source-map-explorer-2.4.2.tgz#fb23f86c3112eacde5683f24efaf4ddc9f677985" + integrity sha512-3ECQLffCFV8QgrTqcmddLkWL4/aQs6ljYfgWCLselo5QtizOfOeUCKnS4rFn7MIrdeZLM6TZrseOtsrWZhWKoQ== dependencies: btoa "^1.2.1" - chalk "^2.4.2" - convert-source-map "^1.6.0" - ejs "^2.6.2" + chalk "^3.0.0" + convert-source-map "^1.7.0" + ejs "^3.0.2" escape-html "^1.0.3" - glob "^7.1.4" - lodash "^4.17.11" - open "^6.3.0" + glob "^7.1.6" + gzip-size "^5.1.1" + lodash "^4.17.15" + open "^7.0.3" source-map "^0.7.3" - temp "^0.9.0" - yargs "^13.2.4" + temp "^0.9.1" + yargs "^15.3.1" source-map-resolve@^0.5.0, source-map-resolve@^0.5.1: version "0.5.1" @@ -25605,7 +25639,14 @@ temp-dir@^1.0.0: resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= -temp@^0.9.0, temp@~0.9.0: +temp@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.1.tgz#2d666114fafa26966cd4065996d7ceedd4dd4697" + integrity sha512-WMuOgiua1xb5R56lE0eH6ivpVmg/lq2OHm4+LtT/xtEtPQ+sz6N3bBM6WZ5FvO1lO4IKIOb43qnhoc4qxP5OeA== + dependencies: + rimraf "~2.6.2" + +temp@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.0.tgz#61391795a11bd9738d4c4d7f55f012cb8f55edaa" integrity sha512-YfUhPQCJoNQE5N+FJQcdPz63O3x3sdT4Xju69Gj4iZe0lBKOtnAMi0SLj9xKhGkcGhsxThvTJ/usxtFPo438zQ== @@ -28041,7 +28082,7 @@ yargs-parser@13.1.2, yargs-parser@^13.1.0, yargs-parser@^13.1.1, yargs-parser@^1 camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^18.1.1, yargs-parser@^18.1.3: +yargs-parser@^18.1.1, yargs-parser@^18.1.2, yargs-parser@^18.1.3: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== @@ -28163,6 +28204,23 @@ yargs@^15.0.0, yargs@^15.0.2: y18n "^4.0.0" yargs-parser "^18.1.1" +yargs@^15.3.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + yargs@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" From ee291d48e9d9cf78d708d225456f65d58b8faffe Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 30 Jul 2020 14:55:26 -0300 Subject: [PATCH 028/137] Update `gulp-rename` from v1.4.0 to v2.0.0 (#9112) The changes between these versions don't affect us. The breaking change was related to passing in a function to `gulp-rename`, which we don't do. --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fa511502ac67..d6977899a3b5 100644 --- a/package.json +++ b/package.json @@ -233,7 +233,7 @@ "gulp-imagemin": "^6.1.0", "gulp-livereload": "4.0.0", "gulp-multi-process": "^1.3.1", - "gulp-rename": "^1.4.0", + "gulp-rename": "^2.0.0", "gulp-replace": "^1.0.0", "gulp-rtlcss": "^1.4.0", "gulp-sass": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index c513bcb96e0e..ab56ca74f60d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12888,10 +12888,10 @@ gulp-multi-process@^1.3.1: dependencies: async.queue "^0.5.2" -gulp-rename@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.4.0.tgz#de1c718e7c4095ae861f7296ef4f3248648240bd" - integrity sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg== +gulp-rename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-2.0.0.tgz#9bbc3962b0c0f52fc67cd5eaff6c223ec5b9cf6c" + integrity sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ== gulp-replace@^1.0.0: version "1.0.0" From 081153a0df3285ea1d849d90c54ac660e67b2c06 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 30 Jul 2020 14:55:46 -0300 Subject: [PATCH 029/137] Update `sesify-viz` from v3.0.9 to v3.0.10 (#9111) The changes between v3.0.9 and v3.0.10 are minimial - just some minor improvements to error handling. --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d6977899a3b5..5215472a778c 100644 --- a/package.json +++ b/package.json @@ -266,7 +266,7 @@ "selenium-webdriver": "^4.0.0-alpha.5", "serve-handler": "^6.1.2", "sesify": "^4.2.1", - "sesify-viz": "^3.0.5", + "sesify-viz": "^3.0.10", "sinon": "^9.0.0", "source-map": "^0.7.2", "source-map-explorer": "^2.4.2", diff --git a/yarn.lock b/yarn.lock index ab56ca74f60d..39aebf9e284f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23886,10 +23886,10 @@ sesify-tofu@^2.0.4: dependencies: acorn-globals "^4.3.3" -sesify-viz@^3.0.5: - version "3.0.9" - resolved "https://registry.yarnpkg.com/sesify-viz/-/sesify-viz-3.0.9.tgz#2fefff0456c3fa4e407e8564d2d0ab8797e29065" - integrity sha512-6weweTW6XQJyeoWK2vdoov52fpN07/lHqTlFwVO/M3LJMNr//BPfgxGxXVxtd09RdSLyAk5NZ7B3m3WgY8vMkQ== +sesify-viz@^3.0.10: + version "3.0.10" + resolved "https://registry.yarnpkg.com/sesify-viz/-/sesify-viz-3.0.10.tgz#1936e9a62bf8155c57dfc42e5eeceaa28b1cb875" + integrity sha512-Gamqr/8qbZDJ7Yq/NGUk3Iq2woTK67x1mZ59Qrt5ssLZZPzeCBYFeqnNWu8SUO42GlP1D3eyiGLHA31xceySHg== dependencies: ncp "^2.0.0" pify "^4.0.1" From b19e048f581a71b0fde624c6845b08790182aa4d Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 30 Jul 2020 16:02:27 -0300 Subject: [PATCH 030/137] Update `browserify` from v16.2.3 to v16.5.1 (#9113) The changes between these two versions don't seen to affect us a great deal. The browserify dependency updates do result in changes to our production bundle, but the changes have no obvious functional impact. --- package.json | 2 +- yarn.lock | 53 +++++++++++++++++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index 5215472a778c..63a41bb394eb 100644 --- a/package.json +++ b/package.json @@ -196,7 +196,7 @@ "babel-loader": "^8.0.6", "babelify": "^10.0.0", "brfs": "^1.6.1", - "browserify": "^16.2.3", + "browserify": "^16.5.1", "browserify-derequire": "^1.0.1", "browserify-transform-tools": "^1.7.0", "chai": "^4.1.0", diff --git a/yarn.lock b/yarn.lock index 39aebf9e284f..3245b5190d7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5734,17 +5734,17 @@ browserify-zlib@^0.2.0, browserify-zlib@~0.2.0: dependencies: pako "~1.0.5" -browserify@^16.1.0, browserify@^16.2.3: - version "16.2.3" - resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.2.3.tgz#7ee6e654ba4f92bce6ab3599c3485b1cc7a0ad0b" - integrity sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ== +browserify@^16.1.0, browserify@^16.5.1: + version "16.5.1" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.5.1.tgz#3c13c97436802930d5c3ae28658ddc33bfd37dc2" + integrity sha512-EQX0h59Pp+0GtSRb5rL6OTfrttlzv+uyaUVlK6GX3w11SQ0jKPKyjC/54RhPR2ib2KmfcELM06e8FxcI5XNU2A== dependencies: JSONStream "^1.0.3" assert "^1.4.0" browser-pack "^6.0.1" browser-resolve "^1.11.0" browserify-zlib "~0.2.0" - buffer "^5.0.2" + buffer "~5.2.1" cached-path-relative "^1.0.0" concat-stream "^1.6.0" console-browserify "^1.1.0" @@ -5762,7 +5762,7 @@ browserify@^16.1.0, browserify@^16.2.3: inherits "~2.0.1" insert-module-globals "^7.0.0" labeled-stream-splicer "^2.0.0" - mkdirp "^0.5.0" + mkdirp-classic "^0.5.2" module-deps "^6.0.0" os-browserify "~0.3.0" parents "^1.0.1" @@ -5776,7 +5776,7 @@ browserify@^16.1.0, browserify@^16.2.3: shasum "^1.0.0" shell-quote "^1.6.1" stream-browserify "^2.0.0" - stream-http "^2.0.0" + stream-http "^3.0.0" string_decoder "^1.1.1" subarg "^1.0.0" syntax-error "^1.1.1" @@ -5964,7 +5964,7 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.0.2, buffer@^5.0.5: +buffer@^5.0.5, buffer@~5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== @@ -18249,6 +18249,11 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" @@ -22448,15 +22453,6 @@ readable-stream@1.1, readable-stream@1.1.x, readable-stream@^1.0.33, readable-st isarray "0.0.1" string_decoder "~0.10.x" -"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.0.2, readable-stream@^3.0.5, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" - integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.5, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" @@ -22470,6 +22466,15 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.8, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" +"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.0.2, readable-stream@^3.0.5, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@~1.0.15: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" @@ -24803,7 +24808,7 @@ stream-exhaust@^1.0.1: resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d" integrity sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw== -stream-http@^2.0.0, stream-http@^2.7.2: +stream-http@^2.7.2: version "2.7.2" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad" integrity sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw== @@ -24814,6 +24819,16 @@ stream-http@^2.0.0, stream-http@^2.7.2: to-arraybuffer "^1.0.0" xtend "^4.0.0" +stream-http@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.1.tgz#0370a8017cf8d050b9a8554afe608f043eaff564" + integrity sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.4" + readable-stream "^3.6.0" + xtend "^4.0.2" + stream-parser@~0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/stream-parser/-/stream-parser-0.3.1.tgz#1618548694420021a1182ff0af1911c129761773" @@ -28015,7 +28030,7 @@ xregexp@2.0.0: resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= -xtend@^4.0.0, xtend@~4.0.0: +xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== From 9e12cdc01bd42c31526bfe5b0dbf54d450786d7f Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 30 Jul 2020 16:19:42 -0300 Subject: [PATCH 031/137] Factor out `getEnvironment` function in build script (#9114) There are no functional changes. This was extracted from #8170 --- development/build/scripts.js | 37 +++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/development/build/scripts.js b/development/build/scripts.js index 04f21aa76585..6f206ee57705 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -316,23 +316,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) { bundler = bundler.external(opts.externalDependencies) } - let environment - if (opts.devMode) { - environment = 'development' - } else if (opts.testing) { - environment = 'testing' - } else if (process.env.CIRCLE_BRANCH === 'master') { - environment = 'production' - } else if (/^Version-v(\d+)[.](\d+)[.](\d+)/.test(process.env.CIRCLE_BRANCH)) { - environment = 'release-candidate' - } else if (process.env.CIRCLE_BRANCH === 'develop') { - environment = 'staging' - } else if (process.env.CIRCLE_PULL_REQUEST) { - environment = 'pull-request' - } else { - environment = 'other' - } - + const environment = getEnvironment({ devMode: opts.devMode, test: opts.testing }) if (environment === 'production' && !process.env.SENTRY_DSN) { throw new Error('Missing SENTRY_DSN environment variable') } @@ -372,3 +356,22 @@ function createScriptTasks ({ browserPlatforms, livereload }) { function beep () { process.stdout.write('\x07') } + +function getEnvironment ({ devMode, test }) { + // get environment slug + if (devMode) { + return 'development' + } else if (test) { + return 'testing' + } else if (process.env.CIRCLE_BRANCH === 'master') { + return 'production' + } else if (/^Version-v(\d+)[.](\d+)[.](\d+)/.test(process.env.CIRCLE_BRANCH)) { + return 'release-candidate' + } else if (process.env.CIRCLE_BRANCH === 'develop') { + return 'staging' + } else if (process.env.CIRCLE_PULL_REQUEST) { + return 'pull-request' + } else { + return 'other' + } +} From c7db4c5a4d1983fc6a7559bf338d1a2e3c307505 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 30 Jul 2020 17:44:13 -0300 Subject: [PATCH 032/137] Update `brfs` from v1.6.1 to v2.0.2 (#9115) We were not affected by the breaking changes introduced with v2.0.0. This was updated primarily to get a bugfix relating to source maps, and to update some older transitive dependencies. --- package.json | 2 +- yarn.lock | 157 +++++++++++++++++++++++++-------------------------- 2 files changed, 79 insertions(+), 80 deletions(-) diff --git a/package.json b/package.json index 63a41bb394eb..25634fed147c 100644 --- a/package.json +++ b/package.json @@ -195,7 +195,7 @@ "babel-eslint": "^10.1.0", "babel-loader": "^8.0.6", "babelify": "^10.0.0", - "brfs": "^1.6.1", + "brfs": "^2.0.2", "browserify": "^16.5.1", "browserify-derequire": "^1.0.1", "browserify-transform-tools": "^1.7.0", diff --git a/yarn.lock b/yarn.lock index 3245b5190d7b..885354726adf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3748,6 +3748,11 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= +array-from@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/array-from/-/array-from-2.1.1.tgz#cfe9d8c26628b9dc5aecc62a9f5d8f1f352c1195" + integrity sha1-z+nYwmYoudxa7MYqn12PHzUsEZU= + array-includes@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" @@ -5584,14 +5589,14 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" -brfs@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3" - integrity sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ== +brfs@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brfs/-/brfs-2.0.2.tgz#44237878fa82aa479ce4f5fe2c1796ec69f07845" + integrity sha512-IrFjVtwu4eTJZyu8w/V2gxU7iLTtcHih67sgEdzrhjLBMHp2uYefUBfdM4k2UvcuWMgV7PQDZHSLeNWnLFKWVQ== dependencies: quote-stream "^1.0.1" resolve "^1.1.5" - static-module "^2.2.0" + static-module "^3.0.2" through2 "^2.0.0" brorand@^1.0.1: @@ -8002,6 +8007,11 @@ d@^1.0.1: es5-ext "^0.10.50" type "^1.0.1" +dash-ast@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dash-ast/-/dash-ast-1.0.0.tgz#12029ba5fb2f8aa6f0a861795b23c1b4b6c27d37" + integrity sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA== + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -9484,7 +9494,7 @@ es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-map@^0.1.3: +es6-map@^0.1.3, es6-map@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= @@ -9513,7 +9523,7 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -es6-set@~0.1.5: +es6-set@^0.1.5, es6-set@~0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= @@ -9570,34 +9580,10 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@1.x.x, escodegen@^1.8.1, escodegen@~1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" - integrity sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -escodegen@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.0.tgz#9811a2f265dc1cd3894420ee3717064b632b8852" - integrity sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.5.6" - -escodegen@^1.9.1: - version "1.13.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.13.0.tgz#c7adf9bd3f3cc675bb752f202f79a720189cab29" - integrity sha512-eYk2dCkxR07DsHA/X2hRBj0CFAZeri/LyDMc0C8JT1Hqi6JnVpMhJ7XFITbb0+yZS3lVkaPL2oCkZ3AVmeVbMw== +escodegen@1.x.x, escodegen@^1.11.1, escodegen@^1.9.0, escodegen@^1.9.1: + version "1.14.3" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" + integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== dependencies: esprima "^4.0.1" estraverse "^4.2.0" @@ -9902,7 +9888,7 @@ espree@^6.1.2: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.1.0" -esprima@3.x.x, esprima@^3.1.3: +esprima@3.x.x: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= @@ -9937,6 +9923,11 @@ estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= +estree-is-function@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/estree-is-function/-/estree-is-function-1.0.0.tgz#c0adc29806d7f18a74db7df0f3b2666702e37ad2" + integrity sha512-nSCWn1jkSq2QAtkaVLJZY2ezwcFO161HVc174zL1KPW3RJ+O6C3eJb8Nx7OXzvhoEv+nLgSR1g71oWUHUDTrJA== + esutils@^2.0.0, esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -11154,7 +11145,7 @@ fake-tag@^1.0.0: resolved "https://registry.yarnpkg.com/fake-tag/-/fake-tag-1.0.1.tgz#1d59da482240a02bd83500ca98976530ed154b0d" integrity sha512-qmewZoBpa71mM+y6oxXYW/d1xOYQmeIvnEXAt1oCmdP0sqcogWYLepR87QL1jQVLSVMVYDq2cjY6ec/Wu8/4pg== -falafel@^2.0.0, falafel@^2.1.0: +falafel@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.1.0.tgz#96bb17761daba94f46d001738b3cedf3a67fe06c" integrity sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw= @@ -12151,7 +12142,7 @@ gensync@^1.0.0-beta.1: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== -get-assigned-identifiers@^1.2.0: +get-assigned-identifiers@^1.1.0, get-assigned-identifiers@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" integrity sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ== @@ -17583,12 +17574,12 @@ mafmt@^6.0.0, mafmt@^6.0.2, mafmt@^6.0.4, mafmt@^6.0.7: dependencies: multiaddr "^6.0.4" -magic-string@^0.22.4: - version "0.22.5" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" - integrity sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w== +magic-string@0.25.1: + version "0.25.1" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.1.tgz#b1c248b399cd7485da0fe7385c2fc7011843266e" + integrity sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg== dependencies: - vlq "^0.2.2" + sourcemap-codec "^1.4.1" make-dir@^1.0.0, make-dir@^1.2.0: version "1.3.0" @@ -19299,11 +19290,6 @@ object-inspect@~1.3.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.3.0.tgz#5b1eb8e6742e2ee83342a637034d844928ba2f6d" integrity sha512-OHHnLgLNXpM++GnJRyyhbr2bwl3pPVm4YvaraHrRvDt/N3r+s/gDVHciA7EJBTkijKXj61ssgSAikq1fb0IBRg== -object-inspect@~1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4" - integrity sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw== - object-is@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" @@ -21732,7 +21718,7 @@ quick-lru@^4.0.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== -quote-stream@^1.0.1, quote-stream@~1.0.2: +quote-stream@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2" integrity sha1-hJY/jJwmuULhU/7rU6rnRlK34LI= @@ -22453,6 +22439,15 @@ readable-stream@1.1, readable-stream@1.1.x, readable-stream@^1.0.33, readable-st isarray "0.0.1" string_decoder "~0.10.x" +"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.0.2, readable-stream@^3.0.5, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.5, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" @@ -22466,15 +22461,6 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.8, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.0.2, readable-stream@^3.0.5, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readable-stream@~1.0.15: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" @@ -23653,6 +23639,19 @@ schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6 ajv "^6.10.2" ajv-keywords "^3.4.1" +scope-analyzer@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/scope-analyzer/-/scope-analyzer-2.1.1.tgz#5156c27de084d74bf75af9e9506aaf95c6e73dd6" + integrity sha512-azEAihtQ9mEyZGhfgTJy3IbOWEzeOrYbg7NcYEshPKnKd+LZmC3TNd5dmDxbLBsTG/JVWmCp+vDJ03vJjeXMHg== + dependencies: + array-from "^2.1.1" + dash-ast "^1.0.0" + es6-map "^0.1.5" + es6-set "^0.1.5" + es6-symbol "^3.1.1" + estree-is-function "^1.0.0" + get-assigned-identifiers "^1.1.0" + scrollbarwidth@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/scrollbarwidth/-/scrollbarwidth-0.1.3.tgz#1b0de64e288c38c427f4a01fe00a462a04b94fdf" @@ -24494,7 +24493,7 @@ source-map@^0.4.2: dependencies: amdefine ">=0.0.4" -source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3, source-map@~0.5.6: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -24504,6 +24503,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +sourcemap-codec@^1.4.1: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + space-separated-tokens@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.4.tgz#27910835ae00d0adfcdbd0ad7e611fb9544351fa" @@ -24676,12 +24680,12 @@ state-toggle@^1.0.0: resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.2.tgz#75e93a61944116b4959d665c8db2d243631d6ddc" integrity sha512-8LpelPGR0qQM4PnfLiplOQNJcIN1/r2Gy0xKB2zKnIW2YzPMt2sR4I/+gtPjhN7Svh9kw+zqEg2SFwpBO9iNiw== -static-eval@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.2.tgz#2d1759306b1befa688938454c546b7871f806a42" - integrity sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg== +static-eval@^2.0.5: + version "2.1.0" + resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.1.0.tgz#a16dbe54522d7fa5ef1389129d813fd47b148014" + integrity sha512-agtxZ/kWSsCkI5E4QifRwsaPs0P0JmZV6dkLz6ILYfFYQGn+5plctanRN+IC8dJRiFkyXHrwEE3W9Wmx67uDbw== dependencies: - escodegen "^1.8.1" + escodegen "^1.11.1" static-extend@^0.1.1: version "0.1.2" @@ -24691,24 +24695,24 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -static-module@^2.2.0: - version "2.2.5" - resolved "https://registry.yarnpkg.com/static-module/-/static-module-2.2.5.tgz#bd40abceae33da6b7afb84a0e4329ff8852bfbbf" - integrity sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ== +static-module@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/static-module/-/static-module-3.0.4.tgz#bfbd1d1c38dd1fbbf0bb4af0c1b3ae18a93a2b68" + integrity sha512-gb0v0rrgpBkifXCa3yZXxqVmXDVE+ETXj6YlC/jt5VzOnGXR2C15+++eXuMDUYsePnbhf+lwW0pE1UXyOLtGCw== dependencies: + acorn-node "^1.3.0" concat-stream "~1.6.0" convert-source-map "^1.5.1" duplexer2 "~0.1.4" - escodegen "~1.9.0" - falafel "^2.1.0" + escodegen "^1.11.1" has "^1.0.1" - magic-string "^0.22.4" + magic-string "0.25.1" merge-source-map "1.0.4" - object-inspect "~1.4.0" - quote-stream "~1.0.2" + object-inspect "^1.6.0" readable-stream "~2.3.3" + scope-analyzer "^2.0.1" shallow-copy "~0.0.1" - static-eval "^2.0.0" + static-eval "^2.0.5" through2 "~2.0.3" "statuses@>= 1.3.1 < 2": @@ -27121,11 +27125,6 @@ vinyl@^2.2.0: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" -vlq@^0.2.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" - integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== - vm-browserify@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" From 1c46715b46dc6215020bb14833eb94f9ee62cdca Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Fri, 31 Jul 2020 09:17:29 -0500 Subject: [PATCH 033/137] delete unused confirm styles (#9118) --- ui/app/css/itcss/components/confirm.scss | 344 ----------------------- ui/app/css/itcss/components/index.scss | 1 - 2 files changed, 345 deletions(-) delete mode 100644 ui/app/css/itcss/components/confirm.scss diff --git a/ui/app/css/itcss/components/confirm.scss b/ui/app/css/itcss/components/confirm.scss deleted file mode 100644 index b382bcae608e..000000000000 --- a/ui/app/css/itcss/components/confirm.scss +++ /dev/null @@ -1,344 +0,0 @@ -.confirm-screen-container { - position: relative; - align-items: center; - flex: 1 0 auto; - flex-flow: column nowrap; - box-shadow: 0 2px 4px 0 rgba($black, 0.08); - border-radius: 8px; - display: flex; - - @media screen and (max-width: 575px) { - width: 100%; - box-shadow: initial; - } -} - -.notification { - .confirm-screen-wrapper { - @media screen and (max-width: $break-small) { - height: calc(100vh - 85px); - } - } -} - -.confirm-screen-wrapper { - height: 100%; - width: 380px; - background-color: $white; - display: flex; - flex-flow: column nowrap; - z-index: 25; - align-items: center; - position: relative; - overflow-y: auto; - overflow-x: hidden; - border-top-left-radius: 8px; - border-top-right-radius: 8px; - - @media screen and (max-width: $break-small) { - width: 100%; - overflow-x: hidden; - overflow-y: auto; - top: 0; - box-shadow: none; - height: calc(100vh - 58px - 85px); - border-top-left-radius: 0; - border-top-right-radius: 0; - } -} - -.confirm-screen-wrapper > .confirm-screen-total-box { - margin-left: 10px; - margin-right: 10px; -} - -.confirm-screen-wrapper > .confirm-memo-wrapper { - margin: 0; -} - -.confirm-screen-header { - height: 88px; - background-color: $athens-grey; - position: relative; - display: flex; - justify-content: center; - align-items: center; - font-size: 22px; - line-height: 29px; - width: 100%; - padding: 25px 0; - flex: 0 0 auto; - - @media screen and (max-width: $break-small) { - font-size: 20px; - } -} - -.confirm-screen-header-tip { - height: 25px; - width: 25px; - background: $athens-grey; - position: absolute; - transform: rotate(45deg); - top: 71px; - left: 0; - right: 0; - margin: 0 auto; -} - -.confirm-screen-title { - line-height: 27px; - - @media screen and (max-width: $break-small) { - margin-left: 22px; - margin-right: 8px; - } -} - -.confirm-screen-back-button { - color: $primary-blue; - font-size: 1rem; - position: absolute; - top: 38px; - right: 38px; - background: none; -} - -.confirm-screen-account-wrapper { - display: flex; - flex-direction: column; - align-items: center; -} - -.confirm-screen-account-name { - margin-top: 12px; - font-size: 14px; - line-height: 19px; - color: $scorpion; - text-align: center; -} - -.confirm-screen-row-info { - font-size: 16px; - line-height: 21px; -} - -.confirm-screen-account-number { - font-size: 10px; - line-height: 16px; - color: $dusty-gray; - text-align: center; - height: 16px; -} - -.confirm-send-ether, -.confirm-send-token { - i.fa-arrow-right { - align-self: start; - margin: 24px 14px 0 !important; - } -} - -.confirm-screen-identicons { - margin-top: 24px; - flex: 0 0 auto; - - i.fa-arrow-right { - align-self: start; - margin: 42px 14px 0; - } - - i.fa-file-text-o { - font-size: 60px; - margin: 16px 8px 0 8px; - text-align: center; - } -} - -.confirm-screen-sending-to-message { - text-align: center; - font-size: 16px; - margin-top: 30px; - font-weight: 300; -} - -.confirm-screen-send-amount { - color: $scorpion; - margin-top: 12px; - text-align: center; - font-size: 40px; - line-height: 53px; - flex: 0 0 auto; -} - -.confirm-screen-send-amount-currency { - font-size: 20px; - line-height: 20px; - text-align: center; - flex: 0 0 auto; -} - -.confirm-memo-wrapper { - min-height: 24px; - width: 100%; - border-bottom: 1px solid $alto; - flex: 0 0 auto; -} - -.confirm-screen-send-memo { - color: $scorpion; - font-size: 16px; - line-height: 19px; - font-weight: 400; -} - -.confirm-screen-label { - font-size: 16px; - line-height: 40px; - color: $scorpion; - text-align: left; -} - -section .confirm-screen-account-name, -section .confirm-screen-account-number, -.confirm-screen-row-info, -.confirm-screen-row-detail { - text-align: left; -} - -.confirm-screen-rows { - display: flex; - flex-flow: column nowrap; - width: 100%; - flex: 0 0 auto; -} - -.confirm-screen-section-column { - flex: 0.5; -} - -.confirm-screen-row { - display: flex; - flex-flow: row nowrap; - width: 100%; - align-items: center; - padding: 12px; - padding-left: 35px; - font-size: 16px; - line-height: 22px; - - &:not(:last-of-type) { - border-bottom: 1px solid $alto; - } -} - -@media screen and (max-width: 379px) { - .confirm-screen-row { - span.confirm-screen-section-column { - flex: 0.4; - } - - div.confirm-screen-section-column { - flex: 0.6; - } - - .currency-display__input { - font-size: 14px; - } - } -} - -.confirm-screen-row-detail { - font-size: 12px; - line-height: 16px; - color: $dusty-gray; -} - -.confirm-screen-total-box { - background-color: $wild-sand; - position: relative; - - .confirm-screen-label { - line-height: 21px; - } - - .confirm-screen-row-detail { - color: $scorpion; - } - - &__subtitle { - font-size: 12px; - line-height: 16px; - } - - .confirm-screen-row-info { - font-size: 16px; - font-weight: 500; - line-height: 21px; - } -} - -.confirm-screen-error { - font-size: 12px; - line-height: 12px; - color: #f00; - position: absolute; - right: 12px; - width: 80px; - text-align: right; -} - -.confirm-screen-row.confirm-screen-total-box { - .confirm-screen-section-column--with-error { - flex: 0.6; - } -} - -@media screen and (max-width: 379px) { - .confirm-screen-row.confirm-screen-total-box { - .confirm-screen-section-column--with-error { - flex: 0.4; - } - } -} - -.confirm-screen-form { - position: relative; - - .confirm-screen-error { - right: 0; - width: 100%; - margin-top: 7px; - text-align: center; - } -} - -.confirm-screen-confirm-button { - height: 50px; - border-radius: 4px; - background-color: #02c9b1; - font-size: 16px; - color: $white; - text-align: center; - padding-top: 15px; - padding-bottom: 15px; - border-width: 0; - box-shadow: none; - flex: 1 0 auto; - margin: 0 5px; -} - -.btn-light.confirm-screen-cancel-button { - height: 50px; - background: none; - border: none; - opacity: 1; - border-width: 0; - padding-top: 15px; - padding-bottom: 15px; - font-size: 16px; - box-shadow: none; - cursor: pointer; - flex: 1 0 auto; - margin: 0 5px; -} diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index b9a698503f09..dda191fbdfbc 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -11,7 +11,6 @@ @import './newui-sections'; @import './account-dropdown'; @import './send'; -@import './confirm'; @import './loading-overlay'; // Tx List and Sections From 943d637cd2624b0cafdc6bb78e53fa01f9721944 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Fri, 31 Jul 2020 09:17:43 -0500 Subject: [PATCH 034/137] remove unused tx-list styles (#9121) --- ui/app/css/itcss/components/index.scss | 1 - .../itcss/components/transaction-list.scss | 297 ------------------ 2 files changed, 298 deletions(-) delete mode 100644 ui/app/css/itcss/components/transaction-list.scss diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index dda191fbdfbc..2b104a2eb600 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -14,7 +14,6 @@ @import './loading-overlay'; // Tx List and Sections -@import './transaction-list'; @import './sections'; @import './currency-display'; @import './menu'; diff --git a/ui/app/css/itcss/components/transaction-list.scss b/ui/app/css/itcss/components/transaction-list.scss deleted file mode 100644 index e0aef961e51a..000000000000 --- a/ui/app/css/itcss/components/transaction-list.scss +++ /dev/null @@ -1,297 +0,0 @@ -.tx-list-container { - height: 87.5%; - - @media screen and (min-width: $break-large) { - overflow-y: scroll; - } -} - -.tx-list-header-wrapper { - flex: 0 0 auto; -} - -.tx-list-header { - text-transform: capitalize; -} - -@media screen and (max-width: $break-small) { - .tx-list-header-wrapper { - margin-top: 0.2em; - margin-bottom: 0.6em; - justify-content: center; - flex: 0 0 auto; - } - - .tx-list-header { - align-self: center; - font-size: 12px; - color: $dusty-gray; - text-transform: uppercase; - } -} - -@media screen and (min-width: $break-large) { - .tx-list-header { - font-size: 16px; - margin: 1.1em 2.37em 0.8em; - } - - .tx-list-container::-webkit-scrollbar { - display: none; - } -} - -.tx-list-content-divider { - height: 1px; - background: rgb(231, 231, 231); - flex: 0 0 1px; - - @media screen and (max-width: $break-small) { - margin: 0.1em 0; - } - - @media screen and (min-width: $break-large) { - margin: 0.1em 2.37em; - } -} - -.tx-list-item-wrapper { - flex: 1 1 auto; - width: 0; - align-items: stretch; - justify-content: flex-start; - display: flex; - flex-flow: column nowrap; - - @media screen and (max-width: $break-small) { - padding: 0 1.3em 0.8em; - } - - @media screen and (min-width: $break-large) { - padding-bottom: 8px; - } -} - -.tx-list-pending-item-container { - cursor: pointer; - opacity: 0.5; -} - -.tx-list-date-wrapper { - margin-top: 6px; - flex: 1 1 auto; -} - -.tx-list-content-wrapper { - align-items: stretch; - margin: 4px 0; - flex: 1 0 auto; - width: 100%; - display: flex; - flex-flow: row nowrap; - - @media screen and (max-width: $break-small) { - font-size: 12px; - - .tx-list-status { - font-size: 12px !important; - } - - .tx-list-account { - font-size: 14px !important; - } - - .tx-list-value { - font-size: 14px; - line-height: 18px; - } - - .tx-list-fiat-value { - font-size: 12px; - line-height: 22px; - } - } -} - -.tx-list-item-retry-container { - background: #d1edff; - width: 100%; - border-radius: 12px; - font-size: 0.75rem; - display: flex; - justify-content: center; - margin-left: 44px; - width: calc(100% - 44px); - padding: 4px; - cursor: pointer; - - @media screen and (min-width: 576px) and (max-width: 679px) { - flex-flow: column; - align-items: center; - } - - @media screen and (min-width: 380px) and (max-width: 575px) { - flex-flow: row; - } - - @media screen and (max-width: 379px) { - flex-flow: column; - align-items: center; - } -} - -.tx-list-item-retry-link { - text-decoration: underline; - margin-left: 6px; - cursor: pointer; - - @media screen and (min-width: 576px) and (max-width: 679px) { - margin-left: 0; - } - - @media screen and (min-width: 380px) and (max-width: 575px) { - margin-left: 6px; - } - - @media screen and (max-width: 379px) { - margin-left: 0; - text-align: center; - } -} - -.tx-list-date { - color: $dusty-gray; - font-size: 12px; -} - -.tx-list-identicon-wrapper { - align-self: center; - flex: 0 0 auto; - margin-right: 16px; - display: flex; -} - -.tx-list-account-and-status-wrapper { - display: flex; - flex: 1 1 auto; - flex-flow: row wrap; - width: 0; - - @media screen and (max-width: $break-small) { - flex-direction: column; - justify-content: flex-start; - align-items: flex-start; - align-self: center; - - .tx-list-account-wrapper { - height: 18px; - - .tx-list-account { - line-height: 14px; - } - } - } - - @media screen and (min-width: $break-large) { - flex-direction: row; - justify-content: flex-start; - align-items: center; - - .tx-list-account-wrapper { - flex: 1.3 2 auto; - min-width: 153px; - } - - .tx-list-status-wrapper { - flex: 6 6 auto; - } - } - - .tx-list-account { - font-size: 16px; - color: $scorpion; - } - - .tx-list-status { - color: $dusty-gray; - font-size: 16px; - text-transform: capitalize; - } - - .tx-list-status--rejected, - .tx-list-status--failed { - color: $monzo; - } - - .tx-list-status--dropped { - opacity: 0.5; - } -} - -.tx-list-item { - border-bottom: 1px solid $geyser; - flex: 0 0 auto; - display: flex; - flex-flow: row nowrap; - - @media screen and (min-width: $break-large) { - padding: 0 2.37em; - } - - &:last-of-type { - border-bottom: 1px solid rgb(231, 231, 231); - margin-bottom: 32px; - } - - &__wrapper { - align-self: center; - flex: 2 2 auto; - color: $dusty-gray; - - .tx-list-value { - font-size: 16px; - text-align: right; - } - - .tx-list-value--confirmed { - color: $caribbean-green; - } - - .tx-list-fiat-value { - font-size: 12px; - text-align: right; - } - } - - &--empty { - text-align: center; - border-bottom: none !important; - padding: 16px; - } -} - -.tx-list-details-wrapper { - overflow: hidden; - flex: 0 0 35%; -} - -.tx-list-value { - font-size: 16px; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} - -.tx-list-fiat-value { - font-size: 12px; - line-height: initial; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} - -.tx-list-value--confirmed { - color: $caribbean-green; -} From 5df42c09d60e5bd30f4d9299c994a058dcf2ca39 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 4 Aug 2020 12:09:02 -0300 Subject: [PATCH 035/137] Non-zero exit code upon failure to validate source maps (#9132) The source map validator will now exit with a non-zero exit code when an error occurs, or when the source maps cannot be validated. --- development/sourcemap-validator.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/development/sourcemap-validator.js b/development/sourcemap-validator.js index e87c0604f6cb..2fda2a1142e8 100644 --- a/development/sourcemap-validator.js +++ b/development/sourcemap-validator.js @@ -13,13 +13,23 @@ const fsAsync = pify(fs) // if not working it may error or print minified garbage // -start().catch(console.error) +start().catch((error) => { + console.error(error) + process.exit(1) +}) async function start () { const targetFiles = [`inpage.js`, `contentscript.js`, `ui.js`, `background.js`] + let valid = true + for (const buildName of targetFiles) { - await validateSourcemapForFile({ buildName }) + const fileIsValid = await validateSourcemapForFile({ buildName }) + valid = valid && fileIsValid + } + + if (!valid) { + process.exit(1) } } @@ -59,6 +69,7 @@ async function validateSourcemapForFile ({ buildName }) { console.log(` sampling from ${consumer.sources.length} files`) let sampleCount = 0 + let valid = true const buildLines = rawBuild.split('\n') const targetString = 'new Error' @@ -71,6 +82,7 @@ async function validateSourcemapForFile ({ buildName }) { const result = consumer.originalPositionFor(position) // warn if source content is missing if (!result.source) { + valid = false console.warn(`!! missing source for position: ${JSON.stringify(position)}`) // const buildLine = buildLines[position.line - 1] console.warn(` origin in build:`) @@ -86,6 +98,7 @@ async function validateSourcemapForFile ({ buildName }) { const portion = line.slice(result.column) const isMaybeValid = portion.includes(targetString) if (!isMaybeValid) { + valid = false console.error('Sourcemap seems invalid:') console.log(`\n========================== ${result.source} ====================================\n`) console.log(line) @@ -94,6 +107,7 @@ async function validateSourcemapForFile ({ buildName }) { }) }) console.log(` checked ${sampleCount} samples`) + return valid } function indicesOf (substring, string) { From 96dd43553804487e9167cea2e39dc58f3ed6a6a3 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 4 Aug 2020 12:10:28 -0300 Subject: [PATCH 036/137] Add `validate-source-maps` npm script (#9134) This script executes the `sourcemap-validator.js` script to validate the source maps in the `dist` directory. --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 25634fed147c..578574cb9fa9 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "lint:shellcheck": "./development/shellcheck.sh", "lint:styles": "stylelint '*/**/*.scss'", "lint:lockfile": "lockfile-lint --path yarn.lock --allowed-hosts npm yarn github.com codeload.github.com --empty-hostname false --allowed-schemes \"https:\" \"git+https:\"", + "validate-source-maps": "node ./development/sourcemap-validator.js", "verify-locales": "node ./development/verify-locale-strings.js", "verify-locales:fix": "node ./development/verify-locale-strings.js --fix", "mozilla-lint": "addons-linter dist/firefox", From 7f87bdb2134604c8ca5d3d54e5064eeb5a219f50 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 4 Aug 2020 12:55:11 -0300 Subject: [PATCH 037/137] Improve sourcemap validator console report (#9131) The report printed to the console for invalid source map samples has been improved in a few ways: * The entire message is now printed using `console.error`, so the contents aren't split between STDERR and STDOUT * The code fence is now guaranteed to be a set length, rather than it varying depending on the filename * The code fence is no longer padded on the inside with newlines, which results in a more compact output that is (in my opinion) just as readable. --- development/sourcemap-validator.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/development/sourcemap-validator.js b/development/sourcemap-validator.js index 2fda2a1142e8..d4d9b82937f2 100644 --- a/development/sourcemap-validator.js +++ b/development/sourcemap-validator.js @@ -99,10 +99,7 @@ async function validateSourcemapForFile ({ buildName }) { const isMaybeValid = portion.includes(targetString) if (!isMaybeValid) { valid = false - console.error('Sourcemap seems invalid:') - console.log(`\n========================== ${result.source} ====================================\n`) - console.log(line) - console.log(`\n==============================================================================\n`) + console.error(`Sourcemap seems invalid:\n${getFencedCode(result.source, line)}`) } }) }) @@ -110,6 +107,20 @@ async function validateSourcemapForFile ({ buildName }) { return valid } +const CODE_FENCE_LENGTH = 80 +const TITLE_PADDING_LENGTH = 1 + +function getFencedCode (filename, code) { + const title = `${' '.repeat(TITLE_PADDING_LENGTH)}${filename}${' '.repeat(TITLE_PADDING_LENGTH)}` + const openingFenceLength = Math.max(CODE_FENCE_LENGTH - (filename.length + (TITLE_PADDING_LENGTH * 2)), 0) + const startOpeningFenceLength = Math.floor(openingFenceLength / 2) + const endOpeningFenceLength = Math.ceil(openingFenceLength / 2) + const openingFence = `${'='.repeat(startOpeningFenceLength)}${title}${'='.repeat(endOpeningFenceLength)}` + const closingFence = '='.repeat(CODE_FENCE_LENGTH) + + return `${openingFence}\n${code}\n${closingFence}\n` +} + function indicesOf (substring, string) { const a = [] let i = -1 From e1b9cfa5f8e1a38683e05e913db40d0799aa9d2e Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 4 Aug 2020 13:45:03 -0300 Subject: [PATCH 038/137] Update source map validator target files (#9133) All JavaScript files included in the final bundle are now listed as target files. The `phishing-detect.js` file is the only new file to be validated that was not validated before. Any files that are expected to fail validation are commented out, with a note explaining why they're expected to fail. --- development/sourcemap-validator.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/development/sourcemap-validator.js b/development/sourcemap-validator.js index d4d9b82937f2..7be473110a4f 100644 --- a/development/sourcemap-validator.js +++ b/development/sourcemap-validator.js @@ -20,7 +20,15 @@ start().catch((error) => { async function start () { - const targetFiles = [`inpage.js`, `contentscript.js`, `ui.js`, `background.js`] + const targetFiles = [ + `background.js`, + // `bg-libs`, skipped because source maps are invalid due to browserify bug: https://github.com/browserify/browserify/issues/1971 + // `contentscript.js`, skipped because the validator is erroneously sampling the inlined `inpage.js` script + `inpage.js`, + 'phishing-detect.js', + `ui.js`, + // `ui-libs.js`, skipped because source maps are invalid due to browserify bug: https://github.com/browserify/browserify/issues/1971 + ] let valid = true for (const buildName of targetFiles) { From f7edc83a4e8b1e7d814593e1dd091301181206e0 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 4 Aug 2020 14:21:46 -0300 Subject: [PATCH 039/137] Add source map validator to CI (#9135) Source maps are now validated during CI. This is done during a new job called "validate-source-maps`, and it is required to pass for tests to pass. --- .circleci/config.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 240b4aa0274d..d4b0febd7ab0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -38,6 +38,9 @@ workflows: - test-unit-global: requires: - prep-deps + - validate-source-maps: + requires: + - prep-build - test-mozilla-lint: requires: - prep-deps @@ -49,6 +52,7 @@ workflows: - test-lint-lockfile - test-unit - test-unit-global + - validate-source-maps - test-mozilla-lint - test-e2e-chrome - test-e2e-firefox @@ -358,6 +362,18 @@ jobs: - run: name: test:unit:global command: yarn test:unit:global + + validate-source-maps: + docker: + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 + steps: + - checkout + - attach_workspace: + at: . + - run: + name: Validate source maps + command: yarn validate-source-maps + test-mozilla-lint: docker: - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 From 658e478f29b546e5c3d05585234a98c781e4062b Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Tue, 4 Aug 2020 13:02:48 -0700 Subject: [PATCH 040/137] Fix connection removal bug (#9137) * fix remove connections bug --- app/scripts/metamask-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 5aa4539e325c..41a2d8fb31bf 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1722,7 +1722,7 @@ export default class MetamaskController extends EventEmitter { delete connections[id] - if (Object.keys(connections.length === 0)) { + if (Object.keys(connections).length === 0) { delete this.connections[origin] } } From 723e478689b291363f0914a86713d82328147bc2 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Wed, 5 Aug 2020 08:43:07 -0500 Subject: [PATCH 041/137] move currency-display styles to where they are used (#9119) --- .../itcss/components/currency-display.scss | 82 ------------------- ui/app/css/itcss/components/index.scss | 1 - .../send-gas-row/send-gas-row.scss | 82 +++++++++++++++++++ ui/app/pages/send/send.scss | 2 + 4 files changed, 84 insertions(+), 83 deletions(-) delete mode 100644 ui/app/css/itcss/components/currency-display.scss diff --git a/ui/app/css/itcss/components/currency-display.scss b/ui/app/css/itcss/components/currency-display.scss deleted file mode 100644 index b8a23d06b13d..000000000000 --- a/ui/app/css/itcss/components/currency-display.scss +++ /dev/null @@ -1,82 +0,0 @@ -.currency-display { - height: 54px; - border: 1px solid $alto; - border-radius: 4px; - background-color: $white; - color: $scorpion; - font-size: 16px; - padding: 8px 10px; - position: relative; - - &__primary-row { - display: flex; - } - - &__input { - color: $scorpion; - font-size: 16px; - line-height: 22px; - border: none; - max-width: 22ch; - } - - &__primary-currency { - color: $scorpion; - font-weight: 400; - font-size: 16px; - line-height: 22px; - } - - &__converted-row { - display: flex; - } - - &__converted-value, - &__converted-currency { - color: $dusty-gray; - font-size: 12px; - line-height: 12px; - } - - &__input-wrapper { - position: relative; - display: flex; - flex: 1; - max-width: 100%; - - input[type="number"] { - -moz-appearance: textfield; - } - - input[type="number"]::-webkit-inner-spin-button { - -webkit-appearance: none; - -moz-appearance: none; - display: none; - } - - input[type="number"]:hover::-webkit-inner-spin-button { - -webkit-appearance: none; - -moz-appearance: none; - display: none; - } - } - - &__currency-symbol { - margin-top: 1px; - color: $scorpion; - } - - .react-numeric-input { - input[type="number"]::-webkit-inner-spin-button { - -webkit-appearance: none; - -moz-appearance: none; - display: none; - } - - input[type="number"]:hover::-webkit-inner-spin-button { - -webkit-appearance: none; - -moz-appearance: none; - display: none; - } - } -} diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 2b104a2eb600..7d47b8cefaf7 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -15,7 +15,6 @@ // Tx List and Sections @import './sections'; -@import './currency-display'; @import './menu'; @import './gas-slider'; @import './tab-bar'; diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss index e69de29bb2d1..b8a23d06b13d 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss +++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss @@ -0,0 +1,82 @@ +.currency-display { + height: 54px; + border: 1px solid $alto; + border-radius: 4px; + background-color: $white; + color: $scorpion; + font-size: 16px; + padding: 8px 10px; + position: relative; + + &__primary-row { + display: flex; + } + + &__input { + color: $scorpion; + font-size: 16px; + line-height: 22px; + border: none; + max-width: 22ch; + } + + &__primary-currency { + color: $scorpion; + font-weight: 400; + font-size: 16px; + line-height: 22px; + } + + &__converted-row { + display: flex; + } + + &__converted-value, + &__converted-currency { + color: $dusty-gray; + font-size: 12px; + line-height: 12px; + } + + &__input-wrapper { + position: relative; + display: flex; + flex: 1; + max-width: 100%; + + input[type="number"] { + -moz-appearance: textfield; + } + + input[type="number"]::-webkit-inner-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + display: none; + } + + input[type="number"]:hover::-webkit-inner-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + display: none; + } + } + + &__currency-symbol { + margin-top: 1px; + color: $scorpion; + } + + .react-numeric-input { + input[type="number"]::-webkit-inner-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + display: none; + } + + input[type="number"]:hover::-webkit-inner-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + display: none; + } + } +} diff --git a/ui/app/pages/send/send.scss b/ui/app/pages/send/send.scss index 81de75a853da..61b1fe805970 100644 --- a/ui/app/pages/send/send.scss +++ b/ui/app/pages/send/send.scss @@ -1,3 +1,5 @@ +@import './send-content/send-gas-row/send-gas-row'; + .send { &__header { position: relative; From b92475ac7c86dee44ab7708803d505726da2a7c4 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Wed, 5 Aug 2020 08:43:21 -0500 Subject: [PATCH 042/137] Colocate alert styles (#9117) --- ui/app/components/app/index.scss | 1 + .../components/alert.scss => components/ui/alert/index.scss} | 0 ui/app/css/itcss/components/index.scss | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename ui/app/{css/itcss/components/alert.scss => components/ui/alert/index.scss} (100%) diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/index.scss index 00724f3e2473..73881885eaa2 100644 --- a/ui/app/components/app/index.scss +++ b/ui/app/components/app/index.scss @@ -1,5 +1,6 @@ @import 'account-menu/index'; @import 'add-token-button/index'; +@import '../ui/alert/index'; @import 'alerts/alerts'; @import 'app-header/index'; @import 'asset-list-item/asset-list-item'; diff --git a/ui/app/css/itcss/components/alert.scss b/ui/app/components/ui/alert/index.scss similarity index 100% rename from ui/app/css/itcss/components/alert.scss rename to ui/app/components/ui/alert/index.scss diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 7d47b8cefaf7..19f202711166 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -7,7 +7,6 @@ @import './footer'; @import './network'; @import './modal'; -@import './alert'; @import './newui-sections'; @import './account-dropdown'; @import './send'; From db1b72a95c50ce955b7f8b9d63bc72923ea6b9e5 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Wed, 5 Aug 2020 08:44:17 -0500 Subject: [PATCH 043/137] colocate editable label styles and code (#9120) --- ui/app/components/app/index.scss | 1 + ui/app/components/ui/{ => editable-label}/editable-label.js | 0 ui/app/components/ui/editable-label/index.js | 1 + .../ui/editable-label/index.scss} | 0 ui/app/css/itcss/components/index.scss | 1 - ui/app/css/itcss/components/sections.scss | 4 ---- 6 files changed, 2 insertions(+), 5 deletions(-) rename ui/app/components/ui/{ => editable-label}/editable-label.js (100%) create mode 100644 ui/app/components/ui/editable-label/index.js rename ui/app/{css/itcss/components/editable-label.scss => components/ui/editable-label/index.scss} (100%) diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/index.scss index 73881885eaa2..5cb6fd2a7682 100644 --- a/ui/app/components/app/index.scss +++ b/ui/app/components/app/index.scss @@ -10,6 +10,7 @@ @import 'confirm-page-container/index'; @import '../ui/currency-input/index'; @import '../ui/currency-display/index'; +@import '../ui/editable-label/index'; @import '../ui/error-message/index'; @import '../ui/export-text-container/index'; @import '../ui/identicon/index'; diff --git a/ui/app/components/ui/editable-label.js b/ui/app/components/ui/editable-label/editable-label.js similarity index 100% rename from ui/app/components/ui/editable-label.js rename to ui/app/components/ui/editable-label/editable-label.js diff --git a/ui/app/components/ui/editable-label/index.js b/ui/app/components/ui/editable-label/index.js new file mode 100644 index 000000000000..43078e7f7435 --- /dev/null +++ b/ui/app/components/ui/editable-label/index.js @@ -0,0 +1 @@ +export { default } from './editable-label' diff --git a/ui/app/css/itcss/components/editable-label.scss b/ui/app/components/ui/editable-label/index.scss similarity index 100% rename from ui/app/css/itcss/components/editable-label.scss rename to ui/app/components/ui/editable-label/index.scss diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 19f202711166..ea01b5060d42 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -21,7 +21,6 @@ @import './request-signature'; @import './request-encryption-public-key'; @import './request-decrypt-message'; -@import './editable-label'; @import './pages/index'; @import './new-account'; @import './tooltip'; diff --git a/ui/app/css/itcss/components/sections.scss b/ui/app/css/itcss/components/sections.scss index c187b121bd82..4ddda782a883 100644 --- a/ui/app/css/itcss/components/sections.scss +++ b/ui/app/css/itcss/components/sections.scss @@ -100,10 +100,6 @@ textarea.twelve-word-phrase { padding-left: 5px; } -.editable-label { - display: flex; -} - /* accounts */ .accounts-section { From ecaa6c55dd199f68e4d3aa6a2181f1d263ee53fa Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Thu, 6 Aug 2020 08:04:55 -0500 Subject: [PATCH 044/137] trim unused account-list-item code and co-locate styles (#9116) --- .../account-list-item/account-list-item.js | 51 +++++++++ .../components/app/account-list-item/index.js | 1 + .../app/account-list-item/index.scss | 26 +++++ .../tests/account-list-item-component.test.js | 40 +------ ui/app/components/app/index.scss | 1 + .../signature-request-original.component.js | 3 +- .../signature-request-header.component.js | 3 +- ui/app/css/base-styles.scss | 2 - .../itcss/components/account-dropdown.scss | 104 ------------------ ui/app/css/itcss/components/index.scss | 1 - .../confirm-decrypt-message.component.js | 3 +- ...confirm-encryption-public-key.component.js | 3 +- .../account-list-item.component.js | 101 ----------------- .../account-list-item.container.js | 21 ---- ui/app/pages/send/account-list-item/index.js | 1 - .../tests/account-list-item-container.test.js | 63 ----------- 16 files changed, 85 insertions(+), 339 deletions(-) create mode 100644 ui/app/components/app/account-list-item/account-list-item.js create mode 100644 ui/app/components/app/account-list-item/index.js create mode 100644 ui/app/components/app/account-list-item/index.scss rename ui/app/{pages/send => components/app}/account-list-item/tests/account-list-item-component.test.js (75%) delete mode 100644 ui/app/css/itcss/components/account-dropdown.scss delete mode 100644 ui/app/pages/send/account-list-item/account-list-item.component.js delete mode 100644 ui/app/pages/send/account-list-item/account-list-item.container.js delete mode 100644 ui/app/pages/send/account-list-item/index.js delete mode 100644 ui/app/pages/send/account-list-item/tests/account-list-item-container.test.js diff --git a/ui/app/components/app/account-list-item/account-list-item.js b/ui/app/components/app/account-list-item/account-list-item.js new file mode 100644 index 000000000000..7e001f7d6025 --- /dev/null +++ b/ui/app/components/app/account-list-item/account-list-item.js @@ -0,0 +1,51 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { checksumAddress } from '../../../helpers/utils/util' +import Identicon from '../../ui/identicon' +import AccountMismatchWarning from '../../ui/account-mismatch-warning/account-mismatch-warning.component' + +export default function AccountListItem ({ + account, + className, + displayAddress = false, + handleClick, + icon = null, +}) { + const { name, address, balance } = account || {} + + return ( +
handleClick && handleClick({ name, address, balance })} + > + +
+ + +
{ name || address }
+ + {icon &&
{ icon }
} + + +
+ + {displayAddress && name && ( +
+ { checksumAddress(address) } +
+ )} +
+ ) +} + +AccountListItem.propTypes = { + account: PropTypes.object, + className: PropTypes.string, + displayAddress: PropTypes.bool, + handleClick: PropTypes.func, + icon: PropTypes.node, +} diff --git a/ui/app/components/app/account-list-item/index.js b/ui/app/components/app/account-list-item/index.js new file mode 100644 index 000000000000..1759f6597e2e --- /dev/null +++ b/ui/app/components/app/account-list-item/index.js @@ -0,0 +1 @@ +export { default } from './account-list-item' diff --git a/ui/app/components/app/account-list-item/index.scss b/ui/app/components/app/account-list-item/index.scss new file mode 100644 index 000000000000..dcc08d9b5ee1 --- /dev/null +++ b/ui/app/components/app/account-list-item/index.scss @@ -0,0 +1,26 @@ +.account-list-item { + &__top-row { + display: flex; + margin-top: 10px; + margin-left: 8px; + position: relative; + } + + &__account-name { + font-size: 16px; + margin-left: 8px; + } + + &__icon { + position: absolute; + right: 12px; + top: 1px; + } + + &__account-address { + margin-left: 35px; + width: 80%; + overflow: hidden; + text-overflow: ellipsis; + } +} diff --git a/ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js b/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js similarity index 75% rename from ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js rename to ui/app/components/app/account-list-item/tests/account-list-item-component.test.js index a2949511a3e7..ee4ef3c89a02 100644 --- a/ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js +++ b/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js @@ -3,9 +3,8 @@ import assert from 'assert' import { shallow } from 'enzyme' import sinon from 'sinon' import * as utils from '../../../../helpers/utils/util' -import Identicon from '../../../../components/ui/identicon' -import UserPreferencedCurrencyDisplay from '../../../../components/app/user-preferenced-currency-display' -import AccountListItem from '../account-list-item.component' +import Identicon from '../../../ui/identicon' +import AccountListItem from '../account-list-item' describe('AccountListItem Component', function () { let wrapper, propsMethodSpies, checksumAddressStub @@ -22,11 +21,7 @@ describe('AccountListItem Component', function () { } /> @@ -113,36 +108,5 @@ describe('AccountListItem Component', function () { wrapper.setProps({ account: { address: 'someAddressButNoName' } }) assert.equal(wrapper.find('.account-list-item__account-address').length, 0) }) - - it('should render a CurrencyDisplay with the correct props if displayBalance is true', function () { - wrapper.setProps({ displayBalance: true }) - assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 2) - assert.deepEqual( - wrapper.find(UserPreferencedCurrencyDisplay).at(0).props(), - { - type: 'PRIMARY', - value: 'mockBalance', - hideTitle: true, - }, - ) - }) - - it('should only render one CurrencyDisplay if showFiat is false', function () { - wrapper.setProps({ showFiat: false, displayBalance: true }) - assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 1) - assert.deepEqual( - wrapper.find(UserPreferencedCurrencyDisplay).at(0).props(), - { - type: 'PRIMARY', - value: 'mockBalance', - hideTitle: true, - }, - ) - }) - - it('should not render a CurrencyDisplay if displayBalance is false', function () { - wrapper.setProps({ displayBalance: false }) - assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 0) - }) }) }) diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/index.scss index 5cb6fd2a7682..64136c6619e3 100644 --- a/ui/app/components/app/index.scss +++ b/ui/app/components/app/index.scss @@ -1,3 +1,4 @@ +@import 'account-list-item/index'; @import 'account-menu/index'; @import 'add-token-button/index'; @import '../ui/alert/index'; diff --git a/ui/app/components/app/signature-request-original/signature-request-original.component.js b/ui/app/components/app/signature-request-original/signature-request-original.component.js index 8587f024ed66..29e06bab6f92 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.component.js @@ -7,7 +7,7 @@ import { ObjectInspector } from 'react-inspector' import { ENVIRONMENT_TYPE_NOTIFICATION, MESSAGE_TYPE } from '../../../../../app/scripts/lib/enums' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import Identicon from '../../ui/identicon' -import AccountListItem from '../../../pages/send/account-list-item/account-list-item.component' +import AccountListItem from '../account-list-item' import { conversionUtil } from '../../../helpers/utils/conversion-util' import Button from '../../ui/button' @@ -95,7 +95,6 @@ export default class SignatureRequestOriginal extends Component {
diff --git a/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js b/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js index 89440acdca1d..2ec74748c7c1 100644 --- a/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js +++ b/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' -import AccountListItem from '../../../../pages/send/account-list-item/account-list-item.component' +import AccountListItem from '../../account-list-item' import NetworkDisplay from '../../network-display' export default class SignatureRequestHeader extends PureComponent { @@ -16,7 +16,6 @@ export default class SignatureRequestHeader extends PureComponent {
{fromAccount && ( )} diff --git a/ui/app/css/base-styles.scss b/ui/app/css/base-styles.scss index 6a970f9a3a11..5445d2f34f75 100644 --- a/ui/app/css/base-styles.scss +++ b/ui/app/css/base-styles.scss @@ -24,8 +24,6 @@ html { input:focus, textarea:focus, .unit-input__input, - .account-list-item__account-primary-balance, - .account-list-item__input, .currency-display__input { outline: none; } diff --git a/ui/app/css/itcss/components/account-dropdown.scss b/ui/app/css/itcss/components/account-dropdown.scss deleted file mode 100644 index 3d2e29b42dbf..000000000000 --- a/ui/app/css/itcss/components/account-dropdown.scss +++ /dev/null @@ -1,104 +0,0 @@ -.account-dropdown-balance { - color: $dusty-gray; - line-height: 19px; -} - -.account-dropdown-edit-button { - color: $dusty-gray; - - &:hover { - color: $white; - } -} - -.account-list-item { - &__top-row { - display: flex; - margin-top: 10px; - margin-left: 8px; - position: relative; - } - - &__tooltip-wrapper { - left: -10px; - } - - &__account-balances { - height: auto; - border: none; - background-color: transparent; - color: #9b9b9b; - margin-left: 34px; - margin-top: 4px; - position: relative; - } - - &__primary-cached-container { - display: flex; - } - - &__cached-star { - margin-left: 4px; - } - - &__cached-balances { - div:first-of-type { - color: $web-orange; - } - - div:last-of-type { - color: rgba(220, 153, 18, 0.6901960784313725); - } - } - - &__account-name { - font-size: 16px; - margin-left: 8px; - } - - &__icon { - position: absolute; - right: 12px; - top: 1px; - } - - &__account-primary-balance, - &__account-secondary-balance { - line-height: 16px; - font-size: 12px; - } - - &__balance-flag { - position: absolute; - top: 3px; - left: -8px; - color: $primary-blue; - } - - &__account-primary-balance { - color: $scorpion; - border: none; - } - - &__account-secondary-balance { - color: $dusty-gray; - } - - &__account-address { - margin-left: 35px; - width: 80%; - overflow: hidden; - text-overflow: ellipsis; - } - - &__dropdown { - &:hover { - background: rgba($alto, 0.2); - cursor: pointer; - - input { - background: rgba($alto, 0.1); - } - } - } -} diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index ea01b5060d42..e26483b32064 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -8,7 +8,6 @@ @import './network'; @import './modal'; @import './newui-sections'; -@import './account-dropdown'; @import './send'; @import './loading-overlay'; diff --git a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js index a95e6d4cded0..a054eb2b33b5 100644 --- a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js +++ b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import copyToClipboard from 'copy-to-clipboard' import classnames from 'classnames' -import AccountListItem from '../send/account-list-item/account-list-item.component' +import AccountListItem from '../../components/app/account-list-item' import Button from '../../components/ui/button' import Identicon from '../../components/ui/identicon' import Tooltip from '../../components/ui/tooltip-v2' @@ -119,7 +119,6 @@ export default class ConfirmDecryptMessage extends Component {
diff --git a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js index 5ef485c72a0d..3dbba9b8f6df 100644 --- a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js +++ b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' -import AccountListItem from '../send/account-list-item/account-list-item.component' +import AccountListItem from '../../components/app/account-list-item' import Button from '../../components/ui/button' import Identicon from '../../components/ui/identicon' @@ -99,7 +99,6 @@ export default class ConfirmEncryptionPublicKey extends Component {
diff --git a/ui/app/pages/send/account-list-item/account-list-item.component.js b/ui/app/pages/send/account-list-item/account-list-item.component.js deleted file mode 100644 index 58df336e55b6..000000000000 --- a/ui/app/pages/send/account-list-item/account-list-item.component.js +++ /dev/null @@ -1,101 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { checksumAddress } from '../../../helpers/utils/util' -import Identicon from '../../../components/ui/identicon' -import UserPreferencedCurrencyDisplay from '../../../components/app/user-preferenced-currency-display' -import { PRIMARY, SECONDARY } from '../../../helpers/constants/common' -import Tooltip from '../../../components/ui/tooltip-v2' -import AccountMismatchWarning from '../../../components/ui/account-mismatch-warning/account-mismatch-warning.component' -import { useI18nContext } from '../../../hooks/useI18nContext' - -export default function AccountListItem ({ - account, - className, - displayAddress = false, - displayBalance = true, - handleClick, - icon = null, - balanceIsCached, - showFiat = true, -}) { - const t = useI18nContext() - const { name, address, balance } = account || {} - - return ( -
handleClick && handleClick({ name, address, balance })} - > - -
- - -
{ name || address }
- - {icon &&
{ icon }
} - - -
- - {displayAddress && name && ( -
- { checksumAddress(address) } -
- )} - - {displayBalance && ( - -
-
- - { - balanceIsCached - ? * - : null - } -
- {showFiat && ( - - )} -
-
- )} - -
- ) -} - -AccountListItem.propTypes = { - account: PropTypes.object, - className: PropTypes.string, - displayAddress: PropTypes.bool, - displayBalance: PropTypes.bool, - handleClick: PropTypes.func, - icon: PropTypes.node, - balanceIsCached: PropTypes.bool, - showFiat: PropTypes.bool, -} diff --git a/ui/app/pages/send/account-list-item/account-list-item.container.js b/ui/app/pages/send/account-list-item/account-list-item.container.js deleted file mode 100644 index 40888d3ba8e4..000000000000 --- a/ui/app/pages/send/account-list-item/account-list-item.container.js +++ /dev/null @@ -1,21 +0,0 @@ -import { connect } from 'react-redux' -import { - getNativeCurrency, - getIsMainnet, - isBalanceCached, - getPreferences, -} from '../../../selectors' -import AccountListItem from './account-list-item.component' - -export default connect(mapStateToProps)(AccountListItem) - -function mapStateToProps (state) { - const { showFiatInTestnets } = getPreferences(state) - const isMainnet = getIsMainnet(state) - - return { - nativeCurrency: getNativeCurrency(state), - balanceIsCached: isBalanceCached(state), - showFiat: (isMainnet || !!showFiatInTestnets), - } -} diff --git a/ui/app/pages/send/account-list-item/index.js b/ui/app/pages/send/account-list-item/index.js deleted file mode 100644 index 907485cf773b..000000000000 --- a/ui/app/pages/send/account-list-item/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './account-list-item.container' diff --git a/ui/app/pages/send/account-list-item/tests/account-list-item-container.test.js b/ui/app/pages/send/account-list-item/tests/account-list-item-container.test.js deleted file mode 100644 index 611830d78bf6..000000000000 --- a/ui/app/pages/send/account-list-item/tests/account-list-item-container.test.js +++ /dev/null @@ -1,63 +0,0 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' - -let mapStateToProps - -proxyquire('../account-list-item.container.js', { - 'react-redux': { - connect: (ms) => { - mapStateToProps = ms - return () => ({}) - }, - }, - '../../../selectors': { - getConversionRate: () => `mockConversionRate`, - getCurrentCurrency: () => `mockCurrentCurrency`, - getNativeCurrency: () => `mockNativeCurrency`, - isBalanceCached: () => `mockBalanceIsCached`, - getPreferences: ({ showFiatInTestnets }) => ({ - showFiatInTestnets, - }), - getIsMainnet: ({ isMainnet }) => isMainnet, - }, -}) - -describe('account-list-item container', function () { - - describe('mapStateToProps()', function () { - - it('should map the correct properties to props', function () { - assert.deepEqual(mapStateToProps({ isMainnet: true, showFiatInTestnets: false }), { - nativeCurrency: 'mockNativeCurrency', - balanceIsCached: 'mockBalanceIsCached', - showFiat: true, - }) - }) - - it('should map the correct properties to props when in mainnet and showFiatInTestnet is true', function () { - assert.deepEqual(mapStateToProps({ isMainnet: true, showFiatInTestnets: true }), { - nativeCurrency: 'mockNativeCurrency', - balanceIsCached: 'mockBalanceIsCached', - showFiat: true, - }) - }) - - it('should map the correct properties to props when not in mainnet and showFiatInTestnet is true', function () { - assert.deepEqual(mapStateToProps({ isMainnet: false, showFiatInTestnets: true }), { - nativeCurrency: 'mockNativeCurrency', - balanceIsCached: 'mockBalanceIsCached', - showFiat: true, - }) - }) - - it('should map the correct properties to props when not in mainnet and showFiatInTestnet is false', function () { - assert.deepEqual(mapStateToProps({ isMainnet: false, showFiatInTestnets: false }), { - nativeCurrency: 'mockNativeCurrency', - balanceIsCached: 'mockBalanceIsCached', - showFiat: false, - }) - }) - - }) - -}) From a914eae51e87e660ec03f16789feb06e8ec6697b Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Thu, 6 Aug 2020 13:52:12 -0230 Subject: [PATCH 045/137] Adds decETHToDecWEI util method (#9141) --- ui/app/helpers/utils/conversions.util.js | 9 ++++++ ui/app/helpers/utils/conversions.util.test.js | 29 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 ui/app/helpers/utils/conversions.util.test.js diff --git a/ui/app/helpers/utils/conversions.util.js b/ui/app/helpers/utils/conversions.util.js index 5e1c21ff7cc9..0cde0d0acff7 100644 --- a/ui/app/helpers/utils/conversions.util.js +++ b/ui/app/helpers/utils/conversions.util.js @@ -129,3 +129,12 @@ export function hexWEIToDecGWEI (decGWEI) { toDenomination: 'GWEI', }) } + +export function decETHToDecWEI (decEth) { + return conversionUtil(decEth, { + fromNumericBase: 'dec', + toNumericBase: 'dec', + fromDenomination: 'ETH', + toDenomination: 'WEI', + }) +} diff --git a/ui/app/helpers/utils/conversions.util.test.js b/ui/app/helpers/utils/conversions.util.test.js new file mode 100644 index 000000000000..553fd1fd6f11 --- /dev/null +++ b/ui/app/helpers/utils/conversions.util.test.js @@ -0,0 +1,29 @@ +import * as utils from './conversions.util' +import assert from 'assert' + +describe('decETHToDecWEI', function () { + it('should correctly convert 1 ETH to WEI', function () { + const weiValue = utils.decETHToDecWEI('1') + assert.equal(weiValue, '1000000000000000000') + }) + + it('should correctly convert 0.000000000000000001 ETH to WEI', function () { + const weiValue = utils.decETHToDecWEI('0.000000000000000001') + assert.equal(weiValue, '1') + }) + + it('should correctly convert 1000000.000000000000000001 ETH to WEI', function () { + const weiValue = utils.decETHToDecWEI('1000000.000000000000000001') + assert.equal(weiValue, '1000000000000000000000001') + }) + + it('should correctly convert 9876.543210 ETH to WEI', function () { + const weiValue = utils.decETHToDecWEI('9876.543210') + assert.equal(weiValue, '9876543210000000000000') + }) + + it('should correctly convert 1.0000000000000000 ETH to WEI', function () { + const weiValue = utils.decETHToDecWEI('1.0000000000000000') + assert.equal(weiValue, '1000000000000000000') + }) +}) From 9e1aed88c24a9ec6b3f3388f1489e572d6ec2598 Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Thu, 6 Aug 2020 12:30:28 -0700 Subject: [PATCH 046/137] Update 'react-devtools' to ^4.8.0 (#9140) * bump-react-devtools * Completed yarn lock after version bump of react-devtools --- package.json | 2 +- yarn.lock | 289 ++++++++++++++++++++++++++------------------------- 2 files changed, 151 insertions(+), 140 deletions(-) diff --git a/package.json b/package.json index 578574cb9fa9..0472e8e567d7 100644 --- a/package.json +++ b/package.json @@ -255,7 +255,7 @@ "proxyquire": "^2.1.3", "randomcolor": "^0.5.4", "rc": "^1.2.8", - "react-devtools": "^4.4.0", + "react-devtools": "^4.8.0", "react-test-renderer": "^16.12.0", "read-installed": "^4.0.3", "redux-mock-store": "^1.5.4", diff --git a/yarn.lock b/yarn.lock index 885354726adf..9938af5181ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1104,6 +1104,22 @@ resolved "https://registry.yarnpkg.com/@download/blockies/-/blockies-1.0.3.tgz#9aea770f9de72f3f947f1b3a53ee1e92f8dc4a68" integrity sha512-iGDh2M6pFuXg9kyW+U//963LKylSLFpLG5hZvUppCjhkiDwsYquQPyamxCQlLASYySS3gGKAki2eWG9qIHKCew== +"@electron/get@^1.0.1": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.12.2.tgz#6442066afb99be08cefb9a281e4b4692b33764f3" + integrity sha512-vAuHUbfvBQpYTJ5wB7uVIDq5c/Ry0fiTBMs7lnEYAo/qXXppIVcWdfBr57u6eRnKdVso7KSiH6p/LbQAG6Izrg== + dependencies: + debug "^4.1.1" + env-paths "^2.2.0" + fs-extra "^8.1.0" + got "^9.6.0" + progress "^2.0.3" + sanitize-filename "^1.6.2" + sumchecker "^3.0.1" + optionalDependencies: + global-agent "^2.0.2" + global-tunnel-ng "^2.7.1" + "@emotion/cache@^10.0.27": version "10.0.27" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.27.tgz#7895db204e2c1a991ae33d51262a3a44f6737303" @@ -2604,6 +2620,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.14.tgz#a47955df2acf76ba7f0ac3b205d325da193dc9ad" integrity sha512-xXD08vZsvpv4xptQXj1+ky22f7ZoKu5ZNI/4l+/BXG3X+XaeZsmaFbbTKuhSE3NjjvRuZFxFf9sQBMXIcZNFMQ== +"@types/node@^12.0.12": + version "12.12.54" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1" + integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w== + "@types/node@^12.6.1": version "12.12.38" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.38.tgz#58841a382f231ad005dbb935c36d44aa1118a26b" @@ -5490,6 +5511,11 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +boolean@^3.0.0, boolean@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.1.tgz#35ecf2b4a2ee191b0b44986f14eb5f052a5cbb4f" + integrity sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA== + boom@^7.2.0: version "7.3.0" resolved "https://registry.yarnpkg.com/boom/-/boom-7.3.0.tgz#733a6d956d33b0b1999da3fe6c12996950d017b9" @@ -7326,6 +7352,11 @@ core-js@^3.0.4: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647" integrity sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw== +core-js@^3.6.5: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" + integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -7999,14 +8030,6 @@ d@1: dependencies: es5-ext "^0.10.9" -d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - dash-ast@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dash-ast/-/dash-ast-1.0.0.tgz#12029ba5fb2f8aa6f0a861795b23c1b4b6c27d37" @@ -8124,7 +8147,7 @@ debug-fabulous@1.X: memoizee "0.4.X" object-assign "4.X" -debug@2, debug@2.6.9, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: +debug@2, debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -9047,21 +9070,6 @@ ejs@^3.0.2: dependencies: jake "^10.6.1" -electron-download@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8" - integrity sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg== - dependencies: - debug "^3.0.0" - env-paths "^1.0.0" - fs-extra "^4.0.1" - minimist "^1.2.0" - nugget "^2.0.1" - path-exists "^3.0.0" - rc "^1.2.1" - semver "^5.4.1" - sumchecker "^2.0.2" - electron-to-chromium@^1.3.122: version "1.3.146" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.146.tgz#d7010f417f87c2068fbb6700ae57767e2393eba7" @@ -9077,13 +9085,13 @@ electron-to-chromium@^1.3.47, electron-to-chromium@^1.3.488: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.498.tgz#fd7188c8a49d6d0b5df1df55a1f1a4bf2c177457" integrity sha512-W1hGwaQEU8j9su2jeAr3aabkPuuXw+j8t73eajGAkEJWbfWiwbxBwQN/8Qmv2qCy3uCDm2rOAaZneYQM8VGC4w== -electron@^5.0.0: - version "5.0.12" - resolved "https://registry.yarnpkg.com/electron/-/electron-5.0.12.tgz#2d5438f8e2b8b99ea99848b61238fc66c283e861" - integrity sha512-Ydby8wfShB39MkZCF2PcAuNACj4PYbGxc0hGpThqZOiDgnSVroqvUAOSX9GCJogrjcP30ZZIe6TgPtQEABYg3w== +electron@^9.1.0: + version "9.1.2" + resolved "https://registry.yarnpkg.com/electron/-/electron-9.1.2.tgz#bfa26d6b192ea13abb6f1461371fd731a8358988" + integrity sha512-xEYadr3XqIqJ4ktBPo0lhzPdovv4jLCpiUUGc2M1frUhFhwqXokwhPaTUcE+zfu5+uf/ONDnQApwjzznBsRrgQ== dependencies: - "@types/node" "^10.12.18" - electron-download "^4.1.0" + "@electron/get" "^1.0.1" + "@types/node" "^12.0.12" extract-zip "^1.0.3" element-resize-detector@^1.2.1: @@ -9247,10 +9255,10 @@ env-ci@^2.1.0: execa "^1.0.0" java-properties "^0.2.9" -env-paths@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" - integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA= +env-paths@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" + integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== envify@^4.1.0: version "4.1.0" @@ -9480,7 +9488,7 @@ es5-shim@^4.5.13: resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.5.13.tgz#5d88062de049f8969f83783f4a4884395f21d28b" integrity sha512-xi6hh6gsvDE0MaW4Vp1lgNEBpVcCXRWfPXj5egDvtgLz4L9MEvNwYEMdJH+JJinWkwa8c3c3o5HduV7dB/e1Hw== -es6-error@^4.0.1: +es6-error@^4.0.1, es6-error@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== @@ -9547,14 +9555,6 @@ es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: d "1" es5-ext "~0.10.14" -es6-symbol@^3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== - dependencies: - d "^1.0.1" - ext "^1.1.2" - es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" @@ -9580,6 +9580,11 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + escodegen@1.x.x, escodegen@^1.11.1, escodegen@^1.9.0, escodegen@^1.9.1: version "1.14.3" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" @@ -11022,13 +11027,6 @@ ext-name@^5.0.0: ext-list "^2.0.0" sort-keys-length "^1.0.0" -ext@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" - integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== - dependencies: - type "^2.0.0" - extend-shallow@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" @@ -11886,7 +11884,7 @@ fs-extra@^1.0.0: jsonfile "^2.1.0" klaw "^1.0.0" -fs-extra@^4.0.1, fs-extra@^4.0.2: +fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== @@ -12420,6 +12418,19 @@ glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" +global-agent@^2.0.2: + version "2.1.12" + resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-2.1.12.tgz#e4ae3812b731a9e81cbf825f9377ef450a8e4195" + integrity sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg== + dependencies: + boolean "^3.0.1" + core-js "^3.6.5" + es6-error "^4.1.1" + matcher "^3.0.0" + roarr "^2.15.3" + semver "^7.3.2" + serialize-error "^7.0.1" + global-dirs@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" @@ -12463,6 +12474,16 @@ global-prefix@^3.0.0: kind-of "^6.0.2" which "^1.3.1" +global-tunnel-ng@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz#d03b5102dfde3a69914f5ee7d86761ca35d57d8f" + integrity sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg== + dependencies: + encodeurl "^1.0.2" + lodash "^4.17.10" + npm-conf "^1.1.3" + tunnel "^0.0.6" + global@^4.3.2, global@~4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" @@ -12505,6 +12526,13 @@ globalthis@^1.0.0: function-bind "^1.1.1" object-keys "^1.0.12" +globalthis@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.1.tgz#40116f5d9c071f9e8fb0037654df1ab3a83b7ef9" + integrity sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw== + dependencies: + define-properties "^1.1.3" + globby@8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" @@ -17684,6 +17712,13 @@ matchdep@^2.0.0: resolve "^1.4.0" stack-trace "0.0.10" +matcher@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" + integrity sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng== + dependencies: + escape-string-regexp "^4.0.0" + material-colors@^1.2.1: version "1.2.5" resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.5.tgz#5292593e6754cb1bcc2b98030e4e0d6a3afc9ea1" @@ -17813,7 +17848,7 @@ memory-fs@^0.4.0, memory-fs@^0.4.1: errno "^0.1.3" readable-stream "^2.0.1" -meow@^3.1.0, meow@^3.3.0, meow@^3.7.0: +meow@^3.3.0, meow@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= @@ -18145,7 +18180,7 @@ minimist-options@^4.0.2: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.0: +minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@~1.2.0: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -19105,7 +19140,7 @@ npm-bundled@^1.0.1: resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== -npm-conf@^1.1.0: +npm-conf@^1.1.0, npm-conf@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== @@ -19152,19 +19187,6 @@ nth-check@~1.0.1: dependencies: boolbase "~1.0.0" -nugget@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nugget/-/nugget-2.0.1.tgz#201095a487e1ad36081b3432fa3cada4f8d071b0" - integrity sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA= - dependencies: - debug "^2.1.3" - minimist "^1.1.0" - pretty-bytes "^1.0.2" - progress-stream "^1.1.0" - request "^2.45.0" - single-line-log "^1.1.2" - throttleit "0.0.2" - num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" @@ -21042,14 +21064,6 @@ preserve@^0.2.0: resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= -pretty-bytes@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-1.0.4.tgz#0a22e8210609ad35542f8c8d5d2159aff0751c84" - integrity sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ= - dependencies: - get-stdin "^4.0.1" - meow "^3.1.0" - pretty-bytes@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" @@ -21123,14 +21137,6 @@ process@~0.5.1: resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= -progress-stream@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-1.2.0.tgz#2cd3cfea33ba3a89c9c121ec3347abe9ab125f77" - integrity sha1-LNPP6jO6OonJwSHsM0er6asSX3c= - dependencies: - speedometer "~0.1.2" - through2 "~0.2.3" - progress-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-2.0.0.tgz#fac63a0b3d11deacbb0969abcc93b214bce19ed5" @@ -21851,7 +21857,7 @@ raw-loader@^3.1.0: loader-utils "^1.1.0" schema-utils "^2.0.1" -rc@^1.0.1, rc@^1.1.6, rc@^1.2.1, rc@^1.2.7, rc@^1.2.8: +rc@^1.0.1, rc@^1.1.6, rc@^1.2.7, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -21911,25 +21917,24 @@ react-dev-utils@^9.0.0: strip-ansi "5.2.0" text-table "0.2.0" -react-devtools-core@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.4.0.tgz#614cabe5f3d6fb69730dc76da10f8fa4eb033695" - integrity sha512-ayyz+clbjekj5rqTjieI/eE0xGZkgotklVnxfa4Pyk9se5+AHUAhUwMhLvK5N2+mR2PGOZkv159RDTmvgs+wZQ== +react-devtools-core@4.8.2: + version "4.8.2" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.8.2.tgz#4465f2e8de7795564aa20f28b2f3a9737586db23" + integrity sha512-3Lv3nI8FPAwKqUco35oOlgf+4j8mgYNnIcDv2QTfxEqg2G69q17ZJ8ScU9aBnymS28YC1OW+kTxLmdIQeTN8yg== dependencies: - es6-symbol "^3" shell-quote "^1.6.1" ws "^7" -react-devtools@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/react-devtools/-/react-devtools-4.4.0.tgz#03df973d889583bc75afdf3352d3bb29141b3f36" - integrity sha512-Wfa7re+BJGy8fyYodbOfjB1YILKspmfgXLSZ0nPaVvaCpfy2lEqy3Unz5bOzOWoFsDldg7wVL2Xy0LOjd3rz1A== +react-devtools@^4.8.0: + version "4.8.2" + resolved "https://registry.yarnpkg.com/react-devtools/-/react-devtools-4.8.2.tgz#24c2e1d4975ac087665ab48c925cd418a97797c2" + integrity sha512-NGANnExgSsd34IGJlKURCBtDG6Avi2LeWcqfLQ7/oG7khCT6Wm390ZM+GBnI1gGnZD7y/h7oWXd5B/Dp2s5s6Q== dependencies: cross-spawn "^5.0.1" - electron "^5.0.0" + electron "^9.1.0" ip "^1.1.4" - minimist "^1.2.0" - react-devtools-core "4.4.0" + minimist "^1.2.3" + react-devtools-core "4.8.2" update-notifier "^2.1.0" react-dnd-html5-backend@^7.4.4: @@ -22429,7 +22434,7 @@ read-pkg@^5.2.0: string_decoder "~1.0.3" util-deprecate "~1.0.1" -readable-stream@1.1, readable-stream@1.1.x, readable-stream@^1.0.33, readable-stream@~1.1.9: +readable-stream@1.1, readable-stream@1.1.x, readable-stream@^1.0.33: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= @@ -23054,7 +23059,7 @@ request-promise-native@^1.0.5: tunnel-agent "^0.6.0" uuid "^3.3.2" -request@^2.45.0, request@^2.81.0, request@^2.83.0: +request@^2.81.0, request@^2.83.0: version "2.87.0" resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" integrity sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw== @@ -23349,6 +23354,18 @@ rn-host-detect@^1.1.5: resolved "https://registry.yarnpkg.com/rn-host-detect/-/rn-host-detect-1.1.5.tgz#fbecb982b73932f34529e97932b9a63e58d8deb6" integrity sha512-ufk2dFT3QeP9HyZ/xTuMtW27KnFy815CYitJMqQm+pgG3ZAtHBsrU8nXizNKkqXGy3bQmhEoloVbrfbvMJMqkg== +roarr@^2.15.3: + version "2.15.3" + resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.3.tgz#65248a291a15af3ebfd767cbf7e44cb402d1d836" + integrity sha512-AEjYvmAhlyxOeB9OqPUzQCo3kuAkNfuDk/HqWbZdFsqDFpapkTjiw+p4svNEoRLvuqNTxqfL+s+gtD4eDgZ+CA== + dependencies: + boolean "^3.0.0" + detect-node "^2.0.4" + globalthis "^1.0.1" + json-stringify-safe "^5.0.1" + semver-compare "^1.0.0" + sprintf-js "^1.1.2" + rpc-cap@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/rpc-cap/-/rpc-cap-3.1.0.tgz#61ae8ca27c43da93f40972393ff34df1a28c3b5e" @@ -23507,6 +23524,13 @@ sanitize-filename@^1.6.1: dependencies: truncate-utf8-bytes "^1.0.0" +sanitize-filename@^1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" + integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== + dependencies: + truncate-utf8-bytes "^1.0.0" + sass-graph@2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8" @@ -23757,6 +23781,11 @@ semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + semver-diff@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" @@ -23808,6 +23837,11 @@ semver@^6.0.0, semver@^6.1.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.1.tgz#53f53da9b30b2103cd4f15eab3a18ecbcb210c9b" integrity sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ== +semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -23832,6 +23866,13 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" +serialize-error@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18" + integrity sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw== + dependencies: + type-fest "^0.13.1" + serialize-javascript@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" @@ -24162,13 +24203,6 @@ single-call-balance-checker-abi@^1.0.0: resolved "https://registry.yarnpkg.com/single-call-balance-checker-abi/-/single-call-balance-checker-abi-1.0.0.tgz#b369009fd4cc6214968cdba650ad93986315d92d" integrity sha512-T5fRBJHmGEMe76JFGB36gcZnOh1ip2S7Qsp7cwmwrfMRjadxTe02zJHtXERpnQf2yvSqNWRxvae5f6e8v4rhng== -single-line-log@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-1.1.2.tgz#c2f83f273a3e1a16edb0995661da0ed5ef033364" - integrity sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q= - dependencies: - string-width "^1.0.1" - sinon@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.0.0.tgz#9f1ed502fa2e287e65220de08f6a44f33e314006" @@ -24562,11 +24596,6 @@ specificity@^0.4.1: resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019" integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg== -speedometer@~0.1.2: - version "0.1.4" - resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d" - integrity sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0= - speedometer@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-1.0.0.tgz#cd671cb06752c22bca3370e2f334440be4fc62e2" @@ -24607,7 +24636,7 @@ split@^1.0.1: dependencies: through "2" -sprintf-js@1.1.2: +sprintf-js@1.1.2, sprintf-js@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== @@ -25284,12 +25313,12 @@ sugarss@^2.0.0: dependencies: postcss "^7.0.2" -sumchecker@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-2.0.2.tgz#0f42c10e5d05da5d42eea3e56c3399a37d6c5b3e" - integrity sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4= +sumchecker@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42" + integrity sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg== dependencies: - debug "^2.2.0" + debug "^4.1.0" summary@0.3.x: version "0.3.2" @@ -25773,11 +25802,6 @@ throttle-debounce@^2.1.0: resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5" integrity sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg== -throttleit@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" - integrity sha1-z+34jmDADdlpe2H90qg0OptoDq8= - throttleit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" @@ -25821,14 +25845,6 @@ through2@^2.0.2, through2@^2.0.5: readable-stream "~2.3.6" xtend "~4.0.1" -through2@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f" - integrity sha1-6zKE2k6jEbbMis42U3SKUqvyWj8= - dependencies: - readable-stream "~1.1.9" - xtend "~2.1.1" - through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.7, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -26233,6 +26249,11 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + tweetnacl-util@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.0.tgz#4576c1cee5e2d63d207fee52f1ba02819480bc75" @@ -26303,16 +26324,6 @@ type-is@^1.6.16, type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" - integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== - typed-styles@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" From 365a096e5b58307fe4c22b8c0e7c3ce796ba6227 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Thu, 6 Aug 2020 15:45:02 -0700 Subject: [PATCH 047/137] remove .network-name height --- ui/app/css/itcss/components/network.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/app/css/itcss/components/network.scss b/ui/app/css/itcss/components/network.scss index ef8e7843ff86..31ca8c201654 100644 --- a/ui/app/css/itcss/components/network.scss +++ b/ui/app/css/itcss/components/network.scss @@ -74,7 +74,6 @@ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; - height: 16px; } .dropdown-menu-item .fa.delete { From d0366ad8f21bdded8d0ede99d3bbb72bc06529ba Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 7 Aug 2020 12:33:03 -0230 Subject: [PATCH 048/137] Use luxon@1.24.1 (#9154) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 0472e8e567d7..59b494bff86d 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "jsonschema": "^1.2.4", "lodash": "^4.17.19", "loglevel": "^1.4.1", - "luxon": "^1.23.0", + "luxon": "^1.24.1", "metamask-logo": "^2.1.4", "multihashes": "^0.4.12", "nanoid": "^2.1.6", diff --git a/yarn.lock b/yarn.lock index 9938af5181ca..9d4efe99f625 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17590,10 +17590,10 @@ ltgt@~2.1.1: resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" integrity sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ= -luxon@^1.23.0: - version "1.23.0" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.23.0.tgz#23b748ad0f2d5494dc4d2878c19278c1e651410c" - integrity sha512-+6a/bXsCWrrR8vfbL41iM92es12zwV2Rum/KPkT+ubOZnnU3Sqbqok/FmD1xsWlWN2Y9Hu0fU/vNgU24ns7bpA== +luxon@^1.24.1: + version "1.24.1" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.24.1.tgz#a8383266131ed4eaed4b5f430f96f3695403a52a" + integrity sha512-CgnIMKAWT0ghcuWFfCWBnWGOddM0zu6c4wZAWmD0NN7MZTnro0+833DF6tJep+xlxRPg4KtsYEHYLfTMBQKwYg== mafmt@^6.0.0, mafmt@^6.0.2, mafmt@^6.0.4, mafmt@^6.0.7: version "6.0.7" From 85e658993b6a6f0ccf459b644e191bb40754cdab Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Fri, 7 Aug 2020 10:25:00 -0500 Subject: [PATCH 049/137] colocate notification-modal styles (#9147) Follows former examples of colocating styles with the modals that use them. --- ui/app/components/app/modals/index.scss | 1 + .../app/modals/notification-modal/index.js | 1 + .../app/modals/notification-modal/index.scss | 56 +++++++++++ .../notification-modal.js | 2 +- ui/app/css/itcss/components/modal.scss | 94 ------------------- 5 files changed, 59 insertions(+), 95 deletions(-) create mode 100644 ui/app/components/app/modals/notification-modal/index.js create mode 100644 ui/app/components/app/modals/notification-modal/index.scss rename ui/app/components/app/modals/{ => notification-modal}/notification-modal.js (97%) diff --git a/ui/app/components/app/modals/index.scss b/ui/app/components/app/modals/index.scss index ebb662b96fbe..c7f01b20b7dd 100644 --- a/ui/app/components/app/modals/index.scss +++ b/ui/app/components/app/modals/index.scss @@ -1,5 +1,6 @@ @import 'cancel-transaction/index'; @import 'confirm-remove-account/index'; +@import 'notification-modal/index'; @import 'qr-scanner/index'; @import 'transaction-confirmed/index'; @import 'metametrics-opt-in-modal/index'; diff --git a/ui/app/components/app/modals/notification-modal/index.js b/ui/app/components/app/modals/notification-modal/index.js new file mode 100644 index 000000000000..a2aab7c1d6b4 --- /dev/null +++ b/ui/app/components/app/modals/notification-modal/index.js @@ -0,0 +1 @@ +export { default } from './notification-modal' diff --git a/ui/app/components/app/modals/notification-modal/index.scss b/ui/app/components/app/modals/notification-modal/index.scss new file mode 100644 index 000000000000..93e085496967 --- /dev/null +++ b/ui/app/components/app/modals/notification-modal/index.scss @@ -0,0 +1,56 @@ +.notification-modal { + &__wrapper { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; + position: relative; + border: 1px solid $alto; + box-shadow: 0 0 2px 2px $alto; + } + + &__header { + background: $wild-sand; + width: 100%; + display: flex; + justify-content: center; + padding: 30px; + font-size: 22px; + color: $nile-blue; + } + + &__message { + padding: 20px; + width: 100%; + display: flex; + justify-content: center; + font-size: 17px; + color: $nile-blue; + } + + &__buttons { + display: flex; + justify-content: space-evenly; + width: 100%; + margin-bottom: 24px; + padding: 0 42px; + + &__btn { + cursor: pointer; + } + } + + &__link { + color: $primary-blue; + } + + .modal-close-x::after { + content: '\00D7'; + font-size: 2em; + color: $dusty-gray; + position: absolute; + top: 25px; + right: 17.5px; + cursor: pointer; + } +} diff --git a/ui/app/components/app/modals/notification-modal.js b/ui/app/components/app/modals/notification-modal/notification-modal.js similarity index 97% rename from ui/app/components/app/modals/notification-modal.js rename to ui/app/components/app/modals/notification-modal/notification-modal.js index 7fe776934c68..71f826747afc 100644 --- a/ui/app/components/app/modals/notification-modal.js +++ b/ui/app/components/app/modals/notification-modal/notification-modal.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' import { connect } from 'react-redux' -import { hideModal } from '../../../store/actions' +import { hideModal } from '../../../../store/actions' class NotificationModal extends Component { static contextProps = { diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index 318cfb1ee91c..7b63ffd9f9ee 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -212,16 +212,6 @@ padding: 9px 13px 8px; } -.modal-close-x::after { - content: '\00D7'; - font-size: 2em; - color: $dusty-gray; - position: absolute; - top: 25px; - right: 17.5px; - cursor: pointer; -} - // Hide token confirmation .hide-token-confirmation { @@ -286,55 +276,6 @@ } } -//Notification Modal - -.notification-modal { - &__wrapper { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: center; - position: relative; - border: 1px solid $alto; - box-shadow: 0 0 2px 2px $alto; - } - - &__header { - background: $wild-sand; - width: 100%; - display: flex; - justify-content: center; - padding: 30px; - font-size: 22px; - color: $nile-blue; - } - - &__message { - padding: 20px; - width: 100%; - display: flex; - justify-content: center; - font-size: 17px; - color: $nile-blue; - } - - &__buttons { - display: flex; - justify-content: space-evenly; - width: 100%; - margin-bottom: 24px; - padding: 0 42px; - - &__btn { - cursor: pointer; - } - } - - &__link { - color: $primary-blue; - } -} - // Deposit Ether Modal .deposit-ether-modal { border-radius: 8px; @@ -498,38 +439,3 @@ text-align: center; } } - -//Notification Modal - -.notification-modal-wrapper { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: center; - position: relative; - border: 1px solid $alto; - box-shadow: 0 0 2px 2px $alto; -} - -.notification-modal-header { - background: $wild-sand; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - padding: 30px; - font-size: 22px; - color: $nile-blue; -} - -.notification-modal-message { - padding: 20px; -} - -.notification-modal-message { - width: 100%; - display: flex; - justify-content: center; - font-size: 17px; - color: $nile-blue; -} From f3ba18d79fb2bc833fb4ed166e906a87e1ece3b3 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Fri, 7 Aug 2020 10:58:48 -0500 Subject: [PATCH 050/137] remove unused section scss (#9146) --- test/e2e/ethereum-on.spec.js | 2 +- test/e2e/from-import-ui.spec.js | 6 +- test/e2e/incremental-security.spec.js | 2 +- test/e2e/metamask-ui.spec.js | 2 +- test/e2e/permissions.spec.js | 2 +- test/e2e/signature-request.spec.js | 2 +- ui/app/components/app/account-panel.js | 63 --- ui/app/components/app/index.scss | 2 + .../export-private-key-modal.component.js | 1 - ui/app/components/ui/qr-code/index.js | 1 + ui/app/components/ui/qr-code/index.scss | 25 + ui/app/components/ui/{ => qr-code}/qr-code.js | 17 +- ui/app/components/ui/readonly-input/index.js | 1 + .../components/ui/readonly-input/index.scss | 8 + .../ui/{ => readonly-input}/readonly-input.js | 5 +- ui/app/css/base-styles.scss | 22 + ui/app/css/itcss/components/index.scss | 1 - ui/app/css/itcss/components/modal.scss | 4 +- ui/app/css/itcss/components/sections.scss | 426 ------------------ ui/app/css/itcss/tools/utilities.scss | 8 - .../mobile-sync/mobile-sync.component.js | 1 - 21 files changed, 80 insertions(+), 521 deletions(-) delete mode 100644 ui/app/components/app/account-panel.js create mode 100644 ui/app/components/ui/qr-code/index.js create mode 100644 ui/app/components/ui/qr-code/index.scss rename ui/app/components/ui/{ => qr-code}/qr-code.js (79%) create mode 100644 ui/app/components/ui/readonly-input/index.js create mode 100644 ui/app/components/ui/readonly-input/index.scss rename ui/app/components/ui/{ => readonly-input}/readonly-input.js (78%) delete mode 100644 ui/app/css/itcss/components/sections.scss diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index e7412ac689cc..361579cd2c23 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -89,7 +89,7 @@ describe('MetaMask', function () { }) it('gets the current accounts address', async function () { - const addressInput = await driver.findElement(By.css('.qr-ellip-address')) + const addressInput = await driver.findElement(By.css('.readonly-input__input')) publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index 7a112c7221d3..78bdd03528f7 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -99,10 +99,10 @@ describe('Using MetaMask with an existing account', function () { it('shows the correct account address', async function () { await driver.clickElement(By.css('[data-testid="account-options-menu-button"]')) await driver.clickElement(By.css('[data-testid="account-options-menu__account-details"]')) - await driver.findVisibleElement(By.css('.qr-wrapper')) + await driver.findVisibleElement(By.css('.qr-code__wrapper')) await driver.delay(regularDelayMs) - const [address] = await driver.findElements(By.css('input.qr-ellip-address')) + const [address] = await driver.findElements(By.css('.readonly-input__input')) assert.equal(await address.getAttribute('value'), testAddress) await driver.clickElement(By.css('.account-modal-close')) @@ -112,7 +112,7 @@ describe('Using MetaMask with an existing account', function () { it('shows a QR code for the account', async function () { await driver.clickElement(By.css('[data-testid="account-options-menu-button"]')) await driver.clickElement(By.css('[data-testid="account-options-menu__account-details"]')) - await driver.findVisibleElement(By.css('.qr-wrapper')) + await driver.findVisibleElement(By.css('.qr-code__wrapper')) const detailModal = await driver.findElement(By.css('span .modal')) await driver.delay(regularDelayMs) diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 82e3fc0e016a..a6482c58d90f 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -95,7 +95,7 @@ describe('MetaMask', function () { }) it('gets the current accounts address', async function () { - const addressInput = await driver.findElement(By.css('.qr-ellip-address')) + const addressInput = await driver.findElement(By.css('.readonly-input__input')) publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 15d0198cd446..d501bdb3ac38 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -121,7 +121,7 @@ describe('MetaMask', function () { it('shows the QR code for the account', async function () { await driver.clickElement(By.css('[data-testid="account-options-menu-button"]')) await driver.clickElement(By.css('[data-testid="account-options-menu__account-details"]')) - await driver.findVisibleElement(By.css('.qr-wrapper')) + await driver.findVisibleElement(By.css('.qr-code__wrapper')) await driver.delay(regularDelayMs) const accountModal = await driver.findElement(By.css('span .modal')) diff --git a/test/e2e/permissions.spec.js b/test/e2e/permissions.spec.js index 8ec86b3cbceb..3d45e447784c 100644 --- a/test/e2e/permissions.spec.js +++ b/test/e2e/permissions.spec.js @@ -90,7 +90,7 @@ describe('MetaMask', function () { }) it('gets the current accounts address', async function () { - const addressInput = await driver.findElement(By.css('.qr-ellip-address')) + const addressInput = await driver.findElement(By.css('.readonly-input__input')) publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) diff --git a/test/e2e/signature-request.spec.js b/test/e2e/signature-request.spec.js index 6e2a558ec597..9abac241b849 100644 --- a/test/e2e/signature-request.spec.js +++ b/test/e2e/signature-request.spec.js @@ -124,7 +124,7 @@ describe('MetaMask', function () { await driver.clickElement(By.css('[data-testid="account-options-menu__account-details"]')) await driver.delay(regularDelayMs) - const addressInput = await driver.findElement(By.css('.qr-ellip-address')) + const addressInput = await driver.findElement(By.css('.readonly-input__input')) const newPublicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) diff --git a/ui/app/components/app/account-panel.js b/ui/app/components/app/account-panel.js deleted file mode 100644 index 36517f474b95..000000000000 --- a/ui/app/components/app/account-panel.js +++ /dev/null @@ -1,63 +0,0 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import Identicon from '../ui/identicon' -import { addressSummary, formatBalance } from '../../helpers/utils/util' - -export default class AccountPanel extends Component { - static propTypes = { - identity: PropTypes.object, - account: PropTypes.object, - isFauceting: PropTypes.bool, - } - - static defaultProps = { - identity: {}, - account: {}, - isFauceting: false, - } - - render () { - const { identity, account, isFauceting } = this.props - - const panelState = { - key: `accountPanel${identity.address}`, - identiconKey: identity.address, - identiconLabel: identity.name || '', - attributes: [ - { - key: 'ADDRESS', - value: addressSummary(identity.address), - }, - balanceOrFaucetingIndication(account, isFauceting), - ], - } - - return ( -
-
- - {panelState.identiconLabel.substring(0, 7) + '...'} -
-
- {panelState.attributes.map((attr, index) => ( -
- - {attr.value} -
- ))} -
-
- ) - } -} - -function balanceOrFaucetingIndication (account) { - return { - key: 'BALANCE', - value: formatBalance(account.balance), - } -} diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/index.scss index 64136c6619e3..69ed2bb231f1 100644 --- a/ui/app/components/app/index.scss +++ b/ui/app/components/app/index.scss @@ -24,6 +24,8 @@ @import '../ui/page-container/index'; @import '../../pages/index'; @import 'permission-page-container/index'; +@import '../ui/qr-code/index'; +@import '../ui/readonly-input/index'; @import 'selected-account/index'; @import '../ui/sender-to-recipient/index'; @import '../ui/tabs/index'; diff --git a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js index 695762b7329a..318dd0d5891b 100644 --- a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js +++ b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js @@ -146,7 +146,6 @@ export default class ExportPrivateKeyModal extends Component { {name}
diff --git a/ui/app/components/ui/qr-code/index.js b/ui/app/components/ui/qr-code/index.js new file mode 100644 index 000000000000..f638ae4fb393 --- /dev/null +++ b/ui/app/components/ui/qr-code/index.js @@ -0,0 +1 @@ +export { default } from './qr-code' diff --git a/ui/app/components/ui/qr-code/index.scss b/ui/app/components/ui/qr-code/index.scss new file mode 100644 index 000000000000..86bd5af4332a --- /dev/null +++ b/ui/app/components/ui/qr-code/index.scss @@ -0,0 +1,25 @@ +.qr-code { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + &__message-container > div:first-child { + margin-top: 18px; + font-size: 15px; + color: #4d4d4d; + } + + &__message { + font-size: 12px; + color: #f7861c; + } + + &__error { + display: flex; + justify-content: center; + align-items: center; + color: #f7861c; + margin-bottom: 9px; + } +} diff --git a/ui/app/components/ui/qr-code.js b/ui/app/components/ui/qr-code/qr-code.js similarity index 79% rename from ui/app/components/ui/qr-code.js rename to ui/app/components/ui/qr-code/qr-code.js index 267277c011b0..0ddf6caa6783 100644 --- a/ui/app/components/ui/qr-code.js +++ b/ui/app/components/ui/qr-code/qr-code.js @@ -3,8 +3,8 @@ import React from 'react' import qrCode from 'qrcode-generator' import { connect } from 'react-redux' import { isHexPrefixed } from 'ethereumjs-util' -import ReadOnlyInput from './readonly-input' -import { checksumAddress } from '../../helpers/utils/util' +import ReadOnlyInput from '../readonly-input/readonly-input' +import { checksumAddress } from '../../../helpers/utils/util' export default connect(mapStateToProps)(QrCodeView) @@ -24,20 +24,20 @@ function QrCodeView (props) { qrImage.make() return ( -
+
{ Array.isArray(message) ? ( -
+
{props.Qr.message.map((message, index) => ( -
+
{message}
))}
) : message && ( -
+
{message}
) @@ -45,21 +45,20 @@ function QrCodeView (props) { { props.warning ? (props.warning && ( - + {props.warning} )) : null }
diff --git a/ui/app/components/ui/readonly-input/index.js b/ui/app/components/ui/readonly-input/index.js new file mode 100644 index 000000000000..151a02ee8770 --- /dev/null +++ b/ui/app/components/ui/readonly-input/index.js @@ -0,0 +1 @@ +export { default } from './readonly-input' diff --git a/ui/app/components/ui/readonly-input/index.scss b/ui/app/components/ui/readonly-input/index.scss new file mode 100644 index 000000000000..9eff60bbb161 --- /dev/null +++ b/ui/app/components/ui/readonly-input/index.scss @@ -0,0 +1,8 @@ +.readonly-input { + &__input { + direction: ltr; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + } +} diff --git a/ui/app/components/ui/readonly-input.js b/ui/app/components/ui/readonly-input/readonly-input.js similarity index 78% rename from ui/app/components/ui/readonly-input.js rename to ui/app/components/ui/readonly-input/readonly-input.js index b884da1bcb1c..eba6fd6c2e1c 100644 --- a/ui/app/components/ui/readonly-input.js +++ b/ui/app/components/ui/readonly-input/readonly-input.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types' import React from 'react' +import classnames from 'classnames' export default function ReadOnlyInput (props) { const { @@ -13,9 +14,9 @@ export default function ReadOnlyInput (props) { const InputType = textarea ? 'textarea' : 'input' return ( -
+
event.target.select()} diff --git a/ui/app/css/base-styles.scss b/ui/app/css/base-styles.scss index 5445d2f34f75..8b2220f9c6aa 100644 --- a/ui/app/css/base-styles.scss +++ b/ui/app/css/base-styles.scss @@ -29,6 +29,28 @@ html { } } +/* + This error class is used in the following files still: + /ui/app/pages/create-account/connect-hardware/index.js + /ui/app/pages/create-account/import-account/json.js + /ui/app/pages/create-account/import-account/private-key.js + /ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js + /ui/app/pages/keychains/restore-vault.js +*/ +.error { + color: #f7861c; + margin-bottom: 9px; +} + +/* + This warning class is used in the following files still: + /ui/app/pages/create-account/import-account/json.js + /ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js +*/ +.warning { + color: #ffae00; +} + /* stylelint-disable */ #app-content { overflow-x: hidden; diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index e26483b32064..1936706dcb72 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -12,7 +12,6 @@ @import './loading-overlay'; // Tx List and Sections -@import './sections'; @import './menu'; @import './gas-slider'; @import './tab-bar'; diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index 7b63ffd9f9ee..8d47c753e9df 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -85,12 +85,12 @@ // Account Details Modal .account-modal-container { - .qr-header { + .qr-code__header { margin-top: 9px; font-size: 20px; } - .qr-wrapper { + .qr-code__wrapper { margin-top: 5px; } diff --git a/ui/app/css/itcss/components/sections.scss b/ui/app/css/itcss/components/sections.scss deleted file mode 100644 index 4ddda782a883..000000000000 --- a/ui/app/css/itcss/components/sections.scss +++ /dev/null @@ -1,426 +0,0 @@ -// Old scss, do not lint - clean up later -/* stylelint-disable */ - - -/* -App Sections - TODO: Move into separate files. -*/ - -/* initialize */ -textarea.twelve-word-phrase { - padding: 12px; - width: 300px; - height: 140px; - font-size: 16px; - background: $white; - resize: none; -} - -.initialize-screen { - width: 100%; - z-index: $main-container-z-index; - background: #f7f7f7; -} - -.initialize-screen hr { - width: 60px; - margin: 12px; - border-color: #f7861c; - border-style: solid; -} - -.initialize-screen label { - margin-top: 20px; -} - -.initialize-screen button.create-vault { - margin-top: 40px; -} - -.initialize-screen .warning { - font-size: 14px; - margin: 0 16px; -} - -/* unlock */ -.error { - color: #f7861c; - margin-bottom: 9px; -} - -.warning { - color: #ffae00; -} - -.lock { - width: 50px; - height: 50px; -} - -.lock.locked { - transform: scale(1.5); - opacity: 0; - transition: opacity 400ms ease-in, transform 400ms ease-in; -} - -.lock.unlocked { - transform: scale(1); - opacity: 1; - transition: opacity 500ms ease-out, transform 500ms ease-out, background 200ms ease-in; -} - -.lock.locked .lock-top { - transform: scaleX(1) translateX(0); - transition: transform 250ms ease-in; -} - -.lock.unlocked .lock-top { - transform: scaleX(-1) translateX(-12px); - transition: transform 250ms ease-in; -} - -.lock.unlocked:hover { - border-radius: 4px; - background: #e5e5e5; - border: 1px solid #b1b1b1; -} - -.lock.unlocked:active { - background: #c3c3c3; -} - -.section-title .fa-arrow-left { - margin: -2px 8px 0 -8px; -} - -.sizing-input { - font-size: 14px; - height: 30px; - padding-left: 5px; -} - -/* accounts */ - -.accounts-section { - margin: 0 0; -} - -.accounts-section .horizontal-line { - margin: 0 18px; -} - -.accounts-list-option { - height: 120px; -} - -.accounts-list-option .identicon-wrapper { - width: 100px; -} - -.unconftx-link { - margin-top: 24px; - cursor: pointer; -} - -.unconftx-link .fa-arrow-right { - margin: 0 -8px 0 8px; -} - -/* identity panel */ - -.identity-panel { - font-weight: 500; -} - -.identity-panel .identicon-wrapper { - margin: 4px; - margin-top: 8px; - display: flex; - align-items: center; -} - -.identity-panel .identicon-wrapper span { - margin: 0 auto; -} - -.identity-panel .identity-data { - margin: 8px 8px 8px 18px; -} - -.identity-panel i { - margin-top: 32px; - margin-right: 6px; - color: #b9b9b9; -} - -.identity-panel .arrow-right { - padding-left: 18px; - width: 42px; - min-width: 18px; - height: 100%; -} - -.identity-copy.flex-column { - flex: 0.25 0 auto; - justify-content: center; -} - -/* accounts screen */ - -.identity-section { -} - -.identity-section .identity-panel { - background: #e9e9e9; - border-bottom: 1px solid #b1b1b1; - cursor: pointer; -} - -.identity-section .identity-panel.selected { - background: $white; - color: #f3c83e; -} - -.identity-section .identity-panel.selected .identicon { - border-color: $orange; -} - -.identity-section .accounts-list-option:hover, -.identity-section .accounts-list-option.selected { - background: $white; -} - -/* account detail screen */ - -.account-detail-section { - display: flex; - flex-wrap: wrap; - overflow-y: auto; - flex-direction: inherit; -} - -.grow-tenx { - flex-grow: 10; -} - -.name-label { -} - -.unapproved-tx-icon { - height: 16px; - width: 16px; - background: rgb(47, 174, 244); - border-color: $silver-chalice; - border-radius: 13px; -} - -.edit-text { - height: 100%; - visibility: hidden; -} - -.editing-label { - display: flex; - justify-content: flex-start; - margin-left: 50px; - margin-bottom: 2px; - font-size: 11px; - text-rendering: geometricPrecision; - color: #f7861c; -} - -.name-label:hover .edit-text { - visibility: visible; -} - -/* tx confirm */ - -.unconftx-section input[type=password] { - height: 22px; - padding: 2px; - margin: 12px; - margin-bottom: 24px; - border-radius: 4px; - border: 2px solid #f3c83e; - background: #faf6f0; -} - -/* Info screen */ -.info-gray { - text-transform: uppercase; - color: $silver-chalice; -} - -.icon-size { - width: 20px; -} - -.info { - padding-bottom: 10px; - display: inline-block; - padding-left: 5px; -} - -/* buy eth warning screen */ -.custom-radios { - justify-content: space-around; - align-items: center; -} - -.custom-radio-selected { - width: 17px; - height: 17px; - border: solid; - border-style: double; - border-radius: 15px; - border-width: 5px; - background: rgba(247, 134, 28, 1); - border-color: #f7f7f7; -} - -.custom-radio-inactive { - width: 14px; - height: 14px; - border: solid; - border-width: 1px; - border-radius: 24px; - border-color: $silver-chalice; -} - -.radio-titles { - color: rgba(247, 134, 28, 1); -} - -.eth-warning { - transition: opacity 400ms ease-in, transform 400ms ease-in; -} - -.buy-subview { - transition: opacity 400ms ease-in, transform 400ms ease-in; -} - -.input-container:hover .edit-text { - visibility: visible; -} - -.buy-inputs { - font-size: 13px; - height: 20px; - background: transparent; - box-sizing: border-box; - border: solid; - border-color: transparent; - border-width: 0.5px; - border-radius: 2px; -} - -.input-container:hover .buy-inputs { - box-sizing: inherit; - border: solid; - border-color: #f7861c; - border-width: 0.5px; - border-radius: 2px; -} - -.buy-inputs:focus { - border: solid; - border-color: #f7861c; - border-width: 0.5px; - border-radius: 2px; -} - -.activeForm { - background: #f7f7f7; - border: none; - border-radius: 8px 8px 0 0; - width: 50%; - text-align: center; - padding-bottom: 4px; -} - -.inactiveForm { - border: none; - border-radius: 8px 8px 0 0; - width: 50%; - text-align: center; - padding-bottom: 4px; -} - -.ex-coins { - text-transform: uppercase; - text-align: center; - font-size: 33px; - width: 118px; - height: 42px; - padding: 1px; - color: #4d4d4d; -} - -.marketinfo { - color: $silver-chalice; - font-size: 15px; - line-height: 17px; -} - -#fromCoin::-webkit-calendar-picker-indicator { - display: none; -} - -#coinList { - width: 400px; - height: 500px; - overflow: scroll; -} - -.icon-control .fa-sync { - visibility: hidden; -} - -.icon-control:hover .fa-sync { - visibility: visible; -} - -.icon-control:hover .fa-chevron-right { - visibility: hidden; -} - -.inactive { - color: $silver-chalice; -} - -.inactive button { - background: $silver-chalice; - color: $white; -} - -.qr-ellip-address, -.ellip-address { - /*rtl:ignore*/ - direction: ltr; - overflow: hidden; - text-overflow: ellipsis; - width: 100%; -} - -.qr-header { - font-size: 25px; - margin-top: 40px; -} - -.qr-message { - font-size: 12px; - color: #f7861c; -} - -div.message-container > div:first-child { - margin-top: 18px; - font-size: 15px; - color: #4d4d4d; -} - -.pop-hover:hover { - transform: scale(1.1); -} - -/* stylelint-enable */ diff --git a/ui/app/css/itcss/tools/utilities.scss b/ui/app/css/itcss/tools/utilities.scss index 1d0d1c463e75..aa80ab8673dc 100644 --- a/ui/app/css/itcss/tools/utilities.scss +++ b/ui/app/css/itcss/tools/utilities.scss @@ -112,14 +112,6 @@ z-index: 1; } -.select-none { - cursor: inherit; - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; - user-select: none; -} - .pointer { cursor: pointer; } diff --git a/ui/app/pages/mobile-sync/mobile-sync.component.js b/ui/app/pages/mobile-sync/mobile-sync.component.js index d93e64c0d3af..e0da0074c428 100644 --- a/ui/app/pages/mobile-sync/mobile-sync.component.js +++ b/ui/app/pages/mobile-sync/mobile-sync.component.js @@ -369,7 +369,6 @@ export default class MobileSyncPage extends Component { {t('syncWithMobileScanThisCode')}
Date: Fri, 7 Aug 2020 13:45:49 -0300 Subject: [PATCH 051/137] Change MetaMetrics category for background events (#9155) Background events are now sent in the `Background` category, rather than `backend`. Conventionally we use the term "background" over "backend", as it's not really a "backend" in the normal sense since it's a client background process. Also it's capitalized because all of the other event categories are capitalized as well. The metrics URL has been updated to use `background` instead of `backend` as well, for consistency. Luckily we don't have to worry about our metrics being disjointed due to this name change, because the background metrics never worked to begin with! So there will be none under the old name. The metrics will be made functional in a separate PR. --- app/scripts/lib/backend-metametrics.js | 2 +- app/scripts/metamask-controller.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/scripts/lib/backend-metametrics.js b/app/scripts/lib/backend-metametrics.js index baaf1c6661e3..a035b9d91ad8 100644 --- a/app/scripts/lib/backend-metametrics.js +++ b/app/scripts/lib/backend-metametrics.js @@ -14,7 +14,7 @@ export default function backEndMetaMetricsEvent (metaMaskState, eventData) { sendMetaMetricsEvent({ ...stateEventData, ...eventData, - url: METAMETRICS_TRACKING_URL + '/backend', + url: METAMETRICS_TRACKING_URL + '/background', }) } } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 41a2d8fb31bf..8008cb77946a 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -257,7 +257,7 @@ export default class MetamaskController extends EventEmitter { errorMessage: txMeta.simulationFails?.reason, }, eventOpts: { - category: 'backend', + category: 'Background', action: 'Transactions', name: 'On Chain Failure', }, From 8713927e5e08e45f7653f32af7ea1cb08ef2a2be Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 7 Aug 2020 14:57:27 -0300 Subject: [PATCH 052/137] Remove `url` parameter from `metricsEvent` (#9157) * Remove `url` parameter from `metricsEvent` The `url` parameter was used to override the `currentPath`, but it never worked correctly. It was supposed to be used for setting the `url` query parameter that was sent to Matomo, but `currentPath` was always used even if it `url` was set and `currentPath` was empty. Instead, `currentPath` is now always used. There was never a need to provide an "override" for `currentPath` when it can be set directly. The metrics provider does set `currentPath` automatically by default, but this can be overwritten already by passing a second parameter to `metricsEvent`. There were two places this `url` parameter was being used: background events, and path changes. Background events were submitted with no `currentPath`, so because of the bug with the `url` parameter, the metrics utility would crash upon each event. So those were never actually sent. This commit will fix that crash. The `currentPath` parameter was supplied as an empty string for the path change events, so those never crashed. They just had the `url` query string parameter set incorrectly (to an empty string). It should now be correctly populated, which should mean we'll be capturing all path changes now. Previously we were only capturing path changes to pages that happened to include an event, because of this blank `url` problem. * Use `url` query parameter as fallback for generating `pv_id` The `pv_id` parameter currently isn't generated correctly on Firefox, as the generation assumes that the current URL starts with `chrome-extension://`. The `url` query parameter is still unique for each path, so it's probably good enough for generating an id for each page. This is just a temporary fix; it will be removed in a future PR, where Firefox will be properly supported. --- app/scripts/lib/backend-metametrics.js | 2 +- ui/app/helpers/utils/metametrics.util.js | 8 +++----- ui/app/pages/routes/routes.component.js | 6 +++--- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/scripts/lib/backend-metametrics.js b/app/scripts/lib/backend-metametrics.js index a035b9d91ad8..9328fa3af77d 100644 --- a/app/scripts/lib/backend-metametrics.js +++ b/app/scripts/lib/backend-metametrics.js @@ -14,7 +14,7 @@ export default function backEndMetaMetricsEvent (metaMaskState, eventData) { sendMetaMetricsEvent({ ...stateEventData, ...eventData, - url: METAMETRICS_TRACKING_URL + '/background', + currentPath: METAMETRICS_TRACKING_URL + '/background', }) } } diff --git a/ui/app/helpers/utils/metametrics.util.js b/ui/app/helpers/utils/metametrics.util.js index 98b83f3d8aec..3cba4f21518b 100644 --- a/ui/app/helpers/utils/metametrics.util.js +++ b/ui/app/helpers/utils/metametrics.util.js @@ -13,7 +13,7 @@ const METAMETRICS_BASE_URL = 'https://chromeextensionmm.innocraft.cloud/piwik.ph const METAMETRICS_REQUIRED_PARAMS = `?idsite=${projectId}&rec=1&apiv=1` const METAMETRICS_BASE_FULL = METAMETRICS_BASE_URL + METAMETRICS_REQUIRED_PARAMS -const METAMETRICS_TRACKING_URL = inDevelopment +export const METAMETRICS_TRACKING_URL = inDevelopment ? 'http://www.metamask.io/metametrics' : 'http://www.metamask.io/metametrics-prod' @@ -119,7 +119,6 @@ function composeParamAddition (paramValue, paramName) { * @property {string} config.currentPath The location path the user is on at the time of the event * @property {string} config.metaMetricsId A random id assigned to a user at the time of opting in to metametrics. A hexadecimal number * @property {string} config.confirmTransactionOrigin The origin on a transaction - * @property {string} config.url The url to track an event at. Overrides `currentPath` * @property {boolean} config.excludeMetaMetricsId Whether or not the tracked event data should be associated with a metametrics id * @property {boolean} config.isNewVisit Whether or not the event should be tracked as a new visit/user sessions * @returns {string} - Returns a url to be passed to fetch to make the appropriate request to matomo. @@ -141,7 +140,6 @@ function composeUrl (config) { currentPath, metaMetricsId, confirmTransactionOrigin, - url: configUrl, excludeMetaMetricsId, isNewVisit, } = config @@ -167,10 +165,10 @@ function composeUrl (config) { numberOfTokens: (customVariables && customVariables.numberOfTokens) || numberOfTokens, numberOfAccounts: (customVariables && customVariables.numberOfAccounts) || numberOfAccounts, }) : '' - const url = configUrl || currentPath ? `&url=${encodeURIComponent(currentPath.replace(/chrome-extension:\/\/\w+/, METAMETRICS_TRACKING_URL))}` : '' + const url = currentPath ? `&url=${encodeURIComponent(currentPath.replace(/chrome-extension:\/\/\w+/, METAMETRICS_TRACKING_URL))}` : '' const _id = metaMetricsId && !excludeMetaMetricsId ? `&_id=${metaMetricsId.slice(2, 18)}` : '' const rand = `&rand=${String(Math.random()).slice(2)}` - const pv_id = ((url || currentPath) && `&pv_id=${ethUtil.bufferToHex(ethUtil.sha3(url || currentPath.match(/chrome-extension:\/\/\w+\/(.+)/)[0])).slice(2, 8)}`) || '' + const pv_id = currentPath ? `&pv_id=${ethUtil.bufferToHex(ethUtil.sha3(currentPath.match(/chrome-extension:\/\/\w+\/(.+)/)?.[0] || url)).slice(2, 8)}` : '' const uid = metaMetricsId && !excludeMetaMetricsId ? `&uid=${metaMetricsId.slice(2, 18)}` : excludeMetaMetricsId diff --git a/ui/app/pages/routes/routes.component.js b/ui/app/pages/routes/routes.component.js index 1dc556a98288..1aca07f07175 100644 --- a/ui/app/pages/routes/routes.component.js +++ b/ui/app/pages/routes/routes.component.js @@ -52,6 +52,8 @@ import { UNLOCK_ROUTE, } from '../../helpers/constants/routes' +import { METAMETRICS_TRACKING_URL } from '../../helpers/utils/metametrics.util' + import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums' import { getEnvironmentType } from '../../../../app/scripts/lib/util' @@ -98,11 +100,9 @@ export default class Routes extends Component { this.props.history.listen((locationObj, action) => { if (action === 'PUSH') { pageChanged(locationObj.pathname) - const url = `&url=${encodeURIComponent('http://www.metamask.io/metametrics' + locationObj.pathname)}` this.context.metricsEvent({}, { - currentPath: '', + currentPath: `${METAMETRICS_TRACKING_URL}${locationObj.pathname}`, pathname: locationObj.pathname, - url, pageOpts: { hideDimensions: true, }, From 1419c14fb6a29e7461757f102d6a4af4d70ad286 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 7 Aug 2020 15:32:46 -0300 Subject: [PATCH 053/137] Use `pathname` instead of URL for `currentPath` metrics parameter (#9158) The `currentPath` parameter passed to our metrics utility had been passed the full URL rather than just the path, contrary to what the name would imply. We only used the path portion, so passing the full URL did lead to complications. Now just the `pathname` is passed in, rather than the full URL. This simplifies the metrics logic, and it incidentally fixes two bugs. The main bug fixed is regarding Firefox metrics. Previously we had assumed the `currentPath` would start with `chrome-extension://`, which of course was not true on Firefox. This lead to us incorrectly parsing the `currentPath`, so path tracking was broken for Firefox events. This broken parsing is now bypassed entirely, so metrics should now work the same on Firefox as on Chrome. The second bug was that we were incorrectly setting the tracking URL for background events during tests. As a result, we were incorrectly detecting ourselves as an internal site that had referred the user to us. But this was not of major concern, since it only affected test metrics (which get sent to the development Matomo project). Lastly, this change let us discard the `pathname` parameter used in the `overrides` parameter of the `metricsEvent` function. Now that `currentPath` is equivalent to `pathname`, the `pathname` parameter is redundant. --- app/scripts/lib/backend-metametrics.js | 8 +------- ui/app/contexts/metametrics.js | 8 ++++---- ui/app/helpers/utils/metametrics.util.js | 12 ++++++------ ui/app/pages/routes/routes.component.js | 5 +---- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/app/scripts/lib/backend-metametrics.js b/app/scripts/lib/backend-metametrics.js index 9328fa3af77d..e62f09d0de07 100644 --- a/app/scripts/lib/backend-metametrics.js +++ b/app/scripts/lib/backend-metametrics.js @@ -1,12 +1,6 @@ import { getBackgroundMetaMetricState } from '../../../ui/app/selectors' import { sendMetaMetricsEvent } from '../../../ui/app/helpers/utils/metametrics.util' -const inDevelopment = process.env.NODE_ENV === 'development' - -const METAMETRICS_TRACKING_URL = inDevelopment - ? 'http://www.metamask.io/metametrics' - : 'http://www.metamask.io/metametrics-prod' - export default function backEndMetaMetricsEvent (metaMaskState, eventData) { const stateEventData = getBackgroundMetaMetricState({ metamask: metaMaskState }) @@ -14,7 +8,7 @@ export default function backEndMetaMetricsEvent (metaMaskState, eventData) { sendMetaMetricsEvent({ ...stateEventData, ...eventData, - currentPath: METAMETRICS_TRACKING_URL + '/background', + currentPath: '/background', }) } } diff --git a/ui/app/contexts/metametrics.js b/ui/app/contexts/metametrics.js index ced6d4944d4b..b1440429edd1 100644 --- a/ui/app/contexts/metametrics.js +++ b/ui/app/contexts/metametrics.js @@ -41,7 +41,7 @@ export function MetaMetricsProvider ({ children }) { const numberOfAccounts = useSelector(getNumberOfAccounts) const history = useHistory() const [state, setState] = useState(() => ({ - currentPath: window.location.href, + currentPath: (new URL(window.location.href)).pathname, previousPath: '', })) @@ -49,7 +49,7 @@ export function MetaMetricsProvider ({ children }) { useEffect(() => { const unlisten = history.listen(() => setState((prevState) => ({ - currentPath: window.location.href, + currentPath: (new URL(window.location.href)).pathname, previousPath: prevState.currentPath, }))) // remove this listener if the component is no longer mounted @@ -59,8 +59,8 @@ export function MetaMetricsProvider ({ children }) { const metricsEvent = useCallback((config = {}, overrides = {}) => { const { eventOpts = {} } = config const { name = '' } = eventOpts - const { pathname: overRidePathName = '' } = overrides - const isSendFlow = Boolean(name.match(/^send|^confirm/) || overRidePathName.match(/send|confirm/)) + const { currentPath: overrideCurrentPath = '' } = overrides + const isSendFlow = Boolean(name.match(/^send|^confirm/) || overrideCurrentPath.match(/send|confirm/)) if (participateInMetaMetrics || config.isOptIn) { return sendMetaMetricsEvent({ diff --git a/ui/app/helpers/utils/metametrics.util.js b/ui/app/helpers/utils/metametrics.util.js index 3cba4f21518b..d2563c7fcf43 100644 --- a/ui/app/helpers/utils/metametrics.util.js +++ b/ui/app/helpers/utils/metametrics.util.js @@ -13,7 +13,7 @@ const METAMETRICS_BASE_URL = 'https://chromeextensionmm.innocraft.cloud/piwik.ph const METAMETRICS_REQUIRED_PARAMS = `?idsite=${projectId}&rec=1&apiv=1` const METAMETRICS_BASE_FULL = METAMETRICS_BASE_URL + METAMETRICS_REQUIRED_PARAMS -export const METAMETRICS_TRACKING_URL = inDevelopment +const METAMETRICS_TRACKING_URL = inDevelopment ? 'http://www.metamask.io/metametrics' : 'http://www.metamask.io/metametrics-prod' @@ -74,7 +74,7 @@ const customDimensionsNameIdMap = { function composeUrlRefParamAddition (previousPath, confirmTransactionOrigin) { const externalOrigin = confirmTransactionOrigin && confirmTransactionOrigin !== 'metamask' - return `&urlref=${externalOrigin ? 'EXTERNAL' : encodeURIComponent(previousPath.replace(/chrome-extension:\/\/\w+/, METAMETRICS_TRACKING_URL))}` + return `&urlref=${externalOrigin ? 'EXTERNAL' : encodeURIComponent(`${METAMETRICS_TRACKING_URL}${previousPath}`)}` } // composes query params of the form &dimension[0-999]=[value] @@ -115,8 +115,8 @@ function composeParamAddition (paramValue, paramName) { * @property {string} config.accountType The account type being used at the time of the event: 'hardware', 'imported' or 'default' * @property {number} config.numberOfTokens The number of tokens that the user has added at the time of the event * @property {number} config.numberOfAccounts The number of accounts the user has added at the time of the event - * @property {string} config.previousPath The location path the user was on prior to the path they are on at the time of the event - * @property {string} config.currentPath The location path the user is on at the time of the event + * @property {string} config.previousPath The pathname of the URL the user was on prior to the URL they are on at the time of the event + * @property {string} config.currentPath The pathname of the URL the user is on at the time of the event * @property {string} config.metaMetricsId A random id assigned to a user at the time of opting in to metametrics. A hexadecimal number * @property {string} config.confirmTransactionOrigin The origin on a transaction * @property {boolean} config.excludeMetaMetricsId Whether or not the tracked event data should be associated with a metametrics id @@ -165,10 +165,10 @@ function composeUrl (config) { numberOfTokens: (customVariables && customVariables.numberOfTokens) || numberOfTokens, numberOfAccounts: (customVariables && customVariables.numberOfAccounts) || numberOfAccounts, }) : '' - const url = currentPath ? `&url=${encodeURIComponent(currentPath.replace(/chrome-extension:\/\/\w+/, METAMETRICS_TRACKING_URL))}` : '' + const url = currentPath ? `&url=${encodeURIComponent(`${METAMETRICS_TRACKING_URL}${currentPath}`)}` : '' const _id = metaMetricsId && !excludeMetaMetricsId ? `&_id=${metaMetricsId.slice(2, 18)}` : '' const rand = `&rand=${String(Math.random()).slice(2)}` - const pv_id = currentPath ? `&pv_id=${ethUtil.bufferToHex(ethUtil.sha3(currentPath.match(/chrome-extension:\/\/\w+\/(.+)/)?.[0] || url)).slice(2, 8)}` : '' + const pv_id = currentPath ? `&pv_id=${ethUtil.bufferToHex(ethUtil.sha3(currentPath)).slice(2, 8)}` : '' const uid = metaMetricsId && !excludeMetaMetricsId ? `&uid=${metaMetricsId.slice(2, 18)}` : excludeMetaMetricsId diff --git a/ui/app/pages/routes/routes.component.js b/ui/app/pages/routes/routes.component.js index 1aca07f07175..578483425c34 100644 --- a/ui/app/pages/routes/routes.component.js +++ b/ui/app/pages/routes/routes.component.js @@ -52,8 +52,6 @@ import { UNLOCK_ROUTE, } from '../../helpers/constants/routes' -import { METAMETRICS_TRACKING_URL } from '../../helpers/utils/metametrics.util' - import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums' import { getEnvironmentType } from '../../../../app/scripts/lib/util' @@ -101,8 +99,7 @@ export default class Routes extends Component { if (action === 'PUSH') { pageChanged(locationObj.pathname) this.context.metricsEvent({}, { - currentPath: `${METAMETRICS_TRACKING_URL}${locationObj.pathname}`, - pathname: locationObj.pathname, + currentPath: locationObj.pathname, pageOpts: { hideDimensions: true, }, From d59fc79e0febb2306a4681077641f8680922e8fd Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Fri, 7 Aug 2020 13:57:33 -0500 Subject: [PATCH 054/137] colocate deposit-ether-modal styles (#9148) Moves the still alive deposit-ether-modal styles to be colocated with it's component, as per the examples already in place in the components/modal folder --- .../app/modals/deposit-ether-modal/index.scss | 162 +++++++++++++++++ ui/app/components/app/modals/index.scss | 1 + ui/app/css/itcss/components/modal.scss | 164 ------------------ 3 files changed, 163 insertions(+), 164 deletions(-) create mode 100644 ui/app/components/app/modals/deposit-ether-modal/index.scss diff --git a/ui/app/components/app/modals/deposit-ether-modal/index.scss b/ui/app/components/app/modals/deposit-ether-modal/index.scss new file mode 100644 index 000000000000..c52e4e5637ca --- /dev/null +++ b/ui/app/components/app/modals/deposit-ether-modal/index.scss @@ -0,0 +1,162 @@ +.deposit-ether-modal { + border-radius: 8px; + display: flex; + flex-flow: column; + height: 100%; + + &__header { + width: 100%; + border-radius: 8px 8px 0 0; + background-color: $mid-gray; + display: flex; + position: relative; + padding: 25px; + flex-flow: column; + align-items: flex-start; + + &__title { + color: $white; + font-size: 24px; + line-height: 32px; + } + + &__description { + color: $white; + font-size: 16px; + line-height: 22px; + margin-top: 10px; + } + + &__close::after { + content: '\00D7'; + font-size: 2em; + color: $white; + position: absolute; + top: 20.8px; + right: 28px; + cursor: pointer; + } + } + + &__buy-rows { + width: 100%; + padding: 0 30px; + display: flex; + flex-flow: column nowrap; + flex: 1; + align-items: center; + + @media screen and (max-width: 575px) { + height: 0; + } + } + + &__logo { + height: 60px; + background-repeat: no-repeat; + background-size: contain; + background-position: center; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + } + + &__buy-row { + border-bottom: 1px solid $alto; + display: flex; + justify-content: space-between; + align-items: center; + flex: 1 0 auto; + padding: 30px 0 20px; + min-height: 170px; + + @media screen and (max-width: 575px) { + min-height: 270px; + flex-flow: column; + justify-content: flex-start; + } + + &__back { + position: absolute; + top: 10px; + left: 0; + } + + &__logo-container { + display: flex; + justify-content: center; + flex: 0 0 auto; + padding: 0 20px; + + @media screen and (min-width: 576px) { + width: 12rem; + } + + @media screen and (max-width: 575px) { + width: 100%; + max-height: 6rem; + padding-bottom: 20px; + } + } + + &__right { + display: flex; + } + + &__description { + color: $cape-cod; + padding-bottom: 20px; + align-self: flex-start; + + @media screen and (min-width: 575px) { + width: 15rem; + } + + &__title { + font-size: 20px; + line-height: 30px; + } + + &__text { + font-size: 14px; + line-height: 22px; + margin-top: 7px; + } + } + + &__button { + display: flex; + justify-content: flex-end; + + @media screen and (min-width: 575px) { + min-width: 300px; + } + } + } + + &__buy-row:last-of-type { + border-bottom: 0; + } + + &__deposit-button { + width: 257px; + } + + .simple-dropdown { + color: #5b5d67; + font-size: 16px; + line-height: 21px; + border: 1px solid #d8d8d8; + background-color: #fff; + text-align: center; + width: 100%; + height: 45px; + line-height: 44px; + font-weight: 300; + } + + .simple-dropdown__selected { + text-align: center; + } +} diff --git a/ui/app/components/app/modals/index.scss b/ui/app/components/app/modals/index.scss index c7f01b20b7dd..ae162ea16113 100644 --- a/ui/app/components/app/modals/index.scss +++ b/ui/app/components/app/modals/index.scss @@ -1,5 +1,6 @@ @import 'cancel-transaction/index'; @import 'confirm-remove-account/index'; +@import 'deposit-ether-modal/index'; @import 'notification-modal/index'; @import 'qr-scanner/index'; @import 'transaction-confirmed/index'; diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index 8d47c753e9df..a0ed3728de8d 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -275,167 +275,3 @@ margin: 0 5px; } } - -// Deposit Ether Modal -.deposit-ether-modal { - border-radius: 8px; - display: flex; - flex-flow: column; - height: 100%; - - &__header { - width: 100%; - border-radius: 8px 8px 0 0; - background-color: $mid-gray; - display: flex; - position: relative; - padding: 25px; - flex-flow: column; - align-items: flex-start; - - &__title { - color: $white; - font-size: 24px; - line-height: 32px; - } - - &__description { - color: $white; - font-size: 16px; - line-height: 22px; - margin-top: 10px; - } - - &__close::after { - content: '\00D7'; - font-size: 2em; - color: $white; - position: absolute; - top: 20.8px; - right: 28px; - cursor: pointer; - } - } - - &__buy-rows { - width: 100%; - padding: 0 30px; - display: flex; - flex-flow: column nowrap; - flex: 1; - align-items: center; - - @media screen and (max-width: 575px) { - height: 0; - } - } - - &__logo { - height: 60px; - background-repeat: no-repeat; - background-size: contain; - background-position: center; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - } - - &__buy-row { - border-bottom: 1px solid $alto; - display: flex; - justify-content: space-between; - align-items: center; - flex: 1 0 auto; - padding: 30px 0 20px; - min-height: 170px; - - @media screen and (max-width: 575px) { - min-height: 270px; - flex-flow: column; - justify-content: flex-start; - } - - &__back { - position: absolute; - top: 10px; - left: 0; - } - - &__logo-container { - display: flex; - justify-content: center; - flex: 0 0 auto; - padding: 0 20px; - - @media screen and (min-width: 576px) { - width: 12rem; - } - - @media screen and (max-width: 575px) { - width: 100%; - max-height: 6rem; - padding-bottom: 20px; - } - } - - &__right { - display: flex; - } - - &__description { - color: $cape-cod; - padding-bottom: 20px; - align-self: flex-start; - - @media screen and (min-width: 575px) { - width: 15rem; - } - - &__title { - font-size: 20px; - line-height: 30px; - } - - &__text { - font-size: 14px; - line-height: 22px; - margin-top: 7px; - } - } - - &__button { - display: flex; - justify-content: flex-end; - - @media screen and (min-width: 575px) { - min-width: 300px; - } - } - } - - &__buy-row:last-of-type { - border-bottom: 0; - } - - &__deposit-button { - width: 257px; - } - - .simple-dropdown { - color: #5b5d67; - font-size: 16px; - line-height: 21px; - border: 1px solid #d8d8d8; - background-color: #fff; - text-align: center; - width: 100%; - height: 45px; - line-height: 44px; - font-weight: 300; - } - - .simple-dropdown__selected { - text-align: center; - } -} From e5cb63eea2f37718860017421b2e35cb746e8e09 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Fri, 7 Aug 2020 12:28:23 -0700 Subject: [PATCH 055/137] Add web3 usage metrics, prepare for web3 removal (#9144) * add web3 usage metrics * move web3 metrics method to new middleware * rename some methods, files, and exports --- app/scripts/controllers/permissions/index.js | 4 +- ...ware.js => permissionsMethodMiddleware.js} | 2 +- app/scripts/inpage.js | 27 ++--------- ...tametrics.js => background-metametrics.js} | 4 +- app/scripts/lib/createMethodMiddleware.js | 32 +++++++++++++ .../lib/{auto-reload.js => setupWeb3.js} | 47 +++++++++++++++++-- app/scripts/metamask-controller.js | 40 +++++++++++----- ui/app/helpers/utils/metametrics.util.js | 4 +- 8 files changed, 114 insertions(+), 46 deletions(-) rename app/scripts/controllers/permissions/{methodMiddleware.js => permissionsMethodMiddleware.js} (98%) rename app/scripts/lib/{backend-metametrics.js => background-metametrics.js} (78%) create mode 100644 app/scripts/lib/createMethodMiddleware.js rename app/scripts/lib/{auto-reload.js => setupWeb3.js} (64%) diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index 311a0d1ca872..a5aeb7b1429a 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -7,7 +7,7 @@ import { CapabilitiesController as RpcCap } from 'rpc-cap' import { ethErrors } from 'eth-json-rpc-errors' import { cloneDeep } from 'lodash' -import createMethodMiddleware from './methodMiddleware' +import createPermissionsMethodMiddleware from './permissionsMethodMiddleware' import PermissionsLogController from './permissionsLog' // Methods that do not require any permissions to use: @@ -90,7 +90,7 @@ export class PermissionsController { engine.push(this.permissionsLog.createMiddleware()) - engine.push(createMethodMiddleware({ + engine.push(createPermissionsMethodMiddleware({ addDomainMetadata: this.addDomainMetadata.bind(this), getAccounts: this.getAccounts.bind(this, origin), getUnlockPromise: () => this._getUnlockPromise(true), diff --git a/app/scripts/controllers/permissions/methodMiddleware.js b/app/scripts/controllers/permissions/permissionsMethodMiddleware.js similarity index 98% rename from app/scripts/controllers/permissions/methodMiddleware.js rename to app/scripts/controllers/permissions/permissionsMethodMiddleware.js index 613ea3876df2..075f67cf85ba 100644 --- a/app/scripts/controllers/permissions/methodMiddleware.js +++ b/app/scripts/controllers/permissions/permissionsMethodMiddleware.js @@ -4,7 +4,7 @@ import { ethErrors } from 'eth-json-rpc-errors' /** * Create middleware for handling certain methods and preprocessing permissions requests. */ -export default function createMethodMiddleware ({ +export default function createPermissionsMethodMiddleware ({ addDomainMetadata, getAccounts, getUnlockPromise, diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 67250228635a..c7c92faceede 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -1,5 +1,3 @@ -/*global Web3*/ - // need to make sure we aren't affected by overlapping namespaces // and that we dont affect the app with our namespace // mostly a fix for web3's BigNumber if AMD's "define" is defined... @@ -37,9 +35,7 @@ import LocalMessageDuplexStream from 'post-message-stream' import { initProvider } from '@metamask/inpage-provider' // TODO:deprecate:2020 -import 'web3/dist/web3.min.js' - -import setupDappAutoReload from './lib/auto-reload.js' +import setupWeb3 from './lib/setupWeb3.js' restoreContextAfterImports() @@ -59,11 +55,9 @@ initProvider({ connectionStream: metamaskStream, }) -// // TODO:deprecate:2020 -// +// Setup web3 -// setup web3 if (typeof window.web3 !== 'undefined') { throw new Error(`MetaMask detected another web3. @@ -73,18 +67,5 @@ if (typeof window.web3 !== 'undefined') { and try again.`) } -const web3 = new Web3(window.ethereum) -web3.setProvider = function () { - log.debug('MetaMask - overrode web3.setProvider') -} -log.debug('MetaMask - injected web3') - -Object.defineProperty(window.ethereum, '_web3Ref', { - enumerable: false, - writable: true, - configurable: true, - value: web3.eth, -}) - -// setup dapp auto reload AND proxy web3 -setupDappAutoReload(web3, window.ethereum._publicConfigStore) +// proxy web3, assign to window, and set up site auto reload +setupWeb3(log) diff --git a/app/scripts/lib/backend-metametrics.js b/app/scripts/lib/background-metametrics.js similarity index 78% rename from app/scripts/lib/backend-metametrics.js rename to app/scripts/lib/background-metametrics.js index e62f09d0de07..f381ea3a12b3 100644 --- a/app/scripts/lib/backend-metametrics.js +++ b/app/scripts/lib/background-metametrics.js @@ -1,13 +1,13 @@ import { getBackgroundMetaMetricState } from '../../../ui/app/selectors' import { sendMetaMetricsEvent } from '../../../ui/app/helpers/utils/metametrics.util' -export default function backEndMetaMetricsEvent (metaMaskState, eventData) { +export default function backgroundMetaMetricsEvent (metaMaskState, eventData) { const stateEventData = getBackgroundMetaMetricState({ metamask: metaMaskState }) - if (stateEventData.participateInMetaMetrics) { sendMetaMetricsEvent({ ...stateEventData, ...eventData, + category: 'Background', currentPath: '/background', }) } diff --git a/app/scripts/lib/createMethodMiddleware.js b/app/scripts/lib/createMethodMiddleware.js new file mode 100644 index 000000000000..308cf0a99e56 --- /dev/null +++ b/app/scripts/lib/createMethodMiddleware.js @@ -0,0 +1,32 @@ +/** + * Returns a middleware that implements the following RPC methods: + * - metamask_logInjectedWeb3Usage + * + * @param {Object} opts - The middleware options + * @param {string} opts.origin - The origin for the middleware stack + * @param {Function} opts.sendMetrics - A function for sending a metrics event + * @returns {(req: any, res: any, next: Function, end: Function) => void} + */ +export default function createMethodMiddleware ({ origin, sendMetrics }) { + return function methodMiddleware (req, res, next, end) { + switch (req.method) { + + case 'metamask_logInjectedWeb3Usage': + + const { action, name } = req.params[0] + + sendMetrics({ + action, + name, + customVariables: { origin }, + }) + + res.result = true + break + + default: + return next() + } + return end() + } +} diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/setupWeb3.js similarity index 64% rename from app/scripts/lib/auto-reload.js rename to app/scripts/lib/setupWeb3.js index 2f50e3e88530..da5d8d422b19 100644 --- a/app/scripts/lib/auto-reload.js +++ b/app/scripts/lib/setupWeb3.js @@ -1,26 +1,67 @@ +/*global Web3*/ // TODO:deprecate:2020 +// Delete this file -export default function setupDappAutoReload (web3, observable) { +import 'web3/dist/web3.min.js' + +const shouldLogUsage = !([ + 'docs.metamask.io', + 'metamask.github.io', + 'metamask.io', +].includes(window.location.hostname)) + +export default function setupWeb3 (log) { // export web3 as a global, checking for usage let reloadInProgress = false let lastTimeUsed let lastSeenNetwork let hasBeenWarned = false + const web3 = new Web3(window.ethereum) + web3.setProvider = function () { + log.debug('MetaMask - overrode web3.setProvider') + } + log.debug('MetaMask - injected web3') + + Object.defineProperty(window.ethereum, '_web3Ref', { + enumerable: false, + writable: true, + configurable: true, + value: web3.eth, + }) + const web3Proxy = new Proxy(web3, { get: (_web3, key) => { + // get the time of use lastTimeUsed = Date.now() + // show warning once on web3 access - if (!hasBeenWarned && key !== 'currentProvider') { + if (!hasBeenWarned) { console.warn(`MetaMask: We will stop injecting web3 in Q4 2020.\nPlease see this article for more information: https://medium.com/metamask/no-longer-injecting-web3-js-4a899ad6e59e`) hasBeenWarned = true } + + if (shouldLogUsage) { + window.ethereum.request({ + method: 'metamask_logInjectedWeb3Usage', + params: [{ action: 'window.web3 get', name: key }], + }) + } + // return value normally return _web3[key] }, set: (_web3, key, value) => { + + if (shouldLogUsage) { + window.ethereum.request({ + method: 'metamask_logInjectedWeb3Usage', + params: [{ action: 'window.web3 set', name: key }], + }) + } + // set value normally _web3[key] = value }, @@ -33,7 +74,7 @@ export default function setupDappAutoReload (web3, observable) { value: web3Proxy, }) - observable.subscribe(function (state) { + window.ethereum._publicConfigStore.subscribe((state) => { // if the auto refresh on network change is false do not // do anything if (!window.ethereum.autoRefreshOnNetworkChange) { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 8008cb77946a..f9821e822cbd 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -19,6 +19,7 @@ import createEngineStream from 'json-rpc-middleware-stream/engineStream' import createFilterMiddleware from 'eth-json-rpc-filters' import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager' import createLoggerMiddleware from './lib/createLoggerMiddleware' +import createMethodMiddleware from './lib/createMethodMiddleware' import createOriginMiddleware from './lib/createOriginMiddleware' import createTabIdMiddleware from './lib/createTabIdMiddleware' import createOnboardingMiddleware from './lib/createOnboardingMiddleware' @@ -66,7 +67,7 @@ import { PhishingController, } from '@metamask/controllers' -import backEndMetaMetricsEvent from './lib/backend-metametrics' +import backgroundMetaMetricsEvent from './lib/background-metametrics' export default class MetamaskController extends EventEmitter { @@ -249,18 +250,11 @@ export default class MetamaskController extends EventEmitter { this.platform.showTransactionNotification(txMeta) const { txReceipt } = txMeta - const participateInMetaMetrics = this.preferencesController.getParticipateInMetaMetrics() - if (txReceipt && txReceipt.status === '0x0' && participateInMetaMetrics) { - const metamaskState = await this.getState() - backEndMetaMetricsEvent(metamaskState, { - customVariables: { - errorMessage: txMeta.simulationFails?.reason, - }, - eventOpts: { - category: 'Background', - action: 'Transactions', - name: 'On Chain Failure', - }, + if (txReceipt && txReceipt.status === '0x0') { + this.sendBackgroundMetaMetrics({ + action: 'Transactions', + name: 'On Chain Failure', + customVariables: { errorMessage: txMeta.simulationFails?.reason }, }) } } @@ -1637,6 +1631,10 @@ export default class MetamaskController extends EventEmitter { location, registerOnboarding: this.onboardingController.registerOnboarding, })) + engine.push(createMethodMiddleware({ + origin, + sendMetrics: this.sendBackgroundMetaMetrics.bind(this), + })) // filter and subscription polyfills engine.push(filterMiddleware) engine.push(subscriptionManager.middleware) @@ -1837,6 +1835,22 @@ export default class MetamaskController extends EventEmitter { return nonceLock.nextNonce } + async sendBackgroundMetaMetrics ({ action, name, customVariables } = {}) { + + if (!action || !name) { + throw new Error('Must provide action and name.') + } + + const metamaskState = await this.getState() + backgroundMetaMetricsEvent(metamaskState, { + customVariables, + eventOpts: { + action, + name, + }, + }) + } + //============================================================================= // CONFIG //============================================================================= diff --git a/ui/app/helpers/utils/metametrics.util.js b/ui/app/helpers/utils/metametrics.util.js index d2563c7fcf43..cf9f157202ea 100644 --- a/ui/app/helpers/utils/metametrics.util.js +++ b/ui/app/helpers/utils/metametrics.util.js @@ -23,7 +23,7 @@ const METAMETRICS_CUSTOM_GAS_LIMIT_CHANGE = 'gasLimitChange' const METAMETRICS_CUSTOM_GAS_PRICE_CHANGE = 'gasPriceChange' const METAMETRICS_CUSTOM_FUNCTION_TYPE = 'functionType' const METAMETRICS_CUSTOM_RECIPIENT_KNOWN = 'recipientKnown' -const METAMETRICS_CUSTOM_CONFIRM_SCREEN_ORIGIN = 'origin' +const METAMETRICS_REQUEST_ORIGIN = 'origin' const METAMETRICS_CUSTOM_FROM_NETWORK = 'fromNetwork' const METAMETRICS_CUSTOM_TO_NETWORK = 'toNetwork' const METAMETRICS_CUSTOM_ERROR_FIELD = 'errorField' @@ -36,7 +36,7 @@ const METAMETRICS_CUSTOM_ASSET_SELECTED = 'assetSelected' const customVariableNameIdMap = { [METAMETRICS_CUSTOM_FUNCTION_TYPE]: 1, [METAMETRICS_CUSTOM_RECIPIENT_KNOWN]: 2, - [METAMETRICS_CUSTOM_CONFIRM_SCREEN_ORIGIN]: 3, + [METAMETRICS_REQUEST_ORIGIN]: 3, [METAMETRICS_CUSTOM_GAS_LIMIT_CHANGE]: 4, [METAMETRICS_CUSTOM_GAS_PRICE_CHANGE]: 5, From 5527a6d9e9bcdf860536a8c64d35cef50048114f Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Fri, 7 Aug 2020 12:29:50 -0700 Subject: [PATCH 056/137] Remove web3 e2e tests (#9159) --- package.json | 2 - test/e2e/run-web3.sh | 13 -- test/e2e/web3.spec.js | 288 ------------------------------------------ test/web3/index.html | 105 --------------- test/web3/schema.js | 209 ------------------------------ test/web3/web3.js | 34 ----- 6 files changed, 651 deletions(-) delete mode 100755 test/e2e/run-web3.sh delete mode 100644 test/e2e/web3.spec.js delete mode 100644 test/web3/index.html delete mode 100644 test/web3/schema.js delete mode 100644 test/web3/web3.js diff --git a/package.json b/package.json index 59b494bff86d..c20828989043 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,6 @@ "test:unit:strict": "mocha --exit --require test/env.js --require test/setup.js --recursive \"test/unit/**/permissions/*.js\"", "test:unit:path": "mocha --exit --require test/env.js --require test/setup.js --recursive", "test:e2e:chrome": "SELENIUM_BROWSER=chrome test/e2e/run-all.sh", - "test:web3:chrome": "SELENIUM_BROWSER=chrome test/e2e/run-web3.sh", - "test:web3:firefox": "SELENIUM_BROWSER=firefox test/e2e/run-web3.sh", "test:e2e:firefox": "SELENIUM_BROWSER=firefox test/e2e/run-all.sh", "test:coverage": "nyc --silent --check-coverage yarn test:unit:strict && nyc --silent --no-clean yarn test:unit:lax && nyc report --reporter=text --reporter=html", "test:coverage:strict": "nyc --check-coverage yarn test:unit:strict", diff --git a/test/e2e/run-web3.sh b/test/e2e/run-web3.sh deleted file mode 100755 index 729333b840a6..000000000000 --- a/test/e2e/run-web3.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -u -set -o pipefail - -export PATH="$PATH:./node_modules/.bin" - -concurrently --kill-others \ - --names 'dapp,e2e' \ - --prefix '[{time}][{name}]' \ - 'node development/static-server.js test/web3 --port 8080' \ - 'sleep 5 && mocha test/e2e/web3.spec' diff --git a/test/e2e/web3.spec.js b/test/e2e/web3.spec.js deleted file mode 100644 index 4bcca74dd3aa..000000000000 --- a/test/e2e/web3.spec.js +++ /dev/null @@ -1,288 +0,0 @@ -const assert = require('assert') -const webdriver = require('selenium-webdriver') - -const { By } = webdriver -const { - regularDelayMs, - largeDelayMs, -} = require('./helpers') -const { buildWebDriver } = require('./webdriver') -const enLocaleMessages = require('../../app/_locales/en/messages.json') - -describe('Using MetaMask with an existing account', function () { - let driver - - const testSeedPhrase = 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress' - - const button = async (x) => { - const buttoncheck = x - await buttoncheck.click() - await driver.delay(largeDelayMs) - const [results] = await driver.findElements(By.css('#results')) - const resulttext = await results.getText() - const parsedData = JSON.parse(resulttext) - - return (parsedData) - - } - - this.timeout(0) - this.bail(true) - - before(async function () { - const result = await buildWebDriver() - driver = result.driver - }) - - afterEach(async function () { - if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors(driver) - if (errors.length) { - const errorReports = errors.map((err) => err.message) - const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` - console.error(new Error(errorMessage)) - } - } - if (this.currentTest.state === 'failed') { - await driver.verboseReportOnFailure(this.currentTest.title) - } - }) - - after(async function () { - await driver.quit() - }) - - describe('First time flow starting from an existing seed phrase', function () { - it('clicks the continue button on the welcome screen', async function () { - await driver.findElement(By.css('.welcome-page__header')) - await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await driver.delay(largeDelayMs) - }) - - it('clicks the "Import Wallet" option', async function () { - await driver.clickElement(By.xpath(`//button[contains(text(), 'Import wallet')]`)) - await driver.delay(largeDelayMs) - }) - - it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { - await driver.clickElement(By.css('.btn-default')) - await driver.delay(largeDelayMs) - }) - - it('imports a seed phrase', async function () { - const [seedTextArea] = await driver.findElements(By.css('input[placeholder="Paste seed phrase from clipboard"]')) - await seedTextArea.sendKeys(testSeedPhrase) - await driver.delay(regularDelayMs) - - const [password] = await driver.findElements(By.id('password')) - await password.sendKeys('correct horse battery staple') - const [confirmPassword] = await driver.findElements(By.id('confirm-password')) - confirmPassword.sendKeys('correct horse battery staple') - - await driver.clickElement(By.css('.first-time-flow__terms')) - - await driver.clickElement(By.xpath(`//button[contains(text(), 'Import')]`)) - await driver.delay(regularDelayMs) - }) - - it('clicks through the success screen', async function () { - await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) - await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) - await driver.delay(regularDelayMs) - }) - }) - - - describe('opens dapp', function () { - - it('switches to mainnet', async function () { - await driver.clickElement(By.css('.network-name')) - await driver.delay(regularDelayMs) - - await driver.clickElement(By.xpath(`//span[contains(text(), 'Main Ethereum Network')]`)) - await driver.delay(largeDelayMs * 2) - }) - - it('connects to dapp', async function () { - await driver.openNewPage('http://127.0.0.1:8080/') - await driver.delay(regularDelayMs) - - await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`)) - - await driver.delay(regularDelayMs) - - await driver.waitUntilXWindowHandles(3) - const windowHandles = await driver.getAllWindowHandles() - - const extension = windowHandles[0] - const popup = await driver.switchToWindowWithTitle('MetaMask Notification', windowHandles) - const dapp = windowHandles.find((handle) => handle !== extension && handle !== popup) - - await driver.delay(regularDelayMs) - await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`)) - - await driver.switchToWindow(dapp) - await driver.delay(regularDelayMs) - }) - }) - - describe('testing web3 methods', function () { - - - it('testing hexa methods', async function () { - - - const List = await driver.findClickableElements(By.className('hexaNumberMethods')) - - for (let i = 0; i < List.length; i++) { - try { - - const parsedData = await button(List[i]) - console.log(parsedData) - const result = parseInt(parsedData.result, 16) - - assert.equal((typeof result === 'number'), true) - await driver.delay(regularDelayMs) - } catch (err) { - console.log(err) - assert(false) - - } - } - }) - - it('testing booleanMethods', async function () { - - const List = await driver.findClickableElement(By.className('booleanMethods')) - - for (let i = 0; i < List.length; i++) { - try { - - const parsedData = await button(List[i]) - console.log(parsedData) - const result = parsedData.result - - assert.equal(result, false) - await driver.delay(regularDelayMs) - } catch (err) { - console.log(err) - assert(false) - - - } - } - - }) - - it('testing transactionMethods', async function () { - - const List = await driver.findClickableElement(By.className('transactionMethods')) - - for (let i = 0; i < List.length; i++) { - try { - - const parsedData = await button(List[i]) - - console.log(parsedData.result.blockHash) - - const result = [] - result.push(parseInt(parsedData.result.blockHash, 16)) - result.push(parseInt(parsedData.result.blockNumber, 16)) - result.push(parseInt(parsedData.result.gas, 16)) - result.push(parseInt(parsedData.result.gasPrice, 16)) - result.push(parseInt(parsedData.result.hash, 16)) - result.push(parseInt(parsedData.result.input, 16)) - result.push(parseInt(parsedData.result.nonce, 16)) - result.push(parseInt(parsedData.result.r, 16)) - result.push(parseInt(parsedData.result.s, 16)) - result.push(parseInt(parsedData.result.v, 16)) - result.push(parseInt(parsedData.result.to, 16)) - result.push(parseInt(parsedData.result.value, 16)) - - - result.forEach((value) => { - assert.equal((typeof value === 'number'), true) - }) - - - } catch (err) { - - console.log(err) - assert(false) - - - } - } - - }) - - it('testing blockMethods', async function () { - - const List = await driver.findClickableElement(By.className('blockMethods')) - - for (let i = 0; i < List.length; i++) { - try { - - const parsedData = await button(List[i]) - console.log(JSON.stringify(parsedData) + i) - - console.log(parsedData.result.parentHash) - - const result = parseInt(parsedData.result.parentHash, 16) - - assert.equal((typeof result === 'number'), true) - await driver.delay(regularDelayMs) - } catch (err) { - - console.log(err) - assert(false) - - - } - } - }) - - it('testing methods', async function () { - - const List = await driver.findClickableElement(By.className('methods')) - let parsedData - let result - - for (let i = 0; i < List.length; i++) { - try { - - if (i === 2) { - - parsedData = await button(List[i]) - console.log(parsedData.result.blockHash) - - result = parseInt(parsedData.result.blockHash, 16) - - assert.equal((typeof result === 'number' || (result === 0)), true) - await driver.delay(regularDelayMs) - } else { - parsedData = await button(List[i]) - console.log(parsedData.result) - - result = parseInt(parsedData.result, 16) - - assert.equal((typeof result === 'number' || (result === 0)), true) - await driver.delay(regularDelayMs) - } - - - } catch (err) { - - console.log(err) - assert(false) - - - } - } - }) - - - }) - - -}) diff --git a/test/web3/index.html b/test/web3/index.html deleted file mode 100644 index cbc43290cd51..000000000000 --- a/test/web3/index.html +++ /dev/null @@ -1,105 +0,0 @@ - - - Web3 Test Dapp - - -
-
hexaNumberMethods
-
- - - - - - - -
-
- - - -
-
- - - - - - -
-
-
-
booleanMethods
-
- - - -
-
-
-
transactionMethods
-
- - - - - -
-
- -
-
blockMethods
- -
- - - - -
-
- - - -
-
- -
-
Methods
-
- - - - -
-
-
-
-
- - - - -
- - - - - diff --git a/test/web3/schema.js b/test/web3/schema.js deleted file mode 100644 index 54a6ff1a9708..000000000000 --- a/test/web3/schema.js +++ /dev/null @@ -1,209 +0,0 @@ -/* eslint no-unused-vars: 0 */ - -const params = { - // diffrent params used in the methods - param: [], - blockHashParams: '0xb3b20624f8f0f86eb50dd04688409e5cea4bd02d700bf6e79e9384d47d6a5a35', - filterParams: ['0xfe704947a3cd3ca12541458a4321c869'], - transactionHashParams: [ - '0xbb3a336e3f823ec18197f1e13ee875700f08f03e2cab75f0d0b118dabb44cba0', - ], - blockHashAndIndexParams: [ - '0xb3b20624f8f0f86eb50dd04688409e5cea4bd02d700bf6e79e9384d47d6a5a35', - '0x0', - ], - uncleByBlockNumberAndIndexParams: ['0x29c', '0x0'], - blockParameterParams: '0x5bad55', - data: '0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675', - addressParams: '0xc94770007dda54cF92009BFF0dE90c06F603a09f', - getStorageAtParams: [ - '0x295a70b2de5e3953354a6a8344e616ed314d7251', - '0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9', - '0x65a8db', - ], - getCodeParams: ['0x06012c8cf97bead5deae237070f9587f8e7a266d', '0x65a8db'], - estimateTransaction: { - from: '0xb60e8dd61c5d32be8058bb8eb970870f07233155', - to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567', - gas: '0x76c0', - gasPrice: '0x9184e72a000', - value: '0x9184e72a', - data: '0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675', - }, - filterGetLogs: [{ 'blockHash': '0x7c5a35e9cb3e8ae0e221ab470abae9d446c3a5626ce6689fc777dcffcab52c70', 'topics': ['0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80'] }], - block: { - __required: [], - number: 'Q', - hash: 'D32', - parentHash: 'D32', - nonce: 'D', - sha3Uncles: 'D', - logsBloom: 'D', - transactionsRoot: 'D', - stateRoot: 'D', - receiptsRoot: 'D', - miner: 'D', - difficulty: 'Q', - totalDifficulty: 'Q', - extraData: 'D', - size: 'Q', - gasLimit: 'Q', - gasUsed: 'Q', - timestamp: 'Q', - transactions: ['DATA|Transaction'], - uncles: ['D'], - }, - transaction: { - __required: [], - hash: 'D32', - nonce: 'Q', - blockHash: 'D32', - blockNumber: 'Q', - transactionIndex: 'Q', - from: 'D20', - to: 'D20', - value: 'Q', - gasPrice: 'Q', - gas: 'Q', - input: 'D', - }, - receipt: { - __required: [], - transactionHash: 'D32', - transactionIndex: 'Q', - blockHash: 'D32', - blockNumber: 'Q', - cumulativeGasUsed: 'Q', - gasUsed: 'Q', - contractAddress: 'D20', - logs: ['FilterChange'], - }, - - filterChange: { - __required: [], - removed: 'B', - logIndex: 'Q', - transactionIndex: 'Q', - transactionHash: 'D32', - blockHash: 'D32', - blockNumber: 'Q', - address: 'D20', - data: 'Array|DATA', - topics: ['D'], - }, -} - -const methods = { - hexaNumberMethods: { - // these are the methods which have output in the form of hexa decimal numbers - eth_blockNumber: ['eth_blockNumber', params.param, 'Q'], - eth_gasPrice: ['eth_gasPrice', params.param, 'Q'], - eth_newBlockFilter: ['eth_newBlockFilter', params.param, 'Q'], - eth_newPendingTransactionFilter: [ - 'eth_newPendingTransactionFilter', - params.param, - 'Q', - ], - eth_getUncleCountByBlockHash: [ - 'eth_getUncleCountByBlockHash', - [params.blockHashParams], - 'Q', - 1, - ], - eth_getBlockTransactionCountByHash: [ - 'eth_getBlockTransactionCountByHash', - [params.blockHashParams], - 'Q', - 1, - ], - eth_getTransactionCount: [ - 'eth_getTransactionCount', - [params.addressParams, params.blockParameterParams], - 'Q', - 1, - 2, - ], - eth_getBalance: ['eth_getBalance', [params.addressParams, 'latest'], 'Q', 1, 2], - eth_estimateGas: ['eth_estimateGas', [params.estimateTransaction], 'Q', 1], - eth_getUncleCountByBlockNumber: [ - 'eth_getUncleCountByBlockNumber', - [params.blockParameterParams], - 'Q', - 1, - ], - eth_getBlockTransactionCountByNumber: [ - 'eth_getBlockTransactionCountByNumber', - ['latest'], - 'Q', - 1, - ], - eth_protocolVersion: ['eth_protocolVersion', params.param, 'S'], - eth_getCode: ['eth_getCode', params.getCodeParams, 'D', 1, 2], - }, - booleanMethods: { - // these are the methods which have output in the form of boolean - eth_uninstallFilter: ['eth_uninstallFilter', params.filterParams, 'B', 1], - eth_mining: ['eth_mining', params.param, 'B'], - eth_syncing: ['eth_syncing', params.param, 'B|EthSyncing'], - }, - transactionMethods: { - // these are the methods which have output in the form of transaction object - eth_getTransactionByHash: [ - 'eth_getTransactionByHash', - params.transactionHashParams, - params.transaction, - 1, - ], - eth_getTransactionByBlockHashAndIndex: [ - 'eth_getTransactionByBlockHashAndIndex', - params.blockHashAndIndexParams, - params.transaction, - 2, - ], - eth_getTransactionByBlockNumberAndIndex: [ - 'eth_getTransactionByBlockNumberAndIndex', - [params.blockParameterParams, '0x0'], - params.transaction, - 2, - ], - - }, - blockMethods: { - // these are the methods which have output in the form of a block - - eth_getUncleByBlockNumberAndIndex: [ - 'eth_getUncleByBlockNumberAndIndex', - params.uncleByBlockNumberAndIndexParams, - params.block, - 2, - ], - eth_getBlockByHash: [ - 'eth_getBlockByHash', - [params.params, false], - params.block, - 2, - ], - eth_getBlockByNumber: [ - 'eth_getBlockByNumber', - [params.blockParameterParams, false], - params.block, - 2, - ], - }, - - methods: { - // these are the methods which have output in the form of bytes data - - eth_call: ['eth_call', [params.estimateTransaction, 'latest'], 'D', 1, 2], - eth_getStorageAt: ['eth_getStorageAt', params.getStorageAtParams, 'D', 2, 2], - eth_getTransactionReceipt: [ - 'eth_getTransactionReceipt', - params.transactionHashParams, - params.receipt, - 1, - ], - - }, - -} - diff --git a/test/web3/web3.js b/test/web3/web3.js deleted file mode 100644 index 49898044d7a0..000000000000 --- a/test/web3/web3.js +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint no-undef: 0 */ - -const json = methods - -web3.currentProvider.enable().then(() => { - - Object.keys(json).forEach((methodGroupKey) => { - - console.log(methodGroupKey) - const methodGroup = json[methodGroupKey] - console.log(methodGroup) - Object.keys(methodGroup).forEach((methodKey) => { - - const methodButton = document.getElementById(methodKey) - methodButton.addEventListener('click', () => { - - window.ethereum.sendAsync({ - method: methodKey, - params: methodGroup[methodKey][1], - }, (err, result) => { - if (err) { - console.log(err) - console.log(methodKey) - } else { - document.getElementById('results').innerHTML = JSON.stringify(result) - } - }) - }) - - }) - - }) -}) - From 2e33b57d174c463514772a6ac144ebda572db4cd Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Fri, 7 Aug 2020 14:31:02 -0500 Subject: [PATCH 057/137] colocate hide-token-confirmation modal styles (#9149) --- .../hide-token-confirmation-modal.js | 4 +- .../hide-token-confirmation-modal/index.js | 1 + .../hide-token-confirmation-modal/index.scss | 61 ++++++++++++++++++ ui/app/components/app/modals/index.scss | 1 + ui/app/css/itcss/components/modal.scss | 63 ------------------- 5 files changed, 65 insertions(+), 65 deletions(-) rename ui/app/components/app/modals/{ => hide-token-confirmation-modal}/hide-token-confirmation-modal.js (96%) create mode 100644 ui/app/components/app/modals/hide-token-confirmation-modal/index.js create mode 100644 ui/app/components/app/modals/hide-token-confirmation-modal/index.scss diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal.js b/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js similarity index 96% rename from ui/app/components/app/modals/hide-token-confirmation-modal.js rename to ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js index 5f8e6001a953..58fd01170652 100644 --- a/ui/app/components/app/modals/hide-token-confirmation-modal.js +++ b/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js @@ -1,8 +1,8 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' import { connect } from 'react-redux' -import * as actions from '../../../store/actions' -import Identicon from '../../ui/identicon' +import * as actions from '../../../../store/actions' +import Identicon from '../../../ui/identicon' function mapStateToProps (state) { return { diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal/index.js b/ui/app/components/app/modals/hide-token-confirmation-modal/index.js new file mode 100644 index 000000000000..31e8663986e6 --- /dev/null +++ b/ui/app/components/app/modals/hide-token-confirmation-modal/index.js @@ -0,0 +1 @@ +export { default } from './hide-token-confirmation-modal' diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal/index.scss b/ui/app/components/app/modals/hide-token-confirmation-modal/index.scss new file mode 100644 index 000000000000..d640b6c5c0b2 --- /dev/null +++ b/ui/app/components/app/modals/hide-token-confirmation-modal/index.scss @@ -0,0 +1,61 @@ +.hide-token-confirmation { + min-height: 250.72px; + border-radius: 4px; + background-color: $white; + box-shadow: 0 1px 7px 0 rgba(0, 0, 0, 0.5); + + &__container { + padding: 24px 27px 21px; + display: flex; + flex-direction: column; + align-items: center; + } + + &__identicon { + margin-bottom: 10px; + } + + &__symbol { + color: $tundora; + font-size: 16px; + line-height: 24px; + text-align: center; + margin-bottom: 7.5px; + } + + &__title { + height: 30px; + width: 271.28px; + color: $tundora; + font-size: 22px; + line-height: 30px; + text-align: center; + margin-bottom: 10.5px; + } + + &__copy { + height: 41px; + width: 318px; + color: $scorpion; + font-size: 14px; + line-height: 18px; + text-align: center; + } + + &__buttons { + display: flex; + flex-direction: row; + justify-content: center; + margin-top: 15px; + width: 100%; + } + + &__button { + @include Paragraph; + + @extend %button; + + width: 141px; + margin: 0 5px; + } +} diff --git a/ui/app/components/app/modals/index.scss b/ui/app/components/app/modals/index.scss index ae162ea16113..cf5a9d66b73a 100644 --- a/ui/app/components/app/modals/index.scss +++ b/ui/app/components/app/modals/index.scss @@ -1,6 +1,7 @@ @import 'cancel-transaction/index'; @import 'confirm-remove-account/index'; @import 'deposit-ether-modal/index'; +@import 'hide-token-confirmation-modal/index'; @import 'notification-modal/index'; @import 'qr-scanner/index'; @import 'transaction-confirmed/index'; diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index a0ed3728de8d..81b41e73c4d7 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -212,66 +212,3 @@ padding: 9px 13px 8px; } -// Hide token confirmation - -.hide-token-confirmation { - min-height: 250.72px; - border-radius: 4px; - background-color: $white; - box-shadow: 0 1px 7px 0 rgba(0, 0, 0, 0.5); - - &__container { - padding: 24px 27px 21px; - display: flex; - flex-direction: column; - align-items: center; - } - - &__identicon { - margin-bottom: 10px; - } - - &__symbol { - color: $tundora; - font-size: 16px; - line-height: 24px; - text-align: center; - margin-bottom: 7.5px; - } - - &__title { - height: 30px; - width: 271.28px; - color: $tundora; - font-size: 22px; - line-height: 30px; - text-align: center; - margin-bottom: 10.5px; - } - - &__copy { - height: 41px; - width: 318px; - color: $scorpion; - font-size: 14px; - line-height: 18px; - text-align: center; - } - - &__buttons { - display: flex; - flex-direction: row; - justify-content: center; - margin-top: 15px; - width: 100%; - } - - &__button { - @include Paragraph; - - @extend %button; - - width: 141px; - margin: 0 5px; - } -} From 3a7097a4cf991e4e2320ba08d84fee9c0d0e116d Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Sat, 8 Aug 2020 20:42:36 -0700 Subject: [PATCH 058/137] Add category in eventOpts (#9164) --- app/scripts/lib/background-metametrics.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/scripts/lib/background-metametrics.js b/app/scripts/lib/background-metametrics.js index f381ea3a12b3..9905e115bf0d 100644 --- a/app/scripts/lib/background-metametrics.js +++ b/app/scripts/lib/background-metametrics.js @@ -2,12 +2,14 @@ import { getBackgroundMetaMetricState } from '../../../ui/app/selectors' import { sendMetaMetricsEvent } from '../../../ui/app/helpers/utils/metametrics.util' export default function backgroundMetaMetricsEvent (metaMaskState, eventData) { + + eventData.eventOpts['category'] = 'Background' + const stateEventData = getBackgroundMetaMetricState({ metamask: metaMaskState }) if (stateEventData.participateInMetaMetrics) { sendMetaMetricsEvent({ ...stateEventData, ...eventData, - category: 'Background', currentPath: '/background', }) } From c557e25ba62bab9d848dce7c27027e2b4452d46d Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 10 Aug 2020 12:10:30 -0300 Subject: [PATCH 059/137] Add `version` dimension to background metrics (#9167) The background metrics were missing the `version` custom dimension. It has now been added to all background metric events. --- app/scripts/lib/background-metametrics.js | 3 ++- app/scripts/metamask-controller.js | 17 +++++++++++------ ui/app/helpers/utils/metametrics.util.js | 1 + 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/app/scripts/lib/background-metametrics.js b/app/scripts/lib/background-metametrics.js index 9905e115bf0d..a9baa79b71b2 100644 --- a/app/scripts/lib/background-metametrics.js +++ b/app/scripts/lib/background-metametrics.js @@ -1,7 +1,7 @@ import { getBackgroundMetaMetricState } from '../../../ui/app/selectors' import { sendMetaMetricsEvent } from '../../../ui/app/helpers/utils/metametrics.util' -export default function backgroundMetaMetricsEvent (metaMaskState, eventData) { +export default function backgroundMetaMetricsEvent (metaMaskState, version, eventData) { eventData.eventOpts['category'] = 'Background' @@ -10,6 +10,7 @@ export default function backgroundMetaMetricsEvent (metaMaskState, eventData) { sendMetaMetricsEvent({ ...stateEventData, ...eventData, + version, currentPath: '/background', }) } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index f9821e822cbd..b0866ce08987 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1842,13 +1842,18 @@ export default class MetamaskController extends EventEmitter { } const metamaskState = await this.getState() - backgroundMetaMetricsEvent(metamaskState, { - customVariables, - eventOpts: { - action, - name, + const version = this.platform.getVersion() + backgroundMetaMetricsEvent( + metamaskState, + version, + { + customVariables, + eventOpts: { + action, + name, + }, }, - }) + ) } //============================================================================= diff --git a/ui/app/helpers/utils/metametrics.util.js b/ui/app/helpers/utils/metametrics.util.js index cf9f157202ea..0ffe856bfbd1 100644 --- a/ui/app/helpers/utils/metametrics.util.js +++ b/ui/app/helpers/utils/metametrics.util.js @@ -115,6 +115,7 @@ function composeParamAddition (paramValue, paramName) { * @property {string} config.accountType The account type being used at the time of the event: 'hardware', 'imported' or 'default' * @property {number} config.numberOfTokens The number of tokens that the user has added at the time of the event * @property {number} config.numberOfAccounts The number of accounts the user has added at the time of the event + * @property {string} config.version The current version of the MetaMask extension * @property {string} config.previousPath The pathname of the URL the user was on prior to the URL they are on at the time of the event * @property {string} config.currentPath The pathname of the URL the user is on at the time of the event * @property {string} config.metaMetricsId A random id assigned to a user at the time of opting in to metametrics. A hexadecimal number From cb503d9403b7a8bf7efe1282b58cf715f46b6440 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 10 Aug 2020 12:38:56 -0300 Subject: [PATCH 060/137] Refactor assignment of "Background" metrics category (#9168) The "Background" metrics category was being set in the `backgroundMetaMetricsEvent` function. This function might not necessarily include any event at all though, so setting it here seemed inappropriate. It would also crash if `eventData.eventOpts` was not set, which is not great since that property is optional. The background category is now set in the `sendBackgroundMetaMetrics` function in `metamask-controller`. This method is used solely for event data, so it would make sense for this category to be always set. There is no functional difference, since `backgroundMetaMetricsEvent` is called solely by `sendBackgroundMetaMetrics`. --- app/scripts/lib/background-metametrics.js | 3 --- app/scripts/metamask-controller.js | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/scripts/lib/background-metametrics.js b/app/scripts/lib/background-metametrics.js index a9baa79b71b2..7af1125c1780 100644 --- a/app/scripts/lib/background-metametrics.js +++ b/app/scripts/lib/background-metametrics.js @@ -2,9 +2,6 @@ import { getBackgroundMetaMetricState } from '../../../ui/app/selectors' import { sendMetaMetricsEvent } from '../../../ui/app/helpers/utils/metametrics.util' export default function backgroundMetaMetricsEvent (metaMaskState, version, eventData) { - - eventData.eventOpts['category'] = 'Background' - const stateEventData = getBackgroundMetaMetricState({ metamask: metaMaskState }) if (stateEventData.participateInMetaMetrics) { sendMetaMetricsEvent({ diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index b0866ce08987..2b32a8a42639 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1850,6 +1850,7 @@ export default class MetamaskController extends EventEmitter { customVariables, eventOpts: { action, + category: 'Background', name, }, }, From 4922b1b9b56844c68571070a300a4683f74b6946 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Mon, 10 Aug 2020 08:58:17 -0700 Subject: [PATCH 061/137] Check if getCleanAppState is defined before calling (#9170) --- test/e2e/webdriver/driver.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index daf3a1acc8f4..6ae17bdcfb46 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -180,7 +180,9 @@ class Driver { await fs.writeFile(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' }) const htmlSource = await this.driver.getPageSource() await fs.writeFile(`${filepathBase}-dom.html`, htmlSource) - const uiState = await this.driver.executeScript(() => window.getCleanAppState()) + const uiState = await this.driver.executeScript( + () => window.getCleanAppState && window.getCleanAppState(), + ) await fs.writeFile(`${filepathBase}-state.json`, JSON.stringify(uiState, null, 2)) } From b8edc32f48cdb327d5ae6276a902722b7072f61a Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 11 Aug 2020 10:59:24 -0230 Subject: [PATCH 062/137] Fee card component (#9169) * Fee card component * Clean up * Style lint fixes --- .storybook/main.js | 2 +- ui/app/pages/index.scss | 1 + ui/app/pages/token/fee-card/fee-card.js | 69 ++++++++++++ .../pages/token/fee-card/fee-card.stories.js | 47 ++++++++ ui/app/pages/token/fee-card/index.js | 1 + ui/app/pages/token/fee-card/index.scss | 102 ++++++++++++++++++ ui/app/pages/token/index.scss | 1 + 7 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 ui/app/pages/token/fee-card/fee-card.js create mode 100644 ui/app/pages/token/fee-card/fee-card.stories.js create mode 100644 ui/app/pages/token/fee-card/index.js create mode 100644 ui/app/pages/token/fee-card/index.scss create mode 100644 ui/app/pages/token/index.scss diff --git a/.storybook/main.js b/.storybook/main.js index 598003cddb11..74acf6fb81a4 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,5 +1,5 @@ module.exports = { - stories: ['../ui/app/components/**/*.stories.js'], + stories: ['../ui/app/**/*.stories.js'], addons: [ '@storybook/addon-knobs', '@storybook/addon-actions', diff --git a/ui/app/pages/index.scss b/ui/app/pages/index.scss index 95bdc748969f..8154fc77d043 100644 --- a/ui/app/pages/index.scss +++ b/ui/app/pages/index.scss @@ -12,3 +12,4 @@ @import 'confirm-approve/index'; @import 'permissions-connect/index'; @import 'asset/asset'; +@import 'token/index'; diff --git a/ui/app/pages/token/fee-card/fee-card.js b/ui/app/pages/token/fee-card/fee-card.js new file mode 100644 index 000000000000..42e751d77191 --- /dev/null +++ b/ui/app/pages/token/fee-card/fee-card.js @@ -0,0 +1,69 @@ +import React from 'react' +import PropTypes from 'prop-types' + +export default function FeeCard ({ + onFeeRowClick = null, + feeRowText, + feeRowLinkText = '', + primaryFee, + secondaryFee = '', + onSecondRowClick = null, + secondRowText = '', + secondRowLinkText = '', + hideSecondRow = false, +}) { + return ( +
+
+
onFeeRowClick && onFeeRowClick()}> +
+
+ {feeRowText} +
+ {onFeeRowClick && ( +
+ {feeRowLinkText} +
+ )} +
+
+
+ {primaryFee} +
+ {secondaryFee && ( +
+ {secondaryFee} +
+ )} +
+
+ {!hideSecondRow && secondRowText && ( +
+
+
+ {secondRowText} +
+ {secondRowLinkText && ( +
onSecondRowClick && onSecondRowClick()}> + {secondRowLinkText} +
+ )} +
+
+ )} +
+
+ ) +} + +FeeCard.propTypes = { + onFeeRowClick: PropTypes.func, + feeRowText: PropTypes.string.isRequired, + feeRowLinkText: PropTypes.string, + primaryFee: PropTypes.string.isRequired, + secondaryFee: PropTypes.string, + onSecondRowClick: PropTypes.func, + secondRowText: PropTypes.string, + secondRowLinkText: PropTypes.string, + hideSecondRow: PropTypes.bool, +} diff --git a/ui/app/pages/token/fee-card/fee-card.stories.js b/ui/app/pages/token/fee-card/fee-card.stories.js new file mode 100644 index 000000000000..8cadfed27033 --- /dev/null +++ b/ui/app/pages/token/fee-card/fee-card.stories.js @@ -0,0 +1,47 @@ +import React from 'react' +import FeeCard from './fee-card.js' +import { action } from '@storybook/addon-actions' +import { text } from '@storybook/addon-knobs/react' + +const containerStyle = { + width: '300px', +} + +export default { + title: 'FeeCard', +} + +export const WithSecondRow = () => { + return ( +
+ +
+ ) +} + +export const WithoutSecondRow = () => { + return ( +
+ +
+ ) +} diff --git a/ui/app/pages/token/fee-card/index.js b/ui/app/pages/token/fee-card/index.js new file mode 100644 index 000000000000..84bc1acbb584 --- /dev/null +++ b/ui/app/pages/token/fee-card/index.js @@ -0,0 +1 @@ +export { default } from './fee-card' diff --git a/ui/app/pages/token/fee-card/index.scss b/ui/app/pages/token/fee-card/index.scss new file mode 100644 index 000000000000..d9acd2554c5e --- /dev/null +++ b/ui/app/pages/token/fee-card/index.scss @@ -0,0 +1,102 @@ +.fee-card { + border-radius: 8px; + border: 1px solid $Grey-100; + width: 100%; + margin-top: auto; + margin-bottom: 8px; + + @include H7; + + &__main { + padding: 16px 16px 12px 16px; + } + + &__row-header { + display: flex; + align-items: center; + margin-top: 8px; + justify-content: space-between; + + @media screen and (min-width: 576px) { + @include H6; + } + + &:first-of-type { + margin-top: 0; + } + + div { + display: flex; + align-items: center; + } + } + + &__row-header-text { + font-weight: bold; + margin-right: 8px; + cursor: pointer; + } + + &__row { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 8px; + } + + &__row-label { + display: flex; + align-items: center; + + img { + height: 10px; + width: 10px; + margin-left: 4px; + cursor: pointer; + } + } + + &__row-text { + margin-right: 8px; + } + + &__row-fee { + margin-right: 4px; + } + + &__link { + color: $Blue-500; + cursor: pointer; + } + + &__total-box { + border-top: 1px solid $Grey-100; + padding: 12px 16px 16px 16px; + } + + &__total-row { + display: flex; + justify-content: space-between; + align-items: center; + font-weight: bold; + } + + &__total-secondary { + width: 100%; + display: flex; + justify-content: flex-end; + font-weight: bold; + color: $Grey-500; + margin-top: 4px; + } + + &__row-header-secondary { + color: $Grey-500; + margin-right: 20px; + } + + &__row-header-primary { + font-weight: bold; + color: $Grey-500; + } +} diff --git a/ui/app/pages/token/index.scss b/ui/app/pages/token/index.scss new file mode 100644 index 000000000000..013ff392875f --- /dev/null +++ b/ui/app/pages/token/index.scss @@ -0,0 +1 @@ +@import 'fee-card/index'; From 6ba9e657128c6261f0df03b9d465df9cd884d997 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Tue, 11 Aug 2020 08:58:10 -0500 Subject: [PATCH 063/137] colocate tab-bar styles with the tab-bar component (#9176) Moves styles out of the itcss components folder and places them alongside the component. --- ui/app/components/app/index.scss | 1 + ui/app/components/app/tab-bar/index.js | 1 + ui/app/components/app/tab-bar/index.scss | 80 +++++++++++++++++++ .../components/app/{ => tab-bar}/tab-bar.js | 0 ui/app/css/itcss/components/index.scss | 1 - ui/app/css/itcss/components/tab-bar.scss | 79 ------------------ 6 files changed, 82 insertions(+), 80 deletions(-) create mode 100644 ui/app/components/app/tab-bar/index.js create mode 100644 ui/app/components/app/tab-bar/index.scss rename ui/app/components/app/{ => tab-bar}/tab-bar.js (100%) delete mode 100644 ui/app/css/itcss/components/tab-bar.scss diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/index.scss index 69ed2bb231f1..cff447a65c5e 100644 --- a/ui/app/components/app/index.scss +++ b/ui/app/components/app/index.scss @@ -59,6 +59,7 @@ @import '../ui/dropdown/dropdown'; @import 'permissions-connect-header/index'; @import 'permissions-connect-footer/index'; +@import 'tab-bar/index'; @import 'wallet-overview/index'; @import '../ui/account-mismatch-warning/index'; @import '../ui/icon-border/icon-border'; diff --git a/ui/app/components/app/tab-bar/index.js b/ui/app/components/app/tab-bar/index.js new file mode 100644 index 000000000000..74f9a752921d --- /dev/null +++ b/ui/app/components/app/tab-bar/index.js @@ -0,0 +1 @@ +export { default } from './tab-bar' diff --git a/ui/app/components/app/tab-bar/index.scss b/ui/app/components/app/tab-bar/index.scss new file mode 100644 index 000000000000..0b9d0605d250 --- /dev/null +++ b/ui/app/components/app/tab-bar/index.scss @@ -0,0 +1,80 @@ +.tab-bar { + display: flex; + flex-direction: column; + justify-content: flex-start; + + + &__tab { + display: flex; + flex-flow: row nowrap; + align-items: flex-start; + min-width: 0; + flex: 0 0 auto; + box-sizing: border-box; + font-size: 16px; + padding: 16px 24px; + opacity: 0.5; + transition: opacity 200ms ease-in-out; + + @media screen and (min-width: 576px) { + &:hover { + opacity: 0.4; + } + + &:active { + opacity: 0.6; + } + } + + @media screen and (max-width: 575px) { + font-size: 18px; + padding: 24px; + border-bottom: 1px solid $alto; + opacity: 1; + } + + &__content { + flex: 1 1 auto; + width: 0; + + &__description { + display: none; + + @media screen and (max-width: 575px) { + display: block; + font-size: 14px; + font-weight: 300; + margin-top: 8px; + min-height: 14px; + } + } + } + + &__caret { + display: none; + + @media screen and (max-width: 575px) { + display: block; + background-image: url('/images/caret-right.svg'); + width: 36px; + height: 36px; + opacity: 0.5; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + + [dir='rtl'] & { + transform: rotate(180deg); + } + } + } + + &--active { + opacity: 1 !important; + } + } + + &__grow-tab { + flex-grow: 1; + } +} diff --git a/ui/app/components/app/tab-bar.js b/ui/app/components/app/tab-bar/tab-bar.js similarity index 100% rename from ui/app/components/app/tab-bar.js rename to ui/app/components/app/tab-bar/tab-bar.js diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 1936706dcb72..f9ca7c41d295 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -14,7 +14,6 @@ // Tx List and Sections @import './menu'; @import './gas-slider'; -@import './tab-bar'; @import './simple-dropdown'; @import './request-signature'; @import './request-encryption-public-key'; diff --git a/ui/app/css/itcss/components/tab-bar.scss b/ui/app/css/itcss/components/tab-bar.scss deleted file mode 100644 index 2579b279fd52..000000000000 --- a/ui/app/css/itcss/components/tab-bar.scss +++ /dev/null @@ -1,79 +0,0 @@ -.tab-bar { - display: flex; - flex-direction: column; - justify-content: flex-start; -} - -.tab-bar__tab { - display: flex; - flex-flow: row nowrap; - align-items: flex-start; - min-width: 0; - flex: 0 0 auto; - box-sizing: border-box; - font-size: 16px; - padding: 16px 24px; - opacity: 0.5; - transition: opacity 200ms ease-in-out; - - @media screen and (min-width: 576px) { - &:hover { - opacity: 0.4; - } - - &:active { - opacity: 0.6; - } - } - - @media screen and (max-width: 575px) { - font-size: 18px; - padding: 24px; - border-bottom: 1px solid $alto; - opacity: 1; - } - - &__content { - flex: 1 1 auto; - width: 0; - - &__description { - display: none; - - @media screen and (max-width: 575px) { - display: block; - font-size: 14px; - font-weight: 300; - margin-top: 8px; - min-height: 14px; - } - } - } - - &__caret { - display: none; - - @media screen and (max-width: 575px) { - display: block; - background-image: url('/images/caret-right.svg'); - width: 36px; - height: 36px; - opacity: 0.5; - background-size: contain; - background-repeat: no-repeat; - background-position: center; - - [dir='rtl'] & { - transform: rotate(180deg); - } - } - } - - &--active { - opacity: 1 !important; - } -} - -.tab-bar__grow-tab { - flex-grow: 1; -} From 01f69d7e7a2dd19b471d351883d000dee42a992b Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Tue, 11 Aug 2020 11:07:47 -0500 Subject: [PATCH 064/137] colocate account modal styles with their components (#9150) This one gets a bit more complicated because the styles were interwoven and needed to be untangled to be moved. Essentially, though, the goal is to put the styles where they make the most sense and colocate them with their components. --- test/e2e/ethereum-on.spec.js | 2 +- test/e2e/from-import-ui.spec.js | 4 +- test/e2e/incremental-security.spec.js | 2 +- test/e2e/metamask-ui.spec.js | 2 +- test/e2e/permissions.spec.js | 2 +- test/e2e/signature-request.spec.js | 2 +- .../account-details-modal.component.js | 10 +- .../modals/account-details-modal/index.scss | 37 ++++ .../account-modal-container.component.js | 13 +- .../modals/account-modal-container/index.scss | 50 +++++ .../export-private-key-modal.component.js | 29 +-- .../export-private-key-modal/index.scss | 106 ++++++++++ ui/app/components/app/modals/index.scss | 3 + .../tests/account-details-modal.test.js | 10 +- ui/app/css/itcss/components/modal.scss | 184 ------------------ 15 files changed, 236 insertions(+), 220 deletions(-) create mode 100644 ui/app/components/app/modals/account-details-modal/index.scss create mode 100644 ui/app/components/app/modals/account-modal-container/index.scss create mode 100644 ui/app/components/app/modals/export-private-key-modal/index.scss diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index 361579cd2c23..8c0426a0d126 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -93,7 +93,7 @@ describe('MetaMask', function () { publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) - await driver.clickElement(By.css('.account-modal-close')) + await driver.clickElement(By.css('.account-modal__close')) await driver.wait(until.stalenessOf(accountModal)) await driver.delay(regularDelayMs) diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index 78bdd03528f7..432432b3e579 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -105,7 +105,7 @@ describe('Using MetaMask with an existing account', function () { const [address] = await driver.findElements(By.css('.readonly-input__input')) assert.equal(await address.getAttribute('value'), testAddress) - await driver.clickElement(By.css('.account-modal-close')) + await driver.clickElement(By.css('.account-modal__close')) await driver.delay(largeDelayMs) }) @@ -116,7 +116,7 @@ describe('Using MetaMask with an existing account', function () { const detailModal = await driver.findElement(By.css('span .modal')) await driver.delay(regularDelayMs) - await driver.clickElement(By.css('.account-modal-close')) + await driver.clickElement(By.css('.account-modal__close')) await driver.wait(until.stalenessOf(detailModal)) await driver.delay(regularDelayMs) }) diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index a6482c58d90f..7008ec69cb33 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -100,7 +100,7 @@ describe('MetaMask', function () { const accountModal = await driver.findElement(By.css('span .modal')) - await driver.clickElement(By.css('.account-modal-close')) + await driver.clickElement(By.css('.account-modal__close')) await driver.wait(until.stalenessOf(accountModal)) await driver.delay(regularDelayMs) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index d501bdb3ac38..dfff8e49bac1 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -125,7 +125,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) const accountModal = await driver.findElement(By.css('span .modal')) - await driver.clickElement(By.css('.account-modal-close')) + await driver.clickElement(By.css('.account-modal__close')) await driver.wait(until.stalenessOf(accountModal)) await driver.delay(regularDelayMs) diff --git a/test/e2e/permissions.spec.js b/test/e2e/permissions.spec.js index 3d45e447784c..cd6cef45318d 100644 --- a/test/e2e/permissions.spec.js +++ b/test/e2e/permissions.spec.js @@ -94,7 +94,7 @@ describe('MetaMask', function () { publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) - await driver.clickElement(By.css('.account-modal-close')) + await driver.clickElement(By.css('.account-modal__close')) await driver.wait(until.stalenessOf(accountModal)) await driver.delay(regularDelayMs) diff --git a/test/e2e/signature-request.spec.js b/test/e2e/signature-request.spec.js index 9abac241b849..4ad70e15e69d 100644 --- a/test/e2e/signature-request.spec.js +++ b/test/e2e/signature-request.spec.js @@ -128,7 +128,7 @@ describe('MetaMask', function () { const newPublicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) - await driver.clickElement(By.css('.account-modal-close')) + await driver.clickElement(By.css('.account-modal__close')) await driver.wait(until.stalenessOf(accountModal)) await driver.delay(regularDelayMs) diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js index fafdd8444b3b..b6647f4c2036 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js @@ -42,9 +42,9 @@ export default class AccountDetailsModal extends Component { } return ( - + setAccountLabel(address, label)} /> @@ -56,11 +56,11 @@ export default class AccountDetailsModal extends Component { }} /> -
+
@@ -44,6 +46,7 @@ AccountModalContainer.defaultProps = { } AccountModalContainer.propTypes = { + className: PropTypes.string, selectedIdentity: PropTypes.object.isRequired, showBackButton: PropTypes.bool, backButtonAction: PropTypes.func, diff --git a/ui/app/components/app/modals/account-modal-container/index.scss b/ui/app/components/app/modals/account-modal-container/index.scss new file mode 100644 index 000000000000..8981854ee811 --- /dev/null +++ b/ui/app/components/app/modals/account-modal-container/index.scss @@ -0,0 +1,50 @@ +// Account Modal Container +.account-modal { + &__container { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; + position: relative; + padding: 5px 0 31px 0; + border: 1px solid $silver; + border-radius: 4px; + } + + &__back { + color: $dusty-gray; + position: absolute; + top: 13px; + left: 17px; + cursor: pointer; + } + + &__text { + margin-top: 2px; + font-size: 14px; + line-height: 18px; + } + + &__close { + font-size: 40px; + background-color: transparent; + color: $dusty-gray; + position: absolute; + cursor: pointer; + top: 10px; + right: 12px; + + &::after { + content: '\00D7'; + } + } + + & .identicon { + position: relative; + left: 0; + right: 0; + margin: 0 auto; + top: -32px; + margin-bottom: -32px; + } +} diff --git a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js index 318dd0d5891b..ba30d5218919 100644 --- a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js +++ b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js @@ -47,7 +47,7 @@ export default class ExportPrivateKeyModal extends Component { renderPasswordLabel (privateKey) { return ( - + { privateKey ? this.context.t('copyPrivateKey') @@ -64,7 +64,7 @@ export default class ExportPrivateKeyModal extends Component { return ( this.setState({ password: event.target.value })} /> ) @@ -72,8 +72,8 @@ export default class ExportPrivateKeyModal extends Component { return ( copyToClipboard(plainKey)} @@ -83,12 +83,12 @@ export default class ExportPrivateKeyModal extends Component { renderButtons (privateKey, address, hideModal) { return ( -
+
{!privateKey && ( @@ -111,7 +111,7 @@ export default class ExportPrivateKeyModal extends Component { onClick={() => this.exportAccountAndGetPrivateKey(this.state.password, address)} type="secondary" large - className="export-private-key__button" + className="export-private-key-modal__button" disabled={!this.state.password} > {this.context.t('confirm')} @@ -139,27 +139,28 @@ export default class ExportPrivateKeyModal extends Component { return ( showAccountDetailModal()} > - {name} + {name} -
- {this.context.t('showPrivateKeys')} -
+
+ {this.context.t('showPrivateKeys')} +
{this.renderPasswordLabel(privateKey)} {this.renderPasswordInput(privateKey)} { (showWarning && warning) - ? {warning} + ? {warning} : null }
-
{this.context.t('privateKeyWarning')}
+
{this.context.t('privateKeyWarning')}
{this.renderButtons(privateKey, address, hideModal)} ) diff --git a/ui/app/components/app/modals/export-private-key-modal/index.scss b/ui/app/components/app/modals/export-private-key-modal/index.scss new file mode 100644 index 000000000000..8fd3c31336d2 --- /dev/null +++ b/ui/app/components/app/modals/export-private-key-modal/index.scss @@ -0,0 +1,106 @@ +.export-private-key-modal { + &__body-title { + margin-top: 16px; + margin-bottom: 16px; + font-size: 18px; + } + + &__divider { + width: 100%; + height: 1px; + margin: 19px 0 8px 0; + background-color: $alto; + } + + &__account-name { + margin-top: 9px; + font-size: 20px; + } + + &__password { + display: flex; + flex-direction: column; + } + + &__password-label, + &__password--error { + color: $scorpion; + font-size: 14px; + line-height: 18px; + margin-bottom: 10px; + } + + &__password--error { + color: $crimson; + margin-bottom: 0; + } + + &__password-input { + padding: 10px 0 13px 17px; + font-size: 16px; + line-height: 21px; + width: 291px; + height: 44px; + } + + &__password::-webkit-input-placeholder { + color: $dusty-gray; + } + + &__password--warning { + border-radius: 8px; + background-color: #fff6f6; + font-size: 12px; + font-weight: 500; + line-height: 15px; + color: $crimson; + width: 292px; + padding: 9px 15px; + margin-top: 18px; + } + + &__password-display-wrapper { + height: 80px; + width: 291px; + border: 1px solid $silver; + border-radius: 2px; + } + + &__password-display-textarea { + color: $crimson; + font-size: 16px; + line-height: 21px; + border: none; + height: 75px; + width: 100%; + overflow: hidden; + resize: none; + padding: 9px 13px 8px; + } + + &__buttons { + display: flex; + flex-direction: row; + justify-content: center; + } + + &__button { + margin-top: 17px; + width: 141px; + min-width: initial; + } + + &__button--cancel { + margin-right: 15px; + } + + & .ellip-address-wrapper { + display: flex; + justify-content: center; + border: 1px solid $alto; + padding: 5px 10px; + margin-top: 7px; + width: 286px; + } +} + diff --git a/ui/app/components/app/modals/index.scss b/ui/app/components/app/modals/index.scss index cf5a9d66b73a..84ad997b6eb5 100644 --- a/ui/app/components/app/modals/index.scss +++ b/ui/app/components/app/modals/index.scss @@ -1,6 +1,9 @@ +@import 'account-details-modal/index'; +@import 'account-modal-container/index'; @import 'cancel-transaction/index'; @import 'confirm-remove-account/index'; @import 'deposit-ether-modal/index'; +@import 'export-private-key-modal/index'; @import 'hide-token-confirmation-modal/index'; @import 'notification-modal/index'; @import 'qr-scanner/index'; diff --git a/ui/app/components/app/modals/tests/account-details-modal.test.js b/ui/app/components/app/modals/tests/account-details-modal.test.js index 3c0dd8f2572c..505b823cd12c 100644 --- a/ui/app/components/app/modals/tests/account-details-modal.test.js +++ b/ui/app/components/app/modals/tests/account-details-modal.test.js @@ -46,7 +46,7 @@ describe('Account Details Modal', function () { }) it('sets account label when changing default account label', function () { - const accountLabel = wrapper.find('.account-modal__name').first() + const accountLabel = wrapper.find('.account-details-modal__name').first() accountLabel.simulate('submit', 'New Label') assert(props.setAccountLabel.calledOnce) @@ -54,7 +54,7 @@ describe('Account Details Modal', function () { }) it('opens new tab when view block explorer is clicked', function () { - const modalButton = wrapper.find('.account-modal__button') + const modalButton = wrapper.find('.account-details-modal__button') const etherscanLink = modalButton.first() etherscanLink.simulate('click') @@ -62,7 +62,7 @@ describe('Account Details Modal', function () { }) it('shows export private key modal when clicked', function () { - const modalButton = wrapper.find('.account-modal__button') + const modalButton = wrapper.find('.account-details-modal__button') const etherscanLink = modalButton.last() etherscanLink.simulate('click') @@ -73,9 +73,9 @@ describe('Account Details Modal', function () { const blockExplorerUrl = 'https://block.explorer' wrapper.setProps({ rpcPrefs: { blockExplorerUrl } }) - const modalButton = wrapper.find('.account-modal__button') + const modalButton = wrapper.find('.account-details-modal__button') const blockExplorerLink = modalButton.first() - assert.equal(blockExplorerLink.html(), '') + assert.equal(blockExplorerLink.html(), '') }) }) diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index 81b41e73c4d7..1dbf63e66f20 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -28,187 +28,3 @@ .modal > div:focus { outline: none !important; } - -// Account Modal Container -.account-modal-container { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: center; - position: relative; - padding: 5px 0 31px 0; - border: 1px solid $silver; - border-radius: 4px; - - button { - cursor: pointer; - } -} - -.account-modal-back { - color: $dusty-gray; - position: absolute; - top: 13px; - left: 17px; - cursor: pointer; - - &__text { - margin-top: 2px; - font-size: 14px; - line-height: 18px; - } -} - -.account-modal-close { - font-size: 40px; - background-color: transparent; - color: $dusty-gray; - position: absolute; - top: 10px; - right: 12px; -} - -.account-modal-close::after { - content: '\00D7'; -} - -.account-modal-container .identicon { - position: relative; - left: 0; - right: 0; - margin: 0 auto; - top: -32px; - margin-bottom: -32px; -} - - -// Account Details Modal - -.account-modal-container { - .qr-code__header { - margin-top: 9px; - font-size: 20px; - } - - .qr-code__wrapper { - margin-top: 5px; - } - - .ellip-address-wrapper { - display: flex; - justify-content: center; - border: 1px solid $alto; - padding: 5px 10px; - margin-top: 7px; - width: 286px; - } - - .account-modal__button { - margin-top: 17px; - padding: 10px 22px; - width: 286px; - } -} - -.account-modal-divider { - width: 100%; - height: 1px; - margin: 19px 0 8px 0; - background-color: $alto; -} - -// Export Private Key Modal - -.account-modal-container .account-name { - margin-top: 9px; - font-size: 20px; -} - -.account-modal-container .modal-body-title { - margin-top: 16px; - margin-bottom: 16px; - font-size: 18px; -} - -.account-modal__name { - margin-top: 9px; - font-size: 20px; -} - -.private-key-password { - display: flex; - flex-direction: column; -} - -.private-key-password-label, -.private-key-password-error { - color: $scorpion; - font-size: 14px; - line-height: 18px; - margin-bottom: 10px; -} - -.private-key-password-error { - color: $crimson; - margin-bottom: 0; -} - -.private-key-password-input { - padding: 10px 0 13px 17px; - font-size: 16px; - line-height: 21px; - width: 291px; - height: 44px; -} - -.private-key-password::-webkit-input-placeholder { - color: $dusty-gray; -} - -.private-key-password-warning { - border-radius: 8px; - background-color: #fff6f6; - font-size: 12px; - font-weight: 500; - line-height: 15px; - color: $crimson; - width: 292px; - padding: 9px 15px; - margin-top: 18px; -} - -.export-private-key-buttons { - display: flex; - flex-direction: row; - justify-content: center; -} - -.export-private-key__button { - margin-top: 17px; - width: 141px; - min-width: initial; -} - -.export-private-key__button--cancel { - margin-right: 15px; -} - -.private-key-password-display-wrapper { - height: 80px; - width: 291px; - border: 1px solid $silver; - border-radius: 2px; -} - -.private-key-password-display-textarea { - color: $crimson; - font-size: 16px; - line-height: 21px; - border: none; - height: 75px; - width: 100%; - overflow: hidden; - resize: none; - padding: 9px 13px 8px; -} - From ef68a7963c30869b374f902b6508b142788adb68 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Tue, 11 Aug 2020 09:17:50 -0700 Subject: [PATCH 065/137] fix account modal back styling --- .../account-modal-container.component.js | 2 +- .../app/modals/account-modal-container/index.scss | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js b/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js index d1fbe0b7e78b..fb8cee58c22d 100644 --- a/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js +++ b/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js @@ -25,7 +25,7 @@ export default function AccountModalContainer (props, context) { {showBackButton && (
- {' ' + context.t('back')} + {context.t('back')}
)} + , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, ) diff --git a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js index 0c9726aef166..f0e3edf4df1f 100644 --- a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js +++ b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js @@ -34,7 +34,7 @@ describe('TransactionListItemDetails Component', function () { title="Test Transaction Details" recipientAddress="0x1" senderAddress="0x2" - tryReverseResolveAddress={() => {}} + tryReverseResolveAddress={() => undefined} transactionGroup={transactionGroup} senderNickname="sender-nickname" recipientNickname="recipient-nickname" @@ -77,7 +77,7 @@ describe('TransactionListItemDetails Component', function () { {}} + tryReverseResolveAddress={() => undefined} transactionGroup={transactionGroup} showSpeedUp senderNickname="sender-nickname" @@ -117,7 +117,7 @@ describe('TransactionListItemDetails Component', function () { {}} + tryReverseResolveAddress={() => undefined} transactionGroup={transactionGroup} senderNickname="sender-nickname" recipientNickname="recipient-nickname" @@ -159,7 +159,7 @@ describe('TransactionListItemDetails Component', function () { {}} + tryReverseResolveAddress={() => undefined} transactionGroup={transactionGroup} senderNickname="sender-nickname" recipientNickname="recipient-nickname" diff --git a/ui/app/hooks/tests/useCancelTransaction.test.js b/ui/app/hooks/tests/useCancelTransaction.test.js index be2256cd9df0..920b9e223378 100644 --- a/ui/app/hooks/tests/useCancelTransaction.test.js +++ b/ui/app/hooks/tests/useCancelTransaction.test.js @@ -46,7 +46,7 @@ describe('useCancelTransaction', function () { it(`should return a function that kicks off cancellation for id ${transactionId}`, function () { const { result } = renderHook(() => useCancelTransaction(transactionGroup)) assert.equal(typeof result.current[1], 'function') - result.current[1]({ preventDefault: () => {}, stopPropagation: () => {} }) + result.current[1]({ preventDefault: () => undefined, stopPropagation: () => undefined }) assert.equal( dispatch.calledWith( showModal({ @@ -90,7 +90,7 @@ describe('useCancelTransaction', function () { it(`should return a function that kicks off cancellation for id ${transactionId}`, function () { const { result } = renderHook(() => useCancelTransaction(transactionGroup)) assert.equal(typeof result.current[1], 'function') - result.current[1]({ preventDefault: () => {}, stopPropagation: () => {} }) + result.current[1]({ preventDefault: () => undefined, stopPropagation: () => undefined }) assert.equal( dispatch.calledWith( showModal({ diff --git a/ui/app/hooks/tests/useRetryTransaction.test.js b/ui/app/hooks/tests/useRetryTransaction.test.js index d6c55d0f8b7e..e4e8160a8948 100644 --- a/ui/app/hooks/tests/useRetryTransaction.test.js +++ b/ui/app/hooks/tests/useRetryTransaction.test.js @@ -12,7 +12,7 @@ describe('useRetryTransaction', function () { describe('when transaction meets retry enabled criteria', function () { const dispatch = sinon.spy(() => Promise.resolve({ blockTime: 0 })) const trackEvent = sinon.spy() - const event = { preventDefault: () => {}, stopPropagation: () => {} } + const event = { preventDefault: () => undefined, stopPropagation: () => undefined } before(function () { sinon.stub(reactRedux, 'useDispatch').returns(dispatch) diff --git a/ui/app/pages/add-token/tests/add-token.test.js b/ui/app/pages/add-token/tests/add-token.test.js index fa9e4bd193a1..da4a42f20387 100644 --- a/ui/app/pages/add-token/tests/add-token.test.js +++ b/ui/app/pages/add-token/tests/add-token.test.js @@ -19,7 +19,7 @@ describe('Add Token', function () { const props = { history: { - push: sinon.stub().callsFake(() => {}), + push: sinon.stub().callsFake(() => undefined), }, setPendingTokens: sinon.spy(), clearPendingTokens: sinon.spy(), diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js index a9ac7b66cc3b..dfc0457786c0 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js @@ -23,7 +23,7 @@ describe('Reveal Seed Phrase', function () { , { context: { t: (str) => str, - metricsEvent: () => {}, + metricsEvent: () => undefined, }, }, ) diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js index 0b964dfca197..008bcec30366 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js @@ -13,7 +13,7 @@ describe('AmountMaxButton Component', function () { setMaxModeTo: sinon.spy(), } - const MOCK_EVENT = { preventDefault: () => {} } + const MOCK_EVENT = { preventDefault: () => undefined } before(function () { sinon.spy(AmountMaxButton.prototype, 'setMaxAmount') @@ -33,7 +33,7 @@ describe('AmountMaxButton Component', function () { ), { context: { t: (str) => str + '_t', - metricsEvent: () => {}, + metricsEvent: () => undefined, }, }) instance = wrapper.instance() diff --git a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js index 4f99b8909c34..b22819f258dc 100644 --- a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js @@ -158,7 +158,7 @@ function shallowRenderSendAmountRow () { updateGasFeeError={updateGasFeeError} updateSendAmount={updateSendAmount} updateSendAmountError={updateSendAmountError} - updateGas={() => {}} + updateGas={() => undefined} /> ), { context: { t: (str) => str + '_t' } }) const instance = wrapper.instance() diff --git a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js index d200e2dd71a3..ba2c8c1e556f 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js @@ -18,7 +18,7 @@ describe('SendFooter Component', function () { const historySpies = { push: sinon.spy(), } - const MOCK_EVENT = { preventDefault: () => {} } + const MOCK_EVENT = { preventDefault: () => undefined } before(function () { sinon.spy(SendFooter.prototype, 'onCancel') diff --git a/ui/app/pages/send/tests/send-component.test.js b/ui/app/pages/send/tests/send-component.test.js index 757b8fa636a5..43c296009f2e 100644 --- a/ui/app/pages/send/tests/send-component.test.js +++ b/ui/app/pages/send/tests/send-component.test.js @@ -63,12 +63,12 @@ describe('Send Component', function () { tokenBalance="mockTokenBalance" tokenContract={{ method: 'mockTokenMethod' }} updateAndSetGasLimit={propsMethodSpies.updateAndSetGasLimit} - qrCodeDetected={() => {}} - scanQrCode={() => {}} - updateSendEnsResolution={() => {}} - updateSendEnsResolutionError={() => {}} + qrCodeDetected={() => undefined} + scanQrCode={() => undefined} + updateSendEnsResolution={() => undefined} + updateSendEnsResolutionError={() => undefined} updateSendErrors={propsMethodSpies.updateSendErrors} - updateSendTo={() => {}} + updateSendTo={() => undefined} updateSendTokenBalance={propsMethodSpies.updateSendTokenBalance} resetSendState={propsMethodSpies.resetSendState} updateToNicknameIfNecessary={propsMethodSpies.updateToNicknameIfNecessary} diff --git a/ui/app/pages/send/tests/send-container.test.js b/ui/app/pages/send/tests/send-container.test.js index 84a138d92b23..ae9cfd2d4251 100644 --- a/ui/app/pages/send/tests/send-container.test.js +++ b/ui/app/pages/send/tests/send-container.test.js @@ -21,7 +21,7 @@ proxyquire('../send.container.js', { return () => ({}) }, }, - 'react-router-dom': { withRouter: () => {} }, + 'react-router-dom': { withRouter: () => undefined }, 'redux': { compose: (_, arg2) => () => arg2() }, '../../store/actions': actionSpies, '../../ducks/send/send.duck': duckActionSpies, diff --git a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js index 69fe064c8588..cd8e9a200ab4 100644 --- a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js +++ b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js @@ -10,10 +10,10 @@ describe('AdvancedTab Component', function () { const root = shallow( {}} - setIpfsGateway={() => {}} - setShowFiatConversionOnTestnetsPreference={() => {}} - setThreeBoxSyncingPermission={() => {}} + setAutoLockTimeLimit={() => undefined} + setIpfsGateway={() => undefined} + setShowFiatConversionOnTestnetsPreference={() => undefined} + setThreeBoxSyncingPermission={() => undefined} threeBoxDisabled threeBoxSyncingAllowed={false} />, @@ -33,9 +33,9 @@ describe('AdvancedTab Component', function () { {}} - setShowFiatConversionOnTestnetsPreference={() => {}} - setThreeBoxSyncingPermission={() => {}} + setIpfsGateway={() => undefined} + setShowFiatConversionOnTestnetsPreference={() => undefined} + setThreeBoxSyncingPermission={() => undefined} threeBoxDisabled threeBoxSyncingAllowed={false} />, diff --git a/ui/app/pages/settings/security-tab/tests/security-tab.test.js b/ui/app/pages/settings/security-tab/tests/security-tab.test.js index 1ac996d050dd..d5720aa6a0e2 100644 --- a/ui/app/pages/settings/security-tab/tests/security-tab.test.js +++ b/ui/app/pages/settings/security-tab/tests/security-tab.test.js @@ -28,7 +28,7 @@ describe('Security Tab', function () { , { context: { t: (str) => str, - metricsEvent: () => {}, + metricsEvent: () => undefined, }, }, ) From 884775cf710fe4f9e001d54b00249d7ac9e8b0d6 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 14 Aug 2020 09:17:43 -0230 Subject: [PATCH 096/137] Fix no-negated-condition issues (#9222) See [`no-negated-condition`](https://eslint.org/docs/rules/no-negated-condition) for more information. This change enables `no-negated-condition` and fixes the issues raised by the rule. --- .eslintrc.js | 1 + app/scripts/controllers/transactions/index.js | 6 +-- .../transactions/tx-state-manager.js | 2 +- app/scripts/lib/freezeGlobals.js | 6 +-- app/scripts/lib/util.js | 14 ++--- app/scripts/metamask-controller.js | 19 +++---- development/metamaskbot-build-announce.js | 8 +-- development/sentry-publish.js | 10 ++-- test/unit/app/nodeify-test.js | 5 +- ...confirm-page-container-header.component.js | 34 ++++++------- .../connected-accounts-list.component.js | 6 +-- .../advanced-tab-content.component.js | 6 +-- .../basic-tab-content.component.js | 6 +-- .../gas-price-button-group.component.js | 8 +-- .../app/info-box/info-box.component.js | 10 ++-- .../components/app/modal/modal.component.js | 51 ++++++++++--------- .../edit-approval-permission.component.js | 2 +- .../modals/qr-scanner/qr-scanner.component.js | 8 +-- .../transaction-breakdown.component.js | 19 +++---- .../transaction-list-item.component.js | 16 +++--- ui/app/ducks/gas/gas.duck.js | 49 +++++++++--------- ui/app/helpers/utils/metametrics.util.js | 22 ++++---- ui/app/hooks/tests/useTokenData.test.js | 6 +-- .../confirm-decrypt-message.component.js | 8 +-- .../metametrics-opt-in.component.js | 4 +- .../onboarding-initiator-util.js | 6 +-- .../confirm-seed-phrase.component.js | 6 +-- .../seed-phrase/seed-phrase.component.js | 6 +-- .../mobile-sync/mobile-sync.component.js | 12 ++--- .../permissions-connect.component.js | 16 +++--- ui/app/pages/routes/routes.component.js | 8 +-- .../add-recipient/ens-input.component.js | 2 +- .../amount-max-button.component.js | 8 +-- ui/app/pages/send/send.container.js | 6 +-- ui/app/selectors/permissions.js | 6 +-- 35 files changed, 204 insertions(+), 198 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 94ddd7bef3c3..c7997bce97ed 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -57,6 +57,7 @@ module.exports = { 'no-eq-null': 'error', 'no-global-assign': 'error', 'no-loop-func': 'error', + 'no-negated-condition': 'error', 'no-nested-ternary': 'error', 'no-plusplus': ['error', { 'allowForLoopAfterthoughts': true }], 'no-process-exit': 'error', diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 24c5a1edb036..795c7c6ea20a 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -560,9 +560,9 @@ export default class TransactionController extends EventEmitter { // It seems that sometimes the numerical values being returned from // this.query.getTransactionReceipt are BN instances and not strings. - const gasUsed = typeof txReceipt.gasUsed !== 'string' - ? txReceipt.gasUsed.toString(16) - : txReceipt.gasUsed + const gasUsed = typeof txReceipt.gasUsed === 'string' + ? txReceipt.gasUsed + : txReceipt.gasUsed.toString(16) txMeta.txReceipt = { ...txReceipt, diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index d064c4d7795f..7de54fb9cad8 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -424,7 +424,7 @@ export default class TransactionStateManager extends EventEmitter { @param {erroObject} err - error object */ setTxStatusFailed (txId, err) { - const error = !err ? new Error('Internal metamask failure') : err + const error = err || new Error('Internal metamask failure') const txMeta = this.getTx(txId) txMeta.err = { diff --git a/app/scripts/lib/freezeGlobals.js b/app/scripts/lib/freezeGlobals.js index 6599088d68de..b17a84781523 100644 --- a/app/scripts/lib/freezeGlobals.js +++ b/app/scripts/lib/freezeGlobals.js @@ -30,11 +30,11 @@ function freeze (target, key, value, enumerable = true) { configurable: false, writable: false, } - if (value !== undefined) { + if (value === undefined) { + target[key] = deepFreeze(target[key]) + } else { opts.value = deepFreeze(value) opts.enumerable = enumerable - } else { - target[key] = deepFreeze(target[key]) } Object.defineProperty(target, key, opts) diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index e52058a86201..ab8653669170 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -55,19 +55,19 @@ const getEnvironmentType = (url = window.location.href) => getEnvironmentTypeMem */ const getPlatform = (_) => { const ua = window.navigator.userAgent - if (ua.search('Firefox') !== -1) { - return PLATFORM_FIREFOX - } else { + if (ua.search('Firefox') === -1) { if (window && window.chrome && window.chrome.ipcRenderer) { return PLATFORM_BRAVE - } else if (ua.search('Edge') !== -1) { + } + if (ua.search('Edge') !== -1) { return PLATFORM_EDGE - } else if (ua.search('OPR') !== -1) { + } + if (ua.search('OPR') !== -1) { return PLATFORM_OPERA - } else { - return PLATFORM_CHROME } + return PLATFORM_CHROME } + return PLATFORM_FIREFOX } /** diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index dcf5524343fa..1e4af85b1678 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -710,15 +710,16 @@ export default class MetamaskController extends EventEmitter { Object.keys(accountTokens).forEach((address) => { const checksummedAddress = ethUtil.toChecksumAddress(address) filteredAccountTokens[checksummedAddress] = {} - Object.keys(accountTokens[address]).forEach( - (networkType) => (filteredAccountTokens[checksummedAddress][networkType] = networkType !== 'mainnet' ? - accountTokens[address][networkType] : - accountTokens[address][networkType].filter(({ address }) => { - const tokenAddress = ethUtil.toChecksumAddress(address) - return contractMap[tokenAddress] ? contractMap[tokenAddress].erc20 : true - }) - ), - ) + Object.keys(accountTokens[address]).forEach((networkType) => { + filteredAccountTokens[checksummedAddress][networkType] = networkType === 'mainnet' + ? ( + accountTokens[address][networkType].filter(({ address }) => { + const tokenAddress = ethUtil.toChecksumAddress(address) + return contractMap[tokenAddress] ? contractMap[tokenAddress].erc20 : true + }) + ) + : accountTokens[address][networkType] + }) }) const preferences = { diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index 788929fb3070..2414901dedc5 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -81,10 +81,7 @@ async function start () { const summaryPlatform = 'chrome' const summaryPage = 'home' let commentBody - if (!benchmarkResults[summaryPlatform]) { - console.log(`No results for ${summaryPlatform} found; skipping benchmark`) - commentBody = artifactsBody - } else { + if (benchmarkResults[summaryPlatform]) { try { const summaryPageLoad = Math.round(parseFloat(benchmarkResults[summaryPlatform][summaryPage].average.load)) const summaryPageLoadMarginOfError = Math.round(parseFloat(benchmarkResults[summaryPlatform][summaryPage].marginOfError.load)) @@ -147,6 +144,9 @@ async function start () { console.error(`Error constructing benchmark results: '${error}'`) commentBody = artifactsBody } + } else { + console.log(`No results for ${summaryPlatform} found; skipping benchmark`) + commentBody = artifactsBody } const JSON_PAYLOAD = JSON.stringify({ body: commentBody }) diff --git a/development/sentry-publish.js b/development/sentry-publish.js index 81034374e50e..650ac37fdf75 100644 --- a/development/sentry-publish.js +++ b/development/sentry-publish.js @@ -25,12 +25,14 @@ async function start () { // check if version has artifacts or not const versionHasArtifacts = versionAlreadyExists && await checkIfVersionHasArtifacts() - if (!versionHasArtifacts) { - // upload sentry source and sourcemaps - await exec(`./development/sentry-upload-artifacts.sh --release ${VERSION}`) - } else { + if (versionHasArtifacts) { console.log(`Version "${VERSION}" already has artifacts on Sentry, skipping sourcemap upload`) + return } + + // upload sentry source and sourcemaps + await exec(`./development/sentry-upload-artifacts.sh --release ${VERSION}`) + } async function checkIfAuthWorks () { diff --git a/test/unit/app/nodeify-test.js b/test/unit/app/nodeify-test.js index 4008309149d3..c8d1c46d90f7 100644 --- a/test/unit/app/nodeify-test.js +++ b/test/unit/app/nodeify-test.js @@ -16,9 +16,10 @@ describe('nodeify', function () { if (!err) { assert.equal(res, 'barbaz') done() - } else { - done(new Error(err.toString())) + return } + + done(new Error(err.toString())) }) }) diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js index f1f10a797eb5..c72600274a09 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js @@ -30,8 +30,22 @@ export default function ConfirmPageContainerHeader ({ return (
- { !showAccountInHeader + { showAccountInHeader ? ( +
+
+ +
+
+ { shortenAddress(accountAddress) } +
+ +
+ ) + : (
) - : null - } - { showAccountInHeader - ? ( -
-
- -
-
- { shortenAddress(accountAddress) } -
- -
- ) - : null } { !isFullScreen && }
diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js b/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js index 567af6b72b06..5509e9cd4751 100644 --- a/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js +++ b/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js @@ -149,9 +149,9 @@ export default class ConnectedAccountsList extends PureComponent { : null } action={ - address !== selectedAddress - ? this.renderListItemAction(address) - : null + address === selectedAddress + ? null + : this.renderListItemAction(address) } /> ) diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js index 19e3aa776432..91c36f0a4171 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js @@ -86,9 +86,9 @@ export default class AdvancedTabContent extends Component { ? (
{ t('liveGasPricePredictions') }
- {!gasEstimatesLoading - ? - : + {gasEstimatesLoading + ? + : }
{ t('slower') } diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js index 94d22ee4a100..5a80e4c9820b 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js @@ -20,15 +20,15 @@ export default class BasicTabContent extends Component {
{ t('estimatedProcessingTimes') }
{ t('selectAHigherGasFee') }
- {!gasPriceButtonGroupProps.loading - ? ( + {gasPriceButtonGroupProps.loading + ? + : ( ) - : }
{ t('acceleratingATransaction') }
diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js b/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js index b578ff1ed46a..8916c7e8e563 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js +++ b/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js @@ -89,18 +89,18 @@ export default class GasPriceButtonGroup extends Component { } = this.props return ( - !buttonDataLoading - ? ( + buttonDataLoading + ?
{this.context.t('loading')}
+ : ( - { gasButtonInfo.map((obj, index) => this.renderButton(obj, buttonPropsAndFlags, index)) } + {gasButtonInfo.map((obj, index) => this.renderButton(obj, buttonPropsAndFlags, index))} ) - :
{ this.context.t('loading') }
) } } diff --git a/ui/app/components/app/info-box/info-box.component.js b/ui/app/components/app/info-box/info-box.component.js index 68aae5d11ba3..163869ef5245 100644 --- a/ui/app/components/app/info-box/info-box.component.js +++ b/ui/app/components/app/info-box/info-box.component.js @@ -29,17 +29,17 @@ export default class InfoBox extends Component { render () { const { title, description } = this.props - return !this.state.isShowing - ? null - : ( + return this.state.isShowing + ? (
this.handleClose()} /> -
{ title }
-
{ description }
+
{title}
+
{description}
) + : null } } diff --git a/ui/app/components/app/modal/modal.component.js b/ui/app/components/app/modal/modal.component.js index 6c45160fdc63..41e4ea694486 100644 --- a/ui/app/components/app/modal/modal.component.js +++ b/ui/app/components/app/modal/modal.component.js @@ -63,31 +63,32 @@ export default class Modal extends PureComponent {
{ children }
- { !hideFooter - ? ( -
- { - onCancel && ( - - ) - } - -
- ) - : null + { + hideFooter + ? null + : ( +
+ { + onCancel && ( + + ) + } + +
+ ) }
) diff --git a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js index 9e1dafced8d4..fca21145a65c 100644 --- a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js +++ b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js @@ -204,7 +204,7 @@ export default class EditApprovalPermission extends PureComponent { return ( { - setCustomAmount(!selectedOptionIsUnlimited ? customSpendLimit : '') + setCustomAmount(selectedOptionIsUnlimited ? '' : customSpendLimit) hideModal() }} submitText={t('save')} diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js index 63ca45b88932..fd79c9e41e4a 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js @@ -117,11 +117,11 @@ export default class QrScanner extends Component { const result = this.parseContent(content.text) if (!this.mounted) { return - } else if (result.type !== 'unknown') { + } else if (result.type === 'unknown') { + this.setState({ error: new Error(this.context.t('unknownQrCode')) }) + } else { this.props.qrCodeDetected(result) this.stopAndClose() - } else { - this.setState({ error: new Error(this.context.t('unknownQrCode')) }) } } catch (error) { if (!this.mounted) { @@ -248,7 +248,7 @@ export default class QrScanner extends Component { display: ready === READY_STATE.READY ? 'block' : 'none', }} /> - { ready !== READY_STATE.READY ? : null} + {ready === READY_STATE.READY ? null : }
diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js index 85c24a3e3acc..a534ae1a6fcd 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js @@ -37,13 +37,14 @@ export default class TransactionBreakdown extends PureComponent { { t('transaction') }
- {typeof nonce !== 'undefined' - ? ( + {typeof nonce === 'undefined' + ? null + : ( - ) : null + ) } @@ -57,14 +58,14 @@ export default class TransactionBreakdown extends PureComponent { title={`${t('gasLimit')} (${t('units')})`} className="transaction-breakdown__row-title" > - {typeof gas !== 'undefined' - ? ( + {typeof gas === 'undefined' + ? '?' + : ( ) - : '?' } { @@ -81,8 +82,9 @@ export default class TransactionBreakdown extends PureComponent { ) } - {typeof gasPrice !== 'undefined' - ? ( + {typeof gasPrice === 'undefined' + ? '?' + : ( ) - : '?' } diff --git a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js index bd6a61c913b8..c2c1279eb7b0 100644 --- a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js +++ b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js @@ -86,13 +86,15 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce return null } - return !cancelEnabled ? ( - -
- {cancelButton} -
-
- ) : cancelButton + return cancelEnabled + ? cancelButton + : ( + +
+ {cancelButton} +
+
+ ) }, [isPending, t, isUnapproved, cancelEnabled, cancelTransaction, hasCancelled]) diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/app/ducks/gas/gas.duck.js index c1d7336e3578..78b9ef8baa2f 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/app/ducks/gas/gas.duck.js @@ -399,29 +399,28 @@ export function fetchGasEstimates (blockTime) { const next = arr[i + 1] if (!next) { return [{ expectedWait, gasprice }] - } else { - const supplementalPrice = getRandomArbitrary(gasprice, next.gasprice) - const supplementalTime = extrapolateY({ - higherY: next.expectedWait, - lowerY: expectedWait, - higherX: next.gasprice, - lowerX: gasprice, - xForExtrapolation: supplementalPrice, - }) - const supplementalPrice2 = getRandomArbitrary(supplementalPrice, next.gasprice) - const supplementalTime2 = extrapolateY({ - higherY: next.expectedWait, - lowerY: supplementalTime, - higherX: next.gasprice, - lowerX: supplementalPrice, - xForExtrapolation: supplementalPrice2, - }) - return [ - { expectedWait, gasprice }, - { expectedWait: supplementalTime, gasprice: supplementalPrice }, - { expectedWait: supplementalTime2, gasprice: supplementalPrice2 }, - ] } + const supplementalPrice = getRandomArbitrary(gasprice, next.gasprice) + const supplementalTime = extrapolateY({ + higherY: next.expectedWait, + lowerY: expectedWait, + higherX: next.gasprice, + lowerX: gasprice, + xForExtrapolation: supplementalPrice, + }) + const supplementalPrice2 = getRandomArbitrary(supplementalPrice, next.gasprice) + const supplementalTime2 = extrapolateY({ + higherY: next.expectedWait, + lowerY: supplementalTime, + higherX: next.gasprice, + lowerX: supplementalPrice, + xForExtrapolation: supplementalPrice2, + }) + return [ + { expectedWait, gasprice }, + { expectedWait: supplementalTime, gasprice: supplementalPrice }, + { expectedWait: supplementalTime2, gasprice: supplementalPrice2 }, + ] })) const withOutliersRemoved = inliersByIQR(withSupplementalTimeEstimates.slice(0).reverse(), 'expectedWait').reverse() const timeMappedToSeconds = withOutliersRemoved.map(({ expectedWait, gasprice }) => { @@ -453,11 +452,11 @@ export function fetchGasEstimates (blockTime) { export function setCustomGasPriceForRetry (newPrice) { return (dispatch) => { - if (newPrice !== '0x0') { - dispatch(setCustomGasPrice(newPrice)) - } else { + if (newPrice === '0x0') { const { fast } = loadLocalStorageData('BASIC_PRICE_ESTIMATES') dispatch(setCustomGasPrice(decGWEIToHexWEI(fast))) + } else { + dispatch(setCustomGasPrice(newPrice)) } } } diff --git a/ui/app/helpers/utils/metametrics.util.js b/ui/app/helpers/utils/metametrics.util.js index f9e56bcbf02c..ce76b8385cde 100644 --- a/ui/app/helpers/utils/metametrics.util.js +++ b/ui/app/helpers/utils/metametrics.util.js @@ -157,15 +157,19 @@ function composeUrl (config) { const urlref = previousPath && composeUrlRefParamAddition(previousPath, confirmTransactionOrigin) - const dimensions = !pageOpts.hideDimensions ? composeCustomDimensionParamAddition({ - network, - environmentType, - activeCurrency, - accountType, - version, - numberOfTokens: (customVariables && customVariables.numberOfTokens) || numberOfTokens, - numberOfAccounts: (customVariables && customVariables.numberOfAccounts) || numberOfAccounts, - }) : '' + const dimensions = pageOpts.hideDimensions + ? '' + : ( + composeCustomDimensionParamAddition({ + network, + environmentType, + activeCurrency, + accountType, + version, + numberOfTokens: (customVariables && customVariables.numberOfTokens) || numberOfTokens, + numberOfAccounts: (customVariables && customVariables.numberOfAccounts) || numberOfAccounts, + }) + ) const url = currentPath ? `&url=${encodeURIComponent(`${METAMETRICS_TRACKING_URL}${currentPath}`)}` : '' const _id = metaMetricsId && !excludeMetaMetricsId ? `&_id=${metaMetricsId.slice(2, 18)}` : '' const rand = `&rand=${String(Math.random()).slice(2)}` diff --git a/ui/app/hooks/tests/useTokenData.test.js b/ui/app/hooks/tests/useTokenData.test.js index 9bc507de4053..7154581c65b0 100644 --- a/ui/app/hooks/tests/useTokenData.test.js +++ b/ui/app/hooks/tests/useTokenData.test.js @@ -65,9 +65,9 @@ const tests = [ describe('useTokenData', function () { tests.forEach((test) => { - const testTitle = test.tokenData !== null - ? `should return properly decoded data with _value ${test.tokenData.params[1].value}` - : `should return null when no data provided` + const testTitle = test.tokenData === null + ? `should return null when no data provided` + : `should return properly decoded data with _value ${test.tokenData.params[1].value}` it(testTitle, function () { const { result } = renderHook(() => useTokenData(test.data)) assert.deepEqual(result.current, test.tokenData) diff --git a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js index a054eb2b33b5..6b3c0adaebb7 100644 --- a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js +++ b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js @@ -220,7 +220,7 @@ export default class ConfirmDecryptMessage extends Component { className="request-decrypt-message__message-text" > { !hasDecrypted && !hasError ? txData.msgParams.data : rawMessage } - { !hasError ? '' : errorMessage } + { hasError ? errorMessage : '' }
{ decryptMessageInline(txData, event).then((result) => { - if (!result.error) { - this.setState({ hasDecrypted: true, rawMessage: result.rawData }) - } else { + if (result.error) { this.setState({ hasError: true, errorMessage: this.context.t('decryptInlineError', [result.error]) }) + } else { + this.setState({ hasDecrypted: true, rawMessage: result.rawData }) } }) }} diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js b/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js index e5d622ef24a5..789de5372b66 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js @@ -88,7 +88,7 @@ export default class MetaMetricsOptIn extends Component { onCancel={() => { setParticipateInMetaMetrics(false) .then(() => { - const promise = participateInMetaMetrics !== false + const promise = participateInMetaMetrics === true ? metricsEvent({ eventOpts: { category: 'Onboarding', @@ -110,7 +110,7 @@ export default class MetaMetricsOptIn extends Component { onSubmit={() => { setParticipateInMetaMetrics(true) .then(([_, metaMetricsId]) => { - const promise = participateInMetaMetrics !== true + const promise = participateInMetaMetrics === false ? metricsEvent({ eventOpts: { category: 'Onboarding', diff --git a/ui/app/pages/first-time-flow/onboarding-initiator-util.js b/ui/app/pages/first-time-flow/onboarding-initiator-util.js index 7653f78526c9..a7848bdbe335 100644 --- a/ui/app/pages/first-time-flow/onboarding-initiator-util.js +++ b/ui/app/pages/first-time-flow/onboarding-initiator-util.js @@ -16,12 +16,12 @@ const returnToOnboardingInitiatorTab = async (onboardingInitiator) => { }) })) - if (!tab) { + if (tab) { + window.close() + } else { // this case can happen if the tab was closed since being checked with `extension.tabs.get` log.warn(`Setting current tab to onboarding initiator has failed; falling back to redirect`) window.location.assign(onboardingInitiator.location) - } else { - window.close() } } diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index 8847a0d01f14..8cc34e2af741 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -173,10 +173,10 @@ export default class ConfirmSeedPhrase extends PureComponent { className="confirm-seed-phrase__seed-word--sorted" selected={isSelected} onClick={() => { - if (!isSelected) { - this.handleSelectSeedWord(index) - } else { + if (isSelected) { this.handleDeselectSeedWord(index) + } else { + this.handleSelectSeedWord(index) } }} word={word} diff --git a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js index 67eccb34cce0..ade1904c4993 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js @@ -30,10 +30,10 @@ export default class SeedPhrase extends PureComponent { if (!seedPhrase) { verifySeedPhrase() .then((verifiedSeedPhrase) => { - if (!verifiedSeedPhrase) { - history.push(DEFAULT_ROUTE) - } else { + if (verifiedSeedPhrase) { this.setState({ verifiedSeedPhrase }) + } else { + history.push(DEFAULT_ROUTE) } }) } diff --git a/ui/app/pages/mobile-sync/mobile-sync.component.js b/ui/app/pages/mobile-sync/mobile-sync.component.js index 1bd69b9cbf6c..51ad3e6b72bc 100644 --- a/ui/app/pages/mobile-sync/mobile-sync.component.js +++ b/ui/app/pages/mobile-sync/mobile-sync.component.js @@ -194,10 +194,10 @@ export default class MobileSyncPage extends Component { storeInHistory: false, }, (status, response) => { - if (!status.error) { - resolve() - } else { + if (status.error) { reject(response) + } else { + resolve() } }) }) @@ -253,10 +253,10 @@ export default class MobileSyncPage extends Component { storeInHistory: false, }, (status, response) => { - if (!status.error) { - resolve() - } else { + if (status.error) { reject(response) + } else { + resolve() } }, ) diff --git a/ui/app/pages/permissions-connect/permissions-connect.component.js b/ui/app/pages/permissions-connect/permissions-connect.component.js index abb5709d5354..207ce8c592d8 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.component.js +++ b/ui/app/pages/permissions-connect/permissions-connect.component.js @@ -162,26 +162,24 @@ export default class PermissionConnect extends Component { const { redirecting } = this.state const { page } = this.props const { t } = this.context - return !redirecting - ? ( -
- { page === '2' + return redirecting + ? null + : ( +
+ {page === '2' ? (
this.goBack()}> - { t('back') } + {t('back')}
) : null }
- { t('xOfY', [ page, '2' ]) } + {t('xOfY', [page, '2'])}
) - : null } render () { diff --git a/ui/app/pages/routes/routes.component.js b/ui/app/pages/routes/routes.component.js index 578483425c34..88b8321e90c2 100644 --- a/ui/app/pages/routes/routes.component.js +++ b/ui/app/pages/routes/routes.component.js @@ -265,16 +265,16 @@ export default class Routes extends Component { } toggleMetamaskActive () { - if (!this.props.isUnlocked) { + if (this.props.isUnlocked) { + // currently active: deactivate + this.props.lockMetaMask() + } else { // currently inactive: redirect to password box const passwordBox = document.querySelector('input[type=password]') if (!passwordBox) { return } passwordBox.focus() - } else { - // currently active: deactivate - this.props.lockMetaMask() } } diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js index d25243a15945..df8bf87a2774 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js @@ -122,7 +122,7 @@ export default class EnsInput extends Component { if (!networkHasEnsSupport && !isValidAddress(input) && !isValidAddressHead(input)) { updateEnsResolution('') - updateEnsResolutionError(!networkHasEnsSupport ? 'Network does not support ENS' : '') + updateEnsResolutionError(networkHasEnsSupport ? '' : 'Network does not support ENS') return } diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js index 59fcea36789a..adab9856e20b 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js @@ -51,12 +51,12 @@ export default class AmountMaxButton extends Component { name: 'Clicked "Amount Max"', }, }) - if (!maxModeOn) { - setMaxModeTo(true) - this.setMaxAmount() - } else { + if (maxModeOn) { setMaxModeTo(false) clearMaxAmount() + } else { + setMaxModeTo(true) + this.setMaxAmount() } } diff --git a/ui/app/pages/send/send.container.js b/ui/app/pages/send/send.container.js index 9698255be9ee..ca58a3e7db90 100644 --- a/ui/app/pages/send/send.container.js +++ b/ui/app/pages/send/send.container.js @@ -90,9 +90,9 @@ function mapDispatchToProps (dispatch) { value, data, }) => { - !editingTransactionId - ? dispatch(updateGasData({ gasPrice, selectedAddress, sendToken, blockGasLimit, to, value, data })) - : dispatch(setGasTotal(calcGasTotal(gasLimit, gasPrice))) + editingTransactionId + ? dispatch(setGasTotal(calcGasTotal(gasLimit, gasPrice))) + : dispatch(updateGasData({ gasPrice, selectedAddress, sendToken, blockGasLimit, to, value, data })) }, updateSendTokenBalance: ({ sendToken, tokenContract, address }) => { dispatch(updateSendTokenBalance({ diff --git a/ui/app/selectors/permissions.js b/ui/app/selectors/permissions.js index d4208115390a..47d7857da53d 100644 --- a/ui/app/selectors/permissions.js +++ b/ui/app/selectors/permissions.js @@ -261,10 +261,10 @@ export function getPermissionsMetadataHostCounts (state) { const metadata = getPermissionDomainsMetadata(state) return Object.values(metadata).reduce((counts, { host }) => { if (host) { - if (!counts[host]) { - counts[host] = 1 - } else { + if (counts[host]) { counts[host] += 1 + } else { + counts[host] = 1 } } return counts From 5d42a9b7732eba86bc4e16b98a3e386f95b2e952 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 14 Aug 2020 09:18:42 -0230 Subject: [PATCH 097/137] Fix require-unicode-regexp issues (#9212) * Fix require-unicode-regexp issues See [`require-unicode-regexp`](https://eslint.org/docs/rules/require-unicode-regexp) for more information. This change enables `require-unicode-regexp` and fixes the issues raised by the rule. * Remove case-insensitive flag from regexps --- .eslintrc.js | 1 + app/scripts/contentscript.js | 6 +- app/scripts/controllers/threebox.js | 2 +- app/scripts/lib/decrypt-message-manager.js | 2 +- app/scripts/lib/personal-message-manager.js | 2 +- development/build/scripts.js | 4 +- development/static-server.js | 2 +- development/verify-locale-strings.js | 4 +- test/e2e/address-book.spec.js | 6 +- test/e2e/benchmark.js | 6 +- test/e2e/from-import-ui.spec.js | 2 +- test/e2e/incremental-security.spec.js | 6 +- test/e2e/metamask-responsive-ui.spec.js | 4 +- test/e2e/metamask-ui.spec.js | 66 +++++++++---------- test/e2e/send-edit.spec.js | 2 +- test/e2e/tests/localization.spec.js | 2 +- test/e2e/threebox.spec.js | 4 +- test/e2e/webdriver/index.js | 2 +- .../app/controllers/detect-tokens-test.js | 2 +- .../controllers/metamask-controller-test.js | 4 +- test/unit/migrations/migrator-test.js | 4 +- .../app/menu-bar/account-options-menu.js | 2 +- .../account-details-modal.component.js | 2 +- .../ui/unit-input/unit-input.component.js | 2 +- ui/app/contexts/metametrics.js | 2 +- .../confirm-transaction.duck.test.js | 2 +- ui/app/ducks/gas/gas-duck.test.js | 2 +- ui/app/helpers/utils/common.util.js | 4 +- ui/app/helpers/utils/i18n-helper.js | 4 +- ui/app/helpers/utils/transactions.util.js | 2 +- ui/app/helpers/utils/util.js | 8 +-- ui/app/helpers/utils/util.test.js | 2 +- .../confirm-transaction-base.component.js | 6 +- .../confirm-transaction-switch.container.js | 2 +- .../tests/add-recipient-utils.test.js | 2 +- .../send-hex-data-row.component.js | 2 +- ui/app/pages/send/send.utils.js | 2 +- ui/app/pages/send/tests/send-utils.test.js | 10 +-- .../advanced-tab/advanced-tab.component.js | 2 +- .../contact-list-tab.container.js | 2 +- .../edit-contact/edit-contact.container.js | 2 +- .../view-contact/view-contact.component.js | 2 +- .../view-contact/view-contact.container.js | 2 +- .../network-form/network-form.component.js | 2 +- ui/app/pages/settings/settings.container.js | 2 +- ui/lib/account-link.js | 2 +- 46 files changed, 103 insertions(+), 102 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index c7997bce97ed..2e74bd47614c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -67,6 +67,7 @@ module.exports = { 'no-useless-concat': 'error', 'prefer-rest-params': 'error', 'prefer-spread': 'error', + 'require-unicode-regexp': 'error', /* End v2 rules */ 'arrow-parens': 'error', 'no-tabs': 'error', diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 57e95fa634b2..e7a983a693b2 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -155,8 +155,8 @@ function doctypeCheck () { */ function suffixCheck () { const prohibitedTypes = [ - /\.xml$/, - /\.pdf$/, + /\.xml$/u, + /\.pdf$/u, ] const currentUrl = window.location.pathname for (let i = 0; i < prohibitedTypes.length; i++) { @@ -202,7 +202,7 @@ function blockedDomainCheck () { let currentRegex for (let i = 0; i < blockedDomains.length; i++) { const blockedDomain = blockedDomains[i].replace('.', '\\.') - currentRegex = new RegExp(`(?:https?:\\/\\/)(?:(?!${blockedDomain}).)*$`) + currentRegex = new RegExp(`(?:https?:\\/\\/)(?:(?!${blockedDomain}).)*$`, 'u') if (!currentRegex.test(currentUrl)) { return true } diff --git a/app/scripts/controllers/threebox.js b/app/scripts/controllers/threebox.js index bca43d9f6536..726a14ffa358 100644 --- a/app/scripts/controllers/threebox.js +++ b/app/scripts/controllers/threebox.js @@ -123,7 +123,7 @@ export default class ThreeBoxController { const threeBoxConfig = await Box.getConfig(this.address) backupExists = threeBoxConfig.spaces && threeBoxConfig.spaces.metamask } catch (e) { - if (e.message.match(/^Error: Invalid response \(404\)/)) { + if (e.message.match(/^Error: Invalid response \(404\)/u)) { backupExists = false } else { throw e diff --git a/app/scripts/lib/decrypt-message-manager.js b/app/scripts/lib/decrypt-message-manager.js index 2a53c9fa2596..a379d656146b 100644 --- a/app/scripts/lib/decrypt-message-manager.js +++ b/app/scripts/lib/decrypt-message-manager.js @@ -5,7 +5,7 @@ import { ethErrors } from 'eth-json-rpc-errors' import createId from './random-id' import { MESSAGE_TYPE } from './enums' -const hexRe = /^[0-9A-Fa-f]+$/g +const hexRe = /^[0-9A-Fa-f]+$/ug import log from 'loglevel' /** diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 3cf7564baca1..647b7e58938c 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -5,7 +5,7 @@ import { ethErrors } from 'eth-json-rpc-errors' import createId from './random-id' import { MESSAGE_TYPE } from './enums' -const hexRe = /^[0-9A-Fa-f]+$/g +const hexRe = /^[0-9A-Fa-f]+$/ug import log from 'loglevel' /** diff --git a/development/build/scripts.js b/development/build/scripts.js index 6f206ee57705..0831dbf69829 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -25,7 +25,7 @@ module.exports = createScriptTasks const dependencies = Object.keys((packageJSON && packageJSON.dependencies) || {}) const materialUIDependencies = ['@material-ui/core'] -const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/)) +const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/u)) const d3Dependencies = ['c3', 'd3'] const externalDependenciesMap = { @@ -365,7 +365,7 @@ function getEnvironment ({ devMode, test }) { return 'testing' } else if (process.env.CIRCLE_BRANCH === 'master') { return 'production' - } else if (/^Version-v(\d+)[.](\d+)[.](\d+)/.test(process.env.CIRCLE_BRANCH)) { + } else if (/^Version-v(\d+)[.](\d+)[.](\d+)/u.test(process.env.CIRCLE_BRANCH)) { return 'release-candidate' } else if (process.env.CIRCLE_BRANCH === 'develop') { return 'staging' diff --git a/development/static-server.js b/development/static-server.js index fff4103c460f..368c186e92a6 100644 --- a/development/static-server.js +++ b/development/static-server.js @@ -61,7 +61,7 @@ const main = async () => { } while (args.length) { - if (/^(--port|-p)$/i.test(args[0])) { + if (/^(--port|-p)$/u.test(args[0])) { if (args[1] === undefined) { throw new Error('Missing port argument') } diff --git a/development/verify-locale-strings.js b/development/verify-locale-strings.js index cef27f6a0aec..3b9e72bf30bd 100644 --- a/development/verify-locale-strings.js +++ b/development/verify-locale-strings.js @@ -169,11 +169,11 @@ async function verifyEnglishLocale (fix = false) { // match "t(`...`)" because constructing message keys from template strings // prevents this script from finding the messages, and then inappropriately // deletes them - const templateStringRegex = /\bt\(`.*`\)/g + const templateStringRegex = /\bt\(`.*`\)/ug const templateUsage = [] // match the keys from the locale file - const keyRegex = /'(\w+)'|"(\w+)"/g + const keyRegex = /'(\w+)'|"(\w+)"/ug const usedMessages = new Set() for await (const fileContents of getFileContents(javascriptFiles)) { for (const match of matchAll.call(fileContents, keyRegex)) { diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index f9fc7d5bea37..fdd0b6b28a32 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -152,7 +152,7 @@ describe('MetaMask', function () { it('balance renders', async function () { const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading')) - await driver.wait(until.elementTextMatches(balance, /25\s*ETH/)) + await driver.wait(until.elementTextMatches(balance, /25\s*ETH/u)) await driver.delay(regularDelayMs) }) }) @@ -202,7 +202,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) }) }) @@ -239,7 +239,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-2\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-2\s*ETH/u), 10000) }) }) }) diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index 39786abe93ec..f34436328204 100644 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -117,7 +117,7 @@ async function main () { let existingParentDirectory while (args.length) { - if (/^(--pages|-p)$/i.test(args[0])) { + if (/^(--pages|-p)$/u.test(args[0])) { if (args[1] === undefined) { throw new Error('Missing pages argument') } @@ -128,7 +128,7 @@ async function main () { } } args.splice(0, 2) - } else if (/^(--samples|-s)$/i.test(args[0])) { + } else if (/^(--samples|-s)$/u.test(args[0])) { if (args[1] === undefined) { throw new Error('Missing number of samples') } @@ -137,7 +137,7 @@ async function main () { throw new Error(`Invalid 'samples' argument given: '${args[1]}'`) } args.splice(0, 2) - } else if (/^(--out|-o)$/i.test(args[0])) { + } else if (/^(--out|-o)$/u.test(args[0])) { if (args[1] === undefined) { throw new Error('Missing output filename') } diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index 432432b3e579..b0eab48e498f 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -223,7 +223,7 @@ describe('Using MetaMask with an existing account', function () { const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) assert.equal(txValues.length, 1) - assert.ok(/-1\s*ETH/.test(await txValues[0].getText())) + assert.ok(/-1\s*ETH/u.test(await txValues[0].getText())) }) }) diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 7008ec69cb33..1e1a30349d36 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -127,7 +127,7 @@ describe('MetaMask', function () { await driver.clickElement(By.css('#send')) const txStatus = await driver.findElement(By.css('#success')) - await driver.wait(until.elementTextMatches(txStatus, /Success/), 15000) + await driver.wait(until.elementTextMatches(txStatus, /Success/u), 15000) }) it('switches back to MetaMask', async function () { @@ -136,7 +136,7 @@ describe('MetaMask', function () { it('should have the correct amount of eth', async function () { const balances = await driver.findElements(By.css('.currency-display-component__text')) - await driver.wait(until.elementTextMatches(balances[0], /1/), 15000) + await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000) const balance = await balances[0].getText() assert.equal(balance, '1') @@ -193,7 +193,7 @@ describe('MetaMask', function () { it('should have the correct amount of eth', async function () { const balances = await driver.findElements(By.css('.currency-display-component__text')) - await driver.wait(until.elementTextMatches(balances[0], /1/), 15000) + await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000) const balance = await balances[0].getText() assert.equal(balance, '1') diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index 0b7e8b4d4380..b2d8e9c5ec74 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -167,7 +167,7 @@ describe('MetaMask', function () { it('balance renders', async function () { const balance = await driver.findElement(By.css('[data-testid="eth-overview__primary-currency"]')) - await driver.wait(until.elementTextMatches(balance, /100\s*ETH/)) + await driver.wait(until.elementTextMatches(balance, /100\s*ETH/u)) await driver.delay(regularDelayMs) }) }) @@ -218,7 +218,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) }) }) }) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index dfff8e49bac1..bb13c0646eb2 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -208,7 +208,7 @@ describe('MetaMask', function () { it('balance renders', async function () { const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading')) - await driver.wait(until.elementTextMatches(balance, /100\s*ETH/)) + await driver.wait(until.elementTextMatches(balance, /100\s*ETH/u)) await driver.delay(regularDelayMs) }) }) @@ -273,7 +273,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) }) }) @@ -312,7 +312,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) }) }) @@ -360,7 +360,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) }) }) @@ -463,7 +463,7 @@ describe('MetaMask', function () { }, 10000) const txValue = await driver.findClickableElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValue, /-3\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValue, /-3\s*ETH/u), 10000) }) it('the transaction has the expected gas price', async function () { @@ -471,7 +471,7 @@ describe('MetaMask', function () { await txValue.click() const popoverCloseButton = await driver.findClickableElement(By.css('.popover-header__button')) const txGasPrice = await driver.findElement(By.css('[data-testid="transaction-breakdown__gas-price"]')) - await driver.wait(until.elementTextMatches(txGasPrice, /^10$/), 10000) + await driver.wait(until.elementTextMatches(txGasPrice, /^10$/u), 10000) await popoverCloseButton.click() }) }) @@ -654,7 +654,7 @@ describe('MetaMask', function () { }, 10000) const txAction = await driver.findElements(By.css('.list-item__heading')) - await driver.wait(until.elementTextMatches(txAction[0], /Contract\sDeployment/), 10000) + await driver.wait(until.elementTextMatches(txAction[0], /Contract\sDeployment/u), 10000) await driver.delay(regularDelayMs) }) @@ -663,20 +663,20 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) let contractStatus = await driver.findElement(By.css('#contractStatus')) - await driver.wait(until.elementTextMatches(contractStatus, /Deployed/), 15000) + await driver.wait(until.elementTextMatches(contractStatus, /Deployed/u), 15000) await driver.clickElement(By.css('#depositButton')) await driver.delay(largeDelayMs) contractStatus = await driver.findElement(By.css('#contractStatus')) - await driver.wait(until.elementTextMatches(contractStatus, /Deposit\sinitiated/), 10000) + await driver.wait(until.elementTextMatches(contractStatus, /Deposit\sinitiated/u), 10000) await driver.switchToWindow(extension) await driver.delay(largeDelayMs * 2) await driver.findElements(By.css('.transaction-list-item')) const txListValue = await driver.findClickableElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txListValue, /-4\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txListValue, /-4\s*ETH/u), 10000) await txListValue.click() await driver.delay(regularDelayMs) @@ -718,7 +718,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues[0], /-4\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues[0], /-4\s*ETH/u), 10000) }) it('calls and confirms a contract method where ETH is received', async function () { @@ -743,7 +743,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-0\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-0\s*ETH/u), 10000) await driver.closeAllWindowHandlesExcept([extension, dapp]) await driver.switchToWindow(extension) @@ -752,9 +752,9 @@ describe('MetaMask', function () { it('renders the correct ETH balance', async function () { const balance = await driver.findElement(By.css('[data-testid="eth-overview__primary-currency"]')) await driver.delay(regularDelayMs) - await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/), 10000) + await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/u), 10000) const tokenAmount = await balance.getText() - assert.ok(/^87.*\s*ETH.*$/.test(tokenAmount)) + assert.ok(/^87.*\s*ETH.*$/u.test(tokenAmount)) await driver.delay(regularDelayMs) }) }) @@ -797,7 +797,7 @@ describe('MetaMask', function () { await driver.delay(tinyDelayMs) const tokenContractAddress = await driver.findElement(By.css('#tokenAddress')) - await driver.wait(until.elementTextMatches(tokenContractAddress, /0x/)) + await driver.wait(until.elementTextMatches(tokenContractAddress, /0x/u)) tokenAddress = await tokenContractAddress.getText() await driver.delay(regularDelayMs) @@ -830,9 +830,9 @@ describe('MetaMask', function () { it('renders the balance for the new token', async function () { const balance = await driver.findElement(By.css('.wallet-overview .token-overview__primary-balance')) - await driver.wait(until.elementTextMatches(balance, /^10\s*TST\s*$/)) + await driver.wait(until.elementTextMatches(balance, /^10\s*TST\s*$/u)) const tokenAmount = await balance.getText() - assert.ok(/^10\s*TST\s*$/.test(tokenAmount)) + assert.ok(/^10\s*TST\s*$/u.test(tokenAmount)) await driver.delay(regularDelayMs) }) }) @@ -887,7 +887,7 @@ describe('MetaMask', function () { const confirmDataText = await confirmDataDiv.getText() await driver.delay(regularDelayMs) - assert(confirmDataText.match(/0xa9059cbb0000000000000000000000002f318c334780961fb129d2a6c30d0763d9a5c97/)) + assert(confirmDataText.match(/0xa9059cbb0000000000000000000000002f318c334780961fb129d2a6c30d0763d9a5c97/u)) await driver.clickElement(By.xpath(`//li[contains(text(), 'Details')]`)) await driver.delay(regularDelayMs) @@ -906,10 +906,10 @@ describe('MetaMask', function () { const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) assert.equal(txValues.length, 1) - await driver.wait(until.elementTextMatches(txValues[0], /-1\s*TST/), 10000) + await driver.wait(until.elementTextMatches(txValues[0], /-1\s*TST/u), 10000) const txStatuses = await driver.findElements(By.css('.list-item__heading')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Send\sTST/i), 10000) + await driver.wait(until.elementTextMatches(txStatuses[0], /Send\sTST/u), 10000) }) }) @@ -931,7 +931,7 @@ describe('MetaMask', function () { await driver.findElements(By.css('.transaction-list__pending-transactions')) const txListValue = await driver.findClickableElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/), 10000) + await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/u), 10000) await txListValue.click() await driver.delay(regularDelayMs) @@ -987,12 +987,12 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/)) + await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/u)) const txStatuses = await driver.findElements(By.css('.list-item__heading')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Send\sTST/), 10000) + await driver.wait(until.elementTextMatches(txStatuses[0], /Send\sTST/u), 10000) const tokenBalanceAmount = await driver.findElements(By.css('.token-overview__primary-balance')) - await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.5\s*TST/), 10000) + await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.5\s*TST/u), 10000) }) }) @@ -1019,7 +1019,7 @@ describe('MetaMask', function () { }, 10000) const [txtListHeading] = await driver.findElements(By.css('.transaction-list-item .list-item__heading')) - await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/)) + await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/u)) await driver.clickElement(By.css('.transaction-list-item')) await driver.delay(regularDelayMs) }) @@ -1034,7 +1034,7 @@ describe('MetaMask', function () { const confirmDataDiv = await driver.findElement(By.css('.confirm-approve-content__data__data-block')) const confirmDataText = await confirmDataDiv.getText() - assert(confirmDataText.match(/0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/)) + assert(confirmDataText.match(/0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/u)) }) it('opens the gas edit modal', async function () { @@ -1105,7 +1105,7 @@ describe('MetaMask', function () { }, 10000) const txStatuses = await driver.findElements(By.css('.list-item__heading')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/)) + await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/u)) }) }) @@ -1130,7 +1130,7 @@ describe('MetaMask', function () { }, 10000) const [txListValue] = await driver.findElements(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/)) + await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/u)) await driver.clickElement(By.css('.transaction-list-item')) await driver.delay(regularDelayMs) }) @@ -1148,9 +1148,9 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/)) + await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/u)) const txStatuses = await driver.findElements(By.css('.list-item__heading')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Send TST/)) + await driver.wait(until.elementTextMatches(txStatuses[0], /Send TST/u)) }) }) @@ -1176,7 +1176,7 @@ describe('MetaMask', function () { }, 10000) const [txtListHeading] = await driver.findElements(By.css('.transaction-list-item .list-item__heading')) - await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/)) + await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/u)) await driver.clickElement(By.css('.transaction-list-item')) await driver.delay(regularDelayMs) }) @@ -1203,7 +1203,7 @@ describe('MetaMask', function () { }, 10000) const txStatuses = await driver.findElements(By.css('.list-item__heading')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/)) + await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/u)) }) }) @@ -1244,7 +1244,7 @@ describe('MetaMask', function () { it('renders the balance for the chosen token', async function () { const balance = await driver.findElement(By.css('.token-overview__primary-balance')) - await driver.wait(until.elementTextMatches(balance, /0\s*BAT/)) + await driver.wait(until.elementTextMatches(balance, /0\s*BAT/u)) await driver.delay(regularDelayMs) }) }) diff --git a/test/e2e/send-edit.spec.js b/test/e2e/send-edit.spec.js index c3e60f1c2aaa..ddf9bfde4a9f 100644 --- a/test/e2e/send-edit.spec.js +++ b/test/e2e/send-edit.spec.js @@ -205,7 +205,7 @@ describe('Using MetaMask with an existing account', function () { const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) assert.equal(txValues.length, 1) - assert.ok(/-2.2\s*ETH/.test(await txValues[0].getText())) + assert.ok(/-2.2\s*ETH/u.test(await txValues[0].getText())) }) }) }) diff --git a/test/e2e/tests/localization.spec.js b/test/e2e/tests/localization.spec.js index e3d4520cae7b..127d432bd2ae 100644 --- a/test/e2e/tests/localization.spec.js +++ b/test/e2e/tests/localization.spec.js @@ -20,7 +20,7 @@ describe('Localization', function () { await passwordField.sendKeys(Key.ENTER) const secondaryBalance = await driver.findElement(By.css('[data-testid="eth-overview__secondary-currency"]')) const secondaryBalanceText = await secondaryBalance.getText() - const [fiatAmount, fiatUnit] = secondaryBalanceText.trim().split(/\s+/) + const [fiatAmount, fiatUnit] = secondaryBalanceText.trim().split(/\s+/u) assert.ok(fiatAmount.startsWith('₱')) assert.equal(fiatUnit, 'PHP') }, diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js index e7affbfeb123..6d46e037702f 100644 --- a/test/e2e/threebox.spec.js +++ b/test/e2e/threebox.spec.js @@ -97,7 +97,7 @@ describe('MetaMask', function () { it('balance renders', async function () { const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading')) - await driver.wait(until.elementTextMatches(balance, /25\s*ETH/)) + await driver.wait(until.elementTextMatches(balance, /25\s*ETH/u)) await driver.delay(regularDelayMs) }) }) @@ -203,7 +203,7 @@ describe('MetaMask', function () { it('balance renders', async function () { const balance = await driver2.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading')) - await driver2.wait(until.elementTextMatches(balance, /25\s*ETH/)) + await driver2.wait(until.elementTextMatches(balance, /25\s*ETH/u)) await driver2.delay(regularDelayMs) }) }) diff --git a/test/e2e/webdriver/index.js b/test/e2e/webdriver/index.js index 652e27283d79..8972d54a651f 100644 --- a/test/e2e/webdriver/index.js +++ b/test/e2e/webdriver/index.js @@ -45,7 +45,7 @@ async function setupFetchMocking (driver) { return { json: async () => clone(fetchMockResponses.ethGasBasic) } } else if (url.match(/http(s?):\/\/ethgasstation\.info\/json\/predictTable.*/u)) { return { json: async () => clone(fetchMockResponses.ethGasPredictTable) } - } else if (url.match(/chromeextensionmm/)) { + } else if (url.match(/chromeextensionmm/u)) { return { json: async () => clone(fetchMockResponses.metametrics) } } return window.origFetch(...args) diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js index 22bc3795877a..83ca9eb01beb 100644 --- a/test/unit/app/controllers/detect-tokens-test.js +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -24,7 +24,7 @@ describe('DetectTokensController', function () { nock('https://api.infura.io') - .get(/.*/) + .get(/.*/u) .reply(200) keyringMemStore = new ObservableStore({ isUnlocked: false }) diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index f2556bde2617..92be16f51bf5 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -92,12 +92,12 @@ describe('MetaMaskController', function () { nock('https://api.infura.io') .persist() - .get(/.*/) + .get(/.*/u) .reply(200) nock('https://min-api.cryptocompare.com') .persist() - .get(/.*/) + .get(/.*/u) .reply(200, '{"JPY":12415.9}') metamaskController = new MetaMaskController({ diff --git a/test/unit/migrations/migrator-test.js b/test/unit/migrations/migrator-test.js index c54866ec0eb5..a3dc2fbb7a7e 100644 --- a/test/unit/migrations/migrator-test.js +++ b/test/unit/migrations/migrator-test.js @@ -50,7 +50,7 @@ describe('migrations', function () { migrationNumbers = fileNames .reduce((acc, filename) => { const name = filename.split('.')[0] - if (/^\d+$/.test(name)) { + if (/^\d+$/u.test(name)) { acc.push(name) } return acc @@ -70,7 +70,7 @@ describe('migrations', function () { const testNumbers = fileNames .reduce((acc, filename) => { const name = filename.split('-test.')[0] - if (/^\d+$/.test(name)) { + if (/^\d+$/u.test(name)) { acc.push(name) } return acc diff --git a/ui/app/components/app/menu-bar/account-options-menu.js b/ui/app/components/app/menu-bar/account-options-menu.js index 9edf908d466d..bd3d5b0528cc 100644 --- a/ui/app/components/app/menu-bar/account-options-menu.js +++ b/ui/app/components/app/menu-bar/account-options-menu.js @@ -97,7 +97,7 @@ export default function AccountOptionsMenu ({ anchorElement, onClose }) { rpcPrefs.blockExplorerUrl ? ( - { rpcPrefs.blockExplorerUrl.match(/^https?:\/\/(.+)/)[1] } + { rpcPrefs.blockExplorerUrl.match(/^https?:\/\/(.+)/u)[1] } ) : null diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js index b43575063d6c..267083227ebe 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js @@ -66,7 +66,7 @@ export default class AccountDetailsModal extends Component { }} > {rpcPrefs.blockExplorerUrl - ? this.context.t('blockExplorerView', [rpcPrefs.blockExplorerUrl.match(/^https?:\/\/(.+)/)[1]]) + ? this.context.t('blockExplorerView', [rpcPrefs.blockExplorerUrl.match(/^https?:\/\/(.+)/u)[1]]) : this.context.t('viewOnEtherscan') } diff --git a/ui/app/components/ui/unit-input/unit-input.component.js b/ui/app/components/ui/unit-input/unit-input.component.js index d2368291fa12..6c43aaf2685f 100644 --- a/ui/app/components/ui/unit-input/unit-input.component.js +++ b/ui/app/components/ui/unit-input/unit-input.component.js @@ -58,7 +58,7 @@ export default class UnitInput extends PureComponent { getInputWidth (value) { const valueString = String(value) const valueLength = valueString.length || 1 - const decimalPointDeficit = valueString.match(/\./) ? -0.5 : 0 + const decimalPointDeficit = valueString.match(/\./u) ? -0.5 : 0 return (valueLength + decimalPointDeficit + 0.5) + 'ch' } diff --git a/ui/app/contexts/metametrics.js b/ui/app/contexts/metametrics.js index 9206915093b3..19349bb5d3fa 100644 --- a/ui/app/contexts/metametrics.js +++ b/ui/app/contexts/metametrics.js @@ -60,7 +60,7 @@ export function MetaMetricsProvider ({ children }) { const { eventOpts = {} } = config const { name = '' } = eventOpts const { currentPath: overrideCurrentPath = '' } = overrides - const isSendFlow = Boolean(name.match(/^send|^confirm/) || overrideCurrentPath.match(/send|confirm/)) + const isSendFlow = Boolean(name.match(/^send|^confirm/u) || overrideCurrentPath.match(/send|confirm/u)) if (participateInMetaMetrics || config.isOptIn) { return sendMetaMetricsEvent({ diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js index e2c99f224ccd..60ada9797da9 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js @@ -482,7 +482,7 @@ describe('Confirm Transaction Duck', function () { beforeEach(function () { global.eth = { getCode: sinon.stub().callsFake( - (address) => Promise.resolve(address && address.match(/isContract/) ? 'not-0x' : '0x'), + (address) => Promise.resolve(address && address.match(/isContract/u) ? 'not-0x' : '0x'), ), } }) diff --git a/ui/app/ducks/gas/gas-duck.test.js b/ui/app/ducks/gas/gas-duck.test.js index c4687569304f..a152bff16f4a 100644 --- a/ui/app/ducks/gas/gas-duck.test.js +++ b/ui/app/ducks/gas/gas-duck.test.js @@ -67,7 +67,7 @@ describe('Gas Duck', function () { { expectedTime: 1, expectedWait: 0.5, gasprice: 20, somethingElse: 'foobar' }, ] const fakeFetch = (url) => new Promise((resolve) => { - const dataToResolve = url.match(/ethgasAPI/) + const dataToResolve = url.match(/ethgasAPI/u) ? mockEthGasApiResponse : mockPredictTableResponse resolve({ diff --git a/ui/app/helpers/utils/common.util.js b/ui/app/helpers/utils/common.util.js index a45fdc407629..365ff4376804 100644 --- a/ui/app/helpers/utils/common.util.js +++ b/ui/app/helpers/utils/common.util.js @@ -1,5 +1,5 @@ export function camelCaseToCapitalize (str = '') { return str - .replace(/([A-Z])/g, ' $1') - .replace(/^./, (str) => str.toUpperCase()) + .replace(/([A-Z])/ug, ' $1') + .replace(/^./u, (str) => str.toUpperCase()) } diff --git a/ui/app/helpers/utils/i18n-helper.js b/ui/app/helpers/utils/i18n-helper.js index ff3514f847e3..198e025d5b84 100644 --- a/ui/app/helpers/utils/i18n-helper.js +++ b/ui/app/helpers/utils/i18n-helper.js @@ -48,10 +48,10 @@ export const getMessage = (localeCode, localeMessages, key, substitutions) => { // perform substitutions if (hasSubstitutions) { - const parts = phrase.split(/(\$\d)/g) + const parts = phrase.split(/(\$\d)/ug) const substitutedParts = parts.map((part) => { - const subMatch = part.match(/\$(\d)/) + const subMatch = part.match(/\$(\d)/u) if (!subMatch) { return part } diff --git a/ui/app/helpers/utils/transactions.util.js b/ui/app/helpers/utils/transactions.util.js index b3d2889e1441..3d14c0336d4d 100644 --- a/ui/app/helpers/utils/transactions.util.js +++ b/ui/app/helpers/utils/transactions.util.js @@ -238,7 +238,7 @@ export function getStatusKey (transaction) { */ export function getBlockExplorerUrlForTx (networkId, hash, rpcPrefs = {}) { if (rpcPrefs.blockExplorerUrl) { - return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/, '')}/tx/${hash}` + return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/u, '')}/tx/${hash}` } const prefix = getEtherscanNetworkPrefix(networkId) return `https://${prefix}etherscan.io/tx/${hash}` diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index 40129375629e..98e58053f86f 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -75,7 +75,7 @@ export function isValidDomainName (address) { // Checks that the domain consists of at least one valid domain pieces separated by periods, followed by a tld // Each piece of domain name has only the characters a-z, 0-9, and a hyphen (but not at the start or end of chunk) // A chunk has minimum length of 1, but minimum tld is set to 2 for now (no 1-character tlds exist yet) - .match(/^(?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?\.)+[a-z0-9][-a-z0-9]*[a-z0-9]$/) + .match(/^(?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?\.)+[a-z0-9][-a-z0-9]*[a-z0-9]$/u) return match !== null } @@ -102,7 +102,7 @@ export function parseBalance (balance) { let afterDecimal const wei = numericBalance(balance) const weiString = wei.toString() - const trailingZeros = /0+$/ + const trailingZeros = /0+$/u const beforeDecimal = weiString.length > 18 ? weiString.slice(0, weiString.length - 18) : '0' afterDecimal = ('000000000000000000' + wei).slice(-18).replace(trailingZeros, '') @@ -122,7 +122,7 @@ export function formatBalance (balance, decimalsToKeep, needsParse = true, ticke if (decimalsToKeep === undefined) { if (beforeDecimal === '0') { if (afterDecimal !== '0') { - const sigFigs = afterDecimal.match(/^0*(.{2})/) // default: grabs 2 most significant digits + const sigFigs = afterDecimal.match(/^0*(.{2})/u) // default: grabs 2 most significant digits if (sigFigs) { afterDecimal = sigFigs[0] } @@ -219,7 +219,7 @@ export function normalizeNumberToWei (n, currency) { } export function isHex (str) { - return Boolean(str.match(/^(0x)?[0-9a-fA-F]+$/)) + return Boolean(str.match(/^(0x)?[0-9a-fA-F]+$/u)) } export function getContractAtAddress (tokenAddress) { diff --git a/ui/app/helpers/utils/util.test.js b/ui/app/helpers/utils/util.test.js index ef1f5f1531f9..cbeb624d164e 100644 --- a/ui/app/helpers/utils/util.test.js +++ b/ui/app/helpers/utils/util.test.js @@ -307,7 +307,7 @@ describe('util', function () { describe('#getRandomFileName', function () { it('should only return a string containing alphanumeric characters', function () { const result = util.getRandomFileName() - assert(result.match(/^[a-zA-Z0-9]*$/g)) + assert(result.match(/^[a-zA-Z0-9]*$/ug)) }) // 50 samples diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js index 7f8df41685b9..1b44c4376166 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -727,7 +727,7 @@ export function getMethodName (camelCase) { } return camelCase - .replace(/([a-z])([A-Z])/g, '$1 $2') - .replace(/([A-Z])([a-z])/g, ' $1$2') - .replace(/ +/g, ' ') + .replace(/([a-z])([A-Z])/ug, '$1 $2') + .replace(/([A-Z])([a-z])/ug, ' $1$2') + .replace(/ +/ug, ' ') } diff --git a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js index 11daa6cc623b..b0d0a8924b0a 100644 --- a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js +++ b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js @@ -5,7 +5,7 @@ import { unconfirmedTransactionsListSelector } from '../../selectors' const mapStateToProps = (state, ownProps) => { const { metamask: { unapprovedTxs } } = state const { match: { params = {}, url } } = ownProps - const urlId = url && url.match(/\d+/) && url.match(/\d+/)[0] + const urlId = url && url.match(/\d+/u) && url.match(/\d+/u)[0] const { id: paramsId } = params const transactionId = paramsId || urlId diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js index a35ba5b9face..6284206886a4 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js @@ -9,7 +9,7 @@ import { } from '../../../send.constants' const stubs = { - isValidAddress: sinon.stub().callsFake((to) => Boolean(to.match(/^[0xabcdef123456798]+$/))), + isValidAddress: sinon.stub().callsFake((to) => Boolean(to.match(/^[0xabcdef123456798]+$/u))), } const toRowUtils = proxyquire('../add-recipient.js', { diff --git a/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js b/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js index eeff87b84d7c..cf774ae0cea7 100644 --- a/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js +++ b/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js @@ -15,7 +15,7 @@ export default class SendHexDataRow extends Component { onInput = (event) => { const { updateSendHexData, updateGas } = this.props - const data = event.target.value.replace(/\n/g, '') || null + const data = event.target.value.replace(/\n/ug, '') || null updateSendHexData(data) updateGas({ data }) } diff --git a/ui/app/pages/send/send.utils.js b/ui/app/pages/send/send.utils.js index ff3b5295a1a0..ca0fdf0441b8 100644 --- a/ui/app/pages/send/send.utils.js +++ b/ui/app/pages/send/send.utils.js @@ -314,7 +314,7 @@ function getToAddressForGasUpdate (...addresses) { } function removeLeadingZeroes (str) { - return str.replace(/^0*(?=\d)/, '') + return str.replace(/^0*(?=\d)/u, '') } function ellipsify (text, first = 6, last = 4) { diff --git a/ui/app/pages/send/tests/send-utils.test.js b/ui/app/pages/send/tests/send-utils.test.js index 08bc302898e9..b1f57e49a6f6 100644 --- a/ui/app/pages/send/tests/send-utils.test.js +++ b/ui/app/pages/send/tests/send-utils.test.js @@ -10,10 +10,10 @@ import { const stubs = { addCurrencies: sinon.stub().callsFake((a, b) => { - if (String(a).match(/^0x.+/)) { + if (String(a).match(/^0x.+/u)) { a = Number(String(a).slice(2)) } - if (String(b).match(/^0x.+/)) { + if (String(b).match(/^0x.+/u)) { b = Number(String(b).slice(2)) } return a + b @@ -294,8 +294,8 @@ describe('send utils', function () { to: '0xisContract', estimateGasMethod: sinon.stub().callsFake( ({ to }) => { - if (typeof to === 'string' && to.match(/willFailBecauseOf:/)) { - throw new Error(to.match(/:(.+)$/)[1]) + if (typeof to === 'string' && to.match(/willFailBecauseOf:/u)) { + throw new Error(to.match(/:(.+)$/u)[1]) } return { toString: (n) => `0xabc${n}` } }, @@ -311,7 +311,7 @@ describe('send utils', function () { beforeEach(function () { global.eth = { getCode: sinon.stub().callsFake( - (address) => Promise.resolve(address.match(/isContract/) ? 'not-0x' : '0x'), + (address) => Promise.resolve(address.match(/isContract/u) ? 'not-0x' : '0x'), ), } }) diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js index df952eff6a11..ec8cbbbdaec9 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js @@ -489,7 +489,7 @@ export default class AdvancedTab extends PureComponent { function addUrlProtocolPrefix (urlString) { if (!urlString.match( - /(^http:\/\/)|(^https:\/\/)/, + /(^http:\/\/)|(^https:\/\/)/u, )) { return 'https://' + urlString } diff --git a/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js b/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js index d3bb1799a7c5..63a7db52d795 100644 --- a/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js +++ b/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js @@ -20,7 +20,7 @@ const mapStateToProps = (state, ownProps) => { const { location } = ownProps const { pathname } = location - const pathNameTail = pathname.match(/[^/]+$/)[0] + const pathNameTail = pathname.match(/[^/]+$/u)[0] const pathNameTailIsAddress = pathNameTail.includes('0x') const viewingContact = Boolean(pathname.match(CONTACT_VIEW_ROUTE) || pathname.match(CONTACT_MY_ACCOUNTS_VIEW_ROUTE)) diff --git a/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js b/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js index 3766f1ac8588..4cd7bd59ecab 100644 --- a/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js +++ b/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js @@ -15,7 +15,7 @@ import { addToAddressBook, removeFromAddressBook, setAccountLabel } from '../../ const mapStateToProps = (state, ownProps) => { const { location } = ownProps const { pathname } = location - const pathNameTail = pathname.match(/[^/]+$/)[0] + const pathNameTail = pathname.match(/[^/]+$/u)[0] const pathNameTailIsAddress = pathNameTail.includes('0x') const address = pathNameTailIsAddress ? pathNameTail.toLowerCase() : ownProps.match.params.id diff --git a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js index ce9312c87f1e..9b3e9a17c325 100644 --- a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js +++ b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js @@ -15,7 +15,7 @@ function quadSplit (address) { '0x ' + address .slice(2) - .match(/.{1,4}/g) + .match(/.{1,4}/ug) .join(' ') ) } diff --git a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js index 7f7c5d8c1536..33579d1545ea 100644 --- a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js +++ b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js @@ -15,7 +15,7 @@ import { const mapStateToProps = (state, ownProps) => { const { location } = ownProps const { pathname } = location - const pathNameTail = pathname.match(/[^/]+$/)[0] + const pathNameTail = pathname.match(/[^/]+$/u)[0] const pathNameTailIsAddress = pathNameTail.includes('0x') const address = pathNameTailIsAddress ? pathNameTail.toLowerCase() : ownProps.match.params.id diff --git a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js index 34209983a9fd..8f029771f564 100644 --- a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js +++ b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js @@ -214,7 +214,7 @@ export default class NetworkForm extends PureComponent { isValidWhenAppended = (url) => { const appendedRpc = `http://${url}` - return validUrl.isWebUri(appendedRpc) && !url.match(/^https?:\/\/$/) + return validUrl.isWebUri(appendedRpc) && !url.match(/^https?:\/\/$/u) } validateBlockExplorerURL = (url, stateKey) => { diff --git a/ui/app/pages/settings/settings.container.js b/ui/app/pages/settings/settings.container.js index ebeb2ae4bb78..e0b3cfbaf007 100644 --- a/ui/app/pages/settings/settings.container.js +++ b/ui/app/pages/settings/settings.container.js @@ -42,7 +42,7 @@ const ROUTES_TO_I18N_KEYS = { const mapStateToProps = (state, ownProps) => { const { location } = ownProps const { pathname } = location - const pathNameTail = pathname.match(/[^/]+$/)[0] + const pathNameTail = pathname.match(/[^/]+$/u)[0] const isAddressEntryPage = pathNameTail.includes('0x') const isMyAccountsPage = pathname.match('my-accounts') diff --git a/ui/lib/account-link.js b/ui/lib/account-link.js index 1f9ba293e273..3e653b088501 100644 --- a/ui/lib/account-link.js +++ b/ui/lib/account-link.js @@ -1,6 +1,6 @@ export default function getAccountLink (address, network, rpcPrefs) { if (rpcPrefs && rpcPrefs.blockExplorerUrl) { - return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/, '')}/address/${address}` + return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/u, '')}/address/${address}` } const net = parseInt(network) From 937616565ddee27ede58376a56547cfa07d3a567 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 14 Aug 2020 11:57:42 -0230 Subject: [PATCH 098/137] Tidy ConnectHardwareForm#checkIfUnlocked (#9224) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change tidies up the implementation of `ConnectHardwareForm#checkIfUnlocked`—passing an `async` function to `forEach` doesn't ensure that the one is run before the other. --- ui/app/pages/create-account/connect-hardware/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/app/pages/create-account/connect-hardware/index.js b/ui/app/pages/create-account/connect-hardware/index.js index 4bae249e6b2c..32189bf63029 100644 --- a/ui/app/pages/create-account/connect-hardware/index.js +++ b/ui/app/pages/create-account/connect-hardware/index.js @@ -35,13 +35,13 @@ class ConnectHardwareForm extends Component { } async checkIfUnlocked () { - ['trezor', 'ledger'].forEach(async (device) => { + for (const device of ['trezor', 'ledger']) { const unlocked = await this.props.checkHardwareStatus(device, this.props.defaultHdPaths[device]) if (unlocked) { this.setState({ unlocked: true }) this.getPage(device, 0, this.props.defaultHdPaths[device]) } - }) + } } connectToHardwareWallet = (device) => { From 2aa4b6bbeeb6ef97ca7f7e58b9a592d9a075e2e0 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 14 Aug 2020 12:31:59 -0230 Subject: [PATCH 099/137] Tidy up getAccountLink (#9223) --- .../app/menu-bar/account-options-menu.js | 4 ++-- .../account-details-modal.component.js | 4 ++-- .../confirm-remove-account.component.js | 4 ++-- .../connect-hardware/account-list.js | 4 ++-- ui/lib/account-link.js | 24 ++++++------------- 5 files changed, 15 insertions(+), 25 deletions(-) diff --git a/ui/app/components/app/menu-bar/account-options-menu.js b/ui/app/components/app/menu-bar/account-options-menu.js index bd3d5b0528cc..32c31b6c0c50 100644 --- a/ui/app/components/app/menu-bar/account-options-menu.js +++ b/ui/app/components/app/menu-bar/account-options-menu.js @@ -6,7 +6,7 @@ import { useDispatch, useSelector } from 'react-redux' import { showModal } from '../../../store/actions' import { CONNECTED_ROUTE } from '../../../helpers/constants/routes' import { Menu, MenuItem } from '../../ui/menu' -import genAccountLink from '../../../../lib/account-link' +import getAccountLink from '../../../../lib/account-link' import { getCurrentKeyring, getCurrentNetwork, getRpcPrefsForCurrentProvider, getSelectedIdentity } from '../../../selectors' import { useI18nContext } from '../../../hooks/useI18nContext' import { useMetricEvent } from '../../../hooks/useMetricEvent' @@ -90,7 +90,7 @@ export default function AccountOptionsMenu ({ anchorElement, onClose }) { { viewOnEtherscanEvent() - global.platform.openTab({ url: genAccountLink(address, network, rpcPrefs) }) + global.platform.openTab({ url: getAccountLink(address, network, rpcPrefs) }) onClose() }} subtitle={ diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js index 267083227ebe..858ae8296735 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import AccountModalContainer from '../account-modal-container' -import genAccountLink from '../../../../../lib/account-link' +import getAccountLink from '../../../../../lib/account-link' import QrView from '../../../ui/qr-code' import EditableLabel from '../../../ui/editable-label' import Button from '../../../ui/button' @@ -62,7 +62,7 @@ export default class AccountDetailsModal extends Component { type="secondary" className="account-details-modal__button" onClick={() => { - global.platform.openTab({ url: genAccountLink(address, network, rpcPrefs) }) + global.platform.openTab({ url: getAccountLink(address, network, rpcPrefs) }) }} > {rpcPrefs.blockExplorerUrl diff --git a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js index 12d652514cc3..4258d9462a64 100644 --- a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js +++ b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import Modal from '../../modal' import { addressSummary } from '../../../../helpers/utils/util' import Identicon from '../../../ui/identicon' -import genAccountLink from '../../../../../lib/account-link' +import getAccountLink from '../../../../../lib/account-link' export default class ConfirmRemoveAccount extends Component { static propTypes = { @@ -47,7 +47,7 @@ export default class ConfirmRemoveAccount extends Component {
Date: Fri, 14 Aug 2020 12:52:38 -0230 Subject: [PATCH 100/137] Delete page-container.component.test.js (#9229) --- .../ui/page-container/tests/page-container.component.test.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 ui/app/components/ui/page-container/tests/page-container.component.test.js diff --git a/ui/app/components/ui/page-container/tests/page-container.component.test.js b/ui/app/components/ui/page-container/tests/page-container.component.test.js deleted file mode 100644 index e69de29bb2d1..000000000000 From 9e7841fa918435612bc85754dc03943a6514c762 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 14 Aug 2020 13:41:25 -0230 Subject: [PATCH 101/137] Consolidate ESLint config files (#9231) --- .eslintrc.js | 7 +++++++ test/e2e/.eslintrc.js | 5 ----- 2 files changed, 7 insertions(+), 5 deletions(-) delete mode 100644 test/e2e/.eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js index 2e74bd47614c..ee22e7f4c586 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -126,6 +126,13 @@ module.exports = { }, overrides: [{ + files: [ + 'test/e2e/**/*.js', + ], + rules: { + 'mocha/no-hooks-for-single-case': 'off', + }, + }, { files: [ 'app/scripts/migrations/*.js', '*.stories.js', diff --git a/test/e2e/.eslintrc.js b/test/e2e/.eslintrc.js deleted file mode 100644 index d84a4b2fb6d7..000000000000 --- a/test/e2e/.eslintrc.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - rules: { - 'mocha/no-hooks-for-single-case': 'off', - }, -} From e021acdc0ad52e06ca5bbcf6c55022d0c3e37bf7 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 14 Aug 2020 15:13:56 -0230 Subject: [PATCH 102/137] Fix max-statements-per-line issues (#9218) See [`max-statements-per-line`](https://eslint.org/docs/rules/max-statements-per-line) for more information. This change enables `max-statements-per-line` and fixes the issues raised by the rule. --- .eslintrc.js | 1 + app/scripts/lib/decrypt-message-manager.js | 3 ++- app/scripts/lib/encryption-public-key-manager.js | 3 ++- app/scripts/lib/message-manager.js | 3 ++- app/scripts/lib/personal-message-manager.js | 3 ++- app/scripts/lib/typed-message-manager.js | 3 ++- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index ee22e7f4c586..2f5e14f17031 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -49,6 +49,7 @@ module.exports = { 'guard-for-in': 'error', 'implicit-arrow-linebreak': 'error', 'import/extensions': ['error', 'never', { 'json': 'always' }], + 'max-statements-per-line': ['error', { 'max': 1 }], 'no-case-declarations': 'error', 'no-constant-condition': 'error', 'no-dupe-else-if': 'error', diff --git a/app/scripts/lib/decrypt-message-manager.js b/app/scripts/lib/decrypt-message-manager.js index a379d656146b..d6986f52fe34 100644 --- a/app/scripts/lib/decrypt-message-manager.js +++ b/app/scripts/lib/decrypt-message-manager.js @@ -65,7 +65,8 @@ export default class DecryptMessageManager extends EventEmitter { getUnapprovedMsgs () { return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg; return result + result[msg.id] = msg + return result }, {}) } diff --git a/app/scripts/lib/encryption-public-key-manager.js b/app/scripts/lib/encryption-public-key-manager.js index 6ca78fdcfc76..7550a26e37e5 100644 --- a/app/scripts/lib/encryption-public-key-manager.js +++ b/app/scripts/lib/encryption-public-key-manager.js @@ -62,7 +62,8 @@ export default class EncryptionPublicKeyManager extends EventEmitter { getUnapprovedMsgs () { return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg; return result + result[msg.id] = msg + return result }, {}) } diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index b06246852079..6c74b017adca 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -64,7 +64,8 @@ export default class MessageManager extends EventEmitter { getUnapprovedMsgs () { return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg; return result + result[msg.id] = msg + return result }, {}) } diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 647b7e58938c..7770e810658f 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -68,7 +68,8 @@ export default class PersonalMessageManager extends EventEmitter { getUnapprovedMsgs () { return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg; return result + result[msg.id] = msg + return result }, {}) } diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index 4bab84d3e964..38762a97ac5d 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -61,7 +61,8 @@ export default class TypedMessageManager extends EventEmitter { getUnapprovedMsgs () { return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg; return result + result[msg.id] = msg + return result }, {}) } From c2edc342fb96e2228eeefee93e32e82567ad2a71 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 14 Aug 2020 15:51:48 -0230 Subject: [PATCH 103/137] Remove unused buyEth fn from bg (#9236) --- app/scripts/metamask-controller.js | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 1e4af85b1678..cd372978418d 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -47,7 +47,6 @@ import { PermissionsController } from './controllers/permissions' import getRestrictedMethods from './controllers/permissions/restrictedMethods' import nodeify from './lib/nodeify' import accountImporter from './account-import-strategies' -import getBuyEthUrl from './lib/buy-eth-url' import selectChainId from './lib/select-chain-id' import { Mutex } from 'await-semaphore' import { version } from '../manifest/_base.json' @@ -449,7 +448,6 @@ export default class MetamaskController extends EventEmitter { setCurrentLocale: this.setCurrentLocale.bind(this), markPasswordForgotten: this.markPasswordForgotten.bind(this), unMarkPasswordForgotten: this.unMarkPasswordForgotten.bind(this), - buyEth: this.buyEth.bind(this), safelistPhishingDomain: this.safelistPhishingDomain.bind(this), getRequestAccountTabIds: (cb) => cb(null, this.getRequestAccountTabIds()), getOpenMetamaskTabsIds: (cb) => cb(null, this.getOpenMetamaskTabsIds()), @@ -1879,24 +1877,6 @@ export default class MetamaskController extends EventEmitter { } } - /** - * A method for forwarding the user to the easiest way to obtain ether, - * or the network "gas" currency, for the current selected network. - * - * @param {string} address - The address to fund. - * @param {string} amount - The amount of ether desired, as a base 10 string. - */ - buyEth (address, amount) { - if (!amount) { - amount = '5' - } - const network = this.networkController.getNetworkState() - const url = getBuyEthUrl({ network, address, amount }) - if (url) { - this.platform.openTab({ url }) - } - } - // network /** * A method for selecting a custom URL for an ethereum RPC provider and updating it From aaacf66c6efe95947223539efbc9d01e49db3149 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 14 Aug 2020 17:34:56 -0230 Subject: [PATCH 104/137] Fix import/no-extraneous-dependencies issues (#9232) See [`import/no-extraneous-dependencies`](https://eslint.org/docs/rules/import/no-extraneous-dependencies) for more information. This change enables `import/no-extraneous-dependencies` and fixes the issues raised by the rule. --- .eslintrc.js | 1 + test/unit/app/controllers/ens-controller-test.js | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 2f5e14f17031..6c505839039a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -49,6 +49,7 @@ module.exports = { 'guard-for-in': 'error', 'implicit-arrow-linebreak': 'error', 'import/extensions': ['error', 'never', { 'json': 'always' }], + 'import/no-extraneous-dependencies': 'error', 'max-statements-per-line': ['error', { 'max': 1 }], 'no-case-declarations': 'error', 'no-constant-condition': 'error', diff --git a/test/unit/app/controllers/ens-controller-test.js b/test/unit/app/controllers/ens-controller-test.js index 1176b8b42037..cf57bdf1fbad 100644 --- a/test/unit/app/controllers/ens-controller-test.js +++ b/test/unit/app/controllers/ens-controller-test.js @@ -1,7 +1,6 @@ import assert from 'assert' import sinon from 'sinon' import ObservableStore from 'obs-store' -import HttpProvider from 'ethjs-provider-http' import EnsController from '../../../../app/scripts/controllers/ens' const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' @@ -10,11 +9,10 @@ const ZERO_X_ERROR_ADDRESS = '0x' describe('EnsController', function () { describe('#constructor', function () { it('should construct the controller given a provider and a network', async function () { - const provider = new HttpProvider('https://ropsten.infura.io') const currentNetworkId = '3' const networkStore = new ObservableStore(currentNetworkId) const ens = new EnsController({ - provider, + provider: { }, networkStore, }) From f77151003e7ad12a4c265b1b95645d0e9a14211c Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 14 Aug 2020 19:15:21 -0300 Subject: [PATCH 105/137] Send web3 usage metrics once per origin/property (#9237) The usage metrics for the injected web3 instance were being sent upon each use, which exceeded the limits of our Matomo plan. These metrics are now only being sent upon the first usage, for each origin and property. --- app/scripts/lib/createMethodMiddleware.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/app/scripts/lib/createMethodMiddleware.js b/app/scripts/lib/createMethodMiddleware.js index 8224dbf332e8..7a98ce531255 100644 --- a/app/scripts/lib/createMethodMiddleware.js +++ b/app/scripts/lib/createMethodMiddleware.js @@ -1,3 +1,6 @@ + +const recordedWeb3Usage = {} + /** * Returns a middleware that implements the following RPC methods: * - metamask_logInjectedWeb3Usage @@ -15,11 +18,17 @@ export default function createMethodMiddleware ({ origin, sendMetrics }) { const { action, name } = req.params[0] - sendMetrics({ - action, - name, - customVariables: { origin }, - }) + if (!recordedWeb3Usage[origin]) { + recordedWeb3Usage[origin] = {} + } + if (!recordedWeb3Usage[origin][name]) { + recordedWeb3Usage[origin][name] = true + sendMetrics({ + action, + name, + customVariables: { origin }, + }) + } res.result = true break From aad840777deb9e59967cf8e6921198261b25ee73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20=C5=81ucka?= Date: Sat, 15 Aug 2020 00:18:46 +0200 Subject: [PATCH 106/137] Permit all-caps addresses (#9227) * permit all-caps addresses * handle empty address --- ui/app/helpers/utils/util.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index 98e58053f86f..28f3dd6f46b7 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -62,11 +62,11 @@ export function addressSummary (address, firstSegLength = 10, lastSegLength = 4, } export function isValidAddress (address) { - const prefixed = ethUtil.addHexPrefix(address) - if (address === '0x0000000000000000000000000000000000000000') { + if (!address || address === '0x0000000000000000000000000000000000000000') { return false } - return (isAllOneCase(prefixed) && ethUtil.isValidAddress(prefixed)) || ethUtil.isValidChecksumAddress(prefixed) + const prefixed = address.startsWith('0X') ? address : ethUtil.addHexPrefix(address) + return (isAllOneCase(prefixed.slice(2)) && ethUtil.isValidAddress(prefixed)) || ethUtil.isValidChecksumAddress(prefixed) } export function isValidDomainName (address) { From 87e5281a822fc6a6e5f4b2f03d37da7080d54696 Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Fri, 14 Aug 2020 16:08:26 -0700 Subject: [PATCH 107/137] Clear Account Details in AppState (#9238) * Clear Account Details in AppState We store sensitive information in the AppState under accountDetail for when the modal is active and present. This adds a new action/reducer and componentWillUnmount to clean up the persisted data left after leaving the modal. * Remove reduntant clearAccountDetails call when clicking done button --- test/unit/ui/app/reducers/app.spec.js | 17 +++++++++++++++++ .../export-private-key-modal.component.js | 5 +++++ .../export-private-key-modal.container.js | 3 ++- ui/app/ducks/app/app.js | 6 ++++++ ui/app/store/actionConstants.js | 1 + ui/app/store/actions.js | 6 ++++++ 6 files changed, 37 insertions(+), 1 deletion(-) diff --git a/test/unit/ui/app/reducers/app.spec.js b/test/unit/ui/app/reducers/app.spec.js index cd135d22076f..027f574f2181 100644 --- a/test/unit/ui/app/reducers/app.spec.js +++ b/test/unit/ui/app/reducers/app.spec.js @@ -167,6 +167,23 @@ describe('App State', function () { }) + it('clears account details', function () { + const exportPrivKeyModal = { + accountDetail: { + subview: 'export', + accountExport: 'completed', + privateKey: 'a-priv-key', + }, + } + + const state = { ...metamaskState, appState: { ...exportPrivKeyModal } } + const newState = reduceApp(state, { + type: actions.CLEAR_ACCOUNT_DETAILS, + }) + + assert.deepStrictEqual(newState.accountDetail, {}) + }) + it('shoes account page', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_ACCOUNTS_PAGE, diff --git a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js index ba30d5218919..965d5a703a9d 100644 --- a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js +++ b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js @@ -25,6 +25,7 @@ export default class ExportPrivateKeyModal extends Component { warning: PropTypes.node, showAccountDetailModal: PropTypes.func.isRequired, hideModal: PropTypes.func.isRequired, + clearAccountDetails: PropTypes.func.isRequired, previousModalState: PropTypes.string, } @@ -34,6 +35,10 @@ export default class ExportPrivateKeyModal extends Component { showWarning: true, } + componentWillUnmount () { + this.props.clearAccountDetails() + } + exportAccountAndGetPrivateKey = (password, address) => { const { exportAccount } = this.props diff --git a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.container.js b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.container.js index 3137292178c8..e1676f8be925 100644 --- a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.container.js +++ b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.container.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux' -import { exportAccount, hideWarning, showModal, hideModal } from '../../../../store/actions' +import { exportAccount, hideWarning, showModal, hideModal, clearAccountDetails } from '../../../../store/actions' import { getSelectedIdentity } from '../../../../selectors' import ExportPrivateKeyModal from './export-private-key-modal.component' @@ -32,6 +32,7 @@ function mapDispatchToProps (dispatch) { }, showAccountDetailModal: () => dispatch(showModal({ name: 'ACCOUNT_DETAILS' })), hideModal: () => dispatch(hideModal()), + clearAccountDetails: () => dispatch(clearAccountDetails()), } } diff --git a/ui/app/ducks/app/app.js b/ui/app/ducks/app/app.js index f45a4b294c11..e7672dd37d7e 100644 --- a/ui/app/ducks/app/app.js +++ b/ui/app/ducks/app/app.js @@ -137,6 +137,12 @@ export default function reduceApp (state = {}, action) { ), } + case actionConstants.CLEAR_ACCOUNT_DETAILS: + return { + ...appState, + accountDetail: {}, + } + case actionConstants.FORGOT_PASSWORD: return { ...appState, diff --git a/ui/app/store/actionConstants.js b/ui/app/store/actionConstants.js index 4a11aa11135e..ac7cc11a0657 100644 --- a/ui/app/store/actionConstants.js +++ b/ui/app/store/actionConstants.js @@ -36,6 +36,7 @@ export const SET_CURRENT_FIAT = 'SET_CURRENT_FIAT' export const SHOW_SEND_TOKEN_PAGE = 'SHOW_SEND_TOKEN_PAGE' export const SHOW_PRIVATE_KEY = 'SHOW_PRIVATE_KEY' export const SET_ACCOUNT_LABEL = 'SET_ACCOUNT_LABEL' +export const CLEAR_ACCOUNT_DETAILS = 'CLEAR_ACCOUNT_DETAILS' // tx conf screen export const COMPLETED_TX = 'COMPLETED_TX' export const TRANSACTION_ERROR = 'TRANSACTION_ERROR' diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 9f4396507235..c9c4a63dd109 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -1808,6 +1808,12 @@ export function setAccountLabel (account, label) { } } +export function clearAccountDetails () { + return { + type: actionConstants.CLEAR_ACCOUNT_DETAILS, + } +} + export function showSendTokenPage () { return { type: actionConstants.SHOW_SEND_TOKEN_PAGE, From e803807dd9f93ce23dda7120be525ea0e9435ad3 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Sat, 15 Aug 2020 09:28:11 -0230 Subject: [PATCH 108/137] Fix no-param-reassign issues (#9235) See [`no-param-reassign`](https://eslint.org/docs/rules/no-param-reassign) for more information. This change enables `no-param-reassign` and fixes the issues raised by the rule. --- .eslintrc.js | 1 + app/scripts/controllers/network/network.js | 3 +-- app/scripts/controllers/preferences.js | 1 + app/scripts/controllers/transactions/index.js | 1 + .../transactions/tx-state-manager.js | 1 + app/scripts/lib/buy-eth-url.js | 1 + app/scripts/lib/migrator/index.js | 1 + app/scripts/lib/setupSentry.js | 8 +++---- app/scripts/migrations/038.js | 23 ++++++++++--------- test/e2e/benchmark.js | 9 ++++---- test/e2e/ganache.js | 5 ++-- test/e2e/webdriver/driver.js | 6 ++--- .../unit/app/controllers/permissions/mocks.js | 1 + .../signature-request-original.component.js | 1 + .../ui/check-box/check-box.component.js | 1 + .../confirm-transaction.duck.js | 6 ++--- ui/app/ducks/gas/gas.duck.js | 8 ++++--- ui/app/helpers/utils/switch-direction.js | 3 ++- ui/app/helpers/utils/util.js | 1 + .../add-recipient/ens-input.component.js | 4 ++-- ui/app/pages/send/send.utils.js | 1 + ui/app/pages/send/tests/send-utils.test.js | 7 +++--- ui/app/store/actions.js | 3 +-- 23 files changed, 54 insertions(+), 42 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 6c505839039a..4e74e1209906 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -61,6 +61,7 @@ module.exports = { 'no-loop-func': 'error', 'no-negated-condition': 'error', 'no-nested-ternary': 'error', + 'no-param-reassign': 'error', 'no-plusplus': ['error', { 'allowForLoopAfterthoughts': true }], 'no-process-exit': 'error', 'no-prototype-builtins': 'error', diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index f22dbc323c1c..90a60f8cd676 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -101,8 +101,7 @@ export default class NetworkController extends EventEmitter { if (!type) { return } - network = networks.networkList[type]?.chainId || network - this.networkStore.putState(network) + this.networkStore.putState(networks.networkList[type]?.chainId || network) } isNetworkLoading () { diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 4c0e97ceb575..dee126a8b228 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -689,6 +689,7 @@ export default class PreferencesController { _getTokenRelatedStates (selectedAddress) { const accountTokens = this.store.getState().accountTokens if (!selectedAddress) { + // eslint-disable-next-line no-param-reassign selectedAddress = this.store.getState().selectedAddress } const providerType = this.network.providerStore.getState().type diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 795c7c6ea20a..9f8da729da5e 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -271,6 +271,7 @@ export default class TransactionController extends EventEmitter { const defaultGasPrice = await this._getDefaultGasPrice(txMeta) const { gasLimit: defaultGasLimit, simulationFails } = await this._getDefaultGasLimit(txMeta, getCodeResponse) + // eslint-disable-next-line no-param-reassign txMeta = this.txStateManager.getTx(txMeta.id) if (simulationFails) { txMeta.simulationFails = simulationFails diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 7de54fb9cad8..89eaf2464054 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -262,6 +262,7 @@ export default class TransactionStateManager extends EventEmitter { if (typeof txParams.data === 'undefined') { delete txParams.data } + // eslint-disable-next-line no-param-reassign txParams = normalizeTxParams(txParams, false) this.validateTxParams(txParams) return txParams diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js index 46d8909da239..a82d3f2b02c3 100644 --- a/app/scripts/lib/buy-eth-url.js +++ b/app/scripts/lib/buy-eth-url.js @@ -11,6 +11,7 @@ export default function getBuyEthUrl ({ network, address, service }) { // default service by network if not specified if (!service) { + // eslint-disable-next-line no-param-reassign service = getDefaultServiceForNetwork(network) } diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index a82b93294261..5c2f6185fa7a 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -46,6 +46,7 @@ export default class Migrator extends EventEmitter { throw new Error('Migrator - Migration did not update version number correctly') } // accept the migration as good + // eslint-disable-next-line no-param-reassign versionedData = migratedData } catch (err) { // rewrite error message to add context without clobbering stack diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index c974aafd8319..02ad02d6bd2a 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -122,13 +122,13 @@ export default function setupSentry ({ release, getState }) { function simplifyErrorMessages (report) { rewriteErrorMessages(report, (errorMessage) => { // simplify ethjs error messages - errorMessage = extractEthjsErrorMessage(errorMessage) + let simplifiedErrorMessage = extractEthjsErrorMessage(errorMessage) // simplify 'Transaction Failed: known transaction' - if (errorMessage.indexOf('Transaction Failed: known transaction') === 0) { + if (simplifiedErrorMessage.indexOf('Transaction Failed: known transaction') === 0) { // cut the hash from the error message - errorMessage = 'Transaction Failed: known transaction' + simplifiedErrorMessage = 'Transaction Failed: known transaction' } - return errorMessage + return simplifiedErrorMessage }) } diff --git a/app/scripts/migrations/038.js b/app/scripts/migrations/038.js index fdbaa1d3b733..e5386f7a929d 100644 --- a/app/scripts/migrations/038.js +++ b/app/scripts/migrations/038.js @@ -19,17 +19,18 @@ function transformState (state) { const { ABTestController: ABTestControllerState = {} } = state const { abTests = {} } = ABTestControllerState - if (!abTests.fullScreenVsPopup) { - state = { - ...state, - ABTestController: { - ...ABTestControllerState, - abTests: { - ...abTests, - fullScreenVsPopup: 'control', - }, + if (abTests.fullScreenVsPopup) { + return state + } + + return { + ...state, + ABTestController: { + ...ABTestControllerState, + abTests: { + ...abTests, + fullScreenVsPopup: 'control', }, - } + }, } - return state } diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index f34436328204..a70bf6805676 100644 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -92,17 +92,18 @@ async function isWritable (directory) { } async function getFirstParentDirectoryThatExists (directory) { + let nextDirectory = directory for (;;) { try { - await fs.access(directory, fsConstants.F_OK) - return directory + await fs.access(nextDirectory, fsConstants.F_OK) + return nextDirectory } catch (error) { if (error.code !== 'ENOENT') { throw error - } else if (directory === path.dirname(directory)) { + } else if (nextDirectory === path.dirname(nextDirectory)) { throw new Error('Failed to find parent directory that exists') } - directory = path.dirname(directory) + nextDirectory = path.dirname(nextDirectory) } } } diff --git a/test/e2e/ganache.js b/test/e2e/ganache.js index cd15990c8ab7..29cc085bc335 100644 --- a/test/e2e/ganache.js +++ b/test/e2e/ganache.js @@ -10,9 +10,8 @@ const defaultOptions = { } class Ganache { - async start (options) { - options = Object.assign({}, defaultOptions, options) - + async start (opts) { + const options = { ...defaultOptions, ...opts } const port = options.port this._server = ganache.server(options) diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 6ae17bdcfb46..8f1bc6744b27 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -136,9 +136,8 @@ class Driver { } async switchToWindowWithTitle (title, windowHandles) { - if (!windowHandles) { - windowHandles = await this.driver.getAllWindowHandles() - } + // eslint-disable-next-line no-param-reassign + windowHandles = windowHandles || await this.driver.getAllWindowHandles() for (const handle of windowHandles) { await this.driver.switchTo().window(handle) @@ -158,6 +157,7 @@ class Driver { * @returns {Promise} */ async closeAllWindowHandlesExcept (exceptions, windowHandles) { + // eslint-disable-next-line no-param-reassign windowHandles = windowHandles || await this.driver.getAllWindowHandles() for (const handle of windowHandles) { diff --git a/test/unit/app/controllers/permissions/mocks.js b/test/unit/app/controllers/permissions/mocks.js index 65b311182d79..54f47e5d808e 100644 --- a/test/unit/app/controllers/permissions/mocks.js +++ b/test/unit/app/controllers/permissions/mocks.js @@ -108,6 +108,7 @@ export function getPermissionsMiddleware (permController, origin, extensionId) { return (req, res = {}, next = noop, end) => { return new Promise((resolve, reject) => { + // eslint-disable-next-line no-param-reassign end = end || _end middleware(req, res, next, end) diff --git a/ui/app/components/app/signature-request-original/signature-request-original.component.js b/ui/app/components/app/signature-request-original/signature-request-original.component.js index 29e06bab6f92..31c214e38e6d 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.component.js @@ -247,6 +247,7 @@ export default class SignatureRequestOriginal extends Component { { rows.map(({ name, value }, index) => { if (typeof value === 'boolean') { + // eslint-disable-next-line no-param-reassign value = value.toString() } return ( diff --git a/ui/app/components/ui/check-box/check-box.component.js b/ui/app/components/ui/check-box/check-box.component.js index b1c62433a116..4a745714098f 100644 --- a/ui/app/components/ui/check-box/check-box.component.js +++ b/ui/app/components/ui/check-box/check-box.component.js @@ -12,6 +12,7 @@ export const { CHECKED, INDETERMINATE, UNCHECKED } = CHECKBOX_STATE const CheckBox = ({ className, disabled, id, onClick, checked, title }) => { if (typeof checked === 'boolean') { + // eslint-disable-next-line no-param-reassign checked = checked ? CHECKBOX_STATE.CHECKED : CHECKBOX_STATE.UNCHECKED diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js index 536307ac7e97..441b4e161fb9 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js @@ -258,16 +258,14 @@ export function setFetchingData (isFetching) { } export function updateGasAndCalculate ({ gasLimit, gasPrice }) { - gasLimit = addHexPrefix(gasLimit) - gasPrice = addHexPrefix(gasPrice) return (dispatch, getState) => { const { confirmTransaction: { txData } } = getState() const newTxData = { ...txData, txParams: { ...txData.txParams, - gas: gasLimit, - gasPrice, + gas: addHexPrefix(gasLimit), + gasPrice: addHexPrefix(gasPrice), }, } diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/app/ducks/gas/gas.duck.js index 78b9ef8baa2f..8451c800a7b3 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/app/ducks/gas/gas.duck.js @@ -323,20 +323,22 @@ async function fetchExternalBasicGasAndTimeEstimates (dispatch) { } function extrapolateY ({ higherY, lowerY, higherX, lowerX, xForExtrapolation }) { + /* eslint-disable no-param-reassign */ higherY = new BigNumber(higherY, 10) lowerY = new BigNumber(lowerY, 10) higherX = new BigNumber(higherX, 10) lowerX = new BigNumber(lowerX, 10) xForExtrapolation = new BigNumber(xForExtrapolation, 10) + /* eslint-enable no-param-reassign */ const slope = (higherY.minus(lowerY)).div(higherX.minus(lowerX)) const newTimeEstimate = slope.times(higherX.minus(xForExtrapolation)).minus(higherY).negated() return Number(newTimeEstimate.toPrecision(10)) } -function getRandomArbitrary (min, max) { - min = new BigNumber(min, 10) - max = new BigNumber(max, 10) +function getRandomArbitrary (minStr, maxStr) { + const min = new BigNumber(minStr, 10) + const max = new BigNumber(maxStr, 10) const random = new BigNumber(String(Math.random()), 10) return new BigNumber(random.times(max.minus(min)).plus(min)).toPrecision(10) } diff --git a/ui/app/helpers/utils/switch-direction.js b/ui/app/helpers/utils/switch-direction.js index f0ed42bf1d42..81170f43cbb7 100644 --- a/ui/app/helpers/utils/switch-direction.js +++ b/ui/app/helpers/utils/switch-direction.js @@ -1,10 +1,11 @@ /** * Switch the CSS stylesheet used between 'rtl' and 'ltr' - * @param {('ltr' | 'rtl')} direction - Text direction, either left-to-right (ltr) or right-to-left (rtl) + * @param {('ltr' | 'rtl' | 'auto')} direction - Text direction, either left-to-right (ltr) or right-to-left (rtl) * @return {Promise} */ const switchDirection = async (direction) => { if (direction === 'auto') { + // eslint-disable-next-line no-param-reassign direction = 'ltr' } let updatedLink diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index 28f3dd6f46b7..ffd8aa412cb4 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -241,6 +241,7 @@ export function getRandomFileName () { } export function exportAsFile (filename, data, type = 'text/csv') { + // eslint-disable-next-line no-param-reassign filename = filename || getRandomFileName() // source: https://stackoverflow.com/a/33542499 by Ludovic Feltz const blob = new window.Blob([data], { type }) diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js index df8bf87a2774..392b9af77c73 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js @@ -78,8 +78,8 @@ export default class EnsInput extends Component { updateEnsResolutionError('') } - lookupEnsName = (recipient) => { - recipient = recipient.trim() + lookupEnsName = (ensName) => { + const recipient = ensName.trim() log.info(`ENS attempting to resolve name: ${recipient}`) this.ens.lookup(recipient) diff --git a/ui/app/pages/send/send.utils.js b/ui/app/pages/send/send.utils.js index ca0fdf0441b8..ed01da74cacf 100644 --- a/ui/app/pages/send/send.utils.js +++ b/ui/app/pages/send/send.utils.js @@ -238,6 +238,7 @@ async function estimateGas ({ // if not, fall back to block gasLimit if (!blockGasLimit) { + // eslint-disable-next-line no-param-reassign blockGasLimit = MIN_GAS_LIMIT_HEX } diff --git a/ui/app/pages/send/tests/send-utils.test.js b/ui/app/pages/send/tests/send-utils.test.js index b1f57e49a6f6..1640c80463e0 100644 --- a/ui/app/pages/send/tests/send-utils.test.js +++ b/ui/app/pages/send/tests/send-utils.test.js @@ -10,13 +10,14 @@ import { const stubs = { addCurrencies: sinon.stub().callsFake((a, b) => { + let [a1, b1] = [a, b] if (String(a).match(/^0x.+/u)) { - a = Number(String(a).slice(2)) + a1 = Number(String(a).slice(2)) } if (String(b).match(/^0x.+/u)) { - b = Number(String(b).slice(2)) + b1 = Number(String(b).slice(2)) } - return a + b + return a1 + b1 }), conversionUtil: sinon.stub().callsFake((val) => parseInt(val, 16)), conversionGTE: sinon.stub().callsFake((obj1, obj2) => obj1.value >= obj2.value), diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index c9c4a63dd109..f2b774ada1d4 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -511,8 +511,7 @@ export function decryptMsgInline (decryptedMsgData) { } dispatch(updateMetamaskState(newState)) - decryptedMsgData = newState.unapprovedDecryptMsgs[decryptedMsgData.metamaskId] - return decryptedMsgData + return newState.unapprovedDecryptMsgs[decryptedMsgData.metamaskId] } } From a89b6677a12b844f85a591cc9def1f82a18f72c0 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 17 Aug 2020 13:51:01 -0230 Subject: [PATCH 109/137] Fix import/unambiguous issues (#9233) See [`import/unambiguous`](https://eslint.org/docs/rules/import/unambiguous) for more information. This change enables `import/unambiguous` and fixes the issues raised by the rule. --- .eslintrc.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index 4e74e1209906..176d636661af 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -50,6 +50,7 @@ module.exports = { 'implicit-arrow-linebreak': 'error', 'import/extensions': ['error', 'never', { 'json': 'always' }], 'import/no-extraneous-dependencies': 'error', + 'import/unambiguous': 'error', 'max-statements-per-line': ['error', { 'max': 1 }], 'no-case-declarations': 'error', 'no-constant-condition': 'error', @@ -168,6 +169,20 @@ module.exports = { rules: { 'no-process-exit': 'off', }, + }, { + files: [ + '.eslintrc.js', + 'babel.config.js', + 'nyc.config.js', + 'stylelint.config.js', + 'development/**/*.js', + 'test/e2e/**/*.js', + 'test/env.js', + 'test/setup.js', + ], + parserOptions: { + sourceType: 'script', + }, }], settings: { From 807acaa536fdc233030f742d19649f43ab9b8588 Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Tue, 18 Aug 2020 11:23:54 -0230 Subject: [PATCH 110/137] Add exchange-rate-display component --- .../exchange-rate-display.js | 65 +++++++++++++++++++ .../exchange-rate-display.stories.js | 47 ++++++++++++++ .../token/exchange-rate-display/index.js | 1 + .../token/exchange-rate-display/index.scss | 26 ++++++++ ui/app/pages/token/index.scss | 1 + 5 files changed, 140 insertions(+) create mode 100644 ui/app/pages/token/exchange-rate-display/exchange-rate-display.js create mode 100644 ui/app/pages/token/exchange-rate-display/exchange-rate-display.stories.js create mode 100644 ui/app/pages/token/exchange-rate-display/index.js create mode 100644 ui/app/pages/token/exchange-rate-display/index.scss diff --git a/ui/app/pages/token/exchange-rate-display/exchange-rate-display.js b/ui/app/pages/token/exchange-rate-display/exchange-rate-display.js new file mode 100644 index 000000000000..46e2f4e09109 --- /dev/null +++ b/ui/app/pages/token/exchange-rate-display/exchange-rate-display.js @@ -0,0 +1,65 @@ +import React, { useState } from 'react' +import PropTypes from 'prop-types' +import BigNumber from 'bignumber.js' +import classnames from 'classnames' +import { calcTokenAmount } from '../../../helpers/utils/token-util.js' + +export default function ExchangeRateDisplay ({ + primaryTokenValue, + primaryTokenDecimals = 18, + primaryTokenSymbol, + secondaryTokenValue, + secondaryTokenDecimals = 18, + secondaryTokenSymbol, + arrowColor = 'black', + className, +}) { + const [showPrimaryToSecondary, setShowPrimaryToSecondary] = useState(true) + const [arrowsRotation, setArrowRotation] = useState(0) + + const primaryTokenAmount = calcTokenAmount(primaryTokenValue, primaryTokenDecimals) + const secondaryTokenAmount = calcTokenAmount(secondaryTokenValue, secondaryTokenDecimals) + + const conversionRateFromPrimaryToSecondary = (new BigNumber(secondaryTokenAmount)).div(primaryTokenAmount).round(6).toString(10) + const conversionRateFromSecondaryToPrimary = (new BigNumber(primaryTokenAmount)).div(secondaryTokenAmount).round(6).toString(10) + + const baseSymbol = showPrimaryToSecondary ? primaryTokenSymbol : secondaryTokenSymbol + const ratiodSymbol = showPrimaryToSecondary ? secondaryTokenSymbol : primaryTokenSymbol + const rate = showPrimaryToSecondary ? conversionRateFromPrimaryToSecondary : conversionRateFromSecondaryToPrimary + + return ( +
+ 1 + {baseSymbol} + = + {rate} + {ratiodSymbol} +
{ + setShowPrimaryToSecondary(!showPrimaryToSecondary) + setArrowRotation(arrowsRotation + 360) + }} + style={{ transform: `rotate(${arrowsRotation}deg)` }} + > + + + +
+
+ ) +} + +ExchangeRateDisplay.propTypes = { + primaryTokenValue: PropTypes.string.isRequired, + primaryTokenDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + primaryTokenSymbol: PropTypes.string.isRequired, + secondaryTokenValue: PropTypes.string.isRequired, + secondaryTokenDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + secondaryTokenSymbol: PropTypes.string.isRequired, + className: PropTypes.string, + arrowColor: PropTypes.string, +} diff --git a/ui/app/pages/token/exchange-rate-display/exchange-rate-display.stories.js b/ui/app/pages/token/exchange-rate-display/exchange-rate-display.stories.js new file mode 100644 index 000000000000..d7708dd08d76 --- /dev/null +++ b/ui/app/pages/token/exchange-rate-display/exchange-rate-display.stories.js @@ -0,0 +1,47 @@ +import React from 'react' +import { text, number } from '@storybook/addon-knobs/react' +import ExchangeRateDisplay from './exchange-rate-display' + +export default { + title: 'ExchangeRateDisplay', +} + +export const Default = () => { + return ( + + ) +} + +export const WhiteOnBlue = () => { + return ( +
+ +
+ ) +} diff --git a/ui/app/pages/token/exchange-rate-display/index.js b/ui/app/pages/token/exchange-rate-display/index.js new file mode 100644 index 000000000000..e572fe6986ee --- /dev/null +++ b/ui/app/pages/token/exchange-rate-display/index.js @@ -0,0 +1 @@ +export { default } from './exchange-rate-display' diff --git a/ui/app/pages/token/exchange-rate-display/index.scss b/ui/app/pages/token/exchange-rate-display/index.scss new file mode 100644 index 000000000000..d5c740453f32 --- /dev/null +++ b/ui/app/pages/token/exchange-rate-display/index.scss @@ -0,0 +1,26 @@ +.exchange-rate-display { + @include H6; + + display: flex; + align-items: flex-end; + justify-content: center; + color: $Black-100; + + span { + margin-right: 4px; + } + + &__bold { + font-weight: bold; + } + + &__switch-arrows { + cursor: pointer; + margin-top: 2px; + transition: transform 0.5s ease-in-out; + } +} + +.exchange-rate-display-white { + color: $white; +} diff --git a/ui/app/pages/token/index.scss b/ui/app/pages/token/index.scss index 013ff392875f..01c54828115c 100644 --- a/ui/app/pages/token/index.scss +++ b/ui/app/pages/token/index.scss @@ -1 +1,2 @@ @import 'fee-card/index'; +@import 'exchange-rate-display/index'; From 7bc2de006fe4d350360ca676f88e1d5f8ee57b01 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Tue, 18 Aug 2020 09:06:46 -0500 Subject: [PATCH 111/137] Colocate create-account styles with the create-account page (#9181) Follows previous patterns of moving styles to exist alongside the components that use them. I would like these styles to be updated to use BEM syntax as well but I am holding off for a future PR to improve these styles. --- ui/app/css/itcss/components/index.scss | 1 - .../connect-hardware/index.scss} | 201 ------------------ .../create-account/import-account/index.scss | 100 +++++++++ ui/app/pages/create-account/index.scss | 103 +++++++++ ui/app/pages/index.scss | 1 + 5 files changed, 204 insertions(+), 202 deletions(-) rename ui/app/{css/itcss/components/new-account.scss => pages/create-account/connect-hardware/index.scss} (60%) create mode 100644 ui/app/pages/create-account/import-account/index.scss create mode 100644 ui/app/pages/create-account/index.scss diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 4693a30ed371..5faf5b6df033 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -17,6 +17,5 @@ @import './request-encryption-public-key'; @import './request-decrypt-message'; @import './pages/index'; -@import './new-account'; @import './tooltip'; @import '../../../components/app/index'; diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/pages/create-account/connect-hardware/index.scss similarity index 60% rename from ui/app/css/itcss/components/new-account.scss rename to ui/app/pages/create-account/connect-hardware/index.scss index c7aa38e035ca..887fd7ec9462 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/pages/create-account/connect-hardware/index.scss @@ -1,165 +1,3 @@ -.new-account { - width: 375px; - background-color: #fff; - box-shadow: 0 0 7px 0 rgba(0, 0, 0, 0.08); - z-index: 25; - height: unset; - overflow: auto; - scrollbar-width: none; - - &::-webkit-scrollbar { - display: none; - } - - @media screen and (min-width: 576px) { - position: absolute; - } - - &__header { - display: flex; - flex-flow: column; - border-bottom: 1px solid $geyser; - } - - &__title { - color: $tundora; - font-size: 32px; - font-weight: 500; - line-height: 43px; - margin-top: 22px; - margin-left: 29px; - } - - &__tabs { - margin-left: 22px; - display: flex; - margin-top: 10px; - - &__tab { - height: 54px; - padding: 15px 10px; - color: $dusty-gray; - font-size: 18px; - line-height: 24px; - text-align: center; - cursor: pointer; - } - - &__tab:hover { - color: $black; - border-bottom: none; - } - - &__selected { - color: $primary-blue; - border-bottom: 3px solid $primary-blue; - cursor: initial; - pointer-events: none; - } - } -} - -.new-account-import-disclaimer { - width: 120%; - background-color: #f4f9fc; - display: inline-block; - align-items: center; - padding: 20px 30px 20px; - font-size: 12px; - line-height: 1.5; -} - -.new-account-import-form { - display: flex; - flex-flow: column; - align-items: center; - padding: 0 30px 30px; - - &__select-section { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 29px; - width: 100%; - } - - &__select-label { - color: $scorpion; - font-size: 16px; - line-height: 21px; - } - - &__select { - height: 54px; - width: 210px; - border: 1px solid #d2d8dd; - border-radius: 4px; - background-color: #fff; - display: flex; - align-items: center; - - .Select-control, - .Select-control:hover { - height: 100%; - border: none; - box-shadow: none; - - .Select-value { - display: flex; - align-items: center; - } - } - } - - &__private-key-password-container { - display: flex; - flex-flow: column; - align-items: center; - width: 100%; - } - - &__instruction { - color: $scorpion; - font-size: 16px; - line-height: 21px; - align-self: flex-start; - } - - &__private-key { - display: flex; - flex-flow: column; - align-items: flex-start; - margin-top: 34px; - } - - &__input-password { - height: 54px; - width: 315px; - border: 1px solid $geyser; - border-radius: 4px; - background-color: $white; - margin-top: 16px; - color: $scorpion; - font-size: 16px; - padding: 0 20px; - } - - &__json { - display: flex; - flex-flow: column; - align-items: center; - margin-top: 29px; - width: 100%; - } - - &__buttons { - margin-top: 39px; - display: flex; - width: 100%; - justify-content: space-between; - } -} - .hw-tutorial { width: 375px; border-top: 1px solid #d2d8dd; @@ -503,42 +341,3 @@ cursor: pointer; } } - -.new-account-create-form { - display: flex; - flex-flow: column; - align-items: center; - padding: 30px; - - &__input-label { - color: $scorpion; - font-size: 16px; - line-height: 21px; - align-self: flex-start; - } - - &__input { - height: 54px; - width: 315.84px; - border: 1px solid $geyser; - border-radius: 4px; - background-color: $white; - color: $scorpion; - font-size: 16px; - line-height: 21px; - margin-top: 15px; - padding: 0 20px; - } - - &__buttons { - margin-top: 39px; - display: flex; - width: 100%; - justify-content: space-between; - } - - &__button { - width: 150px; - min-width: initial; - } -} diff --git a/ui/app/pages/create-account/import-account/index.scss b/ui/app/pages/create-account/import-account/index.scss new file mode 100644 index 000000000000..8ad30cc13acb --- /dev/null +++ b/ui/app/pages/create-account/import-account/index.scss @@ -0,0 +1,100 @@ +.new-account-import-disclaimer { + width: 120%; + background-color: #f4f9fc; + display: inline-block; + align-items: center; + padding: 20px 30px 20px; + font-size: 12px; + line-height: 1.5; +} + +.new-account-import-form { + display: flex; + flex-flow: column; + align-items: center; + padding: 0 30px 30px; + + &__select-section { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 29px; + width: 100%; + } + + &__select-label { + color: $scorpion; + font-size: 16px; + line-height: 21px; + } + + &__select { + height: 54px; + width: 210px; + border: 1px solid #d2d8dd; + border-radius: 4px; + background-color: #fff; + display: flex; + align-items: center; + + .Select-control, + .Select-control:hover { + height: 100%; + border: none; + box-shadow: none; + + .Select-value { + display: flex; + align-items: center; + } + } + } + + &__private-key-password-container { + display: flex; + flex-flow: column; + align-items: center; + width: 100%; + } + + &__instruction { + color: $scorpion; + font-size: 16px; + line-height: 21px; + align-self: flex-start; + } + + &__private-key { + display: flex; + flex-flow: column; + align-items: flex-start; + margin-top: 34px; + } + + &__input-password { + height: 54px; + width: 315px; + border: 1px solid $geyser; + border-radius: 4px; + background-color: $white; + margin-top: 16px; + color: $scorpion; + font-size: 16px; + padding: 0 20px; + } + + &__json { + display: flex; + flex-flow: column; + align-items: center; + margin-top: 29px; + width: 100%; + } + + &__buttons { + margin-top: 39px; + display: flex; + width: 100%; + justify-content: space-between; + } +} diff --git a/ui/app/pages/create-account/index.scss b/ui/app/pages/create-account/index.scss new file mode 100644 index 000000000000..d6b1717e07f4 --- /dev/null +++ b/ui/app/pages/create-account/index.scss @@ -0,0 +1,103 @@ +@import 'connect-hardware/index'; +@import 'import-account/index'; + +.new-account { + width: 375px; + background-color: #fff; + box-shadow: 0 0 7px 0 rgba(0, 0, 0, 0.08); + z-index: 25; + height: unset; + overflow: auto; + scrollbar-width: none; + + &::-webkit-scrollbar { + display: none; + } + + @media screen and (min-width: 576px) { + position: absolute; + } + + &__header { + display: flex; + flex-flow: column; + border-bottom: 1px solid $geyser; + } + + &__title { + color: $tundora; + font-size: 32px; + font-weight: 500; + line-height: 43px; + margin-top: 22px; + margin-left: 29px; + } + + &__tabs { + margin-left: 22px; + display: flex; + margin-top: 10px; + + &__tab { + height: 54px; + padding: 15px 10px; + color: $dusty-gray; + font-size: 18px; + line-height: 24px; + text-align: center; + cursor: pointer; + } + + &__tab:hover { + color: $black; + border-bottom: none; + } + + &__selected { + color: $primary-blue; + border-bottom: 3px solid $primary-blue; + cursor: initial; + pointer-events: none; + } + } +} + + +.new-account-create-form { + display: flex; + flex-flow: column; + align-items: center; + padding: 30px; + + &__input-label { + color: $scorpion; + font-size: 16px; + line-height: 21px; + align-self: flex-start; + } + + &__input { + height: 54px; + width: 315.84px; + border: 1px solid $geyser; + border-radius: 4px; + background-color: $white; + color: $scorpion; + font-size: 16px; + line-height: 21px; + margin-top: 15px; + padding: 0 20px; + } + + &__buttons { + margin-top: 39px; + display: flex; + width: 100%; + justify-content: space-between; + } + + &__button { + width: 150px; + min-width: initial; + } +} diff --git a/ui/app/pages/index.scss b/ui/app/pages/index.scss index 8154fc77d043..bef5f4b83f63 100644 --- a/ui/app/pages/index.scss +++ b/ui/app/pages/index.scss @@ -13,3 +13,4 @@ @import 'permissions-connect/index'; @import 'asset/asset'; @import 'token/index'; +@import 'create-account/index'; From 2e565d02b2ed8a85d637240c3114f26260430890 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Tue, 18 Aug 2020 09:09:56 -0500 Subject: [PATCH 112/137] Removes the dropdown menu and colocates old styles with account-menu (#9185) The only place that these .menu styles were being used was the account-menu by way of components/app/dropdowns/menu. Because account-menu is the only place that used these styles I moved them to exist with the account-menu --- .../account-menu/account-menu.component.js | 72 ++++++++++++---- ui/app/components/app/account-menu/index.scss | 61 ++++++++++++++ .../app/dropdowns/components/menu.js | 83 ------------------- .../app/dropdowns/tests/menu.test.js | 69 --------------- ui/app/css/itcss/components/index.scss | 1 - ui/app/css/itcss/components/menu.scss | 63 -------------- 6 files changed, 116 insertions(+), 233 deletions(-) delete mode 100644 ui/app/components/app/dropdowns/components/menu.js delete mode 100644 ui/app/components/app/dropdowns/tests/menu.test.js delete mode 100644 ui/app/css/itcss/components/menu.scss diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index 6409a9cd6cf2..ec3f3f7a9a89 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -3,8 +3,7 @@ import PropTypes from 'prop-types' import { debounce } from 'lodash' import Fuse from 'fuse.js' import InputAdornment from '@material-ui/core/InputAdornment' - -import { Menu, Item, Divider, CloseArea } from '../dropdowns/components/menu' +import classnames from 'classnames' import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import Identicon from '../../ui/identicon' @@ -22,6 +21,42 @@ import { import TextField from '../../ui/text-field' import SearchIcon from '../../ui/search-icon' +export function AccountMenuItem (props) { + const { + icon, + children, + text, + subText, + className, + onClick, + } = props + + const itemClassName = classnames('account-menu__item', className, { + 'account-menu__item--clickable': Boolean(onClick), + }) + return children + ?
{children}
+ : ( +
+ {icon ?
{icon}
: null} + {text ?
{text}
: null} + {subText ?
{subText}
: null} +
+ ) +} + +AccountMenuItem.propTypes = { + icon: PropTypes.node, + children: PropTypes.node, + text: PropTypes.node, + subText: PropTypes.node, + onClick: PropTypes.func, + className: PropTypes.string, +} + export default class AccountMenu extends Component { static contextTypes = { t: PropTypes.func, @@ -106,7 +141,7 @@ export default class AccountMenu extends Component { fullWidth theme="material-white-padded" />, - , +
, ] } @@ -277,13 +312,16 @@ export default class AccountMenu extends Component { history, } = this.props + if (!isAccountMenuOpen) { + return null + } + return ( - - - +
+ { t('myAccounts') } - - + +
{shouldShowAccountsSearch ? this.renderAccountsSearch() : null}
{ this.renderScrollButton() }
- - + { toggleAccountMenu() metricsEvent({ @@ -330,7 +368,7 @@ export default class AccountMenu extends Component { )} text={t('createAccount')} /> - { toggleAccountMenu() metricsEvent({ @@ -350,7 +388,7 @@ export default class AccountMenu extends Component { )} text={t('importAccount')} /> - { toggleAccountMenu() metricsEvent({ @@ -374,8 +412,8 @@ export default class AccountMenu extends Component { )} text={t('connectHardwareWallet')} /> - - + { toggleAccountMenu() history.push(ABOUT_US_ROUTE) @@ -385,7 +423,7 @@ export default class AccountMenu extends Component { } text={t('infoHelp')} /> - { toggleAccountMenu() history.push(SETTINGS_ROUTE) @@ -405,7 +443,7 @@ export default class AccountMenu extends Component { )} text={t('settings')} /> -
+
) } } diff --git a/ui/app/components/app/account-menu/index.scss b/ui/app/components/app/account-menu/index.scss index 8a2a34bc3643..94fb24abe389 100644 --- a/ui/app/components/app/account-menu/index.scss +++ b/ui/app/components/app/account-menu/index.scss @@ -3,6 +3,11 @@ z-index: 100; top: 58px; width: 320px; + border-radius: 4px; + background: rgba($black, 0.8); + box-shadow: rgba($black, 0.15) 0 2px 2px 2px; + min-width: 150px; + color: $white; @media screen and (max-width: 575px) { right: calc(((100vw - 100%) / 2) + 8px); @@ -20,6 +25,62 @@ right: calc((100vw - 65vw) / 2); } + &__item { + padding: 18px; + display: flex; + flex-flow: row wrap; + align-items: center; + position: relative; + z-index: 201; + + @media screen and (max-width: 575px) { + padding: 14px; + } + + &--clickable { + cursor: pointer; + + &:hover { + background-color: rgba($white, 0.05); + } + + &:active { + background-color: rgba($white, 0.1); + } + } + + &__icon { + height: 16px; + width: 16px; + margin-right: 14px; + } + + &__text { + font-size: 16px; + line-height: 21px; + } + + &__subtext { + font-size: 12px; + padding: 5px 0 0 30px; + } + } + + &__divider { + background-color: $scorpion; + width: 100%; + height: 1px; + } + + &__close-area { + position: fixed; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 100; + } + &__icon { margin-left: 1rem; cursor: pointer; diff --git a/ui/app/components/app/dropdowns/components/menu.js b/ui/app/components/app/dropdowns/components/menu.js deleted file mode 100644 index 7861ba534d9e..000000000000 --- a/ui/app/components/app/dropdowns/components/menu.js +++ /dev/null @@ -1,83 +0,0 @@ -import PropTypes from 'prop-types' -import React from 'react' -import classnames from 'classnames' - -/** - * Menu component - * @returns {Component|null} - */ -export function Menu (props) { - const { className, children, isShowing } = props - return isShowing - ?
{children}
- : null -} - -Menu.defaultProps = { - className: '', - isShowing: false, - children: null, -} - -Menu.propTypes = { - className: PropTypes.string, - children: PropTypes.node, - isShowing: PropTypes.bool, -} - -export function Item (props) { - const { - icon, - children, - text, - subText, - className, - onClick, - } = props - - const itemClassName = classnames('menu__item', className, { - 'menu__item--clickable': Boolean(onClick), - }) - return children - ?
{children}
- : ( -
- {icon ?
{icon}
: null} - {text ?
{text}
: null} - {subText ?
{subText}
: null} -
- ) -} - -Item.defaultProps = { - children: null, - icon: null, - text: null, - subText: null, - className: '', - onClick: null, -} - -Item.propTypes = { - icon: PropTypes.node, - children: PropTypes.node, - text: PropTypes.node, - subText: PropTypes.node, - className: PropTypes.string, - onClick: PropTypes.func, -} - -export function Divider () { - return
-} - -export function CloseArea ({ onClick }) { - return
-} - -CloseArea.propTypes = { - onClick: PropTypes.func.isRequired, -} diff --git a/ui/app/components/app/dropdowns/tests/menu.test.js b/ui/app/components/app/dropdowns/tests/menu.test.js deleted file mode 100644 index 2291be41dcfc..000000000000 --- a/ui/app/components/app/dropdowns/tests/menu.test.js +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react' -import assert from 'assert' -import sinon from 'sinon' -import { shallow } from 'enzyme' -import { Menu, Item, Divider, CloseArea } from '../components/menu' - -describe('Dropdown Menu Components', function () { - describe('Menu', function () { - it('adds prop className to menu', function () { - const wrapper = shallow( - , - ) - assert.equal(wrapper.find('.menu').prop('className'), 'menu Test Class') - }) - }) - - describe('Item', function () { - let wrapper - const onClickSpy = sinon.spy() - - beforeEach(function () { - wrapper = shallow( - , - ) - }) - - it('add className based on props', function () { - assert.equal(wrapper.find('.menu__item').prop('className'), 'menu__item test foo1 menu__item--clickable') - }) - - it('simulates onClick called', function () { - wrapper.find('.menu__item').prop('onClick')() - assert.equal(onClickSpy.callCount, 1) - }) - - it('adds icon based on icon props', function () { - assert.equal(wrapper.find('.menu__item__icon').text(), 'test icon') - }) - - it('adds html text based on text props', function () { - assert.equal(wrapper.find('.menu__item__text').text(), 'test text') - }) - }) - - describe('Divider', function () { - it('renders menu divider', function () { - const wrapper = shallow() - assert.equal(wrapper.find('.menu__divider').length, 1) - }) - }) - - describe('CloseArea', function () { - it('simulates click', function () { - const onClickSpy = sinon.spy() - const wrapper = shallow(( - - )) - wrapper.prop('onClick')() - assert.ok(onClickSpy.calledOnce) - }) - }) -}) diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 5faf5b6df033..0d1b928d9611 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -11,7 +11,6 @@ @import './loading-overlay'; // Tx List and Sections -@import './menu'; @import './gas-slider'; @import './simple-dropdown'; @import './request-encryption-public-key'; diff --git a/ui/app/css/itcss/components/menu.scss b/ui/app/css/itcss/components/menu.scss deleted file mode 100644 index f2dfd8ca3799..000000000000 --- a/ui/app/css/itcss/components/menu.scss +++ /dev/null @@ -1,63 +0,0 @@ -.menu { - border-radius: 4px; - background: rgba($black, 0.8); - box-shadow: rgba($black, 0.15) 0 2px 2px 2px; - min-width: 150px; - color: $white; - - &__item { - padding: 18px; - display: flex; - flex-flow: row wrap; - align-items: center; - position: relative; - z-index: 201; - - @media screen and (max-width: 575px) { - padding: 14px; - } - - &--clickable { - cursor: pointer; - - &:hover { - background-color: rgba($white, 0.05); - } - - &:active { - background-color: rgba($white, 0.1); - } - } - - &__icon { - height: 16px; - width: 16px; - margin-right: 14px; - } - - &__text { - font-size: 16px; - line-height: 21px; - } - - &__subtext { - font-size: 12px; - padding: 5px 0 0 30px; - } - } - - &__divider { - background-color: $scorpion; - width: 100%; - height: 1px; - } - - &__close-area { - position: fixed; - width: 100%; - height: 100%; - top: 0; - left: 0; - z-index: 100; - } -} From d5948f1cbeb8cde2ca772afc2bc9ddcba553cfac Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Tue, 18 Aug 2020 09:10:15 -0500 Subject: [PATCH 113/137] colocate confirm-encryption-public-key page styles (#9251) Follows the previously set pattern of colocating styles along side the consuming components. This one was really straight forward and just a reorganization of files and imports. No code changes occurred. --- ui/app/css/itcss/components/index.scss | 1 - .../confirm-encryption-public-key.scss} | 0 ui/app/pages/index.scss | 1 + 3 files changed, 1 insertion(+), 1 deletion(-) rename ui/app/{css/itcss/components/request-encryption-public-key.scss => pages/confirm-encryption-public-key/confirm-encryption-public-key.scss} (100%) diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 0d1b928d9611..10fffc9ac9e8 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -13,7 +13,6 @@ // Tx List and Sections @import './gas-slider'; @import './simple-dropdown'; -@import './request-encryption-public-key'; @import './request-decrypt-message'; @import './pages/index'; @import './tooltip'; diff --git a/ui/app/css/itcss/components/request-encryption-public-key.scss b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.scss similarity index 100% rename from ui/app/css/itcss/components/request-encryption-public-key.scss rename to ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.scss diff --git a/ui/app/pages/index.scss b/ui/app/pages/index.scss index bef5f4b83f63..9c0b3f1b22d5 100644 --- a/ui/app/pages/index.scss +++ b/ui/app/pages/index.scss @@ -4,6 +4,7 @@ @import 'home/index'; @import 'send/send'; @import 'confirm-add-token/index'; +@import 'confirm-encryption-public-key/confirm-encryption-public-key'; @import 'connected-sites/index'; @import 'connected-accounts/index'; @import 'settings/index'; From f7e4e209ef9600822ec3f40ba42ad9a7ba6e95e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20=C5=81ucka?= Date: Tue, 18 Aug 2020 16:10:56 +0200 Subject: [PATCH 114/137] move footer buttons to scrollable area (#9228) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patryk Łucka --- ...onfirm-page-container-content.component.js | 34 ++++++++++++++++ .../confirm-page-container-content/index.scss | 6 +++ .../confirm-page-container.component.js | 40 ++++++++++++------- 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js index e87492832205..0143df6d10aa 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js @@ -4,6 +4,8 @@ import classnames from 'classnames' import { Tabs, Tab } from '../../../ui/tabs' import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.' import ErrorMessage from '../../../ui/error-message' +import { PageContainerFooter } from '../../../ui/page-container' + export default class ConfirmPageContainerContent extends Component { static propTypes = { @@ -22,6 +24,15 @@ export default class ConfirmPageContainerContent extends Component { title: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), titleComponent: PropTypes.node, warning: PropTypes.string, + // Footer + onCancelAll: PropTypes.func, + onCancel: PropTypes.func, + cancelText: PropTypes.string, + onSubmit: PropTypes.func, + submitText: PropTypes.string, + disabled: PropTypes.bool, + unapprovedTxCount: PropTypes.number, + rejectNText: PropTypes.string, } renderContent () { @@ -66,6 +77,14 @@ export default class ConfirmPageContainerContent extends Component { detailsComponent, dataComponent, warning, + onCancelAll, + onCancel, + cancelText, + onSubmit, + submitText, + disabled, + unapprovedTxCount, + rejectNText, } = this.props return ( @@ -104,6 +123,21 @@ export default class ConfirmPageContainerContent extends Component {
) } + + {unapprovedTxCount > 1 && ( +
+ {rejectNText} + + )} + +
) } diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/index.scss b/ui/app/components/app/confirm-page-container/confirm-page-container-content/index.scss index 854327f1214e..cb263ec9cdb9 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/index.scss +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/index.scss @@ -5,6 +5,8 @@ overflow-y: auto; height: 100%; flex: 1; + display: flex; + flex-direction: column; &__error-container { padding: 0 16px 16px 16px; @@ -72,4 +74,8 @@ text-transform: uppercase; margin: 0 8px; } + + .page-container__footer { + margin-top: auto; + } } diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container.component.js index 404e214f4cd9..baf75bbd3ae7 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container.component.js @@ -157,23 +157,35 @@ export default class ConfirmPageContainer extends Component { nonce={nonce} assetImage={assetImage} warning={warning} + onCancelAll={onCancelAll} + onCancel={onCancel} + cancelText={this.context.t('reject')} + onSubmit={onSubmit} + submitText={this.context.t('confirm')} + disabled={disabled} + unapprovedTxCount={unapprovedTxCount} + rejectNText={this.context.t('rejectTxsN', [unapprovedTxCount])} /> ) } - onCancel()} - cancelText={this.context.t('reject')} - onSubmit={() => onSubmit()} - submitText={this.context.t('confirm')} - submitButtonType="confirm" - disabled={disabled} - > - {unapprovedTxCount > 1 && ( - onCancelAll()}> - {this.context.t('rejectTxsN', [unapprovedTxCount])} - - )} - + { + contentComponent && ( + + {unapprovedTxCount > 1 && ( + + {this.context.t('rejectTxsN', [unapprovedTxCount])} + + )} + + ) + }
) } From 27e1189c91ed7224fb4b6ed6c763afb954d9881b Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 18 Aug 2020 12:01:43 -0300 Subject: [PATCH 115/137] Handle non-String web3 property access (#9256) The web3 usage metrics added in #9144 assumed that all web3 properties were strings. When a `Symbol` property is accessed, our `inpage.js` script crashes because the `Symbol` cannot be serialized correctly. A check has been added for non-string property access. The metric event in these cases is set to the string "typeof ", followed by the type of the key. (e.g. `typeof symbol` for a `Symbol` property). Fixes #9234 --- app/scripts/lib/setupWeb3.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/scripts/lib/setupWeb3.js b/app/scripts/lib/setupWeb3.js index b795d292195d..493ac2767763 100644 --- a/app/scripts/lib/setupWeb3.js +++ b/app/scripts/lib/setupWeb3.js @@ -44,9 +44,10 @@ export default function setupWeb3 (log) { } if (shouldLogUsage) { + const name = stringifyKey(key) window.ethereum.request({ method: 'metamask_logInjectedWeb3Usage', - params: [{ action: 'window.web3 get', name: key }], + params: [{ action: 'window.web3 get', name }], }) } @@ -54,11 +55,11 @@ export default function setupWeb3 (log) { return _web3[key] }, set: (_web3, key, value) => { - + const name = stringifyKey(key) if (shouldLogUsage) { window.ethereum.request({ method: 'metamask_logInjectedWeb3Usage', - params: [{ action: 'window.web3 set', name: key }], + params: [{ action: 'window.web3 set', name }], }) } @@ -120,3 +121,15 @@ export default function setupWeb3 (log) { function triggerReset () { global.location.reload() } + +/** + * Returns a "stringified" key. Keys that are already strings are returned + * unchanged, and any non-string values are returned as "typeof ". + * + * @param {any} key - The key to stringify + */ +function stringifyKey (key) { + return typeof key === 'string' + ? key + : `typeof ${typeof key}` +} From d5a539e0e5fe26a0850533909fc88650ee9cc9ba Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Tue, 18 Aug 2020 11:13:55 -0500 Subject: [PATCH 116/137] remove old tooltip component and styles (#9250) The old tooltip component was only used in two places. Removing those usages was simple and straight forward. So, instead of colocating the old tooltip styles with the deprecated tooltip component, I removed all old styles and made tooltip-v2 now simply 'tooltip' and removed the deprecated component. --- .../unconnected-account-alert.js | 2 +- .../app/asset-list-item/asset-list-item.js | 2 +- ...ission-page-container-content.component.js | 2 +- .../selected-account.component.js | 2 +- ...transaction-list-item-details.component.js | 2 +- .../transaction-list-item.component.js | 2 +- .../transaction-status.component.test.js | 2 +- .../transaction-status.component.js | 2 +- .../app/wallet-overview/eth-overview.js | 2 +- .../account-mismatch-warning.component.js | 2 +- .../sender-to-recipient.component.js | 2 +- ui/app/components/ui/tooltip.js | 189 ------------------ ui/app/components/ui/tooltip/index.js | 1 + .../ui/{tooltip-v2.js => tooltip/tooltip.js} | 0 ui/app/css/index.scss | 6 +- ui/app/css/itcss/components/index.scss | 1 - ui/app/css/itcss/components/tooltip.scss | 126 ------------ .../confirm-decrypt-message.component.js | 2 +- .../choose-account.component.js | 2 +- .../pages/settings/alerts-tab/alerts-tab.js | 2 +- .../view-contact/view-contact.component.js | 2 +- 21 files changed, 21 insertions(+), 332 deletions(-) delete mode 100644 ui/app/components/ui/tooltip.js create mode 100644 ui/app/components/ui/tooltip/index.js rename ui/app/components/ui/{tooltip-v2.js => tooltip/tooltip.js} (100%) delete mode 100644 ui/app/css/itcss/components/tooltip.scss diff --git a/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js b/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js index 9d8483648b0b..b56408a484fb 100644 --- a/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js +++ b/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js @@ -19,7 +19,7 @@ import { isExtensionUrl } from '../../../../helpers/utils/util' import Popover from '../../../ui/popover' import Button from '../../../ui/button' import Checkbox from '../../../ui/check-box' -import Tooltip from '../../../ui/tooltip-v2' +import Tooltip from '../../../ui/tooltip' import ConnectedAccountsList from '../../connected-accounts-list' import { useI18nContext } from '../../../../hooks/useI18nContext' diff --git a/ui/app/components/app/asset-list-item/asset-list-item.js b/ui/app/components/app/asset-list-item/asset-list-item.js index 1b7cbe672322..4faafccc69dd 100644 --- a/ui/app/components/app/asset-list-item/asset-list-item.js +++ b/ui/app/components/app/asset-list-item/asset-list-item.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import classnames from 'classnames' import Identicon from '../../ui/identicon' import ListItem from '../../ui/list-item' -import Tooltip from '../../ui/tooltip-v2' +import Tooltip from '../../ui/tooltip' import InfoIcon from '../../ui/icon/info-icon.component' import Button from '../../ui/button' import { useI18nContext } from '../../../hooks/useI18nContext' diff --git a/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js b/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js index 338a60631807..a10f89b9a03e 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js +++ b/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types' import React, { PureComponent } from 'react' import PermissionsConnectHeader from '../../permissions-connect-header' -import Tooltip from '../../../ui/tooltip-v2' +import Tooltip from '../../../ui/tooltip' import CheckBox from '../../../ui/check-box' export default class PermissionPageContainerContent extends PureComponent { diff --git a/ui/app/components/app/selected-account/selected-account.component.js b/ui/app/components/app/selected-account/selected-account.component.js index ab5b56b2455a..ff2dd17c9641 100644 --- a/ui/app/components/app/selected-account/selected-account.component.js +++ b/ui/app/components/app/selected-account/selected-account.component.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import copyToClipboard from 'copy-to-clipboard' import { shortenAddress, checksumAddress } from '../../../helpers/utils/util' -import Tooltip from '../../ui/tooltip-v2' +import Tooltip from '../../ui/tooltip' class SelectedAccount extends Component { state = { diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js index cc5418860c62..cfd2aecfddd9 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js @@ -114,7 +114,7 @@ export default class TransactionListItemDetails extends PureComponent { return cancelDisabled ? ( - +
diff --git a/ui/app/pages/token/exchange-rate-display/index.scss b/ui/app/pages/token/exchange-rate-display/index.scss index d5c740453f32..c416f1f53a50 100644 --- a/ui/app/pages/token/exchange-rate-display/index.scss +++ b/ui/app/pages/token/exchange-rate-display/index.scss @@ -19,8 +19,8 @@ margin-top: 2px; transition: transform 0.5s ease-in-out; } -} -.exchange-rate-display-white { - color: $white; + &--white { + color: $white; + } } From eb653dfb6ed206945e0afd2870d92fc9af148a2f Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 18 Aug 2020 15:45:22 -0230 Subject: [PATCH 119/137] New info tooltip component (#9180) * Add info-tooltip and associated storybook stories * Allow tooltip-v2 to support react-tippy themes * Update info-tooltip to use tooltip-v2 --- ui/app/components/app/index.scss | 1 + ui/app/components/ui/info-tooltip/index.js | 1 + ui/app/components/ui/info-tooltip/index.scss | 39 +++++++++++++++++++ .../ui/info-tooltip/info-tooltip.js | 36 +++++++++++++++++ .../ui/info-tooltip/info-tooltip.stories.js | 35 +++++++++++++++++ ui/app/components/ui/tooltip/tooltip.js | 4 ++ 6 files changed, 116 insertions(+) create mode 100644 ui/app/components/ui/info-tooltip/index.js create mode 100644 ui/app/components/ui/info-tooltip/index.scss create mode 100644 ui/app/components/ui/info-tooltip/info-tooltip.js create mode 100644 ui/app/components/ui/info-tooltip/info-tooltip.stories.js diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/index.scss index d538aa21ce71..5102d1c986fc 100644 --- a/ui/app/components/app/index.scss +++ b/ui/app/components/app/index.scss @@ -64,3 +64,4 @@ @import 'wallet-overview/index'; @import '../ui/account-mismatch-warning/index'; @import '../ui/icon-border/icon-border'; +@import '../ui/info-tooltip/index'; diff --git a/ui/app/components/ui/info-tooltip/index.js b/ui/app/components/ui/info-tooltip/index.js new file mode 100644 index 000000000000..2fe0f2786e78 --- /dev/null +++ b/ui/app/components/ui/info-tooltip/index.js @@ -0,0 +1 @@ +export { default } from './info-tooltip' diff --git a/ui/app/components/ui/info-tooltip/index.scss b/ui/app/components/ui/info-tooltip/index.scss new file mode 100644 index 000000000000..a85f041ce0f1 --- /dev/null +++ b/ui/app/components/ui/info-tooltip/index.scss @@ -0,0 +1,39 @@ +.info-tooltip { + img { + height: 10px; + width: 10px; + } +} + +.tippy-popper[x-placement^=top] .info-theme [x-arrow] { + border-top-color: $white; +} + +.tippy-popper[x-placement^=right] .info-theme [x-arrow] { + border-right-color: $white; +} + +.tippy-popper[x-placement^=left] .info-theme [x-arrow] { + border-left-color: $white; +} + +.tippy-popper[x-placement^=bottom] .info-theme [x-arrow] { + border-bottom-color: $white; +} + +.tippy-tooltip.info-theme { + background: white; + color: black; + box-shadow: 0 0 14px rgba(0, 0, 0, 0.18); + border-radius: 8px; + max-width: 203px; + padding: 16px; + padding-bottom: 15px; + + .tippy-tooltip-content { + @include H8; + + text-align: left; + color: $Grey-500; + } +} diff --git a/ui/app/components/ui/info-tooltip/info-tooltip.js b/ui/app/components/ui/info-tooltip/info-tooltip.js new file mode 100644 index 000000000000..aecba58ef9db --- /dev/null +++ b/ui/app/components/ui/info-tooltip/info-tooltip.js @@ -0,0 +1,36 @@ +import React from 'react' +import PropTypes from 'prop-types' +import Tooltip from '../tooltip' + +const positionArrowClassMap = { + top: 'info-tooltip__top-tooltip-arrow', + bottom: 'info-tooltip__bottom-tooltip-arrow', + left: 'info-tooltip__left-tooltip-arrow', + right: 'info-tooltip__right-tooltip-arrow', +} + +export default function InfoTooltip ({ + contentText = '', + position = '', +}) { + return ( +
+ + + +
+ ) +} + +InfoTooltip.propTypes = { + contentText: PropTypes.string, + position: PropTypes.oneOf(['top', 'left', 'bottom', 'right']), +} diff --git a/ui/app/components/ui/info-tooltip/info-tooltip.stories.js b/ui/app/components/ui/info-tooltip/info-tooltip.stories.js new file mode 100644 index 000000000000..35c1b9fa46f2 --- /dev/null +++ b/ui/app/components/ui/info-tooltip/info-tooltip.stories.js @@ -0,0 +1,35 @@ +import React from 'react' +import InfoTooltip from './info-tooltip' +import { text } from '@storybook/addon-knobs/react' + +export default { + title: 'InfoTooltip', +} + +export const Top = () => ( + +) + +export const Bottom = () => ( + +) + +export const Left = () => ( + +) + +export const Right = () => ( + +) diff --git a/ui/app/components/ui/tooltip/tooltip.js b/ui/app/components/ui/tooltip/tooltip.js index 8941aa1fd725..e6b5726d4287 100644 --- a/ui/app/components/ui/tooltip/tooltip.js +++ b/ui/app/components/ui/tooltip/tooltip.js @@ -16,6 +16,7 @@ export default class Tooltip extends PureComponent { title: null, trigger: 'mouseenter', wrapperClassName: undefined, + theme: '', } static propTypes = { @@ -40,6 +41,7 @@ export default class Tooltip extends PureComponent { trigger: PropTypes.any, wrapperClassName: PropTypes.string, style: PropTypes.object, + theme: PropTypes.string, } render () { @@ -58,6 +60,7 @@ export default class Tooltip extends PureComponent { offset, wrapperClassName, style, + theme, } = this.props if (!title && !html) { @@ -84,6 +87,7 @@ export default class Tooltip extends PureComponent { style={style} title={title} trigger={trigger} + theme={theme} > {children} From b7259e5d6ae1cb9ef0d610629d2239db4110105b Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 18 Aug 2020 16:38:22 -0230 Subject: [PATCH 120/137] Fix radix issues (#9247) See [`radix`](https://eslint.org/docs/rules/radix) for more information. This change enables `radix` and fixes the issues raised by the rule. --- .eslintrc.js | 1 + app/scripts/controllers/preferences.js | 1 + app/scripts/controllers/transactions/index.js | 1 + app/scripts/lib/typed-message-manager.js | 1 + app/scripts/migrations/030.js | 3 +++ app/scripts/platforms/extension.js | 2 +- test/unit/app/controllers/metamask-controller-test.js | 8 ++++---- .../app/controllers/transactions/tx-controller-test.js | 2 +- test/unit/app/typed-message-manager.spec.js | 4 ++-- test/unit/migrations/migrator-test.js | 4 ++-- test/unit/ui/app/actions.spec.js | 6 +++--- ui/app/components/app/menu-droppo.js | 4 ++-- ui/app/pages/send/send.constants.js | 4 ++-- .../networks-tab/network-form/network-form.component.js | 1 + ui/lib/account-link.js | 1 + 15 files changed, 26 insertions(+), 17 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index dd453beb9456..fc0add36e8fa 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -72,6 +72,7 @@ module.exports = { 'no-useless-concat': 'error', 'prefer-rest-params': 'error', 'prefer-spread': 'error', + 'radix': 'error', 'require-unicode-regexp': 'error', /* End v2 rules */ 'arrow-parens': 'error', diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index dee126a8b228..3a871f47322b 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -529,6 +529,7 @@ export default class PreferencesController { } if (url !== 'http://localhost:8545') { let checkedChainId + // eslint-disable-next-line radix if (!!chainId && !Number.isNaN(parseInt(chainId))) { checkedChainId = chainId } diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index ece1d47ad0c1..543603f83f1b 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -133,6 +133,7 @@ export default class TransactionController extends EventEmitter { */ getChainId () { const networkState = this.networkStore.getState() + // eslint-disable-next-line radix const integerChainId = parseInt(networkState) if (Number.isNaN(integerChainId)) { return 0 diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index 38762a97ac5d..b582396d353e 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -165,6 +165,7 @@ export default class TypedMessageManager extends EventEmitter { assert.ok(data.primaryType in data.types, `Primary type of "${data.primaryType}" has no type definition.`) assert.equal(validation.errors.length, 0, 'Signing data must conform to EIP-712 schema. See https://git.io/fNtcx.') const chainId = data.domain.chainId + // eslint-disable-next-line radix const activeChainId = parseInt(this.networkController.getNetworkState()) chainId && assert.equal(chainId, activeChainId, `Provided chainId "${chainId}" must match the active chainId "${activeChainId}"`) break diff --git a/app/scripts/migrations/030.js b/app/scripts/migrations/030.js index 499f8d664cf5..8b6cdeaaa051 100644 --- a/app/scripts/migrations/030.js +++ b/app/scripts/migrations/030.js @@ -28,6 +28,7 @@ function transformState (state) { const frequentRpcListDetail = newState.PreferencesController.frequentRpcListDetail if (frequentRpcListDetail) { frequentRpcListDetail.forEach((rpc, index) => { + // eslint-disable-next-line radix if (!!rpc.chainId && Number.isNaN(parseInt(rpc.chainId))) { delete frequentRpcListDetail[index].chainId } @@ -36,10 +37,12 @@ function transformState (state) { } } if (state.NetworkController) { + // eslint-disable-next-line radix if (newState.NetworkController.network && Number.isNaN(parseInt(newState.NetworkController.network))) { delete newState.NetworkController.network } + // eslint-disable-next-line radix if (newState.NetworkController.provider && newState.NetworkController.provider.chainId && Number.isNaN(parseInt(newState.NetworkController.provider.chainId))) { delete newState.NetworkController.provider.chainId } diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 11340c8cc2ad..d5b025c02f93 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -189,7 +189,7 @@ export default class ExtensionPlatform { this._subscribeToNotificationClicked() - const url = explorerLink(txMeta.hash, parseInt(txMeta.metamaskNetworkId)) + const url = explorerLink(txMeta.hash, txMeta.metamaskNetworkId) const nonce = parseInt(txMeta.txParams.nonce, 16) const title = 'Confirmed transaction' diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index 4abd3316e3db..b69b0c0a9b37 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -694,7 +694,7 @@ describe('MetaMaskController', function () { metamaskMsgs = metamaskController.messageManager.getUnapprovedMsgs() messages = metamaskController.messageManager.messages msgId = Object.keys(metamaskMsgs)[0] - messages[0].msgParams.metamaskId = parseInt(msgId) + messages[0].msgParams.metamaskId = parseInt(msgId, 10) }) it('persists address from msg params', function () { @@ -714,7 +714,7 @@ describe('MetaMaskController', function () { }) it('rejects the message', function () { - const msgIdInt = parseInt(msgId) + const msgIdInt = parseInt(msgId, 10) metamaskController.cancelMessage(msgIdInt, noop) assert.equal(messages[0].status, 'rejected') }) @@ -754,7 +754,7 @@ describe('MetaMaskController', function () { metamaskPersonalMsgs = metamaskController.personalMessageManager.getUnapprovedMsgs() personalMessages = metamaskController.personalMessageManager.messages msgId = Object.keys(metamaskPersonalMsgs)[0] - personalMessages[0].msgParams.metamaskId = parseInt(msgId) + personalMessages[0].msgParams.metamaskId = parseInt(msgId, 10) }) it('errors with no from in msgParams', async function () { @@ -785,7 +785,7 @@ describe('MetaMaskController', function () { }) it('rejects the message', function () { - const msgIdInt = parseInt(msgId) + const msgIdInt = parseInt(msgId, 10) metamaskController.cancelPersonalMessage(msgIdInt, noop) assert.equal(personalMessages[0].status, 'rejected') }) diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index b3649a9b3e4b..01e874ff1aea 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -307,7 +307,7 @@ describe('Transaction Controller', function () { txController.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, noop) const rawTx = await txController.signTransaction('1') const ethTx = new EthTx(ethUtil.toBuffer(rawTx)) - assert.equal(ethTx.getChainId(), parseInt(currentNetworkId)) + assert.equal(ethTx.getChainId(), 42) }) }) diff --git a/test/unit/app/typed-message-manager.spec.js b/test/unit/app/typed-message-manager.spec.js index c69e407a302f..65ba33fbd7af 100644 --- a/test/unit/app/typed-message-manager.spec.js +++ b/test/unit/app/typed-message-manager.spec.js @@ -68,8 +68,8 @@ describe('Typed Message Manager', function () { typedMsgs = typedMessageManager.getUnapprovedMsgs() messages = typedMessageManager.messages msgId = Object.keys(typedMsgs)[0] - messages[0].msgParams.metamaskId = parseInt(msgId) - numberMsgId = parseInt(msgId) + messages[0].msgParams.metamaskId = parseInt(msgId, 10) + numberMsgId = parseInt(msgId, 10) }) it('supports version 1 of signedTypedData', function () { diff --git a/test/unit/migrations/migrator-test.js b/test/unit/migrations/migrator-test.js index c44ce3df7bb7..3cf08c35520a 100644 --- a/test/unit/migrations/migrator-test.js +++ b/test/unit/migrations/migrator-test.js @@ -55,7 +55,7 @@ describe('migrations', function () { } return acc }, []) - .map((num) => parseInt(num)) + .map((num) => parseInt(num, 10)) }) it('should include all migrations', function () { @@ -75,7 +75,7 @@ describe('migrations', function () { } return acc }, []) - .map((num) => parseInt(num)) + .map((num) => parseInt(num, 10)) migrationNumbers.forEach((num) => { if (num >= 33) { diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index af5f56f60f90..49bc191a50f4 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -573,7 +573,7 @@ describe('Actions', function () { metamaskMsgs = metamaskController.messageManager.getUnapprovedMsgs() messages = metamaskController.messageManager.messages msgId = Object.keys(metamaskMsgs)[0] - messages[0].msgParams.metamaskId = parseInt(msgId) + messages[0].msgParams.metamaskId = parseInt(msgId, 10) }) afterEach(function () { @@ -626,7 +626,7 @@ describe('Actions', function () { metamaskMsgs = metamaskController.personalMessageManager.getUnapprovedMsgs() personalMessages = metamaskController.personalMessageManager.messages msgId = Object.keys(metamaskMsgs)[0] - personalMessages[0].msgParams.metamaskId = parseInt(msgId) + personalMessages[0].msgParams.metamaskId = parseInt(msgId, 10) }) afterEach(function () { @@ -714,7 +714,7 @@ describe('Actions', function () { messages = metamaskController.typedMessageManager.getUnapprovedMsgs() typedMessages = metamaskController.typedMessageManager.messages msgId = Object.keys(messages)[0] - typedMessages[0].msgParams.metamaskId = parseInt(msgId) + typedMessages[0].msgParams.metamaskId = parseInt(msgId, 10) }) afterEach(function () { diff --git a/ui/app/components/app/menu-droppo.js b/ui/app/components/app/menu-droppo.js index 79c22d8d8216..fd26a5208c78 100644 --- a/ui/app/components/app/menu-droppo.js +++ b/ui/app/components/app/menu-droppo.js @@ -111,8 +111,8 @@ export default class MenuDroppoComponent extends Component { {this.renderPrimary()} diff --git a/ui/app/pages/send/send.constants.js b/ui/app/pages/send/send.constants.js index 7ef707440db7..c7460fa32e62 100644 --- a/ui/app/pages/send/send.constants.js +++ b/ui/app/pages/send/send.constants.js @@ -2,9 +2,9 @@ import ethUtil from 'ethereumjs-util' import { conversionUtil, multiplyCurrencies } from '../../helpers/utils/conversion-util' const MIN_GAS_PRICE_DEC = '0' -const MIN_GAS_PRICE_HEX = (parseInt(MIN_GAS_PRICE_DEC)).toString(16) +const MIN_GAS_PRICE_HEX = (parseInt(MIN_GAS_PRICE_DEC, 10)).toString(16) const MIN_GAS_LIMIT_DEC = '21000' -const MIN_GAS_LIMIT_HEX = (parseInt(MIN_GAS_LIMIT_DEC)).toString(16) +const MIN_GAS_LIMIT_HEX = (parseInt(MIN_GAS_LIMIT_DEC, 10)).toString(16) const MIN_GAS_PRICE_GWEI = ethUtil.addHexPrefix(conversionUtil(MIN_GAS_PRICE_HEX, { fromDenomination: 'WEI', diff --git a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js index 8f029771f564..3ca23e7f9cee 100644 --- a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js +++ b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js @@ -206,6 +206,7 @@ export default class NetworkForm extends PureComponent { } validateChainId = (chainId) => { + // eslint-disable-next-line radix this.setErrorTo('chainId', !!chainId && Number.isNaN(parseInt(chainId)) ? `${this.context.t('invalidInput')} chainId` : '', diff --git a/ui/lib/account-link.js b/ui/lib/account-link.js index eadecdd3cb25..8427d41addc9 100644 --- a/ui/lib/account-link.js +++ b/ui/lib/account-link.js @@ -3,6 +3,7 @@ export default function getAccountLink (address, network, rpcPrefs) { return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/u, '')}/address/${address}` } + // eslint-disable-next-line radix const net = parseInt(network) switch (net) { case 1: // main net From c1e3c229bc008ddc7ca3507e75845ed73b837e1c Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 18 Aug 2020 16:48:25 -0230 Subject: [PATCH 121/137] Fix import/order issues (#9239) See [`import/order`](https://eslint.org/docs/rules/import/order) for more information. This change enables `import/order` and fixes the issues raised by the rule. --- .eslintrc.js | 1 + app/scripts/background.js | 14 ++++---- app/scripts/contentscript.js | 2 +- app/scripts/controllers/app-state.js | 2 +- app/scripts/controllers/detect-tokens.js | 4 +-- app/scripts/controllers/ens/index.js | 2 +- .../controllers/network/middleware/pending.js | 2 +- app/scripts/controllers/network/network.js | 2 +- app/scripts/controllers/preferences.js | 2 +- app/scripts/controllers/threebox.js | 8 +++-- app/scripts/controllers/transactions/index.js | 10 +++--- .../controllers/transactions/tx-gas-utils.js | 2 +- .../transactions/tx-state-manager.js | 2 +- app/scripts/lib/account-tracker.js | 2 +- app/scripts/lib/decrypt-message-manager.js | 2 +- .../lib/encryption-public-key-manager.js | 2 +- app/scripts/lib/ens-ipfs/resolver.js | 2 +- app/scripts/lib/personal-message-manager.js | 2 +- app/scripts/lib/typed-message-manager.js | 4 +-- app/scripts/lib/util.js | 2 +- app/scripts/metamask-controller.js | 35 +++++++++---------- app/scripts/phishing-detect.js | 2 +- app/scripts/ui.js | 20 +++++------ development/build/etc.js | 2 +- development/build/scripts.js | 2 +- development/build/static.js | 2 +- development/sentry-publish.js | 4 ++- development/sourcemap-validator.js | 2 +- test/e2e/address-book.spec.js | 2 +- test/e2e/ethereum-on.spec.js | 2 +- test/e2e/fixture-server.js | 2 +- test/e2e/from-import-ui.spec.js | 2 +- test/e2e/ganache.js | 2 +- test/e2e/helpers.js | 2 +- test/e2e/incremental-security.spec.js | 2 +- test/e2e/metamask-responsive-ui.spec.js | 2 +- test/e2e/metamask-ui.spec.js | 2 +- test/e2e/permissions.spec.js | 2 +- test/e2e/send-edit.spec.js | 2 +- test/e2e/threebox.spec.js | 2 +- test/e2e/webdriver/driver.js | 2 +- test/e2e/webdriver/index.js | 2 +- test/unit/app/ComposableObservableStore.js | 2 +- .../controllers/metamask-controller-test.js | 4 +-- .../preferences-controller-test.js | 2 +- .../app/controllers/token-rates-controller.js | 2 +- .../transactions/pending-tx-tracker-test.js | 2 +- test/unit/lib/account-link.test.js | 2 +- .../responsive/components/dropdown-test.js | 2 +- .../tests/account-list-item-component.test.js | 2 +- .../account-menu/tests/account-menu.test.js | 4 +-- .../add-token-button.component.js | 2 +- ui/app/components/app/alerts/alerts.js | 2 +- .../app/app-header/app-header.container.js | 2 +- .../app/app-header/tests/app-header.test.js | 2 +- .../app/asset-list-item/asset-list-item.js | 4 +-- .../confirm-detail-row.component.test.js | 4 +-- ...onfirm-page-container-content.component.js | 2 +- .../connected-accounts-list.component.js | 2 +- .../connected-status-indicator.container.js | 2 +- .../recipient-group.component.js | 2 +- .../app/dropdowns/network-dropdown.js | 2 +- .../app/dropdowns/tests/dropdown.test.js | 2 +- .../tests/network-dropdown-icon.test.js | 2 +- .../dropdowns/tests/network-dropdown.test.js | 2 +- .../advanced-gas-input-component.test.js | 2 +- .../advanced-tab-content-component.test.js | 4 +-- .../tests/basic-tab-content-component.test.js | 2 +- .../gas-modal-page-container.container.js | 4 +-- ...gas-modal-page-container-component.test.js | 4 +-- .../gas-price-button-group-component.test.js | 4 +-- .../tests/gas-price-chart.component.test.js | 4 +-- .../app/info-box/tests/info-box.test.js | 2 +- .../loading-network-screen.container.js | 2 +- ui/app/components/app/menu-bar/menu-bar.js | 2 +- .../app/menu-bar/tests/menu-bar.test.js | 2 +- .../tests/modal-content.component.test.js | 2 +- .../components/app/modal/modal.component.js | 2 +- .../app/modal/tests/modal.component.test.js | 2 +- .../account-modal-container.component.js | 2 +- .../add-to-addressbook-modal.container.js | 2 +- ...ncel-transaction-gas-fee.component.test.js | 2 +- .../cancel-transaction.component.js | 2 +- .../cancel-transaction.container.js | 2 +- .../cancel-transaction.component.test.js | 2 +- .../confirm-delete-network.container.js | 2 +- .../tests/confirm-delete-network.test.js | 2 +- .../confirm-remove-account.container.js | 2 +- .../tests/confirm-remove-account.test.js | 2 +- .../confirm-reset-account.container.js | 2 +- .../tests/confirm-reset-account.test.js | 2 +- .../edit-approval-permission.component.js | 4 +-- .../edit-approval-permission.container.js | 2 +- .../loading-network-error.container.js | 2 +- .../metametrics-opt-in-modal.container.js | 2 +- .../tests/metametrics-opt-in-modal.test.js | 2 +- ui/app/components/app/modals/modal.js | 2 +- .../new-account-modal.container.js | 2 +- .../modals/qr-scanner/qr-scanner.container.js | 2 +- .../reject-transactions.container.js | 2 +- .../tests/reject-transactions.test.js | 2 +- .../tests/account-details-modal.test.js | 2 +- .../tests/transaction-confirmed.test.js | 2 +- .../transaction-confirmed.container.js | 2 +- .../permission-page-container.component.js | 2 +- .../permission-page-container.container.js | 2 +- .../selected-account.container.js | 2 +- .../tests/selected-account-component.test.js | 2 +- .../sidebars/tests/sidebars-component.test.js | 2 +- .../signature-request-original.container.js | 2 +- .../signature-request.component.js | 4 +-- .../signature-request.container.js | 2 +- .../tests/signature-request.test.js | 2 +- .../app/tests/signature-request.test.js | 2 +- .../components/app/token-cell/token-cell.js | 2 +- .../app/token-cell/token-cell.test.js | 4 +-- .../components/app/token-list/token-list.js | 2 +- .../transaction-action.component.test.js | 2 +- ...transaction-activity-log.component.test.js | 2 +- .../transaction-activity-log.component.js | 2 +- .../transaction-activity-log.container.js | 2 +- .../transaction-activity-log.util.js | 8 ++--- .../transaction-breakdown.component.test.js | 2 +- ...ransaction-breakdown-row.component.test.js | 2 +- .../transaction-breakdown.component.js | 2 +- .../transaction-breakdown.container.js | 2 +- ...action-list-item-details.component.test.js | 2 +- ...transaction-list-item-details.container.js | 2 +- .../transaction-list-item.component.js | 2 +- .../transaction-status.component.test.js | 2 +- ...erenced-currency-display.component.test.js | 4 +-- ...eferenced-currency-input.component.test.js | 2 +- ...er-preferenced-currency-input.container.js | 2 +- ...-preferenced-token-input.component.test.js | 2 +- .../user-preferenced-token-input.container.js | 2 +- .../app/wallet-overview/eth-overview.js | 2 +- .../app/wallet-overview/token-overview.js | 2 +- .../account-mismatch-warning.component.js | 2 +- ...cccount-mismatch-warning.component.test.js | 2 +- .../components/ui/alert/tests/alert.test.js | 2 +- .../tests/breadcrumbs.component.test.js | 2 +- .../ui/button-group/button-group.stories.js | 4 +-- .../tests/button-group-component.test.js | 2 +- ui/app/components/ui/button/button.stories.js | 2 +- .../ui/card/tests/card.component.test.js | 2 +- .../ui/check-box/check-box.stories.js | 2 +- .../tests/currency-display.component.test.js | 4 +-- .../currency-input.container.js | 2 +- .../tests/currency-input.component.test.js | 2 +- .../ui/dropdown/dropdown.stories.js | 2 +- .../tests/error-message.component.test.js | 2 +- .../tests/hex-to-decimal.component.test.js | 2 +- ui/app/components/ui/icon/icon.stories.js | 2 +- .../ui/identicon/identicon.component.js | 2 +- .../ui/identicon/identicon.stories.js | 2 +- .../tests/identicon.component.test.js | 2 +- .../ui/info-tooltip/info-tooltip.stories.js | 2 +- .../ui/list-item/list-item.stories.js | 2 +- .../ui/list-item/tests/list-item.test.js | 4 +-- ui/app/components/ui/menu/menu.stories.js | 2 +- .../tests/metafox-logo.component.test.js | 2 +- .../page-container-footer.component.test.js | 2 +- .../page-container-header.component.test.js | 2 +- .../components/ui/popover/popover.stories.js | 2 +- .../sender-to-recipient.component.js | 6 ++-- ui/app/components/ui/tabs/tabs.stories.js | 2 +- .../tests/token-input.component.test.js | 2 +- .../ui/token-input/token-input.component.js | 2 +- .../ui/token-input/token-input.container.js | 2 +- .../tests/unit-input.component.test.js | 2 +- .../confirm-transaction.duck.js | 2 +- ui/app/ducks/index.js | 2 +- ui/app/helpers/utils/common.util.test.js | 2 +- ui/app/helpers/utils/confirm-tx.util.js | 2 +- ui/app/helpers/utils/confirm-tx.util.test.js | 2 +- ui/app/helpers/utils/conversion-util.test.js | 2 +- ui/app/helpers/utils/conversions.util.test.js | 2 +- ui/app/helpers/utils/i18n-helper.test.js | 4 +-- ui/app/helpers/utils/token-util.js | 2 +- ui/app/helpers/utils/transactions.util.js | 6 ++-- .../helpers/utils/transactions.util.test.js | 2 +- ui/app/helpers/utils/util.js | 2 +- .../hooks/tests/useCancelTransaction.test.js | 2 +- ui/app/hooks/tests/useCurrencyDisplay.test.js | 2 +- .../hooks/tests/useRetryTransaction.test.js | 2 +- ui/app/hooks/tests/useTokenData.test.js | 2 +- .../hooks/tests/useTokenDisplayValue.test.js | 2 +- .../tests/useTransactionDisplayData.test.js | 2 +- .../tests/useUserPreferencedCurrency.test.js | 4 +-- ui/app/hooks/useTokenDisplayValue.js | 2 +- ui/app/hooks/useTransactionDisplayData.js | 8 ++--- ui/app/hooks/useTransactionTimeRemaining.js | 4 +-- ui/app/hooks/useUserPreferencedCurrency.js | 2 +- ui/app/pages/add-token/add-token.component.js | 4 +-- ui/app/pages/add-token/add-token.container.js | 2 +- .../pages/add-token/tests/add-token.test.js | 2 +- .../confirm-add-suggested-token.container.js | 2 +- .../confirm-add-token.container.js | 2 +- .../pages/confirm-approve/confirm-approve.js | 4 +-- .../confirm-decrypt-message.container.js | 2 +- ...confirm-encryption-public-key.container.js | 2 +- .../confirm-send-token.container.js | 2 +- ...onfirm-token-transaction-base.container.js | 2 +- .../confirm-transaction-base.container.js | 2 +- .../confirm-transaction-switch.container.js | 2 +- ui/app/pages/confirm-transaction/conf-tx.js | 2 +- .../confirm-transaction.component.js | 2 +- .../confirm-transaction.container.js | 2 +- .../connected-accounts.container.js | 2 +- .../connected-sites.container.js | 2 +- .../create-account/connect-hardware/index.js | 4 +-- .../create-account.component.js | 6 ++-- .../create-account/import-account/json.js | 2 +- .../create-account/new-account.container.js | 2 +- .../tests/create-account.test.js | 2 +- .../create-password.component.js | 4 +-- .../import-with-seed-phrase.container.js | 2 +- .../import-with-seed-phrase.component.test.js | 2 +- .../end-of-flow/end-of-flow.container.js | 2 +- .../end-of-flow/tests/end-of-flow.test.js | 2 +- .../tests/first-time-flow-switch.test.js | 2 +- .../first-time-flow.component.js | 14 ++++---- .../first-time-flow.container.js | 2 +- .../metametrics-opt-in.container.js | 2 +- .../tests/metametrics-opt-in.test.js | 2 +- .../confirm-seed-phrase.container.js | 2 +- .../reveal-seed-phrase.container.js | 2 +- .../tests/reveal-seed-phrase.test.js | 2 +- .../seed-phrase/seed-phrase.component.js | 8 ++--- .../confirm-seed-phrase-component.test.js | 2 +- .../select-action/tests/select-action.test.js | 2 +- .../welcome/tests/welcome.test.js | 2 +- ui/app/pages/home/home.container.js | 2 +- ui/app/pages/index.js | 4 +-- .../pages/keychains/tests/reveal-seed.test.js | 2 +- ui/app/pages/lock/lock.container.js | 2 +- ui/app/pages/lock/tests/lock.test.js | 2 +- .../mobile-sync/mobile-sync.container.js | 2 +- .../permissions-connect.container.js | 2 +- ui/app/pages/routes/routes.container.js | 2 +- .../add-recipient/add-recipient.js | 4 +-- .../add-recipient/ens-input.component.js | 4 +-- .../add-recipient/ens-input.container.js | 2 +- .../tests/add-recipient-component.test.js | 2 +- .../amount-max-button.container.js | 4 +-- .../amount-max-button.utils.js | 2 +- .../tests/amount-max-button-component.test.js | 2 +- .../send-amount-row.component.js | 2 +- .../tests/send-amount-row-component.test.js | 2 +- .../send-asset-row.container.js | 2 +- .../send-content/send-content.component.js | 2 +- .../send-content/send-content.container.js | 2 +- .../tests/gas-fee-display.component.test.js | 4 +-- .../send-gas-row/send-gas-row.component.js | 2 +- .../tests/send-gas-row-component.test.js | 2 +- .../send-row-error-message-component.test.js | 2 +- .../tests/send-row-wrapper-component.test.js | 2 +- .../tests/send-content-component.test.js | 2 +- .../send/send-footer/send-footer.container.js | 2 +- .../tests/send-footer-component.test.js | 2 +- .../send/send-header/send-header.container.js | 2 +- .../tests/send-header-component.test.js | 2 +- ui/app/pages/send/send.component.js | 2 +- ui/app/pages/send/send.container.js | 8 ++--- ui/app/pages/send/send.utils.js | 4 +-- .../pages/send/tests/send-component.test.js | 2 +- .../advanced-tab/advanced-tab.container.js | 2 +- .../tests/advanced-tab-component.test.js | 2 +- .../add-contact/add-contact.component.js | 2 +- .../add-contact/add-contact.container.js | 2 +- .../contact-list-tab.component.js | 8 ++--- .../contact-list-tab.container.js | 2 +- .../edit-contact/edit-contact.container.js | 2 +- .../my-accounts/my-accounts.container.js | 2 +- .../view-contact/view-contact.container.js | 2 +- .../networks-tab/networks-tab.component.js | 4 +-- .../networks-tab/networks-tab.container.js | 2 +- .../security-tab/security-tab.container.js | 2 +- .../security-tab/tests/security-tab.test.js | 2 +- .../settings-tab/settings-tab.container.js | 2 +- .../settings-tab/tests/settings-tab.test.js | 2 +- ui/app/pages/settings/settings.component.js | 16 ++++----- ui/app/pages/settings/settings.container.js | 2 +- .../pages/token/fee-card/fee-card.stories.js | 2 +- .../unlock-page/tests/unlock-page.test.js | 2 +- .../unlock-page/unlock-page.component.js | 4 +-- ui/app/selectors/custom-gas.js | 8 ++--- ui/app/selectors/permissions.js | 2 +- ui/app/selectors/selectors.js | 2 +- ui/app/selectors/send.js | 2 +- ui/app/selectors/transactions.js | 2 +- ui/app/store/actions.js | 6 ++-- ui/index.js | 8 ++--- ui/lib/icon-factory.js | 2 +- ui/lib/tx-helper.js | 2 +- 295 files changed, 411 insertions(+), 407 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index fc0add36e8fa..6822190538e1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -50,6 +50,7 @@ module.exports = { 'implicit-arrow-linebreak': 'error', 'import/extensions': ['error', 'never', { 'json': 'always' }], 'import/no-extraneous-dependencies': 'error', + 'import/order': 'error', 'import/unambiguous': 'error', 'max-statements-per-line': ['error', { 'max': 1 }], 'no-case-declarations': 'error', diff --git a/app/scripts/background.js b/app/scripts/background.js index c890441c9050..fcf504107bc2 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -1,11 +1,11 @@ /** * @file The entry point for the web extension singleton process. */ - - // these need to run before anything else +/* eslint-disable import/order */ import './lib/freezeGlobals' import setupFetchDebugging from './lib/setupFetchDebugging' +/* eslint-enable import/order */ setupFetchDebugging() @@ -17,14 +17,14 @@ import pump from 'pump' import debounce from 'debounce-stream' import log from 'loglevel' import extension from 'extensionizer' -import ReadOnlyNetworkStore from './lib/network-store' -import LocalStore from './lib/local-store' import storeTransform from 'obs-store/lib/transform' import asStream from 'obs-store/lib/asStream' -import ExtensionPlatform from './platforms/extension' -import Migrator from './lib/migrator' -import migrations from './migrations' import PortStream from 'extension-port-stream' +import migrations from './migrations' +import Migrator from './lib/migrator' +import ExtensionPlatform from './platforms/extension' +import LocalStore from './lib/local-store' +import ReadOnlyNetworkStore from './lib/network-store' import createStreamSink from './lib/createStreamSink' import NotificationManager from './lib/notification-manager' import MetamaskController from './metamask-controller' diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index e7a983a693b2..8926f439ce84 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -1,5 +1,5 @@ -import pump from 'pump' import querystring from 'querystring' +import pump from 'pump' import LocalMessageDuplexStream from 'post-message-stream' import ObjectMultiplex from 'obj-multiplex' import extension from 'extensionizer' diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index d43c746707eb..e967b462b865 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -1,5 +1,5 @@ -import ObservableStore from 'obs-store' import EventEmitter from 'events' +import ObservableStore from 'obs-store' export default class AppStateController extends EventEmitter { /** diff --git a/app/scripts/controllers/detect-tokens.js b/app/scripts/controllers/detect-tokens.js index 6b7424f98ff1..93b7af2a6c31 100644 --- a/app/scripts/controllers/detect-tokens.js +++ b/app/scripts/controllers/detect-tokens.js @@ -1,11 +1,11 @@ import Web3 from 'web3' import contracts from 'eth-contract-metadata' import { warn } from 'loglevel' +import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi' import { MAINNET } from './network/enums' + // By default, poll every 3 minutes const DEFAULT_INTERVAL = 180 * 1000 -import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi' - const SINGLE_CALL_BALANCES_ADDRESS = '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39' /** * A controller that polls for token exchange diff --git a/app/scripts/controllers/ens/index.js b/app/scripts/controllers/ens/index.js index e44a97ca36ad..d900bf4e6b0b 100644 --- a/app/scripts/controllers/ens/index.js +++ b/app/scripts/controllers/ens/index.js @@ -1,6 +1,6 @@ +import punycode from 'punycode' import ethUtil from 'ethereumjs-util' import ObservableStore from 'obs-store' -import punycode from 'punycode' import log from 'loglevel' import Ens from './ens' diff --git a/app/scripts/controllers/network/middleware/pending.js b/app/scripts/controllers/network/middleware/pending.js index 95e86f3c938d..1a67688c9501 100644 --- a/app/scripts/controllers/network/middleware/pending.js +++ b/app/scripts/controllers/network/middleware/pending.js @@ -1,5 +1,5 @@ -import { formatTxMetaForRpcResult } from '../util' import createAsyncMiddleware from 'json-rpc-engine/src/createAsyncMiddleware' +import { formatTxMetaForRpcResult } from '../util' export function createPendingNonceMiddleware ({ getPendingNonce }) { return createAsyncMiddleware(async (req, res, next) => { diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 90a60f8cd676..7d45cc5a4daa 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -6,11 +6,11 @@ import EthQuery from 'eth-query' import JsonRpcEngine from 'json-rpc-engine' import providerFromEngine from 'eth-json-rpc-middleware/providerFromEngine' import log from 'loglevel' +import { createSwappableProxy, createEventEmitterProxy } from 'swappable-obj-proxy' import createMetamaskMiddleware from './createMetamaskMiddleware' import createInfuraClient from './createInfuraClient' import createJsonRpcClient from './createJsonRpcClient' import createLocalhostClient from './createLocalhostClient' -import { createSwappableProxy, createEventEmitterProxy } from 'swappable-obj-proxy' const networks = { networkList: {} } diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 3a871f47322b..436648af84a9 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -1,7 +1,7 @@ import ObservableStore from 'obs-store' -import { addInternalMethodPrefix } from './permissions' import { normalize as normalizeAddress } from 'eth-sig-util' import { isValidAddress, sha3, bufferToHex } from 'ethereumjs-util' +import { addInternalMethodPrefix } from './permissions' export default class PreferencesController { diff --git a/app/scripts/controllers/threebox.js b/app/scripts/controllers/threebox.js index 726a14ffa358..92e4ae9071b1 100644 --- a/app/scripts/controllers/threebox.js +++ b/app/scripts/controllers/threebox.js @@ -1,16 +1,18 @@ import ObservableStore from 'obs-store' +/* eslint-disable import/order */ const Box = process.env.IN_TEST ? require('../../../development/mock-3box') : require('3box') +/* eslint-enable import/order */ import log from 'loglevel' -import migrations from '../migrations' -import Migrator from '../lib/migrator' import JsonRpcEngine from 'json-rpc-engine' import providerFromEngine from 'eth-json-rpc-middleware/providerFromEngine' -import createMetamaskMiddleware from './network/createMetamaskMiddleware' +import Migrator from '../lib/migrator' +import migrations from '../migrations' import createOriginMiddleware from '../lib/createOriginMiddleware' +import createMetamaskMiddleware from './network/createMetamaskMiddleware' const SYNC_TIMEOUT = 60 * 1000 // one minute diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 543603f83f1b..22ace157e65f 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -9,6 +9,8 @@ import abiDecoder from 'abi-decoder' abiDecoder.addABI(abi) +import NonceTracker from 'nonce-tracker' +import log from 'loglevel' import { TOKEN_METHOD_APPROVE, TOKEN_METHOD_TRANSFER, @@ -18,13 +20,13 @@ import { CONTRACT_INTERACTION_KEY, } from '../../../../ui/app/helpers/constants/transactions' +import cleanErrorStack from '../../lib/cleanErrorStack' +import { hexToBn, bnToHex, BnMultiplyByFraction } from '../../lib/util' +import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys' import TransactionStateManager from './tx-state-manager' import TxGasUtil from './tx-gas-utils' import PendingTransactionTracker from './pending-tx-tracker' -import NonceTracker from 'nonce-tracker' import * as txUtils from './lib/util' -import cleanErrorStack from '../../lib/cleanErrorStack' -import log from 'loglevel' import { TRANSACTION_TYPE_CANCEL, @@ -33,8 +35,6 @@ import { TRANSACTION_STATUS_APPROVED, } from './enums' -import { hexToBn, bnToHex, BnMultiplyByFraction } from '../../lib/util' -import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys' const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. const MAX_MEMSTORE_TX_LIST_SIZE = 100 // Number of transactions (by unique nonces) to keep in memory diff --git a/app/scripts/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js index 1fca82afd69e..0812820665b5 100644 --- a/app/scripts/controllers/transactions/tx-gas-utils.js +++ b/app/scripts/controllers/transactions/tx-gas-utils.js @@ -1,6 +1,6 @@ import EthQuery from 'ethjs-query' -import { hexToBn, BnMultiplyByFraction, bnToHex } from '../../lib/util' import log from 'loglevel' +import { hexToBn, BnMultiplyByFraction, bnToHex } from '../../lib/util' /** * Result of gas analysis, including either a gas estimate for a successful analysis, or diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 89eaf2464054..5239bd60a68a 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -1,8 +1,8 @@ import EventEmitter from 'safe-event-emitter' import ObservableStore from 'obs-store' import log from 'loglevel' -import { generateHistoryEntry, replayHistory, snapshotFromTxMeta } from './lib/tx-state-history-helpers' import createId from '../../lib/random-id' +import { generateHistoryEntry, replayHistory, snapshotFromTxMeta } from './lib/tx-state-history-helpers' import { getFinalStates, normalizeTxParams } from './lib/util' /** TransactionStateManager is responsible for the state of a transaction and diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index 4ce0d692e4c1..f84a9708bcf5 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -14,7 +14,6 @@ import log from 'loglevel' import pify from 'pify' import Web3 from 'web3' import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi' -import { bnToHex } from './util' import { MAINNET_NETWORK_ID, RINKEBY_NETWORK_ID, ROPSTEN_NETWORK_ID, KOVAN_NETWORK_ID } from '../controllers/network/enums' import { @@ -23,6 +22,7 @@ import { SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN, SINGLE_CALL_BALANCES_ADDRESS_KOVAN, } from '../controllers/network/contract-addresses' +import { bnToHex } from './util' export default class AccountTracker { diff --git a/app/scripts/lib/decrypt-message-manager.js b/app/scripts/lib/decrypt-message-manager.js index d6986f52fe34..060a11d9b902 100644 --- a/app/scripts/lib/decrypt-message-manager.js +++ b/app/scripts/lib/decrypt-message-manager.js @@ -2,11 +2,11 @@ import EventEmitter from 'events' import ObservableStore from 'obs-store' import ethUtil from 'ethereumjs-util' import { ethErrors } from 'eth-json-rpc-errors' +import log from 'loglevel' import createId from './random-id' import { MESSAGE_TYPE } from './enums' const hexRe = /^[0-9A-Fa-f]+$/ug -import log from 'loglevel' /** * Represents, and contains data about, an 'eth_decrypt' type decryption request. These are created when a diff --git a/app/scripts/lib/encryption-public-key-manager.js b/app/scripts/lib/encryption-public-key-manager.js index 7550a26e37e5..8d78bf8bd616 100644 --- a/app/scripts/lib/encryption-public-key-manager.js +++ b/app/scripts/lib/encryption-public-key-manager.js @@ -1,8 +1,8 @@ import EventEmitter from 'events' import ObservableStore from 'obs-store' import { ethErrors } from 'eth-json-rpc-errors' -import createId from './random-id' import log from 'loglevel' +import createId from './random-id' import { MESSAGE_TYPE } from './enums' /** diff --git a/app/scripts/lib/ens-ipfs/resolver.js b/app/scripts/lib/ens-ipfs/resolver.js index 475432ba1c94..67acba8c7f34 100644 --- a/app/scripts/lib/ens-ipfs/resolver.js +++ b/app/scripts/lib/ens-ipfs/resolver.js @@ -1,9 +1,9 @@ import namehash from 'eth-ens-namehash' import Eth from 'ethjs-query' import EthContract from 'ethjs-contract' +import contentHash from 'content-hash' import registryAbi from './contracts/registry' import resolverAbi from './contracts/resolver' -import contentHash from 'content-hash' export default async function resolveEnsToIpfsContentId ({ provider, name }) { const eth = new Eth(provider) diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 7770e810658f..7e6ac3c4ec7b 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -2,11 +2,11 @@ import EventEmitter from 'events' import ObservableStore from 'obs-store' import ethUtil from 'ethereumjs-util' import { ethErrors } from 'eth-json-rpc-errors' +import log from 'loglevel' import createId from './random-id' import { MESSAGE_TYPE } from './enums' const hexRe = /^[0-9A-Fa-f]+$/ug -import log from 'loglevel' /** * Represents, and contains data about, an 'personal_sign' type signature request. These are created when a diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index b582396d353e..324ef6936c98 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -1,12 +1,12 @@ import EventEmitter from 'events' -import ObservableStore from 'obs-store' -import createId from './random-id' import assert from 'assert' +import ObservableStore from 'obs-store' import { ethErrors } from 'eth-json-rpc-errors' import sigUtil from 'eth-sig-util' import { isValidAddress } from 'ethereumjs-util' import log from 'loglevel' import jsonschema from 'jsonschema' +import createId from './random-id' import { MESSAGE_TYPE } from './enums' /** diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index ab8653669170..243a00b65103 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -1,6 +1,6 @@ +import assert from 'assert' import extension from 'extensionizer' import ethUtil from 'ethereumjs-util' -import assert from 'assert' import BN from 'bn.js' import { memoize } from 'lodash' diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 8790e4b69c89..656777eb2626 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -10,22 +10,35 @@ import pump from 'pump' import Dnode from 'dnode' import extension from 'extensionizer' import ObservableStore from 'obs-store' -import ComposableObservableStore from './lib/ComposableObservableStore' import asStream from 'obs-store/lib/asStream' -import AccountTracker from './lib/account-tracker' import RpcEngine from 'json-rpc-engine' import { debounce } from 'lodash' import createEngineStream from 'json-rpc-middleware-stream/engineStream' import createFilterMiddleware from 'eth-json-rpc-filters' import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager' +import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware' +import KeyringController from 'eth-keyring-controller' +import { Mutex } from 'await-semaphore' +import ethUtil from 'ethereumjs-util' +import log from 'loglevel' +import TrezorKeyring from 'eth-trezor-keyring' +import LedgerBridgeKeyring from '@metamask/eth-ledger-bridge-keyring' +import EthQuery from 'eth-query' +import nanoid from 'nanoid' +import contractMap from 'eth-contract-metadata' +import { + AddressBookController, + CurrencyRateController, + PhishingController, +} from '@metamask/controllers' +import ComposableObservableStore from './lib/ComposableObservableStore' +import AccountTracker from './lib/account-tracker' import createLoggerMiddleware from './lib/createLoggerMiddleware' import createMethodMiddleware from './lib/createMethodMiddleware' import createOriginMiddleware from './lib/createOriginMiddleware' import createTabIdMiddleware from './lib/createTabIdMiddleware' import createOnboardingMiddleware from './lib/createOnboardingMiddleware' -import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware' import { setupMultiplex } from './lib/stream-utils' -import KeyringController from 'eth-keyring-controller' import EnsController from './controllers/ens' import NetworkController from './controllers/network' import PreferencesController from './controllers/preferences' @@ -48,22 +61,8 @@ import getRestrictedMethods from './controllers/permissions/restrictedMethods' import nodeify from './lib/nodeify' import accountImporter from './account-import-strategies' import selectChainId from './lib/select-chain-id' -import { Mutex } from 'await-semaphore' -import ethUtil from 'ethereumjs-util' - import seedPhraseVerifier from './lib/seed-phrase-verifier' -import log from 'loglevel' -import TrezorKeyring from 'eth-trezor-keyring' -import LedgerBridgeKeyring from '@metamask/eth-ledger-bridge-keyring' -import EthQuery from 'eth-query' -import nanoid from 'nanoid' -import contractMap from 'eth-contract-metadata' -import { - AddressBookController, - CurrencyRateController, - PhishingController, -} from '@metamask/controllers' import backgroundMetaMetricsEvent from './lib/background-metametrics' diff --git a/app/scripts/phishing-detect.js b/app/scripts/phishing-detect.js index f3333fb5e4b3..6311b7004b52 100644 --- a/app/scripts/phishing-detect.js +++ b/app/scripts/phishing-detect.js @@ -1,6 +1,6 @@ import querystring from 'querystring' -import dnode from 'dnode' import { EventEmitter } from 'events' +import dnode from 'dnode' import PortStream from 'extension-port-stream' import extension from 'extensionizer' import { setupMultiplex } from './lib/stream-utils' diff --git a/app/scripts/ui.js b/app/scripts/ui.js index ab05303ef845..7a76b87788b5 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -6,26 +6,26 @@ import './lib/freezeGlobals' import 'abortcontroller-polyfill/dist/polyfill-patch-fetch' import '@formatjs/intl-relativetimeformat/polyfill' +import { EventEmitter } from 'events' import PortStream from 'extension-port-stream' -import { getEnvironmentType } from './lib/util' -import { - ENVIRONMENT_TYPE_FULLSCREEN, - ENVIRONMENT_TYPE_POPUP, -} from './lib/enums' import extension from 'extensionizer' -import ExtensionPlatform from './platforms/extension' -import setupSentry from './lib/setupSentry' -import { EventEmitter } from 'events' import Dnode from 'dnode' import Eth from 'ethjs' import EthQuery from 'eth-query' -import launchMetaMaskUi from '../../ui' import StreamProvider from 'web3-stream-provider' -import { setupMultiplex } from './lib/stream-utils' import log from 'loglevel' +import launchMetaMaskUi from '../../ui' +import { setupMultiplex } from './lib/stream-utils' +import setupSentry from './lib/setupSentry' +import ExtensionPlatform from './platforms/extension' +import { + ENVIRONMENT_TYPE_FULLSCREEN, + ENVIRONMENT_TYPE_POPUP, +} from './lib/enums' +import { getEnvironmentType } from './lib/util' start().catch(log.error) diff --git a/development/build/etc.js b/development/build/etc.js index 0dbce1255659..81b9a17b70b0 100644 --- a/development/build/etc.js +++ b/development/build/etc.js @@ -1,7 +1,7 @@ +const { promises: fs } = require('fs') const gulp = require('gulp') const gulpZip = require('gulp-zip') const del = require('del') -const { promises: fs } = require('fs') const pify = require('pify') const pump = pify(require('pump')) const baseManifest = require('../../app/manifest/_base.json') diff --git a/development/build/scripts.js b/development/build/scripts.js index 0831dbf69829..1f6d2f9549ac 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -17,8 +17,8 @@ const { makeStringTransform } = require('browserify-transform-tools') const conf = require('rc')('metamask', {}) -const { createTask, composeParallel, composeSeries, runInChildProcess } = require('./task') const packageJSON = require('../../package.json') +const { createTask, composeParallel, composeSeries, runInChildProcess } = require('./task') module.exports = createScriptTasks diff --git a/development/build/static.js b/development/build/static.js index 62dbeaa623fc..f32cd5c39027 100644 --- a/development/build/static.js +++ b/development/build/static.js @@ -1,5 +1,5 @@ -const fs = require('fs-extra') const path = require('path') +const fs = require('fs-extra') const watch = require('gulp-watch') const glob = require('fast-glob') diff --git a/development/sentry-publish.js b/development/sentry-publish.js index 650ac37fdf75..80c373608171 100644 --- a/development/sentry-publish.js +++ b/development/sentry-publish.js @@ -1,6 +1,8 @@ #!/usr/bin/env node +const childProcess = require('child_process') const pify = require('pify') -const exec = pify(require('child_process').exec, { multiArgs: true }) + +const exec = pify(childProcess.exec, { multiArgs: true }) const VERSION = require('../dist/chrome/manifest.json').version // eslint-disable-line import/no-unresolved start().catch(console.error) diff --git a/development/sourcemap-validator.js b/development/sourcemap-validator.js index cfb5691388c3..0babb1d56d8d 100644 --- a/development/sourcemap-validator.js +++ b/development/sourcemap-validator.js @@ -1,6 +1,6 @@ const fs = require('fs') -const { SourceMapConsumer } = require('source-map') const path = require('path') +const { SourceMapConsumer } = require('source-map') const pify = require('pify') const fsAsync = pify(fs) diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index fdd0b6b28a32..85cef65de669 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -1,6 +1,7 @@ const assert = require('assert') const { By, until } = require('selenium-webdriver') +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { tinyDelayMs, regularDelayMs, @@ -8,7 +9,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index 8c0426a0d126..5dd15d5fdd87 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -2,13 +2,13 @@ const assert = require('assert') const webdriver = require('selenium-webdriver') const { By, until } = webdriver +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { regularDelayMs, largeDelayMs, } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() diff --git a/test/e2e/fixture-server.js b/test/e2e/fixture-server.js index f923c0a2624f..b96ba8e9a147 100644 --- a/test/e2e/fixture-server.js +++ b/test/e2e/fixture-server.js @@ -1,6 +1,6 @@ const { promises: fs } = require('fs') -const Koa = require('koa') const path = require('path') +const Koa = require('koa') const CURRENT_STATE_KEY = '__CURRENT__' const DEFAULT_STATE_KEY = '__DEFAULT__' diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index b0eab48e498f..d471f41f39c9 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -2,13 +2,13 @@ const assert = require('assert') const webdriver = require('selenium-webdriver') const { By, Key, until } = webdriver +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { regularDelayMs, largeDelayMs, } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() diff --git a/test/e2e/ganache.js b/test/e2e/ganache.js index 29cc085bc335..0cfbadda3661 100644 --- a/test/e2e/ganache.js +++ b/test/e2e/ganache.js @@ -1,5 +1,5 @@ -const ganache = require('ganache-core') const { promisify } = require('util') +const ganache = require('ganache-core') const defaultOptions = { blockTime: 2, diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 1611e66dad09..b06efb3ec973 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -1,8 +1,8 @@ const path = require('path') +const createStaticServer = require('../../development/create-static-server') const Ganache = require('./ganache') const FixtureServer = require('./fixture-server') const { buildWebDriver } = require('./webdriver') -const createStaticServer = require('../../development/create-static-server') const tinyDelayMs = 200 const regularDelayMs = tinyDelayMs * 2 diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 1e1a30349d36..6b76bae129b7 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -2,6 +2,7 @@ const assert = require('assert') const webdriver = require('selenium-webdriver') const { By, until } = webdriver +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { tinyDelayMs, regularDelayMs, @@ -9,7 +10,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index b2d8e9c5ec74..b776299d49e8 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -2,6 +2,7 @@ const assert = require('assert') const webdriver = require('selenium-webdriver') const { By, until } = webdriver +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { tinyDelayMs, regularDelayMs, @@ -9,7 +10,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index bb13c0646eb2..c1c7a953d94c 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -2,6 +2,7 @@ const assert = require('assert') const webdriver = require('selenium-webdriver') const { By, Key, until } = webdriver +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { tinyDelayMs, regularDelayMs, @@ -9,7 +10,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() diff --git a/test/e2e/permissions.spec.js b/test/e2e/permissions.spec.js index cd6cef45318d..87c439c0c186 100644 --- a/test/e2e/permissions.spec.js +++ b/test/e2e/permissions.spec.js @@ -2,13 +2,13 @@ const assert = require('assert') const webdriver = require('selenium-webdriver') const { By, until } = webdriver +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { regularDelayMs, largeDelayMs, } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() diff --git a/test/e2e/send-edit.spec.js b/test/e2e/send-edit.spec.js index ddf9bfde4a9f..4f7e0ae54213 100644 --- a/test/e2e/send-edit.spec.js +++ b/test/e2e/send-edit.spec.js @@ -2,6 +2,7 @@ const assert = require('assert') const webdriver = require('selenium-webdriver') const { By, until } = webdriver +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { tinyDelayMs, regularDelayMs, @@ -9,7 +10,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js index 6d46e037702f..3ba7c060e110 100644 --- a/test/e2e/threebox.spec.js +++ b/test/e2e/threebox.spec.js @@ -3,6 +3,7 @@ const webdriver = require('selenium-webdriver') const getPort = require('get-port') const { By, until } = webdriver +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { tinyDelayMs, regularDelayMs, @@ -10,7 +11,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 8f1bc6744b27..2d855685060b 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -1,6 +1,6 @@ const { promises: fs } = require('fs') -const { until, error: webdriverError } = require('selenium-webdriver') const { strict: assert } = require('assert') +const { until, error: webdriverError } = require('selenium-webdriver') class Driver { /** diff --git a/test/e2e/webdriver/index.js b/test/e2e/webdriver/index.js index 916b7db36860..23e5acd5a295 100644 --- a/test/e2e/webdriver/index.js +++ b/test/e2e/webdriver/index.js @@ -1,8 +1,8 @@ const { Browser } = require('selenium-webdriver') +const fetchMockResponses = require('../../data/fetch-mocks.json') const Driver = require('./driver') const ChromeDriver = require('./chrome') const FirefoxDriver = require('./firefox') -const fetchMockResponses = require('../../data/fetch-mocks.json') async function buildWebDriver ({ responsive, port } = {}) { const browser = process.env.SELENIUM_BROWSER diff --git a/test/unit/app/ComposableObservableStore.js b/test/unit/app/ComposableObservableStore.js index 4eb5f029960e..961be1dc05be 100644 --- a/test/unit/app/ComposableObservableStore.js +++ b/test/unit/app/ComposableObservableStore.js @@ -1,6 +1,6 @@ import assert from 'assert' -import ComposableObservableStore from '../../../app/scripts/lib/ComposableObservableStore' import ObservableStore from 'obs-store' +import ComposableObservableStore from '../../../app/scripts/lib/ComposableObservableStore' describe('ComposableObservableStore', function () { it('should register initial state', function () { diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index b69b0c0a9b37..09000890f276 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -4,10 +4,10 @@ import { cloneDeep } from 'lodash' import nock from 'nock' import ethUtil from 'ethereumjs-util' import { obj as createThoughStream } from 'through2' -import firstTimeState from '../../localhostState' -import createTxMeta from '../../../lib/createTxMeta' import EthQuery from 'eth-query' import proxyquire from 'proxyquire' +import firstTimeState from '../../localhostState' +import createTxMeta from '../../../lib/createTxMeta' const threeBoxSpies = { init: sinon.stub(), diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index 450aa1ab16ec..5c56b0f88a35 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -1,8 +1,8 @@ import assert from 'assert' import ObservableStore from 'obs-store' +import sinon from 'sinon' import PreferencesController from '../../../../app/scripts/controllers/preferences' import { addInternalMethodPrefix } from '../../../../app/scripts/controllers/permissions' -import sinon from 'sinon' describe('preferences controller', function () { let preferencesController diff --git a/test/unit/app/controllers/token-rates-controller.js b/test/unit/app/controllers/token-rates-controller.js index 2bc341d2248b..1f342abe52c4 100644 --- a/test/unit/app/controllers/token-rates-controller.js +++ b/test/unit/app/controllers/token-rates-controller.js @@ -1,7 +1,7 @@ import assert from 'assert' import sinon from 'sinon' -import TokenRatesController from '../../../../app/scripts/controllers/token-rates' import ObservableStore from 'obs-store' +import TokenRatesController from '../../../../app/scripts/controllers/token-rates' describe('TokenRatesController', function () { it('should listen for preferences store updates', function () { diff --git a/test/unit/app/controllers/transactions/pending-tx-tracker-test.js b/test/unit/app/controllers/transactions/pending-tx-tracker-test.js index 000ad263db04..bbdc72551ef7 100644 --- a/test/unit/app/controllers/transactions/pending-tx-tracker-test.js +++ b/test/unit/app/controllers/transactions/pending-tx-tracker-test.js @@ -1,5 +1,5 @@ -import sinon from 'sinon' import { strict as assert } from 'assert' +import sinon from 'sinon' import BN from 'bn.js' import PendingTransactionTracker from '../../../../../app/scripts/controllers/transactions/pending-tx-tracker' diff --git a/test/unit/lib/account-link.test.js b/test/unit/lib/account-link.test.js index a37bdfcb5038..8ba9404e4deb 100644 --- a/test/unit/lib/account-link.test.js +++ b/test/unit/lib/account-link.test.js @@ -1,5 +1,5 @@ -import getAccountLink from '../../../ui/lib/account-link' import assert from 'assert' +import getAccountLink from '../../../ui/lib/account-link' describe('Account link', function () { describe('getAccountLink', function () { diff --git a/test/unit/responsive/components/dropdown-test.js b/test/unit/responsive/components/dropdown-test.js index 76258277f40d..754879aeecbe 100644 --- a/test/unit/responsive/components/dropdown-test.js +++ b/test/unit/responsive/components/dropdown-test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import configureMockStore from 'redux-mock-store' import thunk from 'redux-thunk' import sinon from 'sinon' diff --git a/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js b/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js index ee4ef3c89a02..46630bfcc4c6 100644 --- a/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js +++ b/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import * as utils from '../../../../helpers/utils/util' diff --git a/ui/app/components/app/account-menu/tests/account-menu.test.js b/ui/app/components/app/account-menu/tests/account-menu.test.js index f4e5e10624ae..5dfbd4f1d776 100644 --- a/ui/app/components/app/account-menu/tests/account-menu.test.js +++ b/ui/app/components/app/account-menu/tests/account-menu.test.js @@ -1,10 +1,10 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import configureMockStore from 'redux-mock-store' +import { Provider } from 'react-redux' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' import AccountMenu from '../index' -import { Provider } from 'react-redux' describe('Account Menu', function () { diff --git a/ui/app/components/app/add-token-button/add-token-button.component.js b/ui/app/components/app/add-token-button/add-token-button.component.js index e1a40d56372f..b1d327a2186b 100644 --- a/ui/app/components/app/add-token-button/add-token-button.component.js +++ b/ui/app/components/app/add-token-button/add-token-button.component.js @@ -1,7 +1,7 @@ import React from 'react' +import { useHistory } from 'react-router-dom' import { useMetricEvent } from '../../../hooks/useMetricEvent' import { useI18nContext } from '../../../hooks/useI18nContext' -import { useHistory } from 'react-router-dom' import { ADD_TOKEN_ROUTE } from '../../../helpers/constants/routes' import Button from '../../ui/button' diff --git a/ui/app/components/app/alerts/alerts.js b/ui/app/components/app/alerts/alerts.js index 5d376494cf5f..72bb4910a229 100644 --- a/ui/app/components/app/alerts/alerts.js +++ b/ui/app/components/app/alerts/alerts.js @@ -1,8 +1,8 @@ import React from 'react' import { useSelector } from 'react-redux' -import UnconnectedAccountAlert from './unconnected-account-alert' import { alertIsOpen as unconnectedAccountAlertIsOpen } from '../../../ducks/alerts/unconnected-account' +import UnconnectedAccountAlert from './unconnected-account-alert' const Alerts = () => { const _unconnectedAccountAlertIsOpen = useSelector(unconnectedAccountAlertIsOpen) diff --git a/ui/app/components/app/app-header/app-header.container.js b/ui/app/components/app/app-header/app-header.container.js index 78c425436eee..955f2f320274 100644 --- a/ui/app/components/app/app-header/app-header.container.js +++ b/ui/app/components/app/app-header/app-header.container.js @@ -2,8 +2,8 @@ import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { compose } from 'redux' -import AppHeader from './app-header.component' import * as actions from '../../../store/actions' +import AppHeader from './app-header.component' const mapStateToProps = (state) => { const { appState, metamask } = state diff --git a/ui/app/components/app/app-header/tests/app-header.test.js b/ui/app/components/app/app-header/tests/app-header.test.js index ece8e498c671..e70684a094ae 100644 --- a/ui/app/components/app/app-header/tests/app-header.test.js +++ b/ui/app/components/app/app-header/tests/app-header.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' import MetaFoxLogo from '../../../ui/metafox-logo' diff --git a/ui/app/components/app/asset-list-item/asset-list-item.js b/ui/app/components/app/asset-list-item/asset-list-item.js index 4faafccc69dd..ad644f40035b 100644 --- a/ui/app/components/app/asset-list-item/asset-list-item.js +++ b/ui/app/components/app/asset-list-item/asset-list-item.js @@ -1,6 +1,8 @@ import React, { useMemo } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' +import { useDispatch } from 'react-redux' +import { useHistory } from 'react-router-dom' import Identicon from '../../ui/identicon' import ListItem from '../../ui/list-item' import Tooltip from '../../ui/tooltip' @@ -8,9 +10,7 @@ import InfoIcon from '../../ui/icon/info-icon.component' import Button from '../../ui/button' import { useI18nContext } from '../../../hooks/useI18nContext' import { useMetricEvent } from '../../../hooks/useMetricEvent' -import { useDispatch } from 'react-redux' import { updateSendToken } from '../../../store/actions' -import { useHistory } from 'react-router-dom' import { SEND_ROUTE } from '../../../helpers/constants/routes' diff --git a/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js b/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js index 32e7a2c1d18f..d431033c3740 100644 --- a/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js +++ b/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js @@ -1,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' -import ConfirmDetailRow from '../confirm-detail-row.component' import sinon from 'sinon' +import ConfirmDetailRow from '../confirm-detail-row.component' const propsMethodSpies = { onHeaderClick: sinon.spy(), diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js index 0143df6d10aa..7b88c14d621d 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js @@ -2,9 +2,9 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' import { Tabs, Tab } from '../../../ui/tabs' -import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.' import ErrorMessage from '../../../ui/error-message' import { PageContainerFooter } from '../../../ui/page-container' +import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.' export default class ConfirmPageContainerContent extends Component { diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js b/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js index 5509e9cd4751..854539477eb6 100644 --- a/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js +++ b/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js @@ -1,8 +1,8 @@ import PropTypes from 'prop-types' import React, { PureComponent } from 'react' +import { MenuItem } from '../../ui/menu' import ConnectedAccountsListItem from './connected-accounts-list-item' import ConnectedAccountsListOptions from './connected-accounts-list-options' -import { MenuItem } from '../../ui/menu' export default class ConnectedAccountsList extends PureComponent { static contextTypes = { diff --git a/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js b/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js index 9cdaea0fa685..678e5175e4de 100644 --- a/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js +++ b/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js @@ -1,6 +1,5 @@ import { findKey } from 'lodash' import { connect } from 'react-redux' -import ConnectedStatusIndicator from './connected-status-indicator.component' import { STATUS_CONNECTED, STATUS_CONNECTED_TO_ANOTHER_ACCOUNT, @@ -11,6 +10,7 @@ import { getOriginOfCurrentTab, getSelectedAddress, } from '../../../selectors' +import ConnectedStatusIndicator from './connected-status-indicator.component' const mapStateToProps = (state) => { diff --git a/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js b/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js index 34f3decd56c7..9614b16a92bc 100644 --- a/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js +++ b/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js @@ -1,7 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' -import Identicon from '../../../ui/identicon' import classnames from 'classnames' +import Identicon from '../../../ui/identicon' import { ellipsify } from '../../../../pages/send/send.utils' function addressesEqual (address1, address2) { diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index e578a8b7561e..223c7d566063 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -4,9 +4,9 @@ import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { compose } from 'redux' import * as actions from '../../../store/actions' +import { NETWORKS_ROUTE } from '../../../helpers/constants/routes' import { Dropdown, DropdownMenuItem } from './components/dropdown' import NetworkDropdownIcon from './components/network-dropdown-icon' -import { NETWORKS_ROUTE } from '../../../helpers/constants/routes' // classes from nodes of the toggle element. const notToggleElementClassnames = [ diff --git a/ui/app/components/app/dropdowns/tests/dropdown.test.js b/ui/app/components/app/dropdowns/tests/dropdown.test.js index 3cb5c60054bd..20d73680011c 100644 --- a/ui/app/components/app/dropdowns/tests/dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/dropdown.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' import { DropdownMenuItem } from '../components/dropdown' diff --git a/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js b/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js index 2d1ad59b0108..370ed334f496 100644 --- a/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js +++ b/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import NetworkDropdownIcon from '../components/network-dropdown-icon' diff --git a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js index 04005f19b1da..5aa458ddbe5d 100644 --- a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import configureMockStore from 'redux-mock-store' import thunk from 'redux-thunk' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js index 3bf49aca1b7f..8130a5179a93 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import AdvancedTabContent from '../index' diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js index caa4d1abcf94..4668ced0bc25 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js @@ -1,7 +1,7 @@ -import React from 'react' import assert from 'assert' -import shallow from '../../../../../../../lib/shallow-with-context' +import React from 'react' import sinon from 'sinon' +import shallow from '../../../../../../../lib/shallow-with-context' import AdvancedTabContent from '../advanced-tab-content.component' import GasPriceChart from '../../../gas-price-chart' diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js index 2e2e8dab5670..f8cec8a0cadd 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import shallow from '../../../../../../../lib/shallow-with-context' import BasicTabContent from '../basic-tab-content.component' import GasPriceButtonGroup from '../../../gas-price-button-group' diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js index 3d2b27f7514a..4babca855920 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' -import GasModalPageContainer from './gas-modal-page-container.component' import { captureException } from '@sentry/browser' +import { addHexPrefix } from 'ethereumjs-util' import { hideModal, setGasLimit, @@ -63,8 +63,8 @@ import { calcGasTotal, isBalanceSufficient, } from '../../../../pages/send/send.utils' -import { addHexPrefix } from 'ethereumjs-util' import { calcMaxAmount } from '../../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils' +import GasModalPageContainer from './gas-modal-page-container.component' const mapStateToProps = (state, ownProps) => { const { currentNetworkTxList, send } = state.metamask diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js index 8557fb2ec7cb..9c8b399fe443 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js @@ -1,7 +1,7 @@ -import React from 'react' import assert from 'assert' -import shallow from '../../../../../../lib/shallow-with-context' +import React from 'react' import sinon from 'sinon' +import shallow from '../../../../../../lib/shallow-with-context' import GasModalPageContainer from '../gas-modal-page-container.component' import timeout from '../../../../../../lib/test-timeout' diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js b/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js index 0499f4005165..24a89e165ede 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js +++ b/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js @@ -1,7 +1,7 @@ -import React from 'react' import assert from 'assert' -import shallow from '../../../../../../lib/shallow-with-context' +import React from 'react' import sinon from 'sinon' +import shallow from '../../../../../../lib/shallow-with-context' import GasPriceButtonGroup from '../gas-price-button-group.component' import ButtonGroup from '../../../../ui/button-group' diff --git a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js index ecb5bafa75ec..df8a58b5525a 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js +++ b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js @@ -1,9 +1,9 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import proxyquire from 'proxyquire' import sinon from 'sinon' -import shallow from '../../../../../../lib/shallow-with-context' import * as d3 from 'd3' +import shallow from '../../../../../../lib/shallow-with-context' function timeout (time) { return new Promise((resolve) => { diff --git a/ui/app/components/app/info-box/tests/info-box.test.js b/ui/app/components/app/info-box/tests/info-box.test.js index e04d4ca6737c..6112a25adc7c 100644 --- a/ui/app/components/app/info-box/tests/info-box.test.js +++ b/ui/app/components/app/info-box/tests/info-box.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' diff --git a/ui/app/components/app/loading-network-screen/loading-network-screen.container.js b/ui/app/components/app/loading-network-screen/loading-network-screen.container.js index 2b5456e4d741..9c348dab7e5d 100644 --- a/ui/app/components/app/loading-network-screen/loading-network-screen.container.js +++ b/ui/app/components/app/loading-network-screen/loading-network-screen.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' -import LoadingNetworkScreen from './loading-network-screen.component' import * as actions from '../../../store/actions' import { getNetworkIdentifier } from '../../../selectors' +import LoadingNetworkScreen from './loading-network-screen.component' const mapStateToProps = (state) => { const { diff --git a/ui/app/components/app/menu-bar/menu-bar.js b/ui/app/components/app/menu-bar/menu-bar.js index 282307f598f8..8c4f5c8b93cb 100644 --- a/ui/app/components/app/menu-bar/menu-bar.js +++ b/ui/app/components/app/menu-bar/menu-bar.js @@ -4,13 +4,13 @@ import { useHistory } from 'react-router-dom' import { useSelector } from 'react-redux' import SelectedAccount from '../selected-account' import ConnectedStatusIndicator from '../connected-status-indicator' -import AccountOptionsMenu from './account-options-menu' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' import { CONNECTED_ACCOUNTS_ROUTE } from '../../../helpers/constants/routes' import { useI18nContext } from '../../../hooks/useI18nContext' import { useMetricEvent } from '../../../hooks/useMetricEvent' import { getOriginOfCurrentTab } from '../../../selectors' +import AccountOptionsMenu from './account-options-menu' export default function MenuBar () { const t = useI18nContext() diff --git a/ui/app/components/app/menu-bar/tests/menu-bar.test.js b/ui/app/components/app/menu-bar/tests/menu-bar.test.js index e48b23ae6592..416179d174f1 100644 --- a/ui/app/components/app/menu-bar/tests/menu-bar.test.js +++ b/ui/app/components/app/menu-bar/tests/menu-bar.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { Provider } from 'react-redux' import configureStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' diff --git a/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js b/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js index 4687757974a5..058727cc2977 100644 --- a/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js +++ b/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import ModalContent from '../modal-content.component' diff --git a/ui/app/components/app/modal/modal.component.js b/ui/app/components/app/modal/modal.component.js index 41e4ea694486..5e2ad00f5fa2 100644 --- a/ui/app/components/app/modal/modal.component.js +++ b/ui/app/components/app/modal/modal.component.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' -import Button from '../../ui/button' import classnames from 'classnames' +import Button from '../../ui/button' export default class Modal extends PureComponent { static propTypes = { diff --git a/ui/app/components/app/modal/tests/modal.component.test.js b/ui/app/components/app/modal/tests/modal.component.test.js index dbb61523310f..5dceb4292f8f 100644 --- a/ui/app/components/app/modal/tests/modal.component.test.js +++ b/ui/app/components/app/modal/tests/modal.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { mount, shallow } from 'enzyme' import sinon from 'sinon' import Modal from '../modal.component' diff --git a/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js b/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js index fb8cee58c22d..93f4ae25bac9 100644 --- a/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js +++ b/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types' import React from 'react' -import Identicon from '../../../ui/identicon' import classnames from 'classnames' +import Identicon from '../../../ui/identicon' export default function AccountModalContainer (props, context) { const { diff --git a/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js b/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js index ff3a6ad128ab..176ac86bcdd4 100644 --- a/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js +++ b/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' -import AddToAddressBookModal from './add-to-addressbook-modal.component' import * as actions from '../../../../store/actions' +import AddToAddressBookModal from './add-to-addressbook-modal.component' function mapStateToProps (state) { return { diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js b/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js index ee9bf1d1c398..339d3454456d 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js +++ b/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import CancelTransactionGasFee from '../cancel-transaction-gas-fee.component' import UserPreferencedCurrencyDisplay from '../../../../user-preferenced-currency-display' diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js index 6bab5ec1fbe8..2d01711ff92a 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js +++ b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js @@ -1,8 +1,8 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import Modal from '../../modal' -import CancelTransactionGasFee from './cancel-transaction-gas-fee' import { SUBMITTED_STATUS } from '../../../../helpers/constants/transactions' +import CancelTransactionGasFee from './cancel-transaction-gas-fee' export default class CancelTransaction extends PureComponent { static contextTypes = { diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js index 4e7a8d644127..9645a5df1159 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js +++ b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js @@ -3,9 +3,9 @@ import { compose } from 'redux' import ethUtil from 'ethereumjs-util' import { multiplyCurrencies } from '../../../../helpers/utils/conversion-util' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import CancelTransaction from './cancel-transaction.component' import { showModal, createCancelTransaction } from '../../../../store/actions' import { getHexGasTotal } from '../../../../helpers/utils/confirm-tx.util' +import CancelTransaction from './cancel-transaction.component' const mapStateToProps = (state, ownProps) => { const { metamask } = state diff --git a/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js b/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js index 3ccf6bda0b4e..aaa87c21bada 100644 --- a/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js +++ b/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import CancelTransaction from '../cancel-transaction.component' diff --git a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js index ca8011d0dab8..b6a5c99f5ece 100644 --- a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js +++ b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' import { compose } from 'redux' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import ConfirmDeleteNetwork from './confirm-delete-network.component' import { delRpcTarget } from '../../../../store/actions' +import ConfirmDeleteNetwork from './confirm-delete-network.component' const mapDispatchToProps = (dispatch) => { return { diff --git a/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js index f4f85d589520..e5c2ceeb5f2d 100644 --- a/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js +++ b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import ConfirmDeleteNetwork from '../index' diff --git a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js index 805b9c3e9f1c..c3b54577c966 100644 --- a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js +++ b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' import { compose } from 'redux' -import ConfirmRemoveAccount from './confirm-remove-account.component' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' import { removeAccount } from '../../../../store/actions' +import ConfirmRemoveAccount from './confirm-remove-account.component' const mapStateToProps = (state) => { return { diff --git a/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js index c380e06da8a0..6aa26ba706b9 100644 --- a/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js +++ b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js @@ -1,7 +1,7 @@ +import assert from 'assert' import React from 'react' import PropTypes from 'prop-types' import { Provider } from 'react-redux' -import assert from 'assert' import sinon from 'sinon' import configureStore from 'redux-mock-store' import { mount } from 'enzyme' diff --git a/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js b/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js index 6ef230f41d60..fcbcb9c7ae09 100644 --- a/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js +++ b/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' import { compose } from 'redux' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import ConfirmResetAccount from './confirm-reset-account.component' import { resetAccount } from '../../../../store/actions' +import ConfirmResetAccount from './confirm-reset-account.component' const mapDispatchToProps = (dispatch) => { return { diff --git a/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js index be27151f1fab..d9e05c6a70fd 100644 --- a/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js +++ b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import ConfirmResetAccount from '../index' diff --git a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js index fca21145a65c..9354dad2c2a3 100644 --- a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js +++ b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js @@ -1,12 +1,12 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import log from 'loglevel' +import classnames from 'classnames' +import BigNumber from 'bignumber.js' import Modal from '../../modal' import Identicon from '../../../ui/identicon' import TextField from '../../../ui/text-field' import { calcTokenAmount } from '../../../../helpers/utils/token-util' -import classnames from 'classnames' -import BigNumber from 'bignumber.js' const MAX_UNSIGNED_256_INT = new BigNumber(2).pow(256).minus(1).toString(10) diff --git a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.container.js b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.container.js index 357d70ef2745..671d99cf616a 100644 --- a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.container.js +++ b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' import { compose } from 'redux' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import EditApprovalPermission from './edit-approval-permission.component' import { getSelectedIdentity } from '../../../../selectors' +import EditApprovalPermission from './edit-approval-permission.component' const mapStateToProps = (state) => { const modalStateProps = state.appState.modal.modalState.props || {} diff --git a/ui/app/components/app/modals/loading-network-error/loading-network-error.container.js b/ui/app/components/app/modals/loading-network-error/loading-network-error.container.js index 38ea9b2ab2a2..765cdf9c5704 100644 --- a/ui/app/components/app/modals/loading-network-error/loading-network-error.container.js +++ b/ui/app/components/app/modals/loading-network-error/loading-network-error.container.js @@ -1,4 +1,4 @@ -import LoadingNetworkError from './loading-network-error.component' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' +import LoadingNetworkError from './loading-network-error.component' export default withModalProps(LoadingNetworkError) diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js b/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js index c3e6fd8b3fc3..8cef4a07684f 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js +++ b/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' import { compose } from 'redux' -import MetaMetricsOptInModal from './metametrics-opt-in-modal.component' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' import { setParticipateInMetaMetrics } from '../../../../store/actions' +import MetaMetricsOptInModal from './metametrics-opt-in-modal.component' const mapStateToProps = (_, ownProps) => { const { unapprovedTxCount } = ownProps diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js b/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js index 0d2787ebcdf4..e35549cbeee2 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js +++ b/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import MetaMetricsOptIn from '../index' diff --git a/ui/app/components/app/modals/modal.js b/ui/app/components/app/modals/modal.js index 812090f10f46..d8e6ef214f19 100644 --- a/ui/app/components/app/modals/modal.js +++ b/ui/app/components/app/modals/modal.js @@ -9,6 +9,7 @@ import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' // Modal Components +import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container' import DepositEtherModal from './deposit-ether-modal' import AccountDetailsModal from './account-details-modal' import ExportPrivateKeyModal from './export-private-key-modal' @@ -24,7 +25,6 @@ import CancelTransaction from './cancel-transaction' import FadeModal from './fade-modal' import MetaMetricsOptInModal from './metametrics-opt-in-modal' import RejectTransactions from './reject-transactions' -import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container' import ConfirmDeleteNetwork from './confirm-delete-network' import AddToAddressBookModal from './add-to-addressbook-modal' import EditApprovalPermission from './edit-approval-permission' diff --git a/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js b/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js index adda14d373e0..c787af9a068e 100644 --- a/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js +++ b/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' -import NewAccountModal from './new-account-modal.component' import * as actions from '../../../../store/actions' +import NewAccountModal from './new-account-modal.component' function mapStateToProps (state) { return { diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js index b7fce752386a..fca9d61adae0 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' +import { hideModal, qrCodeDetected } from '../../../../store/actions' import QrScanner from './qr-scanner.component' -import { hideModal, qrCodeDetected } from '../../../../store/actions' const mapDispatchToProps = (dispatch) => { return { diff --git a/ui/app/components/app/modals/reject-transactions/reject-transactions.container.js b/ui/app/components/app/modals/reject-transactions/reject-transactions.container.js index 72eddbc8bb0a..08061a48d6c2 100644 --- a/ui/app/components/app/modals/reject-transactions/reject-transactions.container.js +++ b/ui/app/components/app/modals/reject-transactions/reject-transactions.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' import { compose } from 'redux' -import RejectTransactionsModal from './reject-transactions.component' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' +import RejectTransactionsModal from './reject-transactions.component' const mapStateToProps = (_, ownProps) => { const { unapprovedTxCount } = ownProps diff --git a/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js index d7623604e5be..93f4495dadd6 100644 --- a/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js +++ b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import RejectTransactionsModal from '../index' diff --git a/ui/app/components/app/modals/tests/account-details-modal.test.js b/ui/app/components/app/modals/tests/account-details-modal.test.js index 505b823cd12c..cc2dabdf2d58 100644 --- a/ui/app/components/app/modals/tests/account-details-modal.test.js +++ b/ui/app/components/app/modals/tests/account-details-modal.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' import AccountDetailsModal from '../account-details-modal' diff --git a/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js index 47b653dd7481..ad8ba565d930 100644 --- a/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js +++ b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import TransactionConfirmed from '../index' diff --git a/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.container.js b/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.container.js index 9089ec158441..3109c5e27c81 100644 --- a/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.container.js +++ b/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.container.js @@ -1,4 +1,4 @@ -import TransactionConfirmed from './transaction-confirmed.component' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' +import TransactionConfirmed from './transaction-confirmed.component' export default withModalProps(TransactionConfirmed) diff --git a/ui/app/components/app/permission-page-container/permission-page-container.component.js b/ui/app/components/app/permission-page-container/permission-page-container.component.js index f61c9c0ab724..8598ab976230 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container.component.js +++ b/ui/app/components/app/permission-page-container/permission-page-container.component.js @@ -1,9 +1,9 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' import { isEqual } from 'lodash' -import { PermissionPageContainerContent } from '.' import { PageContainerFooter } from '../../ui/page-container' import PermissionsConnectFooter from '../permissions-connect-footer' +import { PermissionPageContainerContent } from '.' export default class PermissionPageContainer extends Component { diff --git a/ui/app/components/app/permission-page-container/permission-page-container.container.js b/ui/app/components/app/permission-page-container/permission-page-container.container.js index 4a2b7c66028a..bae0f43d9cb1 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container.container.js +++ b/ui/app/components/app/permission-page-container/permission-page-container.container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' -import PermissionPageContainer from './permission-page-container.component' import { getMetaMaskIdentities } from '../../../selectors' +import PermissionPageContainer from './permission-page-container.component' const mapStateToProps = (state, ownProps) => { const { selectedIdentities } = ownProps diff --git a/ui/app/components/app/selected-account/selected-account.container.js b/ui/app/components/app/selected-account/selected-account.container.js index 57a91cd109ee..22e6cc5eff29 100644 --- a/ui/app/components/app/selected-account/selected-account.container.js +++ b/ui/app/components/app/selected-account/selected-account.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' +import { getSelectedIdentity } from '../../../selectors' import SelectedAccount from './selected-account.component' -import { getSelectedIdentity } from '../../../selectors' const mapStateToProps = (state) => { return { diff --git a/ui/app/components/app/selected-account/tests/selected-account-component.test.js b/ui/app/components/app/selected-account/tests/selected-account-component.test.js index 323ead37bfee..943ccf00a68d 100644 --- a/ui/app/components/app/selected-account/tests/selected-account-component.test.js +++ b/ui/app/components/app/selected-account/tests/selected-account-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { render } from 'enzyme' import SelectedAccount from '../selected-account.component' diff --git a/ui/app/components/app/sidebars/tests/sidebars-component.test.js b/ui/app/components/app/sidebars/tests/sidebars-component.test.js index ba92c72a5ab1..ea9958775fdb 100644 --- a/ui/app/components/app/sidebars/tests/sidebars-component.test.js +++ b/ui/app/components/app/sidebars/tests/sidebars-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup' diff --git a/ui/app/components/app/signature-request-original/signature-request-original.container.js b/ui/app/components/app/signature-request-original/signature-request-original.container.js index 63150d38dc0e..8d0a397ef92f 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.container.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.container.js @@ -10,8 +10,8 @@ import { } from '../../../selectors' import { getAccountByAddress } from '../../../helpers/utils/util' import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck' -import SignatureRequestOriginal from './signature-request-original.component' import { getMostRecentOverviewPage } from '../../../ducks/history/history' +import SignatureRequestOriginal from './signature-request-original.component' function mapStateToProps (state) { return { diff --git a/ui/app/components/app/signature-request/signature-request.component.js b/ui/app/components/app/signature-request/signature-request.component.js index a6cbbdbc8f13..d3a42107cdf4 100644 --- a/ui/app/components/app/signature-request/signature-request.component.js +++ b/ui/app/components/app/signature-request/signature-request.component.js @@ -1,11 +1,11 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' +import { getEnvironmentType } from '../../../../../app/scripts/lib/util' +import Identicon from '../../ui/identicon' import Header from './signature-request-header' import Footer from './signature-request-footer' import Message from './signature-request-message' import { ENVIRONMENT_TYPE_NOTIFICATION } from './signature-request.constants' -import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import Identicon from '../../ui/identicon' export default class SignatureRequest extends PureComponent { static propTypes = { diff --git a/ui/app/components/app/signature-request/signature-request.container.js b/ui/app/components/app/signature-request/signature-request.container.js index 10976e66b5e2..93974190486a 100644 --- a/ui/app/components/app/signature-request/signature-request.container.js +++ b/ui/app/components/app/signature-request/signature-request.container.js @@ -1,11 +1,11 @@ import { connect } from 'react-redux' -import SignatureRequest from './signature-request.component' import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck' import { accountsWithSendEtherInfoSelector, } from '../../../selectors' import { getAccountByAddress } from '../../../helpers/utils/util' import { MESSAGE_TYPE } from '../../../../../app/scripts/lib/enums' +import SignatureRequest from './signature-request.component' function mapStateToProps (state) { return { diff --git a/ui/app/components/app/signature-request/tests/signature-request.test.js b/ui/app/components/app/signature-request/tests/signature-request.test.js index 8956a957da90..ec1ecfd69b6b 100644 --- a/ui/app/components/app/signature-request/tests/signature-request.test.js +++ b/ui/app/components/app/signature-request/tests/signature-request.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import shallow from '../../../../../lib/shallow-with-context' import SignatureRequest from '../signature-request.component' diff --git a/ui/app/components/app/tests/signature-request.test.js b/ui/app/components/app/tests/signature-request.test.js index 21612e5a0738..9efd70973036 100644 --- a/ui/app/components/app/tests/signature-request.test.js +++ b/ui/app/components/app/tests/signature-request.test.js @@ -1,6 +1,6 @@ +import assert from 'assert' import React from 'react' import { Provider } from 'react-redux' -import assert from 'assert' import sinon from 'sinon' import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../test/lib/render-helpers' diff --git a/ui/app/components/app/token-cell/token-cell.js b/ui/app/components/app/token-cell/token-cell.js index e5f6a5d55944..89843b85057d 100644 --- a/ui/app/components/app/token-cell/token-cell.js +++ b/ui/app/components/app/token-cell/token-cell.js @@ -1,8 +1,8 @@ import classnames from 'classnames' import PropTypes from 'prop-types' import React from 'react' -import AssetListItem from '../asset-list-item' import { useSelector } from 'react-redux' +import AssetListItem from '../asset-list-item' import { getSelectedAddress } from '../../../selectors' import { useI18nContext } from '../../../hooks/useI18nContext' import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount' diff --git a/ui/app/components/app/token-cell/token-cell.test.js b/ui/app/components/app/token-cell/token-cell.test.js index b01f581cf0a0..65a238b6959a 100644 --- a/ui/app/components/app/token-cell/token-cell.test.js +++ b/ui/app/components/app/token-cell/token-cell.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import thunk from 'redux-thunk' import { Provider } from 'react-redux' import configureMockStore from 'redux-mock-store' @@ -7,8 +7,8 @@ import { mount } from 'enzyme' import sinon from 'sinon' import { MemoryRouter } from 'react-router-dom' -import TokenCell from '.' import Identicon from '../../ui/identicon' +import TokenCell from '.' describe('Token Cell', function () { let wrapper diff --git a/ui/app/components/app/token-list/token-list.js b/ui/app/components/app/token-list/token-list.js index 591dbe33af12..b71e6930bcd9 100644 --- a/ui/app/components/app/token-list/token-list.js +++ b/ui/app/components/app/token-list/token-list.js @@ -2,10 +2,10 @@ import React from 'react' import PropTypes from 'prop-types' import { isEqual } from 'lodash' +import { useSelector } from 'react-redux' import TokenCell from '../token-cell' import { useI18nContext } from '../../../hooks/useI18nContext' import { useTokenTracker } from '../../../hooks/useTokenTracker' -import { useSelector } from 'react-redux' import { getAssetImages } from '../../../selectors' import { getTokens } from '../../../ducks/metamask/metamask' diff --git a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js index 1d0263cb0c26..d51c7001d378 100644 --- a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js +++ b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import TransactionAction from '../transaction-action.component' diff --git a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js index 99947104cd03..9b3c3979282f 100644 --- a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js +++ b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import TransactionActivityLog from '../transaction-activity-log.component' diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js index 865320a45393..9d071b43240b 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js @@ -3,9 +3,9 @@ import PropTypes from 'prop-types' import classnames from 'classnames' import { getEthConversionFromWeiHex, getValueFromWeiHex } from '../../../helpers/utils/conversions.util' import { formatDate } from '../../../helpers/utils/util' +import { getEtherscanNetworkPrefix } from '../../../../lib/etherscan-prefix-for-network' import TransactionActivityLogIcon from './transaction-activity-log-icon' import { CONFIRMED_STATUS } from './transaction-activity-log.constants' -import { getEtherscanNetworkPrefix } from '../../../../lib/etherscan-prefix-for-network' export default class TransactionActivityLog extends PureComponent { static contextTypes = { diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js index 7e01e8745494..df7a3dc20fbf 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' import { findLastIndex } from 'lodash' -import TransactionActivityLog from './transaction-activity-log.component' import { conversionRateSelector, getNativeCurrency } from '../../../selectors' +import TransactionActivityLog from './transaction-activity-log.component' import { combineTransactionHistories } from './transaction-activity-log.util' import { TRANSACTION_RESUBMITTED_EVENT, diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js index b01c661453e3..ba45b9be03b9 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js @@ -8,6 +8,10 @@ const GAS_LIMIT_PATH = '/txParams/gas' // op constants const REPLACE_OP = 'replace' +import { + TRANSACTION_TYPE_CANCEL, + TRANSACTION_TYPE_RETRY, +} from '../../../../../app/scripts/controllers/transactions/enums' import { // event constants TRANSACTION_CREATED_EVENT, @@ -25,10 +29,6 @@ import { DROPPED_STATUS, } from './transaction-activity-log.constants' -import { - TRANSACTION_TYPE_CANCEL, - TRANSACTION_TYPE_RETRY, -} from '../../../../../app/scripts/controllers/transactions/enums' const eventPathsHash = { [STATUS_PATH]: true, diff --git a/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js b/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js index bd4c3332aa91..608ba34b9ae8 100644 --- a/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js +++ b/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import TransactionBreakdown from '../transaction-breakdown.component' diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js index 752d8b6afd76..f25773e58fd2 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import TransactionBreakdownRow from '../transaction-breakdown-row.component' import Button from '../../../../ui/button' diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js index a534ae1a6fcd..7e99f02c32a8 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js @@ -1,11 +1,11 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import TransactionBreakdownRow from './transaction-breakdown-row' import CurrencyDisplay from '../../ui/currency-display' import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display' import HexToDecimal from '../../ui/hex-to-decimal' import { GWEI, PRIMARY, SECONDARY } from '../../../helpers/constants/common' +import TransactionBreakdownRow from './transaction-breakdown-row' export default class TransactionBreakdown extends PureComponent { static contextTypes = { diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js index bfc23913c881..e52b0bce0301 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' -import TransactionBreakdown from './transaction-breakdown.component' import { getIsMainnet, getNativeCurrency, getPreferences } from '../../../selectors' import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util' import { sumHexes } from '../../../helpers/utils/transactions.util' +import TransactionBreakdown from './transaction-breakdown.component' const mapStateToProps = (state, ownProps) => { const { transaction } = ownProps diff --git a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js index f0e3edf4df1f..d647362f5c4d 100644 --- a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js +++ b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import TransactionListItemDetails from '../transaction-list-item-details.component' import Button from '../../../ui/button' diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js index c9d48bf7e8a1..6bea44d2a15e 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' -import TransactionListItemDetails from './transaction-list-item-details.component' import { checksumAddress } from '../../../helpers/utils/util' import { tryReverseResolveAddress } from '../../../store/actions' import { getAddressBook, getRpcPrefsForCurrentProvider } from '../../../selectors' +import TransactionListItemDetails from './transaction-list-item-details.component' const mapStateToProps = (state, ownProps) => { const { metamask } = state diff --git a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js index 784e49907e91..eb03d3003708 100644 --- a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js +++ b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js @@ -1,6 +1,7 @@ import React, { useMemo, useState, useCallback } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' +import { useHistory } from 'react-router-dom' import ListItem from '../../ui/list-item' import { useTransactionDisplayData } from '../../../hooks/useTransactionDisplayData' import Preloader from '../../ui/icon/preloader' @@ -10,7 +11,6 @@ import { useRetryTransaction } from '../../../hooks/useRetryTransaction' import Button from '../../ui/button' import Tooltip from '../../ui/tooltip' import TransactionListItemDetails from '../transaction-list-item-details' -import { useHistory } from 'react-router-dom' import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes' import { TRANSACTION_CATEGORY_SIGNATURE_REQUEST, diff --git a/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js b/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js index 20100cc463cd..51d02b4511c6 100644 --- a/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js +++ b/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { mount } from 'enzyme' import sinon from 'sinon' import * as i18nHook from '../../../../hooks/useI18nContext' diff --git a/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js b/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js index c2619ad67cf7..c5c903fd9cb6 100644 --- a/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js +++ b/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js @@ -1,11 +1,11 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' +import sinon from 'sinon' import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display.component' import CurrencyDisplay from '../../../ui/currency-display' import * as currencyHook from '../../../../hooks/useCurrencyDisplay' import * as currencyPrefHook from '../../../../hooks/useUserPreferencedCurrency' -import sinon from 'sinon' describe('UserPreferencedCurrencyDisplay Component', function () { diff --git a/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js b/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js index 21105ef7e5d9..3241008e439f 100644 --- a/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js +++ b/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import UserPreferencedCurrencyInput from '../user-preferenced-currency-input.component' import CurrencyInput from '../../../ui/currency-input' diff --git a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js b/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js index 808f9340e03b..2cce58027909 100644 --- a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js +++ b/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' -import UserPreferencedCurrencyInput from './user-preferenced-currency-input.component' import { getPreferences } from '../../../selectors' +import UserPreferencedCurrencyInput from './user-preferenced-currency-input.component' const mapStateToProps = (state) => { const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state) diff --git a/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js b/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js index e0a4f1ea290e..ce882f6e5a6f 100644 --- a/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js +++ b/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import UserPreferencedTokenInput from '../user-preferenced-token-input.component' import TokenInput from '../../../ui/token-input' diff --git a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js b/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js index 141ad24b2317..daddded7f7ca 100644 --- a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js +++ b/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' import PropTypes from 'prop-types' -import UserPreferencedTokenInput from './user-preferenced-token-input.component' import { getPreferences } from '../../../selectors' +import UserPreferencedTokenInput from './user-preferenced-token-input.component' const mapStateToProps = (state) => { const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state) diff --git a/ui/app/components/app/wallet-overview/eth-overview.js b/ui/app/components/app/wallet-overview/eth-overview.js index c90e599f57cc..a98904f245da 100644 --- a/ui/app/components/app/wallet-overview/eth-overview.js +++ b/ui/app/components/app/wallet-overview/eth-overview.js @@ -7,7 +7,6 @@ import { useHistory } from 'react-router-dom' import Button from '../../ui/button' import Identicon from '../../ui/identicon' import { I18nContext } from '../../../contexts/i18n' -import WalletOverview from './wallet-overview' import { SEND_ROUTE } from '../../../helpers/constants/routes' import { useMetricEvent } from '../../../hooks/useMetricEvent' import Tooltip from '../../ui/tooltip' @@ -16,6 +15,7 @@ import { PRIMARY, SECONDARY } from '../../../helpers/constants/common' import { showModal } from '../../../store/actions' import { isBalanceCached, getSelectedAccount, getShouldShowFiat } from '../../../selectors/selectors' import PaperAirplane from '../../ui/icon/paper-airplane-icon' +import WalletOverview from './wallet-overview' const EthOverview = ({ className }) => { const dispatch = useDispatch() diff --git a/ui/app/components/app/wallet-overview/token-overview.js b/ui/app/components/app/wallet-overview/token-overview.js index e1e0df2b6ae4..ea7e870f969b 100644 --- a/ui/app/components/app/wallet-overview/token-overview.js +++ b/ui/app/components/app/wallet-overview/token-overview.js @@ -7,7 +7,6 @@ import Button from '../../ui/button' import Identicon from '../../ui/identicon' import CurrencyDisplay from '../../ui/currency-display' import { I18nContext } from '../../../contexts/i18n' -import WalletOverview from './wallet-overview' import { SEND_ROUTE } from '../../../helpers/constants/routes' import { useMetricEvent } from '../../../hooks/useMetricEvent' import { useTokenTracker } from '../../../hooks/useTokenTracker' @@ -15,6 +14,7 @@ import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount' import { getAssetImages } from '../../../selectors/selectors' import { updateSendToken } from '../../../store/actions' import PaperAirplane from '../../ui/icon/paper-airplane-icon' +import WalletOverview from './wallet-overview' const TokenOverview = ({ className, token }) => { const dispatch = useDispatch() diff --git a/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js b/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js index ff53cd88fa69..fc20a9900e07 100644 --- a/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js +++ b/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js @@ -1,7 +1,7 @@ import React from 'react' -import Tooltip from '../tooltip' import { useSelector } from 'react-redux' import PropTypes from 'prop-types' +import Tooltip from '../tooltip' import { getSelectedAccount } from '../../../selectors' import InfoIcon from '../icon/info-icon.component' import { useI18nContext } from '../../../hooks/useI18nContext' diff --git a/ui/app/components/ui/account-mismatch-warning/tests/acccount-mismatch-warning.component.test.js b/ui/app/components/ui/account-mismatch-warning/tests/acccount-mismatch-warning.component.test.js index 56f67443ea17..f49935770029 100644 --- a/ui/app/components/ui/account-mismatch-warning/tests/acccount-mismatch-warning.component.test.js +++ b/ui/app/components/ui/account-mismatch-warning/tests/acccount-mismatch-warning.component.test.js @@ -1,6 +1,6 @@ +import assert from 'assert' import React from 'react' import * as reactRedux from 'react-redux' -import assert from 'assert' import sinon from 'sinon' import { shallow } from 'enzyme' import InfoIcon from '../../icon/info-icon.component' diff --git a/ui/app/components/ui/alert/tests/alert.test.js b/ui/app/components/ui/alert/tests/alert.test.js index 8899f496955c..ec32d6633839 100644 --- a/ui/app/components/ui/alert/tests/alert.test.js +++ b/ui/app/components/ui/alert/tests/alert.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' import Alert from '../index' diff --git a/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js b/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js index 7bfff56d84c6..1fcf2aaea74f 100644 --- a/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js +++ b/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import Breadcrumbs from '../breadcrumbs.component' diff --git a/ui/app/components/ui/button-group/button-group.stories.js b/ui/app/components/ui/button-group/button-group.stories.js index 069ae6f2c637..e79f8bfea549 100644 --- a/ui/app/components/ui/button-group/button-group.stories.js +++ b/ui/app/components/ui/button-group/button-group.stories.js @@ -1,8 +1,8 @@ import React from 'react' import { action } from '@storybook/addon-actions' -import ButtonGroup from '.' -import Button from '../button' import { text, boolean } from '@storybook/addon-knobs/react' +import Button from '../button' +import ButtonGroup from '.' export default { title: 'ButtonGroup', diff --git a/ui/app/components/ui/button-group/tests/button-group-component.test.js b/ui/app/components/ui/button-group/tests/button-group-component.test.js index f963c86961ac..64a9353d90dc 100644 --- a/ui/app/components/ui/button-group/tests/button-group-component.test.js +++ b/ui/app/components/ui/button-group/tests/button-group-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import ButtonGroup from '../button-group.component' diff --git a/ui/app/components/ui/button/button.stories.js b/ui/app/components/ui/button/button.stories.js index 7ab14f282296..4a251d61b3e0 100644 --- a/ui/app/components/ui/button/button.stories.js +++ b/ui/app/components/ui/button/button.stories.js @@ -1,7 +1,7 @@ import React from 'react' import { action } from '@storybook/addon-actions' -import Button from '.' import { text, boolean } from '@storybook/addon-knobs/react' +import Button from '.' export default { title: 'Button', diff --git a/ui/app/components/ui/card/tests/card.component.test.js b/ui/app/components/ui/card/tests/card.component.test.js index bb7ce3f1a240..9eb1043517ff 100644 --- a/ui/app/components/ui/card/tests/card.component.test.js +++ b/ui/app/components/ui/card/tests/card.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import Card from '../card.component' diff --git a/ui/app/components/ui/check-box/check-box.stories.js b/ui/app/components/ui/check-box/check-box.stories.js index 9ddc14a5fae2..7a573a14c755 100644 --- a/ui/app/components/ui/check-box/check-box.stories.js +++ b/ui/app/components/ui/check-box/check-box.stories.js @@ -1,7 +1,7 @@ import React from 'react' import { action } from '@storybook/addon-actions' -import CheckBox, { CHECKED, INDETERMINATE, UNCHECKED } from './check-box.component' import { boolean, select, text } from '@storybook/addon-knobs/react' +import CheckBox, { CHECKED, INDETERMINATE, UNCHECKED } from './check-box.component' export default { title: 'Check Box', diff --git a/ui/app/components/ui/currency-display/tests/currency-display.component.test.js b/ui/app/components/ui/currency-display/tests/currency-display.component.test.js index 862c160f8caf..68bac84cf173 100644 --- a/ui/app/components/ui/currency-display/tests/currency-display.component.test.js +++ b/ui/app/components/ui/currency-display/tests/currency-display.component.test.js @@ -1,9 +1,9 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' -import CurrencyDisplay from '../currency-display.component' import sinon from 'sinon' import * as reactRedux from 'react-redux' +import CurrencyDisplay from '../currency-display.component' describe('CurrencyDisplay Component', function () { beforeEach(function () { diff --git a/ui/app/components/ui/currency-input/currency-input.container.js b/ui/app/components/ui/currency-input/currency-input.container.js index d8c7a572c11d..581e1c1a289b 100644 --- a/ui/app/components/ui/currency-input/currency-input.container.js +++ b/ui/app/components/ui/currency-input/currency-input.container.js @@ -1,11 +1,11 @@ import { connect } from 'react-redux' -import CurrencyInput from './currency-input.component' import { ETH } from '../../../helpers/constants/common' import { getSendMaxModeState, getIsMainnet, getPreferences, } from '../../../selectors' +import CurrencyInput from './currency-input.component' const mapStateToProps = (state) => { const { metamask: { nativeCurrency, currentCurrency, conversionRate } } = state diff --git a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js index adbd4efd2dd8..24c819e56dc2 100644 --- a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js +++ b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js @@ -1,6 +1,6 @@ +import assert from 'assert' import React from 'react' import PropTypes from 'prop-types' -import assert from 'assert' import { shallow, mount } from 'enzyme' import sinon from 'sinon' import { Provider } from 'react-redux' diff --git a/ui/app/components/ui/dropdown/dropdown.stories.js b/ui/app/components/ui/dropdown/dropdown.stories.js index 9b62f3c80290..82dd1ca4d452 100644 --- a/ui/app/components/ui/dropdown/dropdown.stories.js +++ b/ui/app/components/ui/dropdown/dropdown.stories.js @@ -1,7 +1,7 @@ import React from 'react' import { action } from '@storybook/addon-actions' -import Dropdown from '.' import { boolean, select, text } from '@storybook/addon-knobs/react' +import Dropdown from '.' export default { title: 'Dropdown', diff --git a/ui/app/components/ui/error-message/tests/error-message.component.test.js b/ui/app/components/ui/error-message/tests/error-message.component.test.js index f97b6a94927c..8e4025bc71d9 100644 --- a/ui/app/components/ui/error-message/tests/error-message.component.test.js +++ b/ui/app/components/ui/error-message/tests/error-message.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import ErrorMessage from '../error-message.component' diff --git a/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js b/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js index 3647d2b224e2..683bb29d5dcf 100644 --- a/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js +++ b/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import HexToDecimal from '../hex-to-decimal.component' diff --git a/ui/app/components/ui/icon/icon.stories.js b/ui/app/components/ui/icon/icon.stories.js index ee52a2f90e8f..95ab1f422dd7 100644 --- a/ui/app/components/ui/icon/icon.stories.js +++ b/ui/app/components/ui/icon/icon.stories.js @@ -1,11 +1,11 @@ import React from 'react' +import { color, number } from '@storybook/addon-knobs/react' import Approve from './approve-icon.component' import Copy from './copy-icon.component' import Interaction from './interaction-icon.component' import Preloader from './preloader' import Receive from './receive-icon.component' import Send from './send-icon.component' -import { color, number } from '@storybook/addon-knobs/react' export default { title: 'Icon', diff --git a/ui/app/components/ui/identicon/identicon.component.js b/ui/app/components/ui/identicon/identicon.component.js index 60886063d716..5b91bda234fd 100644 --- a/ui/app/components/ui/identicon/identicon.component.js +++ b/ui/app/components/ui/identicon/identicon.component.js @@ -3,9 +3,9 @@ import PropTypes from 'prop-types' import classnames from 'classnames' import contractMap from 'eth-contract-metadata' -import BlockieIdenticon from './blockieIdenticon' import { checksumAddress } from '../../../helpers/utils/util' import Jazzicon from '../jazzicon' +import BlockieIdenticon from './blockieIdenticon' const getStyles = (diameter) => ( { diff --git a/ui/app/components/ui/identicon/identicon.stories.js b/ui/app/components/ui/identicon/identicon.stories.js index 69d4d2721a94..3785080d5704 100644 --- a/ui/app/components/ui/identicon/identicon.stories.js +++ b/ui/app/components/ui/identicon/identicon.stories.js @@ -1,7 +1,7 @@ import React from 'react' import { text, boolean } from '@storybook/addon-knobs/react' -import Identicon from './identicon.component' import { number } from '@storybook/addon-knobs' +import Identicon from './identicon.component' export default { title: 'Identicon' } diff --git a/ui/app/components/ui/identicon/tests/identicon.component.test.js b/ui/app/components/ui/identicon/tests/identicon.component.test.js index 8735294a0d5c..f14229bfd3b1 100644 --- a/ui/app/components/ui/identicon/tests/identicon.component.test.js +++ b/ui/app/components/ui/identicon/tests/identicon.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import thunk from 'redux-thunk' import configureMockStore from 'redux-mock-store' import { mount } from 'enzyme' diff --git a/ui/app/components/ui/info-tooltip/info-tooltip.stories.js b/ui/app/components/ui/info-tooltip/info-tooltip.stories.js index 35c1b9fa46f2..10e6bec09c39 100644 --- a/ui/app/components/ui/info-tooltip/info-tooltip.stories.js +++ b/ui/app/components/ui/info-tooltip/info-tooltip.stories.js @@ -1,6 +1,6 @@ import React from 'react' -import InfoTooltip from './info-tooltip' import { text } from '@storybook/addon-knobs/react' +import InfoTooltip from './info-tooltip' export default { title: 'InfoTooltip', diff --git a/ui/app/components/ui/list-item/list-item.stories.js b/ui/app/components/ui/list-item/list-item.stories.js index c26015c34279..0b7c661434d4 100644 --- a/ui/app/components/ui/list-item/list-item.stories.js +++ b/ui/app/components/ui/list-item/list-item.stories.js @@ -1,6 +1,5 @@ import React from 'react' import PropTypes from 'prop-types' -import ListItem from './list-item.component' import { text } from '@storybook/addon-knobs/react' import Send from '../icon/send-icon.component' import Interaction from '../icon/interaction-icon.component' @@ -8,6 +7,7 @@ import Approve from '../icon/approve-icon.component' import Receive from '../icon/receive-icon.component' import Preloader from '../icon/preloader' import Button from '../button' +import ListItem from './list-item.component' export default { title: 'ListItem', diff --git a/ui/app/components/ui/list-item/tests/list-item.test.js b/ui/app/components/ui/list-item/tests/list-item.test.js index d5855a75bc9c..10e534446be8 100644 --- a/ui/app/components/ui/list-item/tests/list-item.test.js +++ b/ui/app/components/ui/list-item/tests/list-item.test.js @@ -1,8 +1,8 @@ +import assert from 'assert' import { shallow } from 'enzyme' import React from 'react' -import ListItem from '../list-item.component' -import assert from 'assert' import Sinon from 'sinon' +import ListItem from '../list-item.component' import Preloader from '../../icon/preloader/preloader-icon.component' import Send from '../../icon/send-icon.component' diff --git a/ui/app/components/ui/menu/menu.stories.js b/ui/app/components/ui/menu/menu.stories.js index c3071c7982ef..02eb2186a4e0 100644 --- a/ui/app/components/ui/menu/menu.stories.js +++ b/ui/app/components/ui/menu/menu.stories.js @@ -1,6 +1,6 @@ import React, { useState } from 'react' -import { Menu, MenuItem } from '.' import { action } from '@storybook/addon-actions' +import { Menu, MenuItem } from '.' export default { title: 'Menu', diff --git a/ui/app/components/ui/metafox-logo/tests/metafox-logo.component.test.js b/ui/app/components/ui/metafox-logo/tests/metafox-logo.component.test.js index b44754c145f2..acdf4c1c720f 100644 --- a/ui/app/components/ui/metafox-logo/tests/metafox-logo.component.test.js +++ b/ui/app/components/ui/metafox-logo/tests/metafox-logo.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { mount } from 'enzyme' import MetaFoxLogo from '..' diff --git a/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js b/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js index 268c04466215..8a5cf1114f63 100644 --- a/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js +++ b/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import Button from '../../../button' diff --git a/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js b/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js index 69f5e346b12f..b544e6f4c2fc 100644 --- a/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js +++ b/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import PageContainerHeader from '../page-container-header.component' diff --git a/ui/app/components/ui/popover/popover.stories.js b/ui/app/components/ui/popover/popover.stories.js index a7b0aef9bab0..5108e1f96a98 100644 --- a/ui/app/components/ui/popover/popover.stories.js +++ b/ui/app/components/ui/popover/popover.stories.js @@ -1,7 +1,7 @@ import React from 'react' -import Popover from './popover.component' import { text } from '@storybook/addon-knobs/react' import { action } from '@storybook/addon-actions' +import Popover from './popover.component' const containerStyle = { width: 800, diff --git a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js index bd18a5749b7e..7af7b2af7357 100644 --- a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js +++ b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js @@ -1,13 +1,13 @@ import React, { useState } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import Identicon from '../identicon' -import Tooltip from '../tooltip' import copyToClipboard from 'copy-to-clipboard' -import { DEFAULT_VARIANT, CARDS_VARIANT, FLAT_VARIANT } from './sender-to-recipient.constants' +import Tooltip from '../tooltip' +import Identicon from '../identicon' import { checksumAddress, shortenAddress } from '../../../helpers/utils/util' import AccountMismatchWarning from '../account-mismatch-warning/account-mismatch-warning.component' import { useI18nContext } from '../../../hooks/useI18nContext' +import { DEFAULT_VARIANT, CARDS_VARIANT, FLAT_VARIANT } from './sender-to-recipient.constants' const variantHash = { diff --git a/ui/app/components/ui/tabs/tabs.stories.js b/ui/app/components/ui/tabs/tabs.stories.js index 0e2caffed010..2cf40736c6a0 100644 --- a/ui/app/components/ui/tabs/tabs.stories.js +++ b/ui/app/components/ui/tabs/tabs.stories.js @@ -1,7 +1,7 @@ import React from 'react' +import { text } from '@storybook/addon-knobs/react' import Tab from './tab/tab.component' import Tabs from './tabs.component' -import { text } from '@storybook/addon-knobs/react' export default { title: 'Tabs', diff --git a/ui/app/components/ui/token-input/tests/token-input.component.test.js b/ui/app/components/ui/token-input/tests/token-input.component.test.js index 201c6b4abd31..3ff94d879f63 100644 --- a/ui/app/components/ui/token-input/tests/token-input.component.test.js +++ b/ui/app/components/ui/token-input/tests/token-input.component.test.js @@ -1,6 +1,6 @@ +import assert from 'assert' import React from 'react' import PropTypes from 'prop-types' -import assert from 'assert' import { shallow, mount } from 'enzyme' import sinon from 'sinon' import { Provider } from 'react-redux' diff --git a/ui/app/components/ui/token-input/token-input.component.js b/ui/app/components/ui/token-input/token-input.component.js index a425b3c0a939..78560117155d 100644 --- a/ui/app/components/ui/token-input/token-input.component.js +++ b/ui/app/components/ui/token-input/token-input.component.js @@ -1,9 +1,9 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' +import ethUtil from 'ethereumjs-util' import UnitInput from '../unit-input' import CurrencyDisplay from '../currency-display' import { getWeiHexFromDecimalValue } from '../../../helpers/utils/conversions.util' -import ethUtil from 'ethereumjs-util' import { conversionUtil, multiplyCurrencies } from '../../../helpers/utils/conversion-util' import { ETH } from '../../../helpers/constants/common' diff --git a/ui/app/components/ui/token-input/token-input.container.js b/ui/app/components/ui/token-input/token-input.container.js index b56efc1314fe..f20670d3180c 100644 --- a/ui/app/components/ui/token-input/token-input.container.js +++ b/ui/app/components/ui/token-input/token-input.container.js @@ -1,11 +1,11 @@ import { connect } from 'react-redux' import PropTypes from 'prop-types' -import TokenInput from './token-input.component' import { getIsMainnet, getTokenExchangeRates, getPreferences, } from '../../../selectors' +import TokenInput from './token-input.component' const mapStateToProps = (state) => { const { metamask: { currentCurrency } } = state diff --git a/ui/app/components/ui/unit-input/tests/unit-input.component.test.js b/ui/app/components/ui/unit-input/tests/unit-input.component.test.js index 798ae36761ef..0b92fc5a0173 100644 --- a/ui/app/components/ui/unit-input/tests/unit-input.component.test.js +++ b/ui/app/components/ui/unit-input/tests/unit-input.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow, mount } from 'enzyme' import sinon from 'sinon' import UnitInput from '../unit-input.component' diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js index 441b4e161fb9..eb8975265fbb 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js @@ -1,3 +1,4 @@ +import { addHexPrefix } from 'ethereumjs-util' import { conversionRateSelector, currentCurrencySelector, @@ -21,7 +22,6 @@ import { } from '../../helpers/utils/transactions.util' import { conversionUtil } from '../../helpers/utils/conversion-util' -import { addHexPrefix } from 'ethereumjs-util' // Actions const createActionType = (action) => `metamask/confirm-transaction/${action}` diff --git a/ui/app/ducks/index.js b/ui/app/ducks/index.js index 09af8914ee75..91ba222cb1b3 100644 --- a/ui/app/ducks/index.js +++ b/ui/app/ducks/index.js @@ -1,4 +1,5 @@ import { combineReducers } from 'redux' +import { ALERT_TYPES } from '../../../app/scripts/controllers/alert' import metamaskReducer from './metamask/metamask' import localeMessagesReducer from './locale/locale' import sendReducer from './send/send.duck' @@ -7,7 +8,6 @@ import confirmTransactionReducer from './confirm-transaction/confirm-transaction import gasReducer from './gas/gas.duck' import { unconnectedAccount } from './alerts' import historyReducer from './history/history' -import { ALERT_TYPES } from '../../../app/scripts/controllers/alert' export default combineReducers({ [ALERT_TYPES.unconnectedAccount]: unconnectedAccount, diff --git a/ui/app/helpers/utils/common.util.test.js b/ui/app/helpers/utils/common.util.test.js index 169b780b6204..cd2d71b03117 100644 --- a/ui/app/helpers/utils/common.util.test.js +++ b/ui/app/helpers/utils/common.util.test.js @@ -1,5 +1,5 @@ -import * as utils from './common.util' import assert from 'assert' +import * as utils from './common.util' describe('Common utils', function () { describe('camelCaseToCapitalize', function () { diff --git a/ui/app/helpers/utils/confirm-tx.util.js b/ui/app/helpers/utils/confirm-tx.util.js index e1cd83615b22..7f456984d8f9 100644 --- a/ui/app/helpers/utils/confirm-tx.util.js +++ b/ui/app/helpers/utils/confirm-tx.util.js @@ -3,6 +3,7 @@ import currencies from 'currency-formatter/currencies' import ethUtil from 'ethereumjs-util' import BigNumber from 'bignumber.js' +import { unconfirmedTransactionsCountSelector } from '../../selectors' import { conversionUtil, addCurrencies, @@ -10,7 +11,6 @@ import { conversionGreaterThan, } from './conversion-util' -import { unconfirmedTransactionsCountSelector } from '../../selectors' export function increaseLastGasPrice (lastGasPrice) { return ethUtil.addHexPrefix(multiplyCurrencies(lastGasPrice || '0x0', 1.1, { diff --git a/ui/app/helpers/utils/confirm-tx.util.test.js b/ui/app/helpers/utils/confirm-tx.util.test.js index 71783402e69d..065631c7d59e 100644 --- a/ui/app/helpers/utils/confirm-tx.util.test.js +++ b/ui/app/helpers/utils/confirm-tx.util.test.js @@ -1,5 +1,5 @@ -import * as utils from './confirm-tx.util' import assert from 'assert' +import * as utils from './confirm-tx.util' describe('Confirm Transaction utils', function () { describe('increaseLastGasPrice', function () { diff --git a/ui/app/helpers/utils/conversion-util.test.js b/ui/app/helpers/utils/conversion-util.test.js index 719f7b6d9150..9c570f95d304 100644 --- a/ui/app/helpers/utils/conversion-util.test.js +++ b/ui/app/helpers/utils/conversion-util.test.js @@ -1,6 +1,6 @@ import assert from 'assert' -import { addCurrencies, conversionUtil } from './conversion-util' import BigNumber from 'bignumber.js' +import { addCurrencies, conversionUtil } from './conversion-util' describe('conversion utils', function () { describe('addCurrencies()', function () { diff --git a/ui/app/helpers/utils/conversions.util.test.js b/ui/app/helpers/utils/conversions.util.test.js index 553fd1fd6f11..f4c08cc749f7 100644 --- a/ui/app/helpers/utils/conversions.util.test.js +++ b/ui/app/helpers/utils/conversions.util.test.js @@ -1,5 +1,5 @@ -import * as utils from './conversions.util' import assert from 'assert' +import * as utils from './conversions.util' describe('decETHToDecWEI', function () { it('should correctly convert 1 ETH to WEI', function () { diff --git a/ui/app/helpers/utils/i18n-helper.test.js b/ui/app/helpers/utils/i18n-helper.test.js index 4531865abb85..252cbe3f3137 100644 --- a/ui/app/helpers/utils/i18n-helper.test.js +++ b/ui/app/helpers/utils/i18n-helper.test.js @@ -1,7 +1,7 @@ -import { getMessage } from './i18n-helper' +import assert from 'assert' import React from 'react' import { shallow } from 'enzyme' -import assert from 'assert' +import { getMessage } from './i18n-helper' describe('i18n helper', function () { const TEST_LOCALE_CODE = 'TEST_LOCALE_CODE' diff --git a/ui/app/helpers/utils/token-util.js b/ui/app/helpers/utils/token-util.js index bc091292a642..6d8516ba8abb 100644 --- a/ui/app/helpers/utils/token-util.js +++ b/ui/app/helpers/utils/token-util.js @@ -1,7 +1,7 @@ import log from 'loglevel' -import * as util from './util' import BigNumber from 'bignumber.js' import contractMap from 'eth-contract-metadata' +import * as util from './util' import { conversionUtil, multiplyCurrencies } from './conversion-util' import { formatCurrency } from './confirm-tx.util' diff --git a/ui/app/helpers/utils/transactions.util.js b/ui/app/helpers/utils/transactions.util.js index 3d14c0336d4d..d94bd24d81f6 100644 --- a/ui/app/helpers/utils/transactions.util.js +++ b/ui/app/helpers/utils/transactions.util.js @@ -2,14 +2,13 @@ import ethUtil from 'ethereumjs-util' import MethodRegistry from 'eth-method-registry' import abi from 'human-standard-token-abi' import abiDecoder from 'abi-decoder' +import log from 'loglevel' import { TRANSACTION_TYPE_CANCEL, TRANSACTION_STATUS_CONFIRMED, } from '../../../../app/scripts/controllers/transactions/enums' import { MESSAGE_TYPE } from '../../../../app/scripts/lib/enums' import { getEtherscanNetworkPrefix } from '../../../lib/etherscan-prefix-for-network' -import fetchWithCache from './fetch-with-cache' - import { TOKEN_METHOD_TRANSFER, TOKEN_METHOD_APPROVE, @@ -26,8 +25,9 @@ import { CANCEL_ATTEMPT_ACTION_KEY, DEPOSIT_TRANSACTION_KEY, } from '../constants/transactions' +import fetchWithCache from './fetch-with-cache' + -import log from 'loglevel' import { addCurrencies } from './conversion-util' abiDecoder.addABI(abi) diff --git a/ui/app/helpers/utils/transactions.util.test.js b/ui/app/helpers/utils/transactions.util.test.js index f69e41112d6c..ab8b8ba7b510 100644 --- a/ui/app/helpers/utils/transactions.util.test.js +++ b/ui/app/helpers/utils/transactions.util.test.js @@ -1,5 +1,5 @@ -import * as utils from './transactions.util' import assert from 'assert' +import * as utils from './transactions.util' describe('Transactions utils', function () { describe('getTokenData', function () { diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index ffd8aa412cb4..899adebafb48 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -1,7 +1,7 @@ +import punycode from 'punycode' import abi from 'human-standard-token-abi' import ethUtil from 'ethereumjs-util' import { DateTime } from 'luxon' -import punycode from 'punycode' // formatData :: ( date: ) -> String export function formatDate (date, format = 'M/d/y \'at\' T') { diff --git a/ui/app/hooks/tests/useCancelTransaction.test.js b/ui/app/hooks/tests/useCancelTransaction.test.js index 920b9e223378..e27eb35864d2 100644 --- a/ui/app/hooks/tests/useCancelTransaction.test.js +++ b/ui/app/hooks/tests/useCancelTransaction.test.js @@ -1,5 +1,5 @@ -import * as reactRedux from 'react-redux' import assert from 'assert' +import * as reactRedux from 'react-redux' import { renderHook } from '@testing-library/react-hooks' import sinon from 'sinon' import transactions from '../../../../test/data/transaction-data.json' diff --git a/ui/app/hooks/tests/useCurrencyDisplay.test.js b/ui/app/hooks/tests/useCurrencyDisplay.test.js index 850a08960563..7be42cd50db6 100644 --- a/ui/app/hooks/tests/useCurrencyDisplay.test.js +++ b/ui/app/hooks/tests/useCurrencyDisplay.test.js @@ -1,8 +1,8 @@ import assert from 'assert' import { renderHook } from '@testing-library/react-hooks' import * as reactRedux from 'react-redux' -import { useCurrencyDisplay } from '../useCurrencyDisplay' import sinon from 'sinon' +import { useCurrencyDisplay } from '../useCurrencyDisplay' import { getCurrentCurrency, getNativeCurrency, getConversionRate } from '../../selectors' const tests = [ diff --git a/ui/app/hooks/tests/useRetryTransaction.test.js b/ui/app/hooks/tests/useRetryTransaction.test.js index e4e8160a8948..b922bd92c118 100644 --- a/ui/app/hooks/tests/useRetryTransaction.test.js +++ b/ui/app/hooks/tests/useRetryTransaction.test.js @@ -1,5 +1,5 @@ -import * as reactRedux from 'react-redux' import assert from 'assert' +import * as reactRedux from 'react-redux' import { renderHook } from '@testing-library/react-hooks' import sinon from 'sinon' import transactions from '../../../../test/data/transaction-data.json' diff --git a/ui/app/hooks/tests/useTokenData.test.js b/ui/app/hooks/tests/useTokenData.test.js index 7154581c65b0..10482b63b226 100644 --- a/ui/app/hooks/tests/useTokenData.test.js +++ b/ui/app/hooks/tests/useTokenData.test.js @@ -1,6 +1,6 @@ -import { useTokenData } from '../useTokenData' import assert from 'assert' import { renderHook } from '@testing-library/react-hooks' +import { useTokenData } from '../useTokenData' const tests = [ { diff --git a/ui/app/hooks/tests/useTokenDisplayValue.test.js b/ui/app/hooks/tests/useTokenDisplayValue.test.js index bb8464f8a28c..ce596168f89f 100644 --- a/ui/app/hooks/tests/useTokenDisplayValue.test.js +++ b/ui/app/hooks/tests/useTokenDisplayValue.test.js @@ -1,9 +1,9 @@ import assert from 'assert' import { renderHook } from '@testing-library/react-hooks' +import sinon from 'sinon' import * as tokenUtil from '../../helpers/utils/token-util' import * as txUtil from '../../helpers/utils/transactions.util' import { useTokenDisplayValue } from '../useTokenDisplayValue' -import sinon from 'sinon' const tests = [ { diff --git a/ui/app/hooks/tests/useTransactionDisplayData.test.js b/ui/app/hooks/tests/useTransactionDisplayData.test.js index 2cae72bbfb85..133c9291a972 100644 --- a/ui/app/hooks/tests/useTransactionDisplayData.test.js +++ b/ui/app/hooks/tests/useTransactionDisplayData.test.js @@ -1,5 +1,5 @@ -import * as reactRedux from 'react-redux' import assert from 'assert' +import * as reactRedux from 'react-redux' import { renderHook } from '@testing-library/react-hooks' import sinon from 'sinon' import transactions from '../../../../test/data/transaction-data.json' diff --git a/ui/app/hooks/tests/useUserPreferencedCurrency.test.js b/ui/app/hooks/tests/useUserPreferencedCurrency.test.js index 61aba3cb5953..65fe25c8e182 100644 --- a/ui/app/hooks/tests/useUserPreferencedCurrency.test.js +++ b/ui/app/hooks/tests/useUserPreferencedCurrency.test.js @@ -1,9 +1,9 @@ import assert from 'assert' import { renderHook } from '@testing-library/react-hooks' -import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency' import * as reactRedux from 'react-redux' -import { getPreferences, getShouldShowFiat } from '../../selectors' import sinon from 'sinon' +import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency' +import { getPreferences, getShouldShowFiat } from '../../selectors' const tests = [ { diff --git a/ui/app/hooks/useTokenDisplayValue.js b/ui/app/hooks/useTokenDisplayValue.js index 107a2c11e41f..b7d92af7cb49 100644 --- a/ui/app/hooks/useTokenDisplayValue.js +++ b/ui/app/hooks/useTokenDisplayValue.js @@ -1,5 +1,5 @@ -import { getTokenValue, calcTokenAmount } from '../helpers/utils/token-util' import { useMemo } from 'react' +import { getTokenValue, calcTokenAmount } from '../helpers/utils/token-util' import { useTokenData } from './useTokenData' /** diff --git a/ui/app/hooks/useTransactionDisplayData.js b/ui/app/hooks/useTransactionDisplayData.js index 8fca5c65fd77..3793299f5bf4 100644 --- a/ui/app/hooks/useTransactionDisplayData.js +++ b/ui/app/hooks/useTransactionDisplayData.js @@ -2,11 +2,8 @@ import { useSelector } from 'react-redux' import { getKnownMethodData } from '../selectors/selectors' import { getTransactionActionKey, getStatusKey } from '../helpers/utils/transactions.util' import { camelCaseToCapitalize } from '../helpers/utils/common.util' -import { useI18nContext } from './useI18nContext' -import { useTokenFiatAmount } from './useTokenFiatAmount' import { PRIMARY, SECONDARY } from '../helpers/constants/common' import { getTokenToAddress } from '../helpers/utils/token-util' -import { useUserPreferencedCurrency } from './useUserPreferencedCurrency' import { formatDateWithYearContext, shortenAddress, stripHttpSchemes } from '../helpers/utils/util' import { CONTRACT_INTERACTION_KEY, @@ -24,10 +21,13 @@ import { PENDING_STATUS_HASH, TOKEN_CATEGORY_HASH, } from '../helpers/constants/transactions' +import { getTokens } from '../ducks/metamask/metamask' +import { useI18nContext } from './useI18nContext' +import { useTokenFiatAmount } from './useTokenFiatAmount' +import { useUserPreferencedCurrency } from './useUserPreferencedCurrency' import { useCurrencyDisplay } from './useCurrencyDisplay' import { useTokenDisplayValue } from './useTokenDisplayValue' import { useTokenData } from './useTokenData' -import { getTokens } from '../ducks/metamask/metamask' /** * @typedef {Object} TransactionDisplayData diff --git a/ui/app/hooks/useTransactionTimeRemaining.js b/ui/app/hooks/useTransactionTimeRemaining.js index f7834ead1aca..825d685522ec 100644 --- a/ui/app/hooks/useTransactionTimeRemaining.js +++ b/ui/app/hooks/useTransactionTimeRemaining.js @@ -1,9 +1,9 @@ -import { getEstimatedGasPrices, getEstimatedGasTimes, getFeatureFlags, getIsMainnet } from '../selectors' -import { hexWEIToDecGWEI } from '../helpers/utils/conversions.util' import { useSelector } from 'react-redux' import { useRef, useEffect, useState, useMemo } from 'react' import { isEqual } from 'lodash' import { captureException } from '@sentry/browser' +import { hexWEIToDecGWEI } from '../helpers/utils/conversions.util' +import { getEstimatedGasPrices, getEstimatedGasTimes, getFeatureFlags, getIsMainnet } from '../selectors' import { getRawTimeEstimateData } from '../helpers/utils/gas-time-estimates.util' import { getCurrentLocale } from '../ducks/metamask/metamask' diff --git a/ui/app/hooks/useUserPreferencedCurrency.js b/ui/app/hooks/useUserPreferencedCurrency.js index d8d3a17595b5..986ef6dd7d2a 100644 --- a/ui/app/hooks/useUserPreferencedCurrency.js +++ b/ui/app/hooks/useUserPreferencedCurrency.js @@ -1,5 +1,5 @@ -import { getPreferences, getShouldShowFiat, getNativeCurrency } from '../selectors' import { useSelector } from 'react-redux' +import { getPreferences, getShouldShowFiat, getNativeCurrency } from '../selectors' import { PRIMARY, SECONDARY, ETH } from '../helpers/constants/common' /** diff --git a/ui/app/pages/add-token/add-token.component.js b/ui/app/pages/add-token/add-token.component.js index 158f96a92b65..48e306fc8768 100644 --- a/ui/app/pages/add-token/add-token.component.js +++ b/ui/app/pages/add-token/add-token.component.js @@ -5,10 +5,10 @@ import { checkExistingAddresses } from '../../helpers/utils/util' import { tokenInfoGetter } from '../../helpers/utils/token-util' import { CONFIRM_ADD_TOKEN_ROUTE } from '../../helpers/constants/routes' import TextField from '../../components/ui/text-field' -import TokenList from './token-list' -import TokenSearch from './token-search' import PageContainer from '../../components/ui/page-container' import { Tabs, Tab } from '../../components/ui/tabs' +import TokenList from './token-list' +import TokenSearch from './token-search' const emptyAddr = '0x0000000000000000000000000000000000000000' diff --git a/ui/app/pages/add-token/add-token.container.js b/ui/app/pages/add-token/add-token.container.js index 2e7354b237af..9f3f6d21ede5 100644 --- a/ui/app/pages/add-token/add-token.container.js +++ b/ui/app/pages/add-token/add-token.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' -import AddToken from './add-token.component' import { setPendingTokens, clearPendingTokens } from '../../store/actions' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import AddToken from './add-token.component' const mapStateToProps = (state) => { const { metamask: { identities, tokens, pendingTokens } } = state diff --git a/ui/app/pages/add-token/tests/add-token.test.js b/ui/app/pages/add-token/tests/add-token.test.js index da4a42f20387..6fff131ccfe8 100644 --- a/ui/app/pages/add-token/tests/add-token.test.js +++ b/ui/app/pages/add-token/tests/add-token.test.js @@ -1,6 +1,6 @@ +import assert from 'assert' import React from 'react' import { Provider } from 'react-redux' -import assert from 'assert' import sinon from 'sinon' import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../test/lib/render-helpers' diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js index 1b84279b19e8..319d1ed82599 100644 --- a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js +++ b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js @@ -1,9 +1,9 @@ import { connect } from 'react-redux' import { compose } from 'redux' -import ConfirmAddSuggestedToken from './confirm-add-suggested-token.component' import { withRouter } from 'react-router-dom' import { addToken, removeSuggestedTokens } from '../../store/actions' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConfirmAddSuggestedToken from './confirm-add-suggested-token.component' const mapStateToProps = (state) => { const { metamask: { pendingTokens, suggestedTokens, tokens } } = state diff --git a/ui/app/pages/confirm-add-token/confirm-add-token.container.js b/ui/app/pages/confirm-add-token/confirm-add-token.container.js index d04f159176d4..8c09ad837834 100644 --- a/ui/app/pages/confirm-add-token/confirm-add-token.container.js +++ b/ui/app/pages/confirm-add-token/confirm-add-token.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' -import ConfirmAddToken from './confirm-add-token.component' import { addTokens, clearPendingTokens } from '../../store/actions' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConfirmAddToken from './confirm-add-token.component' const mapStateToProps = (state) => { const { metamask: { pendingTokens } } = state diff --git a/ui/app/pages/confirm-approve/confirm-approve.js b/ui/app/pages/confirm-approve/confirm-approve.js index 3a4184e18853..5bd634113477 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.js +++ b/ui/app/pages/confirm-approve/confirm-approve.js @@ -2,8 +2,6 @@ import React, { useEffect, useRef, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useParams } from 'react-router-dom' import ConfirmTransactionBase from '../confirm-transaction-base' -import ConfirmApproveContent from './confirm-approve-content' -import { getCustomTxParamsData } from './confirm-approve.util' import { showModal } from '../../store/actions' import { getTokenData, @@ -21,6 +19,8 @@ import { } from '../../selectors/confirm-transaction' import { getCurrentCurrency, getDomainMetadata } from '../../selectors/selectors' import { currentNetworkTxListSelector } from '../../selectors/transactions' +import { getCustomTxParamsData } from './confirm-approve.util' +import ConfirmApproveContent from './confirm-approve-content' export default function ConfirmApprove () { const dispatch = useDispatch() diff --git a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js index e068b403ffeb..a73649484959 100644 --- a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js +++ b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js @@ -13,8 +13,8 @@ import { conversionRateSelector, } from '../../selectors' import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' -import ConfirmDecryptMessage from './confirm-decrypt-message.component' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConfirmDecryptMessage from './confirm-decrypt-message.component' function mapStateToProps (state) { const { confirmTransaction, diff --git a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js index 8d91540e5738..1c376ff5aa04 100644 --- a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js +++ b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js @@ -14,8 +14,8 @@ import { } from '../../selectors' import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' -import ConfirmEncryptionPublicKey from './confirm-encryption-public-key.component' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConfirmEncryptionPublicKey from './confirm-encryption-public-key.component' function mapStateToProps (state) { const { confirmTransaction, diff --git a/ui/app/pages/confirm-send-token/confirm-send-token.container.js b/ui/app/pages/confirm-send-token/confirm-send-token.container.js index ba0517ab0e65..330f614a884a 100644 --- a/ui/app/pages/confirm-send-token/confirm-send-token.container.js +++ b/ui/app/pages/confirm-send-token/confirm-send-token.container.js @@ -1,11 +1,11 @@ import { connect } from 'react-redux' import { compose } from 'redux' import { withRouter } from 'react-router-dom' -import ConfirmSendToken from './confirm-send-token.component' import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' import { updateSend, showSendTokenPage } from '../../store/actions' import { conversionUtil } from '../../helpers/utils/conversion-util' import { sendTokenTokenAmountAndToAddressSelector } from '../../selectors' +import ConfirmSendToken from './confirm-send-token.component' const mapStateToProps = (state) => { const { tokenAmount } = sendTokenTokenAmountAndToAddressSelector(state) diff --git a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js index 0faf6b471e33..f6e0a270de2e 100644 --- a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js +++ b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js @@ -1,7 +1,6 @@ import { connect } from 'react-redux' import { compose } from 'redux' import { withRouter } from 'react-router-dom' -import ConfirmTokenTransactionBase from './confirm-token-transaction-base.component' import { contractExchangeRateSelector, transactionFeeSelector, @@ -15,6 +14,7 @@ import { getTokenToAddress, getTokenValue, } from '../../helpers/utils/token-util' +import ConfirmTokenTransactionBase from './confirm-token-transaction-base.component' const mapStateToProps = (state, ownProps) => { diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js index 1759e967d711..7d002356c75a 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -2,7 +2,6 @@ import { connect } from 'react-redux' import { compose } from 'redux' import { withRouter } from 'react-router-dom' import contractMap from 'eth-contract-metadata' -import ConfirmTransactionBase from './confirm-transaction-base.component' import { clearConfirmTransaction, } from '../../ducks/confirm-transaction/confirm-transaction.duck' @@ -38,6 +37,7 @@ import { transactionFeeSelector, } from '../../selectors' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConfirmTransactionBase from './confirm-transaction-base.component' const casedContractMap = Object.keys(contractMap).reduce((acc, base) => { return { diff --git a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js index b0d0a8924b0a..dd6970d87cea 100644 --- a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js +++ b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' -import ConfirmTransactionSwitch from './confirm-transaction-switch.component' import { unconfirmedTransactionsListSelector } from '../../selectors' +import ConfirmTransactionSwitch from './confirm-transaction-switch.component' const mapStateToProps = (state, ownProps) => { const { metamask: { unapprovedTxs } } = state diff --git a/ui/app/pages/confirm-transaction/conf-tx.js b/ui/app/pages/confirm-transaction/conf-tx.js index 40df45a8f21f..0d7be5418350 100644 --- a/ui/app/pages/confirm-transaction/conf-tx.js +++ b/ui/app/pages/confirm-transaction/conf-tx.js @@ -3,9 +3,9 @@ import React, { Component } from 'react' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { compose } from 'redux' +import log from 'loglevel' import * as actions from '../../store/actions' import txHelper from '../../../lib/tx-helper' -import log from 'loglevel' import SignatureRequest from '../../components/app/signature-request' import SignatureRequestOriginal from '../../components/app/signature-request-original' import Loading from '../../components/ui/loading-screen' diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.component.js b/ui/app/pages/confirm-transaction/confirm-transaction.component.js index 47f2b27d94bc..69af2c226a1f 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.component.js +++ b/ui/app/pages/confirm-transaction/confirm-transaction.component.js @@ -9,7 +9,6 @@ import ConfirmSendToken from '../confirm-send-token' import ConfirmDeployContract from '../confirm-deploy-contract' import ConfirmApprove from '../confirm-approve' import ConfirmTokenTransactionBaseContainer from '../confirm-token-transaction-base' -import ConfTx from './conf-tx' import ConfirmDecryptMessage from '../confirm-decrypt-message' import ConfirmEncryptionPublicKey from '../confirm-encryption-public-key' @@ -25,6 +24,7 @@ import { DECRYPT_MESSAGE_REQUEST_PATH, ENCRYPTION_PUBLIC_KEY_REQUEST_PATH, } from '../../helpers/constants/routes' +import ConfTx from './conf-tx' export default class ConfirmTransaction extends Component { static contextTypes = { diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.container.js b/ui/app/pages/confirm-transaction/confirm-transaction.container.js index b0bfccfb89b1..6ee2579ffff7 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.container.js +++ b/ui/app/pages/confirm-transaction/confirm-transaction.container.js @@ -16,9 +16,9 @@ import { getContractMethodData, getTokenParams, } from '../../store/actions' -import ConfirmTransaction from './confirm-transaction.component' import { unconfirmedTransactionsListSelector } from '../../selectors' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConfirmTransaction from './confirm-transaction.component' const mapStateToProps = (state, ownProps) => { const { diff --git a/ui/app/pages/connected-accounts/connected-accounts.container.js b/ui/app/pages/connected-accounts/connected-accounts.container.js index 1bb5ba84a262..0fe24583a8fa 100644 --- a/ui/app/pages/connected-accounts/connected-accounts.container.js +++ b/ui/app/pages/connected-accounts/connected-accounts.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import ConnectedAccounts from './connected-accounts.component' import { getAccountToConnectToActiveTab, getOrderedConnectedAccountsForActiveTab, @@ -9,6 +8,7 @@ import { import { isExtensionUrl } from '../../helpers/utils/util' import { addPermittedAccount, removePermittedAccount, setSelectedAddress } from '../../store/actions' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConnectedAccounts from './connected-accounts.component' const mapStateToProps = (state) => { const { activeTab } = state diff --git a/ui/app/pages/connected-sites/connected-sites.container.js b/ui/app/pages/connected-sites/connected-sites.container.js index a77a2022bf92..f34558741e02 100644 --- a/ui/app/pages/connected-sites/connected-sites.container.js +++ b/ui/app/pages/connected-sites/connected-sites.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import ConnectedSites from './connected-sites.component' import { getOpenMetamaskTabsIds, requestAccountsPermissionWithId, @@ -17,6 +16,7 @@ import { } from '../../selectors' import { CONNECT_ROUTE } from '../../helpers/constants/routes' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConnectedSites from './connected-sites.component' const mapStateToProps = (state) => { const { openMetaMaskTabs } = state.appState diff --git a/ui/app/pages/create-account/connect-hardware/index.js b/ui/app/pages/create-account/connect-hardware/index.js index 32189bf63029..689b6058d9fd 100644 --- a/ui/app/pages/create-account/connect-hardware/index.js +++ b/ui/app/pages/create-account/connect-hardware/index.js @@ -3,10 +3,10 @@ import PropTypes from 'prop-types' import { connect } from 'react-redux' import * as actions from '../../../store/actions' import { getMetaMaskAccounts } from '../../../selectors' -import SelectHardware from './select-hardware' -import AccountList from './account-list' import { formatBalance } from '../../../helpers/utils/util' import { getMostRecentOverviewPage } from '../../../ducks/history/history' +import SelectHardware from './select-hardware' +import AccountList from './account-list' class ConnectHardwareForm extends Component { state = { diff --git a/ui/app/pages/create-account/create-account.component.js b/ui/app/pages/create-account/create-account.component.js index 2389650e7f29..2ff859144dcb 100644 --- a/ui/app/pages/create-account/create-account.component.js +++ b/ui/app/pages/create-account/create-account.component.js @@ -2,14 +2,14 @@ import React, { Component } from 'react' import { Switch, Route, matchPath } from 'react-router-dom' import PropTypes from 'prop-types' import classnames from 'classnames' -import NewAccountCreateForm from './new-account.container' -import NewAccountImportForm from './import-account' -import ConnectHardwareForm from './connect-hardware' import { NEW_ACCOUNT_ROUTE, IMPORT_ACCOUNT_ROUTE, CONNECT_HARDWARE_ROUTE, } from '../../helpers/constants/routes' +import NewAccountCreateForm from './new-account.container' +import NewAccountImportForm from './import-account' +import ConnectHardwareForm from './connect-hardware' export default class CreateAccountPage extends Component { renderTabs () { diff --git a/ui/app/pages/create-account/import-account/json.js b/ui/app/pages/create-account/import-account/json.js index 55a77cb4e8f6..cd81fd8c6e87 100644 --- a/ui/app/pages/create-account/import-account/json.js +++ b/ui/app/pages/create-account/import-account/json.js @@ -3,8 +3,8 @@ import PropTypes from 'prop-types' import { withRouter } from 'react-router-dom' import { compose } from 'redux' import { connect } from 'react-redux' -import * as actions from '../../../store/actions' import FileInput from 'react-simple-file-input' +import * as actions from '../../../store/actions' import { getMetaMaskAccounts } from '../../../selectors' import Button from '../../../components/ui/button' import { getMostRecentOverviewPage } from '../../../ducks/history/history' diff --git a/ui/app/pages/create-account/new-account.container.js b/ui/app/pages/create-account/new-account.container.js index 14c33c2f4397..d1680b4b3f62 100644 --- a/ui/app/pages/create-account/new-account.container.js +++ b/ui/app/pages/create-account/new-account.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' import * as actions from '../../store/actions' -import NewAccountCreateForm from './new-account.component' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import NewAccountCreateForm from './new-account.component' const mapStateToProps = (state) => { const { metamask: { network, selectedAddress, identities = {} } } = state diff --git a/ui/app/pages/create-account/tests/create-account.test.js b/ui/app/pages/create-account/tests/create-account.test.js index b680057f101c..b12ecd36b7ed 100644 --- a/ui/app/pages/create-account/tests/create-account.test.js +++ b/ui/app/pages/create-account/tests/create-account.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mountWithRouter } from '../../../../../test/lib/render-helpers' import CreateAccountPage from '../index' diff --git a/ui/app/pages/first-time-flow/create-password/create-password.component.js b/ui/app/pages/first-time-flow/create-password/create-password.component.js index 5a746d89ea73..a159601da7c2 100644 --- a/ui/app/pages/first-time-flow/create-password/create-password.component.js +++ b/ui/app/pages/first-time-flow/create-password/create-password.component.js @@ -1,14 +1,14 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import { Switch, Route } from 'react-router-dom' -import NewAccount from './new-account' import MetaFoxLogo from '../../../components/ui/metafox-logo' -import ImportWithSeedPhrase from './import-with-seed-phrase' import { INITIALIZE_CREATE_PASSWORD_ROUTE, INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE, INITIALIZE_SEED_PHRASE_ROUTE, } from '../../../helpers/constants/routes' +import NewAccount from './new-account' +import ImportWithSeedPhrase from './import-with-seed-phrase' export default class CreatePassword extends PureComponent { static propTypes = { diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js index 018666b139cc..62d2db4b5283 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js @@ -1,10 +1,10 @@ import { connect } from 'react-redux' -import ImportWithSeedPhrase from './import-with-seed-phrase.component' import { setSeedPhraseBackedUp, initializeThreeBox, setCompletedOnboarding, } from '../../../../store/actions' +import ImportWithSeedPhrase from './import-with-seed-phrase.component' const mapDispatchToProps = (dispatch) => { return { diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js index 2156de687b97..a464bb79e3c9 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import ImportWithSeedPhrase from '../import-with-seed-phrase.component' diff --git a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js index d52f74dbc560..9af0970a660e 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js +++ b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' -import EndOfFlow from './end-of-flow.component' import { getOnboardingInitiator } from '../../../selectors' +import EndOfFlow from './end-of-flow.component' const firstTimeFlowTypeNameMap = { create: 'New Wallet Created', diff --git a/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js b/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js index 2cc5b971085e..6030441a14ea 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js +++ b/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' import { DEFAULT_ROUTE } from '../../../../helpers/constants/routes' diff --git a/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js b/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js index 3aafd2134f79..6e3b130bfe86 100644 --- a/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js +++ b/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' import { DEFAULT_ROUTE, diff --git a/ui/app/pages/first-time-flow/first-time-flow.component.js b/ui/app/pages/first-time-flow/first-time-flow.component.js index a0dee962b562..0c9474161261 100644 --- a/ui/app/pages/first-time-flow/first-time-flow.component.js +++ b/ui/app/pages/first-time-flow/first-time-flow.component.js @@ -1,14 +1,7 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import { Switch, Route } from 'react-router-dom' -import FirstTimeFlowSwitch from './first-time-flow-switch' -import Welcome from './welcome' -import SelectAction from './select-action' -import EndOfFlow from './end-of-flow' import Unlock from '../unlock-page' -import CreatePassword from './create-password' -import SeedPhrase from './seed-phrase' -import MetaMetricsOptInScreen from './metametrics-opt-in' import { DEFAULT_ROUTE, INITIALIZE_WELCOME_ROUTE, @@ -20,6 +13,13 @@ import { INITIALIZE_METAMETRICS_OPT_IN_ROUTE, INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, } from '../../helpers/constants/routes' +import FirstTimeFlowSwitch from './first-time-flow-switch' +import Welcome from './welcome' +import SelectAction from './select-action' +import EndOfFlow from './end-of-flow' +import CreatePassword from './create-password' +import SeedPhrase from './seed-phrase' +import MetaMetricsOptInScreen from './metametrics-opt-in' export default class FirstTimeFlow extends PureComponent { static propTypes = { diff --git a/ui/app/pages/first-time-flow/first-time-flow.container.js b/ui/app/pages/first-time-flow/first-time-flow.container.js index e0070b8537b5..fbab9df425e3 100644 --- a/ui/app/pages/first-time-flow/first-time-flow.container.js +++ b/ui/app/pages/first-time-flow/first-time-flow.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import FirstTimeFlow from './first-time-flow.component' import { getFirstTimeFlowTypeRoute } from '../../selectors' import { createNewVaultAndGetSeedPhrase, @@ -10,6 +9,7 @@ import { import { INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, } from '../../helpers/constants/routes' +import FirstTimeFlow from './first-time-flow.component' const mapStateToProps = (state, ownProps) => { const { metamask: { completedOnboarding, isInitialized, isUnlocked, seedPhraseBackedUp } } = state diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js b/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js index 7c54fd980ab1..aeb323915ff5 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' -import MetaMetricsOptIn from './metametrics-opt-in.component' import { setParticipateInMetaMetrics } from '../../../store/actions' import { getFirstTimeFlowTypeRoute } from '../../../selectors' +import MetaMetricsOptIn from './metametrics-opt-in.component' const firstTimeFlowTypeNameMap = { create: 'Selected Create New Wallet', diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js b/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js index c3b7f04fe018..c8a2491ffcfc 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js index 176601e49a40..8fece3bba600 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js @@ -1,10 +1,10 @@ import { connect } from 'react-redux' -import ConfirmSeedPhrase from './confirm-seed-phrase.component' import { setSeedPhraseBackedUp, initializeThreeBox, setCompletedOnboarding, } from '../../../../store/actions' +import ConfirmSeedPhrase from './confirm-seed-phrase.component' const mapDispatchToProps = (dispatch) => { return { diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js index c1bf9109cd77..64289adc00c9 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js @@ -1,10 +1,10 @@ import { connect } from 'react-redux' -import RevealSeedPhrase from './reveal-seed-phrase.component' import { setCompletedOnboarding, setSeedPhraseBackedUp, } from '../../../../store/actions' import { getOnboardingInitiator } from '../../../../selectors' +import RevealSeedPhrase from './reveal-seed-phrase.component' const mapStateToProps = (state) => { return { diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js index dfc0457786c0..62d64d5b68d8 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import RevealSeedPhrase from '../index' diff --git a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js index ade1904c4993..6e6201a03d6f 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js @@ -1,17 +1,17 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import { Switch, Route } from 'react-router-dom' -import RevealSeedPhrase from './reveal-seed-phrase' -import ConfirmSeedPhrase from './confirm-seed-phrase' +import HTML5Backend from 'react-dnd-html5-backend' +import { DragDropContextProvider } from 'react-dnd' import { INITIALIZE_SEED_PHRASE_ROUTE, INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE, INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, DEFAULT_ROUTE, } from '../../../helpers/constants/routes' -import HTML5Backend from 'react-dnd-html5-backend' -import { DragDropContextProvider } from 'react-dnd' import MetaFoxLogo from '../../../components/ui/metafox-logo' +import ConfirmSeedPhrase from './confirm-seed-phrase' +import RevealSeedPhrase from './reveal-seed-phrase' export default class SeedPhrase extends PureComponent { static propTypes = { diff --git a/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js index a5846a944af9..78c77d3a77ce 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js +++ b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import ConfirmSeedPhrase from '../confirm-seed-phrase/confirm-seed-phrase.component' diff --git a/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js b/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js index 2293cd6a5cbc..6d7954276efa 100644 --- a/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js +++ b/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' import SelectAction from '../index' diff --git a/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js b/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js index 510334dca098..0e3a762a80b4 100644 --- a/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js +++ b/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' diff --git a/ui/app/pages/home/home.container.js b/ui/app/pages/home/home.container.js index 8a1c0eed77aa..a42e539119a5 100644 --- a/ui/app/pages/home/home.container.js +++ b/ui/app/pages/home/home.container.js @@ -1,4 +1,3 @@ -import Home from './home.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -23,6 +22,7 @@ import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_POPUP, } from '../../../../app/scripts/lib/enums' +import Home from './home.component' const mapStateToProps = (state) => { const { metamask, appState } = state diff --git a/ui/app/pages/index.js b/ui/app/pages/index.js index 5ec61b4d2e9f..16e63204c153 100644 --- a/ui/app/pages/index.js +++ b/ui/app/pages/index.js @@ -3,10 +3,10 @@ import PropTypes from 'prop-types' import { Provider } from 'react-redux' import { HashRouter } from 'react-router-dom' import * as Sentry from '@sentry/browser' -import ErrorPage from './error' -import Routes from './routes' import { I18nProvider, LegacyI18nProvider } from '../contexts/i18n' import { MetaMetricsProvider, LegacyMetaMetricsProvider } from '../contexts/metametrics' +import ErrorPage from './error' +import Routes from './routes' class Index extends PureComponent { state = {} diff --git a/ui/app/pages/keychains/tests/reveal-seed.test.js b/ui/app/pages/keychains/tests/reveal-seed.test.js index 7a5325acab46..ee89b58c6136 100644 --- a/ui/app/pages/keychains/tests/reveal-seed.test.js +++ b/ui/app/pages/keychains/tests/reveal-seed.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import RevealSeedPage from '../reveal-seed' diff --git a/ui/app/pages/lock/lock.container.js b/ui/app/pages/lock/lock.container.js index 382f936c7784..e7e12b1039ac 100644 --- a/ui/app/pages/lock/lock.container.js +++ b/ui/app/pages/lock/lock.container.js @@ -1,8 +1,8 @@ -import Lock from './lock.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { lockMetamask } from '../../store/actions' +import Lock from './lock.component' const mapStateToProps = (state) => { const { metamask: { isUnlocked } } = state diff --git a/ui/app/pages/lock/tests/lock.test.js b/ui/app/pages/lock/tests/lock.test.js index 85eff210ad08..77a1a720312b 100644 --- a/ui/app/pages/lock/tests/lock.test.js +++ b/ui/app/pages/lock/tests/lock.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mountWithRouter } from '../../../../../test/lib/render-helpers' import Lock from '../index' diff --git a/ui/app/pages/mobile-sync/mobile-sync.container.js b/ui/app/pages/mobile-sync/mobile-sync.container.js index 053f05d8116e..3c3bf6053406 100644 --- a/ui/app/pages/mobile-sync/mobile-sync.container.js +++ b/ui/app/pages/mobile-sync/mobile-sync.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' import { displayWarning, requestRevealSeedWords, fetchInfoToSync, exportAccounts } from '../../store/actions' -import MobileSyncPage from './mobile-sync.component' import { getMostRecentOverviewPage } from '../../ducks/history/history' import { getMetaMaskKeyrings } from '../../selectors' +import MobileSyncPage from './mobile-sync.component' const mapDispatchToProps = (dispatch) => { return { diff --git a/ui/app/pages/permissions-connect/permissions-connect.container.js b/ui/app/pages/permissions-connect/permissions-connect.container.js index e522e864fd92..e65677a4dec6 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.container.js +++ b/ui/app/pages/permissions-connect/permissions-connect.container.js @@ -1,6 +1,5 @@ import { connect } from 'react-redux' import PropTypes from 'prop-types' -import PermissionApproval from './permissions-connect.component' import { getPermissionsRequests, getNativeCurrency, @@ -22,6 +21,7 @@ import { CONNECT_ROUTE, CONNECT_CONFIRM_PERMISSIONS_ROUTE, } from '../../helpers/constants/routes' +import PermissionApproval from './permissions-connect.component' const mapStateToProps = (state, ownProps) => { const { diff --git a/ui/app/pages/routes/routes.container.js b/ui/app/pages/routes/routes.container.js index d4a638250f82..9fdfa9067e8c 100644 --- a/ui/app/pages/routes/routes.container.js +++ b/ui/app/pages/routes/routes.container.js @@ -7,7 +7,6 @@ import { getPreferences, submittedPendingTransactionsSelector, } from '../../selectors' -import Routes from './routes.component' import { hideSidebar, lockMetamask, @@ -16,6 +15,7 @@ import { setMouseUserState, } from '../../store/actions' import { pageChanged } from '../../ducks/history/history' +import Routes from './routes.component' function mapStateToProps (state) { const { appState } = state diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.js index a5407ece02ac..c669e194320b 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.js @@ -1,3 +1,5 @@ +import ethUtil from 'ethereumjs-util' +import contractMap from 'eth-contract-metadata' import { REQUIRED_ERROR, INVALID_RECIPIENT_ADDRESS_ERROR, @@ -6,8 +8,6 @@ import { } from '../../send.constants' import { isValidAddress, isEthNetwork, checkExistingAddresses } from '../../../../helpers/utils/util' -import ethUtil from 'ethereumjs-util' -import contractMap from 'eth-contract-metadata' export function getToErrorObject (to, hasHexData = false, network) { let toError = null diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js index 392b9af77c73..f36b95594a44 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js @@ -1,14 +1,14 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import { isValidDomainName, isValidAddress, isValidAddressHead } from '../../../../helpers/utils/util' -import { ellipsify } from '../../send.utils' import { debounce } from 'lodash' import copyToClipboard from 'copy-to-clipboard/index' import ENS from 'ethjs-ens' import networkMap from 'ethereum-ens-network-map' import log from 'loglevel' +import { ellipsify } from '../../send.utils' +import { isValidDomainName, isValidAddress, isValidAddressHead } from '../../../../helpers/utils/util' // Local Constants diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.container.js b/ui/app/pages/send/send-content/add-recipient/ens-input.container.js index 48d266db4b7f..479773e9effc 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.container.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.container.js @@ -1,11 +1,11 @@ import { connect } from 'react-redux' -import EnsInput from './ens-input.component' import { getCurrentNetwork, getSendTo, getSendToNickname, getAddressBookEntry, } from '../../../../selectors' +import EnsInput from './ens-input.component' export default connect( (state) => { diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js index b031323bef1c..5d88e4e09433 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import AddRecipient from '../add-recipient.component' diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js index e187a15923c8..1113ad7f9fad 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js @@ -7,15 +7,15 @@ import { getSendMaxModeState, getBasicGasEstimateLoadingStatus, } from '../../../../../selectors' -import { calcMaxAmount } from './amount-max-button.utils' import { updateSendAmount, setMaxModeTo, } from '../../../../../store/actions' -import AmountMaxButton from './amount-max-button.component' import { updateSendErrors, } from '../../../../../ducks/send/send.duck' +import { calcMaxAmount } from './amount-max-button.utils' +import AmountMaxButton from './amount-max-button.component' export default connect(mapStateToProps, mapDispatchToProps)(AmountMaxButton) diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js index 606ab6a84c53..f27207ecb839 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js @@ -1,5 +1,5 @@ -import { multiplyCurrencies, subtractCurrencies } from '../../../../../helpers/utils/conversion-util' import ethUtil from 'ethereumjs-util' +import { multiplyCurrencies, subtractCurrencies } from '../../../../../helpers/utils/conversion-util' export function calcMaxAmount ({ balance, gasTotal, sendToken, tokenBalance }) { const { decimals } = sendToken || {} diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js index 008bcec30366..7ba387c515c5 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import AmountMaxButton from '../amount-max-button.component' diff --git a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js b/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js index 37b764fbcf6c..c21c38509053 100644 --- a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js +++ b/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js @@ -2,9 +2,9 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import { debounce } from 'lodash' import SendRowWrapper from '../send-row-wrapper' -import AmountMaxButton from './amount-max-button' import UserPreferencedCurrencyInput from '../../../../components/app/user-preferenced-currency-input' import UserPreferencedTokenInput from '../../../../components/app/user-preferenced-token-input' +import AmountMaxButton from './amount-max-button' export default class SendAmountRow extends Component { diff --git a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js index b22819f258dc..fa1e5a2aab49 100644 --- a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import SendAmountRow from '../send-amount-row.component' diff --git a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js index 3fdb4803cb28..dbbf2dddb6a5 100644 --- a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js +++ b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' -import SendAssetRow from './send-asset-row.component' import { getMetaMaskAccounts, getSendTokenAddress } from '../../../../selectors' import { updateSendToken } from '../../../../store/actions' +import SendAssetRow from './send-asset-row.component' function mapStateToProps (state) { return { diff --git a/ui/app/pages/send/send-content/send-content.component.js b/ui/app/pages/send/send-content/send-content.component.js index 9188140f9025..a764849f939d 100644 --- a/ui/app/pages/send/send-content/send-content.component.js +++ b/ui/app/pages/send/send-content/send-content.component.js @@ -1,11 +1,11 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import PageContainerContent from '../../../components/ui/page-container/page-container-content.component' +import Dialog from '../../../components/ui/dialog' import SendAmountRow from './send-amount-row' import SendGasRow from './send-gas-row' import SendHexDataRow from './send-hex-data-row' import SendAssetRow from './send-asset-row' -import Dialog from '../../../components/ui/dialog' export default class SendContent extends Component { diff --git a/ui/app/pages/send/send-content/send-content.container.js b/ui/app/pages/send/send-content/send-content.container.js index 8ee785736062..5cde49de9622 100644 --- a/ui/app/pages/send/send-content/send-content.container.js +++ b/ui/app/pages/send/send-content/send-content.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import SendContent from './send-content.component' import { getSendTo, accountsWithSendEtherInfoSelector, @@ -7,6 +6,7 @@ import { } from '../../../selectors' import * as actions from '../../../store/actions' +import SendContent from './send-content.component' function mapStateToProps (state) { const ownedAccounts = accountsWithSendEtherInfoSelector(state) diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js index 63a0eba57cbb..b479efb9d0ce 100644 --- a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js @@ -1,9 +1,9 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' +import sinon from 'sinon' import GasFeeDisplay from '../gas-fee-display.component' import UserPreferencedCurrencyDisplay from '../../../../../../components/app/user-preferenced-currency-display' -import sinon from 'sinon' const propsMethodSpies = { showCustomizeGasModal: sinon.spy(), diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js index 5f593e01b251..3d22971d5135 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js +++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js @@ -1,9 +1,9 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import SendRowWrapper from '../send-row-wrapper' -import GasFeeDisplay from './gas-fee-display/gas-fee-display.component' import GasPriceButtonGroup from '../../../../components/app/gas-customization/gas-price-button-group' import AdvancedGasInputs from '../../../../components/app/gas-customization/advanced-gas-inputs' +import GasFeeDisplay from './gas-fee-display/gas-fee-display.component' export default class SendGasRow extends Component { diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js index 45c5683b6127..9c822404382a 100644 --- a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import SendGasRow from '../send-gas-row.component' diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js index 6213173c29df..1255aac49be6 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import SendRowErrorMessage from '../send-row-error-message.component' diff --git a/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js b/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js index 4240144417b4..00f3ceb7fb43 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import SendRowWrapper from '../send-row-wrapper.component' diff --git a/ui/app/pages/send/send-content/tests/send-content-component.test.js b/ui/app/pages/send/send-content/tests/send-content-component.test.js index 6fdb763127a0..3687e8711c02 100644 --- a/ui/app/pages/send/send-content/tests/send-content-component.test.js +++ b/ui/app/pages/send/send-content/tests/send-content-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import SendContent from '../send-content.component' diff --git a/ui/app/pages/send/send-footer/send-footer.container.js b/ui/app/pages/send/send-footer/send-footer.container.js index 02379a9e67cf..6ffda4952780 100644 --- a/ui/app/pages/send/send-footer/send-footer.container.js +++ b/ui/app/pages/send/send-footer/send-footer.container.js @@ -26,13 +26,13 @@ import { getRenderableEstimateDataForSmallButtonsFromGWEI, getDefaultActiveButtonIndex, } from '../../../selectors' +import { getMostRecentOverviewPage } from '../../../ducks/history/history' import SendFooter from './send-footer.component' import { addressIsNew, constructTxParams, constructUpdatedTx, } from './send-footer.utils' -import { getMostRecentOverviewPage } from '../../../ducks/history/history' export default connect(mapStateToProps, mapDispatchToProps)(SendFooter) diff --git a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js index ba2c8c1e556f..ef502e0aa612 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import { CONFIRM_TRANSACTION_ROUTE } from '../../../../helpers/constants/routes' diff --git a/ui/app/pages/send/send-header/send-header.container.js b/ui/app/pages/send/send-header/send-header.container.js index e79d359c7671..e89d127d3a2e 100644 --- a/ui/app/pages/send/send-header/send-header.container.js +++ b/ui/app/pages/send/send-header/send-header.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' import { clearSend } from '../../../store/actions' -import SendHeader from './send-header.component' import { getTitleKey } from '../../../selectors' import { getMostRecentOverviewPage } from '../../../ducks/history/history' +import SendHeader from './send-header.component' export default connect(mapStateToProps, mapDispatchToProps)(SendHeader) diff --git a/ui/app/pages/send/send-header/tests/send-header-component.test.js b/ui/app/pages/send/send-header/tests/send-header-component.test.js index 3667a2504fc8..2844bc879dc7 100644 --- a/ui/app/pages/send/send-header/tests/send-header-component.test.js +++ b/ui/app/pages/send/send-header/tests/send-header-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import SendHeader from '../send-header.component' diff --git a/ui/app/pages/send/send.component.js b/ui/app/pages/send/send.component.js index 0c7f7804a9b3..882c2edd65de 100644 --- a/ui/app/pages/send/send.component.js +++ b/ui/app/pages/send/send.component.js @@ -1,12 +1,12 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' +import { debounce } from 'lodash' import { getAmountErrorObject, getGasFeeErrorObject, getToAddressForGasUpdate, doesAmountErrorRequireUpdate, } from './send.utils' -import { debounce } from 'lodash' import { getToWarningObject, getToErrorObject } from './send-content/add-recipient/add-recipient' import SendHeader from './send-header' import AddRecipient from './send-content/add-recipient' diff --git a/ui/app/pages/send/send.container.js b/ui/app/pages/send/send.container.js index ca58a3e7db90..34e876aaea7a 100644 --- a/ui/app/pages/send/send.container.js +++ b/ui/app/pages/send/send.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import SendEther from './send.component' import { withRouter } from 'react-router-dom' import { compose } from 'redux' @@ -43,12 +42,13 @@ import { fetchBasicGasEstimates, } from '../../ducks/gas/gas.duck' import { getTokens } from '../../ducks/metamask/metamask' -import { - calcGasTotal, -} from './send.utils' import { isValidDomainName, } from '../../helpers/utils/util' +import { + calcGasTotal, +} from './send.utils' +import SendEther from './send.component' function mapStateToProps (state) { const editingTransactionId = getSendEditingTransactionId(state) diff --git a/ui/app/pages/send/send.utils.js b/ui/app/pages/send/send.utils.js index ed01da74cacf..fe208f7be85d 100644 --- a/ui/app/pages/send/send.utils.js +++ b/ui/app/pages/send/send.utils.js @@ -1,3 +1,5 @@ +import abi from 'ethereumjs-abi' +import ethUtil from 'ethereumjs-util' import { addCurrencies, conversionUtil, @@ -19,8 +21,6 @@ import { TOKEN_TRANSFER_FUNCTION_SIGNATURE, } from './send.constants' -import abi from 'ethereumjs-abi' -import ethUtil from 'ethereumjs-util' export { addGasBuffer, diff --git a/ui/app/pages/send/tests/send-component.test.js b/ui/app/pages/send/tests/send-component.test.js index 43c296009f2e..5a157aa6b601 100644 --- a/ui/app/pages/send/tests/send-component.test.js +++ b/ui/app/pages/send/tests/send-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import proxyquire from 'proxyquire' import { shallow } from 'enzyme' import sinon from 'sinon' diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js b/ui/app/pages/settings/advanced-tab/advanced-tab.container.js index c36bc204fc37..64777f4fa11b 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.container.js @@ -1,4 +1,3 @@ -import AdvancedTab from './advanced-tab.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -14,6 +13,7 @@ import { setIpfsGateway, } from '../../../store/actions' import { getPreferences } from '../../../selectors' +import AdvancedTab from './advanced-tab.component' export const mapStateToProps = (state) => { const { appState: { warning }, metamask } = state diff --git a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js index cd8e9a200ab4..548623187374 100644 --- a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js +++ b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' import AdvancedTab from '../advanced-tab.component' diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js index 20ebdcee64ba..12f42018691d 100644 --- a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js +++ b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js @@ -1,12 +1,12 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' +import { debounce } from 'lodash' import Identicon from '../../../../components/ui/identicon' import TextField from '../../../../components/ui/text-field' import { CONTACT_LIST_ROUTE } from '../../../../helpers/constants/routes' import { isValidAddress, isValidDomainName } from '../../../../helpers/utils/util' import EnsInput from '../../../send/send-content/add-recipient/ens-input' import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer' -import { debounce } from 'lodash' export default class AddContact extends PureComponent { diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js index 66c40e51a301..9c5993e4f1f1 100644 --- a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js +++ b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js @@ -1,4 +1,3 @@ -import AddContact from './add-contact.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -6,6 +5,7 @@ import { addToAddressBook, showQrScanner, qrCodeDetected } from '../../../../sto import { getQrCodeData, } from '../../../../selectors' +import AddContact from './add-contact.component' const mapStateToProps = (state) => { return { diff --git a/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js b/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js index dfcb35c1902a..fc6dc535468a 100644 --- a/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js +++ b/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js @@ -1,15 +1,15 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import ContactList from '../../../components/app/contact-list' -import EditContact from './edit-contact' -import AddContact from './add-contact' -import ViewContact from './view-contact' -import MyAccounts from './my-accounts' import { CONTACT_ADD_ROUTE, CONTACT_VIEW_ROUTE, CONTACT_MY_ACCOUNTS_ROUTE, } from '../../../helpers/constants/routes' +import EditContact from './edit-contact' +import AddContact from './add-contact' +import ViewContact from './view-contact' +import MyAccounts from './my-accounts' export default class ContactListTab extends Component { static contextTypes = { diff --git a/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js b/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js index 63a7db52d795..8871830a8443 100644 --- a/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js +++ b/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js @@ -1,4 +1,3 @@ -import ContactListTab from './contact-list-tab.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -14,6 +13,7 @@ import { CONTACT_MY_ACCOUNTS_VIEW_ROUTE, CONTACT_MY_ACCOUNTS_EDIT_ROUTE, } from '../../../helpers/constants/routes' +import ContactListTab from './contact-list-tab.component' const mapStateToProps = (state, ownProps) => { diff --git a/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js b/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js index 4cd7bd59ecab..b372fae5f7cf 100644 --- a/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js +++ b/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js @@ -1,4 +1,3 @@ -import EditContact from './edit-contact.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -11,6 +10,7 @@ import { CONTACT_LIST_ROUTE, } from '../../../../helpers/constants/routes' import { addToAddressBook, removeFromAddressBook, setAccountLabel } from '../../../../store/actions' +import EditContact from './edit-contact.component' const mapStateToProps = (state, ownProps) => { const { location } = ownProps diff --git a/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.container.js b/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.container.js index 86e569e3dac7..6dab955b6991 100644 --- a/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.container.js +++ b/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.container.js @@ -1,8 +1,8 @@ -import ViewContact from './my-accounts.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { accountsWithSendEtherInfoSelector } from '../../../../selectors' +import ViewContact from './my-accounts.component' const mapStateToProps = (state) => { const myAccounts = accountsWithSendEtherInfoSelector(state) diff --git a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js index 33579d1545ea..87bf707db144 100644 --- a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js +++ b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js @@ -1,4 +1,3 @@ -import ViewContact from './view-contact.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -11,6 +10,7 @@ import { CONTACT_MY_ACCOUNTS_ROUTE, CONTACT_MY_ACCOUNTS_VIEW_ROUTE, } from '../../../../helpers/constants/routes' +import ViewContact from './view-contact.component' const mapStateToProps = (state, ownProps) => { const { location } = ownProps diff --git a/ui/app/pages/settings/networks-tab/networks-tab.component.js b/ui/app/pages/settings/networks-tab/networks-tab.component.js index e0046edfc3ac..f9cb6104801b 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.component.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.component.js @@ -1,12 +1,12 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' +import classnames from 'classnames' import { SETTINGS_ROUTE } from '../../../helpers/constants/routes' import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import classnames from 'classnames' import Button from '../../../components/ui/button' -import NetworkForm from './network-form' import NetworkDropdownIcon from '../../../components/app/dropdowns/components/network-dropdown-icon' +import NetworkForm from './network-form' export default class NetworksTab extends PureComponent { static contextTypes = { diff --git a/ui/app/pages/settings/networks-tab/networks-tab.container.js b/ui/app/pages/settings/networks-tab/networks-tab.container.js index 9377a1111be8..282078246dac 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.container.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.container.js @@ -1,4 +1,3 @@ -import NetworksTab from './networks-tab.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -10,6 +9,7 @@ import { editRpc, showModal, } from '../../../store/actions' +import NetworksTab from './networks-tab.component' import { defaultNetworksData } from './networks-tab.constants' const defaultNetworks = defaultNetworksData.map((network) => ({ ...network, viewOnly: true })) diff --git a/ui/app/pages/settings/security-tab/security-tab.container.js b/ui/app/pages/settings/security-tab/security-tab.container.js index 9852b685ed91..cfbcfbeb9abd 100644 --- a/ui/app/pages/settings/security-tab/security-tab.container.js +++ b/ui/app/pages/settings/security-tab/security-tab.container.js @@ -1,4 +1,3 @@ -import SecurityTab from './security-tab.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -7,6 +6,7 @@ import { setParticipateInMetaMetrics, setUsePhishDetect, } from '../../../store/actions' +import SecurityTab from './security-tab.component' const mapStateToProps = (state) => { const { appState: { warning }, metamask } = state diff --git a/ui/app/pages/settings/security-tab/tests/security-tab.test.js b/ui/app/pages/settings/security-tab/tests/security-tab.test.js index d5720aa6a0e2..1fa1b2eb8ea8 100644 --- a/ui/app/pages/settings/security-tab/tests/security-tab.test.js +++ b/ui/app/pages/settings/security-tab/tests/security-tab.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import SecurityTab from '../index' diff --git a/ui/app/pages/settings/settings-tab/settings-tab.container.js b/ui/app/pages/settings/settings-tab/settings-tab.container.js index 1d9f657504cf..0915ccf7cbc1 100644 --- a/ui/app/pages/settings/settings-tab/settings-tab.container.js +++ b/ui/app/pages/settings/settings-tab/settings-tab.container.js @@ -1,4 +1,3 @@ -import SettingsTab from './settings-tab.component' import { connect } from 'react-redux' import { setCurrentCurrency, @@ -8,6 +7,7 @@ import { setParticipateInMetaMetrics, } from '../../../store/actions' import { getPreferences } from '../../../selectors' +import SettingsTab from './settings-tab.component' const mapStateToProps = (state) => { const { appState: { warning }, metamask } = state diff --git a/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js index 7fefd559e87a..290d5081a9f2 100644 --- a/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js +++ b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import SettingsTab from '../index' diff --git a/ui/app/pages/settings/settings.component.js b/ui/app/pages/settings/settings.component.js index 866ed4be7f8f..d4372eed04af 100644 --- a/ui/app/pages/settings/settings.component.js +++ b/ui/app/pages/settings/settings.component.js @@ -1,15 +1,8 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import { Switch, Route, matchPath } from 'react-router-dom' -import TabBar from '../../components/app/tab-bar' import classnames from 'classnames' -import SettingsTab from './settings-tab' -import AlertsTab from './alerts-tab' -import NetworksTab from './networks-tab' -import AdvancedTab from './advanced-tab' -import InfoTab from './info-tab' -import SecurityTab from './security-tab' -import ContactListTab from './contact-list-tab' +import TabBar from '../../components/app/tab-bar' import { ALERTS_ROUTE, ADVANCED_ROUTE, @@ -26,6 +19,13 @@ import { CONTACT_MY_ACCOUNTS_VIEW_ROUTE, CONTACT_MY_ACCOUNTS_EDIT_ROUTE, } from '../../helpers/constants/routes' +import SettingsTab from './settings-tab' +import AlertsTab from './alerts-tab' +import NetworksTab from './networks-tab' +import AdvancedTab from './advanced-tab' +import InfoTab from './info-tab' +import SecurityTab from './security-tab' +import ContactListTab from './contact-list-tab' class SettingsPage extends PureComponent { static propTypes = { diff --git a/ui/app/pages/settings/settings.container.js b/ui/app/pages/settings/settings.container.js index e0b3cfbaf007..f1881581b5b6 100644 --- a/ui/app/pages/settings/settings.container.js +++ b/ui/app/pages/settings/settings.container.js @@ -1,4 +1,3 @@ -import Settings from './settings.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -24,6 +23,7 @@ import { CONTACT_MY_ACCOUNTS_EDIT_ROUTE, CONTACT_MY_ACCOUNTS_VIEW_ROUTE, } from '../../helpers/constants/routes' +import Settings from './settings.component' const ROUTES_TO_I18N_KEYS = { [GENERAL_ROUTE]: 'general', diff --git a/ui/app/pages/token/fee-card/fee-card.stories.js b/ui/app/pages/token/fee-card/fee-card.stories.js index 3e5b854bcb16..d29807d999e4 100644 --- a/ui/app/pages/token/fee-card/fee-card.stories.js +++ b/ui/app/pages/token/fee-card/fee-card.stories.js @@ -1,7 +1,7 @@ import React from 'react' -import FeeCard from './fee-card' import { action } from '@storybook/addon-actions' import { text } from '@storybook/addon-knobs/react' +import FeeCard from './fee-card' const containerStyle = { width: '300px', diff --git a/ui/app/pages/unlock-page/tests/unlock-page.test.js b/ui/app/pages/unlock-page/tests/unlock-page.test.js index ec4eb914d257..33ae361caa57 100644 --- a/ui/app/pages/unlock-page/tests/unlock-page.test.js +++ b/ui/app/pages/unlock-page/tests/unlock-page.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import UnlockPage from '../index' diff --git a/ui/app/pages/unlock-page/unlock-page.component.js b/ui/app/pages/unlock-page/unlock-page.component.js index ffaadc5ee125..5fffbf3994e2 100644 --- a/ui/app/pages/unlock-page/unlock-page.component.js +++ b/ui/app/pages/unlock-page/unlock-page.component.js @@ -1,9 +1,9 @@ +import { EventEmitter } from 'events' import React, { Component } from 'react' import PropTypes from 'prop-types' import Button from '@material-ui/core/Button' -import TextField from '../../components/ui/text-field' import getCaretCoordinates from 'textarea-caret' -import { EventEmitter } from 'events' +import TextField from '../../components/ui/text-field' import Mascot from '../../components/ui/mascot' import { DEFAULT_ROUTE } from '../../helpers/constants/routes' diff --git a/ui/app/selectors/custom-gas.js b/ui/app/selectors/custom-gas.js index 816242874a0d..8c0c74ab7fc1 100644 --- a/ui/app/selectors/custom-gas.js +++ b/ui/app/selectors/custom-gas.js @@ -1,11 +1,9 @@ +import { addHexPrefix } from 'ethereumjs-util' import { conversionUtil, multiplyCurrencies, conversionGreaterThan, } from '../helpers/utils/conversion-util' -import { - getCurrentCurrency, getIsMainnet, getPreferences, -} from '.' import { formatCurrency, } from '../helpers/utils/confirm-tx.util' @@ -18,9 +16,11 @@ import { import { calcGasTotal, } from '../pages/send/send.utils' -import { addHexPrefix } from 'ethereumjs-util' import { GAS_ESTIMATE_TYPES } from '../helpers/constants/common' +import { + getCurrentCurrency, getIsMainnet, getPreferences, +} from '.' const NUMBER_OF_DECIMALS_SM_BTNS = 5 diff --git a/ui/app/selectors/permissions.js b/ui/app/selectors/permissions.js index 47d7857da53d..22247e60710a 100644 --- a/ui/app/selectors/permissions.js +++ b/ui/app/selectors/permissions.js @@ -1,8 +1,8 @@ import { forOwn } from 'lodash' -import { getMetaMaskAccountsOrdered, getOriginOfCurrentTab, getSelectedAddress } from '.' import { CAVEAT_NAMES, } from '../../../app/scripts/controllers/permissions/enums' +import { getMetaMaskAccountsOrdered, getOriginOfCurrentTab, getSelectedAddress } from '.' // selectors diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index cfa68018647f..b759ccb9bf71 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -1,6 +1,6 @@ -import { NETWORK_TYPES } from '../helpers/constants/common' import { stripHexPrefix, addHexPrefix } from 'ethereumjs-util' import { createSelector } from 'reselect' +import { NETWORK_TYPES } from '../helpers/constants/common' import { shortenAddress, checksumAddress, diff --git a/ui/app/selectors/send.js b/ui/app/selectors/send.js index 8244983a5a14..dd17f90aca3e 100644 --- a/ui/app/selectors/send.js +++ b/ui/app/selectors/send.js @@ -1,4 +1,5 @@ import abi from 'human-standard-token-abi' +import { calcGasTotal } from '../pages/send/send.utils' import { accountsWithSendEtherInfoSelector, getAddressBook, @@ -6,7 +7,6 @@ import { getTargetAccount, getAveragePriceEstimateInHexWEI, } from '.' -import { calcGasTotal } from '../pages/send/send.utils' export function getBlockGasLimit (state) { return state.metamask.currentBlockGasLimit diff --git a/ui/app/selectors/transactions.js b/ui/app/selectors/transactions.js index f0d63b11532a..4faa6a91ea24 100644 --- a/ui/app/selectors/transactions.js +++ b/ui/app/selectors/transactions.js @@ -10,10 +10,10 @@ import { TRANSACTION_TYPE_RETRY, } from '../../../app/scripts/controllers/transactions/enums' import { hexToDecimal } from '../helpers/utils/conversions.util' +import txHelper from '../../lib/tx-helper' import { getSelectedAddress, } from '.' -import txHelper from '../../lib/tx-helper' export const incomingTxListSelector = (state) => { const { showIncomingTransactions } = state.metamask.featureFlags diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index af32443f65a2..4d9f7a4b3957 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -1,26 +1,26 @@ import abi from 'human-standard-token-abi' import pify from 'pify' +import ethUtil from 'ethereumjs-util' +import log from 'loglevel' import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url' import { checksumAddress } from '../helpers/utils/util' import { calcTokenBalance, estimateGas } from '../pages/send/send.utils' -import ethUtil from 'ethereumjs-util' import { fetchLocale, loadRelativeTimeFormatLocaleData } from '../helpers/utils/i18n-helper' import { getMethodDataAsync } from '../helpers/utils/transactions.util' import { fetchSymbolAndDecimals } from '../helpers/utils/token-util' import switchDirection from '../helpers/utils/switch-direction' -import log from 'loglevel' import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../app/scripts/lib/enums' import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util' import { setCustomGasLimit } from '../ducks/gas/gas.duck' import txHelper from '../../lib/tx-helper' import { getEnvironmentType } from '../../../app/scripts/lib/util' -import * as actionConstants from './actionConstants' import { getPermittedAccountsForCurrentTab, getSelectedAddress, } from '../selectors' import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account' import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask' +import * as actionConstants from './actionConstants' let background = null let promisifiedBackground = null diff --git a/ui/index.js b/ui/index.js index 8131b66cc9a8..41da33b4a47c 100644 --- a/ui/index.js +++ b/ui/index.js @@ -3,14 +3,14 @@ import log from 'loglevel' import { clone } from 'lodash' import React from 'react' import { render } from 'react-dom' -import Root from './app/pages' -import * as actions from './app/store/actions' -import configureStore from './app/store/store' -import txHelper from './lib/tx-helper' import { getEnvironmentType } from '../app/scripts/lib/util' import { ALERT_TYPES } from '../app/scripts/controllers/alert' import { SENTRY_STATE } from '../app/scripts/lib/setupSentry' import { ENVIRONMENT_TYPE_POPUP } from '../app/scripts/lib/enums' +import Root from './app/pages' +import * as actions from './app/store/actions' +import configureStore from './app/store/store' +import txHelper from './lib/tx-helper' import { fetchLocale, loadRelativeTimeFormatLocaleData } from './app/helpers/utils/i18n-helper' import switchDirection from './app/helpers/utils/switch-direction' import { getPermittedAccountsForCurrentTab, getSelectedAddress } from './app/selectors' diff --git a/ui/lib/icon-factory.js b/ui/lib/icon-factory.js index 077604195508..142e7bbfd6df 100644 --- a/ui/lib/icon-factory.js +++ b/ui/lib/icon-factory.js @@ -1,7 +1,7 @@ let iconFactory import { isValidAddress } from 'ethereumjs-util' -import { checksumAddress } from '../app/helpers/utils/util' import contractMap from 'eth-contract-metadata' +import { checksumAddress } from '../app/helpers/utils/util' export default function iconFactoryGenerator (jazzicon) { if (!iconFactory) { diff --git a/ui/lib/tx-helper.js b/ui/lib/tx-helper.js index 03a7b3e1e4eb..fcb264c0c69e 100644 --- a/ui/lib/tx-helper.js +++ b/ui/lib/tx-helper.js @@ -1,5 +1,5 @@ -import { valuesFor } from '../app/helpers/utils/util' import log from 'loglevel' +import { valuesFor } from '../app/helpers/utils/util' export default function txHelper (unapprovedTxs, unapprovedMsgs, personalMsgs, decryptMsgs, encryptionPublicKeyMsgs, typedMessages, network) { log.debug('tx-helper called with params:') From 09e7f24b2d464d0be8404bb05944fff6217aae91 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 18 Aug 2020 16:53:36 -0230 Subject: [PATCH 122/137] Adds pulse loader component (#9259) * Adds pulse loader component * Move pulse-loader component to the UI directory --- ui/app/components/app/index.scss | 1 + ui/app/components/ui/pulse-loader/index.js | 1 + ui/app/components/ui/pulse-loader/index.scss | 63 +++++++++++++++++++ .../ui/pulse-loader/pulse-loader.js | 11 ++++ .../ui/pulse-loader/pulse-loader.stories.js | 8 +++ 5 files changed, 84 insertions(+) create mode 100644 ui/app/components/ui/pulse-loader/index.js create mode 100644 ui/app/components/ui/pulse-loader/index.scss create mode 100644 ui/app/components/ui/pulse-loader/pulse-loader.js create mode 100644 ui/app/components/ui/pulse-loader/pulse-loader.stories.js diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/index.scss index 5102d1c986fc..3b708f68ee79 100644 --- a/ui/app/components/app/index.scss +++ b/ui/app/components/app/index.scss @@ -65,3 +65,4 @@ @import '../ui/account-mismatch-warning/index'; @import '../ui/icon-border/icon-border'; @import '../ui/info-tooltip/index'; +@import '../ui/pulse-loader/index'; diff --git a/ui/app/components/ui/pulse-loader/index.js b/ui/app/components/ui/pulse-loader/index.js new file mode 100644 index 000000000000..1fad53e562bf --- /dev/null +++ b/ui/app/components/ui/pulse-loader/index.js @@ -0,0 +1 @@ +export { default } from './pulse-loader' diff --git a/ui/app/components/ui/pulse-loader/index.scss b/ui/app/components/ui/pulse-loader/index.scss new file mode 100644 index 000000000000..2a0447ffe53a --- /dev/null +++ b/ui/app/components/ui/pulse-loader/index.scss @@ -0,0 +1,63 @@ +.pulse-loader { + display: flex; + + &__loading-dot-one, + &__loading-dot-two, + &__loading-dot-three { + background: $Blue-500; + width: 4px; + height: 4px; + margin-right: 2px; + border-radius: 100%; + animation-fill-mode: both; + } + + &__loading-dot-one { + -webkit-animation: loading-dot 0.75s 0.12s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); + animation: loading-dot 0.75s 0.12s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); + } + + &__loading-dot-two { + -webkit-animation: loading-dot 0.75s 0.24s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); + animation: loading-dot 0.75s 0.24s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); + } + + &__loading-dot-three { + -webkit-animation: loading-dot 0.75s 0.36s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); + animation: loading-dot 0.75s 0.36s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); + } + + @-webkit-keyframes loading-dot { + 0% { + transform: scale(1); + opacity: 1; + } + + 45% { + transform: scale(0.7); + opacity: 0.7; + } + + 80% { + transform: scale(1); + opacity: 1; + } + } + + @keyframes loading-dot { + 0% { + transform: scale(1); + opacity: 1; + } + + 45% { + transform: scale(0.7); + opacity: 0.7; + } + + 80% { + transform: scale(1); + opacity: 1; + } + } +} diff --git a/ui/app/components/ui/pulse-loader/pulse-loader.js b/ui/app/components/ui/pulse-loader/pulse-loader.js new file mode 100644 index 000000000000..b1cc13731736 --- /dev/null +++ b/ui/app/components/ui/pulse-loader/pulse-loader.js @@ -0,0 +1,11 @@ +import React from 'react' + +export default function PulseLoader () { + return ( +
+
+
+
+
+ ) +} diff --git a/ui/app/components/ui/pulse-loader/pulse-loader.stories.js b/ui/app/components/ui/pulse-loader/pulse-loader.stories.js new file mode 100644 index 000000000000..4823ac604a78 --- /dev/null +++ b/ui/app/components/ui/pulse-loader/pulse-loader.stories.js @@ -0,0 +1,8 @@ +import React from 'react' +import PulseLoader from '.' + +export default { + title: 'PulseLoader', +} + +export const common = () => () From 6f4c3b34058f6403f0208bbfe761e0287cc5dc38 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 18 Aug 2020 16:54:47 -0230 Subject: [PATCH 123/137] Tidy up Migrator tests (#9264) --- test/unit/migrations/migrator-test.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/test/unit/migrations/migrator-test.js b/test/unit/migrations/migrator-test.js index 3cf08c35520a..de4d16c45212 100644 --- a/test/unit/migrations/migrator-test.js +++ b/test/unit/migrations/migrator-test.js @@ -3,29 +3,30 @@ import assert from 'assert' import { cloneDeep } from 'lodash' import Migrator from '../../../app/scripts/lib/migrator' import liveMigrations from '../../../app/scripts/migrations' +import data from '../../../app/scripts/first-time-state' const stubMigrations = [ { version: 1, - migrate: (data) => { + migrate: (state) => { // clone the data just like we do in migrations - const clonedData = cloneDeep(data) + const clonedData = cloneDeep(state) clonedData.meta.version = 1 return Promise.resolve(clonedData) }, }, { version: 2, - migrate: (data) => { - const clonedData = cloneDeep(data) + migrate: (state) => { + const clonedData = cloneDeep(state) clonedData.meta.version = 2 return Promise.resolve(clonedData) }, }, { version: 3, - migrate: (data) => { - const clonedData = cloneDeep(data) + migrate: (state) => { + const clonedData = cloneDeep(state) clonedData.meta.version = 3 return Promise.resolve(clonedData) }, @@ -33,8 +34,6 @@ const stubMigrations = [ ] const versionedData = { meta: { version: 0 }, data: { hello: 'world' } } -import data from '../../../app/scripts/first-time-state' - const firstTimeState = { meta: { version: 0 }, data, From 8b0a308449c23379cfa082e8acd51897ad5285bf Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Tue, 18 Aug 2020 14:44:32 -0500 Subject: [PATCH 124/137] colocate confirm-decrypt-message page styles (#9252) Follows the previously set pattern of colocating styles along side the consuming components. This one was really straight forward and just a reorganization of files and imports. No code changes occurred. --- ui/app/css/itcss/components/index.scss | 1 - .../confirm-decrypt-message/confirm-decrypt-message.scss} | 0 ui/app/pages/index.scss | 1 + 3 files changed, 1 insertion(+), 1 deletion(-) rename ui/app/{css/itcss/components/request-decrypt-message.scss => pages/confirm-decrypt-message/confirm-decrypt-message.scss} (100%) diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 58d0b7b9116a..367d6c113e72 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -13,6 +13,5 @@ // Tx List and Sections @import './gas-slider'; @import './simple-dropdown'; -@import './request-decrypt-message'; @import './pages/index'; @import '../../../components/app/index'; diff --git a/ui/app/css/itcss/components/request-decrypt-message.scss b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.scss similarity index 100% rename from ui/app/css/itcss/components/request-decrypt-message.scss rename to ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.scss diff --git a/ui/app/pages/index.scss b/ui/app/pages/index.scss index 9c0b3f1b22d5..85237eda361e 100644 --- a/ui/app/pages/index.scss +++ b/ui/app/pages/index.scss @@ -4,6 +4,7 @@ @import 'home/index'; @import 'send/send'; @import 'confirm-add-token/index'; +@import 'confirm-decrypt-message/confirm-decrypt-message'; @import 'confirm-encryption-public-key/confirm-encryption-public-key'; @import 'connected-sites/index'; @import 'connected-accounts/index'; From 6ab12001e3dc24679efe194741b8a363dbf66db3 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 18 Aug 2020 17:36:58 -0230 Subject: [PATCH 125/137] Fix prefer-destructuring issues (#9263) See [`prefer-destructuring`](https://eslint.org/docs/rules/prefer-destructuring) for more information. This change enables `prefer-destructuring` and fixes the issues raised by the rule. --- .eslintrc.js | 12 +++++++ app/scripts/background.js | 10 +++--- app/scripts/contentscript.js | 2 +- app/scripts/controllers/network/network.js | 2 +- app/scripts/controllers/preferences.js | 15 ++++---- app/scripts/controllers/threebox.js | 2 +- app/scripts/controllers/transactions/index.js | 3 +- .../transactions/pending-tx-tracker.js | 2 +- .../controllers/transactions/tx-gas-utils.js | 2 +- .../transactions/tx-state-manager.js | 2 +- app/scripts/lib/account-tracker.js | 10 +++--- app/scripts/lib/cleanErrorStack.js | 2 +- app/scripts/lib/local-store.js | 4 +-- app/scripts/lib/setupSentry.js | 3 +- app/scripts/lib/typed-message-manager.js | 2 +- app/scripts/lib/util.js | 2 +- app/scripts/metamask-controller.js | 35 ++++++++++--------- app/scripts/migrations/005.js | 2 +- app/scripts/migrations/015.js | 2 +- app/scripts/migrations/016.js | 2 +- app/scripts/migrations/017.js | 2 +- app/scripts/migrations/018.js | 2 +- app/scripts/migrations/019.js | 6 ++-- app/scripts/migrations/022.js | 2 +- app/scripts/migrations/023.js | 2 +- app/scripts/migrations/024.js | 2 +- app/scripts/migrations/025.js | 2 +- app/scripts/migrations/027.js | 2 +- app/scripts/migrations/028.js | 3 +- app/scripts/migrations/030.js | 2 +- app/scripts/migrations/fail-tx.js | 2 +- development/build/scripts.js | 3 +- development/metamaskbot-build-announce.js | 7 ++-- test/e2e/ganache.js | 2 +- .../network/network-controller-test.js | 2 +- .../preferences-controller-test.js | 2 +- test/unit/migrations/026-test.js | 2 +- test/unit/ui/app/actions.spec.js | 2 +- .../app/dropdowns/network-dropdown.js | 4 +-- .../gas-modal-page-container.container.js | 2 +- .../app/menu-bar/account-options-menu.js | 2 +- ui/app/components/app/menu-droppo.js | 9 +++-- ui/app/ducks/metamask/metamask.js | 2 +- ui/app/helpers/utils/conversion-util.js | 2 +- ui/app/hooks/useCancelTransaction.js | 2 +- .../add-recipient/ens-input.component.js | 2 +- .../advanced-tab/advanced-tab.component.js | 2 +- ui/app/selectors/custom-gas.js | 4 +-- ui/app/selectors/selectors.js | 6 ++-- ui/app/selectors/transactions.js | 2 +- ui/index.js | 2 +- 51 files changed, 105 insertions(+), 99 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 6822190538e1..cfb2e30880fd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -71,6 +71,18 @@ module.exports = { 'no-template-curly-in-string': 'error', 'no-useless-catch': 'error', 'no-useless-concat': 'error', + 'prefer-destructuring': ['error', { + 'VariableDeclarator': { + 'array': false, + 'object': true, + }, + 'AssignmentExpression': { + 'array': false, + 'object': false, + }, + }, { + 'enforceForRenamedProperties': false, + }], 'prefer-rest-params': 'error', 'prefer-spread': 'error', 'radix': 'error', diff --git a/app/scripts/background.js b/app/scripts/background.js index fcf504107bc2..b88d3b83f5f2 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -406,11 +406,11 @@ function setupController (initState, initLangCode) { function updateBadge () { let label = '' const unapprovedTxCount = controller.txController.getUnapprovedTxCount() - const unapprovedMsgCount = controller.messageManager.unapprovedMsgCount - const unapprovedPersonalMsgCount = controller.personalMessageManager.unapprovedPersonalMsgCount - const unapprovedDecryptMsgCount = controller.decryptMessageManager.unapprovedDecryptMsgCount - const unapprovedEncryptionPublicKeyMsgCount = controller.encryptionPublicKeyManager.unapprovedEncryptionPublicKeyMsgCount - const unapprovedTypedMessagesCount = controller.typedMessageManager.unapprovedTypedMessagesCount + const { unapprovedMsgCount } = controller.messageManager + const { unapprovedPersonalMsgCount } = controller.personalMessageManager + const { unapprovedDecryptMsgCount } = controller.decryptMessageManager + const { unapprovedEncryptionPublicKeyMsgCount } = controller.encryptionPublicKeyManager + const { unapprovedTypedMessagesCount } = controller.typedMessageManager const pendingPermissionRequests = Object.keys(controller.permissionsController.permissions.state.permissionsRequests).length const waitingForUnlockCount = controller.appStateController.waitingForUnlock.length const count = unapprovedTxCount + unapprovedMsgCount + unapprovedPersonalMsgCount + unapprovedDecryptMsgCount + unapprovedEncryptionPublicKeyMsgCount + diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 8926f439ce84..4c5bcecc2fd3 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -136,7 +136,7 @@ function shouldInjectProvider () { * @returns {boolean} {@code true} - if the doctype is html or if none exists */ function doctypeCheck () { - const doctype = window.document.doctype + const { doctype } = window.document if (doctype) { return doctype.name === 'html' } else { diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 7d45cc5a4daa..27d7093d1bb3 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -22,7 +22,7 @@ import { } from './enums' const env = process.env.METAMASK_ENV -const METAMASK_DEBUG = process.env.METAMASK_DEBUG +const { METAMASK_DEBUG } = process.env let defaultProviderConfigType if (process.env.IN_TEST === 'true') { diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 436648af84a9..739004d93f91 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -178,7 +178,7 @@ export default class PreferencesController { * @param {string} methodData - Corresponding data method */ addKnownMethodData (fourBytePrefix, methodData) { - const knownMethodData = this.store.getState().knownMethodData + const { knownMethodData } = this.store.getState() knownMethodData[fourBytePrefix] = methodData this.store.updateState({ knownMethodData }) } @@ -264,8 +264,8 @@ export default class PreferencesController { * @returns {string} - the address that was removed */ removeAddress (address) { - const identities = this.store.getState().identities - const accountTokens = this.store.getState().accountTokens + const { identities } = this.store.getState() + const { accountTokens } = this.store.getState() if (!identities[address]) { throw new Error(`${address} can't be deleted cause it was not found`) } @@ -290,8 +290,7 @@ export default class PreferencesController { * */ addAddresses (addresses) { - const identities = this.store.getState().identities - const accountTokens = this.store.getState().accountTokens + const { identities, accountTokens } = this.store.getState() addresses.forEach((address) => { // skip if already exists if (identities[address]) { @@ -420,7 +419,7 @@ export default class PreferencesController { async addToken (rawAddress, symbol, decimals, image) { const address = normalizeAddress(rawAddress) const newEntry = { address, symbol, decimals } - const tokens = this.store.getState().tokens + const { tokens } = this.store.getState() const assetImages = this.getAssetImages() const previousEntry = tokens.find((token) => { return token.address === address @@ -445,7 +444,7 @@ export default class PreferencesController { * */ removeToken (rawAddress) { - const tokens = this.store.getState().tokens + const { tokens } = this.store.getState() const assetImages = this.getAssetImages() const updatedTokens = tokens.filter((token) => token.address !== rawAddress) delete assetImages[rawAddress] @@ -688,7 +687,7 @@ export default class PreferencesController { * */ _getTokenRelatedStates (selectedAddress) { - const accountTokens = this.store.getState().accountTokens + const { accountTokens } = this.store.getState() if (!selectedAddress) { // eslint-disable-next-line no-param-reassign selectedAddress = this.store.getState().selectedAddress diff --git a/app/scripts/controllers/threebox.js b/app/scripts/controllers/threebox.js index 92e4ae9071b1..dc83f3673a0d 100644 --- a/app/scripts/controllers/threebox.js +++ b/app/scripts/controllers/threebox.js @@ -35,7 +35,7 @@ export default class ThreeBoxController { if (origin !== '3Box') { return [] } - const isUnlocked = getKeyringControllerState().isUnlocked + const { isUnlocked } = getKeyringControllerState() const accounts = await this.keyringController.getAccounts() diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 22ace157e65f..ffc8246dbbd4 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -756,8 +756,7 @@ export default class TransactionController extends EventEmitter { _setupBlockTrackerListener () { let listenersAreActive = false const latestBlockHandler = this._onLatestBlock.bind(this) - const blockTracker = this.blockTracker - const txStateManager = this.txStateManager + const { blockTracker, txStateManager } = this txStateManager.on('tx:status-update', updateSubscription) updateSubscription() diff --git a/app/scripts/controllers/transactions/pending-tx-tracker.js b/app/scripts/controllers/transactions/pending-tx-tracker.js index 8066a116f418..3ae85e4fa067 100644 --- a/app/scripts/controllers/transactions/pending-tx-tracker.js +++ b/app/scripts/controllers/transactions/pending-tx-tracker.js @@ -137,7 +137,7 @@ export default class PendingTransactionTracker extends EventEmitter { return this.approveTransaction(txMeta.id) } - const rawTx = txMeta.rawTx + const { rawTx } = txMeta const txHash = await this.publishTransaction(rawTx) // Increment successful tries: diff --git a/app/scripts/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js index 0812820665b5..4b897b9680bd 100644 --- a/app/scripts/controllers/transactions/tx-gas-utils.js +++ b/app/scripts/controllers/transactions/tx-gas-utils.js @@ -56,7 +56,7 @@ export default class TxGasUtil { @returns {string} - the estimated gas limit as a hex string */ async estimateTxGas (txMeta) { - const txParams = txMeta.txParams + const { txParams } = txMeta // estimate tx gas requirements return await this.query.estimateGas(txParams) diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 5239bd60a68a..bbdd51872fa5 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -178,7 +178,7 @@ export default class TransactionStateManager extends EventEmitter { const transactions = this.getFullTxList() const txCount = transactions.length - const txHistoryLimit = this.txHistoryLimit + const { txHistoryLimit } = this // checks if the length of the tx history is // longer then desired persistence limit diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index f84a9708bcf5..2d97a1382c79 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -92,7 +92,7 @@ export default class AccountTracker { * */ syncWithAddresses (addresses) { - const accounts = this.store.getState().accounts + const { accounts } = this.store.getState() const locals = Object.keys(accounts) const accountsToAdd = [] @@ -121,7 +121,7 @@ export default class AccountTracker { * */ addAccounts (addresses) { - const accounts = this.store.getState().accounts + const { accounts } = this.store.getState() // add initial state for addresses addresses.forEach((address) => { accounts[address] = {} @@ -142,7 +142,7 @@ export default class AccountTracker { * */ removeAccount (addresses) { - const accounts = this.store.getState().accounts + const { accounts } = this.store.getState() // remove each state object addresses.forEach((address) => { delete accounts[address] @@ -194,7 +194,7 @@ export default class AccountTracker { * */ async _updateAccounts () { - const accounts = this.store.getState().accounts + const { accounts } = this.store.getState() const addresses = Object.keys(accounts) const currentNetwork = this.network.getNetworkState() @@ -248,7 +248,7 @@ export default class AccountTracker { * @param {*} deployedContractAddress */ async _updateAccountsViaBalanceChecker (addresses, deployedContractAddress) { - const accounts = this.store.getState().accounts + const { accounts } = this.store.getState() this.web3.setProvider(this._provider) const ethContract = this.web3.eth.contract(SINGLE_CALL_BALANCES_ABI).at(deployedContractAddress) const ethBalance = ['0x0'] diff --git a/app/scripts/lib/cleanErrorStack.js b/app/scripts/lib/cleanErrorStack.js index 5b59ff66ebce..46e069e8e722 100644 --- a/app/scripts/lib/cleanErrorStack.js +++ b/app/scripts/lib/cleanErrorStack.js @@ -4,7 +4,7 @@ * @returns {Error} - Error with clean stack trace. */ export default function cleanErrorStack (err) { - let name = err.name + let { name } = err name = (name === undefined) ? 'Error' : String(name) let msg = err.message diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index a0c0a667aa49..5d51b5f725ed 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -49,7 +49,7 @@ export default class ExtensionStore { * @returns {Object} - the key-value map from local storage */ _get () { - const local = extension.storage.local + const { local } = extension.storage return new Promise((resolve, reject) => { local.get(null, (/** @type {any} */ result) => { const err = checkForError() @@ -69,7 +69,7 @@ export default class ExtensionStore { * @private */ _set (obj) { - const local = extension.storage.local + const { local } = extension.storage return new Promise((resolve, reject) => { local.set(obj, () => { const err = checkForError() diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 02ad02d6bd2a..b5e4f2bec449 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -3,8 +3,7 @@ import { Dedupe, ExtraErrorData } from '@sentry/integrations' import extractEthjsErrorMessage from './extractEthjsErrorMessage' -const METAMASK_DEBUG = process.env.METAMASK_DEBUG -const METAMASK_ENVIRONMENT = process.env.METAMASK_ENVIRONMENT +const { METAMASK_DEBUG, METAMASK_ENVIRONMENT } = process.env const SENTRY_DSN_DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' // This describes the subset of Redux state attached to errors sent to Sentry diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index 324ef6936c98..8c3caca2eacd 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -164,7 +164,7 @@ export default class TypedMessageManager extends EventEmitter { const validation = jsonschema.validate(data, sigUtil.TYPED_MESSAGE_SCHEMA) assert.ok(data.primaryType in data.types, `Primary type of "${data.primaryType}" has no type definition.`) assert.equal(validation.errors.length, 0, 'Signing data must conform to EIP-712 schema. See https://git.io/fNtcx.') - const chainId = data.domain.chainId + const { chainId } = data.domain // eslint-disable-next-line radix const activeChainId = parseInt(this.networkController.getNetworkState()) chainId && assert.equal(chainId, activeChainId, `Provided chainId "${chainId}" must match the active chainId "${activeChainId}"`) diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index 243a00b65103..6d06758b3e9c 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -138,7 +138,7 @@ function BnMultiplyByFraction (targetBN, numerator, denominator) { * @returns {Error|undefined} */ function checkForError () { - const lastError = extension.runtime.lastError + const { lastError } = extension.runtime if (!lastError) { return undefined } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 656777eb2626..e7d1de51d23e 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -406,7 +406,7 @@ export default class MetamaskController extends EventEmitter { * @returns {Object} - status */ getState () { - const vault = this.keyringController.store.getState().vault + const { vault } = this.keyringController.store.getState() const isInitialized = !!vault return { @@ -423,14 +423,16 @@ export default class MetamaskController extends EventEmitter { * @returns {Object} - Object containing API functions. */ getApi () { - const keyringController = this.keyringController - const networkController = this.networkController - const onboardingController = this.onboardingController - const alertController = this.alertController - const permissionsController = this.permissionsController - const preferencesController = this.preferencesController - const threeBoxController = this.threeBoxController - const txController = this.txController + const { + keyringController, + networkController, + onboardingController, + alertController, + permissionsController, + preferencesController, + threeBoxController, + txController, + } = this return { // etc @@ -612,7 +614,7 @@ export default class MetamaskController extends EventEmitter { try { let accounts, lastBalance - const keyringController = this.keyringController + const { keyringController } = this // clear known identities this.preferencesController.setAddresses([]) @@ -744,7 +746,7 @@ export default class MetamaskController extends EventEmitter { // transactions - let transactions = this.txController.store.getState().transactions + let { transactions } = this.txController.store.getState() // delete tx for other accounts that we're not importing transactions = transactions.filter((tx) => { const checksummedTxFrom = ethUtil.toChecksumAddress(tx.txParams.from) @@ -942,7 +944,7 @@ export default class MetamaskController extends EventEmitter { if (!primaryKeyring) { throw new Error('MetamaskController - No HD Key Tree found') } - const keyringController = this.keyringController + const { keyringController } = this const oldAccounts = await keyringController.getAccounts() const keyState = await keyringController.addNewAccount(primaryKeyring) const newAccounts = await keyringController.getAccounts() @@ -1112,7 +1114,7 @@ export default class MetamaskController extends EventEmitter { * @param {string} msgId - The id of the message to cancel. */ cancelMessage (msgId, cb) { - const messageManager = this.messageManager + const { messageManager } = this messageManager.rejectMsg(msgId) if (cb && typeof cb === 'function') { cb(null, this.getState()) @@ -1347,7 +1349,7 @@ export default class MetamaskController extends EventEmitter { async signTypedMessage (msgParams) { log.info('MetaMaskController - eth_signTypedData') const msgId = msgParams.metamaskId - const version = msgParams.version + const { version } = msgParams try { const cleanMsgParams = await this.typedMessageManager.approveMessage(msgParams) @@ -1460,7 +1462,7 @@ export default class MetamaskController extends EventEmitter { */ setupUntrustedCommunication (connectionStream, sender) { const { usePhishDetect } = this.preferencesController.store.getState() - const hostname = (new URL(sender.url)).hostname + const { hostname } = new URL(sender.url) // Check if new connection is blocked if phishing detection is on if (usePhishDetect && this.phishingController.test(hostname)) { log.debug('MetaMask - sending phishing warning for', hostname) @@ -1599,8 +1601,7 @@ export default class MetamaskController extends EventEmitter { setupProviderEngine ({ origin, location, extensionId, tabId, isInternal = false }) { // setup json rpc engine stack const engine = new RpcEngine() - const provider = this.provider - const blockTracker = this.blockTracker + const { provider, blockTracker } = this // create filter polyfill middleware const filterMiddleware = createFilterMiddleware({ provider, blockTracker }) diff --git a/app/scripts/migrations/005.js b/app/scripts/migrations/005.js index 05587c4325d5..00f3ca552d67 100644 --- a/app/scripts/migrations/005.js +++ b/app/scripts/migrations/005.js @@ -27,7 +27,7 @@ export default { } function selectSubstateForKeyringController (state) { - const config = state.config + const { config } = state const newState = { ...state, KeyringController: { diff --git a/app/scripts/migrations/015.js b/app/scripts/migrations/015.js index 4ea61b7d1da0..de6ce94bcbbd 100644 --- a/app/scripts/migrations/015.js +++ b/app/scripts/migrations/015.js @@ -30,7 +30,7 @@ function transformState (state) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = TransactionController.transactions + const { transactions } = TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (!txMeta.err) { return txMeta diff --git a/app/scripts/migrations/016.js b/app/scripts/migrations/016.js index 341658e06584..dcef6f313284 100644 --- a/app/scripts/migrations/016.js +++ b/app/scripts/migrations/016.js @@ -30,7 +30,7 @@ function transformState (state) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (!txMeta.err) { diff --git a/app/scripts/migrations/017.js b/app/scripts/migrations/017.js index e39d7855db66..8e43863adfd2 100644 --- a/app/scripts/migrations/017.js +++ b/app/scripts/migrations/017.js @@ -29,7 +29,7 @@ function transformState (state) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (!txMeta.status === 'failed') { return txMeta diff --git a/app/scripts/migrations/018.js b/app/scripts/migrations/018.js index 7a182ab2ac0c..c2dc39b260d7 100644 --- a/app/scripts/migrations/018.js +++ b/app/scripts/migrations/018.js @@ -34,7 +34,7 @@ function transformState (state) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { // no history: initialize if (!txMeta.history || txMeta.history.length === 0) { diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js index aa1e8a6cc096..d99fa6aa8fe1 100644 --- a/app/scripts/migrations/019.js +++ b/app/scripts/migrations/019.js @@ -32,7 +32,7 @@ function transformState (state) { const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => { if (txMeta.status !== 'submitted') { @@ -66,7 +66,7 @@ function transformState (state) { function getHighestContinuousFrom (txList, startPoint) { const nonces = txList.map((txMeta) => { - const nonce = txMeta.txParams.nonce + const { nonce } = txMeta.txParams return parseInt(nonce, 16) }) @@ -80,7 +80,7 @@ function getHighestContinuousFrom (txList, startPoint) { function getHighestNonce (txList) { const nonces = txList.map((txMeta) => { - const nonce = txMeta.txParams.nonce + const { nonce } = txMeta.txParams return parseInt(nonce || '0x0', 16) }) const highestNonce = Math.max.apply(null, nonces) diff --git a/app/scripts/migrations/022.js b/app/scripts/migrations/022.js index b986a94f4c79..630bc2022fae 100644 --- a/app/scripts/migrations/022.js +++ b/app/scripts/migrations/022.js @@ -30,7 +30,7 @@ function transformState (state) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (txMeta.status !== 'submitted' || txMeta.submittedTime) { diff --git a/app/scripts/migrations/023.js b/app/scripts/migrations/023.js index af4ee8d45641..b6f9a1038f60 100644 --- a/app/scripts/migrations/023.js +++ b/app/scripts/migrations/023.js @@ -31,7 +31,7 @@ function transformState (state) { const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController if (transactions.length <= 40) { return newState diff --git a/app/scripts/migrations/024.js b/app/scripts/migrations/024.js index 569c817c205a..07257d428504 100644 --- a/app/scripts/migrations/024.js +++ b/app/scripts/migrations/024.js @@ -28,7 +28,7 @@ function transformState (state) { if (!newState.TransactionController) { return newState } - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta, _) => { if ( txMeta.status === 'unapproved' && diff --git a/app/scripts/migrations/025.js b/app/scripts/migrations/025.js index 1f3721d27038..0f5f568ab77d 100644 --- a/app/scripts/migrations/025.js +++ b/app/scripts/migrations/025.js @@ -28,7 +28,7 @@ function transformState (state) { if (newState.TransactionController) { if (newState.TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (txMeta.status !== 'unapproved') { return txMeta diff --git a/app/scripts/migrations/027.js b/app/scripts/migrations/027.js index dc4d0beb7c48..2607f03da3ae 100644 --- a/app/scripts/migrations/027.js +++ b/app/scripts/migrations/027.js @@ -26,7 +26,7 @@ function transformState (state) { if (newState.TransactionController) { if (newState.TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.filter((txMeta) => txMeta.status !== 'rejected') } } diff --git a/app/scripts/migrations/028.js b/app/scripts/migrations/028.js index 09fc18f11db9..522067f8ba5d 100644 --- a/app/scripts/migrations/028.js +++ b/app/scripts/migrations/028.js @@ -26,8 +26,7 @@ function transformState (state) { if (newState.PreferencesController) { if (newState.PreferencesController.tokens && newState.PreferencesController.identities) { - const identities = newState.PreferencesController.identities - const tokens = newState.PreferencesController.tokens + const { identities, tokens } = newState.PreferencesController newState.PreferencesController.accountTokens = {} Object.keys(identities).forEach((identity) => { newState.PreferencesController.accountTokens[identity] = { 'mainnet': tokens } diff --git a/app/scripts/migrations/030.js b/app/scripts/migrations/030.js index 8b6cdeaaa051..351fbb2698ec 100644 --- a/app/scripts/migrations/030.js +++ b/app/scripts/migrations/030.js @@ -25,7 +25,7 @@ export default { function transformState (state) { const newState = state if (state.PreferencesController) { - const frequentRpcListDetail = newState.PreferencesController.frequentRpcListDetail + const { frequentRpcListDetail } = newState.PreferencesController if (frequentRpcListDetail) { frequentRpcListDetail.forEach((rpc, index) => { // eslint-disable-next-line radix diff --git a/app/scripts/migrations/fail-tx.js b/app/scripts/migrations/fail-tx.js index e5a3490331a1..c8b5f7c362ba 100644 --- a/app/scripts/migrations/fail-tx.js +++ b/app/scripts/migrations/fail-tx.js @@ -20,7 +20,7 @@ function transformState (state, condition, reason) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = TransactionController.transactions + const { transactions } = TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (!condition(txMeta)) { diff --git a/development/build/scripts.js b/development/build/scripts.js index 1f6d2f9549ac..4b06af86eb23 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -62,8 +62,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) { core.prod, ) - const dev = core.dev - const testDev = core.testDev + const { dev, testDev } = core const test = composeParallel( deps.background, diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index 2414901dedc5..a19acecc6ebb 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -12,12 +12,11 @@ function capitalizeFirstLetter (string) { async function start () { - const GITHUB_COMMENT_TOKEN = process.env.GITHUB_COMMENT_TOKEN - const CIRCLE_PULL_REQUEST = process.env.CIRCLE_PULL_REQUEST + const { GITHUB_COMMENT_TOKEN, CIRCLE_PULL_REQUEST } = process.env console.log('CIRCLE_PULL_REQUEST', CIRCLE_PULL_REQUEST) - const CIRCLE_SHA1 = process.env.CIRCLE_SHA1 + const { CIRCLE_SHA1 } = process.env console.log('CIRCLE_SHA1', CIRCLE_SHA1) - const CIRCLE_BUILD_NUM = process.env.CIRCLE_BUILD_NUM + const { CIRCLE_BUILD_NUM } = process.env console.log('CIRCLE_BUILD_NUM', CIRCLE_BUILD_NUM) if (!CIRCLE_PULL_REQUEST) { diff --git a/test/e2e/ganache.js b/test/e2e/ganache.js index 0cfbadda3661..edce5b15e4d2 100644 --- a/test/e2e/ganache.js +++ b/test/e2e/ganache.js @@ -12,7 +12,7 @@ const defaultOptions = { class Ganache { async start (opts) { const options = { ...defaultOptions, ...opts } - const port = options.port + const { port } = options this._server = ganache.server(options) const listen = promisify(this._server.listen).bind(this._server) diff --git a/test/unit/app/controllers/network/network-controller-test.js b/test/unit/app/controllers/network/network-controller-test.js index be1c7f5366a9..161df61707c2 100644 --- a/test/unit/app/controllers/network/network-controller-test.js +++ b/test/unit/app/controllers/network/network-controller-test.js @@ -53,7 +53,7 @@ describe('NetworkController', function () { it('should update provider.type', function () { networkController.initializeProvider(networkControllerProviderConfig) networkController.setProviderType('mainnet') - const type = networkController.getProviderConfig().type + const { type } = networkController.getProviderConfig() assert.equal(type, 'mainnet', 'provider type is updated') }) it('should set the network to loading', function () { diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index 5c56b0f88a35..ca5001e36908 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -39,7 +39,7 @@ describe('preferences controller', function () { '0x7e57e2', ]) - const accountTokens = preferencesController.store.getState().accountTokens + const { accountTokens } = preferencesController.store.getState() assert.deepEqual(accountTokens, { '0xda22le': {}, diff --git a/test/unit/migrations/026-test.js b/test/unit/migrations/026-test.js index 83858c1c96a9..3227e3394bbc 100644 --- a/test/unit/migrations/026-test.js +++ b/test/unit/migrations/026-test.js @@ -19,7 +19,7 @@ describe('migration #26', function () { it('should move the identities from KeyringController', function (done) { migration26.migrate(oldStorage) .then((newStorage) => { - const identities = newStorage.data.PreferencesController.identities + const { identities } = newStorage.data.PreferencesController assert.deepEqual(identities, { '0x1e77e2': { name: 'Test Account 1', address: '0x1e77e2' }, '0x7e57e2': { name: 'Test Account 2', address: '0x7e57e2' }, diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index 49bc191a50f4..accca3136bc3 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -12,7 +12,7 @@ import * as actions from '../../../../ui/app/store/actions' import MetaMaskController from '../../../../app/scripts/metamask-controller' import firstTimeState from '../../localhostState' -const provider = createTestProviderTools({ scaffold: {} }).provider +const { provider } = createTestProviderTools({ scaffold: {} }) const middleware = [thunk] const defaultState = { metamask: {} } const mockStore = (state = defaultState) => configureStore(middleware)(state) diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index 223c7d566063..3a95e348a3e3 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -86,7 +86,7 @@ class NetworkDropdown extends Component { renderCustomOption (provider) { const { rpcTarget, type, ticker, nickname } = provider - const network = this.props.network + const { network } = this.props if (type !== 'rpc') { return null @@ -136,7 +136,7 @@ class NetworkDropdown extends Component { if ((rpc === 'http://localhost:8545') || currentRpcTarget) { return null } else { - const chainId = entry.chainId + const { chainId } = entry return ( { const newTotalFiat = addHexWEIsToRenderableFiat(value, customGasTotal, currentCurrency, conversionRate) - const hideBasic = state.appState.modal.modalState.props.hideBasic + const { hideBasic } = state.appState.modal.modalState.props const customGasPrice = calcCustomGasPrice(customModalGasPriceInHex) diff --git a/ui/app/components/app/menu-bar/account-options-menu.js b/ui/app/components/app/menu-bar/account-options-menu.js index 32c31b6c0c50..241f6dc9212f 100644 --- a/ui/app/components/app/menu-bar/account-options-menu.js +++ b/ui/app/components/app/menu-bar/account-options-menu.js @@ -51,7 +51,7 @@ export default function AccountOptionsMenu ({ anchorElement, onClose }) { const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider) const selectedIdentity = useSelector(getSelectedIdentity) - const address = selectedIdentity.address + const { address } = selectedIdentity const isRemovable = keyring.type !== 'HD Key Tree' return ( diff --git a/ui/app/components/app/menu-droppo.js b/ui/app/components/app/menu-droppo.js index fd26a5208c78..e460fe118cef 100644 --- a/ui/app/components/app/menu-droppo.js +++ b/ui/app/components/app/menu-droppo.js @@ -17,7 +17,7 @@ export default class MenuDroppoComponent extends Component { } renderPrimary () { - const isOpen = this.props.isOpen + const { isOpen } = this.props if (!isOpen) { return null } @@ -32,8 +32,7 @@ export default class MenuDroppoComponent extends Component { } manageListeners () { - const isOpen = this.props.isOpen - const onClickOutside = this.props.onClickOutside + const { isOpen, onClickOutside } = this.props if (isOpen) { this.outsideClickHandler = onClickOutside @@ -41,7 +40,7 @@ export default class MenuDroppoComponent extends Component { } globalClickOccurred = (event) => { - const target = event.target + const { target } = event // eslint-disable-next-line react/no-find-dom-node const container = findDOMNode(this) @@ -70,7 +69,7 @@ export default class MenuDroppoComponent extends Component { render () { const { containerClassName = '', style } = this.props const speed = this.props.speed || '300ms' - const useCssTransition = this.props.useCssTransition + const { useCssTransition } = this.props const zIndex = ('zIndex' in this.props) ? this.props.zIndex : 0 this.manageListeners() diff --git a/ui/app/ducks/metamask/metamask.js b/ui/app/ducks/metamask/metamask.js index e6449a622fb6..097afee7e968 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/app/ducks/metamask/metamask.js @@ -85,7 +85,7 @@ export default function reduceMetamask (state = {}, action) { } case actionConstants.SET_ACCOUNT_LABEL: { - const account = action.value.account + const { account } = action.value const name = action.value.label const id = {} id[account] = Object.assign({}, metamaskState.identities[account], { name }) diff --git a/ui/app/helpers/utils/conversion-util.js b/ui/app/helpers/utils/conversion-util.js index 784fd4e12d58..6991e1482a30 100644 --- a/ui/app/helpers/utils/conversion-util.js +++ b/ui/app/helpers/utils/conversion-util.js @@ -25,7 +25,7 @@ import BigNumber from 'bignumber.js' import ethUtil, { stripHexPrefix } from 'ethereumjs-util' -const BN = ethUtil.BN +const { BN } = ethUtil // Big Number Constants const BIG_NUMBER_WEI_MULTIPLIER = new BigNumber('1000000000000000000') diff --git a/ui/app/hooks/useCancelTransaction.js b/ui/app/hooks/useCancelTransaction.js index 4dd0cc916608..4dc19bae99c5 100644 --- a/ui/app/hooks/useCancelTransaction.js +++ b/ui/app/hooks/useCancelTransaction.js @@ -19,7 +19,7 @@ import { getConversionRate, getSelectedAccount } from '../selectors' export function useCancelTransaction (transactionGroup) { const { primaryTransaction, initialTransaction } = transactionGroup const gasPrice = primaryTransaction.txParams?.gasPrice - const id = initialTransaction.id + const { id } = initialTransaction const dispatch = useDispatch() const selectedAccount = useSelector(getSelectedAccount) const conversionRate = useSelector(getConversionRate) diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js index f36b95594a44..4607ebdbb7a5 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js @@ -42,7 +42,7 @@ export default class EnsInput extends Component { } componentDidMount () { - const network = this.props.network + const { network } = this.props const networkHasEnsSupport = getNetworkEnsSupport(network) this.setState({ ensResolution: ZERO_ADDRESS }) diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js index ec8cbbbdaec9..898bfad18dd9 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js @@ -422,7 +422,7 @@ export default class AdvancedTab extends PureComponent { handleIpfsGatewaySave () { const url = new URL(addUrlProtocolPrefix(this.state.ipfsGateway)) - const host = url.host + const { host } = url this.props.setIpfsGateway(host) } diff --git a/ui/app/selectors/custom-gas.js b/ui/app/selectors/custom-gas.js index 8c0c74ab7fc1..f8c4ecf4950e 100644 --- a/ui/app/selectors/custom-gas.js +++ b/ui/app/selectors/custom-gas.js @@ -200,7 +200,7 @@ export function getRenderableBasicEstimateData (state, gasLimit) { const { showFiatInTestnets } = getPreferences(state) const isMainnet = getIsMainnet(state) const showFiat = (isMainnet || !!showFiatInTestnets) - const conversionRate = state.metamask.conversionRate + const { conversionRate } = state.metamask const currentCurrency = getCurrentCurrency(state) const { gas: { @@ -255,7 +255,7 @@ export function getRenderableEstimateDataForSmallButtonsFromGWEI (state) { const isMainnet = getIsMainnet(state) const showFiat = (isMainnet || !!showFiatInTestnets) const gasLimit = state.metamask.send.gasLimit || getCustomGasLimit(state) || '0x5208' - const conversionRate = state.metamask.conversionRate + const { conversionRate } = state.metamask const currentCurrency = getCurrentCurrency(state) const { gas: { diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index b759ccb9bf71..9be3b1adc3f1 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -78,7 +78,7 @@ export function getSelectedAddress (state) { export function getSelectedIdentity (state) { const selectedAddress = getSelectedAddress(state) - const identities = state.metamask.identities + const { identities } = state.metamask return identities[selectedAddress] } @@ -88,7 +88,7 @@ export function getNumberOfAccounts (state) { } export function getNumberOfTokens (state) { - const tokens = state.metamask.tokens + const { tokens } = state.metamask return tokens ? tokens.length : 0 } @@ -157,7 +157,7 @@ export function getAssetImages (state) { } export function getAddressBook (state) { - const network = state.metamask.network + const { network } = state.metamask if (!state.metamask.addressBook[network]) { return [] } diff --git a/ui/app/selectors/transactions.js b/ui/app/selectors/transactions.js index 4faa6a91ea24..7d62d49797c6 100644 --- a/ui/app/selectors/transactions.js +++ b/ui/app/selectors/transactions.js @@ -21,7 +21,7 @@ export const incomingTxListSelector = (state) => { return [] } - const network = state.metamask.network + const { network } = state.metamask const selectedAddress = getSelectedAddress(state) return Object.values(state.metamask.incomingTransactions) .filter(({ metamaskNetworkId, txParams }) => ( diff --git a/ui/index.js b/ui/index.js index 41da33b4a47c..9e777ed941a0 100644 --- a/ui/index.js +++ b/ui/index.js @@ -75,7 +75,7 @@ async function startApp (metamaskState, backgroundConnection, opts) { } if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) { - const origin = draftInitialState.activeTab.origin + const { origin } = draftInitialState.activeTab const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab(draftInitialState) const selectedAddress = getSelectedAddress(draftInitialState) const unconnectedAccountAlertShownOrigins = getUnconnectedAccountAlertShown(draftInitialState) From ca35098f675ba2dd285bd77e1a91bbe905ad9927 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 18 Aug 2020 18:09:01 -0230 Subject: [PATCH 126/137] Fix lint issues (#9265) --- .../pages/token/exchange-rate-display/exchange-rate-display.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/pages/token/exchange-rate-display/exchange-rate-display.js b/ui/app/pages/token/exchange-rate-display/exchange-rate-display.js index 46e2f4e09109..85ae82fe1743 100644 --- a/ui/app/pages/token/exchange-rate-display/exchange-rate-display.js +++ b/ui/app/pages/token/exchange-rate-display/exchange-rate-display.js @@ -2,7 +2,7 @@ import React, { useState } from 'react' import PropTypes from 'prop-types' import BigNumber from 'bignumber.js' import classnames from 'classnames' -import { calcTokenAmount } from '../../../helpers/utils/token-util.js' +import { calcTokenAmount } from '../../../helpers/utils/token-util' export default function ExchangeRateDisplay ({ primaryTokenValue, From 7695343a3bddef514de542f744d7765b76c21dbd Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Tue, 18 Aug 2020 09:48:56 -0230 Subject: [PATCH 127/137] Adds actionable message component and stories --- .../actionable-message/actionable-message.js | 46 +++++++++++++ .../actionable-message.stories.js | 69 +++++++++++++++++++ .../pages/token/actionable-message/index.js | 1 + .../pages/token/actionable-message/index.scss | 41 +++++++++++ ui/app/pages/token/index.scss | 1 + 5 files changed, 158 insertions(+) create mode 100644 ui/app/pages/token/actionable-message/actionable-message.js create mode 100644 ui/app/pages/token/actionable-message/actionable-message.stories.js create mode 100644 ui/app/pages/token/actionable-message/index.js create mode 100644 ui/app/pages/token/actionable-message/index.scss diff --git a/ui/app/pages/token/actionable-message/actionable-message.js b/ui/app/pages/token/actionable-message/actionable-message.js new file mode 100644 index 000000000000..d74179d11fa0 --- /dev/null +++ b/ui/app/pages/token/actionable-message/actionable-message.js @@ -0,0 +1,46 @@ +import React from 'react' +import PropTypes from 'prop-types' +import classnames from 'classnames' + +export default function ActionableMessage ({ + shown = true, + message = '', + actions = [], + className = '', +}) { + return ( + shown + ? ( +
+
+ {message} +
+
+ { + actions.map(({ label, onClick, actionClassName }, index) => ( +
+ {label} +
+ )) + } +
+
+ ) + : null + ) +} + +ActionableMessage.propTypes = { + shown: PropTypes.bool, + message: PropTypes.string.isRequired, + actions: PropTypes.shape({ + label: PropTypes.string, + onClick: PropTypes.func, + actionClassName: PropTypes.string, + }), + className: PropTypes.string, +} diff --git a/ui/app/pages/token/actionable-message/actionable-message.stories.js b/ui/app/pages/token/actionable-message/actionable-message.stories.js new file mode 100644 index 000000000000..d39747377442 --- /dev/null +++ b/ui/app/pages/token/actionable-message/actionable-message.stories.js @@ -0,0 +1,69 @@ +import React from 'react' +import { action } from '@storybook/addon-actions' +import { text, boolean } from '@storybook/addon-knobs/react' +import ActionableMessage from '.' + +export default { + title: 'ActionableMessage', +} + +export const NoAction = () => ( +
+ +
+) + +export const OneAction = () => ( +
+ +
+) + +export const TwoActionsWithClassNames = () => ( +
+ +
+) + +export const OneActionWithAClass = () => ( +
+ +
+) diff --git a/ui/app/pages/token/actionable-message/index.js b/ui/app/pages/token/actionable-message/index.js new file mode 100644 index 000000000000..c6edbc359645 --- /dev/null +++ b/ui/app/pages/token/actionable-message/index.js @@ -0,0 +1 @@ +export { default } from './actionable-message' diff --git a/ui/app/pages/token/actionable-message/index.scss b/ui/app/pages/token/actionable-message/index.scss new file mode 100644 index 000000000000..eabd2001ee28 --- /dev/null +++ b/ui/app/pages/token/actionable-message/index.scss @@ -0,0 +1,41 @@ +.actionable-message { + background: $Blue-000; + border: 1px solid $Blue-200; + border-radius: 8px; + padding: 8px 28px 8px 28px; + margin-top: 18px; + display: flex; + flex-flow: column; + align-items: center; + + @include H7; + + &__message { + color: $Blue-600; + } + + &__actions { + display: flex; + width: 80%; + justify-content: space-evenly; + align-items: center; + margin-top: 10px; + color: $Blue-600; + } + + &__action { + font-weight: bold; + cursor: pointer; + } +} + +.actionable-message--warning { + background: $Yellow-100; + border: 1px solid $Yellow-500; + justify-content: center; + + .actionable-message__message, + .actionable-message__action { + color: $Black-100; + } +} diff --git a/ui/app/pages/token/index.scss b/ui/app/pages/token/index.scss index 01c54828115c..9cf06a407877 100644 --- a/ui/app/pages/token/index.scss +++ b/ui/app/pages/token/index.scss @@ -1,2 +1,3 @@ @import 'fee-card/index'; @import 'exchange-rate-display/index'; +@import 'actionable-message/index'; From f106128c418b98780f4f59fc8cf5cc6731fcf92d Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Tue, 18 Aug 2020 15:43:36 -0230 Subject: [PATCH 128/137] Code cleanup and simplification for actionable-message component --- .../actionable-message/actionable-message.js | 53 ++++++++++--------- .../actionable-message.stories.js | 52 +++++------------- .../pages/token/actionable-message/index.scss | 20 ++++--- 3 files changed, 54 insertions(+), 71 deletions(-) diff --git a/ui/app/pages/token/actionable-message/actionable-message.js b/ui/app/pages/token/actionable-message/actionable-message.js index d74179d11fa0..de136366c110 100644 --- a/ui/app/pages/token/actionable-message/actionable-message.js +++ b/ui/app/pages/token/actionable-message/actionable-message.js @@ -3,44 +3,47 @@ import PropTypes from 'prop-types' import classnames from 'classnames' export default function ActionableMessage ({ - shown = true, message = '', - actions = [], + primaryAction = null, + secondaryAction = null, className = '', }) { return ( - shown - ? ( -
-
- {message} +
+
+ {message} +
+
+ {primaryAction && ( +
+ {primaryAction.label}
-
- { - actions.map(({ label, onClick, actionClassName }, index) => ( -
- {label} -
- )) - } + )} + {secondaryAction && ( +
+ {secondaryAction.label}
-
- ) - : null + )} +
+
) } ActionableMessage.propTypes = { - shown: PropTypes.bool, message: PropTypes.string.isRequired, - actions: PropTypes.shape({ + primaryAction: PropTypes.shape({ + label: PropTypes.string, + onClick: PropTypes.func, + }), + secondaryAction: PropTypes.shape({ label: PropTypes.string, onClick: PropTypes.func, - actionClassName: PropTypes.string, }), className: PropTypes.string, } diff --git a/ui/app/pages/token/actionable-message/actionable-message.stories.js b/ui/app/pages/token/actionable-message/actionable-message.stories.js index d39747377442..6856ea17ff75 100644 --- a/ui/app/pages/token/actionable-message/actionable-message.stories.js +++ b/ui/app/pages/token/actionable-message/actionable-message.stories.js @@ -1,6 +1,6 @@ import React from 'react' import { action } from '@storybook/addon-actions' -import { text, boolean } from '@storybook/addon-knobs/react' +import { text } from '@storybook/addon-knobs/react' import ActionableMessage from '.' export default { @@ -10,7 +10,6 @@ export default { export const NoAction = () => (
@@ -19,50 +18,27 @@ export const NoAction = () => ( export const OneAction = () => (
) -export const TwoActionsWithClassNames = () => ( +export const TwoActions = () => (
-
-) - -export const OneActionWithAClass = () => ( -
-
diff --git a/ui/app/pages/token/actionable-message/index.scss b/ui/app/pages/token/actionable-message/index.scss index eabd2001ee28..6657b5e19d83 100644 --- a/ui/app/pages/token/actionable-message/index.scss +++ b/ui/app/pages/token/actionable-message/index.scss @@ -27,15 +27,19 @@ font-weight: bold; cursor: pointer; } -} -.actionable-message--warning { - background: $Yellow-100; - border: 1px solid $Yellow-500; - justify-content: center; + &--warning { + background: $Yellow-100; + border: 1px solid $Yellow-500; + justify-content: center; + + .actionable-message__message, + .actionable-message__action { + color: $Black-100; + } - .actionable-message__message, - .actionable-message__action { - color: $Black-100; + .actionable-message__action--secondary { + text-decoration: underline; + } } } From 6302154c407dfd5a89f81fbc42c3bf6eca7c06a2 Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Tue, 18 Aug 2020 17:21:00 -0230 Subject: [PATCH 129/137] Fix padding, alignment of actionable-message; add left aligned story --- .../actionable-message/actionable-message.js | 38 ++++++++++--------- .../actionable-message.stories.js | 13 +++++++ .../pages/token/actionable-message/index.scss | 12 +++++- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/ui/app/pages/token/actionable-message/actionable-message.js b/ui/app/pages/token/actionable-message/actionable-message.js index de136366c110..84cade2ec723 100644 --- a/ui/app/pages/token/actionable-message/actionable-message.js +++ b/ui/app/pages/token/actionable-message/actionable-message.js @@ -13,24 +13,26 @@ export default function ActionableMessage ({
{message}
-
- {primaryAction && ( -
- {primaryAction.label} -
- )} - {secondaryAction && ( -
- {secondaryAction.label} -
- )} -
+ {(primaryAction || secondaryAction) && ( +
+ {primaryAction && ( +
+ {primaryAction.label} +
+ )} + {secondaryAction && ( +
+ {secondaryAction.label} +
+ )} +
+ )}
) } diff --git a/ui/app/pages/token/actionable-message/actionable-message.stories.js b/ui/app/pages/token/actionable-message/actionable-message.stories.js index 6856ea17ff75..d881fca82062 100644 --- a/ui/app/pages/token/actionable-message/actionable-message.stories.js +++ b/ui/app/pages/token/actionable-message/actionable-message.stories.js @@ -43,3 +43,16 @@ export const TwoActions = () => ( />
) + +export const LeftAligned = () => ( +
+ +
+) diff --git a/ui/app/pages/token/actionable-message/index.scss b/ui/app/pages/token/actionable-message/index.scss index 6657b5e19d83..516e45c44e74 100644 --- a/ui/app/pages/token/actionable-message/index.scss +++ b/ui/app/pages/token/actionable-message/index.scss @@ -2,7 +2,7 @@ background: $Blue-000; border: 1px solid $Blue-200; border-radius: 8px; - padding: 8px 28px 8px 28px; + padding: 16px; margin-top: 18px; display: flex; flex-flow: column; @@ -12,6 +12,7 @@ &__message { color: $Blue-600; + text-align: center; } &__actions { @@ -42,4 +43,13 @@ text-decoration: underline; } } + + &--left-aligned { + .actionable-message__message, + .actionable-message__actions { + justify-content: flex-start; + text-align: left; + width: 100%; + } + } } From 5c7442085061232b754d8651ebe43b85c6d7b26f Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 18 Aug 2020 21:37:02 -0230 Subject: [PATCH 130/137] Use @metamask/controllers@2.0.5 (#9266) --- package.json | 2 +- yarn.lock | 38 +++++--------------------------------- 2 files changed, 6 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index 516212e52a77..35e2eb4f74b0 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "@formatjs/intl-relativetimeformat": "^5.2.6", "@fortawesome/fontawesome-free": "^5.13.0", "@material-ui/core": "^4.11.0", - "@metamask/controllers": "^2.0.1", + "@metamask/controllers": "^2.0.5", "@metamask/eth-ledger-bridge-keyring": "^0.2.6", "@metamask/eth-token-tracker": "^3.0.0", "@metamask/etherscan-link": "^1.1.0", diff --git a/yarn.lock b/yarn.lock index 8915372b2321..6a0d5369cc71 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1702,48 +1702,20 @@ prop-types "^15.7.2" react-is "^16.8.0" -"@metamask/controllers@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-2.0.1.tgz#33b0e2826fb6d4aa582acaff6b347e6abe0f54f5" - integrity sha512-xioh4h+4D2pUSJ9H2CaffxKGmlg0kUK2bbRJ8c9GXPVTo8KhRHryvNKfkVCyoSt35FLROzzwTEdVJ4dmUFuELQ== - dependencies: - await-semaphore "^0.1.3" - eth-contract-metadata "^1.11.0" - eth-ens-namehash "^2.0.8" - eth-json-rpc-errors "^2.0.2" - eth-json-rpc-infura "^4.0.1" - eth-keyring-controller "^5.6.1" - eth-method-registry "1.1.0" - eth-phishing-detect "^1.1.13" - eth-query "^2.1.2" - eth-sig-util "^2.3.0" - ethereumjs-util "^6.1.0" - ethereumjs-wallet "0.6.0" - ethjs-query "^0.3.8" - human-standard-collectible-abi "^1.0.2" - human-standard-token-abi "^2.0.0" - isomorphic-fetch "^2.2.1" - jsonschema "^1.2.4" - percentile "^1.2.1" - single-call-balance-checker-abi "^1.0.0" - uuid "^3.3.2" - web3 "^0.20.7" - web3-provider-engine "^15.0.4" - -"@metamask/controllers@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-2.0.2.tgz#100a5d87b6061751b39edec2288f16f07d471e2d" - integrity sha512-KKxNguTEdkzwvfv2Hl4BE2OMGULLeh7df6iAwcEG8ipXWbTWGZsLr13DBrczQxRi8TiNPaksAakv++6sMu6ngA== +"@metamask/controllers@^2.0.2", "@metamask/controllers@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-2.0.5.tgz#302dbae0595b269f2660253ee40c4c7f9bce069e" + integrity sha512-i+BjTEMy0XQFdcyXeEHmQ7xzktdNPBuw/R9QNBIllOvV4atR0JkZ9of6hi4tDFyjV40CBudqnIgS0iUVLWNGbA== dependencies: await-semaphore "^0.1.3" eth-contract-metadata "^1.11.0" eth-ens-namehash "^2.0.8" - eth-json-rpc-errors "^2.0.2" eth-json-rpc-infura "^4.0.1" eth-keyring-controller "^5.6.1" eth-method-registry "1.1.0" eth-phishing-detect "^1.1.13" eth-query "^2.1.2" + eth-rpc-errors "^2.1.1" eth-sig-util "^2.3.0" ethereumjs-util "^6.1.0" ethereumjs-wallet "0.6.0" From a8199be553924a32ce97e703d0230cef02c757ca Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 19 Aug 2020 11:23:44 -0230 Subject: [PATCH 131/137] Move the mascot component to its own directory (#9272) --- ui/app/components/ui/mascot/index.js | 1 + ui/app/components/ui/{mascot.js => mascot/mascot.component.js} | 0 2 files changed, 1 insertion(+) create mode 100644 ui/app/components/ui/mascot/index.js rename ui/app/components/ui/{mascot.js => mascot/mascot.component.js} (100%) diff --git a/ui/app/components/ui/mascot/index.js b/ui/app/components/ui/mascot/index.js new file mode 100644 index 000000000000..ad6ece33136b --- /dev/null +++ b/ui/app/components/ui/mascot/index.js @@ -0,0 +1 @@ +export { default } from './mascot.component' diff --git a/ui/app/components/ui/mascot.js b/ui/app/components/ui/mascot/mascot.component.js similarity index 100% rename from ui/app/components/ui/mascot.js rename to ui/app/components/ui/mascot/mascot.component.js From 9a3c559b3d7372ec35d2a20bdbf16e61d462e869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20=C5=81ucka?= Date: Wed, 19 Aug 2020 16:03:15 +0200 Subject: [PATCH 132/137] Hide gas estimate on non-main network (#9189) * hide advance gas on non mainnet * hide edit gas button on non mainnet --- .../confirm-detail-row.component.js | 16 ++++++++++------ .../confirm-transaction-base.component.js | 12 ++++++++---- .../confirm-transaction-base.container.js | 1 + .../send-gas-row/send-gas-row.component.js | 12 +++++++++--- .../send-gas-row/send-gas-row.container.js | 2 ++ .../tests/send-gas-row-component.test.js | 1 + 6 files changed, 31 insertions(+), 13 deletions(-) diff --git a/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js b/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js index d4b6cee68397..0cdb53a32c85 100644 --- a/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js @@ -22,12 +22,16 @@ const ConfirmDetailRow = (props) => { { label }
-
onHeaderClick && onHeaderClick()} - > - { headerText } -
+ { + headerText && ( +
onHeaderClick && onHeaderClick()} + > + { headerText } +
+ ) + } { primaryText ? ( diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js index 1b44c4376166..4c9ab94e1ba6 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -97,6 +97,7 @@ export default class ConfirmTransactionBase extends Component { hideSenderToRecipient: PropTypes.bool, showAccountInHeader: PropTypes.bool, mostRecentOverviewPage: PropTypes.string.isRequired, + isMainnet: PropTypes.bool, } state = { @@ -236,12 +237,15 @@ export default class ConfirmTransactionBase extends Component { hideFiatConversion, nextNonce, getNextNonce, + isMainnet, } = this.props if (hideDetails) { return null } + const notMainnetOrTest = !(isMainnet || process.env.IN_TEST) + return ( detailsComponent || (
@@ -249,12 +253,12 @@ export default class ConfirmTransactionBase extends Component { this.handleEditGas()} + headerText={notMainnetOrTest ? '' : 'Edit'} + headerTextClassName={notMainnetOrTest ? '' : 'confirm-detail-row__header-text--edit'} + onHeaderClick={notMainnetOrTest ? null : () => this.handleEditGas()} secondaryText={hideFiatConversion ? this.context.t('noConversionRateAvailable') : ''} /> - {advancedInlineGasShown + {advancedInlineGasShown || notMainnetOrTest ? ( updateGasAndCalculate({ ...customGas, gasPrice: newGasPrice })} diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js index 7d002356c75a..08b0f4581211 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -177,6 +177,7 @@ const mapStateToProps = (state, ownProps) => { transactionCategory, nextNonce, mostRecentOverviewPage: getMostRecentOverviewPage(state), + isMainnet, } } diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js index 3d22971d5135..622bae0c4549 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js +++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js @@ -26,6 +26,7 @@ export default class SendGasRow extends Component { gasPrice: PropTypes.string, gasLimit: PropTypes.string, insufficientBalance: PropTypes.bool, + isMainnet: PropTypes.bool, } static contextTypes = { @@ -35,7 +36,11 @@ export default class SendGasRow extends Component { renderAdvancedOptionsButton () { const { metricsEvent } = this.context - const { showCustomizeGasModal } = this.props + const { showCustomizeGasModal, isMainnet } = this.props + // Tests should behave in same way as mainnet, but are using Localhost + if (!isMainnet && !process.env.IN_TEST) { + return null + } return (
) - - if (advancedInlineGasShown) { + // Tests should behave in same way as mainnet, but are using Localhost + if (advancedInlineGasShown || (!isMainnet && !process.env.IN_TEST)) { return advancedGasInputs } else if (gasButtonGroupShown) { return gasPriceButtonGroup diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js index 82e6b4a7d0b3..51a17a40c0fd 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js +++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js @@ -17,6 +17,7 @@ import { getBasicGasEstimateLoadingStatus, getRenderableEstimateDataForSmallButtonsFromGWEI, getDefaultActiveButtonIndex, + getIsMainnet, } from '../../../../selectors' import { isBalanceSufficient, @@ -74,6 +75,7 @@ function mapStateToProps (state) { maxModeOn: getSendMaxModeState(state), sendToken: getSendToken(state), tokenBalance: getTokenBalance(state), + isMainnet: getIsMainnet(state), } } diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js index 9c822404382a..f80b294f7bfb 100644 --- a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js @@ -34,6 +34,7 @@ describe('SendGasRow Component', function () { }} /> ), { context: { t: (str) => str + '_t', metricsEvent: () => ({}) } }) + wrapper.setProps({ isMainnet: true }) }) afterEach(function () { From c0d78401fc8e63a9f7f8e0391caa5015042f1eae Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 19 Aug 2020 11:34:50 -0230 Subject: [PATCH 133/137] Adds toPrecisionWithoutTrailingZeros utility (#9270) --- ui/app/helpers/utils/util.js | 16 +++++++++++ ui/app/helpers/utils/util.test.js | 44 +++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index 899adebafb48..0d2e741cfbe7 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -1,5 +1,6 @@ import punycode from 'punycode' import abi from 'human-standard-token-abi' +import BigNumber from 'bignumber.js' import ethUtil from 'ethereumjs-util' import { DateTime } from 'luxon' @@ -355,3 +356,18 @@ export function checkExistingAddresses (address, list = []) { return list.some(matchesAddress) } + +/** + * Given a number and specified precision, returns that number in base 10 with a maximum of precision + * significant digits, but without any trailing zeros after the decimal point To be used when wishing + * to display only as much digits to the user as necessary + * + * @param {string | number | BigNumber} n - The number to format + * @param {number} precision - The maximum number of significant digits in the return value + * @returns {string} The number in decimal form, with <= precision significant digits and no decimal trailing zeros + */ +export function toPrecisionWithoutTrailingZeros (n, precision) { + return (new BigNumber(n)) + .toPrecision(precision) + .replace(/(\.[0-9]*[1-9])0*|(\.0*)/u, '$1') +} diff --git a/ui/app/helpers/utils/util.test.js b/ui/app/helpers/utils/util.test.js index cbeb624d164e..8a2aa1ceb45e 100644 --- a/ui/app/helpers/utils/util.test.js +++ b/ui/app/helpers/utils/util.test.js @@ -348,4 +348,48 @@ describe('util', function () { assert(util.checkExistingAddresses('b', tokenList) === false) }) }) + + describe('toPrecisionWithoutTrailingZeros', function () { + const testData = [ + { args: ['0', 9], result: '0' }, + { args: [0, 9], result: '0' }, + { args: ['0.0', 9], result: '0' }, + { args: ['0.000000000000', 9], result: '0' }, + { args: ['1', 9], result: '1' }, + { args: [1 ], result: '1' }, + { args: ['1.0', 9], result: '1' }, + { args: ['1.000000000', 9], result: '1' }, + { args: ['000000001', 9], result: '1' }, + { args: ['000000001.0', 9], result: '1' }, + { args: ['100000000', 9], result: '100000000' }, + { args: ['100000000.00001', 9], result: '100000000' }, + { args: ['100.00001', 9], result: '100.00001' }, + { args: ['100.00001000', 9], result: '100.00001' }, + { args: ['100.000010001', 9], result: '100.00001' }, + { args: ['10.010101', 9], result: '10.010101' }, + { args: ['0.1', 5], result: '0.1' }, + { args: ['0.10', 5], result: '0.1' }, + { args: ['0.1010', 5], result: '0.101' }, + { args: ['0.01001', 5], result: '0.01001' }, + { args: ['0.010010', 5], result: '0.01001' }, + { args: ['0.010011', 5], result: '0.010011' }, + { args: ['1.01005', 5], result: '1.0101' }, + { args: ['1.000049', 5], result: '1' }, + { args: ['1.00005', 5], result: '1.0001' }, + { args: ['0.0000123456789', 9], result: '0.0000123456789' }, + { args: ['1.0000123456789', 10], result: '1.000012346' }, + { args: ['10000.0000012345679', 10], result: '10000' }, + { args: ['1000000000000', 10], result: '1e+12' }, + { args: ['1000050000000', 10], result: '1.00005e+12' }, + { args: ['100000000000000000000', 10], result: '1e+20' }, + { args: ['100005000000000000000', 10], result: '1.00005e+20' }, + { args: ['100005000000000000000.0', 10], result: '1.00005e+20' }, + ] + + testData.forEach(({ args, result }) => { + it(`should return ${result} when passed number ${args[0]} and precision ${args[1]}`, function () { + assert.equal(util.toPrecisionWithoutTrailingZeros(...args), result) + }) + }) + }) }) From 50c4845d05b16e952075c09228c1ed50eb761389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20=C5=81ucka?= Date: Wed, 19 Aug 2020 17:01:58 +0200 Subject: [PATCH 134/137] Add lock icon to default networks (#9269) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patryk Łucka --- ui/app/pages/settings/networks-tab/index.scss | 10 ++++++++++ .../settings/networks-tab/networks-tab.component.js | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/ui/app/pages/settings/networks-tab/index.scss b/ui/app/pages/settings/networks-tab/index.scss index e539ece40f31..f6a69af39bb5 100644 --- a/ui/app/pages/settings/networks-tab/index.scss +++ b/ui/app/pages/settings/networks-tab/index.scss @@ -185,6 +185,11 @@ &:hover { cursor: pointer; } + + svg { + margin-left: 10px; + padding-top: 3px; + } } &__networks-list-arrow { @@ -214,6 +219,11 @@ font-weight: bold; color: #000; } + + &__networks-list-name--disabled { + font-weight: 300; + color: #cdcdcd; + } } .network-form { diff --git a/ui/app/pages/settings/networks-tab/networks-tab.component.js b/ui/app/pages/settings/networks-tab/networks-tab.component.js index f9cb6104801b..40bbc0c36bf7 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.component.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.component.js @@ -5,6 +5,7 @@ import { SETTINGS_ROUTE } from '../../../helpers/constants/routes' import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import Button from '../../../components/ui/button' +import LockIcon from '../../../components/ui/lock-icon' import NetworkDropdownIcon from '../../../components/app/dropdowns/components/network-dropdown-icon' import NetworkForm from './network-form' @@ -117,9 +118,17 @@ export default class NetworksTab extends PureComponent {
{ label || this.context.t(labelKey) } + { currentProviderType !== 'rpc' && ( + + ) }
From b6ccd22d6c0ff6b9797c7aa24429f3df6d031af7 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 19 Aug 2020 13:57:05 -0230 Subject: [PATCH 135/137] Update ESLint shared config to v3 (#9274) Co-authored-by: Mark Stacey --- .eslintrc.js | 62 +------------ app/scripts/background.js | 5 +- app/scripts/contentscript.js | 7 +- app/scripts/controllers/alert.js | 14 ++- app/scripts/controllers/app-state.js | 7 +- app/scripts/controllers/cached-balances.js | 5 +- app/scripts/controllers/detect-tokens.js | 2 + .../controllers/incoming-transactions.js | 9 +- .../network/createLocalhostClient.js | 1 - app/scripts/controllers/network/network.js | 10 +- app/scripts/controllers/onboarding.js | 15 ++- app/scripts/controllers/permissions/index.js | 5 +- .../controllers/permissions/permissionsLog.js | 10 +- app/scripts/controllers/preferences.js | 17 ++-- app/scripts/controllers/threebox.js | 6 +- app/scripts/controllers/token-rates.js | 2 +- app/scripts/controllers/transactions/index.js | 21 +++-- .../transactions/pending-tx-tracker.js | 3 +- .../transactions/tx-state-manager.js | 20 ++-- app/scripts/inpage.js | 3 +- app/scripts/lib/ComposableObservableStore.js | 1 + app/scripts/lib/cleanErrorStack.js | 2 +- app/scripts/lib/createStreamSink.js | 2 +- app/scripts/lib/decrypt-message-manager.js | 6 +- .../lib/encryption-public-key-manager.js | 4 +- app/scripts/lib/ens-ipfs/resolver.js | 2 +- app/scripts/lib/extractEthjsErrorMessage.js | 3 +- app/scripts/lib/local-store.js | 6 +- app/scripts/lib/message-manager.js | 9 +- app/scripts/lib/personal-message-manager.js | 6 +- app/scripts/lib/random-id.js | 2 +- app/scripts/lib/seed-phrase-verifier.js | 6 +- app/scripts/lib/typed-message-manager.js | 5 +- app/scripts/lib/util.js | 3 +- app/scripts/metamask-controller.js | 39 ++++---- app/scripts/migrations/002.js | 5 +- app/scripts/migrations/003.js | 6 +- app/scripts/migrations/004.js | 6 +- app/scripts/migrations/005.js | 7 +- app/scripts/migrations/006.js | 8 +- app/scripts/migrations/007.js | 8 +- app/scripts/migrations/008.js | 8 +- app/scripts/migrations/009.js | 8 +- app/scripts/migrations/010.js | 8 +- app/scripts/migrations/011.js | 8 +- app/scripts/migrations/012.js | 8 +- app/scripts/migrations/013.js | 8 +- app/scripts/migrations/014.js | 8 +- app/scripts/migrations/015.js | 8 +- app/scripts/migrations/016.js | 8 +- app/scripts/migrations/017.js | 8 +- app/scripts/migrations/018.js | 7 +- app/scripts/migrations/019.js | 8 +- app/scripts/migrations/020.js | 8 +- app/scripts/migrations/021.js | 8 +- app/scripts/migrations/022.js | 8 +- app/scripts/migrations/023.js | 8 +- app/scripts/migrations/024.js | 6 +- app/scripts/migrations/025.js | 6 +- app/scripts/migrations/026.js | 6 +- app/scripts/migrations/027.js | 6 +- app/scripts/migrations/028.js | 6 +- app/scripts/migrations/029.js | 3 +- app/scripts/migrations/030.js | 8 +- app/scripts/migrations/031.js | 5 +- app/scripts/migrations/032.js | 5 +- app/scripts/migrations/033.js | 6 +- app/scripts/migrations/034.js | 5 +- app/scripts/migrations/035.js | 6 +- app/scripts/migrations/036.js | 5 +- app/scripts/migrations/037.js | 5 +- app/scripts/migrations/038.js | 5 +- app/scripts/migrations/039.js | 5 +- app/scripts/migrations/040.js | 5 +- app/scripts/migrations/041.js | 5 +- app/scripts/migrations/042.js | 5 +- app/scripts/migrations/043.js | 5 +- app/scripts/migrations/044.js | 5 +- app/scripts/migrations/045.js | 5 +- app/scripts/migrations/046.js | 5 +- app/scripts/migrations/047.js | 5 +- app/scripts/migrations/fail-tx.js | 2 +- app/scripts/migrations/template.js | 6 +- app/scripts/platforms/extension.js | 8 +- app/scripts/ui.js | 3 +- development/build/display.js | 6 +- development/build/etc.js | 1 - development/build/index.js | 12 ++- development/build/manifest.js | 1 - development/build/scripts.js | 23 ++--- development/build/static.js | 1 - development/build/styles.js | 4 - development/build/task.js | 1 - development/metamaskbot-build-announce.js | 2 +- development/mock-3box.js | 2 +- development/sourcemap-validator.js | 1 - development/static-server.js | 2 +- development/verify-locale-strings.js | 7 +- package.json | 2 +- test/e2e/benchmark.js | 6 +- test/e2e/from-import-ui.spec.js | 2 +- test/e2e/metamask-ui.spec.js | 4 +- test/e2e/mock-3box/server.js | 2 +- test/e2e/send-edit.spec.js | 2 +- test/e2e/signature-request.spec.js | 2 +- test/e2e/webdriver/driver.js | 6 +- test/e2e/webdriver/firefox.js | 1 + test/helper.js | 1 - test/lib/createTxMeta.js | 5 +- test/lib/render-helpers.js | 2 +- .../app/account-import-strategies.spec.js | 14 +-- .../app/controllers/detect-tokens-test.js | 1 - .../controllers/incoming-transactions-test.js | 4 +- .../controllers/metamask-controller-test.js | 22 ++--- .../app/controllers/permissions/helpers.js | 1 + .../unit/app/controllers/permissions/mocks.js | 9 +- .../permissions-controller-test.js | 10 +- .../permissions-log-controller-test.js | 20 ++-- .../preferences-controller-test.js | 11 +-- .../transactions/tx-controller-test.js | 11 +-- .../transactions/tx-state-manager-test.js | 4 +- .../controllers/transactions/tx-utils-test.js | 1 - test/unit/app/nodeify-test.js | 2 +- test/unit/app/typed-message-manager.spec.js | 2 +- test/unit/migrations/023-test.js | 1 - test/unit/migrations/024-test.js | 2 - test/unit/migrations/025-test.js | 2 - test/unit/migrations/027-test.js | 2 - test/unit/migrations/028-test.js | 8 +- test/unit/migrations/029-test.js | 2 +- test/unit/migrations/migrator-test.js | 4 +- test/unit/ui/app/actions.spec.js | 13 ++- test/unit/ui/app/reducers/app.spec.js | 1 - test/unit/ui/app/reducers/metamask.spec.js | 7 +- .../tests/account-list-item-component.test.js | 2 +- .../account-menu/account-menu.container.js | 2 +- .../account-menu/tests/account-menu.test.js | 2 +- .../add-token-button.component.js | 1 - .../app/app-header/tests/app-header.test.js | 2 +- .../app/asset-list-item/asset-list-item.js | 1 - ...onfirm-page-container-content.component.js | 5 +- ...confirm-page-container-header.component.js | 1 - .../connected-accounts-list.component.js | 2 +- .../connected-status-indicator.component.js | 2 +- .../connected-status-indicator.container.js | 1 - .../contact-list/contact-list.component.js | 3 +- .../app/dropdowns/components/dropdown.js | 12 +-- .../app/dropdowns/network-dropdown.js | 71 +++++++------- .../advanced-gas-input-component.test.js | 5 +- ...gas-modal-page-container-container.test.js | 31 +++---- .../gas-price-button-group.component.js | 1 - .../gas-price-button-group-component.test.js | 9 +- .../gas-price-chart/gas-price-chart.utils.js | 13 ++- .../tests/gas-price-chart.component.test.js | 2 +- .../app/info-box/tests/info-box.test.js | 2 +- .../app/menu-bar/tests/menu-bar.test.js | 2 +- ui/app/components/app/menu-droppo.js | 10 +- .../account-details-modal.component.js | 2 +- .../cancel-transaction.component.js | 1 - .../tests/confirm-delete-network.test.js | 2 +- .../tests/confirm-remove-account.test.js | 3 +- .../tests/confirm-reset-account.test.js | 2 +- .../deposit-ether-modal.container.js | 1 - ui/app/components/app/modals/fade-modal.js | 18 ++-- .../tests/metametrics-opt-in-modal.test.js | 2 +- .../modals/qr-scanner/qr-scanner.component.js | 2 - .../modals/qr-scanner/qr-scanner.container.js | 1 - .../tests/reject-transactions.test.js | 2 +- .../tests/transaction-confirmed.test.js | 2 +- .../network-display.component.js | 2 +- ...ission-page-container-content.component.js | 16 ++-- .../selected-account.container.js | 1 - .../signature-request-message.component.js | 3 +- .../tests/signature-request.test.js | 1 - .../components/app/token-cell/token-cell.js | 1 - .../transaction-action.component.test.js | 1 - .../transaction-activity-log.util.js | 15 ++- .../transaction-breakdown.container.js | 2 +- .../app/transaction-icon/transaction-icon.js | 1 - .../transaction-list-item.component.js | 2 - .../transaction-list.component.js | 4 +- ...erenced-currency-display.component.test.js | 1 - ui/app/components/ui/alert/index.js | 2 +- .../components/ui/alert/tests/alert.test.js | 2 +- .../tests/breadcrumbs.component.test.js | 6 +- .../tests/currency-input.component.test.js | 2 +- .../ui/dropdown/dropdown.stories.js | 5 +- .../ui/list-item/list-item.stories.js | 1 - .../page-container.component.js | 3 +- .../sender-to-recipient.component.js | 2 - .../ui/text-field/text-field.component.js | 2 +- .../tests/token-input.component.test.js | 6 +- .../ui/unit-input/unit-input.component.js | 2 +- ui/app/contexts/metametrics.js | 1 - ui/app/ducks/app/app.js | 29 +++--- .../confirm-transaction.duck.js | 1 - ui/app/ducks/gas/gas-duck.test.js | 93 ++++++++----------- ui/app/ducks/gas/gas.duck.js | 7 +- ui/app/ducks/metamask/metamask.js | 11 ++- ui/app/helpers/utils/confirm-tx.util.js | 1 - ui/app/helpers/utils/fetch-with-cache.js | 45 +++++---- ui/app/helpers/utils/formatters.js | 2 +- .../helpers/utils/gas-time-estimates.util.js | 4 +- ui/app/helpers/utils/i18n-helper.test.js | 16 ++-- ui/app/helpers/utils/metametrics.util.js | 6 +- ui/app/helpers/utils/transactions.util.js | 10 +- ui/app/helpers/utils/util.js | 16 ++-- ui/app/helpers/utils/util.test.js | 2 +- .../hooks/tests/useCancelTransaction.test.js | 3 - ui/app/hooks/tests/useCurrencyDisplay.test.js | 3 +- .../hooks/tests/useTokenDisplayValue.test.js | 1 - .../tests/useTransactionDisplayData.test.js | 40 +++++--- .../tests/useUserPreferencedCurrency.test.js | 4 +- ui/app/hooks/useCancelTransaction.js | 2 - ui/app/hooks/useCurrencyDisplay.js | 3 +- ui/app/hooks/useMetricEvent.js | 1 - ui/app/hooks/useRetryTransaction.js | 1 - ui/app/hooks/useTokenTracker.js | 2 - ui/app/hooks/useTransactionTimeRemaining.js | 2 +- .../pages/add-token/tests/add-token.test.js | 3 +- .../token-search/token-search.component.js | 2 +- .../confirm-add-suggested-token.component.js | 2 +- .../confirm-add-token.component.js | 2 +- .../confirm-decrypt-message.container.js | 5 +- ...confirm-encryption-public-key.container.js | 7 +- ...onfirm-token-transaction-base.component.js | 9 +- ...onfirm-token-transaction-base.container.js | 1 - ui/app/pages/confirm-transaction/conf-tx.js | 4 +- .../confirm-transaction.component.js | 3 - .../connect-hardware/account-list.js | 1 - .../create-account/connect-hardware/index.js | 4 +- .../connect-hardware/select-hardware.js | 1 - .../create-account/import-account/json.js | 2 +- .../import-account/private-key.js | 7 +- .../tests/create-account.test.js | 2 +- .../import-with-seed-phrase.component.test.js | 2 +- .../end-of-flow/end-of-flow.component.js | 12 +-- .../end-of-flow/tests/end-of-flow.test.js | 2 +- .../tests/first-time-flow-switch.test.js | 2 +- .../first-time-flow.component.js | 1 - .../metametrics-opt-in.component.js | 2 +- .../tests/metametrics-opt-in.test.js | 2 +- .../confirm-seed-phrase.component.js | 2 +- .../draggable-seed.component.js | 2 - .../reveal-seed-phrase.component.js | 3 +- .../tests/reveal-seed-phrase.test.js | 2 +- .../confirm-seed-phrase-component.test.js | 3 +- .../select-action/select-action.component.js | 1 - .../select-action/tests/select-action.test.js | 2 +- .../welcome/tests/welcome.test.js | 2 +- ui/app/pages/home/home.component.js | 3 +- ui/app/pages/lock/tests/lock.test.js | 2 +- .../mobile-sync/mobile-sync.component.js | 5 +- .../add-recipient/add-recipient.component.js | 1 - .../add-recipient/add-recipient.container.js | 2 +- .../add-recipient/ens-input.component.js | 2 - .../tests/add-recipient-component.test.js | 3 +- .../tests/amount-max-button-component.test.js | 2 +- .../tests/send-amount-row-component.test.js | 2 +- .../send-asset-row.component.js | 1 - .../send-content/send-content.container.js | 2 +- .../tests/gas-fee-display.component.test.js | 2 +- .../send-gas-row/send-gas-row.component.js | 3 +- .../send-gas-row/send-gas-row.container.js | 1 - .../tests/send-gas-row-component.test.js | 2 +- .../send-row-error-message-component.test.js | 2 +- .../send-row-error-message-container.test.js | 3 +- .../tests/send-content-component.test.js | 2 +- .../send/send-footer/send-footer.utils.js | 2 +- .../tests/send-footer-component.test.js | 1 - .../tests/send-footer-container.test.js | 6 +- .../tests/send-footer-utils.test.js | 2 +- ui/app/pages/send/send.component.js | 1 - ui/app/pages/send/send.utils.js | 9 +- .../pages/send/tests/send-container.test.js | 4 +- ui/app/pages/send/tests/send-utils.test.js | 38 ++++---- .../advanced-tab/advanced-tab.component.js | 2 +- .../contact-list-tab.component.js | 2 +- .../contact-list-tab.container.js | 1 - .../view-contact/view-contact.component.js | 10 +- .../network-form/network-form.component.js | 5 +- .../networks-tab/networks-tab.component.js | 2 +- .../networks-tab/networks-tab.container.js | 2 +- .../security-tab/tests/security-tab.test.js | 2 +- .../settings-tab/settings-tab.component.js | 1 - .../settings-tab/tests/settings-tab.test.js | 2 +- .../unlock-page/tests/unlock-page.test.js | 3 +- ui/app/selectors/confirm-transaction.js | 1 - ui/app/selectors/custom-gas.js | 9 +- ui/app/selectors/permissions.js | 2 +- ui/app/selectors/selectors.js | 15 ++- ui/app/selectors/send.js | 3 +- ui/app/selectors/tests/custom-gas.test.js | 28 ++++-- ui/app/selectors/tests/send.test.js | 31 ++++--- ui/app/selectors/tests/transactions.test.js | 14 +-- ui/app/store/actions.js | 52 ++++------- ui/lib/icon-factory.js | 3 +- ui/lib/webcam-utils.js | 7 +- yarn.lock | 8 +- 299 files changed, 860 insertions(+), 1038 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index cfb2e30880fd..0b69e664efb8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -41,36 +41,9 @@ module.exports = { }, rules: { - /* TODO: Remove these when upgrading to `@metamask/eslint-config@2` */ - 'array-callback-return': 'error', - 'callback-return': 'error', - 'consistent-return': 'error', - 'global-require': 'error', - 'guard-for-in': 'error', - 'implicit-arrow-linebreak': 'error', - 'import/extensions': ['error', 'never', { 'json': 'always' }], - 'import/no-extraneous-dependencies': 'error', - 'import/order': 'error', - 'import/unambiguous': 'error', - 'max-statements-per-line': ['error', { 'max': 1 }], - 'no-case-declarations': 'error', - 'no-constant-condition': 'error', - 'no-dupe-else-if': 'error', - 'no-empty': 'error', - 'no-empty-function': 'error', - 'no-eq-null': 'error', - 'no-global-assign': 'error', - 'no-loop-func': 'error', - 'no-negated-condition': 'error', - 'no-nested-ternary': 'error', - 'no-param-reassign': 'error', - 'no-plusplus': ['error', { 'allowForLoopAfterthoughts': true }], - 'no-process-exit': 'error', - 'no-prototype-builtins': 'error', - 'no-shadow': 'error', - 'no-template-curly-in-string': 'error', - 'no-useless-catch': 'error', - 'no-useless-concat': 'error', + 'default-param-last': 'off', + 'require-atomic-updates': 'off', + 'import/no-unassigned-import': 'off', 'prefer-destructuring': ['error', { 'VariableDeclarator': { 'array': false, @@ -83,33 +56,6 @@ module.exports = { }, { 'enforceForRenamedProperties': false, }], - 'prefer-rest-params': 'error', - 'prefer-spread': 'error', - 'radix': 'error', - 'require-unicode-regexp': 'error', - /* End v2 rules */ - 'arrow-parens': 'error', - 'no-tabs': 'error', - 'no-mixed-operators': 'error', - 'import/default': 'error', - 'import/export': 'error', - 'import/named': 'error', - 'import/namespace': 'error', - 'import/newline-after-import': 'error', - 'import/no-absolute-path': 'error', - 'import/no-amd': 'error', - 'import/no-anonymous-default-export': 'error', - 'import/no-duplicates': 'error', - 'import/no-dynamic-require': 'error', - 'import/no-mutable-exports': 'error', - 'import/no-named-as-default': 'error', - 'import/no-named-as-default-member': 'error', - 'import/no-named-default': 'error', - 'import/no-self-import': 'error', - 'import/no-unresolved': ['error', { 'commonjs': true }], - 'import/no-unused-modules': 'error', - 'import/no-useless-path-segments': ['error', { 'commonjs': true }], - 'import/no-webpack-loader-syntax': 'error', 'react/no-unused-prop-types': 'error', 'react/no-unused-state': 'error', 'react/jsx-boolean-value': 'error', @@ -121,7 +67,7 @@ module.exports = { 'react/jsx-no-duplicate-props': 'error', 'react/jsx-closing-bracket-location': 'error', 'react/jsx-first-prop-new-line': ['error', 'multiline'], - 'react/jsx-max-props-per-line': ['error', { 'maximum': 1, 'when': 'multiline' } ], + 'react/jsx-max-props-per-line': ['error', { 'maximum': 1, 'when': 'multiline' }], 'react/jsx-tag-spacing': ['error', { 'closingSlash': 'never', 'beforeSelfClosing': 'always', diff --git a/app/scripts/background.js b/app/scripts/background.js index b88d3b83f5f2..3df32dfeb0fe 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -2,7 +2,7 @@ * @file The entry point for the web extension singleton process. */ // these need to run before anything else -/* eslint-disable import/order */ +/* eslint-disable import/first,import/order */ import './lib/freezeGlobals' import setupFetchDebugging from './lib/setupFetchDebugging' /* eslint-enable import/order */ @@ -39,9 +39,10 @@ import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_FULLSCREEN, } from './lib/enums' +/* eslint-enable import/first */ // METAMASK_TEST_CONFIG is used in e2e tests to set the default network to localhost -const firstTimeState = Object.assign({}, rawFirstTimeState, global.METAMASK_TEST_CONFIG) +const firstTimeState = { ...rawFirstTimeState, ...global.METAMASK_TEST_CONFIG } log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 4c5bcecc2fd3..d85aca3f2747 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -10,7 +10,7 @@ const fs = require('fs') const path = require('path') const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js'), 'utf8') -const inpageSuffix = '//# sourceURL=' + extension.runtime.getURL('inpage.js') + '\n' +const inpageSuffix = `//# sourceURL=${extension.runtime.getURL('inpage.js')}\n` const inpageBundle = inpageContent + inpageSuffix // Eventually this streaming injection could be replaced with: @@ -115,7 +115,7 @@ function forwardTrafficBetweenMuxers (channelName, muxA, muxB) { function logStreamDisconnectWarning (remoteLabel, err) { let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}` if (err) { - warningMsg += '\n' + err.stack + warningMsg += `\n${err.stack}` } console.warn(warningMsg) } @@ -139,9 +139,8 @@ function doctypeCheck () { const { doctype } = window.document if (doctype) { return doctype.name === 'html' - } else { - return true } + return true } /** diff --git a/app/scripts/controllers/alert.js b/app/scripts/controllers/alert.js index af49b9df6d0f..820e1a80bb82 100644 --- a/app/scripts/controllers/alert.js +++ b/app/scripts/controllers/alert.js @@ -32,20 +32,18 @@ const defaultState = { * alert related state */ export default class AlertController { + /** * @constructor * @param {AlertControllerOptions} [opts] - Controller configuration parameters */ constructor (opts = {}) { const { initState, preferencesStore } = opts - const state = Object.assign( - {}, - defaultState, - initState, - { - unconnectedAccountAlertShownOrigins: {}, - }, - ) + const state = { + ...defaultState, + ...initState, + unconnectedAccountAlertShownOrigins: {}, + } this.store = new ObservableStore(state) this.selectedAddress = preferencesStore.getState().selectedAddress diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index e967b462b865..c29b76a40d57 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -2,6 +2,7 @@ import EventEmitter from 'events' import ObservableStore from 'obs-store' export default class AppStateController extends EventEmitter { + /** * @constructor * @param opts @@ -18,11 +19,11 @@ export default class AppStateController extends EventEmitter { super() this.onInactiveTimeout = onInactiveTimeout || (() => undefined) - this.store = new ObservableStore(Object.assign({ + this.store = new ObservableStore({ timeoutMinutes: 0, connectedStatusPopoverHasBeenShown: true, - defaultHomeActiveTabName: null, - }, initState)) + defaultHomeActiveTabName: null, ...initState, + }) this.timer = null this.isUnlocked = isUnlocked diff --git a/app/scripts/controllers/cached-balances.js b/app/scripts/controllers/cached-balances.js index 3cee10df06f5..87ca28662570 100644 --- a/app/scripts/controllers/cached-balances.js +++ b/app/scripts/controllers/cached-balances.js @@ -12,6 +12,7 @@ import ObservableStore from 'obs-store' * a cache of account balances in local storage */ export default class CachedBalancesController { + /** * Creates a new controller instance * @@ -23,9 +24,7 @@ export default class CachedBalancesController { this.accountTracker = accountTracker this.getNetwork = getNetwork - const initState = Object.assign({ - cachedBalances: {}, - }, opts.initState) + const initState = { cachedBalances: {}, ...opts.initState } this.store = new ObservableStore(initState) this._registerUpdates() diff --git a/app/scripts/controllers/detect-tokens.js b/app/scripts/controllers/detect-tokens.js index 93b7af2a6c31..40980990c78b 100644 --- a/app/scripts/controllers/detect-tokens.js +++ b/app/scripts/controllers/detect-tokens.js @@ -7,11 +7,13 @@ import { MAINNET } from './network/enums' // By default, poll every 3 minutes const DEFAULT_INTERVAL = 180 * 1000 const SINGLE_CALL_BALANCES_ADDRESS = '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39' + /** * A controller that polls for token exchange * rates based on a user's current token list */ export default class DetectTokensController { + /** * Creates a DetectTokensController * diff --git a/app/scripts/controllers/incoming-transactions.js b/app/scripts/controllers/incoming-transactions.js index 7e8aa87d0b12..de588f38bf4d 100644 --- a/app/scripts/controllers/incoming-transactions.js +++ b/app/scripts/controllers/incoming-transactions.js @@ -40,7 +40,7 @@ export default class IncomingTransactionsController { }) } - const initState = Object.assign({ + const initState = { incomingTransactions: {}, incomingTxLastFetchedBlocksByNetwork: { [ROPSTEN]: null, @@ -48,8 +48,8 @@ export default class IncomingTransactionsController { [KOVAN]: null, [GOERLI]: null, [MAINNET]: null, - }, - }, opts.initState) + }, ...opts.initState, + } this.store = new ObservableStore(initState) this.preferencesController.store.subscribe(pairwise((prevState, currState) => { @@ -265,9 +265,8 @@ function pairwise (fn) { if (first) { first = false return fn(value, value) - } else { - return fn(cache, value) } + return fn(cache, value) } finally { cache = value } diff --git a/app/scripts/controllers/network/createLocalhostClient.js b/app/scripts/controllers/network/createLocalhostClient.js index 447892016749..efd19801c0e3 100644 --- a/app/scripts/controllers/network/createLocalhostClient.js +++ b/app/scripts/controllers/network/createLocalhostClient.js @@ -26,7 +26,6 @@ function delay (time) { return new Promise((resolve) => setTimeout(resolve, time)) } - function createEstimateGasMiddleware () { return createAsyncMiddleware(async (req, _, next) => { if (req.method === 'eth_estimateGas' && inTest) { diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 27d7093d1bb3..29e878cc80a4 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -12,8 +12,6 @@ import createInfuraClient from './createInfuraClient' import createJsonRpcClient from './createJsonRpcClient' import createLocalhostClient from './createLocalhostClient' -const networks = { networkList: {} } - import { RINKEBY, MAINNET, @@ -21,6 +19,8 @@ import { INFURA_PROVIDER_TYPES, } from './enums' +const networks = { networkList: {} } + const env = process.env.METAMASK_ENV const { METAMASK_DEBUG } = process.env @@ -124,7 +124,7 @@ export default class NetworkController extends EventEmitter { this.setNetworkState('loading') return } - log.info('web3.getNetwork returned ' + network) + log.info(`web3.getNetwork returned ${network}`) this.setNetworkState(network, type) } }) @@ -212,7 +212,7 @@ export default class NetworkController extends EventEmitter { log.info('NetworkController - configureStandardProvider', rpcUrl) const networkClient = createJsonRpcClient({ rpcUrl }) // hack to add a 'rpc' network with chainId - networks.networkList['rpc'] = { + networks.networkList.rpc = { chainId, rpcUrl, ticker: ticker || 'ETH', @@ -222,7 +222,7 @@ export default class NetworkController extends EventEmitter { let settings = { network: chainId, } - settings = Object.assign(settings, networks.networkList['rpc']) + settings = Object.assign(settings, networks.networkList.rpc) this.networkConfig.putState(settings) this._setNetworkClient(networkClient) } diff --git a/app/scripts/controllers/onboarding.js b/app/scripts/controllers/onboarding.js index 7efb4523c9f9..0ff92f5b1770 100644 --- a/app/scripts/controllers/onboarding.js +++ b/app/scripts/controllers/onboarding.js @@ -17,6 +17,7 @@ import log from 'loglevel' * state related to onboarding */ export default class OnboardingController { + /** * Creates a new controller instance * @@ -26,13 +27,11 @@ export default class OnboardingController { const initialTransientState = { onboardingTabs: {}, } - const initState = Object.assign( - { - seedPhraseBackedUp: true, - }, - opts.initState, - initialTransientState, - ) + const initState = { + seedPhraseBackedUp: true, + ...opts.initState, + ...initialTransientState, + } this.store = new ObservableStore(initState) this.preferencesController = opts.preferencesController this.completedOnboarding = this.preferencesController.store.getState().completedOnboarding @@ -64,7 +63,7 @@ export default class OnboardingController { log.debug('Ignoring registerOnboarding; user already onboarded') return } - const onboardingTabs = Object.assign({}, this.store.getState().onboardingTabs) + const onboardingTabs = { ...this.store.getState().onboardingTabs } if (!onboardingTabs[location] || onboardingTabs[location] !== tabId) { log.debug(`Registering onboarding tab at location '${location}' with tabId '${tabId}'`) onboardingTabs[location] = tabId diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index f82cb1c750b8..09398334307b 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -36,7 +36,8 @@ export class PermissionsController { showPermissionRequest, } = {}, restoredPermissions = {}, - restoredState = {}) { + restoredState = {}, + ) { // additional top-level store key set in _initializeMetadataStore this.store = new ObservableStore({ @@ -334,7 +335,7 @@ export class PermissionsController { .filter((acc) => acc !== account) if (newPermittedAccounts.length === 0) { - this.removePermissionsFor({ [origin]: [ 'eth_accounts' ] }) + this.removePermissionsFor({ [origin]: ['eth_accounts'] }) } else { this.permissions.updateCaveatFor( diff --git a/app/scripts/controllers/permissions/permissionsLog.js b/app/scripts/controllers/permissions/permissionsLog.js index 3a6f02537f5a..eda7c394a3c9 100644 --- a/app/scripts/controllers/permissions/permissionsLog.js +++ b/app/scripts/controllers/permissions/permissionsLog.js @@ -113,7 +113,7 @@ export default class PermissionsLogController { // eth_requestAccounts is a special case; we need to extract the accounts // from it activityEntry = this.logRequest(req, isInternal) - requestedMethods = [ 'eth_accounts' ] + requestedMethods = ['eth_accounts'] } else { // no-op next() @@ -292,9 +292,9 @@ export default class PermissionsLogController { // eth_accounts requires special handling, because of information // we store about the accounts const existingEthAccountsEntry = ( - history[origin] && history[origin]['eth_accounts'] + history[origin] && history[origin].eth_accounts ) - const newEthAccountsEntry = newEntries['eth_accounts'] + const newEthAccountsEntry = newEntries.eth_accounts if (existingEthAccountsEntry && newEthAccountsEntry) { @@ -306,7 +306,7 @@ export default class PermissionsLogController { ) // merge old and new eth_accounts history entries - newOriginHistory['eth_accounts'] = { + newOriginHistory.eth_accounts = { lastApproved, accounts: { ...existingEthAccountsEntry.accounts, @@ -364,7 +364,7 @@ export default class PermissionsLogController { } } } - return [ ...accounts ] + return [...accounts] } } diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 739004d93f91..c82a1adbc5c1 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -26,7 +26,7 @@ export default class PreferencesController { * */ constructor (opts = {}) { - const initState = Object.assign({ + const initState = { frequentRpcListDetail: [], accountTokens: {}, assetImages: {}, @@ -61,8 +61,8 @@ export default class PreferencesController { metaMetricsSendCount: 0, // ENS decentralized website resolution - ipfsGateway: 'dweb.link', - }, opts.initState) + ipfsGateway: 'dweb.link', ...opts.initState, + } this.diagnostics = opts.diagnostics this.network = opts.network @@ -152,7 +152,6 @@ export default class PreferencesController { this.store.updateState({ firstTimeFlowType: type }) } - getSuggestedTokens () { return this.store.getState().suggestedTokens } @@ -215,7 +214,6 @@ export default class PreferencesController { } next() - return } /** @@ -228,7 +226,7 @@ export default class PreferencesController { const textDirection = (['ar', 'dv', 'fa', 'he', 'ku'].includes(key)) ? 'rtl' : 'auto' this.store.updateState({ currentLocale: key, - textDirection: textDirection, + textDirection, }) return textDirection } @@ -282,7 +280,6 @@ export default class PreferencesController { return address } - /** * Adds addresses to the identities object without removing identities * @@ -470,7 +467,7 @@ export default class PreferencesController { */ setAccountLabel (account, label) { if (!account) { - throw new Error('setAccountLabel requires a valid address, got ' + String(account)) + throw new Error(`setAccountLabel requires a valid address, got ${String(account)}`) } const address = normalizeAddress(account) const { identities } = this.store.getState() @@ -491,7 +488,6 @@ export default class PreferencesController { * */ - updateRpc (newRpcDetails) { const rpcList = this.getFrequentRpcListDetail() const index = rpcList.findIndex((element) => { @@ -508,6 +504,7 @@ export default class PreferencesController { } return Promise.resolve(rpcList) } + /** * Adds custom RPC url to state. * @@ -529,7 +526,7 @@ export default class PreferencesController { if (url !== 'http://localhost:8545') { let checkedChainId // eslint-disable-next-line radix - if (!!chainId && !Number.isNaN(parseInt(chainId))) { + if (Boolean(chainId) && !Number.isNaN(parseInt(chainId))) { checkedChainId = chainId } rpcList.push({ rpcUrl: url, chainId: checkedChainId, ticker, nickname, rpcPrefs }) diff --git a/app/scripts/controllers/threebox.js b/app/scripts/controllers/threebox.js index dc83f3673a0d..080fac6cc257 100644 --- a/app/scripts/controllers/threebox.js +++ b/app/scripts/controllers/threebox.js @@ -1,6 +1,6 @@ import ObservableStore from 'obs-store' -/* eslint-disable import/order */ +/* eslint-disable import/first,import/order */ const Box = process.env.IN_TEST ? require('../../../development/mock-3box') : require('3box') @@ -13,6 +13,7 @@ import Migrator from '../lib/migrator' import migrations from '../migrations' import createOriginMiddleware from '../lib/createOriginMiddleware' import createMetamaskMiddleware from './network/createMetamaskMiddleware' +/* eslint-enable import/first */ const SYNC_TIMEOUT = 60 * 1000 // one minute @@ -42,9 +43,8 @@ export default class ThreeBoxController { if (isUnlocked && accounts[0]) { const appKeyAddress = await this.keyringController.getAppKeyAddress(accounts[0], 'wallet://3box.metamask.io') return [appKeyAddress] - } else { - return [] } + return [] }, processPersonalMessage: async (msgParams) => { const accounts = await this.keyringController.getAccounts() diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js index 4ef8b8ff8df1..bbc4ad778e36 100644 --- a/app/scripts/controllers/token-rates.js +++ b/app/scripts/controllers/token-rates.js @@ -3,7 +3,6 @@ import log from 'loglevel' import { normalize as normalizeAddress } from 'eth-sig-util' import ethUtil from 'ethereumjs-util' - // By default, poll every 3 minutes const DEFAULT_INTERVAL = 180 * 1000 @@ -12,6 +11,7 @@ const DEFAULT_INTERVAL = 180 * 1000 * rates based on a user's current token list */ export default class TokenRatesController { + /** * Creates a TokenRatesController * diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index ffc8246dbbd4..96ac1c5fd435 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -6,9 +6,6 @@ import EthQuery from 'ethjs-query' import { ethErrors } from 'eth-json-rpc-errors' import abi from 'human-standard-token-abi' import abiDecoder from 'abi-decoder' - -abiDecoder.addABI(abi) - import NonceTracker from 'nonce-tracker' import log from 'loglevel' import { @@ -19,7 +16,6 @@ import { DEPLOY_CONTRACT_ACTION_KEY, CONTRACT_INTERACTION_KEY, } from '../../../../ui/app/helpers/constants/transactions' - import cleanErrorStack from '../../lib/cleanErrorStack' import { hexToBn, bnToHex, BnMultiplyByFraction } from '../../lib/util' import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys' @@ -27,7 +23,6 @@ import TransactionStateManager from './tx-state-manager' import TxGasUtil from './tx-gas-utils' import PendingTransactionTracker from './pending-tx-tracker' import * as txUtils from './lib/util' - import { TRANSACTION_TYPE_CANCEL, TRANSACTION_TYPE_RETRY, @@ -35,6 +30,7 @@ import { TRANSACTION_STATUS_APPROVED, } from './enums' +abiDecoder.addABI(abi) const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. const MAX_MEMSTORE_TX_LIST_SIZE = 100 // Number of transactions (by unique nonces) to keep in memory @@ -53,7 +49,6 @@ const MAX_MEMSTORE_TX_LIST_SIZE = 100 // Number of transactions (by unique nonce
- nonceTracker calculating nonces - @class @param {Object} - opts @param {Object} opts.initState - initial transaction list default is an empty array @@ -137,9 +132,8 @@ export default class TransactionController extends EventEmitter { const integerChainId = parseInt(networkState) if (Number.isNaN(integerChainId)) { return 0 - } else { - return integerChainId } + return integerChainId } /** @@ -201,6 +195,7 @@ export default class TransactionController extends EventEmitter { const normalizedTxParams = txUtils.normalizeTxParams(txParams) txUtils.validateTxParams(normalizedTxParams) + /** `generateTxMeta` adds the default txMeta properties to the passed object. These include the tx's `id`. As we use the id for determining order of @@ -233,7 +228,7 @@ export default class TransactionController extends EventEmitter { } } - txMeta['origin'] = origin + txMeta.origin = origin const { transactionCategory, getCodeResponse } = await this._determineTransactionCategory(txParams) txMeta.transactionCategory = transactionCategory @@ -497,7 +492,7 @@ export default class TransactionController extends EventEmitter { const txMeta = this.txStateManager.getTx(txId) // add network/chain id const chainId = this.getChainId() - const txParams = Object.assign({}, txMeta.txParams, { chainId }) + const txParams = { ...txMeta.txParams, chainId } // sign tx const fromAddress = txParams.from const ethTx = new Transaction(txParams) @@ -606,19 +601,25 @@ export default class TransactionController extends EventEmitter { // /** maps methods for convenience*/ _mapMethods () { + /** @returns {Object} - the state in transaction controller */ this.getState = () => this.memStore.getState() + /** @returns {string|number} - the network number stored in networkStore */ this.getNetwork = () => this.networkStore.getState() + /** @returns {string} - the user selected address */ this.getSelectedAddress = () => this.preferencesStore.getState().selectedAddress + /** @returns {array} - transactions whos status is unapproved */ this.getUnapprovedTxCount = () => Object.keys(this.txStateManager.getUnapprovedTxList()).length + /** @returns {number} - number of transactions that have the status submitted @param {string} account - hex prefixed account */ this.getPendingTxCount = (account) => this.txStateManager.getPendingTransactions(account).length + /** see txStateManager */ this.getFilteredTxList = (opts) => this.txStateManager.getFilteredTxList(opts) } diff --git a/app/scripts/controllers/transactions/pending-tx-tracker.js b/app/scripts/controllers/transactions/pending-tx-tracker.js index 3ae85e4fa067..e1b33cb2ffb3 100644 --- a/app/scripts/controllers/transactions/pending-tx-tracker.js +++ b/app/scripts/controllers/transactions/pending-tx-tracker.js @@ -15,11 +15,11 @@ import EthQuery from 'ethjs-query' @param {function} config.getPendingTransactions a function for getting an array of transactions, @param {function} config.publishTransaction a async function for publishing raw transactions, - @class */ export default class PendingTransactionTracker extends EventEmitter { + /** * We wait this many blocks before emitting a 'tx:dropped' event * @@ -196,7 +196,6 @@ export default class PendingTransactionTracker extends EventEmitter { if (await this._checkIfTxWasDropped(txMeta)) { this.emit('tx:dropped', txId) - return } } diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index bbdd51872fa5..b5c7e335395e 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -4,6 +4,7 @@ import log from 'loglevel' import createId from '../../lib/random-id' import { generateHistoryEntry, replayHistory, snapshotFromTxMeta } from './lib/tx-state-history-helpers' import { getFinalStates, normalizeTxParams } from './lib/util' + /** TransactionStateManager is responsible for the state of a transaction and storing the transaction @@ -31,9 +32,8 @@ export default class TransactionStateManager extends EventEmitter { super() this.store = new ObservableStore( - Object.assign({ - transactions: [], - }, initState)) + { transactions: [], ...initState }, + ) this.txHistoryLimit = txHistoryLimit this.getNetwork = getNetwork } @@ -47,13 +47,13 @@ export default class TransactionStateManager extends EventEmitter { if (netId === 'loading') { throw new Error('MetaMask is having trouble connecting to the network') } - return Object.assign({ + return { id: createId(), time: (new Date()).getTime(), status: 'unapproved', metamaskNetworkId: netId, - loadingDefaults: true, - }, opts) + loadingDefaults: true, ...opts, + } } /** @@ -202,6 +202,7 @@ export default class TransactionStateManager extends EventEmitter { this._saveTxList(transactions) return txMeta } + /** @param {number} txId @returns {Object} - the txMeta who matches the given id if none found @@ -241,7 +242,6 @@ export default class TransactionStateManager extends EventEmitter { this._saveTxList(txList) } - /** merges txParams obj onto txMeta.txParams use extend to ensure that all fields are filled @@ -326,6 +326,7 @@ export default class TransactionStateManager extends EventEmitter { }) return filteredTxList } + /** @param {string} key - the key to check @@ -340,9 +341,8 @@ export default class TransactionStateManager extends EventEmitter { return txList.filter((txMeta) => { if (key in txMeta.txParams) { return filter(txMeta.txParams[key]) - } else { - return filter(txMeta[key]) } + return filter(txMeta[key]) }) } @@ -373,6 +373,7 @@ export default class TransactionStateManager extends EventEmitter { setTxStatusUnapproved (txId) { this._setTxStatus(txId, 'unapproved') } + /** should update the status of the tx to 'approved'. @param {number} txId - the txMeta Id @@ -417,7 +418,6 @@ export default class TransactionStateManager extends EventEmitter { this._setTxStatus(txId, 'dropped') } - /** should update the status of the tx to 'failed'. and put the error on the txMeta diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 3cb837373107..546f0a36272a 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -30,12 +30,14 @@ const restoreContextAfterImports = () => { cleanContextForImports() +/* eslint-disable import/first */ import log from 'loglevel' import LocalMessageDuplexStream from 'post-message-stream' import { initProvider } from '@metamask/inpage-provider' // TODO:deprecate:2020 import setupWeb3 from './lib/setupWeb3' +/* eslint-enable import/first */ restoreContextAfterImports() @@ -58,7 +60,6 @@ initProvider({ // TODO:deprecate:2020 // Setup web3 - if (typeof window.web3 !== 'undefined') { throw new Error(`MetaMask detected another web3. MetaMask will not work reliably with another web3 extension. diff --git a/app/scripts/lib/ComposableObservableStore.js b/app/scripts/lib/ComposableObservableStore.js index 3fb90b4b6b0e..ef8e91f22d09 100644 --- a/app/scripts/lib/ComposableObservableStore.js +++ b/app/scripts/lib/ComposableObservableStore.js @@ -5,6 +5,7 @@ import ObservableStore from 'obs-store' * structure of child stores based on configuration */ export default class ComposableObservableStore extends ObservableStore { + /** * Create a new store * diff --git a/app/scripts/lib/cleanErrorStack.js b/app/scripts/lib/cleanErrorStack.js index 46e069e8e722..c68c29b9e1b9 100644 --- a/app/scripts/lib/cleanErrorStack.js +++ b/app/scripts/lib/cleanErrorStack.js @@ -15,7 +15,7 @@ export default function cleanErrorStack (err) { } else if (msg === '') { err.stack = err.name } else { - err.stack = err.name + ': ' + err.message + err.stack = `${err.name}: ${err.message}` } return err diff --git a/app/scripts/lib/createStreamSink.js b/app/scripts/lib/createStreamSink.js index 5a9d0808ede6..ad0a67959af2 100644 --- a/app/scripts/lib/createStreamSink.js +++ b/app/scripts/lib/createStreamSink.js @@ -4,7 +4,7 @@ import promiseToCallback from 'promise-to-callback' class AsyncWritableStream extends WritableStream { constructor (asyncWriteFn, _opts) { - const opts = Object.assign({ objectMode: true }, _opts) + const opts = { objectMode: true, ..._opts } super(opts) this._asyncWriteFn = asyncWriteFn } diff --git a/app/scripts/lib/decrypt-message-manager.js b/app/scripts/lib/decrypt-message-manager.js index 060a11d9b902..a31074f12aaa 100644 --- a/app/scripts/lib/decrypt-message-manager.js +++ b/app/scripts/lib/decrypt-message-manager.js @@ -26,6 +26,7 @@ const hexRe = /^[0-9A-Fa-f]+$/ug */ export default class DecryptMessageManager extends EventEmitter { + /** * Controller in charge of managing - storing, adding, removing, updating - DecryptMessage. * @@ -100,7 +101,6 @@ export default class DecryptMessageManager extends EventEmitter { return default: reject(new Error(`MetaMask Decryption: Unknown problem: ${JSON.stringify(msgParams)}`)) - return } }) }) @@ -128,8 +128,8 @@ export default class DecryptMessageManager extends EventEmitter { const msgId = createId() const msgData = { id: msgId, - msgParams: msgParams, - time: time, + msgParams, + time, status: 'unapproved', type: MESSAGE_TYPE.ETH_DECRYPT, } diff --git a/app/scripts/lib/encryption-public-key-manager.js b/app/scripts/lib/encryption-public-key-manager.js index 8d78bf8bd616..2631dc7d3570 100644 --- a/app/scripts/lib/encryption-public-key-manager.js +++ b/app/scripts/lib/encryption-public-key-manager.js @@ -23,6 +23,7 @@ import { MESSAGE_TYPE } from './enums' */ export default class EncryptionPublicKeyManager extends EventEmitter { + /** * Controller in charge of managing - storing, adding, removing, updating - EncryptionPublicKey. * @@ -94,7 +95,6 @@ export default class EncryptionPublicKeyManager extends EventEmitter { return default: reject(new Error(`MetaMask EncryptionPublicKey: Unknown problem: ${JSON.stringify(address)}`)) - return } }) }) @@ -118,7 +118,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter { const msgData = { id: msgId, msgParams: address, - time: time, + time, status: 'unapproved', type: MESSAGE_TYPE.ETH_GET_ENCRYPTION_PUBLIC_KEY, } diff --git a/app/scripts/lib/ens-ipfs/resolver.js b/app/scripts/lib/ens-ipfs/resolver.js index 67acba8c7f34..cc307e61710f 100644 --- a/app/scripts/lib/ens-ipfs/resolver.js +++ b/app/scripts/lib/ens-ipfs/resolver.js @@ -36,7 +36,7 @@ export default async function resolveEnsToIpfsContentId ({ provider, name }) { decodedContentHash = contentHash.helpers.cidV0ToV1Base32(decodedContentHash) } - return { type: type, hash: decodedContentHash } + return { type, hash: decodedContentHash } } if (isLegacyResolver[0]) { // lookup content id diff --git a/app/scripts/lib/extractEthjsErrorMessage.js b/app/scripts/lib/extractEthjsErrorMessage.js index 6d9d0bf2d930..0dde04f0689b 100644 --- a/app/scripts/lib/extractEthjsErrorMessage.js +++ b/app/scripts/lib/extractEthjsErrorMessage.js @@ -19,7 +19,6 @@ export default function extractEthjsErrorMessage (errorMessage) { const payloadAndError = errorMessage.slice(ethJsRpcSlug.length) const originalError = payloadAndError.slice(payloadAndError.indexOf(errorLabelPrefix) + errorLabelPrefix.length) return originalError - } else { - return errorMessage } + return errorMessage } diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 5d51b5f725ed..e7f05781c8b7 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -6,11 +6,12 @@ import { checkForError } from './util' * A wrapper around the extension's storage local API */ export default class ExtensionStore { + /** * @constructor */ constructor () { - this.isSupported = !!(extension.storage.local) + this.isSupported = Boolean(extension.storage.local) if (!this.isSupported) { log.error('Storage local API not available.') } @@ -29,9 +30,8 @@ export default class ExtensionStore { // if the object is empty, treat it as undefined if (isEmpty(result)) { return undefined - } else { - return result } + return result } /** diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index 6c74b017adca..280003c40c96 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -115,8 +115,8 @@ export default class MessageManager extends EventEmitter { const msgId = createId() const msgData = { id: msgId, - msgParams: msgParams, - time: time, + msgParams, + time, status: 'unapproved', type: MESSAGE_TYPE.ETH_SIGN, } @@ -279,8 +279,7 @@ function normalizeMsgData (data) { if (data.slice(0, 2) === '0x') { // data is already hex return data - } else { - // data is unicode, convert to hex - return ethUtil.bufferToHex(Buffer.from(data, 'utf8')) } + // data is unicode, convert to hex + return ethUtil.bufferToHex(Buffer.from(data, 'utf8')) } diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 7e6ac3c4ec7b..52c0f9bad8dc 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -28,6 +28,7 @@ const hexRe = /^[0-9A-Fa-f]+$/ug */ export default class PersonalMessageManager extends EventEmitter { + /** * Controller in charge of managing - storing, adding, removing, updating - PersonalMessage. * @@ -100,7 +101,6 @@ export default class PersonalMessageManager extends EventEmitter { return default: reject(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`)) - return } }) }) @@ -128,8 +128,8 @@ export default class PersonalMessageManager extends EventEmitter { const msgId = createId() const msgData = { id: msgId, - msgParams: msgParams, - time: time, + msgParams, + time, status: 'unapproved', type: MESSAGE_TYPE.PERSONAL_SIGN, } diff --git a/app/scripts/lib/random-id.js b/app/scripts/lib/random-id.js index eebba061921d..9345fcaad7fa 100644 --- a/app/scripts/lib/random-id.js +++ b/app/scripts/lib/random-id.js @@ -2,7 +2,7 @@ const MAX = Number.MAX_SAFE_INTEGER let idCounter = Math.round(Math.random() * MAX) export default function createRandomId () { - idCounter = idCounter % MAX + idCounter %= MAX // eslint-disable-next-line no-plusplus return idCounter++ } diff --git a/app/scripts/lib/seed-phrase-verifier.js b/app/scripts/lib/seed-phrase-verifier.js index f07e63a2c731..71b9e281949b 100644 --- a/app/scripts/lib/seed-phrase-verifier.js +++ b/app/scripts/lib/seed-phrase-verifier.js @@ -30,8 +30,8 @@ const seedPhraseVerifier = { const keyring = new Keyring(opts) const restoredAccounts = await keyring.getAccounts() - log.debug('Created accounts: ' + JSON.stringify(createdAccounts)) - log.debug('Restored accounts: ' + JSON.stringify(restoredAccounts)) + log.debug(`Created accounts: ${JSON.stringify(createdAccounts)}`) + log.debug(`Restored accounts: ${JSON.stringify(restoredAccounts)}`) if (restoredAccounts.length !== createdAccounts.length) { // this should not happen... @@ -40,7 +40,7 @@ const seedPhraseVerifier = { for (let i = 0; i < restoredAccounts.length; i++) { if (restoredAccounts[i].toLowerCase() !== createdAccounts[i].toLowerCase()) { - throw new Error('Not identical accounts! Original: ' + createdAccounts[i] + ', Restored: ' + restoredAccounts[i]) + throw new Error(`Not identical accounts! Original: ${createdAccounts[i]}, Restored: ${restoredAccounts[i]}`) } } }, diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index 8c3caca2eacd..64ce6427c0d3 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -28,6 +28,7 @@ import { MESSAGE_TYPE } from './enums' */ export default class TypedMessageManager extends EventEmitter { + /** * Controller in charge of managing - storing, adding, removing, updating - TypedMessage. */ @@ -119,8 +120,8 @@ export default class TypedMessageManager extends EventEmitter { const msgId = createId() const msgData = { id: msgId, - msgParams: msgParams, - time: time, + msgParams, + time, status: 'unapproved', type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA, } diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index 6d06758b3e9c..08998d6cc4f1 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -27,9 +27,8 @@ const getEnvironmentTypeMemo = memoize((url) => { return ENVIRONMENT_TYPE_FULLSCREEN } else if (parsedUrl.pathname === '/notification.html') { return ENVIRONMENT_TYPE_NOTIFICATION - } else { - return ENVIRONMENT_TYPE_BACKGROUND } + return ENVIRONMENT_TYPE_BACKGROUND }) /** diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index e7d1de51d23e..1c99424bcd02 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -63,7 +63,6 @@ import accountImporter from './account-import-strategies' import selectChainId from './lib/select-chain-id' import seedPhraseVerifier from './lib/seed-phrase-verifier' - import backgroundMetaMetricsEvent from './lib/background-metametrics' export default class MetamaskController extends EventEmitter { @@ -274,7 +273,6 @@ export default class MetamaskController extends EventEmitter { this.encryptionPublicKeyManager = new EncryptionPublicKeyManager() this.typedMessageManager = new TypedMessageManager({ networkController: this.networkController }) - this.store.updateStructure({ AppStateController: this.appStateController.store, TransactionController: this.txController.store, @@ -407,7 +405,7 @@ export default class MetamaskController extends EventEmitter { */ getState () { const { vault } = this.keyringController.store.getState() - const isInitialized = !!vault + const isInitialized = Boolean(vault) return { ...{ isInitialized }, @@ -929,7 +927,6 @@ export default class MetamaskController extends EventEmitter { return { ...keyState, identities } } - // // Account Management // @@ -1029,7 +1026,6 @@ export default class MetamaskController extends EventEmitter { return address } - /** * Imports an account with the specified import strategy. * These are defined in app/scripts/account-import-strategies @@ -1041,7 +1037,7 @@ export default class MetamaskController extends EventEmitter { */ async importAccountWithStrategy (strategy, args) { const privateKey = await accountImporter.importAccount(strategy, args) - const keyring = await this.keyringController.addNewKeyring('Simple Key Pair', [ privateKey ]) + const keyring = await this.keyringController.addNewKeyring('Simple Key Pair', [privateKey]) const accounts = await keyring.getAccounts() // update accounts in preferences controller const allAccounts = await this.keyringController.getAccounts() @@ -1116,10 +1112,10 @@ export default class MetamaskController extends EventEmitter { cancelMessage (msgId, cb) { const { messageManager } = this messageManager.rejectMsg(msgId) - if (cb && typeof cb === 'function') { - cb(null, this.getState()) + if (!cb || typeof cb !== 'function') { return } + cb(null, this.getState()) } // personal_sign methods: @@ -1175,10 +1171,10 @@ export default class MetamaskController extends EventEmitter { cancelPersonalMessage (msgId, cb) { const messageManager = this.personalMessageManager messageManager.rejectMsg(msgId) - if (cb && typeof cb === 'function') { - cb(null, this.getState()) + if (!cb || typeof cb !== 'function') { return } + cb(null, this.getState()) } // eth_decrypt methods @@ -1260,10 +1256,10 @@ export default class MetamaskController extends EventEmitter { cancelDecryptMessage (msgId, cb) { const messageManager = this.decryptMessageManager messageManager.rejectMsg(msgId) - if (cb && typeof cb === 'function') { - cb(null, this.getState()) + if (!cb || typeof cb !== 'function') { return } + cb(null, this.getState()) } // eth_getEncryptionPublicKey methods @@ -1318,10 +1314,10 @@ export default class MetamaskController extends EventEmitter { cancelEncryptionPublicKey (msgId, cb) { const messageManager = this.encryptionPublicKeyManager messageManager.rejectMsg(msgId) - if (cb && typeof cb === 'function') { - cb(null, this.getState()) + if (!cb || typeof cb !== 'function') { return } + cb(null, this.getState()) } // eth_signTypedData methods @@ -1379,10 +1375,10 @@ export default class MetamaskController extends EventEmitter { cancelTypedMessage (msgId, cb) { const messageManager = this.typedMessageManager messageManager.rejectMsg(msgId) - if (cb && typeof cb === 'function') { - cb(null, this.getState()) + if (!cb || typeof cb !== 'function') { return } + cb(null, this.getState()) } //============================================================================= @@ -1872,6 +1868,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -1892,7 +1889,6 @@ export default class MetamaskController extends EventEmitter { return rpcUrl } - /** * A method for selecting a custom URL for an ethereum RPC provider. * @param {string} rpcTarget - A URL for a valid Ethereum RPC API. @@ -1938,6 +1934,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -1954,6 +1951,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -1970,6 +1968,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -1986,6 +1985,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -2002,6 +2002,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -2013,6 +2014,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -2029,11 +2031,11 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } - /** * A method for setting a user's current locale, affecting the language rendered. * @param {string} key - Locale identifier. @@ -2046,6 +2048,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } diff --git a/app/scripts/migrations/002.js b/app/scripts/migrations/002.js index a726d01e3a1f..24df7f4dedf3 100644 --- a/app/scripts/migrations/002.js +++ b/app/scripts/migrations/002.js @@ -1,12 +1,11 @@ -const version = 2 - import { cloneDeep } from 'lodash' +const version = 2 export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { diff --git a/app/scripts/migrations/003.js b/app/scripts/migrations/003.js index 9584fb88967d..08e4be468728 100644 --- a/app/scripts/migrations/003.js +++ b/app/scripts/migrations/003.js @@ -1,13 +1,13 @@ +import { cloneDeep } from 'lodash' + const version = 3 const oldTestRpc = 'https://rawtestrpc.metamask.io/' const newTestRpc = 'https://testrpc.metamask.io/' -import { cloneDeep } from 'lodash' - export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { diff --git a/app/scripts/migrations/004.js b/app/scripts/migrations/004.js index d2d3136f3c1a..48741a267831 100644 --- a/app/scripts/migrations/004.js +++ b/app/scripts/migrations/004.js @@ -1,11 +1,11 @@ -const version = 4 - import { cloneDeep } from 'lodash' +const version = 4 + export default { version, - migrate: function (versionedData) { + migrate (versionedData) { const safeVersionedData = cloneDeep(versionedData) safeVersionedData.meta.version = version try { diff --git a/app/scripts/migrations/005.js b/app/scripts/migrations/005.js index 00f3ca552d67..baead6890b15 100644 --- a/app/scripts/migrations/005.js +++ b/app/scripts/migrations/005.js @@ -1,5 +1,3 @@ -const version = 5 - /* This migration moves state from the flat state trie into KeyringController substate @@ -8,11 +6,12 @@ This migration moves state from the flat state trie into KeyringController subst import { cloneDeep } from 'lodash' +const version = 5 export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -20,7 +19,7 @@ export default { const newState = selectSubstateForKeyringController(state) versionedData.data = newState } catch (err) { - console.warn('MetaMask Migration #5' + err.stack) + console.warn(`MetaMask Migration #5${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/006.js b/app/scripts/migrations/006.js index b53015315d6e..8d1e72935903 100644 --- a/app/scripts/migrations/006.js +++ b/app/scripts/migrations/006.js @@ -1,5 +1,3 @@ -const version = 6 - /* This migration moves KeyringController.selectedAddress to PreferencesController.selectedAddress @@ -8,10 +6,12 @@ This migration moves KeyringController.selectedAddress to PreferencesController. import { cloneDeep } from 'lodash' +const version = 6 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { const newState = migrateState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/007.js b/app/scripts/migrations/007.js index bacf005fa551..41272ee3b04d 100644 --- a/app/scripts/migrations/007.js +++ b/app/scripts/migrations/007.js @@ -1,5 +1,3 @@ -const version = 7 - /* This migration breaks out the TransactionManager substate @@ -8,10 +6,12 @@ This migration breaks out the TransactionManager substate import { cloneDeep } from 'lodash' +const version = 7 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/008.js b/app/scripts/migrations/008.js index a4537ae9b3f6..6f25bbcd57c9 100644 --- a/app/scripts/migrations/008.js +++ b/app/scripts/migrations/008.js @@ -1,5 +1,3 @@ -const version = 8 - /* This migration breaks out the NoticeController substate @@ -8,10 +6,12 @@ This migration breaks out the NoticeController substate import { cloneDeep } from 'lodash' +const version = 8 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/009.js b/app/scripts/migrations/009.js index 3fddf7aa94af..f632978362a0 100644 --- a/app/scripts/migrations/009.js +++ b/app/scripts/migrations/009.js @@ -1,5 +1,3 @@ -const version = 9 - /* This migration breaks out the CurrencyController substate @@ -8,10 +6,12 @@ This migration breaks out the CurrencyController substate import { cloneDeep, merge } from 'lodash' +const version = 9 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/010.js b/app/scripts/migrations/010.js index c8dd42aafee8..354b198714ee 100644 --- a/app/scripts/migrations/010.js +++ b/app/scripts/migrations/010.js @@ -1,5 +1,3 @@ -const version = 10 - /* This migration breaks out the ShapeShiftController substate @@ -8,10 +6,12 @@ This migration breaks out the ShapeShiftController substate import { cloneDeep, merge } from 'lodash' +const version = 10 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/011.js b/app/scripts/migrations/011.js index d465bf5a6bd2..d8f852f9f2f5 100644 --- a/app/scripts/migrations/011.js +++ b/app/scripts/migrations/011.js @@ -1,5 +1,3 @@ -const version = 11 - /* This migration removes the discaimer state from our app, which was integrated into our notices. @@ -8,10 +6,12 @@ This migration removes the discaimer state from our app, which was integrated in import { cloneDeep } from 'lodash' +const version = 11 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/012.js b/app/scripts/migrations/012.js index fc3ddc59c28c..d01edbc41d32 100644 --- a/app/scripts/migrations/012.js +++ b/app/scripts/migrations/012.js @@ -1,5 +1,3 @@ -const version = 12 - /* This migration modifies our notices to delete their body after being read. @@ -8,10 +6,12 @@ This migration modifies our notices to delete their body after being read. import { cloneDeep } from 'lodash' +const version = 12 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/013.js b/app/scripts/migrations/013.js index 433face729a7..530fc687c44e 100644 --- a/app/scripts/migrations/013.js +++ b/app/scripts/migrations/013.js @@ -1,5 +1,3 @@ -const version = 13 - /* This migration modifies the network config from ambiguous 'testnet' to explicit 'ropsten' @@ -8,10 +6,12 @@ This migration modifies the network config from ambiguous 'testnet' to explicit import { cloneDeep } from 'lodash' +const version = 13 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/014.js b/app/scripts/migrations/014.js index e7a7b8c991c5..630aa2051009 100644 --- a/app/scripts/migrations/014.js +++ b/app/scripts/migrations/014.js @@ -1,5 +1,3 @@ -const version = 14 - /* This migration removes provider from config and moves it too NetworkController. @@ -8,10 +6,12 @@ This migration removes provider from config and moves it too NetworkController. import { cloneDeep } from 'lodash' +const version = 14 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/015.js b/app/scripts/migrations/015.js index de6ce94bcbbd..682eb8db74e9 100644 --- a/app/scripts/migrations/015.js +++ b/app/scripts/migrations/015.js @@ -1,5 +1,3 @@ -const version = 15 - /* This migration sets transactions with the 'Gave up submitting tx.' err message @@ -9,10 +7,12 @@ to a 'failed' stated import { cloneDeep } from 'lodash' +const version = 15 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -20,7 +20,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/016.js b/app/scripts/migrations/016.js index dcef6f313284..974a1125d52a 100644 --- a/app/scripts/migrations/016.js +++ b/app/scripts/migrations/016.js @@ -1,5 +1,3 @@ -const version = 16 - /* This migration sets transactions with the 'Gave up submitting tx.' err message @@ -9,10 +7,12 @@ to a 'failed' stated import { cloneDeep } from 'lodash' +const version = 16 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -20,7 +20,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/017.js b/app/scripts/migrations/017.js index 8e43863adfd2..497cbe33eac6 100644 --- a/app/scripts/migrations/017.js +++ b/app/scripts/migrations/017.js @@ -1,5 +1,3 @@ -const version = 17 - /* This migration sets transactions who were retried and marked as failed to submitted @@ -8,10 +6,12 @@ This migration sets transactions who were retried and marked as failed to submit import { cloneDeep } from 'lodash' +const version = 17 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/018.js b/app/scripts/migrations/018.js index c2dc39b260d7..bb57ddf0cae3 100644 --- a/app/scripts/migrations/018.js +++ b/app/scripts/migrations/018.js @@ -1,5 +1,3 @@ -const version = 18 - /* This migration updates "transaction state history" to diffs style @@ -12,11 +10,12 @@ import { migrateFromSnapshotsToDiffs, } from '../controllers/transactions/lib/tx-state-history-helpers' +const version = 18 export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -24,7 +23,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js index d99fa6aa8fe1..4c786b7c9b28 100644 --- a/app/scripts/migrations/019.js +++ b/app/scripts/migrations/019.js @@ -1,6 +1,4 @@ -const version = 19 - /* This migration sets transactions as failed @@ -10,10 +8,12 @@ whos nonce is too high import { cloneDeep } from 'lodash' +const version = 19 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -21,7 +21,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/020.js b/app/scripts/migrations/020.js index eaf6dcbc00b6..eb8080124799 100644 --- a/app/scripts/migrations/020.js +++ b/app/scripts/migrations/020.js @@ -1,5 +1,3 @@ -const version = 20 - /* This migration ensures previous installations @@ -10,10 +8,12 @@ so that we can version notices in the future. import { cloneDeep } from 'lodash' +const version = 20 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -21,7 +21,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/021.js b/app/scripts/migrations/021.js index c57266f08d3c..ac3170131dcf 100644 --- a/app/scripts/migrations/021.js +++ b/app/scripts/migrations/021.js @@ -1,5 +1,3 @@ -const version = 21 - /* This migration removes the BlackListController from disk state @@ -8,10 +6,12 @@ This migration removes the BlackListController from disk state import { cloneDeep } from 'lodash' +const version = 21 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/022.js b/app/scripts/migrations/022.js index 630bc2022fae..76f96a0ae1f9 100644 --- a/app/scripts/migrations/022.js +++ b/app/scripts/migrations/022.js @@ -1,6 +1,4 @@ -const version = 22 - /* This migration adds submittedTime to the txMeta if it is not their @@ -9,10 +7,12 @@ This migration adds submittedTime to the txMeta if it is not their import { cloneDeep } from 'lodash' +const version = 22 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -20,7 +20,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/023.js b/app/scripts/migrations/023.js index b6f9a1038f60..5f0363d530a0 100644 --- a/app/scripts/migrations/023.js +++ b/app/scripts/migrations/023.js @@ -1,6 +1,4 @@ -const version = 23 - /* This migration removes transactions that are no longer usefull down to 40 total @@ -9,10 +7,12 @@ This migration removes transactions that are no longer usefull down to 40 total import { cloneDeep } from 'lodash' +const version = 23 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -20,7 +20,7 @@ export default { const newState = transformState(state) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) }, diff --git a/app/scripts/migrations/024.js b/app/scripts/migrations/024.js index 07257d428504..84a998d12a48 100644 --- a/app/scripts/migrations/024.js +++ b/app/scripts/migrations/024.js @@ -1,6 +1,4 @@ -const version = 24 - /* This migration ensures that the from address in txParams is to lower case for @@ -10,10 +8,12 @@ all unapproved transactions import { cloneDeep } from 'lodash' +const version = 24 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/025.js b/app/scripts/migrations/025.js index 0f5f568ab77d..72bcdbf01f76 100644 --- a/app/scripts/migrations/025.js +++ b/app/scripts/migrations/025.js @@ -1,6 +1,4 @@ // next version number -const version = 25 - /* normalizes txParams on unconfirmed txs @@ -10,10 +8,12 @@ import ethUtil from 'ethereumjs-util' import { cloneDeep } from 'lodash' +const version = 25 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/026.js b/app/scripts/migrations/026.js index 2282455ef1c5..e6cb9db85ebc 100644 --- a/app/scripts/migrations/026.js +++ b/app/scripts/migrations/026.js @@ -1,5 +1,3 @@ -const version = 26 - /* This migration moves the identities stored in the KeyringController @@ -9,6 +7,8 @@ This migration moves the identities stored in the KeyringController import { cloneDeep } from 'lodash' +const version = 26 + export default { version, migrate (originalVersionedData) { @@ -18,7 +18,7 @@ export default { const state = versionedData.data versionedData.data = transformState(state) } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) return Promise.reject(err) } return Promise.resolve(versionedData) diff --git a/app/scripts/migrations/027.js b/app/scripts/migrations/027.js index 2607f03da3ae..42e024f56ed1 100644 --- a/app/scripts/migrations/027.js +++ b/app/scripts/migrations/027.js @@ -1,6 +1,4 @@ // next version number -const version = 27 - /* normalizes txParams on unconfirmed txs @@ -8,10 +6,12 @@ normalizes txParams on unconfirmed txs */ import { cloneDeep } from 'lodash' +const version = 27 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/028.js b/app/scripts/migrations/028.js index 522067f8ba5d..fa816ca53ef7 100644 --- a/app/scripts/migrations/028.js +++ b/app/scripts/migrations/028.js @@ -1,6 +1,4 @@ // next version number -const version = 28 - /* normalizes txParams on unconfirmed txs @@ -8,10 +6,12 @@ normalizes txParams on unconfirmed txs */ import { cloneDeep } from 'lodash' +const version = 28 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/029.js b/app/scripts/migrations/029.js index 345d1ad92031..4773eb4666ed 100644 --- a/app/scripts/migrations/029.js +++ b/app/scripts/migrations/029.js @@ -1,7 +1,8 @@ // next version number -const version = 29 import failTxsThat from './fail-tx' +const version = 29 + // time const seconds = 1000 const minutes = 60 * seconds diff --git a/app/scripts/migrations/030.js b/app/scripts/migrations/030.js index 351fbb2698ec..6f11e27a5d66 100644 --- a/app/scripts/migrations/030.js +++ b/app/scripts/migrations/030.js @@ -1,6 +1,4 @@ // next version number -const version = 30 - /* removes invalid chaids from preferences and networkController for custom rpcs @@ -9,10 +7,12 @@ removes invalid chaids from preferences and networkController for custom rpcs import { cloneDeep } from 'lodash' +const version = 30 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data @@ -29,7 +29,7 @@ function transformState (state) { if (frequentRpcListDetail) { frequentRpcListDetail.forEach((rpc, index) => { // eslint-disable-next-line radix - if (!!rpc.chainId && Number.isNaN(parseInt(rpc.chainId))) { + if (Boolean(rpc.chainId) && Number.isNaN(parseInt(rpc.chainId))) { delete frequentRpcListDetail[index].chainId } }) diff --git a/app/scripts/migrations/031.js b/app/scripts/migrations/031.js index 14d4a7ef819f..59a8dcf15a47 100644 --- a/app/scripts/migrations/031.js +++ b/app/scripts/migrations/031.js @@ -1,7 +1,8 @@ // next version number -const version = 31 import { cloneDeep } from 'lodash' +const version = 31 + /* * The purpose of this migration is to properly set the completedOnboarding flag based on the state * of the KeyringController. @@ -9,7 +10,7 @@ import { cloneDeep } from 'lodash' export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/032.js b/app/scripts/migrations/032.js index 4f807617de9f..fce4d65a6675 100644 --- a/app/scripts/migrations/032.js +++ b/app/scripts/migrations/032.js @@ -1,12 +1,13 @@ -const version = 32 import { cloneDeep } from 'lodash' +const version = 32 + /** * The purpose of this migration is to set the {@code completedUiMigration} flag based on the user's UI preferences */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/033.js b/app/scripts/migrations/033.js index 70710e793c55..e1e0ea3b428d 100644 --- a/app/scripts/migrations/033.js +++ b/app/scripts/migrations/033.js @@ -1,6 +1,4 @@ // next version number -const version = 33 - /* Cleans up notices and assocated notice controller code @@ -9,10 +7,12 @@ Cleans up notices and assocated notice controller code import { cloneDeep } from 'lodash' +const version = 33 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/034.js b/app/scripts/migrations/034.js index 92a8d909ffe4..ba61131e4104 100644 --- a/app/scripts/migrations/034.js +++ b/app/scripts/migrations/034.js @@ -1,13 +1,14 @@ -const version = 34 import { cloneDeep } from 'lodash' +const version = 34 + /** * The purpose of this migration is to enable the {@code privacyMode} feature flag and set the user as being migrated * if it was {@code false}. */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/035.js b/app/scripts/migrations/035.js index b483c35de756..6ea63473039b 100644 --- a/app/scripts/migrations/035.js +++ b/app/scripts/migrations/035.js @@ -1,6 +1,4 @@ // next version number -const version = 35 - /* Removes the deprecated 'seedWords' state @@ -9,10 +7,12 @@ Removes the deprecated 'seedWords' state import { cloneDeep } from 'lodash' +const version = 35 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version versionedData.data = transformState(versionedData.data) diff --git a/app/scripts/migrations/036.js b/app/scripts/migrations/036.js index 0ba0bc035de9..2b64fc6ea8ca 100644 --- a/app/scripts/migrations/036.js +++ b/app/scripts/migrations/036.js @@ -1,12 +1,13 @@ -const version = 36 import { cloneDeep } from 'lodash' +const version = 36 + /** * The purpose of this migration is to remove the {@code privacyMode} feature flag. */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/037.js b/app/scripts/migrations/037.js index 1d7f13810ba4..e650337d4516 100644 --- a/app/scripts/migrations/037.js +++ b/app/scripts/migrations/037.js @@ -1,7 +1,8 @@ -const version = 37 import { cloneDeep } from 'lodash' import { util } from '@metamask/controllers' +const version = 37 + /** * The purpose of this migration is to update the address book state * to the new schema with chainId as a key. @@ -9,7 +10,7 @@ import { util } from '@metamask/controllers' */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/038.js b/app/scripts/migrations/038.js index e5386f7a929d..b104fe49f668 100644 --- a/app/scripts/migrations/038.js +++ b/app/scripts/migrations/038.js @@ -1,12 +1,13 @@ -const version = 38 import { cloneDeep } from 'lodash' +const version = 38 + /** * The purpose of this migration is to assign all users to a test group for the fullScreenVsPopup a/b test */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/039.js b/app/scripts/migrations/039.js index f1f38c0a5063..d190b4f9b7ba 100644 --- a/app/scripts/migrations/039.js +++ b/app/scripts/migrations/039.js @@ -1,7 +1,8 @@ -const version = 39 import { cloneDeep } from 'lodash' import ethUtil from 'ethereumjs-util' +const version = 39 + const DAI_V1_CONTRACT_ADDRESS = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359' const DAI_V1_TOKEN_SYMBOL = 'DAI' const SAI_TOKEN_SYMBOL = 'SAI' @@ -21,7 +22,7 @@ function isOldDai (token = {}) { */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/040.js b/app/scripts/migrations/040.js index ca243e4aa940..93b0e72be79f 100644 --- a/app/scripts/migrations/040.js +++ b/app/scripts/migrations/040.js @@ -1,6 +1,7 @@ -const version = 40 import { cloneDeep } from 'lodash' +const version = 40 + /** * Site connections are now managed by the PermissionsController, and the * ProviderApprovalController is removed. This migration deletes all @@ -8,7 +9,7 @@ import { cloneDeep } from 'lodash' */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/041.js b/app/scripts/migrations/041.js index 83028ed1b84e..9e81312c33a4 100644 --- a/app/scripts/migrations/041.js +++ b/app/scripts/migrations/041.js @@ -1,12 +1,13 @@ -const version = 41 import { cloneDeep } from 'lodash' +const version = 41 + /** * PreferencesController.autoLogoutTimeLimit -> autoLockTimeLimit */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/042.js b/app/scripts/migrations/042.js index 4c1fb510a700..ed8b9f7cc46d 100644 --- a/app/scripts/migrations/042.js +++ b/app/scripts/migrations/042.js @@ -1,13 +1,14 @@ -const version = 42 import { cloneDeep } from 'lodash' +const version = 42 + /** * Initialize `connectedStatusPopoverHasBeenShown` to `false` if it hasn't yet been set, * so that existing users are introduced to the new connected status indicator */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/043.js b/app/scripts/migrations/043.js index c024b79490f2..ad2dddde5158 100644 --- a/app/scripts/migrations/043.js +++ b/app/scripts/migrations/043.js @@ -1,12 +1,13 @@ -const version = 43 import { cloneDeep } from 'lodash' +const version = 43 + /** * Remove unused 'currentAccountTab' state */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/044.js b/app/scripts/migrations/044.js index 39c9b546ff2a..00a23c012683 100644 --- a/app/scripts/migrations/044.js +++ b/app/scripts/migrations/044.js @@ -1,12 +1,13 @@ -const version = 44 import { cloneDeep } from 'lodash' +const version = 44 + /** * Remove unused 'mkrMigrationReminderTimestamp' state from the `AppStateController` */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/045.js b/app/scripts/migrations/045.js index 9ff7ded5550b..d8024a0f9d61 100644 --- a/app/scripts/migrations/045.js +++ b/app/scripts/migrations/045.js @@ -1,12 +1,13 @@ -const version = 45 import { cloneDeep } from 'lodash' +const version = 45 + /** * Replaces {@code PreferencesController.ipfsGateway} with 'dweb.link' if set */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/046.js b/app/scripts/migrations/046.js index 4f7d36db1bef..6b1ebdae0bee 100644 --- a/app/scripts/migrations/046.js +++ b/app/scripts/migrations/046.js @@ -1,12 +1,13 @@ -const version = 46 import { cloneDeep } from 'lodash' +const version = 46 + /** * Delete {@code ABTestController} state */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/047.js b/app/scripts/migrations/047.js index 255971ec3752..371bf2135a4f 100644 --- a/app/scripts/migrations/047.js +++ b/app/scripts/migrations/047.js @@ -1,12 +1,13 @@ -const version = 47 import { cloneDeep } from 'lodash' +const version = 47 + /** * Stringify the `metamaskNetworkId` property of all transactions */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/fail-tx.js b/app/scripts/migrations/fail-tx.js index c8b5f7c362ba..e6236ec4e67c 100644 --- a/app/scripts/migrations/fail-tx.js +++ b/app/scripts/migrations/fail-tx.js @@ -9,7 +9,7 @@ export default function failTxsThat (version, reason, condition) { const newState = transformState(state, condition, reason) versionedData.data = newState } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) } return Promise.resolve(versionedData) diff --git a/app/scripts/migrations/template.js b/app/scripts/migrations/template.js index c9e3b795b1b3..6427d49f4c51 100644 --- a/app/scripts/migrations/template.js +++ b/app/scripts/migrations/template.js @@ -1,6 +1,4 @@ // next version number -const version = 0 - /* description of migration and what it does @@ -9,10 +7,12 @@ description of migration and what it does import { cloneDeep } from 'lodash' +const version = 0 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index d5b025c02f93..c891ae97c770 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -105,6 +105,7 @@ export default class ExtensionPlatform { }) } catch (e) { cb(e) + // eslint-disable-next-line no-useless-return return } } @@ -210,10 +211,11 @@ export default class ExtensionPlatform { url, { 'type': 'basic', - 'title': title, + title, 'iconUrl': extension.extension.getURL('../../images/icon-64.png'), - 'message': message, - }) + message, + }, + ) } _subscribeToNotificationClicked () { diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 7a76b87788b5..a77c0d6a30e2 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -9,7 +9,6 @@ import '@formatjs/intl-relativetimeformat/polyfill' import { EventEmitter } from 'events' import PortStream from 'extension-port-stream' - import extension from 'extensionizer' import Dnode from 'dnode' @@ -151,7 +150,7 @@ function setupWeb3Connection (connectionStream) { function setupControllerConnection (connectionStream, cb) { const eventEmitter = new EventEmitter() const backgroundDnode = Dnode({ - sendUpdate: function (state) { + sendUpdate (state) { eventEmitter.emit('update', state) }, }) diff --git a/development/build/display.js b/development/build/display.js index 90ca4e7ba4f3..e5556dd091dc 100644 --- a/development/build/display.js +++ b/development/build/display.js @@ -123,9 +123,8 @@ function getSymbolNormal (value) { return SYMBOLS.ThreeQuarters } else if (rounded === 7 / 8) { return SYMBOLS.SevenEighths - } else { - return SYMBOLS.Full } + return SYMBOLS.Full } // get partial block char for value (right-adjusted) @@ -144,7 +143,6 @@ function getSymbolNormalRight (value) { return SYMBOLS.RightEighth } else if (rounded === 1) { return SYMBOLS.Space - } else { - throw new Error('getSymbolNormalRight got unexpected result') } + throw new Error('getSymbolNormalRight got unexpected result') } diff --git a/development/build/etc.js b/development/build/etc.js index 81b9a17b70b0..92af2e338ac7 100644 --- a/development/build/etc.js +++ b/development/build/etc.js @@ -9,7 +9,6 @@ const { createTask, composeParallel } = require('./task') module.exports = createEtcTasks - function createEtcTasks ({ browserPlatforms, livereload }) { const clean = createTask('clean', async function clean () { diff --git a/development/build/index.js b/development/build/index.js index a665410b265a..0a9f519f8328 100755 --- a/development/build/index.js +++ b/development/build/index.js @@ -31,7 +31,8 @@ function defineAllTasks () { const { clean, reload, zip } = createEtcTasks({ livereload, browserPlatforms }) // build for development (livereload) - createTask('dev', + createTask( + 'dev', composeSeries( clean, styleTasks.dev, @@ -45,7 +46,8 @@ function defineAllTasks () { ) // build for test development (livereload) - createTask('testDev', + createTask( + 'testDev', composeSeries( clean, styleTasks.dev, @@ -59,7 +61,8 @@ function defineAllTasks () { ) // build for prod release - createTask('prod', + createTask( + 'prod', composeSeries( clean, styleTasks.prod, @@ -73,7 +76,8 @@ function defineAllTasks () { ) // build for CI testing - createTask('test', + createTask( + 'test', composeSeries( clean, styleTasks.prod, diff --git a/development/build/manifest.js b/development/build/manifest.js index 71d335be0cf1..1ea9e5ad5a64 100644 --- a/development/build/manifest.js +++ b/development/build/manifest.js @@ -7,7 +7,6 @@ const { createTask, composeSeries } = require('./task') module.exports = createManifestTasks - const scriptsToExcludeFromBackgroundDevBuild = { 'bg-libs.js': true, } diff --git a/development/build/scripts.js b/development/build/scripts.js index 4b06af86eb23..c6e3e417355d 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -22,7 +22,6 @@ const { createTask, composeParallel, composeSeries, runInChildProcess } = requir module.exports = createScriptTasks - const dependencies = Object.keys((packageJSON && packageJSON.dependencies) || {}) const materialUIDependencies = ['@material-ui/core'] const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/u)) @@ -72,7 +71,6 @@ function createScriptTasks ({ browserPlatforms, livereload }) { return { prod, dev, testDev, test } - function createTasksForBuildJsDeps ({ key, filename }) { return createTask(`scripts:deps:${key}`, bundleTask({ label: filename, @@ -83,7 +81,6 @@ function createScriptTasks ({ browserPlatforms, livereload }) { })) } - function createTasksForBuildJsExtension ({ taskPrefix, devMode, testing }) { const standardBundles = [ 'background', @@ -93,14 +90,12 @@ function createScriptTasks ({ browserPlatforms, livereload }) { const standardSubtasks = standardBundles.map((filename) => { return createTask(`${taskPrefix}:${filename}`, - createBundleTaskForBuildJsExtensionNormal({ filename, devMode, testing }), - ) + createBundleTaskForBuildJsExtensionNormal({ filename, devMode, testing })) }) // inpage must be built before contentscript // because inpage bundle result is included inside contentscript const contentscriptSubtask = createTask(`${taskPrefix}:contentscript`, - createTaskForBuildJsExtensionContentscript({ devMode, testing }), - ) + createTaskForBuildJsExtensionContentscript({ devMode, testing })) // task for initiating livereload const initiateLiveReload = async () => { @@ -159,7 +154,6 @@ function createScriptTasks ({ browserPlatforms, livereload }) { ) } - function bundleTask (opts) { let bundler @@ -203,7 +197,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) { buildStream = buildStream .pipe(terser({ mangle: { - reserved: [ 'MetamaskInpageProvider' ], + reserved: ['MetamaskInpageProvider'], }, sourceMap: { content: true, @@ -287,9 +281,9 @@ function createScriptTasks ({ browserPlatforms, livereload }) { if (!opts.buildLib) { if (opts.devMode && opts.filename === 'ui.js') { - browserifyOpts['entries'] = ['./development/require-react-devtools.js', opts.filepath] + browserifyOpts.entries = ['./development/require-react-devtools.js', opts.filepath] } else { - browserifyOpts['entries'] = [opts.filepath] + browserifyOpts.entries = [opts.filepath] } } @@ -348,10 +342,8 @@ function createScriptTasks ({ browserPlatforms, livereload }) { return bundler } - } - function beep () { process.stdout.write('\x07') } @@ -364,13 +356,12 @@ function getEnvironment ({ devMode, test }) { return 'testing' } else if (process.env.CIRCLE_BRANCH === 'master') { return 'production' - } else if (/^Version-v(\d+)[.](\d+)[.](\d+)/u.test(process.env.CIRCLE_BRANCH)) { + } else if ((/^Version-v(\d+)[.](\d+)[.](\d+)/u).test(process.env.CIRCLE_BRANCH)) { return 'release-candidate' } else if (process.env.CIRCLE_BRANCH === 'develop') { return 'staging' } else if (process.env.CIRCLE_PULL_REQUEST) { return 'pull-request' - } else { - return 'other' } + return 'other' } diff --git a/development/build/static.js b/development/build/static.js index f32cd5c39027..3d4c7439468a 100644 --- a/development/build/static.js +++ b/development/build/static.js @@ -9,7 +9,6 @@ const { createTask, composeSeries } = require('./task') module.exports = createStaticAssetTasks - const copyTargets = [ { src: `./app/_locales/`, diff --git a/development/build/styles.js b/development/build/styles.js index f57954c94600..d6f3a7855698 100644 --- a/development/build/styles.js +++ b/development/build/styles.js @@ -11,11 +11,9 @@ const rename = require('gulp-rename') const pump = pify(require('pump')) const { createTask } = require('./task') - // scss compilation and autoprefixing tasks module.exports = createStyleTasks - function createStyleTasks ({ livereload }) { const prod = createTask('styles:prod', createScssBuildTask({ @@ -44,7 +42,6 @@ function createStyleTasks ({ livereload }) { return { prod, dev, lint } - function createScssBuildTask ({ src, dest, devMode, pattern }) { return async function () { if (devMode) { @@ -75,5 +72,4 @@ function createStyleTasks ({ livereload }) { } } - } diff --git a/development/build/task.js b/development/build/task.js index 4a0a9d437a3e..879ab1c97c2b 100644 --- a/development/build/task.js +++ b/development/build/task.js @@ -8,7 +8,6 @@ module.exports = { detectAndRunEntryTask, tasks, taskEvents, createTask, runTask const { setupTaskDisplay } = require('./display') - function detectAndRunEntryTask () { // get requested task name and execute const taskName = process.argv[2] diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index a19acecc6ebb..51d9617a27f8 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -57,7 +57,7 @@ async function start () { `dep viz: ${depVizLink}`, `all artifacts`, ] - const hiddenContent = `
    ` + contentRows.map((row) => `
  • ${row}
  • `).join('\n') + `
` + const hiddenContent = `
    ${contentRows.map((row) => `
  • ${row}
  • `).join('\n')}
` const exposedContent = `Builds ready [${SHORT_SHA1}]` const artifactsBody = `
${exposedContent}${hiddenContent}
` diff --git a/development/mock-3box.js b/development/mock-3box.js index 37ff02c7b25a..e4260c6103d9 100644 --- a/development/mock-3box.js +++ b/development/mock-3box.js @@ -3,7 +3,7 @@ function delay (time) { } async function loadFromMock3Box (key) { - const res = await window.fetch('http://localhost:8889?key=' + key) + const res = await window.fetch(`http://localhost:8889?key=${key}`) const text = await res.text() return text.length ? JSON.parse(text) : null } diff --git a/development/sourcemap-validator.js b/development/sourcemap-validator.js index 0babb1d56d8d..cb5f6f6c895c 100644 --- a/development/sourcemap-validator.js +++ b/development/sourcemap-validator.js @@ -18,7 +18,6 @@ start().catch((error) => { process.exit(1) }) - async function start () { const targetFiles = [ `background.js`, diff --git a/development/static-server.js b/development/static-server.js index 368c186e92a6..a209088784e2 100644 --- a/development/static-server.js +++ b/development/static-server.js @@ -61,7 +61,7 @@ const main = async () => { } while (args.length) { - if (/^(--port|-p)$/u.test(args[0])) { + if ((/^(--port|-p)$/u).test(args[0])) { if (args[1] === undefined) { throw new Error('Missing port argument') } diff --git a/development/verify-locale-strings.js b/development/verify-locale-strings.js index f15344d4d50c..1d4c6e3a7162 100644 --- a/development/verify-locale-strings.js +++ b/development/verify-locale-strings.js @@ -104,7 +104,7 @@ async function getLocale (code) { async function writeLocale (code, locale) { try { const localeFilePath = getLocalePath(code) - return writeFile(localeFilePath, JSON.stringify(locale, null, 2) + '\n', 'utf8') + return writeFile(localeFilePath, `${JSON.stringify(locale, null, 2)}\n`, 'utf8') } catch (e) { if (e.code === 'ENOENT') { log.error('Locale file not found') @@ -150,7 +150,7 @@ async function verifyLocale (code) { if (extraItems.length > 0) { if (fix) { - const newLocale = Object.assign({}, targetLocale) + const newLocale = { ...targetLocale } for (const item of extraItems) { delete newLocale[item] } @@ -215,7 +215,7 @@ async function verifyEnglishLocale () { } if (unusedMessages.length > 0 && fix) { - const newLocale = Object.assign({}, englishLocale) + const newLocale = { ...englishLocale } for (const key of unusedMessages) { delete newLocale[key] } @@ -244,7 +244,6 @@ async function * getFileContents (filenames) { } } - function compareLocalesForMissingItems ({ base, subject }) { return Object.keys(base).filter((key) => !subject[key]) } diff --git a/package.json b/package.json index 35e2eb4f74b0..f13bf1902df9 100644 --- a/package.json +++ b/package.json @@ -179,7 +179,7 @@ "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", "@babel/register": "^7.5.5", - "@metamask/eslint-config": "^1.1.0", + "@metamask/eslint-config": "^3.0.0", "@metamask/forwarder": "^1.1.0", "@metamask/test-dapp": "^3.1.0", "@sentry/cli": "^1.49.0", diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index d418f38b7632..d8b79a9eba2b 100644 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -118,7 +118,7 @@ async function main () { let existingParentDirectory while (args.length) { - if (/^(--pages|-p)$/u.test(args[0])) { + if ((/^(--pages|-p)$/u).test(args[0])) { if (args[1] === undefined) { throw new Error('Missing pages argument') } @@ -129,7 +129,7 @@ async function main () { } } args.splice(0, 2) - } else if (/^(--samples|-s)$/u.test(args[0])) { + } else if ((/^(--samples|-s)$/u).test(args[0])) { if (args[1] === undefined) { throw new Error('Missing number of samples') } @@ -138,7 +138,7 @@ async function main () { throw new Error(`Invalid 'samples' argument given: '${args[1]}'`) } args.splice(0, 2) - } else if (/^(--out|-o)$/u.test(args[0])) { + } else if ((/^(--out|-o)$/u).test(args[0])) { if (args[1] === undefined) { throw new Error('Missing output filename') } diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index d471f41f39c9..d9b93bcada60 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -223,7 +223,7 @@ describe('Using MetaMask with an existing account', function () { const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) assert.equal(txValues.length, 1) - assert.ok(/-1\s*ETH/u.test(await txValues[0].getText())) + assert.ok((/-1\s*ETH/u).test(await txValues[0].getText())) }) }) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index c1c7a953d94c..f8c21d1314e7 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -754,7 +754,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/u), 10000) const tokenAmount = await balance.getText() - assert.ok(/^87.*\s*ETH.*$/u.test(tokenAmount)) + assert.ok((/^87.*\s*ETH.*$/u).test(tokenAmount)) await driver.delay(regularDelayMs) }) }) @@ -832,7 +832,7 @@ describe('MetaMask', function () { const balance = await driver.findElement(By.css('.wallet-overview .token-overview__primary-balance')) await driver.wait(until.elementTextMatches(balance, /^10\s*TST\s*$/u)) const tokenAmount = await balance.getText() - assert.ok(/^10\s*TST\s*$/u.test(tokenAmount)) + assert.ok((/^10\s*TST\s*$/u).test(tokenAmount)) await driver.delay(regularDelayMs) }) }) diff --git a/test/e2e/mock-3box/server.js b/test/e2e/mock-3box/server.js index c4fe9d9c79c6..1ac8a758c075 100644 --- a/test/e2e/mock-3box/server.js +++ b/test/e2e/mock-3box/server.js @@ -33,6 +33,6 @@ const server = http.createServer(requestHandler) server.listen(port, (err) => { if (err) { console.log('mock 3box server error: ', err) - return + } }) diff --git a/test/e2e/send-edit.spec.js b/test/e2e/send-edit.spec.js index 4f7e0ae54213..aa0fc6645455 100644 --- a/test/e2e/send-edit.spec.js +++ b/test/e2e/send-edit.spec.js @@ -205,7 +205,7 @@ describe('Using MetaMask with an existing account', function () { const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) assert.equal(txValues.length, 1) - assert.ok(/-2.2\s*ETH/u.test(await txValues[0].getText())) + assert.ok((/-2.2\s*ETH/u).test(await txValues[0].getText())) }) }) }) diff --git a/test/e2e/signature-request.spec.js b/test/e2e/signature-request.spec.js index 03d7fcfe6179..9e83cc25ea6c 100644 --- a/test/e2e/signature-request.spec.js +++ b/test/e2e/signature-request.spec.js @@ -108,7 +108,7 @@ describe('MetaMask', function () { assert.equal(await title.getText(), 'Signature Request') assert.equal(await name.getText(), 'Ether Mail') assert.equal(await origin.getText(), 'http://127.0.0.1:8080') - assert.equal(await address.getText(), publicAddress.slice(0, 8) + '...' + publicAddress.slice(publicAddress.length - 8)) + assert.equal(await address.getText(), `${publicAddress.slice(0, 8)}...${publicAddress.slice(publicAddress.length - 8)}`) }) it('signs the transaction', async function () { diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 2d855685060b..dcd516e415b1 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -3,6 +3,7 @@ const { strict: assert } = require('assert') const { until, error: webdriverError } = require('selenium-webdriver') class Driver { + /** * @param {!ThenableWebDriver} driver - A {@code WebDriver} instance * @param {string} browser - The type of browser this driver is controlling @@ -61,8 +62,7 @@ class Driver { this.driver.wait(until.elementIsEnabled(element), this.timeout), ) return acc - }, []), - ) + }, [])) return elements } @@ -147,7 +147,7 @@ class Driver { } } - throw new Error('No window with title: ' + title) + throw new Error(`No window with title: ${title}`) } /** diff --git a/test/e2e/webdriver/firefox.js b/test/e2e/webdriver/firefox.js index aff7227a441b..f5c8426aef13 100644 --- a/test/e2e/webdriver/firefox.js +++ b/test/e2e/webdriver/firefox.js @@ -20,6 +20,7 @@ const GeckoDriverCommand = { * A wrapper around a {@code WebDriver} instance exposing Firefox-specific functionality */ class FirefoxDriver { + /** * Builds a {@link FirefoxDriver} instance * @param {{extensionPath: string}} options - the options for the build diff --git a/test/helper.js b/test/helper.js index 50ec1f2d814e..d1b79335babf 100644 --- a/test/helper.js +++ b/test/helper.js @@ -5,7 +5,6 @@ import Adapter from 'enzyme-adapter-react-16' import log from 'loglevel' import { JSDOM } from 'jsdom' - nock.disableNetConnect() nock.enableNetConnect('localhost') diff --git a/test/lib/createTxMeta.js b/test/lib/createTxMeta.js index 78f38badede7..4dde18f623e1 100644 --- a/test/lib/createTxMeta.js +++ b/test/lib/createTxMeta.js @@ -1,10 +1,11 @@ import { snapshotFromTxMeta } from '../../app/scripts/controllers/transactions/lib/tx-state-history-helpers' export default function createTxMeta (partialMeta) { - const txMeta = Object.assign({ + const txMeta = { status: 'unapproved', txParams: {}, - }, partialMeta) + ...partialMeta, + } // initialize history txMeta.history = [] // capture initial snapshot of txMeta for history diff --git a/test/lib/render-helpers.js b/test/lib/render-helpers.js index 2224c2165051..c0ac849eab00 100644 --- a/test/lib/render-helpers.js +++ b/test/lib/render-helpers.js @@ -17,7 +17,7 @@ export function mountWithRouter (component, store = {}, pathname = '/') { history: new MemoryRouter().history, route: { location: { - pathname: pathname, + pathname, }, match: {}, }, diff --git a/test/unit/app/account-import-strategies.spec.js b/test/unit/app/account-import-strategies.spec.js index fa43826d6ffe..3c6b6fbefe79 100644 --- a/test/unit/app/account-import-strategies.spec.js +++ b/test/unit/app/account-import-strategies.spec.js @@ -1,6 +1,6 @@ import assert from 'assert' import ethUtil from 'ethereumjs-util' -import accountImporter from '../../../app/scripts/account-import-strategies/index' +import accountImporter from '../../../app/scripts/account-import-strategies' describe('Account Import Strategies', function () { const privkey = '0x4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553' @@ -8,19 +8,19 @@ describe('Account Import Strategies', function () { describe('private key import', function () { it('imports a private key and strips 0x prefix', async function () { - const importPrivKey = await accountImporter.importAccount('Private Key', [ privkey ]) + const importPrivKey = await accountImporter.importAccount('Private Key', [privkey]) assert.equal(importPrivKey, ethUtil.stripHexPrefix(privkey)) }) it('throws an error for empty string private key', async function () { await assert.rejects(async () => { - await accountImporter.importAccount('Private Key', [ '' ]) + await accountImporter.importAccount('Private Key', ['']) }, Error, 'no empty strings') }) it('throws an error for undefined string private key', async function () { await assert.rejects(async () => { - await accountImporter.importAccount('Private Key', [ undefined ]) + await accountImporter.importAccount('Private Key', [undefined]) }) await assert.rejects(async () => { @@ -30,7 +30,7 @@ describe('Account Import Strategies', function () { it('throws an error for invalid private key', async function () { await assert.rejects(async () => { - await accountImporter.importAccount('Private Key', [ 'popcorn' ]) + await accountImporter.importAccount('Private Key', ['popcorn']) }) }) }) @@ -40,7 +40,7 @@ describe('Account Import Strategies', function () { const wrongPassword = 'password2' try { - await accountImporter.importAccount('JSON File', [ json, wrongPassword]) + await accountImporter.importAccount('JSON File', [json, wrongPassword]) } catch (error) { assert.equal(error.message, 'Key derivation failed - possibly wrong passphrase') } @@ -48,7 +48,7 @@ describe('Account Import Strategies', function () { it('imports json string and password to return a private key', async function () { const fileContentsPassword = 'password1' - const importJson = await accountImporter.importAccount('JSON File', [ json, fileContentsPassword]) + const importJson = await accountImporter.importAccount('JSON File', [json, fileContentsPassword]) assert.equal(importJson, '0x5733876abe94146069ce8bcbabbde2677f2e35fa33e875e92041ed2ac87e5bc7') }) }) diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js index 83ca9eb01beb..0b65e92581ed 100644 --- a/test/unit/app/controllers/detect-tokens-test.js +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -22,7 +22,6 @@ describe('DetectTokensController', function () { beforeEach(async function () { - nock('https://api.infura.io') .get(/.*/u) .reply(200) diff --git a/test/unit/app/controllers/incoming-transactions-test.js b/test/unit/app/controllers/incoming-transactions-test.js index 7947a710284b..727c394fa19d 100644 --- a/test/unit/app/controllers/incoming-transactions-test.js +++ b/test/unit/app/controllers/incoming-transactions-test.js @@ -2,12 +2,12 @@ import assert from 'assert' import sinon from 'sinon' import proxyquire from 'proxyquire' +import { ROPSTEN, RINKEBY, KOVAN, GOERLI, MAINNET } from '../../../../app/scripts/controllers/network/enums' + const IncomingTransactionsController = proxyquire('../../../../app/scripts/controllers/incoming-transactions', { '../lib/random-id': { default: () => 54321 }, }).default -import { ROPSTEN, RINKEBY, KOVAN, GOERLI, MAINNET } from '../../../../app/scripts/controllers/network/enums' - describe('IncomingTransactionsController', function () { const EMPTY_INIT_STATE = { incomingTransactions: {}, diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index 09000890f276..3bd1b3689f45 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -104,11 +104,11 @@ describe('MetaMaskController', function () { showUnapprovedTx: noop, showUnconfirmedMessage: noop, encryptor: { - encrypt: function (_, object) { + encrypt (_, object) { this.object = object return Promise.resolve('mock-encrypted') }, - decrypt: function () { + decrypt () { return Promise.resolve(this.object) }, }, @@ -146,7 +146,7 @@ describe('MetaMaskController', function () { beforeEach(async function () { const password = 'a-fake-password' await metamaskController.createNewVaultAndRestore(password, TEST_SEED) - await metamaskController.importAccountWithStrategy('Private Key', [ importPrivkey ]) + await metamaskController.importAccountWithStrategy('Private Key', [importPrivkey]) }) it('adds private key to keyrings in KeyringController', async function () { @@ -306,9 +306,9 @@ describe('MetaMaskController', function () { it('should return the balance known by accountTracker', async function () { const accounts = {} const balance = '0x14ced5122ce0a000' - accounts[TEST_ADDRESS] = { balance: balance } + accounts[TEST_ADDRESS] = { balance } - metamaskController.accountTracker.store.putState({ accounts: accounts }) + metamaskController.accountTracker.store.putState({ accounts }) const gotten = await metamaskController.getBalance(TEST_ADDRESS) @@ -323,7 +323,7 @@ describe('MetaMaskController', function () { callback(undefined, balance) }) - metamaskController.accountTracker.store.putState({ accounts: accounts }) + metamaskController.accountTracker.store.putState({ accounts }) const gotten = await metamaskController.getBalance(TEST_ADDRESS, ethQuery) @@ -367,7 +367,7 @@ describe('MetaMaskController', function () { address = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc' identities = { '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { - 'address': address, + address, 'name': 'Account 1', }, '0xc42edfcc21ed14dda456aa0756c153f7985d8813': { @@ -503,7 +503,6 @@ describe('MetaMaskController', function () { assert.equal(keyrings[0].unlockedAccount, accountToUnlock) }) - it('should call keyringController.addNewAccount', async function () { assert(metamaskController.keyringController.addNewAccount.calledOnce) }) @@ -524,7 +523,6 @@ describe('MetaMaskController', function () { assert(metamaskController.preferencesController.setAccountLabel.calledOnce) }) - }) describe('#setCustomRpc', function () { @@ -684,7 +682,7 @@ describe('MetaMaskController', function () { msgParams = { 'from': address, - 'data': data, + data, } const promise = metamaskController.newUnsignedMessage(msgParams) @@ -744,7 +742,7 @@ describe('MetaMaskController', function () { msgParams = { 'from': address, - 'data': data, + data, } const promise = metamaskController.newUnsignedPersonalMessage(msgParams) @@ -760,7 +758,7 @@ describe('MetaMaskController', function () { it('errors with no from in msgParams', async function () { try { await metamaskController.newUnsignedPersonalMessage({ - 'data': data, + data, }) assert.fail('should have thrown') } catch (error) { diff --git a/test/unit/app/controllers/permissions/helpers.js b/test/unit/app/controllers/permissions/helpers.js index 0378dc08910a..e920b851db02 100644 --- a/test/unit/app/controllers/permissions/helpers.js +++ b/test/unit/app/controllers/permissions/helpers.js @@ -26,6 +26,7 @@ export function grantPermissions (permController, origin, permissions) { * @return {Function} A convenient wrapper for the requestUserApproval function. */ export function getRequestUserApprovalHelper (permController) { + /** * Returns a request object that can be passed to requestUserApproval. * diff --git a/test/unit/app/controllers/permissions/mocks.js b/test/unit/app/controllers/permissions/mocks.js index 54f47e5d808e..578b39911de7 100644 --- a/test/unit/app/controllers/permissions/mocks.js +++ b/test/unit/app/controllers/permissions/mocks.js @@ -33,7 +33,7 @@ const keyringAccounts = deepFreeze([ '0xcc74c7a59194e5d9268476955650d1e285be703c', ]) -const getKeyringAccounts = async () => [ ...keyringAccounts ] +const getKeyringAccounts = async () => [...keyringAccounts] const getIdentities = () => { return keyringAccounts.reduce( @@ -261,7 +261,8 @@ const PERMS = { return { eth_accounts: { caveats: CAVEATS.eth_accounts(accounts), - } } + }, + } }, /** @@ -574,7 +575,7 @@ export const getters = deepFreeze({ return { origin, method: 'wallet_requestPermissions', - params: [ PERMS.requests[permissionName]() ], + params: [PERMS.requests[permissionName]()], } }, @@ -590,7 +591,7 @@ export const getters = deepFreeze({ return { origin, method: 'wallet_requestPermissions', - params: [ permissions ], + params: [permissions], } }, diff --git a/test/unit/app/controllers/permissions/permissions-controller-test.js b/test/unit/app/controllers/permissions/permissions-controller-test.js index f8aa6feaab51..f51ed0800c4c 100644 --- a/test/unit/app/controllers/permissions/permissions-controller-test.js +++ b/test/unit/app/controllers/permissions/permissions-controller-test.js @@ -170,7 +170,6 @@ describe('permissions controller', function () { let bAccounts = await permController.getAccounts(DOMAINS.b.origin) let cAccounts = await permController.getAccounts(DOMAINS.c.origin) - assert.deepEqual( aAccounts, [ACCOUNTS.a.primary], 'first origin should have correct accounts', @@ -189,7 +188,7 @@ describe('permissions controller', function () { Object.keys(notifications).forEach((origin) => { assert.deepEqual( notifications[origin], - [ NOTIFICATIONS.removedAccounts() ], + [NOTIFICATIONS.removedAccounts()], 'origin should have single wallet_accountsChanged:[] notification', ) }) @@ -447,12 +446,12 @@ describe('permissions controller', function () { ) await assert.doesNotThrow( - () => permController.validatePermittedAccounts([ keyringAccounts[0] ]), + () => permController.validatePermittedAccounts([keyringAccounts[0]]), 'should not throw on single keyring account', ) await assert.doesNotThrow( - () => permController.validatePermittedAccounts([ keyringAccounts[1] ]), + () => permController.validatePermittedAccounts([keyringAccounts[1]]), 'should not throw on single keyring account', ) }) @@ -655,7 +654,6 @@ describe('permissions controller', function () { }) }) - describe('removeAllAccountPermissions', function () { let permController, notifications @@ -1284,7 +1282,7 @@ describe('permissions controller', function () { assert.deepEqual( notifications[DOMAINS.a.origin], - [ NOTIFICATIONS.newAccounts(ACCOUNTS.a.permitted) ], + [NOTIFICATIONS.newAccounts(ACCOUNTS.a.permitted)], 'origin should have correct notification', ) }) diff --git a/test/unit/app/controllers/permissions/permissions-log-controller-test.js b/test/unit/app/controllers/permissions/permissions-log-controller-test.js index d6e3482c69eb..6f9fc104b91c 100644 --- a/test/unit/app/controllers/permissions/permissions-log-controller-test.js +++ b/test/unit/app/controllers/permissions/permissions-log-controller-test.js @@ -310,7 +310,7 @@ describe('permissions log', function () { ) // store the id of the current second entry - const nextFirstId = log[1]['id'] + const nextFirstId = log[1].id // add one more entry to log, putting it over the limit lastId = nanoid() @@ -356,7 +356,7 @@ describe('permissions log', function () { const req = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.test_method, ) - const res = { result: [ PERMS.granted.test_method() ] } + const res = { result: [PERMS.granted.test_method()] } // noop => no response logMiddleware({ ...req }, { ...res }, noop) @@ -384,7 +384,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.test_method, ) delete req.params - const res = { result: [ PERMS.granted.test_method() ] } + const res = { result: [PERMS.granted.test_method()] } // no params => no response logMiddleware({ ...req }, { ...res }) @@ -400,7 +400,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.eth_accounts, ) const res = { - result: [ PERMS.granted.eth_accounts(ACCOUNTS.a.permitted) ], + result: [PERMS.granted.eth_accounts(ACCOUNTS.a.permitted)], } logMiddleware({ ...req }, { ...res }) @@ -419,7 +419,7 @@ describe('permissions log', function () { clock.tick(1) - res.result = [ PERMS.granted.eth_accounts([ ACCOUNTS.a.permitted[0] ]) ] + res.result = [PERMS.granted.eth_accounts([ACCOUNTS.a.permitted[0]])] logMiddleware({ ...req }, { ...res }) @@ -438,7 +438,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.eth_accounts, ) const res = { - result: [ PERMS.granted.eth_accounts(ACCOUNTS.a.permitted) ], + result: [PERMS.granted.eth_accounts(ACCOUNTS.a.permitted)], } delete res.result[0].caveats @@ -458,7 +458,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.eth_accounts, ) const res = { - result: [ PERMS.granted.eth_accounts(ACCOUNTS.a.permitted) ], + result: [PERMS.granted.eth_accounts(ACCOUNTS.a.permitted)], } res.result[0].caveats.push({ foo: 'bar' }) @@ -558,7 +558,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.test_method, ), res: { - result: [ PERMS.granted.test_method() ], + result: [PERMS.granted.test_method()], }, }) @@ -568,7 +568,7 @@ describe('permissions log', function () { DOMAINS.b.origin, PERM_NAMES.eth_accounts, ), res: { - result: [ PERMS.granted.eth_accounts(ACCOUNTS.b.permitted) ], + result: [PERMS.granted.eth_accounts(ACCOUNTS.b.permitted)], }, }) @@ -616,7 +616,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.test_method, ), res: { - result: [ PERMS.granted.test_method() ], + result: [PERMS.granted.test_method()], }, }) diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index ca5001e36908..3484dd210e7f 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -119,7 +119,6 @@ describe('preferences controller', function () { address: '0xda22le', }) - preferencesController.setAccountLabel('0xda22le', 'Dazzle') assert.deepEqual(preferencesController.store.getState().identities['0xda22le'], { name: 'Dazzle', @@ -130,7 +129,7 @@ describe('preferences controller', function () { describe('getTokens', function () { it('should return an empty list initially', async function () { - preferencesController.setAddresses([ '0x7e57e2' ]) + preferencesController.setAddresses(['0x7e57e2']) await preferencesController.setSelectedAddress('0x7e57e2') const tokens = preferencesController.getTokens() @@ -144,7 +143,7 @@ describe('preferences controller', function () { const symbol = 'ABBR' const decimals = 5 - preferencesController.setAddresses([ '0x7e57e2' ]) + preferencesController.setAddresses(['0x7e57e2']) await preferencesController.setSelectedAddress('0x7e57e2') await preferencesController.addToken(address, symbol, decimals) @@ -162,7 +161,7 @@ describe('preferences controller', function () { const symbol = 'ABBR' const decimals = 5 - preferencesController.setAddresses([ '0x7e57e2' ]) + preferencesController.setAddresses(['0x7e57e2']) await preferencesController.setSelectedAddress('0x7e57e2') await preferencesController.addToken(address, symbol, decimals) @@ -241,7 +240,7 @@ describe('preferences controller', function () { describe('removeToken', function () { it('should remove the only token from its state', async function () { - preferencesController.setAddresses([ '0x7e57e2' ]) + preferencesController.setAddresses(['0x7e57e2']) await preferencesController.setSelectedAddress('0x7e57e2') await preferencesController.addToken('0xa', 'A', 5) await preferencesController.removeToken('0xa') @@ -251,7 +250,7 @@ describe('preferences controller', function () { }) it('should remove a token from its state', async function () { - preferencesController.setAddresses([ '0x7e57e2' ]) + preferencesController.setAddresses(['0x7e57e2']) await preferencesController.setSelectedAddress('0x7e57e2') await preferencesController.addToken('0xa', 'A', 4) await preferencesController.addToken('0xb', 'B', 5) diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index 01e874ff1aea..c9b5364c7ea6 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -37,7 +37,7 @@ describe('Transaction Controller', function () { blockTrackerStub.getLatestBlock = noop txController = new TransactionController({ provider, - getGasPrice: function () { + getGasPrice () { return '0xee6b2800' }, networkStore: new ObservableStore(currentNetworkId), @@ -108,7 +108,6 @@ describe('Transaction Controller', function () { }) }) - describe('#newUnapprovedTransaction', function () { let stub, txMeta, txParams beforeEach(function () { @@ -387,7 +386,7 @@ describe('Transaction Controller', function () { { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, ]) - expectedTxParams = Object.assign({}, txParams, { gasPrice: '0xb' }) + expectedTxParams = { ...txParams, gasPrice: '0xb' } }) afterEach(function () { @@ -453,7 +452,7 @@ describe('Transaction Controller', function () { }) it('should ignore the error "Transaction Failed: known transaction" and be as usual', async function () { - providerResultStub['eth_sendRawTransaction'] = async (_, __, ___, end) => { + providerResultStub.eth_sendRawTransaction = async (_, __, ___, end) => { end('Transaction Failed: known transaction') } const rawTx = '0xf86204831e848082520894f231d46dd78806e1dd93442cf33c7671f853874880802ca05f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57a00259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a' @@ -547,7 +546,7 @@ describe('Transaction Controller', function () { _blockTrackerStub.getLatestBlock = noop const _txController = new TransactionController({ provider: _provider, - getGasPrice: function () { + getGasPrice () { return '0xee6b2800' }, networkStore: new ObservableStore(currentNetworkId), @@ -579,7 +578,7 @@ describe('Transaction Controller', function () { _blockTrackerStub.getLatestBlock = noop const _txController = new TransactionController({ provider: _provider, - getGasPrice: function () { + getGasPrice () { return '0xee6b2800' }, networkStore: new ObservableStore(currentNetworkId), diff --git a/test/unit/app/controllers/transactions/tx-state-manager-test.js b/test/unit/app/controllers/transactions/tx-state-manager-test.js index 3e1819c410d4..915e36362b80 100644 --- a/test/unit/app/controllers/transactions/tx-state-manager-test.js +++ b/test/unit/app/controllers/transactions/tx-state-manager-test.js @@ -587,13 +587,13 @@ describe('TransactionStateManager', function () { describe('#_removeTx', function () { it('should remove the transaction from the storage', function () { - txStateManager._saveTxList([ { id: 1 } ]) + txStateManager._saveTxList([{ id: 1 }]) txStateManager._removeTx(1) assert.ok(!txStateManager.getFullTxList().length, 'txList should be empty') }) it('should only remove the transaction with ID 1 from the storage', function () { - txStateManager._saveTxList([ { id: 1 }, { id: 2 } ]) + txStateManager._saveTxList([{ id: 1 }, { id: 2 }]) txStateManager._removeTx(1) assert.equal(txStateManager.getFullTxList()[0].id, 2, 'txList should have a id of 2') }) diff --git a/test/unit/app/controllers/transactions/tx-utils-test.js b/test/unit/app/controllers/transactions/tx-utils-test.js index 461a49d51b26..6923d53d53fa 100644 --- a/test/unit/app/controllers/transactions/tx-utils-test.js +++ b/test/unit/app/controllers/transactions/tx-utils-test.js @@ -70,7 +70,6 @@ describe('txUtils', function () { }) }) - describe('#validateFrom', function () { it('should error when from is not a hex string', function () { diff --git a/test/unit/app/nodeify-test.js b/test/unit/app/nodeify-test.js index c8d1c46d90f7..f6e9a320752d 100644 --- a/test/unit/app/nodeify-test.js +++ b/test/unit/app/nodeify-test.js @@ -4,7 +4,7 @@ import nodeify from '../../../app/scripts/lib/nodeify' describe('nodeify', function () { const obj = { foo: 'bar', - promiseFunc: function (a) { + promiseFunc (a) { const solution = this.foo + a return Promise.resolve(solution) }, diff --git a/test/unit/app/typed-message-manager.spec.js b/test/unit/app/typed-message-manager.spec.js index 65ba33fbd7af..5ab7258ad2bf 100644 --- a/test/unit/app/typed-message-manager.spec.js +++ b/test/unit/app/typed-message-manager.spec.js @@ -1,6 +1,6 @@ import assert from 'assert' import sinon from 'sinon' -import NetworkController from '../../../app/scripts/controllers/network/index' +import NetworkController from '../../../app/scripts/controllers/network' import TypedMessageManager from '../../../app/scripts/lib/typed-message-manager' describe('Typed Message Manager', function () { diff --git a/test/unit/migrations/023-test.js b/test/unit/migrations/023-test.js index 362b4dbe2e91..49f40b033baf 100644 --- a/test/unit/migrations/023-test.js +++ b/test/unit/migrations/023-test.js @@ -56,7 +56,6 @@ while (transactions20.length < 20) { transactions20.push({ status }) } - storage.data.TransactionController.transactions = transactions describe('storage is migrated successfully and the proper transactions are remove from state', function () { diff --git a/test/unit/migrations/024-test.js b/test/unit/migrations/024-test.js index 1aa050b73a2f..446f85f0783c 100644 --- a/test/unit/migrations/024-test.js +++ b/test/unit/migrations/024-test.js @@ -18,13 +18,11 @@ const storage = { const transactions = [] - while (transactions.length <= 10) { transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: 'unapproved' }) transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: 'confirmed' }) } - storage.data.TransactionController.transactions = transactions describe('storage is migrated successfully and the txParams.from are lowercase', function () { diff --git a/test/unit/migrations/025-test.js b/test/unit/migrations/025-test.js index 6224eef5af69..2cd3381cad0f 100644 --- a/test/unit/migrations/025-test.js +++ b/test/unit/migrations/025-test.js @@ -19,13 +19,11 @@ const storage = { const transactions = [] - while (transactions.length <= 10) { transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675', random: 'stuff', chainId: 2 }, status: 'unapproved' }) transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: 'confirmed' }) } - storage.data.TransactionController.transactions = transactions describe('storage is migrated successfully and the txParams.from are lowercase', function () { diff --git a/test/unit/migrations/027-test.js b/test/unit/migrations/027-test.js index 126a3b6207da..959f30374348 100644 --- a/test/unit/migrations/027-test.js +++ b/test/unit/migrations/027-test.js @@ -14,14 +14,12 @@ const oldStorage = { const transactions = [] - while (transactions.length < 9) { transactions.push({ status: 'rejected' }) transactions.push({ status: 'unapproved' }) transactions.push({ status: 'approved' }) } - oldStorage.data.TransactionController.transactions = transactions describe('migration #27', function () { diff --git a/test/unit/migrations/028-test.js b/test/unit/migrations/028-test.js index dd58b8a429d4..b352f0a29562 100644 --- a/test/unit/migrations/028-test.js +++ b/test/unit/migrations/028-test.js @@ -24,11 +24,11 @@ describe('migration #28', function () { const testTokens = [{ address: '0xa', symbol: 'A', decimals: 4 }, { address: '0xb', symbol: 'B', decimals: 4 }] assert.equal(newTokens.length, 0, 'tokens is expected to have the length of 0') - assert.equal(newAccountTokens['0x6d14']['mainnet'].length, 2, 'tokens for address is expected to have the length of 2') - assert.equal(newAccountTokens['0x3695']['mainnet'].length, 2, 'tokens for address is expected to have the length of 2') + assert.equal(newAccountTokens['0x6d14'].mainnet.length, 2, 'tokens for address is expected to have the length of 2') + assert.equal(newAccountTokens['0x3695'].mainnet.length, 2, 'tokens for address is expected to have the length of 2') assert.equal(Object.keys(newAccountTokens).length, 2, 'account tokens should be created for all identities') - assert.deepEqual(newAccountTokens['0x6d14']['mainnet'], testTokens, 'tokens for address should be the same than before') - assert.deepEqual(newAccountTokens['0x3695']['mainnet'], testTokens, 'tokens for address should be the same than before') + assert.deepEqual(newAccountTokens['0x6d14'].mainnet, testTokens, 'tokens for address should be the same than before') + assert.deepEqual(newAccountTokens['0x3695'].mainnet, testTokens, 'tokens for address should be the same than before') done() }) .catch(done) diff --git a/test/unit/migrations/029-test.js b/test/unit/migrations/029-test.js index b47bd1b6c78e..ccde6b4cb23c 100644 --- a/test/unit/migrations/029-test.js +++ b/test/unit/migrations/029-test.js @@ -22,7 +22,7 @@ describe('storage is migrated successfully where transactions that are submitted migration29.migrate(storage) .then((migratedData) => { const txs = migratedData.data.TransactionController.transactions - const [ txMeta1 ] = txs + const [txMeta1] = txs assert.equal(migratedData.meta.version, 29) assert.equal(txMeta1.status, 'failed', 'old tx is auto failed') diff --git a/test/unit/migrations/migrator-test.js b/test/unit/migrations/migrator-test.js index de4d16c45212..87468d917750 100644 --- a/test/unit/migrations/migrator-test.js +++ b/test/unit/migrations/migrator-test.js @@ -49,7 +49,7 @@ describe('migrations', function () { migrationNumbers = fileNames .reduce((acc, filename) => { const name = filename.split('.')[0] - if (/^\d+$/u.test(name)) { + if ((/^\d+$/u).test(name)) { acc.push(name) } return acc @@ -69,7 +69,7 @@ describe('migrations', function () { const testNumbers = fileNames .reduce((acc, filename) => { const name = filename.split('-test.')[0] - if (/^\d+$/u.test(name)) { + if ((/^\d+$/u).test(name)) { acc.push(name) } return acc diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index accca3136bc3..8f2dc0bbfb4d 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -38,11 +38,11 @@ describe('Actions', function () { showUnapprovedTx: noop, showUnconfirmedMessage: noop, encryptor: { - encrypt: function (_, object) { + encrypt (_, object) { this.object = object return Promise.resolve('mock-encrypted') }, - decrypt: function () { + decrypt () { return Promise.resolve(this.object) }, }, @@ -56,7 +56,7 @@ describe('Actions', function () { await metamaskController.createNewVaultAndRestore(password, TEST_SEED) - await metamaskController.importAccountWithStrategy('Private Key', [ importPrivkey ]) + await metamaskController.importAccountWithStrategy('Private Key', [importPrivkey]) background = metamaskController.getApi() @@ -97,7 +97,6 @@ describe('Actions', function () { { type: 'HIDE_LOADING_INDICATION' }, ] - submitPasswordSpy = sinon.stub(background, 'submitPassword') submitPasswordSpy.callsFake((_, callback) => { @@ -114,8 +113,8 @@ describe('Actions', function () { it('displays warning error and unlock failed when verifySeed fails', async function () { const store = mockStore() - const displayWarningError = [ { type: 'DISPLAY_WARNING', value: 'error' } ] - const unlockFailedError = [ { type: 'UNLOCK_FAILED', value: 'error' } ] + const displayWarningError = [{ type: 'DISPLAY_WARNING', value: 'error' }] + const unlockFailedError = [{ type: 'UNLOCK_FAILED', value: 'error' }] verifySeedPhraseSpy = sinon.stub(background, 'verifySeedPhrase') verifySeedPhraseSpy.callsFake((callback) => { @@ -861,7 +860,7 @@ describe('Actions', function () { 'value': '0x0', } - const txData = { id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: txParams } + const txData = { id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams } beforeEach(async function () { await metamaskController.txController.txStateManager.addTx(txData) diff --git a/test/unit/ui/app/reducers/app.spec.js b/test/unit/ui/app/reducers/app.spec.js index 027f574f2181..7ba811cc33e6 100644 --- a/test/unit/ui/app/reducers/app.spec.js +++ b/test/unit/ui/app/reducers/app.spec.js @@ -122,7 +122,6 @@ describe('App State', function () { type: actions.MODAL_CLOSE, }) - assert.equal(newState.modal.open, false) assert.equal(newState.modal.modalState.name, null) }) diff --git a/test/unit/ui/app/reducers/metamask.spec.js b/test/unit/ui/app/reducers/metamask.spec.js index 3b232c0f638e..1a872b14ed47 100644 --- a/test/unit/ui/app/reducers/metamask.spec.js +++ b/test/unit/ui/app/reducers/metamask.spec.js @@ -209,7 +209,8 @@ describe('MetaMask Reducers', function () { it('clears send', function () { const initStateSend = { send: - { gasLimit: null, + { + gasLimit: null, gasPrice: null, gasTotal: null, tokenBalance: null, @@ -220,7 +221,8 @@ describe('MetaMask Reducers', function () { errors: {}, maxModeOn: false, editingTransactionId: null, - toNickname: '' }, + toNickname: '', + }, } const sendState = { @@ -240,7 +242,6 @@ describe('MetaMask Reducers', function () { }, } - const state = reduceMetamask(sendState, { type: actionConstants.CLEAR_SEND, }) diff --git a/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js b/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js index 46630bfcc4c6..d42bd7bc9ce3 100644 --- a/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js +++ b/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js @@ -25,7 +25,7 @@ describe('AccountListItem Component', function () { handleClick={propsMethodSpies.handleClick} icon={} /> - ), { context: { t: (str) => str + '_t' } }) + ), { context: { t: (str) => `${str}_t` } }) }) afterEach(function () { diff --git a/ui/app/components/app/account-menu/account-menu.container.js b/ui/app/components/app/account-menu/account-menu.container.js index a9739dccc039..c08537264a3e 100644 --- a/ui/app/components/app/account-menu/account-menu.container.js +++ b/ui/app/components/app/account-menu/account-menu.container.js @@ -32,7 +32,7 @@ function mapStateToProps (state) { isAccountMenuOpen, addressConnectedDomainMap: getAddressConnectedDomainMap(state), originOfCurrentTab: origin, - selectedAddress: selectedAddress, + selectedAddress, keyrings: getMetaMaskKeyrings(state), accounts, shouldShowAccountsSearch: accounts.length >= SHOW_SEARCH_ACCOUNTS_MIN_COUNT, diff --git a/ui/app/components/app/account-menu/tests/account-menu.test.js b/ui/app/components/app/account-menu/tests/account-menu.test.js index 5dfbd4f1d776..e0166dd08ec1 100644 --- a/ui/app/components/app/account-menu/tests/account-menu.test.js +++ b/ui/app/components/app/account-menu/tests/account-menu.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import configureMockStore from 'redux-mock-store' import { Provider } from 'react-redux' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import AccountMenu from '../index' +import AccountMenu from '..' describe('Account Menu', function () { diff --git a/ui/app/components/app/add-token-button/add-token-button.component.js b/ui/app/components/app/add-token-button/add-token-button.component.js index b1d327a2186b..1ddf2b1ffe05 100644 --- a/ui/app/components/app/add-token-button/add-token-button.component.js +++ b/ui/app/components/app/add-token-button/add-token-button.component.js @@ -5,7 +5,6 @@ import { useI18nContext } from '../../../hooks/useI18nContext' import { ADD_TOKEN_ROUTE } from '../../../helpers/constants/routes' import Button from '../../ui/button' - export default function AddTokenButton () { const addTokenEvent = useMetricEvent({ eventOpts: { diff --git a/ui/app/components/app/app-header/tests/app-header.test.js b/ui/app/components/app/app-header/tests/app-header.test.js index e70684a094ae..76ece07a7c17 100644 --- a/ui/app/components/app/app-header/tests/app-header.test.js +++ b/ui/app/components/app/app-header/tests/app-header.test.js @@ -3,7 +3,7 @@ import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' import MetaFoxLogo from '../../../ui/metafox-logo' -import AppHeader from '../index' +import AppHeader from '..' describe('App Header', function () { let wrapper diff --git a/ui/app/components/app/asset-list-item/asset-list-item.js b/ui/app/components/app/asset-list-item/asset-list-item.js index ad644f40035b..e5ff8212f4fe 100644 --- a/ui/app/components/app/asset-list-item/asset-list-item.js +++ b/ui/app/components/app/asset-list-item/asset-list-item.js @@ -13,7 +13,6 @@ import { useMetricEvent } from '../../../hooks/useMetricEvent' import { updateSendToken } from '../../../store/actions' import { SEND_ROUTE } from '../../../helpers/constants/routes' - const AssetListItem = ({ className, 'data-testid': dataTestId, diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js index 7b88c14d621d..bf226df7e2ef 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js @@ -6,7 +6,6 @@ import ErrorMessage from '../../../ui/error-message' import { PageContainerFooter } from '../../../ui/page-container' import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.' - export default class ConfirmPageContainerContent extends Component { static propTypes = { action: PropTypes.string, @@ -40,9 +39,9 @@ export default class ConfirmPageContainerContent extends Component { if (detailsComponent && dataComponent) { return this.renderTabs() - } else { - return detailsComponent || dataComponent } + return detailsComponent || dataComponent + } renderTabs () { diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js index c72600274a09..f2e2c0f2b870 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js @@ -11,7 +11,6 @@ import { shortenAddress } from '../../../../helpers/utils/util' import AccountMismatchWarning from '../../../ui/account-mismatch-warning/account-mismatch-warning.component' import { useI18nContext } from '../../../../hooks/useI18nContext' - export default function ConfirmPageContainerHeader ({ onEdit, showEdit, diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js b/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js index 854539477eb6..1208b1f12ff3 100644 --- a/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js +++ b/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js @@ -32,7 +32,7 @@ export default class ConnectedAccountsList extends PureComponent { return new Error( `Warning: Failed prop type: '${propName}' of component '${componentName}' must be a boolean. Received: ${typeof props[propName]}`, ) - } else if (props[propName] && !props['removePermittedAccount']) { + } else if (props[propName] && !props.removePermittedAccount) { return new Error( `Warning: Failed prop type: '${propName}' of component '${componentName}' requires prop 'removePermittedAccount'.`, ) diff --git a/ui/app/components/app/connected-status-indicator/connected-status-indicator.component.js b/ui/app/components/app/connected-status-indicator/connected-status-indicator.component.js index 5954565b5cf3..d000aaf7ace6 100644 --- a/ui/app/components/app/connected-status-indicator/connected-status-indicator.component.js +++ b/ui/app/components/app/connected-status-indicator/connected-status-indicator.component.js @@ -13,7 +13,7 @@ export default class ConnectedStatusIndicator extends Component { } static propTypes = { - status: PropTypes.oneOf([ STATUS_CONNECTED, STATUS_CONNECTED_TO_ANOTHER_ACCOUNT, STATUS_NOT_CONNECTED ]), + status: PropTypes.oneOf([STATUS_CONNECTED, STATUS_CONNECTED_TO_ANOTHER_ACCOUNT, STATUS_NOT_CONNECTED]), onClick: PropTypes.func, } diff --git a/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js b/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js index 678e5175e4de..17034f32dbc8 100644 --- a/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js +++ b/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js @@ -12,7 +12,6 @@ import { } from '../../../selectors' import ConnectedStatusIndicator from './connected-status-indicator.component' - const mapStateToProps = (state) => { const selectedAddress = getSelectedAddress(state) const addressConnectedDomainMap = getAddressConnectedDomainMap(state) diff --git a/ui/app/components/app/contact-list/contact-list.component.js b/ui/app/components/app/contact-list/contact-list.component.js index b41bfe1c166f..b959fb9c070d 100644 --- a/ui/app/components/app/contact-list/contact-list.component.js +++ b/ui/app/components/app/contact-list/contact-list.component.js @@ -67,9 +67,8 @@ export default class ContactList extends PureComponent { return 1 } else if (letter1 === letter2) { return 0 - } else { - return -1 } + return -1 }) .map(([letter, groupItems]) => ( {children} diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index 3a95e348a3e3..16b645858f55 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -135,45 +135,44 @@ class NetworkDropdown extends Component { if ((rpc === 'http://localhost:8545') || currentRpcTarget) { return null - } else { - const { chainId } = entry - return ( - this.props.hideNetworkDropdown()} - onClick={() => this.props.setRpcTarget(rpc, chainId, ticker, nickname)} + } + const { chainId } = entry + return ( + this.props.hideNetworkDropdown()} + onClick={() => this.props.setRpcTarget(rpc, chainId, ticker, nickname)} + style={{ + fontSize: '16px', + lineHeight: '20px', + padding: '12px 0', + }} + > + { + currentRpcTarget + ? + :
+ } + + - { - currentRpcTarget - ? - :
- } - - - {nickname || rpc} - - { - e.stopPropagation() - this.props.delRpcTarget(rpc) - }} - /> -
- ) - } + {nickname || rpc} + + { + e.stopPropagation() + this.props.delRpcTarget(rpc) + }} + /> +
+ ) }) } diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js index 8130a5179a93..a18e0e114bea 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import AdvancedTabContent from '../index' +import AdvancedTabContent from '..' describe('Advanced Gas Inputs', function () { let wrapper, clock @@ -29,7 +29,8 @@ describe('Advanced Gas Inputs', function () { context: { t: (str) => str, }, - }) + }, + ) }) afterEach(function () { diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js index bc2e45ba71a2..f27d0de522ae 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js @@ -168,21 +168,18 @@ describe('gas-modal-page-container container', function () { const tests = [ { mockState: baseMockState, expectedResult: baseExpectedResult, mockOwnProps: baseMockOwnProps }, { - mockState: Object.assign({}, baseMockState, { - metamask: { ...baseMockState.metamask, balance: '0xfffffffffffffffffffff' }, - }), - expectedResult: Object.assign({}, baseExpectedResult, { balance: '0xfffffffffffffffffffff', insufficientBalance: false }), + mockState: { ...baseMockState, metamask: { ...baseMockState.metamask, balance: '0xfffffffffffffffffffff' } }, + expectedResult: { ...baseExpectedResult, balance: '0xfffffffffffffffffffff', insufficientBalance: false }, mockOwnProps: baseMockOwnProps, }, { mockState: baseMockState, - mockOwnProps: Object.assign({}, baseMockOwnProps, { - transaction: { id: 34, status: 'submitted' }, - }), - expectedResult: Object.assign({}, baseExpectedResult, { isSpeedUp: true, transaction: { id: 34 } }), + mockOwnProps: { ...baseMockOwnProps, transaction: { id: 34, status: 'submitted' } }, + expectedResult: { ...baseExpectedResult, isSpeedUp: true, transaction: { id: 34 } }, }, { - mockState: Object.assign({}, baseMockState, { + mockState: { + ...baseMockState, metamask: { ...baseMockState.metamask, preferences: { @@ -194,7 +191,7 @@ describe('gas-modal-page-container container', function () { type: 'rinkeby', }, }, - }), + }, mockOwnProps: baseMockOwnProps, expectedResult: { ...baseExpectedResult, @@ -206,7 +203,8 @@ describe('gas-modal-page-container container', function () { }, }, { - mockState: Object.assign({}, baseMockState, { + mockState: { + ...baseMockState, metamask: { ...baseMockState.metamask, preferences: { @@ -218,7 +216,7 @@ describe('gas-modal-page-container container', function () { type: 'rinkeby', }, }, - }), + }, mockOwnProps: baseMockOwnProps, expectedResult: { ...baseExpectedResult, @@ -226,7 +224,8 @@ describe('gas-modal-page-container container', function () { }, }, { - mockState: Object.assign({}, baseMockState, { + mockState: { + ...baseMockState, metamask: { ...baseMockState.metamask, preferences: { @@ -238,7 +237,7 @@ describe('gas-modal-page-container container', function () { type: 'mainnet', }, }, - }), + }, mockOwnProps: baseMockOwnProps, expectedResult: baseExpectedResult, }, @@ -404,7 +403,7 @@ describe('gas-modal-page-container container', function () { }) it('should return the expected props when isConfirm is false', function () { - const result = mergeProps(Object.assign({}, stateProps, { isConfirm: false }), dispatchProps, ownProps) + const result = mergeProps({ ...stateProps, isConfirm: false }, dispatchProps, ownProps) assert.equal(result.isConfirm, false) assert.equal(result.someOtherStateProp, 'baz') @@ -435,7 +434,7 @@ describe('gas-modal-page-container container', function () { }) it('should dispatch the expected actions from obSubmit when isConfirm is false and isSpeedUp is true', function () { - const result = mergeProps(Object.assign({}, stateProps, { isSpeedUp: true, isConfirm: false }), dispatchProps, ownProps) + const result = mergeProps({ ...stateProps, isSpeedUp: true, isConfirm: false }, dispatchProps, ownProps) result.onSubmit() diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js b/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js index 8916c7e8e563..77c098983cf0 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js +++ b/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js @@ -4,7 +4,6 @@ import ButtonGroup from '../../../ui/button-group' import Button from '../../../ui/button' import { GAS_ESTIMATE_TYPES } from '../../../../helpers/constants/common' - const GAS_OBJECT_PROPTYPES_SHAPE = { gasEstimateType: PropTypes.oneOf(Object.values(GAS_ESTIMATE_TYPES)).isRequired, feeInPrimaryCurrency: PropTypes.string, diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js b/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js index 24a89e165ede..4cd44066ca3d 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js +++ b/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js @@ -41,11 +41,11 @@ describe('GasPriceButtonGroup Component', function () { showCheck: true, } - mockButtonPropsAndFlags = Object.assign({}, { + mockButtonPropsAndFlags = { className: mockGasPriceButtonGroupProps.className, handleGasPriceSelection: mockGasPriceButtonGroupProps.handleGasPriceSelection, showCheck: mockGasPriceButtonGroupProps.showCheck, - }) + } sinon.spy(GasPriceButtonGroup.prototype, 'renderButton') sinon.spy(GasPriceButtonGroup.prototype, 'renderButtonContent') @@ -81,7 +81,7 @@ describe('GasPriceButtonGroup Component', function () { assert.deepEqual( GasPriceButtonGroup.prototype.renderButton.getCall(i).args, [ - Object.assign({}, mockGasPriceButtonGroupProps.gasButtonInfo[i]), + { ...mockGasPriceButtonGroupProps.gasButtonInfo[i] }, mockPropsAndFlags, i, ], @@ -109,7 +109,7 @@ describe('GasPriceButtonGroup Component', function () { beforeEach(function () { GasPriceButtonGroup.prototype.renderButtonContent.resetHistory() const renderButtonResult = GasPriceButtonGroup.prototype.renderButton( - Object.assign({}, mockGasPriceButtonGroupProps.gasButtonInfo[0]), + { ...mockGasPriceButtonGroupProps.gasButtonInfo[0] }, mockButtonPropsAndFlags, ) wrappedRenderButtonResult = shallow(renderButtonResult) @@ -225,7 +225,6 @@ describe('GasPriceButtonGroup Component', function () { assert.equal(wrappedRenderButtonContentResult.children().length, 5) }) - it('should render no elements if all args passed', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent({}, {}) const wrappedRenderButtonContentResult = shallow(renderButtonContentResult) diff --git a/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js b/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js index f60e36be1377..ff6dd9390ee5 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js +++ b/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js @@ -127,7 +127,7 @@ export function setTickPosition (axis, n, newPosition, secondNewPosition) { /* eslint-disable babel/no-invalid-this */ export function appendOrUpdateCircle ({ data, itemIndex, cx, cy, cssId, appendOnly }) { const circle = this.main - .select('.c3-selected-circles' + this.getTargetSelectorSuffix(data.id)) + .select(`.c3-selected-circles${this.getTargetSelectorSuffix(data.id)}`) .selectAll(`.c3-selected-circle-${itemIndex}`) if (appendOnly || circle.empty()) { @@ -182,7 +182,6 @@ export function setSelectedCircle ({ ) } - export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimatedTimesMax) { const gasPricesMaxPadded = gasPricesMax + 1 const chart = c3.generate({ @@ -216,8 +215,8 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate tick: { values: [Math.floor(gasPrices[0]), Math.ceil(gasPricesMax)], outer: false, - format: function (val) { - return val + ' GWEI' + format (val) { + return `${val} GWEI` }, }, padding: { left: gasPricesMax / 50, right: gasPricesMax / 50 }, @@ -260,7 +259,7 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate format: { title: (v) => v.toPrecision(4), }, - contents: function (d) { + contents (d) { const titleFormat = this.config.tooltip_format_title let text d.forEach((el) => { @@ -270,7 +269,7 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate }) return `${text}
` }, - position: function () { + position () { if (d3.select('#overlayed-circle').empty()) { return { top: -100, left: -100 } } @@ -332,7 +331,7 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate const tHeight = this.tooltip.property('offsetHeight') const position = this.config.tooltip_position.call(this, dataToShow, tWidth, tHeight, element) // Set tooltip - this.tooltip.style('top', position.top + 'px').style('left', position.left + 'px') + this.tooltip.style('top', `${position.top}px`).style('left', `${position.left}px`) } } diff --git a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js index df8a58b5525a..d95fa63a1ad6 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js +++ b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js @@ -69,7 +69,7 @@ describe('GasPriceChart Component', function () { './gas-price-chart.utils.js': gasPriceChartUtilsSpies, 'd3': { ...d3, - select: function (...args) { + select (...args) { const result = d3.select(...args) return result.empty() ? mockSelectReturn diff --git a/ui/app/components/app/info-box/tests/info-box.test.js b/ui/app/components/app/info-box/tests/info-box.test.js index 6112a25adc7c..5ad89b4fda60 100644 --- a/ui/app/components/app/info-box/tests/info-box.test.js +++ b/ui/app/components/app/info-box/tests/info-box.test.js @@ -3,7 +3,7 @@ import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' -import InfoBox from '../index' +import InfoBox from '..' describe('InfoBox', function () { diff --git a/ui/app/components/app/menu-bar/tests/menu-bar.test.js b/ui/app/components/app/menu-bar/tests/menu-bar.test.js index 416179d174f1..1212977bed40 100644 --- a/ui/app/components/app/menu-bar/tests/menu-bar.test.js +++ b/ui/app/components/app/menu-bar/tests/menu-bar.test.js @@ -3,7 +3,7 @@ import React from 'react' import { Provider } from 'react-redux' import configureStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import MenuBar from '../index' +import MenuBar from '..' const initState = { activeTab: {}, diff --git a/ui/app/components/app/menu-droppo.js b/ui/app/components/app/menu-droppo.js index e460fe118cef..35d7b458eaa3 100644 --- a/ui/app/components/app/menu-droppo.js +++ b/ui/app/components/app/menu-droppo.js @@ -74,11 +74,11 @@ export default class MenuDroppoComponent extends Component { this.manageListeners() - const baseStyle = Object.assign( - { position: 'fixed' }, - style, - { zIndex }, - ) + const baseStyle = { + position: 'fixed', + ...style, + zIndex, + } return (
diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js index 858ae8296735..faa910c43fd2 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js @@ -52,7 +52,7 @@ export default class AccountDetailsModal extends Component { diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js index 2d01711ff92a..f13cca55091a 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js +++ b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js @@ -26,7 +26,6 @@ export default class CancelTransaction extends PureComponent { if (transactionStatus !== SUBMITTED_STATUS) { showTransactionConfirmedModal() - return } } diff --git a/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js index e5c2ceeb5f2d..adf8de80af36 100644 --- a/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js +++ b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import ConfirmDeleteNetwork from '../index' +import ConfirmDeleteNetwork from '..' describe('Confirm Delete Network', function () { let wrapper diff --git a/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js index 6aa26ba706b9..12f6d365563d 100644 --- a/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js +++ b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js @@ -5,7 +5,7 @@ import { Provider } from 'react-redux' import sinon from 'sinon' import configureStore from 'redux-mock-store' import { mount } from 'enzyme' -import ConfirmRemoveAccount from '../index' +import ConfirmRemoveAccount from '..' describe('Confirm Remove Account', function () { let wrapper @@ -26,7 +26,6 @@ describe('Confirm Remove Account', function () { }, } - const mockStore = configureStore() const store = mockStore(state) diff --git a/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js index d9e05c6a70fd..0059930594bc 100644 --- a/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js +++ b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import ConfirmResetAccount from '../index' +import ConfirmResetAccount from '..' describe('Confirm Reset Account', function () { let wrapper diff --git a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js index 5c7c8caecec1..7217ac21e128 100644 --- a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js +++ b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js @@ -30,5 +30,4 @@ function mapDispatchToProps (dispatch) { } } - export default connect(mapStateToProps, mapDispatchToProps)(DepositEtherModal) diff --git a/ui/app/components/app/modals/fade-modal.js b/ui/app/components/app/modals/fade-modal.js index 89cace1467ff..72d1c7288301 100644 --- a/ui/app/components/app/modals/fade-modal.js +++ b/ui/app/components/app/modals/fade-modal.js @@ -22,14 +22,14 @@ const insertRule = (css) => { const insertKeyframesRule = (keyframes) => { // random name // eslint-disable-next-line no-plusplus - const name = 'anim_' + (++index) + (+new Date()) + const name = `anim_${++index}${Number(new Date())}` let css = `@keyframes ${name} {` Object.keys(keyframes).forEach((key) => { - css += key + ' {' + css += `${key} {` Object.keys(keyframes[key]).forEach((property) => { - const part = ':' + keyframes[key][property] + ';' + const part = `:${keyframes[key][property]};` css += property + part }) @@ -179,15 +179,15 @@ class FadeModal extends Component { const { willHide } = this.state const { modalStyle } = this.props - const backdropStyle = Object.assign({}, { + const backdropStyle = { animationName: willHide ? animation.hideBackdropAnimation : animation.showBackdropAnimation, - animationTimingFunction: (willHide ? animation.hide : animation.show).animationTimingFunction, - }, this.props.backdropStyle) - const contentStyle = Object.assign({}, { + animationTimingFunction: (willHide ? animation.hide : animation.show).animationTimingFunction, ...this.props.backdropStyle, + } + const contentStyle = { animationDuration: (willHide ? animation.hide : animation.show).animationDuration, animationName: willHide ? animation.hideContentAnimation : animation.showContentAnimation, - animationTimingFunction: (willHide ? animation.hide : animation.show).animationTimingFunction, - }, this.props.contentStyle) + animationTimingFunction: (willHide ? animation.hide : animation.show).animationTimingFunction, ...this.props.contentStyle, + } const backdrop = this.props.backdrop ? ( diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js b/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js index e35549cbeee2..bd39976b300b 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js +++ b/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import MetaMetricsOptIn from '../index' +import MetaMetricsOptIn from '..' describe('MetaMetrics Opt In', function () { let wrapper diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js index fd79c9e41e4a..d78db3d14103 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js @@ -144,7 +144,6 @@ export default class QrScanner extends Component { // To parse other type of links // For ex. EIP-681 (https://eips.ethereum.org/EIPS/eip-681) - // Ethereum address links - fox ex. ethereum:0x.....1111 if (content.split('ethereum:').length > 1) { @@ -161,7 +160,6 @@ export default class QrScanner extends Component { return { type, values } } - stopAndClose = () => { if (this.codeReader) { this.codeReader.reset() diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js index fca9d61adae0..98472c6ea3cb 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js @@ -2,7 +2,6 @@ import { connect } from 'react-redux' import { hideModal, qrCodeDetected } from '../../../../store/actions' import QrScanner from './qr-scanner.component' - const mapDispatchToProps = (dispatch) => { return { hideModal: () => dispatch(hideModal()), diff --git a/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js index 93f4495dadd6..1d8a1df68047 100644 --- a/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js +++ b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import RejectTransactionsModal from '../index' +import RejectTransactionsModal from '..' describe('Reject Transactions Model', function () { let wrapper diff --git a/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js index ad8ba565d930..971ed324cb2d 100644 --- a/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js +++ b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import TransactionConfirmed from '../index' +import TransactionConfirmed from '..' describe('Transaction Confirmed', function () { it('clicks ok to submit and hide modal', function () { diff --git a/ui/app/components/app/network-display/network-display.component.js b/ui/app/components/app/network-display/network-display.component.js index 2dbe96adf2be..eb89755c3e58 100644 --- a/ui/app/components/app/network-display/network-display.component.js +++ b/ui/app/components/app/network-display/network-display.component.js @@ -57,7 +57,7 @@ export default class NetworkDisplay extends Component {
{ diff --git a/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js b/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js index a10f89b9a03e..94895e92da97 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js +++ b/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js @@ -95,7 +95,7 @@ export default class PermissionPageContainerContent extends PureComponent { ) }) } { selectedIdentities.length > 6 - ? t('plusXMore', [ selectedIdentities.length - 6 ]) + ? t('plusXMore', [selectedIdentities.length - 6]) : null }
@@ -115,23 +115,19 @@ export default class PermissionPageContainerContent extends PureComponent { } else if (allIdentitiesSelected) { return t( 'connectToAll', - [ this.renderAccountTooltip(t('connectToAllAccounts')) ], + [this.renderAccountTooltip(t('connectToAllAccounts'))], ) } else if (selectedIdentities.length > 1) { return t( 'connectToMultiple', [ - this.renderAccountTooltip(t('connectToMultipleNumberOfAccounts', [ selectedIdentities.length ])), - ], - ) - } else { - return t( - 'connectTo', - [ - this.getAccountDescriptor(selectedIdentities[0]), + this.renderAccountTooltip(t('connectToMultipleNumberOfAccounts', [selectedIdentities.length])), ], ) } + return t('connectTo', [ + this.getAccountDescriptor(selectedIdentities[0]), + ]) } render () { diff --git a/ui/app/components/app/selected-account/selected-account.container.js b/ui/app/components/app/selected-account/selected-account.container.js index 22e6cc5eff29..154bf431148d 100644 --- a/ui/app/components/app/selected-account/selected-account.container.js +++ b/ui/app/components/app/selected-account/selected-account.container.js @@ -2,7 +2,6 @@ import { connect } from 'react-redux' import { getSelectedIdentity } from '../../../selectors' import SelectedAccount from './selected-account.component' - const mapStateToProps = (state) => { return { selectedIdentity: getSelectedIdentity(state), diff --git a/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js b/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js index 16b6c3bea714..5c4b455d32e6 100644 --- a/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js +++ b/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js @@ -14,7 +14,7 @@ export default class SignatureRequestMessage extends PureComponent { renderNode (data) { return (
- {Object.entries(data).map(([ label, value ], i) => ( + {Object.entries(data).map(([label, value], i) => (
key - describe('Outgoing transaction', function () { beforeEach(function () { global.eth = { diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js index ba45b9be03b9..ed07e1ee48d7 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js @@ -1,13 +1,5 @@ import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util' -// path constants -const STATUS_PATH = '/status' -const GAS_PRICE_PATH = '/txParams/gasPrice' -const GAS_LIMIT_PATH = '/txParams/gas' - -// op constants -const REPLACE_OP = 'replace' - import { TRANSACTION_TYPE_CANCEL, TRANSACTION_TYPE_RETRY, @@ -29,6 +21,13 @@ import { DROPPED_STATUS, } from './transaction-activity-log.constants' +// path constants +const STATUS_PATH = '/status' +const GAS_PRICE_PATH = '/txParams/gasPrice' +const GAS_LIMIT_PATH = '/txParams/gas' + +// op constants +const REPLACE_OP = 'replace' const eventPathsHash = { [STATUS_PATH]: true, diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js index e52b0bce0301..6aee276a72b7 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js @@ -17,7 +17,7 @@ const mapStateToProps = (state, ownProps) => { return { nativeCurrency: getNativeCurrency(state), - showFiat: (isMainnet || !!showFiatInTestnets), + showFiat: (isMainnet || Boolean(showFiatInTestnets)), totalInHex, gas, gasPrice, diff --git a/ui/app/components/app/transaction-icon/transaction-icon.js b/ui/app/components/app/transaction-icon/transaction-icon.js index 24f4f47159bb..d0c7ef455d26 100644 --- a/ui/app/components/app/transaction-icon/transaction-icon.js +++ b/ui/app/components/app/transaction-icon/transaction-icon.js @@ -20,7 +20,6 @@ import { APPROVED_STATUS, } from '../../../helpers/constants/transactions' - const ICON_MAP = { [TRANSACTION_CATEGORY_APPROVAL]: Approve, [TRANSACTION_CATEGORY_INTERACTION]: Interaction, diff --git a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js index eb03d3003708..0b64678ff78d 100644 --- a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js +++ b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js @@ -26,7 +26,6 @@ import TransactionIcon from '../transaction-icon' import { useTransactionTimeRemaining } from '../../../hooks/useTransactionTimeRemaining' import IconWithLabel from '../../ui/icon-with-label' - export default function TransactionListItem ({ transactionGroup, isEarliestNonce = false }) { const t = useI18nContext() const history = useHistory() @@ -54,7 +53,6 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce const timeRemaining = useTransactionTimeRemaining(isPending, isEarliestNonce, submittedTime, gasPrice) - const isSignatureReq = category === TRANSACTION_CATEGORY_SIGNATURE_REQUEST const isApproval = category === TRANSACTION_CATEGORY_APPROVAL const isUnapproved = status === UNAPPROVED_STATUS diff --git a/ui/app/components/app/transaction-list/transaction-list.component.js b/ui/app/components/app/transaction-list/transaction-list.component.js index a293b8aa1205..a05cf06f9079 100644 --- a/ui/app/components/app/transaction-list/transaction-list.component.js +++ b/ui/app/components/app/transaction-list/transaction-list.component.js @@ -26,7 +26,6 @@ const tokenTransactionFilter = ({ }, }) => !TOKEN_CATEGORY_HASH[transactionCategory] - const getFilteredTransactionGroups = (transactionGroups, hideTokenTransactions, tokenAddress) => { if (hideTokenTransactions) { return transactionGroups.filter(tokenTransactionFilter) @@ -72,11 +71,10 @@ export default function TransactionList ({ hideTokenTransactions, tokenAddress } .then(({ blockTime }) => fetchGasEstimates(blockTime)) } prevState.current = { loaded: true, pendingTransactions, transactionTimeFeatureActive } - }, [fetchGasEstimates, fetchBasicGasAndTimeEstimates, transactionTimeFeatureActive, pendingTransactions ]) + }, [fetchGasEstimates, fetchBasicGasAndTimeEstimates, transactionTimeFeatureActive, pendingTransactions]) const viewMore = useCallback(() => setLimit((prev) => prev + PAGE_INCREMENT), []) - const pendingLength = pendingTransactions.length return ( diff --git a/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js b/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js index c5c903fd9cb6..d9f271e105b7 100644 --- a/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js +++ b/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js @@ -7,7 +7,6 @@ import CurrencyDisplay from '../../../ui/currency-display' import * as currencyHook from '../../../../hooks/useCurrencyDisplay' import * as currencyPrefHook from '../../../../hooks/useUserPreferencedCurrency' - describe('UserPreferencedCurrencyDisplay Component', function () { describe('rendering', function () { beforeEach(function () { diff --git a/ui/app/components/ui/alert/index.js b/ui/app/components/ui/alert/index.js index 3bc1b4581930..437bf492bb5c 100644 --- a/ui/app/components/ui/alert/index.js +++ b/ui/app/components/ui/alert/index.js @@ -19,7 +19,7 @@ class Alert extends Component { animateIn (msg) { this.setState({ - msg: msg, + msg, visible: true, className: 'visible', }) diff --git a/ui/app/components/ui/alert/tests/alert.test.js b/ui/app/components/ui/alert/tests/alert.test.js index ec32d6633839..70aaa5e16fa8 100644 --- a/ui/app/components/ui/alert/tests/alert.test.js +++ b/ui/app/components/ui/alert/tests/alert.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' -import Alert from '../index' +import Alert from '..' describe('Alert', function () { let wrapper diff --git a/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js b/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js index 1fcf2aaea74f..63b9a3f51e44 100644 --- a/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js +++ b/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js @@ -15,8 +15,8 @@ describe('Breadcrumbs Component', function () { assert.ok(wrapper) assert.equal(wrapper.find('.breadcrumbs').length, 1) assert.equal(wrapper.find('.breadcrumb').length, 3) - assert.equal(wrapper.find('.breadcrumb').at(0).props().style['backgroundColor'], '#FFFFFF') - assert.equal(wrapper.find('.breadcrumb').at(1).props().style['backgroundColor'], '#D8D8D8') - assert.equal(wrapper.find('.breadcrumb').at(2).props().style['backgroundColor'], '#FFFFFF') + assert.equal(wrapper.find('.breadcrumb').at(0).props().style.backgroundColor, '#FFFFFF') + assert.equal(wrapper.find('.breadcrumb').at(1).props().style.backgroundColor, '#D8D8D8') + assert.equal(wrapper.find('.breadcrumb').at(2).props().style.backgroundColor, '#FFFFFF') }) }) diff --git a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js index 24c819e56dc2..1e7936978940 100644 --- a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js +++ b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js @@ -137,7 +137,7 @@ describe('CurrencyInput Component', function () { /> , { - context: { t: (str) => str + '_t' }, + context: { t: (str) => `${str}_t` }, childContextTypes: { t: PropTypes.func }, }, ) diff --git a/ui/app/components/ui/dropdown/dropdown.stories.js b/ui/app/components/ui/dropdown/dropdown.stories.js index 82dd1ca4d452..1ecb31bc9ce7 100644 --- a/ui/app/components/ui/dropdown/dropdown.stories.js +++ b/ui/app/components/ui/dropdown/dropdown.stories.js @@ -12,14 +12,13 @@ const unnamedOptions = [...Array(10).keys()].map((index) => { }) const namedOptions = unnamedOptions.map((option, index) => { - return Object.assign({}, option, { name: `Option ${index}` }) + return { ...option, name: `Option ${index}` } }) const namedOptionsWithVeryLongNames = unnamedOptions.map((option, index) => { - return Object.assign({}, option, { name: `Option ${index} with a very${', very'.repeat(index)} long name` }) + return { ...option, name: `Option ${index} with a very${', very'.repeat(index)} long name` } }) - export const simple = () => ( ( /> ) - export const approve = () => ( } diff --git a/ui/app/components/ui/page-container/page-container.component.js b/ui/app/components/ui/page-container/page-container.component.js index b4af4e719a7b..fd3b2eedeb3a 100644 --- a/ui/app/components/ui/page-container/page-container.component.js +++ b/ui/app/components/ui/page-container/page-container.component.js @@ -75,9 +75,8 @@ export default class PageContainer extends PureComponent { return contentComponent } else if (tabsComponent) { return this.renderActiveTabContent() - } else { - return null } + return null } render () { diff --git a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js index 7af7b2af7357..de7e54745f4b 100644 --- a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js +++ b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js @@ -9,7 +9,6 @@ import AccountMismatchWarning from '../account-mismatch-warning/account-mismatch import { useI18nContext } from '../../../hooks/useI18nContext' import { DEFAULT_VARIANT, CARDS_VARIANT, FLAT_VARIANT } from './sender-to-recipient.constants' - const variantHash = { [DEFAULT_VARIANT]: 'sender-to-recipient--default', [CARDS_VARIANT]: 'sender-to-recipient--cards', @@ -161,7 +160,6 @@ RecipientWithAddress.propTypes = { onRecipientClick: PropTypes.func, } - function Arrow ({ variant }) { return variant === DEFAULT_VARIANT ? ( diff --git a/ui/app/components/ui/text-field/text-field.component.js b/ui/app/components/ui/text-field/text-field.component.js index 008e621d459a..9e80e3bc8725 100644 --- a/ui/app/components/ui/text-field/text-field.component.js +++ b/ui/app/components/ui/text-field/text-field.component.js @@ -146,7 +146,7 @@ const getBorderedThemeInputProps = ({ disableUnderline: true, classes: { root: inputRoot, - input: input, + input, focused: inputFocused, }, inputProps: { diff --git a/ui/app/components/ui/token-input/tests/token-input.component.test.js b/ui/app/components/ui/token-input/tests/token-input.component.test.js index 3ff94d879f63..a7cda504f05b 100644 --- a/ui/app/components/ui/token-input/tests/token-input.component.test.js +++ b/ui/app/components/ui/token-input/tests/token-input.component.test.js @@ -32,7 +32,8 @@ describe('TokenInput Component', function () { }} /> , - { context: { t }, + { + context: { t }, childContextTypes: { t: PropTypes.func, }, @@ -66,7 +67,8 @@ describe('TokenInput Component', function () { tokenExchangeRates={{ '0x1': 2 }} /> , - { context: { t }, + { + context: { t }, childContextTypes: { t: PropTypes.func, }, diff --git a/ui/app/components/ui/unit-input/unit-input.component.js b/ui/app/components/ui/unit-input/unit-input.component.js index 6c43aaf2685f..6a9b76e7c345 100644 --- a/ui/app/components/ui/unit-input/unit-input.component.js +++ b/ui/app/components/ui/unit-input/unit-input.component.js @@ -59,7 +59,7 @@ export default class UnitInput extends PureComponent { const valueString = String(value) const valueLength = valueString.length || 1 const decimalPointDeficit = valueString.match(/\./u) ? -0.5 : 0 - return (valueLength + decimalPointDeficit + 0.5) + 'ch' + return `${valueLength + decimalPointDeficit + 0.5}ch` } render () { diff --git a/ui/app/contexts/metametrics.js b/ui/app/contexts/metametrics.js index 19349bb5d3fa..11162258706d 100644 --- a/ui/app/contexts/metametrics.js +++ b/ui/app/contexts/metametrics.js @@ -20,7 +20,6 @@ import { sendCountIsTrackable, } from '../helpers/utils/metametrics.util' - export const MetaMetricsContext = createContext(() => { captureException( Error(`MetaMetrics context function was called from a react node that is not a descendant of a MetaMetrics context provider`), diff --git a/ui/app/ducks/app/app.js b/ui/app/ducks/app/app.js index e7672dd37d7e..2b905a1ace6c 100644 --- a/ui/app/ducks/app/app.js +++ b/ui/app/ducks/app/app.js @@ -5,7 +5,7 @@ const SET_THREEBOX_LAST_UPDATED = 'metamask/app/SET_THREEBOX_LAST_UPDATED' export default function reduceApp (state = {}, action) { // default state - const appState = Object.assign({ + const appState = { shouldClose: false, menuOpen: false, modal: { @@ -51,7 +51,8 @@ export default function reduceApp (state = {}, action) { requestAccountTabs: {}, openMetaMaskTabs: {}, currentWindowTab: {}, - }, state) + ...state, + } switch (action.type) { // dropdown methods @@ -108,7 +109,6 @@ export default function reduceApp (state = {}, action) { qrCodeData: action.value, } - // modal methods: case actionConstants.MODAL_OPEN: { const { name, ...modalProps } = action.payload @@ -118,7 +118,7 @@ export default function reduceApp (state = {}, action) { modal: { open: true, modalState: { - name: name, + name, props: { ...modalProps }, }, previousModalState: { ...appState.modal.modalState }, @@ -209,17 +209,16 @@ export default function reduceApp (state = {}, action) { txId: null, warning: null, } - } else { - return { - ...appState, - // indicate notification should close - shouldClose: true, - warning: null, - txId: null, - accountDetail: { - subview: 'transactions', - }, - } + } + return { + ...appState, + // indicate notification should close + shouldClose: true, + warning: null, + txId: null, + accountDetail: { + subview: 'transactions', + }, } case actionConstants.TRANSACTION_ERROR: diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js index eb8975265fbb..2285e8bd7646 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js @@ -366,7 +366,6 @@ export function setTransactionToConfirm (transactionId) { if (txParams.data) { const { data } = txParams - const tokenData = getTokenData(data) dispatch(updateTokenData(tokenData)) diff --git a/ui/app/ducks/gas/gas-duck.test.js b/ui/app/ducks/gas/gas-duck.test.js index 4a7addaf6132..d7ae9b87368d 100644 --- a/ui/app/ducks/gas/gas-duck.test.js +++ b/ui/app/ducks/gas/gas-duck.test.js @@ -288,7 +288,7 @@ describe('Gas Duck', function () { })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok( window.fetch.getCall(0).args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'), @@ -296,7 +296,7 @@ describe('Gas Duck', function () { ) assert.deepEqual( mockDistpatch.getCall(1).args, - [{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ], + [{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 }], ) assert.deepEqual( mockDistpatch.getCall(2).args, @@ -334,14 +334,10 @@ describe('Gas Duck', function () { safeLow: 15, }) - await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - {}, - ) })) + await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: { ...initState } })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok(window.fetch.notCalled) assert.deepEqual( @@ -370,14 +366,10 @@ describe('Gas Duck', function () { .withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') .returns(2000000 - 1) // one second ago from "now" - await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - {}, - ) })) + await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: { ...initState } })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok( window.fetch.getCall(0).args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'), @@ -385,7 +377,7 @@ describe('Gas Duck', function () { ) assert.deepEqual( mockDistpatch.getCall(1).args, - [{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ], + [{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 }], ) assert.deepEqual( mockDistpatch.getCall(2).args, @@ -412,16 +404,16 @@ describe('Gas Duck', function () { it('should call fetch with the expected params', async function () { const mockDistpatch = sinon.spy() - await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - { basicPriceAndTimeEstimatesLastRetrieved: 1000000 }, - ), - metamask: { provider: { type: 'ropsten' } }, + await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ + gas: { + ...initState, + basicPriceAndTimeEstimatesLastRetrieved: 1000000, + }, + metamask: { provider: { type: 'ropsten' } }, })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok( window.fetch.getCall(0).args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'), @@ -430,7 +422,7 @@ describe('Gas Duck', function () { assert.deepEqual( mockDistpatch.getCall(1).args, - [{ type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ], + [{ type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 }], ) assert.deepEqual( @@ -479,16 +471,15 @@ describe('Gas Duck', function () { speed: 'mockSpeed', }) - await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - {}, - ), - metamask: { provider: { type: 'ropsten' } }, + await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ + gas: { + ...initState, + }, + metamask: { provider: { type: 'ropsten' } }, })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok(window.fetch.notCalled) @@ -523,16 +514,15 @@ describe('Gas Duck', function () { .withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED') .returns(2000000 - 1) // one second ago from "now" - await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - {}, - ), - metamask: { provider: { type: 'ropsten' } }, + await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ + gas: { + ...initState, + }, + metamask: { provider: { type: 'ropsten' } }, })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok( window.fetch.getCall(0).args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'), @@ -541,7 +531,7 @@ describe('Gas Duck', function () { assert.deepEqual( mockDistpatch.getCall(1).args, - [{ type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ], + [{ type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 }], ) assert.deepEqual( @@ -574,16 +564,16 @@ describe('Gas Duck', function () { it('should call fetch with the expected params', async function () { const mockDistpatch = sinon.spy() - await fetchGasEstimates(5)(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - { priceAndTimeEstimatesLastRetrieved: 1000000 }, - ), - metamask: { provider: { type: 'ropsten' } }, + await fetchGasEstimates(5)(mockDistpatch, () => ({ + gas: { + ...initState, + priceAndTimeEstimatesLastRetrieved: 1000000, + }, + metamask: { provider: { type: 'ropsten' } }, })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok( window.fetch.getCall(0).args[0].startsWith('https://ethgasstation.info/json/predictTable.json'), @@ -611,10 +601,9 @@ describe('Gas Duck', function () { it('should not call fetch if the estimates were retrieved < 75000 ms ago', async function () { const mockDistpatch = sinon.spy() - await fetchGasEstimates(5)(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - { + await fetchGasEstimates(5)(mockDistpatch, () => ({ + gas: { + ...initState, priceAndTimeEstimatesLastRetrieved: Date.now(), priceAndTimeEstimates: [{ expectedTime: '10', @@ -622,12 +611,11 @@ describe('Gas Duck', function () { gasprice: 50, }], }, - ), - metamask: { provider: { type: 'ropsten' } }, + metamask: { provider: { type: 'ropsten' } }, })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: GAS_ESTIMATE_LOADING_STARTED }], ) assert.equal(window.fetch.callCount, 0) @@ -741,5 +729,4 @@ describe('Gas Duck', function () { ) }) }) - }) diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/app/ducks/gas/gas.duck.js index 8451c800a7b3..9d83a66e09e2 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/app/ducks/gas/gas.duck.js @@ -194,8 +194,8 @@ async function queryEthGasStationPredictionTable () { 'referrerPolicy': 'no-referrer-when-downgrade', 'body': null, 'method': 'GET', - 'mode': 'cors' }, - ) + 'mode': 'cors', + }) } export function fetchBasicGasEstimates () { @@ -442,8 +442,7 @@ export function fetchGasEstimates (blockTime) { }) : Promise.resolve(priceAndTimeEstimates.length ? priceAndTimeEstimates - : loadLocalStorageData('GAS_API_ESTIMATES'), - ) + : loadLocalStorageData('GAS_API_ESTIMATES')) return promiseToFetch.then((estimates) => { dispatch(setPricesAndTimeEstimates(estimates)) diff --git a/ui/app/ducks/metamask/metamask.js b/ui/app/ducks/metamask/metamask.js index 097afee7e968..c2058fc06564 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/app/ducks/metamask/metamask.js @@ -2,7 +2,7 @@ import * as actionConstants from '../../store/actionConstants' import { ALERT_TYPES } from '../../../../app/scripts/controllers/alert' export default function reduceMetamask (state = {}, action) { - const metamaskState = Object.assign({ + const metamaskState = { isInitialized: false, isUnlocked: false, isAccountMenuOpen: false, @@ -46,7 +46,8 @@ export default function reduceMetamask (state = {}, action) { participateInMetaMetrics: null, metaMetricsSendCount: 0, nextNonce: null, - }, state) + ...state, + } switch (action.type) { @@ -88,8 +89,8 @@ export default function reduceMetamask (state = {}, action) { const { account } = action.value const name = action.value.label const id = {} - id[account] = Object.assign({}, metamaskState.identities[account], { name }) - const identities = Object.assign({}, metamaskState.identities, id) + id[account] = { ...metamaskState.identities[account], name } + const identities = { ...metamaskState.identities, ...id } return Object.assign(metamaskState, { identities }) } @@ -272,7 +273,7 @@ export default function reduceMetamask (state = {}, action) { let { currentNetworkTxList } = metamaskState currentNetworkTxList = currentNetworkTxList.map((tx) => { if (tx.id === txId) { - const newTx = Object.assign({}, tx) + const newTx = { ...tx } newTx.txParams = value return newTx } diff --git a/ui/app/helpers/utils/confirm-tx.util.js b/ui/app/helpers/utils/confirm-tx.util.js index 7f456984d8f9..a6319ef97b1b 100644 --- a/ui/app/helpers/utils/confirm-tx.util.js +++ b/ui/app/helpers/utils/confirm-tx.util.js @@ -11,7 +11,6 @@ import { conversionGreaterThan, } from './conversion-util' - export function increaseLastGasPrice (lastGasPrice) { return ethUtil.addHexPrefix(multiplyCurrencies(lastGasPrice || '0x0', 1.1, { multiplicandBase: 16, diff --git a/ui/app/helpers/utils/fetch-with-cache.js b/ui/app/helpers/utils/fetch-with-cache.js index 1b9693d81f32..470f2a8d6f02 100644 --- a/ui/app/helpers/utils/fetch-with-cache.js +++ b/ui/app/helpers/utils/fetch-with-cache.js @@ -24,30 +24,29 @@ const fetchWithCache = async (url, fetchOptions = {}, { cacheRefreshTime = 36000 const { cachedResponse, cachedTime } = cachedFetch[url] || {} if (cachedResponse && currentTime - cachedTime < cacheRefreshTime) { return cachedResponse - } else { - fetchOptions.headers.set('Content-Type', 'application/json') - const _fetch = timeout ? - fetchWithTimeout({ timeout }) : - window.fetch - const response = await _fetch(url, { - referrerPolicy: 'no-referrer-when-downgrade', - body: null, - method: 'GET', - mode: 'cors', - ...fetchOptions, - }) - if (!response.ok) { - throw new Error(`Fetch failed with status '${response.status}': '${response.statusText}'`) - } - const responseJson = await response.json() - const cacheEntry = { - cachedResponse: responseJson, - cachedTime: currentTime, - } - cachedFetch[url] = cacheEntry - saveLocalStorageData(cachedFetch, 'cachedFetch') - return responseJson } + fetchOptions.headers.set('Content-Type', 'application/json') + const _fetch = timeout + ? fetchWithTimeout({ timeout }) + : window.fetch + const response = await _fetch(url, { + referrerPolicy: 'no-referrer-when-downgrade', + body: null, + method: 'GET', + mode: 'cors', + ...fetchOptions, + }) + if (!response.ok) { + throw new Error(`Fetch failed with status '${response.status}': '${response.statusText}'`) + } + const responseJson = await response.json() + const cacheEntry = { + cachedResponse: responseJson, + cachedTime: currentTime, + } + cachedFetch[url] = cacheEntry + saveLocalStorageData(cachedFetch, 'cachedFetch') + return responseJson } export default fetchWithCache diff --git a/ui/app/helpers/utils/formatters.js b/ui/app/helpers/utils/formatters.js index 106a2520dfb2..d722ef09b26b 100644 --- a/ui/app/helpers/utils/formatters.js +++ b/ui/app/helpers/utils/formatters.js @@ -1,3 +1,3 @@ export function formatETHFee (ethFee) { - return ethFee + ' ETH' + return `${ethFee} ETH` } diff --git a/ui/app/helpers/utils/gas-time-estimates.util.js b/ui/app/helpers/utils/gas-time-estimates.util.js index 7e143a0280ec..5aadacf3a224 100644 --- a/ui/app/helpers/utils/gas-time-estimates.util.js +++ b/ui/app/helpers/utils/gas-time-estimates.util.js @@ -47,8 +47,8 @@ export function formatTimeEstimate (totalSeconds, greaterThanMax, lessThanMin) { symbol = '> ' } - const formattedMin = `${minutes ? minutes + ' min' : ''}` - const formattedSec = `${seconds ? seconds + ' sec' : ''}` + const formattedMin = `${minutes ? `${minutes} min` : ''}` + const formattedSec = `${seconds ? `${seconds} sec` : ''}` const formattedCombined = formattedMin && formattedSec ? `${symbol}${formattedMin} ${formattedSec}` : symbol + (formattedMin || formattedSec) diff --git a/ui/app/helpers/utils/i18n-helper.test.js b/ui/app/helpers/utils/i18n-helper.test.js index 252cbe3f3137..4e41f8c2003f 100644 --- a/ui/app/helpers/utils/i18n-helper.test.js +++ b/ui/app/helpers/utils/i18n-helper.test.js @@ -118,42 +118,42 @@ describe('i18n helper', function () { }) it('should return the correct message when a single non-react substitution is made', function () { - const result = t(TEST_KEY_2, [ TEST_SUBSTITUTION_1 ]) + const result = t(TEST_KEY_2, [TEST_SUBSTITUTION_1]) assert.equal(result, `This is a message with a single non-react substitution ${TEST_SUBSTITUTION_1}.`) }) it('should return the correct message when two non-react substitutions are made', function () { - const result = t(TEST_KEY_3, [ TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_2 ]) + const result = t(TEST_KEY_3, [TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_2]) assert.equal(result, `This is a message with two non-react substitutions ${TEST_SUBSTITUTION_1} and ${TEST_SUBSTITUTION_2}.`) }) it('should return the correct message when multiple non-react substitutions are made', function () { - const result = t(TEST_KEY_4, [ TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_2, TEST_SUBSTITUTION_3, TEST_SUBSTITUTION_4, TEST_SUBSTITUTION_5 ]) + const result = t(TEST_KEY_4, [TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_2, TEST_SUBSTITUTION_3, TEST_SUBSTITUTION_4, TEST_SUBSTITUTION_5]) assert.equal(result, `${TEST_SUBSTITUTION_1} - ${TEST_SUBSTITUTION_2} - ${TEST_SUBSTITUTION_3} - ${TEST_SUBSTITUTION_4} - ${TEST_SUBSTITUTION_5}`) }) it('should correctly render falsey substitutions', function () { - const result = t(TEST_KEY_4, [ 0, -0, '', false, NaN ]) + const result = t(TEST_KEY_4, [0, -0, '', false, NaN]) assert.equal(result, '0 - 0 - - false - NaN') }) it('should render nothing for "null" and "undefined" substitutions', function () { - const result = t(TEST_KEY_5, [ null, TEST_SUBSTITUTION_2 ]) + const result = t(TEST_KEY_5, [null, TEST_SUBSTITUTION_2]) assert.equal(result, ` - ${TEST_SUBSTITUTION_2} - `) }) it('should return the correct message when a single react substitution is made', function () { - const result = t(TEST_KEY_6, [ TEST_SUBSTITUTION_6 ]) + const result = t(TEST_KEY_6, [TEST_SUBSTITUTION_6]) assert.equal(shallow(result).html(), ' Testing a react substitution
TEST_SUBSTITUTION_1
.
') }) it('should return the correct message when two react substitutions are made', function () { - const result = t(TEST_KEY_7, [ TEST_SUBSTITUTION_7_1, TEST_SUBSTITUTION_7_2 ]) + const result = t(TEST_KEY_7, [TEST_SUBSTITUTION_7_1, TEST_SUBSTITUTION_7_2]) assert.equal(shallow(result).html(), ' Testing a react substitution
TEST_SUBSTITUTION_1
and another
TEST_SUBSTITUTION_2
.
') }) it('should return the correct message when substituting a mix of react elements and strings', function () { - const result = t(TEST_KEY_8, [ TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_8_1, TEST_SUBSTITUTION_2, TEST_SUBSTITUTION_8_2 ]) + const result = t(TEST_KEY_8, [TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_8_1, TEST_SUBSTITUTION_2, TEST_SUBSTITUTION_8_2]) assert.equal(shallow(result).html(), ' Testing a mix TEST_SUBSTITUTION_1 of react substitutions
TEST_SUBSTITUTION_3
and string substitutions TEST_SUBSTITUTION_2 +
TEST_SUBSTITUTION_4
.
') }) }) diff --git a/ui/app/helpers/utils/metametrics.util.js b/ui/app/helpers/utils/metametrics.util.js index ce76b8385cde..41a4bb22d73e 100644 --- a/ui/app/helpers/utils/metametrics.util.js +++ b/ui/app/helpers/utils/metametrics.util.js @@ -52,6 +52,7 @@ const customVariableNameIdMap = { [METAMETRICS_CUSTOM_GAS_CHANGED]: 1, [METAMETRICS_CUSTOM_ASSET_SELECTED]: 2, } + /** ********************************************************** **/ const METAMETRICS_CUSTOM_NETWORK = 'network' @@ -182,7 +183,7 @@ function composeUrl (config) { uid = `&uid=${metaMetricsId.slice(2, 18)}` } - return [ base, e_c, e_a, e_n, cvar, action_name, urlref, dimensions, url, _id, rand, pv_id, uid, new_visit ].join('') + return [base, e_c, e_a, e_n, cvar, action_name, urlref, dimensions, url, _id, rand, pv_id, uid, new_visit].join('') } export function sendMetaMetricsEvent (config) { @@ -209,9 +210,8 @@ export function verifyUserPermission (config, props) { return true } else if (allowSendMetrics && eventOpts.name === 'send') { return true - } else { - return false } + return false } const trackableSendCounts = { diff --git a/ui/app/helpers/utils/transactions.util.js b/ui/app/helpers/utils/transactions.util.js index d94bd24d81f6..3c6481c80b1d 100644 --- a/ui/app/helpers/utils/transactions.util.js +++ b/ui/app/helpers/utils/transactions.util.js @@ -27,7 +27,6 @@ import { } from '../constants/transactions' import fetchWithCache from './fetch-with-cache' - import { addCurrencies } from './conversion-util' abiDecoder.addABI(abi) @@ -46,9 +45,8 @@ async function getMethodFrom4Byte (fourBytePrefix) { if (fourByteResponse.count === 1) { return fourByteResponse.results[0].text_signature - } else { - return null } + return null } let registry @@ -142,9 +140,8 @@ export function getTransactionActionKey (transaction) { return DECRYPT_REQUEST_KEY } else if (type === MESSAGE_TYPE.ETH_GET_ENCRYPTION_PUBLIC_KEY) { return ENCRYPTION_PUBLIC_KEY_REQUEST_KEY - } else { - return SIGNATURE_REQUEST_KEY } + return SIGNATURE_REQUEST_KEY } if (isConfirmDeployContract(transaction)) { @@ -185,9 +182,8 @@ export function getLatestSubmittedTxWithNonce (transactions = [], nonce = '0x0') return current } return submittedTime > acc.submittedTime ? current : acc - } else { - return acc } + return acc }, {}) } diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index 0d2e741cfbe7..3382104fd592 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -59,7 +59,7 @@ export function addressSummary (address, firstSegLength = 10, lastSegLength = 4, if (!includeHex) { checked = ethUtil.stripHexPrefix(checked) } - return checked ? checked.slice(0, firstSegLength) + '...' + checked.slice(checked.length - lastSegLength) : '...' + return checked ? `${checked.slice(0, firstSegLength)}...${checked.slice(checked.length - lastSegLength)}` : '...' } export function isValidAddress (address) { @@ -106,7 +106,7 @@ export function parseBalance (balance) { const trailingZeros = /0+$/u const beforeDecimal = weiString.length > 18 ? weiString.slice(0, weiString.length - 18) : '0' - afterDecimal = ('000000000000000000' + wei).slice(-18).replace(trailingZeros, '') + afterDecimal = (`000000000000000000${wei}`).slice(-18).replace(trailingZeros, '') if (afterDecimal === '') { afterDecimal = '0' } @@ -127,14 +127,14 @@ export function formatBalance (balance, decimalsToKeep, needsParse = true, ticke if (sigFigs) { afterDecimal = sigFigs[0] } - formatted = '0.' + afterDecimal + ` ${ticker}` + formatted = `0.${afterDecimal} ${ticker}` } } else { - formatted = beforeDecimal + '.' + afterDecimal.slice(0, 3) + ` ${ticker}` + formatted = `${beforeDecimal}.${afterDecimal.slice(0, 3)} ${ticker}` } } else { afterDecimal += Array(decimalsToKeep).join('0') - formatted = beforeDecimal + '.' + afterDecimal.slice(0, decimalsToKeep) + ` ${ticker}` + formatted = `${beforeDecimal}.${afterDecimal.slice(0, decimalsToKeep)} ${ticker}` } return formatted } @@ -177,12 +177,10 @@ export function shortenBalance (balance, decimalsToKeep = 1) { const stringBalance = convertedBalance.toString() if (stringBalance.split('.')[1].length > 3) { return convertedBalance.toFixed(3) - } else { - return stringBalance } - } else { - return convertedBalance.toFixed(decimalsToKeep) + return stringBalance } + return convertedBalance.toFixed(decimalsToKeep) } // Takes a BN and an ethereum currency name, diff --git a/ui/app/helpers/utils/util.test.js b/ui/app/helpers/utils/util.test.js index 8a2aa1ceb45e..0a930e413542 100644 --- a/ui/app/helpers/utils/util.test.js +++ b/ui/app/helpers/utils/util.test.js @@ -356,7 +356,7 @@ describe('util', function () { { args: ['0.0', 9], result: '0' }, { args: ['0.000000000000', 9], result: '0' }, { args: ['1', 9], result: '1' }, - { args: [1 ], result: '1' }, + { args: [1], result: '1' }, { args: ['1.0', 9], result: '1' }, { args: ['1.000000000', 9], result: '1' }, { args: ['000000001', 9], result: '1' }, diff --git a/ui/app/hooks/tests/useCancelTransaction.test.js b/ui/app/hooks/tests/useCancelTransaction.test.js index e27eb35864d2..a355ee5e5e11 100644 --- a/ui/app/hooks/tests/useCancelTransaction.test.js +++ b/ui/app/hooks/tests/useCancelTransaction.test.js @@ -8,7 +8,6 @@ import { useCancelTransaction } from '../useCancelTransaction' import { showModal } from '../../store/actions' import { increaseLastGasPrice } from '../../helpers/utils/confirm-tx.util' - describe('useCancelTransaction', function () { let useSelector const dispatch = sinon.spy() @@ -64,7 +63,6 @@ describe('useCancelTransaction', function () { }) }) - describe('when account has sufficient balance to cover gas', function () { before(function () { useSelector = sinon.stub(reactRedux, 'useSelector') @@ -108,7 +106,6 @@ describe('useCancelTransaction', function () { }) }) - after(function () { sinon.restore() }) diff --git a/ui/app/hooks/tests/useCurrencyDisplay.test.js b/ui/app/hooks/tests/useCurrencyDisplay.test.js index 7be42cd50db6..8b3f6910ae15 100644 --- a/ui/app/hooks/tests/useCurrencyDisplay.test.js +++ b/ui/app/hooks/tests/useCurrencyDisplay.test.js @@ -95,7 +95,6 @@ const tests = [ }, ] - describe('useCurrencyDisplay', function () { tests.forEach(({ input: { value, ...restProps }, result }) => { describe(`when input is { value: ${value}, decimals: ${restProps.numberOfDecimals}, denomation: ${restProps.denomination} }`, function () { @@ -111,7 +110,7 @@ describe('useCurrencyDisplay', function () { return undefined }) const hookReturn = renderHook(() => useCurrencyDisplay(value, restProps)) - const [ displayValue, parts ] = hookReturn.result.current + const [displayValue, parts] = hookReturn.result.current stub.restore() it(`should return ${result.displayValue} as displayValue`, function () { assert.equal(displayValue, result.displayValue) diff --git a/ui/app/hooks/tests/useTokenDisplayValue.test.js b/ui/app/hooks/tests/useTokenDisplayValue.test.js index ce596168f89f..ed0c81e4f714 100644 --- a/ui/app/hooks/tests/useTokenDisplayValue.test.js +++ b/ui/app/hooks/tests/useTokenDisplayValue.test.js @@ -118,7 +118,6 @@ const tests = [ }, ] - describe('useTokenDisplayValue', function () { tests.forEach((test, idx) => { describe(`when input is decimals: ${test.token.decimals} and value: ${test.tokenValue}`, function () { diff --git a/ui/app/hooks/tests/useTransactionDisplayData.test.js b/ui/app/hooks/tests/useTransactionDisplayData.test.js index 133c9291a972..a8eb15148a8e 100644 --- a/ui/app/hooks/tests/useTransactionDisplayData.test.js +++ b/ui/app/hooks/tests/useTransactionDisplayData.test.js @@ -11,9 +11,9 @@ import * as i18nhooks from '../useI18nContext' import { getMessage } from '../../helpers/utils/i18n-helper' import messages from '../../../../app/_locales/en/messages.json' - const expectedResults = [ - { title: 'Send ETH', + { + title: 'Send ETH', category: 'send', subtitle: 'To: 0xffe5...1a97', subtitleContainsOrigin: false, @@ -23,8 +23,10 @@ const expectedResults = [ recipientAddress: '0xffe5bc4e8f1f969934d773fa67da095d2e491a97', secondaryCurrency: '-1 ETH', isPending: false, - status: 'confirmed' }, - { title: 'Send ETH', + status: 'confirmed', + }, + { + title: 'Send ETH', category: 'send', subtitle: 'To: 0x0ccc...8848', subtitleContainsOrigin: false, @@ -34,8 +36,10 @@ const expectedResults = [ recipientAddress: '0x0ccc8aeeaf5ce790f3b448325981a143fdef8848', secondaryCurrency: '-2 ETH', isPending: false, - status: 'confirmed' }, - { title: 'Send ETH', + status: 'confirmed', + }, + { + title: 'Send ETH', category: 'send', subtitle: 'To: 0xffe5...1a97', subtitleContainsOrigin: false, @@ -45,8 +49,10 @@ const expectedResults = [ recipientAddress: '0xffe5bc4e8f1f969934d773fa67da095d2e491a97', secondaryCurrency: '-2 ETH', isPending: false, - status: 'confirmed' }, - { title: 'Receive', + status: 'confirmed', + }, + { + title: 'Receive', category: 'receive', subtitle: 'From: 0x31b9...4523', subtitleContainsOrigin: false, @@ -56,8 +62,10 @@ const expectedResults = [ recipientAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149', secondaryCurrency: '18.75 ETH', isPending: false, - status: 'confirmed' }, - { title: 'Receive', + status: 'confirmed', + }, + { + title: 'Receive', category: 'receive', subtitle: 'From: 0x9eca...a149', subtitleContainsOrigin: false, @@ -67,8 +75,10 @@ const expectedResults = [ recipientAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149', secondaryCurrency: '0 ETH', isPending: false, - status: 'confirmed' }, - { title: 'Receive', + status: 'confirmed', + }, + { + title: 'Receive', category: 'receive', subtitle: 'From: 0xee01...febb', subtitleContainsOrigin: false, @@ -78,7 +88,8 @@ const expectedResults = [ recipientAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149', secondaryCurrency: '1 ETH', isPending: false, - status: 'confirmed' }, + status: 'confirmed', + }, ] let useSelector, useI18nContext, useTokenFiatAmount @@ -105,9 +116,8 @@ describe('useTransactionDisplayData', function () { return 'ETH' } else if (selector === getCurrentCurrency) { return 'ETH' - } else { - return null } + return null }) }) transactions.forEach((transactionGroup, idx) => { diff --git a/ui/app/hooks/tests/useUserPreferencedCurrency.test.js b/ui/app/hooks/tests/useUserPreferencedCurrency.test.js index 65fe25c8e182..b5d7b47e9bbe 100644 --- a/ui/app/hooks/tests/useUserPreferencedCurrency.test.js +++ b/ui/app/hooks/tests/useUserPreferencedCurrency.test.js @@ -117,13 +117,11 @@ function getFakeUseSelector (state) { return state } else if (selector === getShouldShowFiat) { return state.showFiat - } else { - return state.nativeCurrency } + return state.nativeCurrency } } - describe('useUserPreferencedCurrency', function () { tests.forEach(({ params: { type, ...otherParams }, state, result }) => { describe(`when showFiat is ${state.showFiat}, useNativeCurrencyAsPrimary is ${state.useNativeCurrencyAsPrimaryCurrency} and type is ${type}`, function () { diff --git a/ui/app/hooks/useCancelTransaction.js b/ui/app/hooks/useCancelTransaction.js index 4dc19bae99c5..54769736093b 100644 --- a/ui/app/hooks/useCancelTransaction.js +++ b/ui/app/hooks/useCancelTransaction.js @@ -5,7 +5,6 @@ import { isBalanceSufficient } from '../pages/send/send.utils' import { getHexGasTotal, increaseLastGasPrice } from '../helpers/utils/confirm-tx.util' import { getConversionRate, getSelectedAccount } from '../selectors' - /** * Determine whether a transaction can be cancelled and provide a method to * kick off the process of cancellation. @@ -29,7 +28,6 @@ export function useCancelTransaction (transactionGroup) { return dispatch(showModal({ name: 'CANCEL_TRANSACTION', transactionId: id, originalGasPrice: gasPrice })) }, [dispatch, id, gasPrice]) - const hasEnoughCancelGas = primaryTransaction.txParams && isBalanceSufficient({ amount: '0x0', gasTotal: getHexGasTotal({ diff --git a/ui/app/hooks/useCurrencyDisplay.js b/ui/app/hooks/useCurrencyDisplay.js index 17568b874315..4e2c99e3fdb5 100644 --- a/ui/app/hooks/useCurrencyDisplay.js +++ b/ui/app/hooks/useCurrencyDisplay.js @@ -61,6 +61,5 @@ export function useCurrencyDisplay (inputValue, { displayValue, prefix, numberOf suffix = opts.suffix || toCurrency.toUpperCase() } - - return [`${prefix || ''}${value}${suffix ? ' ' + suffix : ''}`, { prefix, value, suffix }] + return [`${prefix || ''}${value}${suffix ? ` ${suffix}` : ''}`, { prefix, value, suffix }] } diff --git a/ui/app/hooks/useMetricEvent.js b/ui/app/hooks/useMetricEvent.js index a5a883b5f30c..a701bd9334a9 100644 --- a/ui/app/hooks/useMetricEvent.js +++ b/ui/app/hooks/useMetricEvent.js @@ -1,7 +1,6 @@ import { useContext, useCallback } from 'react' import { MetaMetricsContext } from '../contexts/metametrics' - export function useMetricEvent (config = {}, overrides = {}) { const metricsEvent = useContext(MetaMetricsContext) const trackEvent = useCallback(() => metricsEvent(config, overrides), [config, metricsEvent, overrides]) diff --git a/ui/app/hooks/useRetryTransaction.js b/ui/app/hooks/useRetryTransaction.js index 9b0a9e5f5340..1f3ffe7011c9 100644 --- a/ui/app/hooks/useRetryTransaction.js +++ b/ui/app/hooks/useRetryTransaction.js @@ -10,7 +10,6 @@ import { import { increaseLastGasPrice } from '../helpers/utils/confirm-tx.util' import { useMetricEvent } from './useMetricEvent' - /** * Provides a reusable hook that, given a transactionGroup, will return * a method for beginning the retry process diff --git a/ui/app/hooks/useTokenTracker.js b/ui/app/hooks/useTokenTracker.js index fe8eba61b678..55a92273bfac 100644 --- a/ui/app/hooks/useTokenTracker.js +++ b/ui/app/hooks/useTokenTracker.js @@ -3,7 +3,6 @@ import TokenTracker from '@metamask/eth-token-tracker' import { useSelector } from 'react-redux' import { getCurrentNetwork, getSelectedAddress } from '../selectors' - export function useTokenTracker (tokens) { const network = useSelector(getCurrentNetwork) const userAddress = useSelector(getSelectedAddress) @@ -57,7 +56,6 @@ export function useTokenTracker (tokens) { return teardownTracker }, [teardownTracker]) - // Effect to set loading state and initialize tracker when values change useEffect(() => { // This effect will only run initially and when: diff --git a/ui/app/hooks/useTransactionTimeRemaining.js b/ui/app/hooks/useTransactionTimeRemaining.js index 825d685522ec..10ac8545f138 100644 --- a/ui/app/hooks/useTransactionTimeRemaining.js +++ b/ui/app/hooks/useTransactionTimeRemaining.js @@ -64,7 +64,7 @@ export function useTransactionTimeRemaining ( captureException(error) return NaN } - }, [ currentGasPrice, gasPrices, estimatedTimes ]) + }, [currentGasPrice, gasPrices, estimatedTimes]) useEffect(() => { if ( diff --git a/ui/app/pages/add-token/tests/add-token.test.js b/ui/app/pages/add-token/tests/add-token.test.js index 6fff131ccfe8..8138845e78e3 100644 --- a/ui/app/pages/add-token/tests/add-token.test.js +++ b/ui/app/pages/add-token/tests/add-token.test.js @@ -4,7 +4,7 @@ import { Provider } from 'react-redux' import sinon from 'sinon' import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../test/lib/render-helpers' -import AddToken from '../index' +import AddToken from '..' describe('Add Token', function () { let wrapper @@ -58,7 +58,6 @@ describe('Add Token', function () { assert.equal(wrapper.find('AddToken').instance().state.customAddress, tokenAddress) }) - it('edits token symbol', function () { const tokenSymbol = 'META' const event = { target: { value: tokenSymbol } } diff --git a/ui/app/pages/add-token/token-search/token-search.component.js b/ui/app/pages/add-token/token-search/token-search.component.js index 82aaae3fc95d..460c7f15fc49 100644 --- a/ui/app/pages/add-token/token-search/token-search.component.js +++ b/ui/app/pages/add-token/token-search/token-search.component.js @@ -6,7 +6,7 @@ import InputAdornment from '@material-ui/core/InputAdornment' import TextField from '../../../components/ui/text-field' const contractList = Object.entries(contractMap) - .map(([address, tokenData]) => Object.assign({}, tokenData, { address })) + .map(([address, tokenData]) => ({ ...tokenData, address })) .filter((tokenData) => Boolean(tokenData.erc20)) const fuse = new Fuse(contractList, { diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js index 876fbd7614c7..28b04ba408e8 100644 --- a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js +++ b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js @@ -92,7 +92,7 @@ export default class ConfirmAddSuggestedToken extends Component {
{ Object.entries(pendingTokens) - .map(([ address, token ]) => { + .map(([address, token]) => { const { name, symbol, image } = token return ( diff --git a/ui/app/pages/confirm-add-token/confirm-add-token.component.js b/ui/app/pages/confirm-add-token/confirm-add-token.component.js index 2f98242ebf92..f79d962eb225 100644 --- a/ui/app/pages/confirm-add-token/confirm-add-token.component.js +++ b/ui/app/pages/confirm-add-token/confirm-add-token.component.js @@ -58,7 +58,7 @@ export default class ConfirmAddToken extends Component {
{ Object.entries(pendingTokens) - .map(([ address, token ]) => { + .map(([address, token]) => { const { name, symbol } = token return ( diff --git a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js index a73649484959..57d00021a3ae 100644 --- a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js +++ b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js @@ -17,7 +17,8 @@ import { getMostRecentOverviewPage } from '../../ducks/history/history' import ConfirmDecryptMessage from './confirm-decrypt-message.component' function mapStateToProps (state) { - const { confirmTransaction, + const { + confirmTransaction, metamask: { domainMetadata = {} }, } = state @@ -30,7 +31,7 @@ function mapStateToProps (state) { const fromAccount = getTargetAccountWithSendEtherInfo(state, from) return { - txData: txData, + txData, domainMetadata, fromAccount, requester: null, diff --git a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js index 1c376ff5aa04..7a0b2c37f325 100644 --- a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js +++ b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js @@ -18,7 +18,8 @@ import { getMostRecentOverviewPage } from '../../ducks/history/history' import ConfirmEncryptionPublicKey from './confirm-encryption-public-key.component' function mapStateToProps (state) { - const { confirmTransaction, + const { + confirmTransaction, metamask: { domainMetadata = {} }, } = state @@ -31,8 +32,8 @@ function mapStateToProps (state) { const fromAccount = getTargetAccountWithSendEtherInfo(state, from) return { - txData: txData, - domainMetadata: domainMetadata, + txData, + domainMetadata, fromAccount, requester: null, requesterAddress: null, diff --git a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js index 8aea19663d30..ca690a61ac45 100644 --- a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js +++ b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js @@ -89,12 +89,11 @@ export default class ConfirmTokenTransactionBase extends Component { if (typeof contractExchangeRate === 'undefined') { return formatCurrency(fiatTransactionTotal, currentCurrency) - } else { - const fiatTransactionAmount = this.getFiatTransactionAmount() - const fiatTotal = addFiat(fiatTransactionAmount, fiatTransactionTotal) - const roundedFiatTotal = roundExponential(fiatTotal) - return formatCurrency(roundedFiatTotal, currentCurrency) } + const fiatTransactionAmount = this.getFiatTransactionAmount() + const fiatTotal = addFiat(fiatTransactionAmount, fiatTransactionTotal) + const roundedFiatTotal = roundExponential(fiatTotal) + return formatCurrency(roundedFiatTotal, currentCurrency) } render () { diff --git a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js index f6e0a270de2e..8583ea238475 100644 --- a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js +++ b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js @@ -16,7 +16,6 @@ import { } from '../../helpers/utils/token-util' import ConfirmTokenTransactionBase from './confirm-token-transaction-base.component' - const mapStateToProps = (state, ownProps) => { const { match: { params = {} } } = ownProps const { id: paramsTransactionId } = params diff --git a/ui/app/pages/confirm-transaction/conf-tx.js b/ui/app/pages/confirm-transaction/conf-tx.js index 0d7be5418350..f9dbde2a5d64 100644 --- a/ui/app/pages/confirm-transaction/conf-tx.js +++ b/ui/app/pages/confirm-transaction/conf-tx.js @@ -105,7 +105,7 @@ class ConfirmTxScreen extends Component { log.info(`rendering a combined ${unconfTxList.length} unconf msgs & txs`) return transactionId - ? unconfTxList.find(({ id }) => id + '' === transactionId) + ? unconfTxList.find(({ id }) => `${id}` === transactionId) : unconfTxList[index] } @@ -195,7 +195,7 @@ class ConfirmTxScreen extends Component { let prevTx if (transactionId) { - prevTx = currentNetworkTxList.find(({ id }) => id + '' === transactionId) + prevTx = currentNetworkTxList.find(({ id }) => `${id}` === transactionId) } else { const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network) diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.component.js b/ui/app/pages/confirm-transaction/confirm-transaction.component.js index 69af2c226a1f..087b8e8b42ad 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.component.js +++ b/ui/app/pages/confirm-transaction/confirm-transaction.component.js @@ -95,13 +95,10 @@ export default class ConfirmTransaction extends Component { clearConfirmTransaction() getContractMethodData(data) setTransactionToConfirm(paramsTransactionId) - return } else if (prevProps.transactionId && !transactionId && !totalUnapprovedCount) { history.replace(mostRecentOverviewPage) - return } else if (prevProps.transactionId && transactionId && prevProps.transactionId !== transactionId) { history.replace(mostRecentOverviewPage) - return } } diff --git a/ui/app/pages/create-account/connect-hardware/account-list.js b/ui/app/pages/create-account/connect-hardware/account-list.js index cac29cdf004e..f1f54ddbcc73 100644 --- a/ui/app/pages/create-account/connect-hardware/account-list.js +++ b/ui/app/pages/create-account/connect-hardware/account-list.js @@ -181,7 +181,6 @@ class AccountList extends Component { } - AccountList.propTypes = { onPathChange: PropTypes.func.isRequired, selectedPath: PropTypes.string.isRequired, diff --git a/ui/app/pages/create-account/connect-hardware/index.js b/ui/app/pages/create-account/connect-hardware/index.js index 689b6058d9fd..4e537cacf032 100644 --- a/ui/app/pages/create-account/connect-hardware/index.js +++ b/ui/app/pages/create-account/connect-hardware/index.js @@ -29,7 +29,6 @@ class ConnectHardwareForm extends Component { this.setState({ accounts: newAccounts }) } - componentDidMount () { this.checkIfUnlocked() } @@ -99,7 +98,6 @@ class ConnectHardwareForm extends Component { newState.selectedAccount = null } - // Map accounts with balances newState.accounts = accounts.map((account) => { const normalizedAddress = account.address.toLowerCase() @@ -148,7 +146,7 @@ class ConnectHardwareForm extends Component { eventOpts: { category: 'Accounts', action: 'Connected Hardware Wallet', - name: 'Connected Account with: ' + device, + name: `Connected Account with: ${device}`, }, }) history.push(mostRecentOverviewPage) diff --git a/ui/app/pages/create-account/connect-hardware/select-hardware.js b/ui/app/pages/create-account/connect-hardware/select-hardware.js index 5c16bd452876..02c26c95e63b 100644 --- a/ui/app/pages/create-account/connect-hardware/select-hardware.js +++ b/ui/app/pages/create-account/connect-hardware/select-hardware.js @@ -133,7 +133,6 @@ export default class SelectHardware extends Component { ) } - scrollToTutorial = () => { if (this.referenceNode) { this.referenceNode.scrollIntoView({ behavior: 'smooth' }) diff --git a/ui/app/pages/create-account/import-account/json.js b/ui/app/pages/create-account/import-account/json.js index cd81fd8c6e87..1edaed355df0 100644 --- a/ui/app/pages/create-account/import-account/json.js +++ b/ui/app/pages/create-account/import-account/json.js @@ -107,7 +107,7 @@ class JsonImportSubview extends Component { const password = this.inputRef.current.value - importNewJsonAccount([ fileContents, password ]) + importNewJsonAccount([fileContents, password]) .then(({ selectedAddress }) => { if (selectedAddress) { history.push(mostRecentOverviewPage) diff --git a/ui/app/pages/create-account/import-account/private-key.js b/ui/app/pages/create-account/import-account/private-key.js index f23e7f418d0d..cbc155f815da 100644 --- a/ui/app/pages/create-account/import-account/private-key.js +++ b/ui/app/pages/create-account/import-account/private-key.js @@ -32,7 +32,7 @@ class PrivateKeyImportView extends Component { const privateKey = this.inputRef.current.value const { importNewAccount, history, displayWarning, mostRecentOverviewPage, setSelectedAddress, firstAddress } = this.props - importNewAccount('Private Key', [ privateKey ]) + importNewAccount('Private Key', [privateKey]) .then(({ selectedAddress }) => { if (selectedAddress) { this.context.metricsEvent({ @@ -131,7 +131,6 @@ export default compose( connect(mapStateToProps, mapDispatchToProps), )(PrivateKeyImportView) - function mapStateToProps (state) { return { error: state.appState.warning, @@ -142,8 +141,8 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - importNewAccount: (strategy, [ privateKey ]) => { - return dispatch(actions.importNewAccount(strategy, [ privateKey ])) + importNewAccount: (strategy, [privateKey]) => { + return dispatch(actions.importNewAccount(strategy, [privateKey])) }, displayWarning: (message) => dispatch(actions.displayWarning(message || null)), setSelectedAddress: (address) => dispatch(actions.setSelectedAddress(address)), diff --git a/ui/app/pages/create-account/tests/create-account.test.js b/ui/app/pages/create-account/tests/create-account.test.js index b12ecd36b7ed..f41aa27960ca 100644 --- a/ui/app/pages/create-account/tests/create-account.test.js +++ b/ui/app/pages/create-account/tests/create-account.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mountWithRouter } from '../../../../../test/lib/render-helpers' -import CreateAccountPage from '../index' +import CreateAccountPage from '..' describe('Create Account Page', function () { let wrapper diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js index a464bb79e3c9..95177e62af74 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js @@ -7,7 +7,7 @@ import ImportWithSeedPhrase from '../import-with-seed-phrase.component' function shallowRender (props = {}, context = {}) { return shallow(, { context: { - t: (str) => str + '_t', + t: (str) => `${str}_t`, metricsEvent: sinon.spy(), ...context, }, diff --git a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js index a6510553dafe..aa2611fc628b 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js +++ b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js @@ -56,22 +56,22 @@ export default class EndOfFlowScreen extends PureComponent { { t('endOfFlowMessage2') }
- { '• ' + t('endOfFlowMessage3') } + { `• ${t('endOfFlowMessage3')}` }
- { '• ' + t('endOfFlowMessage4') } + { `• ${t('endOfFlowMessage4')}` }
- { '• ' + t('endOfFlowMessage5') } + { `• ${t('endOfFlowMessage5')}` }
- { '• ' + t('endOfFlowMessage6') } + { `• ${t('endOfFlowMessage6')}` }
- { '• ' + t('endOfFlowMessage7') } + { `• ${t('endOfFlowMessage7')}` }
- { '*' + t('endOfFlowMessage8') }  + { `*${t('endOfFlowMessage8')}` }  { t('gdprMessagePrivacyPolicy') } - ]) + ]) }
diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js b/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js index c8a2491ffcfc..2f7ade5e5ba5 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js @@ -3,7 +3,7 @@ import React from 'react' import sinon from 'sinon' import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import MetaMetricsOptIn from '../index' +import MetaMetricsOptIn from '..' describe('MetaMetricsOptIn', function () { it('opt out of MetaMetrics', function () { diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index 8cc34e2af741..318e4fcb52db 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -247,7 +247,7 @@ export default class ConfirmSeedPhrase extends PureComponent { setDraggingSeedIndex={this.setDraggingSeedIndex} setHoveringIndex={this.setHoveringIndex} onDrop={this.onDrop} - droppable={!!word} + droppable={Boolean(word)} /> ) }) diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js index 9eea945a5024..66f227318159 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js @@ -121,5 +121,3 @@ const collectDrop = (connect, monitor) => { } export default DropTarget(SEEDWORD, seedTarget, collectDrop)(DragSource(SEEDWORD, seedSource, collectDrag)(DraggableSeed)) - - diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js index afcd771c46e5..0130e3a34ce7 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js @@ -82,7 +82,8 @@ export default class RevealSeedPhrase extends PureComponent { className={classnames( 'reveal-seed-phrase__secret-words notranslate', { 'reveal-seed-phrase__secret-words--hidden': !isShowingSeedPhrase, - })} + }, + )} > { seedPhrase }
diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js index 62d64d5b68d8..152e2493533d 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import RevealSeedPhrase from '../index' +import RevealSeedPhrase from '..' describe('Reveal Seed Phrase', function () { let wrapper diff --git a/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js index 78c77d3a77ce..200d2867f671 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js +++ b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js @@ -9,7 +9,7 @@ function shallowRender (props = {}, context = {}) { , { context: { - t: (str) => str + '_t', + t: (str) => `${str}_t`, ...context, }, }, @@ -152,7 +152,6 @@ describe('ConfirmSeedPhrase Component', function () { const sorted = root.state().sortedSeedWords const seeds = root.find('.confirm-seed-phrase__seed-word--sorted') - originalSeed.forEach((seed) => { const seedIndex = sorted.findIndex((s) => s === seed) seeds.at(seedIndex).simulate('click') diff --git a/ui/app/pages/first-time-flow/select-action/select-action.component.js b/ui/app/pages/first-time-flow/select-action/select-action.component.js index 5379952f1aaf..f66eda3a5fb9 100644 --- a/ui/app/pages/first-time-flow/select-action/select-action.component.js +++ b/ui/app/pages/first-time-flow/select-action/select-action.component.js @@ -45,7 +45,6 @@ export default class SelectAction extends PureComponent {
-
{ t('newToMetaMask') } diff --git a/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js b/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js index 6d7954276efa..baeda007b064 100644 --- a/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js +++ b/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import SelectAction from '../index' +import SelectAction from '..' describe('Selection Action', function () { let wrapper diff --git a/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js b/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js index 0e3a762a80b4..c3a584f0c654 100644 --- a/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js +++ b/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js @@ -3,7 +3,7 @@ import React from 'react' import sinon from 'sinon' import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import Welcome from '../index' +import Welcome from '..' describe('Welcome', function () { const mockStore = { diff --git a/ui/app/pages/home/home.component.js b/ui/app/pages/home/home.component.js index 880e438e0be1..92af97d3b34c 100644 --- a/ui/app/pages/home/home.component.js +++ b/ui/app/pages/home/home.component.js @@ -158,7 +158,7 @@ export default class Home extends PureComponent { threeBoxLastUpdated && showRestorePrompt ? ( ) } + renderPopover = () => { const { setConnectedStatusPopoverHasBeenShown } = this.props const { t } = this.context diff --git a/ui/app/pages/lock/tests/lock.test.js b/ui/app/pages/lock/tests/lock.test.js index 77a1a720312b..4f4c870e72d3 100644 --- a/ui/app/pages/lock/tests/lock.test.js +++ b/ui/app/pages/lock/tests/lock.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mountWithRouter } from '../../../../../test/lib/render-helpers' -import Lock from '../index' +import Lock from '..' describe('Lock', function () { diff --git a/ui/app/pages/mobile-sync/mobile-sync.component.js b/ui/app/pages/mobile-sync/mobile-sync.component.js index 51ad3e6b72bc..be0d3dbe2753 100644 --- a/ui/app/pages/mobile-sync/mobile-sync.component.js +++ b/ui/app/pages/mobile-sync/mobile-sync.component.js @@ -29,7 +29,6 @@ export default class MobileSyncPage extends Component { keyrings: PropTypes.array, } - state = { screen: PASSWORD_PROMPT_SCREEN, password: '', @@ -199,7 +198,8 @@ export default class MobileSyncPage extends Component { } else { resolve() } - }) + }, + ) }) } @@ -263,7 +263,6 @@ export default class MobileSyncPage extends Component { }) } - componentWillUnmount () { this.clearTimeouts() this.disconnectWebsockets() diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js index 76b6a5570cff..07b4c95f88da 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js @@ -222,7 +222,6 @@ export default class AddRecipient extends Component { ) } - if (toWarning) { return ( !!name), + contacts: addressBook.filter(({ name }) => Boolean(name)), nonContacts: addressBook.filter(({ name }) => !name), } } diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js index 4607ebdbb7a5..c3dce42d8a0e 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js @@ -10,7 +10,6 @@ import log from 'loglevel' import { ellipsify } from '../../send.utils' import { isValidDomainName, isValidAddress, isValidAddressHead } from '../../../../helpers/utils/util' - // Local Constants const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const ZERO_X_ERROR_ADDRESS = '0x' @@ -188,7 +187,6 @@ export default class EnsInput extends Component { const { className, selectedAddress, selectedName, contact = {} } = this.props const name = contact.name || selectedName - return (
- ), { context: { t: (str) => str + '_t' } }) + ), { context: { t: (str) => `${str}_t` } }) instance = wrapper.instance() }) @@ -94,7 +94,6 @@ describe('AddRecipient Component', function () { const xferLink = wrapper.find('.send__select-recipient-wrapper__list__link') assert.equal(xferLink.length, 1) - const groups = wrapper.find('RecipientGroup') assert.equal(groups.shallow().find('.send__select-recipient-wrapper__group').length, 1) }) diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js index 7ba387c515c5..cc4546f58fdd 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js @@ -32,7 +32,7 @@ describe('AmountMaxButton Component', function () { /> ), { context: { - t: (str) => str + '_t', + t: (str) => `${str}_t`, metricsEvent: () => undefined, }, }) diff --git a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js index fa1e5a2aab49..5b025e98582a 100644 --- a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js @@ -160,7 +160,7 @@ function shallowRenderSendAmountRow () { updateSendAmountError={updateSendAmountError} updateGas={() => undefined} /> - ), { context: { t: (str) => str + '_t' } }) + ), { context: { t: (str) => `${str}_t` } }) const instance = wrapper.instance() const updateAmount = sinon.spy(instance, 'updateAmount') const updateGas = sinon.spy(instance, 'updateGas') diff --git a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js index 4920156f0ca9..831bf9ac7c2a 100644 --- a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js +++ b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js @@ -124,7 +124,6 @@ export default class SendAssetRow extends Component { ) } - renderAsset (token, insideDropdown = false) { const { address, symbol } = token const { t } = this.context diff --git a/ui/app/pages/send/send-content/send-content.container.js b/ui/app/pages/send/send-content/send-content.container.js index 5cde49de9622..3bbc36a49a46 100644 --- a/ui/app/pages/send/send-content/send-content.container.js +++ b/ui/app/pages/send/send-content/send-content.container.js @@ -12,7 +12,7 @@ function mapStateToProps (state) { const ownedAccounts = accountsWithSendEtherInfoSelector(state) const to = getSendTo(state) return { - isOwnedAccount: !!ownedAccounts.find(({ address }) => address.toLowerCase() === to.toLowerCase()), + isOwnedAccount: Boolean(ownedAccounts.find(({ address }) => address.toLowerCase() === to.toLowerCase())), contact: getAddressBookEntry(state, to), to, } diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js index b479efb9d0ce..d5f6716a75f5 100644 --- a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js @@ -24,7 +24,7 @@ describe('GasFeeDisplay Component', function () { showGasButtonGroup={propsMethodSpies.showCustomizeGasModal} onReset={propsMethodSpies.onReset} /> - ), { context: { t: (str) => str + '_t' } }) + ), { context: { t: (str) => `${str}_t` } }) }) afterEach(function () { diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js index 622bae0c4549..8df7bbbfaebf 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js +++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js @@ -151,9 +151,8 @@ export default class SendGasRow extends Component { return advancedGasInputs } else if (gasButtonGroupShown) { return gasPriceButtonGroup - } else { - return gasFeeDisplay } + return gasFeeDisplay } render () { diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js index 51a17a40c0fd..b215087fe08d 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js +++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js @@ -36,7 +36,6 @@ import { import { showModal, setGasPrice, setGasLimit, setGasTotal, updateSendAmount } from '../../../../store/actions' import SendGasRow from './send-gas-row.component' - export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(SendGasRow) function mapStateToProps (state) { diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js index f80b294f7bfb..e078ed25a307 100644 --- a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js @@ -33,7 +33,7 @@ describe('SendGasRow Component', function () { anotherGasPriceButtonGroupProp: 'bar', }} /> - ), { context: { t: (str) => str + '_t', metricsEvent: () => ({}) } }) + ), { context: { t: (str) => `${str}_t`, metricsEvent: () => ({}) } }) wrapper.setProps({ isMainnet: true }) }) diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js index 1255aac49be6..5e2b261e06a1 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js @@ -13,7 +13,7 @@ describe('SendRowErrorMessage Component', function () { errors={{ error1: 'abc', error2: 'def' }} errorType="error3" /> - ), { context: { t: (str) => str + '_t' } }) + ), { context: { t: (str) => `${str}_t` } }) }) it('should render null if the passed errors do not contain an error of errorType', function () { diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js index 8c57cf268f1f..5e87735291bc 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js @@ -20,7 +20,8 @@ describe('send-row-error-message container', function () { it('should map the correct properties to props', function () { assert.deepEqual(mapStateToProps('mockState', { errorType: 'someType' }), { errors: 'mockErrors:mockState', - errorType: 'someType' }) + errorType: 'someType', + }) }) }) diff --git a/ui/app/pages/send/send-content/tests/send-content-component.test.js b/ui/app/pages/send/send-content/tests/send-content-component.test.js index 3687e8711c02..dff83a6106f4 100644 --- a/ui/app/pages/send/send-content/tests/send-content-component.test.js +++ b/ui/app/pages/send/send-content/tests/send-content-component.test.js @@ -18,7 +18,7 @@ describe('SendContent Component', function () { , - { context: { t: (str) => str + '_t' } }, + { context: { t: (str) => `${str}_t` } }, ) }) diff --git a/ui/app/pages/send/send-footer/send-footer.utils.js b/ui/app/pages/send/send-footer/send-footer.utils.js index c92c73a309df..2fec545dc940 100644 --- a/ui/app/pages/send/send-footer/send-footer.utils.js +++ b/ui/app/pages/send/send-footer/send-footer.utils.js @@ -61,7 +61,7 @@ export function constructUpdatedTx ({ data: ( TOKEN_TRANSFER_FUNCTION_SIGNATURE + Array.prototype.map.call( ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]), - (x) => ('00' + x.toString(16)).slice(-2), + (x) => (`00${x.toString(16)}`).slice(-2), ).join('') ), })) diff --git a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js index ef502e0aa612..0ddd961eec5a 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js @@ -83,7 +83,6 @@ describe('SendFooter Component', function () { }) }) - describe('formShouldBeDisabled()', function () { const config = { 'should return true if inError is truthy': { diff --git a/ui/app/pages/send/send-footer/tests/send-footer-container.test.js b/ui/app/pages/send/send-footer/tests/send-footer-container.test.js index 54040bfd7402..314503e0d82c 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-container.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-container.test.js @@ -97,7 +97,7 @@ describe('send-footer container', function () { ) assert.deepEqual( actionSpies.signTokenTx.getCall(0).args, - [ '0xabc', 'mockTo', 'mockAmount', { value: 'mockAmount' } ], + ['0xabc', 'mockTo', 'mockAmount', { value: 'mockAmount' }], ) }) @@ -125,7 +125,7 @@ describe('send-footer container', function () { ) assert.deepEqual( actionSpies.signTx.getCall(0).args, - [ { value: 'mockAmount' } ], + [{ value: 'mockAmount' }], ) }) }) @@ -168,7 +168,7 @@ describe('send-footer container', function () { assert.equal(utilsStubs.addressIsNew.getCall(0).args[0], 'mockToAccounts') assert.deepEqual( actionSpies.addToAddressBook.getCall(0).args, - [ '0xmockNewAddress', 'mockNickname' ], + ['0xmockNewAddress', 'mockNickname'], ) }) }) diff --git a/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js b/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js index c84856c3ce01..b0f5f6586458 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js @@ -5,7 +5,7 @@ import { TOKEN_TRANSFER_FUNCTION_SIGNATURE } from '../../send.constants' const stubs = { rawEncode: sinon.stub().callsFake((arr1, arr2) => { - return [ ...arr1, ...arr2 ] + return [...arr1, ...arr2] }), } diff --git a/ui/app/pages/send/send.component.js b/ui/app/pages/send/send.component.js index 882c2edd65de..ff6a54e58e5e 100644 --- a/ui/app/pages/send/send.component.js +++ b/ui/app/pages/send/send.component.js @@ -14,7 +14,6 @@ import SendContent from './send-content' import SendFooter from './send-footer' import EnsInput from './send-content/add-recipient/ens-input' - export default class SendTransactionScreen extends Component { static propTypes = { diff --git a/ui/app/pages/send/send.utils.js b/ui/app/pages/send/send.utils.js index fe208f7be85d..32dc1939a9a9 100644 --- a/ui/app/pages/send/send.utils.js +++ b/ui/app/pages/send/send.utils.js @@ -21,7 +21,6 @@ import { TOKEN_TRANSFER_FUNCTION_SIGNATURE, } from './send.constants' - export { addGasBuffer, calcGasTotal, @@ -69,7 +68,7 @@ function isBalanceSufficient ({ { value: totalAmount, fromNumericBase: 'hex', - conversionRate: conversionRate, + conversionRate, fromCurrency: primaryCurrency, }, ) @@ -262,9 +261,9 @@ async function estimateGas ({ if (simulationFailed) { const estimateWithBuffer = addGasBuffer(paramsForGasEstimate.gas, blockGasLimit, 1.5) return ethUtil.addHexPrefix(estimateWithBuffer) - } else { - throw error } + throw error + } } @@ -306,7 +305,7 @@ function generateTokenTransferData ({ toAddress = '0x0', amount = '0x0', sendTok } return TOKEN_TRANSFER_FUNCTION_SIGNATURE + Array.prototype.map.call( abi.rawEncode(['address', 'uint256'], [toAddress, ethUtil.addHexPrefix(amount)]), - (x) => ('00' + x.toString(16)).slice(-2), + (x) => (`00${x.toString(16)}`).slice(-2), ).join('') } diff --git a/ui/app/pages/send/tests/send-container.test.js b/ui/app/pages/send/tests/send-container.test.js index ae9cfd2d4251..6cc39fe310c0 100644 --- a/ui/app/pages/send/tests/send-container.test.js +++ b/ui/app/pages/send/tests/send-container.test.js @@ -67,7 +67,7 @@ describe('send container', function () { it('should dispatch an updateGasData action when editingTransactionId is falsy', function () { const { gasPrice, selectedAddress, sendToken, blockGasLimit, to, value, data } = mockProps mapDispatchToPropsObject.updateAndSetGasLimit( - Object.assign({}, mockProps, { editingTransactionId: false }), + { ...mockProps, editingTransactionId: false }, ) assert(dispatchSpy.calledOnce) assert.deepEqual( @@ -85,7 +85,7 @@ describe('send container', function () { } it('should dispatch an action', function () { - mapDispatchToPropsObject.updateSendTokenBalance(Object.assign({}, mockProps)) + mapDispatchToPropsObject.updateSendTokenBalance({ ...mockProps }) assert(dispatchSpy.calledOnce) assert.deepEqual( actionSpies.updateSendTokenBalance.getCall(0).args[0], diff --git a/ui/app/pages/send/tests/send-utils.test.js b/ui/app/pages/send/tests/send-utils.test.js index 1640c80463e0..0d23947ff981 100644 --- a/ui/app/pages/send/tests/send-utils.test.js +++ b/ui/app/pages/send/tests/send-utils.test.js @@ -22,7 +22,7 @@ const stubs = { conversionUtil: sinon.stub().callsFake((val) => parseInt(val, 16)), conversionGTE: sinon.stub().callsFake((obj1, obj2) => obj1.value >= obj2.value), multiplyCurrencies: sinon.stub().callsFake((a, b) => `${a}x${b}`), - calcTokenAmount: sinon.stub().callsFake((a, d) => 'calc:' + a + d), + calcTokenAmount: sinon.stub().callsFake((a, d) => `calc:${a}${d}`), rawEncode: sinon.stub().returns([16, 1100]), conversionGreaterThan: sinon.stub().callsFake((obj1, obj2) => obj1.value > obj2.value), conversionLessThan: sinon.stub().callsFake((obj1, obj2) => obj1.value < obj2.value), @@ -70,7 +70,7 @@ describe('send utils', function () { toNumericBase: 'hex', multiplicandBase: 16, multiplierBase: 16, - } ], + }], ) }) }) @@ -327,32 +327,32 @@ describe('send utils', function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], - Object.assign({ gasPrice: undefined, value: undefined }, baseExpectedCall), + { gasPrice: undefined, value: undefined, ...baseExpectedCall }, ) assert.equal(result, '0xabc16') }) it('should call ethQuery.estimateGas with the expected params when initialGasLimitHex is lower than the upperGasLimit', async function () { - const result = await estimateGas(Object.assign({}, baseMockParams, { blockGasLimit: '0xbcd' })) + const result = await estimateGas({ ...baseMockParams, blockGasLimit: '0xbcd' }) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], - Object.assign({ gasPrice: undefined, value: undefined }, baseExpectedCall, { gas: '0xbcdx0.95' }), + { gasPrice: undefined, value: undefined, ...baseExpectedCall, gas: '0xbcdx0.95' }, ) assert.equal(result, '0xabc16x1.5') }) it('should call ethQuery.estimateGas with a value of 0x0 and the expected data and to if passed a sendToken', async function () { - const result = await estimateGas(Object.assign({ data: 'mockData', sendToken: { address: 'mockAddress' } }, baseMockParams)) + const result = await estimateGas({ data: 'mockData', sendToken: { address: 'mockAddress' }, ...baseMockParams }) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], - Object.assign({}, baseExpectedCall, { - gasPrice: undefined, + { + ...baseExpectedCall, gasPrice: undefined, value: '0x0', data: '0xa9059cbb104c', to: 'mockAddress', - }), + }, ) assert.equal(result, '0xabc16') }) @@ -371,46 +371,40 @@ describe('send utils', function () { it(`should return ${SIMPLE_GAS_COST} if ethQuery.getCode does not return '0x'`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) - const result = await estimateGas(Object.assign({}, baseMockParams, { to: '0x123' })) + const result = await estimateGas({ ...baseMockParams, to: '0x123' }) assert.equal(result, SIMPLE_GAS_COST) }) it(`should return ${SIMPLE_GAS_COST} if not passed a sendToken or truthy to address`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) - const result = await estimateGas(Object.assign({}, baseMockParams, { to: null })) + const result = await estimateGas({ ...baseMockParams, to: null }) assert.equal(result, SIMPLE_GAS_COST) }) it(`should not return ${SIMPLE_GAS_COST} if passed a sendToken`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) - const result = await estimateGas(Object.assign({}, baseMockParams, { to: '0x123', sendToken: { address: '0x0' } })) + const result = await estimateGas({ ...baseMockParams, to: '0x123', sendToken: { address: '0x0' } }) assert.notEqual(result, SIMPLE_GAS_COST) }) it(`should return ${BASE_TOKEN_GAS_COST} if passed a sendToken but no to address`, async function () { - const result = await estimateGas(Object.assign({}, baseMockParams, { to: null, sendToken: { address: '0x0' } })) + const result = await estimateGas({ ...baseMockParams, to: null, sendToken: { address: '0x0' } }) assert.equal(result, BASE_TOKEN_GAS_COST) }) it(`should return the adjusted blockGasLimit if it fails with a 'Transaction execution error.'`, async function () { - const result = await estimateGas(Object.assign({}, baseMockParams, { - to: 'isContract willFailBecauseOf:Transaction execution error.', - })) + const result = await estimateGas({ ...baseMockParams, to: 'isContract willFailBecauseOf:Transaction execution error.' }) assert.equal(result, '0x64x0.95') }) it(`should return the adjusted blockGasLimit if it fails with a 'gas required exceeds allowance or always failing transaction.'`, async function () { - const result = await estimateGas(Object.assign({}, baseMockParams, { - to: 'isContract willFailBecauseOf:gas required exceeds allowance or always failing transaction.', - })) + const result = await estimateGas({ ...baseMockParams, to: 'isContract willFailBecauseOf:gas required exceeds allowance or always failing transaction.' }) assert.equal(result, '0x64x0.95') }) it(`should reject other errors`, async function () { try { - await estimateGas(Object.assign({}, baseMockParams, { - to: 'isContract willFailBecauseOf:some other error', - })) + await estimateGas({ ...baseMockParams, to: 'isContract willFailBecauseOf:some other error' }) } catch (err) { assert.equal(err.message, 'some other error') } diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js index 898bfad18dd9..055ad29777e0 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js @@ -491,7 +491,7 @@ function addUrlProtocolPrefix (urlString) { if (!urlString.match( /(^http:\/\/)|(^https:\/\/)/u, )) { - return 'https://' + urlString + return `https://${urlString}` } return urlString } diff --git a/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js b/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js index fc6dc535468a..74cc1b89b76f 100644 --- a/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js +++ b/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js @@ -30,7 +30,7 @@ export default class ContactListTab extends Component { renderAddresses () { const { addressBook, history, selectedAddress } = this.props - const contacts = addressBook.filter(({ name }) => !!name) + const contacts = addressBook.filter(({ name }) => Boolean(name)) const nonContacts = addressBook.filter(({ name }) => !name) return ( diff --git a/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js b/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js index 8871830a8443..597b74683123 100644 --- a/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js +++ b/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js @@ -15,7 +15,6 @@ import { } from '../../../helpers/constants/routes' import ContactListTab from './contact-list-tab.component' - const mapStateToProps = (state, ownProps) => { const { location } = ownProps const { pathname } = location diff --git a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js index faa670f054a5..6256c11349bc 100644 --- a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js +++ b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js @@ -12,11 +12,11 @@ import { useCopyToClipboard } from '../../../../hooks/useCopyToClipboard' function quadSplit (address) { return ( - '0x ' + - address - .slice(2) - .match(/.{1,4}/ug) - .join(' ') + `0x ${ + address + .slice(2) + .match(/.{1,4}/ug) + .join(' ')}` ) } diff --git a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js index 3ca23e7f9cee..024af3a31384 100644 --- a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js +++ b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js @@ -207,10 +207,9 @@ export default class NetworkForm extends PureComponent { validateChainId = (chainId) => { // eslint-disable-next-line radix - this.setErrorTo('chainId', !!chainId && Number.isNaN(parseInt(chainId)) + this.setErrorTo('chainId', Boolean(chainId) && Number.isNaN(parseInt(chainId)) ? `${this.context.t('invalidInput')} chainId` - : '', - ) + : '') } isValidWhenAppended = (url) => { diff --git a/ui/app/pages/settings/networks-tab/networks-tab.component.js b/ui/app/pages/settings/networks-tab/networks-tab.component.js index 40bbc0c36bf7..c9450e4c5ffb 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.component.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.component.js @@ -104,7 +104,7 @@ export default class NetworksTab extends PureComponent { return (
{ setNetworksTabAddMode(false) diff --git a/ui/app/pages/settings/networks-tab/networks-tab.container.js b/ui/app/pages/settings/networks-tab/networks-tab.container.js index 282078246dac..5b35f3ba53ea 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.container.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.container.js @@ -36,7 +36,7 @@ const mapStateToProps = (state) => { } }) - const networksToRender = [ ...defaultNetworks, ...frequentRpcNetworkListDetails ] + const networksToRender = [...defaultNetworks, ...frequentRpcNetworkListDetails] let selectedNetwork = networksToRender.find((network) => network.rpcUrl === networksTabSelectedRpcUrl) || {} const networkIsSelected = Boolean(selectedNetwork.rpcUrl) diff --git a/ui/app/pages/settings/security-tab/tests/security-tab.test.js b/ui/app/pages/settings/security-tab/tests/security-tab.test.js index 1fa1b2eb8ea8..fd1b8c08535e 100644 --- a/ui/app/pages/settings/security-tab/tests/security-tab.test.js +++ b/ui/app/pages/settings/security-tab/tests/security-tab.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import SecurityTab from '../index' +import SecurityTab from '..' describe('Security Tab', function () { let wrapper diff --git a/ui/app/pages/settings/settings-tab/settings-tab.component.js b/ui/app/pages/settings/settings-tab/settings-tab.component.js index 2e3c7f220e8c..c7d984f88f14 100644 --- a/ui/app/pages/settings/settings-tab/settings-tab.component.js +++ b/ui/app/pages/settings/settings-tab/settings-tab.component.js @@ -101,7 +101,6 @@ export default class SettingsTab extends PureComponent { ) } - renderBlockieOptIn () { const { t } = this.context const { useBlockie, setUseBlockie } = this.props diff --git a/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js index 290d5081a9f2..1803ff5900a3 100644 --- a/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js +++ b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import SettingsTab from '../index' +import SettingsTab from '..' describe('Settings Tab', function () { let wrapper diff --git a/ui/app/pages/unlock-page/tests/unlock-page.test.js b/ui/app/pages/unlock-page/tests/unlock-page.test.js index 33ae361caa57..48bb2b78d275 100644 --- a/ui/app/pages/unlock-page/tests/unlock-page.test.js +++ b/ui/app/pages/unlock-page/tests/unlock-page.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import UnlockPage from '../index' +import UnlockPage from '..' describe('Unlock Page', function () { let wrapper @@ -19,7 +19,6 @@ describe('Unlock Page', function () { showOptInModal: sinon.spy(), } - beforeEach(function () { wrapper = mount( diff --git a/ui/app/selectors/confirm-transaction.js b/ui/app/selectors/confirm-transaction.js index 553a44307cfd..93c876ef717c 100644 --- a/ui/app/selectors/confirm-transaction.js +++ b/ui/app/selectors/confirm-transaction.js @@ -121,7 +121,6 @@ export const unconfirmedTransactionsCountSelector = createSelector( }, ) - export const currentCurrencySelector = (state) => state.metamask.currentCurrency export const conversionRateSelector = (state) => state.metamask.conversionRate diff --git a/ui/app/selectors/custom-gas.js b/ui/app/selectors/custom-gas.js index f8c4ecf4950e..b3c1b1dcdc1a 100644 --- a/ui/app/selectors/custom-gas.js +++ b/ui/app/selectors/custom-gas.js @@ -132,7 +132,6 @@ export function getRenderableEthFee (estimate, gasLimit, numberOfDecimals = 9) { return formatETHFee(fee) } - export function getRenderableConvertedCurrencyFee (estimate, gasLimit, convertedCurrency, conversionRate) { const value = conversionUtil(estimate, { fromNumericBase: 'dec', toNumericBase: 'hex' }) const fee = basicPriceEstimateToETHTotal(value, gasLimit) @@ -164,8 +163,8 @@ export function formatTimeEstimate (totalSeconds, greaterThanMax, lessThanMin) { symbol = '> ' } - const formattedMin = `${minutes ? minutes + ' min' : ''}` - const formattedSec = `${seconds ? seconds + ' sec' : ''}` + const formattedMin = `${minutes ? `${minutes} min` : ''}` + const formattedSec = `${seconds ? `${seconds} sec` : ''}` const formattedCombined = formattedMin && formattedSec ? `${symbol}${formattedMin} ${formattedSec}` : symbol + [formattedMin, formattedSec].find((t) => t) @@ -199,7 +198,7 @@ export function getRenderableBasicEstimateData (state, gasLimit) { const { showFiatInTestnets } = getPreferences(state) const isMainnet = getIsMainnet(state) - const showFiat = (isMainnet || !!showFiatInTestnets) + const showFiat = (isMainnet || Boolean(showFiatInTestnets)) const { conversionRate } = state.metamask const currentCurrency = getCurrentCurrency(state) const { @@ -253,7 +252,7 @@ export function getRenderableEstimateDataForSmallButtonsFromGWEI (state) { const { showFiatInTestnets } = getPreferences(state) const isMainnet = getIsMainnet(state) - const showFiat = (isMainnet || !!showFiatInTestnets) + const showFiat = (isMainnet || Boolean(showFiatInTestnets)) const gasLimit = state.metamask.send.gasLimit || getCustomGasLimit(state) || '0x5208' const { conversionRate } = state.metamask const currentCurrency = getCurrentCurrency(state) diff --git a/ui/app/selectors/permissions.js b/ui/app/selectors/permissions.js index 22247e60710a..bc7bcabe49b7 100644 --- a/ui/app/selectors/permissions.js +++ b/ui/app/selectors/permissions.js @@ -249,7 +249,7 @@ export function getPermissionsForActiveTab (state) { export function getLastConnectedInfo (state) { const { permissionsHistory = {} } = state.metamask return Object.keys(permissionsHistory).reduce((acc, origin) => { - const ethAccountsHistory = JSON.parse(JSON.stringify(permissionsHistory[origin]['eth_accounts'])) + const ethAccountsHistory = JSON.parse(JSON.stringify(permissionsHistory[origin].eth_accounts)) return { ...acc, [origin]: ethAccountsHistory, diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index 9be3b1adc3f1..3789e38543c7 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -63,11 +63,10 @@ export const getMetaMaskAccounts = createSelector( }, } - } else { - return { - ...selectedAccounts, - [accountID]: account, - } + } + return { + ...selectedAccounts, + [accountID]: account, } }, {}), ) @@ -119,7 +118,7 @@ export const getMetaMaskAccountsOrdered = createSelector( getMetaMaskAccounts, (keyrings, identities, accounts) => keyrings .reduce((list, keyring) => list.concat(keyring.accounts), []) - .filter((address) => !!identities[address]) + .filter((address) => Boolean(identities[address])) .map((address) => ({ ...identities[address], ...accounts[address] })), ) @@ -180,7 +179,7 @@ export function accountsWithSendEtherInfoSelector (state) { const identities = getMetaMaskIdentities(state) const accountsWithSendEtherInfo = Object.entries(identities).map(([key, identity]) => { - return Object.assign({}, identity, accounts[key]) + return { ...identity, ...accounts[key] } }) return accountsWithSendEtherInfo @@ -258,7 +257,7 @@ export function isEthereumNetwork (state) { GOERLI, } = NETWORK_TYPES - return [ KOVAN, MAINNET, RINKEBY, ROPSTEN, GOERLI].includes(networkType) + return [KOVAN, MAINNET, RINKEBY, ROPSTEN, GOERLI].includes(networkType) } export function getPreferences ({ metamask }) { diff --git a/ui/app/selectors/send.js b/ui/app/selectors/send.js index dd17f90aca3e..3fcd3e7609ff 100644 --- a/ui/app/selectors/send.js +++ b/ui/app/selectors/send.js @@ -157,9 +157,8 @@ export function getTitleKey (state) { return 'edit' } else if (isToken) { return 'sendTokens' - } else { - return 'sendETH' } + return 'sendETH' } export function isSendFormInError (state) { diff --git a/ui/app/selectors/tests/custom-gas.test.js b/ui/app/selectors/tests/custom-gas.test.js index 7e3e6c0852fd..6ae6119c4b22 100644 --- a/ui/app/selectors/tests/custom-gas.test.js +++ b/ui/app/selectors/tests/custom-gas.test.js @@ -52,22 +52,30 @@ describe('custom-gas selectors', function () { describe('getEstimatedGasPrices', function () { it('should return price and time estimates', function () { - const mockState = { gas: { priceAndTimeEstimates: [ - { gasprice: 12, somethingElse: 20 }, - { gasprice: 22, expectedTime: 30 }, - { gasprice: 32, somethingElse: 40 }, - ] } } + const mockState = { + gas: { + priceAndTimeEstimates: [ + { gasprice: 12, somethingElse: 20 }, + { gasprice: 22, expectedTime: 30 }, + { gasprice: 32, somethingElse: 40 }, + ], + }, + } assert.deepEqual(getEstimatedGasPrices(mockState), [12, 22, 32]) }) }) describe('getEstimatedGasTimes', function () { it('should return price and time estimates', function () { - const mockState = { gas: { priceAndTimeEstimates: [ - { somethingElse: 12, expectedTime: 20 }, - { gasPrice: 22, expectedTime: 30 }, - { somethingElse: 32, expectedTime: 40 }, - ] } } + const mockState = { + gas: { + priceAndTimeEstimates: [ + { somethingElse: 12, expectedTime: 20 }, + { gasPrice: 22, expectedTime: 30 }, + { somethingElse: 32, expectedTime: 40 }, + ], + }, + } assert.deepEqual(getEstimatedGasTimes(mockState), [20, 30, 40]) }) }) diff --git a/ui/app/selectors/tests/send.test.js b/ui/app/selectors/tests/send.test.js index d232baf1bb06..529e039582e0 100644 --- a/ui/app/selectors/tests/send.test.js +++ b/ui/app/selectors/tests/send.test.js @@ -37,11 +37,11 @@ import { import mockState from './send-selectors-test-data' describe('send selectors', function () { - const tempGlobalEth = Object.assign({}, global.eth) + const tempGlobalEth = { ...global.eth } beforeEach(function () { global.eth = { contract: sinon.stub().returns({ - at: (address) => 'mockAt:' + address, + at: (address) => `mockAt:${address}`, }), } }) @@ -217,9 +217,9 @@ describe('send selectors', function () { }) it('should return null if send token is not set', function () { - const modifiedMetamaskState = Object.assign({}, mockState.metamask, { send: {} }) + const modifiedMetamaskState = { ...mockState.metamask, send: {} } assert.equal( - getSendTokenContract(Object.assign({}, mockState, { metamask: modifiedMetamaskState })), + getSendTokenContract({ ...mockState, metamask: modifiedMetamaskState }), null, ) }) @@ -280,11 +280,12 @@ describe('send selectors', function () { it('should get the selected account balance if the send.from does not exist', function () { const editedMockState = { - metamask: Object.assign({}, mockState.metamask, { + metamask: { + ...mockState.metamask, send: { from: null, }, - }), + }, } assert.equal( getSendFromBalance(editedMockState), @@ -308,11 +309,12 @@ describe('send selectors', function () { it('should return the current account if send.from does not exist', function () { const editedMockState = { - metamask: Object.assign({}, mockState.metamask, { + metamask: { + ...mockState.metamask, send: { from: null, }, - }), + }, } assert.deepEqual( getSendFromObject(editedMockState), @@ -532,7 +534,8 @@ describe('send selectors', function () { editingTransactionId: true, token: {}, }), - ), 'edit') + ), 'edit', + ) }) it('should return the correct key when getSendEditingTransactionId is falsy and getSendToken is truthy', function () { @@ -543,7 +546,8 @@ describe('send selectors', function () { editingTransactionId: false, token: {}, }), - ), 'sendTokens') + ), 'sendTokens', + ) }) it('should return the correct key when getSendEditingTransactionId is falsy and getSendToken is falsy', function () { @@ -554,7 +558,8 @@ describe('send selectors', function () { editingTransactionId: false, token: null, }), - ), 'sendETH') + ), 'sendETH', + ) }) }) }) @@ -571,7 +576,7 @@ describe('send selectors', function () { it('should return true if any of the values of the object returned by getSendErrors are truthy', function () { assert.equal(isSendFormInError( getSendMockState({ - errors: [ true ], + errors: [true], }), ), true) }) @@ -584,7 +589,7 @@ describe('send selectors', function () { ), false) assert.equal(isSendFormInError( getSendMockState({ - errors: [ false ], + errors: [false], }), ), false) }) diff --git a/ui/app/selectors/tests/transactions.test.js b/ui/app/selectors/tests/transactions.test.js index 12a931e817a0..65f36b3ea21f 100644 --- a/ui/app/selectors/tests/transactions.test.js +++ b/ui/app/selectors/tests/transactions.test.js @@ -184,7 +184,7 @@ describe('Transaction Selectors', function () { const expectedResult = [ { nonce: '0x0', - transactions: [ tx1 ], + transactions: [tx1], initialTransaction: tx1, primaryTransaction: tx1, hasRetried: false, @@ -192,7 +192,7 @@ describe('Transaction Selectors', function () { }, { nonce: '0x1', - transactions: [ tx2 ], + transactions: [tx2], initialTransaction: tx2, primaryTransaction: tx2, hasRetried: false, @@ -273,7 +273,7 @@ describe('Transaction Selectors', function () { const expectedResult = [ { nonce: submittedTx.txParams.nonce, - transactions: [ submittedTx ], + transactions: [submittedTx], initialTransaction: submittedTx, primaryTransaction: submittedTx, hasRetried: false, @@ -281,7 +281,7 @@ describe('Transaction Selectors', function () { }, { nonce: unapprovedTx.txParams.nonce, - transactions: [ unapprovedTx ], + transactions: [unapprovedTx], initialTransaction: unapprovedTx, primaryTransaction: unapprovedTx, hasRetried: false, @@ -289,7 +289,7 @@ describe('Transaction Selectors', function () { }, { nonce: approvedTx.txParams.nonce, - transactions: [ approvedTx ], + transactions: [approvedTx], initialTransaction: approvedTx, primaryTransaction: approvedTx, hasRetried: false, @@ -305,7 +305,7 @@ describe('Transaction Selectors', function () { const expectedResult = [ { nonce: confirmedTx.txParams.nonce, - transactions: [ confirmedTx ], + transactions: [confirmedTx], initialTransaction: confirmedTx, primaryTransaction: confirmedTx, hasRetried: false, @@ -318,7 +318,7 @@ describe('Transaction Selectors', function () { it('submittedPendingTransactionsSelector', function () { - const expectedResult = [ submittedTx ] + const expectedResult = [submittedTx] assert.deepEqual(submittedPendingTransactionsSelector(state), expectedResult) }) }) diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 4d9f7a4b3957..543860f5a840 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -257,7 +257,7 @@ export function resetAccount () { return } - log.info('Transaction history reset for ' + account) + log.info(`Transaction history reset for ${account}`) dispatch(showAccountsPage()) resolve(account) }) @@ -277,7 +277,6 @@ export function removeAccount (address) { return } resolve(account) - return }) }) await forceUpdateMetamaskState(dispatch) @@ -288,7 +287,7 @@ export function removeAccount (address) { dispatch(hideLoadingIndication()) } - log.info('Account removed: ' + address) + log.info(`Account removed: ${address}`) dispatch(showAccountsPage()) } } @@ -412,7 +411,6 @@ export function unlockHardwareWalletAccount (index, deviceName, hdPath) { dispatch(hideLoadingIndication()) resolve() - return }) }) } @@ -589,7 +587,6 @@ export function signTx (txData) { global.ethQuery.sendTransaction(txData, (err) => { if (err) { dispatch(displayWarning(err.message)) - return } }) dispatch(showConfTxPage()) @@ -725,7 +722,7 @@ export function updateSendAmount (amount) { export function updateCustomNonce (value) { return { type: actionConstants.UPDATE_CUSTOM_NONCE, - value: value, + value, } } @@ -1044,7 +1041,7 @@ export function cancelTxs (txDataList) { if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { global.platform.closeCurrentWindow() - return + } } } @@ -1059,7 +1056,7 @@ export function markPasswordForgotten () { return } resolve() - return + }) }) } finally { @@ -1322,15 +1319,15 @@ export function addTokens (tokens) { return Promise.all(tokens.map(({ address, symbol, decimals }) => ( dispatch(addToken(address, symbol, decimals)) ))) - } else { - return Promise.all( - Object - .entries(tokens) - .map(([_, { address, symbol, decimals }]) => ( - dispatch(addToken(address, symbol, decimals)) - )), - ) } + return Promise.all( + Object + .entries(tokens) + .map(([_, { address, symbol, decimals }]) => ( + dispatch(addToken(address, symbol, decimals)) + )), + ) + } } @@ -1534,7 +1531,6 @@ export function setRpcTarget (newRpc, chainId, ticker = 'ETH', nickname) { } catch (error) { log.error(error) dispatch(displayWarning('Had a problem changing networks!')) - return } } } @@ -1573,7 +1569,6 @@ export function addToAddressBook (recipient, nickname = '', memo = '') { } if (!set) { dispatch(displayWarning('Address book failed to update')) - return } } } @@ -1602,7 +1597,6 @@ export function hideNetworkDropdown () { } } - export function showModal (payload) { return { type: actionConstants.MODAL_OPEN, @@ -1735,9 +1729,7 @@ export function exportAccount (password, address) { } dispatch(showPrivateKey(result)) - resolve(result) - return }) }) }) @@ -1764,11 +1756,9 @@ export function exportAccounts (password, addresses) { return } resolve2(result) - return }), )) resolve(Promise.all(accountPromises)) - return }) }) } @@ -1800,7 +1790,6 @@ export function setAccountLabel (account, label) { type: actionConstants.SET_ACCOUNT_LABEL, value: { account, label }, }) - resolve(account) }) }) @@ -1966,7 +1955,6 @@ export function setParticipateInMetaMetrics (val) { type: actionConstants.SET_PARTICIPATE_IN_METAMETRICS, value: val, }) - resolve([val, metaMetricsId]) }) }) @@ -1988,7 +1976,6 @@ export function setMetaMetricsSendCount (val) { type: actionConstants.SET_METAMETRICS_SEND_COUNT, value: val, }) - resolve(val) }) }) @@ -2003,7 +1990,6 @@ export function setUseBlockie (val) { dispatch(hideLoadingIndication()) if (err) { dispatch(displayWarning(err.message)) - return } }) dispatch({ @@ -2021,7 +2007,6 @@ export function setUseNonceField (val) { dispatch(hideLoadingIndication()) if (err) { dispatch(displayWarning(err.message)) - return } }) dispatch({ @@ -2039,7 +2024,6 @@ export function setUsePhishDetect (val) { dispatch(hideLoadingIndication()) if (err) { dispatch(displayWarning(err.message)) - return } }) } @@ -2053,7 +2037,7 @@ export function setIpfsGateway (val) { dispatch(hideLoadingIndication()) if (err) { dispatch(displayWarning(err.message)) - return + } else { dispatch({ type: actionConstants.SET_IPFS_GATEWAY, @@ -2174,7 +2158,7 @@ export function setFirstTimeFlowType (type) { background.setFirstTimeFlowType(type, (err) => { if (err) { dispatch(displayWarning(err.message)) - return + } }) dispatch({ @@ -2203,7 +2187,7 @@ export function setLastActiveTime () { background.setLastActiveTime((err) => { if (err) { dispatch(displayWarning(err.message)) - return + } }) } @@ -2257,9 +2241,7 @@ export function getContractMethodData (data = '') { return getMethodDataAsync(fourBytePrefix) .then(({ name, params }) => { dispatch(loadingMethodDataFinished()) - background.addKnownMethodData(fourBytePrefix, { name, params }) - return { name, params } }) } @@ -2292,7 +2274,6 @@ export function getTokenParams (tokenAddress) { dispatch(loadingTokenParamsStarted()) log.debug(`loadingTokenParams`) - return fetchSymbolAndDecimals(tokenAddress, existingTokens) .then(({ symbol, decimals }) => { dispatch(addToken(tokenAddress, symbol, Number(decimals))) @@ -2476,7 +2457,6 @@ export function setCurrentWindowTab (currentWindowTab) { } } - export function getCurrentWindowTab () { return async (dispatch) => { const currentWindowTab = await global.platform.currentTab() diff --git a/ui/lib/icon-factory.js b/ui/lib/icon-factory.js index 142e7bbfd6df..19489819a654 100644 --- a/ui/lib/icon-factory.js +++ b/ui/lib/icon-factory.js @@ -1,8 +1,9 @@ -let iconFactory import { isValidAddress } from 'ethereumjs-util' import contractMap from 'eth-contract-metadata' import { checksumAddress } from '../app/helpers/utils/util' +let iconFactory + export default function iconFactoryGenerator (jazzicon) { if (!iconFactory) { iconFactory = new IconFactory(jazzicon) diff --git a/ui/lib/webcam-utils.js b/ui/lib/webcam-utils.js index ef7da9496397..c9b6c550368f 100644 --- a/ui/lib/webcam-utils.js +++ b/ui/lib/webcam-utils.js @@ -25,11 +25,10 @@ class WebcamUtils { permissions: hasWebcamPermissions, environmentReady, } - } else { - const error = new Error('No webcam found') - error.type = 'NO_WEBCAM_FOUND' - throw error } + const error = new Error('No webcam found') + error.type = 'NO_WEBCAM_FOUND' + throw error } } diff --git a/yarn.lock b/yarn.lock index 6a0d5369cc71..0b0c471f6af8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1730,10 +1730,10 @@ web3 "^0.20.7" web3-provider-engine "^15.0.4" -"@metamask/eslint-config@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-1.1.0.tgz#03c6fbec8ba3d95fa017d8b98ab5d0701f7458a4" - integrity sha512-yFFHIxFn3cBd9brIW/+0fJGq16hT0xUyElP0YxiZHaY7j2T/l+X/414L9kqBOuPfPa9bIKulIcJJOfcrMJZp9w== +"@metamask/eslint-config@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-3.0.0.tgz#39c4275e440cfc690524d328a0bda8227bd69326" + integrity sha512-AYnNopj+K0YyWuCXY4mflgMQzIcm/Jc+HiXzBzY8SJ3fMlnBXjQjsbu0B78zxLR9HZ2uW9IrCj0VG7hMj1b4og== "@metamask/eth-ledger-bridge-keyring@^0.2.6": version "0.2.6" From c04cb63c631579b910728d578111d09ce3646d54 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Wed, 19 Aug 2020 11:41:56 -0500 Subject: [PATCH 136/137] Standardize scss import practices (#9183) --- .../app/{index.scss => app-components.scss} | 64 +++++-------------- .../app/asset-list-item/asset-list-item.scss | 4 +- .../contact-list/contact-list.component.js | 6 +- .../gas-modal-page-container/index.scss | 3 +- .../modals/account-details-modal/index.scss | 2 +- .../hide-token-confirmation-modal.js | 15 +++-- .../hide-token-confirmation-modal/index.scss | 5 -- .../transaction-list-item-details/index.scss | 2 +- .../app/transaction-list-item/index.scss | 2 +- .../components/app/wallet-overview/index.scss | 4 +- ui/app/components/ui/button/button.stories.js | 9 --- ui/app/components/ui/button/buttons.scss | 60 +++++++---------- .../page-container-header.component.js | 3 +- ui/app/components/ui/ui-components.scss | 37 +++++++++++ ui/app/css/design-system/index.scss | 9 +-- ui/app/css/design-system/z-index.scss | 12 ++++ ui/app/css/index.scss | 3 + ui/app/css/itcss/components/index.scss | 7 -- ui/app/css/itcss/settings/variables.scss | 13 ---- .../token-list-placeholder/index.scss | 2 - .../token-list-placeholder.component.js | 6 +- ui/app/pages/{index.scss => pages.scss} | 18 +++--- .../add-recipient/add-recipient.component.js | 11 ++-- ui/app/pages/send/send.scss | 9 ++- ui/app/pages/settings/info-tab/index.scss | 9 +-- .../settings/info-tab/info-tab.component.js | 61 +++++++++--------- ui/app/pages/settings/settings-tab/index.scss | 6 -- 27 files changed, 182 insertions(+), 200 deletions(-) rename ui/app/components/app/{index.scss => app-components.scss} (52%) create mode 100644 ui/app/components/ui/ui-components.scss create mode 100644 ui/app/css/design-system/z-index.scss rename ui/app/pages/{index.scss => pages.scss} (87%) diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/app-components.scss similarity index 52% rename from ui/app/components/app/index.scss rename to ui/app/components/app/app-components.scss index 3b708f68ee79..07eac6ce137d 100644 --- a/ui/app/components/app/index.scss +++ b/ui/app/components/app/app-components.scss @@ -1,68 +1,38 @@ +/** Please import your files in alphabetical order **/ @import 'account-list-item/index'; @import 'account-menu/index'; @import 'add-token-button/index'; -@import '../ui/alert/index'; @import 'alerts/alerts'; @import 'app-header/index'; @import 'asset-list-item/asset-list-item'; -@import '../ui/breadcrumbs/index'; -@import '../ui/button-group/index'; -@import '../ui/card/index'; @import 'confirm-page-container/index'; -@import '../ui/currency-input/index'; -@import '../ui/currency-display/index'; -@import '../ui/editable-label/index'; -@import '../ui/error-message/index'; -@import '../ui/export-text-container/index'; -@import '../ui/identicon/index'; -@import '../ui/menu/menu'; +@import 'connected-accounts-list/index'; +@import 'connected-accounts-permissions/index'; +@import 'connected-sites-list/index'; +@import 'connected-status-indicator/index'; +@import 'gas-customization/gas-modal-page-container/index'; +@import 'gas-customization/gas-price-button-group/index'; +@import 'gas-customization/index'; +@import 'home-notification/index'; @import 'info-box/index'; @import 'menu-bar/index'; @import 'modal/index'; @import 'modals/index'; +@import 'multiple-notifications/index'; @import 'network-display/index'; -@import '../ui/page-container/index'; -@import '../../pages/index'; @import 'permission-page-container/index'; -@import '../ui/qr-code/index'; -@import '../ui/readonly-input/index'; +@import 'permissions-connect-footer/index'; +@import 'permissions-connect-header/index'; @import 'selected-account/index'; -@import '../ui/sender-to-recipient/index'; -@import '../ui/tabs/index'; -@import '../ui/token-balance/index'; +@import 'sidebars/index'; +@import 'signature-request/index'; @import 'signature-request-original/index'; +@import 'tab-bar/index'; @import 'token-cell/token-cell'; @import 'transaction-activity-log/index'; @import 'transaction-breakdown/index'; -@import 'transaction-list/index'; -@import 'transaction-list-item/index'; @import 'transaction-list-item-details/index'; +@import 'transaction-list-item/index'; +@import 'transaction-list/index'; @import 'transaction-status/index'; -@import 'sidebars/index'; -@import '../ui/unit-input/index'; -@import 'gas-customization/gas-modal-page-container/index'; -@import 'gas-customization/index'; -@import 'gas-customization/gas-price-button-group/index'; -@import '../ui/toggle-button/index'; -@import 'home-notification/index'; -@import 'multiple-notifications/index'; -@import 'signature-request/index'; -@import 'connected-sites-list/index'; -@import 'connected-accounts-list/index'; -@import 'connected-accounts-permissions/index'; -@import '../ui/icon/index'; -@import '../ui/icon-with-fallback/icon-with-fallback'; -@import '../ui/icon-with-label/index'; -@import '../ui/circle-icon/index'; -@import '../ui/alert-circle-icon/index'; -@import './connected-status-indicator/index'; -@import '../ui/check-box/index'; -@import '../ui/dropdown/dropdown'; -@import 'permissions-connect-header/index'; -@import 'permissions-connect-footer/index'; -@import 'tab-bar/index'; @import 'wallet-overview/index'; -@import '../ui/account-mismatch-warning/index'; -@import '../ui/icon-border/icon-border'; -@import '../ui/info-tooltip/index'; -@import '../ui/pulse-loader/index'; diff --git a/ui/app/components/app/asset-list-item/asset-list-item.scss b/ui/app/components/app/asset-list-item/asset-list-item.scss index 9167f7b0908f..ddc6fd562b4c 100644 --- a/ui/app/components/app/asset-list-item/asset-list-item.scss +++ b/ui/app/components/app/asset-list-item/asset-list-item.scss @@ -17,7 +17,7 @@ margin-left: 8px; } - &__send-token-button { + & &__send-token-button { display: none; text-transform: uppercase; width: fit-content; @@ -33,7 +33,7 @@ display: flex; } - &__send-token-button { + & &__send-token-button { display: inline-block; } diff --git a/ui/app/components/app/contact-list/contact-list.component.js b/ui/app/components/app/contact-list/contact-list.component.js index b959fb9c070d..0e151d23d124 100644 --- a/ui/app/components/app/contact-list/contact-list.component.js +++ b/ui/app/components/app/contact-list/contact-list.component.js @@ -1,5 +1,6 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' +import Button from '../../ui/button' import RecipientGroup from './recipient-group/recipient-group.component' export default class ContactList extends PureComponent { @@ -37,12 +38,13 @@ export default class ContactList extends PureComponent { /> { showLoadMore && ( -
this.setState({ isShowingAllRecent: true })} > {t('loadMore')} -
+ ) }
diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/index.scss b/ui/app/components/app/gas-customization/gas-modal-page-container/index.scss index 1794a45c125d..d8edc10c1a34 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/index.scss +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/index.scss @@ -34,10 +34,11 @@ font-size: 14px; color: #4eade7; position: absolute; - top: 16px; + top: 4px; right: 16px; cursor: pointer; overflow: hidden; + width: min-content; } &__title { diff --git a/ui/app/components/app/modals/account-details-modal/index.scss b/ui/app/components/app/modals/account-details-modal/index.scss index 94d5cd5412d4..1f14aeaac4cc 100644 --- a/ui/app/components/app/modals/account-details-modal/index.scss +++ b/ui/app/components/app/modals/account-details-modal/index.scss @@ -4,7 +4,7 @@ font-size: 20px; } - &__button { + & &__button { margin-top: 17px; padding: 10px 22px; width: 286px; diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js b/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js index 58fd01170652..57a0bdc01007 100644 --- a/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js +++ b/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js @@ -3,6 +3,7 @@ import React, { Component } from 'react' import { connect } from 'react-redux' import * as actions from '../../../../store/actions' import Identicon from '../../../ui/identicon' +import Button from '../../../ui/button' function mapStateToProps (state) { return { @@ -63,20 +64,22 @@ class HideTokenConfirmationModal extends Component { {this.context.t('readdToken')}
- - +
diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal/index.scss b/ui/app/components/app/modals/hide-token-confirmation-modal/index.scss index d640b6c5c0b2..9482caeba871 100644 --- a/ui/app/components/app/modals/hide-token-confirmation-modal/index.scss +++ b/ui/app/components/app/modals/hide-token-confirmation-modal/index.scss @@ -51,11 +51,6 @@ } &__button { - @include Paragraph; - - @extend %button; - - width: 141px; margin: 0 5px; } } diff --git a/ui/app/components/app/transaction-list-item-details/index.scss b/ui/app/components/app/transaction-list-item-details/index.scss index 64fe1922038a..145e0e9a18f0 100644 --- a/ui/app/components/app/transaction-list-item-details/index.scss +++ b/ui/app/components/app/transaction-list-item-details/index.scss @@ -16,7 +16,7 @@ flex-direction: row; } - &__header-button { + & &__header-button { font-size: 0.625rem; &:not(:last-child) { diff --git a/ui/app/components/app/transaction-list-item/index.scss b/ui/app/components/app/transaction-list-item/index.scss index 1a4e081ef672..53ab7dc945bb 100644 --- a/ui/app/components/app/transaction-list-item/index.scss +++ b/ui/app/components/app/transaction-list-item/index.scss @@ -9,7 +9,7 @@ color: $Grey-500; } - &--unconfirmed { + & &--unconfirmed { color: $Grey-500; } diff --git a/ui/app/components/app/wallet-overview/index.scss b/ui/app/components/app/wallet-overview/index.scss index 391edcc040ff..2deaa5d5559d 100644 --- a/ui/app/components/app/wallet-overview/index.scss +++ b/ui/app/components/app/wallet-overview/index.scss @@ -83,7 +83,7 @@ color: $Grey-400; } - &__button { + .wallet-overview &__button { @extend %asset-buttons; } } @@ -115,7 +115,7 @@ color: $Grey-400; } - &__button { + .wallet-overview &__button { @extend %asset-buttons; } } diff --git a/ui/app/components/ui/button/button.stories.js b/ui/app/components/ui/button/button.stories.js index 4a251d61b3e0..c19551835ba8 100644 --- a/ui/app/components/ui/button/button.stories.js +++ b/ui/app/components/ui/button/button.stories.js @@ -67,12 +67,3 @@ export const dangerPrimaryType = () => ( ) -export const linkType = () => ( - -) diff --git a/ui/app/components/ui/button/buttons.scss b/ui/app/components/ui/button/buttons.scss index 0e38c049cd61..a8364ca656e2 100644 --- a/ui/app/components/ui/button/buttons.scss +++ b/ui/app/components/ui/button/buttons.scss @@ -10,7 +10,7 @@ $hover-red-primary: #c72837; $hover-orange: #ffd3b5; $warning-light-orange: #f8b588; -%button { +.button { @include H6; font-weight: 500; @@ -30,41 +30,6 @@ $warning-light-orange: #f8b588; opacity: 0.5; pointer-events: none; } -} - -%link { - @include H4; - - color: $Blue-500; - line-height: 1.25rem; - cursor: pointer; - background-color: transparent; - - &:hover { - color: $Blue-400; - } - - &:active { - color: $Blue-600; - } - - &--disabled, - &[disabled] { - cursor: auto; - opacity: 1; - pointer-events: none; - color: $hover-secondary; - } -} - -%small-link { - @extend %link; - - @include H6; -} - -.button { - @extend %button; &__icon { display: flex; @@ -202,7 +167,28 @@ $warning-light-orange: #f8b588; } .btn-link { - @extend %link; + @include H4; + + color: $Blue-500; + line-height: 1.25rem; + cursor: pointer; + background-color: transparent; + + &:hover { + color: $Blue-400; + } + + &:active { + color: $Blue-600; + } + + &--disabled, + &[disabled] { + cursor: auto; + opacity: 1; + pointer-events: none; + color: $hover-secondary; + } } .btn--large { diff --git a/ui/app/components/ui/page-container/page-container-header/page-container-header.component.js b/ui/app/components/ui/page-container/page-container-header/page-container-header.component.js index c5ff365dba80..5d5a88a9ea4b 100644 --- a/ui/app/components/ui/page-container/page-container-header/page-container-header.component.js +++ b/ui/app/components/ui/page-container/page-container-header/page-container-header.component.js @@ -1,6 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' +import Button from '../../button' export default class PageContainerHeader extends Component { static propTypes = { @@ -72,7 +73,7 @@ export default class PageContainerHeader extends Component { { onClose && headerCloseText - ?
onClose()}>{ headerCloseText }
+ ? : onClose && (
{ this.context.t('addAcquiredTokens') }
- { this.context.t('learnMore') } - +
) } diff --git a/ui/app/pages/index.scss b/ui/app/pages/pages.scss similarity index 87% rename from ui/app/pages/index.scss rename to ui/app/pages/pages.scss index 85237eda361e..f09773ae10e7 100644 --- a/ui/app/pages/index.scss +++ b/ui/app/pages/pages.scss @@ -1,18 +1,20 @@ -@import 'unlock-page/index'; +/** Please import your files in alphabetical order **/ @import 'add-token/index'; -@import 'error/index'; -@import 'home/index'; -@import 'send/send'; +@import 'asset/asset'; @import 'confirm-add-token/index'; +@import 'confirm-approve/index'; @import 'confirm-decrypt-message/confirm-decrypt-message'; @import 'confirm-encryption-public-key/confirm-encryption-public-key'; @import 'connected-sites/index'; @import 'connected-accounts/index'; -@import 'settings/index'; +@import 'connected-sites/index'; +@import 'create-account/index'; +@import 'error/index'; @import 'first-time-flow/index'; +@import 'home/index'; @import 'keychains/index'; -@import 'confirm-approve/index'; @import 'permissions-connect/index'; -@import 'asset/asset'; +@import 'send/send'; +@import 'settings/index'; @import 'token/index'; -@import 'create-account/index'; +@import 'unlock-page/index'; diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js index 07b4c95f88da..3230e00d87fd 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js @@ -7,6 +7,7 @@ import Dialog from '../../../../components/ui/dialog' import ContactList from '../../../../components/app/contact-list' import RecipientGroup from '../../../../components/app/contact-list/recipient-group/recipient-group.component' import { ellipsify } from '../../send.utils' +import Button from '../../../../components/ui/button' export default class AddRecipient extends Component { @@ -147,13 +148,14 @@ export default class AddRecipient extends Component { return (
-
this.setState({ isShowingTransfer: false })} >
{ t('backToAll') } -
+ { (ownedAccounts && ownedAccounts.length > 1) && !query && ( -
this.setState({ isShowingTransfer: true })} > { t('transferBetweenAccounts') } -
+ ) } diff --git a/ui/app/pages/send/send.scss b/ui/app/pages/send/send.scss index 61b1fe805970..7e2459f4dd31 100644 --- a/ui/app/pages/send/send.scss +++ b/ui/app/pages/send/send.scss @@ -14,12 +14,12 @@ } .page-container__header-close-text { - @extend %link; - font-size: 1rem; line-height: 1.1875rem; position: absolute; right: 1rem; + top: 6px; + width: min-content; } } @@ -50,13 +50,13 @@ overflow-y: auto; &__link { - @extend %link; @extend %row-nowrap; padding: 1rem; font-size: 1rem; border-bottom: 1px solid $alto; align-items: center; + justify-content: flex-start; } &__back-caret { @@ -78,13 +78,12 @@ @extend %col-nowrap; &__load-more { - @extend %link; - font-size: 0.75rem; line-height: 1.0625rem; padding: 0.5rem; text-align: center; border-bottom: 1px solid $alto; + justify-content: flex-start; } } diff --git a/ui/app/pages/settings/info-tab/index.scss b/ui/app/pages/settings/info-tab/index.scss index 9cc7e21b2a96..3cbe63b5cd7e 100644 --- a/ui/app/pages/settings/info-tab/index.scss +++ b/ui/app/pages/settings/info-tab/index.scss @@ -21,6 +21,11 @@ } } + &__link-text { + width: max-content; + padding: 0; + } + &__link-item { padding: 15px 0; @@ -29,10 +34,6 @@ } } - &__link-text { - @extend %link; - } - &__version-number { padding-top: 5px; font-size: 13px; diff --git a/ui/app/pages/settings/info-tab/info-tab.component.js b/ui/app/pages/settings/info-tab/info-tab.component.js index 9d522a3a1931..21c2ef5f4d67 100644 --- a/ui/app/pages/settings/info-tab/info-tab.component.js +++ b/ui/app/pages/settings/info-tab/info-tab.component.js @@ -1,5 +1,6 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' +import Button from '../../../components/ui/button' export default class InfoTab extends PureComponent { state = { @@ -19,71 +20,71 @@ export default class InfoTab extends PureComponent { { t('links') }
- - - { t('privacyMsg') } - - + { t('privacyMsg') } +
- - - { t('terms') } - - + { t('terms') } +
- - - { t('attributions') } - - + { t('attributions') } +

- - - { t('supportCenter') } - - + { t('supportCenter') } +
- - - { t('visitWebSite') } - - + { t('visitWebSite') } +
- - - { t('contactUs') } - - + { t('contactUs') } +
) diff --git a/ui/app/pages/settings/settings-tab/index.scss b/ui/app/pages/settings/settings-tab/index.scss index 5d9864984264..39670e46fc6d 100644 --- a/ui/app/pages/settings/settings-tab/index.scss +++ b/ui/app/pages/settings/settings-tab/index.scss @@ -5,12 +5,6 @@ color: $crimson; } - &__advanced-link { - @extend %small-link; - - padding-left: 5px; - } - &__rpc-save-button { align-self: flex-end; padding: 5px; From 2b7a692658cdf6bf19f8b10f8d814936a0b18783 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 19 Aug 2020 17:34:58 -0230 Subject: [PATCH 137/137] Use @metamask/eslint-config@3.1.0 (#9275) This change updates the shared ESLint config to the latest published version, v3.1.0. From the config [`CHANGELOG.md`][1]: v3.0.1 has disabled `prefer-object-spread` by default, so it has been enabled for this project. [1]:https://github.com/MetaMask/eslint-config/blob/master/CHANGELOG.md --- .eslintrc.js | 1 + package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 0b69e664efb8..2fbadc34ff5d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -56,6 +56,7 @@ module.exports = { }, { 'enforceForRenamedProperties': false, }], + 'prefer-object-spread': 'error', 'react/no-unused-prop-types': 'error', 'react/no-unused-state': 'error', 'react/jsx-boolean-value': 'error', diff --git a/package.json b/package.json index f13bf1902df9..fc470803d682 100644 --- a/package.json +++ b/package.json @@ -179,7 +179,7 @@ "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", "@babel/register": "^7.5.5", - "@metamask/eslint-config": "^3.0.0", + "@metamask/eslint-config": "^3.1.0", "@metamask/forwarder": "^1.1.0", "@metamask/test-dapp": "^3.1.0", "@sentry/cli": "^1.49.0", diff --git a/yarn.lock b/yarn.lock index 0b0c471f6af8..2683bd446c1e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1730,10 +1730,10 @@ web3 "^0.20.7" web3-provider-engine "^15.0.4" -"@metamask/eslint-config@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-3.0.0.tgz#39c4275e440cfc690524d328a0bda8227bd69326" - integrity sha512-AYnNopj+K0YyWuCXY4mflgMQzIcm/Jc+HiXzBzY8SJ3fMlnBXjQjsbu0B78zxLR9HZ2uW9IrCj0VG7hMj1b4og== +"@metamask/eslint-config@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-3.1.0.tgz#8412ddd3f660748598902fd8dbef6fadc060f25e" + integrity sha512-He/zV0Cb5W421mEQveaqSegLarONJbJPReJppQkwhi239PCE7j+6eRji/j2Unwq8TBuOlgQtqL49+dtvks+lPQ== "@metamask/eth-ledger-bridge-keyring@^0.2.6": version "0.2.6"